diff options
Diffstat (limited to 'source')
502 files changed, 23251 insertions, 23233 deletions
diff --git a/source/API/SBAddress.cpp b/source/API/SBAddress.cpp index 358cb400a76c..dcde25b77917 100644 --- a/source/API/SBAddress.cpp +++ b/source/API/SBAddress.cpp @@ -28,7 +28,7 @@ SBAddress::SBAddress() : m_opaque_up(new Address()) { SBAddress::SBAddress(const Address *lldb_object_ptr) : m_opaque_up(new Address()) { if (lldb_object_ptr) - m_opaque_up = llvm::make_unique<Address>(*lldb_object_ptr); + m_opaque_up = std::make_unique<Address>(*lldb_object_ptr); } SBAddress::SBAddress(const SBAddress &rhs) : m_opaque_up(new Address()) { @@ -210,12 +210,6 @@ bool SBAddress::GetDescription(SBStream &description) { if (m_opaque_up->IsValid()) { m_opaque_up->Dump(&strm, nullptr, Address::DumpStyleResolvedDescription, Address::DumpStyleModuleWithFileAddress, 4); - StreamString sstrm; - // m_opaque_up->Dump (&sstrm, NULL, - // Address::DumpStyleResolvedDescription, Address::DumpStyleInvalid, - // 4); - // if (sstrm.GetData()) - // strm.Printf (" (%s)", sstrm.GetData()); } else strm.PutCString("No value"); diff --git a/source/API/SBBreakpointOptionCommon.cpp b/source/API/SBBreakpointOptionCommon.cpp index 058b3e0398cd..870b4b941ada 100644 --- a/source/API/SBBreakpointOptionCommon.cpp +++ b/source/API/SBBreakpointOptionCommon.cpp @@ -41,7 +41,7 @@ using namespace lldb_private; SBBreakpointCallbackBaton::SBBreakpointCallbackBaton(SBBreakpointHitCallback callback, void *baton) - : TypedBaton(llvm::make_unique<CallbackData>()) { + : TypedBaton(std::make_unique<CallbackData>()) { getItem()->callback = callback; getItem()->callback_baton = baton; } diff --git a/source/API/SBCommandInterpreter.cpp b/source/API/SBCommandInterpreter.cpp index c07dffce0baa..6e5ebe6a7ded 100644 --- a/source/API/SBCommandInterpreter.cpp +++ b/source/API/SBCommandInterpreter.cpp @@ -162,12 +162,11 @@ public: protected: bool DoExecute(Args &command, CommandReturnObject &result) override { - SBCommandReturnObject sb_return(&result); + SBCommandReturnObject sb_return(result); SBCommandInterpreter sb_interpreter(&m_interpreter); SBDebugger debugger_sb(m_interpreter.GetDebugger().shared_from_this()); bool ret = m_backend->DoExecute( debugger_sb, (char **)command.GetArgumentVector(), sb_return); - sb_return.Release(); return ret; } std::shared_ptr<lldb::SBCommandPluginInterface> m_backend; @@ -353,8 +352,6 @@ int SBCommandInterpreter::HandleCompletionWithDescriptions( current_line, cursor, last_char, match_start_point, max_return_elements, matches, descriptions); - int num_completions = 0; - // Sanity check the arguments that are passed in: cursor & last_char have to // be within the current_line. if (current_line == nullptr || cursor == nullptr || last_char == nullptr) @@ -368,20 +365,50 @@ int SBCommandInterpreter::HandleCompletionWithDescriptions( last_char - current_line > static_cast<ptrdiff_t>(current_line_size)) return 0; + if (!IsValid()) + return 0; - if (IsValid()) { - lldb_private::StringList lldb_matches, lldb_descriptions; - num_completions = m_opaque_ptr->HandleCompletion( - current_line, cursor, last_char, match_start_point, max_return_elements, - lldb_matches, lldb_descriptions); - - SBStringList temp_matches_list(&lldb_matches); - matches.AppendList(temp_matches_list); - SBStringList temp_descriptions_list(&lldb_descriptions); - descriptions.AppendList(temp_descriptions_list); + lldb_private::StringList lldb_matches, lldb_descriptions; + CompletionResult result; + CompletionRequest request(current_line, cursor - current_line, result); + m_opaque_ptr->HandleCompletion(request); + result.GetMatches(lldb_matches); + result.GetDescriptions(lldb_descriptions); + + // Make the result array indexed from 1 again by adding the 'common prefix' + // of all completions as element 0. This is done to emulate the old API. + if (request.GetParsedLine().GetArgumentCount() == 0) { + // If we got an empty string, insert nothing. + lldb_matches.InsertStringAtIndex(0, ""); + lldb_descriptions.InsertStringAtIndex(0, ""); + } else { + // Now figure out if there is a common substring, and if so put that in + // element 0, otherwise put an empty string in element 0. + std::string command_partial_str = request.GetCursorArgumentPrefix().str(); + + std::string common_prefix = lldb_matches.LongestCommonPrefix(); + const size_t partial_name_len = command_partial_str.size(); + common_prefix.erase(0, partial_name_len); + + // If we matched a unique single command, add a space... Only do this if + // the completer told us this was a complete word, however... + if (lldb_matches.GetSize() == 1) { + char quote_char = request.GetParsedArg().GetQuoteChar(); + common_prefix = + Args::EscapeLLDBCommandArgument(common_prefix, quote_char); + if (request.GetParsedArg().IsQuoted()) + common_prefix.push_back(quote_char); + common_prefix.push_back(' '); + } + lldb_matches.InsertStringAtIndex(0, common_prefix.c_str()); + lldb_descriptions.InsertStringAtIndex(0, ""); } - return num_completions; + SBStringList temp_matches_list(&lldb_matches); + matches.AppendList(temp_matches_list); + SBStringList temp_descriptions_list(&lldb_descriptions); + descriptions.AppendList(temp_descriptions_list); + return result.GetNumberOfResults(); } int SBCommandInterpreter::HandleCompletionWithDescriptions( diff --git a/source/API/SBCommandReturnObject.cpp b/source/API/SBCommandReturnObject.cpp index 94e89916f7f6..eec1383df875 100644 --- a/source/API/SBCommandReturnObject.cpp +++ b/source/API/SBCommandReturnObject.cpp @@ -10,6 +10,7 @@ #include "SBReproducerPrivate.h" #include "Utils.h" #include "lldb/API/SBError.h" +#include "lldb/API/SBFile.h" #include "lldb/API/SBStream.h" #include "lldb/Interpreter/CommandReturnObject.h" #include "lldb/Utility/ConstString.h" @@ -18,11 +19,43 @@ using namespace lldb; using namespace lldb_private; +class lldb_private::SBCommandReturnObjectImpl { +public: + SBCommandReturnObjectImpl() + : m_ptr(new CommandReturnObject()), m_owned(true) {} + SBCommandReturnObjectImpl(CommandReturnObject &ref) + : m_ptr(&ref), m_owned(false) {} + SBCommandReturnObjectImpl(const SBCommandReturnObjectImpl &rhs) + : m_ptr(new CommandReturnObject(*rhs.m_ptr)), m_owned(rhs.m_owned) {} + SBCommandReturnObjectImpl &operator=(const SBCommandReturnObjectImpl &rhs) { + SBCommandReturnObjectImpl copy(rhs); + std::swap(*this, copy); + return *this; + } + // rvalue ctor+assignment are not used by SBCommandReturnObject. + ~SBCommandReturnObjectImpl() { + if (m_owned) + delete m_ptr; + } + + CommandReturnObject &operator*() const { return *m_ptr; } + +private: + CommandReturnObject *m_ptr; + bool m_owned; +}; + SBCommandReturnObject::SBCommandReturnObject() - : m_opaque_up(new CommandReturnObject()) { + : m_opaque_up(new SBCommandReturnObjectImpl()) { LLDB_RECORD_CONSTRUCTOR_NO_ARGS(SBCommandReturnObject); } +SBCommandReturnObject::SBCommandReturnObject(CommandReturnObject &ref) + : m_opaque_up(new SBCommandReturnObjectImpl(ref)) { + LLDB_RECORD_CONSTRUCTOR(SBCommandReturnObject, + (lldb_private::CommandReturnObject &), ref); +} + SBCommandReturnObject::SBCommandReturnObject(const SBCommandReturnObject &rhs) : m_opaque_up() { LLDB_RECORD_CONSTRUCTOR(SBCommandReturnObject, @@ -31,25 +64,10 @@ SBCommandReturnObject::SBCommandReturnObject(const SBCommandReturnObject &rhs) m_opaque_up = clone(rhs.m_opaque_up); } -SBCommandReturnObject::SBCommandReturnObject(CommandReturnObject *ptr) - : m_opaque_up(ptr) { - LLDB_RECORD_CONSTRUCTOR(SBCommandReturnObject, - (lldb_private::CommandReturnObject *), ptr); -} - -SBCommandReturnObject::~SBCommandReturnObject() = default; - -CommandReturnObject *SBCommandReturnObject::Release() { - LLDB_RECORD_METHOD_NO_ARGS(lldb_private::CommandReturnObject *, - SBCommandReturnObject, Release); - - return LLDB_RECORD_RESULT(m_opaque_up.release()); -} - -const SBCommandReturnObject &SBCommandReturnObject:: +SBCommandReturnObject &SBCommandReturnObject:: operator=(const SBCommandReturnObject &rhs) { LLDB_RECORD_METHOD( - const lldb::SBCommandReturnObject &, + lldb::SBCommandReturnObject &, SBCommandReturnObject, operator=,(const lldb::SBCommandReturnObject &), rhs); @@ -58,6 +76,8 @@ operator=(const SBCommandReturnObject &rhs) { return LLDB_RECORD_RESULT(*this); } +SBCommandReturnObject::~SBCommandReturnObject() = default; + bool SBCommandReturnObject::IsValid() const { LLDB_RECORD_METHOD_CONST_NO_ARGS(bool, SBCommandReturnObject, IsValid); return this->operator bool(); @@ -65,49 +85,38 @@ bool SBCommandReturnObject::IsValid() const { SBCommandReturnObject::operator bool() const { LLDB_RECORD_METHOD_CONST_NO_ARGS(bool, SBCommandReturnObject, operator bool); - return m_opaque_up != nullptr; + // This method is not useful but it needs to stay to keep SB API stable. + return true; } const char *SBCommandReturnObject::GetOutput() { LLDB_RECORD_METHOD_NO_ARGS(const char *, SBCommandReturnObject, GetOutput); - if (m_opaque_up) { - llvm::StringRef output = m_opaque_up->GetOutputData(); - ConstString result(output.empty() ? llvm::StringRef("") : output); - - return result.AsCString(); - } - - return nullptr; + ConstString output(ref().GetOutputData()); + return output.AsCString(/*value_if_empty*/ ""); } const char *SBCommandReturnObject::GetError() { LLDB_RECORD_METHOD_NO_ARGS(const char *, SBCommandReturnObject, GetError); - if (m_opaque_up) { - llvm::StringRef output = m_opaque_up->GetErrorData(); - ConstString result(output.empty() ? llvm::StringRef("") : output); - return result.AsCString(); - } - - return nullptr; + ConstString output(ref().GetErrorData()); + return output.AsCString(/*value_if_empty*/ ""); } size_t SBCommandReturnObject::GetOutputSize() { LLDB_RECORD_METHOD_NO_ARGS(size_t, SBCommandReturnObject, GetOutputSize); - return (m_opaque_up ? m_opaque_up->GetOutputData().size() : 0); + return ref().GetOutputData().size(); } size_t SBCommandReturnObject::GetErrorSize() { LLDB_RECORD_METHOD_NO_ARGS(size_t, SBCommandReturnObject, GetErrorSize); - return (m_opaque_up ? m_opaque_up->GetErrorData().size() : 0); + return ref().GetErrorData().size(); } size_t SBCommandReturnObject::PutOutput(FILE *fh) { - LLDB_RECORD_METHOD(size_t, SBCommandReturnObject, PutOutput, (FILE *), fh); - + LLDB_RECORD_DUMMY(size_t, SBCommandReturnObject, PutOutput, (FILE *), fh); if (fh) { size_t num_bytes = GetOutputSize(); if (num_bytes) @@ -116,9 +125,23 @@ size_t SBCommandReturnObject::PutOutput(FILE *fh) { return 0; } -size_t SBCommandReturnObject::PutError(FILE *fh) { - LLDB_RECORD_METHOD(size_t, SBCommandReturnObject, PutError, (FILE *), fh); +size_t SBCommandReturnObject::PutOutput(FileSP file_sp) { + LLDB_RECORD_METHOD(size_t, SBCommandReturnObject, PutOutput, (FileSP), + file_sp); + if (!file_sp) + return 0; + return file_sp->Printf("%s", GetOutput()); +} + +size_t SBCommandReturnObject::PutOutput(SBFile file) { + LLDB_RECORD_METHOD(size_t, SBCommandReturnObject, PutOutput, (SBFile), file); + if (!file.m_opaque_sp) + return 0; + return file.m_opaque_sp->Printf("%s", GetOutput()); +} +size_t SBCommandReturnObject::PutError(FILE *fh) { + LLDB_RECORD_DUMMY(size_t, SBCommandReturnObject, PutError, (FILE *), fh); if (fh) { size_t num_bytes = GetErrorSize(); if (num_bytes) @@ -127,77 +150,81 @@ size_t SBCommandReturnObject::PutError(FILE *fh) { return 0; } +size_t SBCommandReturnObject::PutError(FileSP file_sp) { + LLDB_RECORD_METHOD(size_t, SBCommandReturnObject, PutError, (FileSP), + file_sp); + if (!file_sp) + return 0; + return file_sp->Printf("%s", GetError()); +} + +size_t SBCommandReturnObject::PutError(SBFile file) { + LLDB_RECORD_METHOD(size_t, SBCommandReturnObject, PutError, (SBFile), file); + if (!file.m_opaque_sp) + return 0; + return file.m_opaque_sp->Printf("%s", GetError()); +} + void SBCommandReturnObject::Clear() { LLDB_RECORD_METHOD_NO_ARGS(void, SBCommandReturnObject, Clear); - if (m_opaque_up) - m_opaque_up->Clear(); + ref().Clear(); } lldb::ReturnStatus SBCommandReturnObject::GetStatus() { LLDB_RECORD_METHOD_NO_ARGS(lldb::ReturnStatus, SBCommandReturnObject, GetStatus); - return (m_opaque_up ? m_opaque_up->GetStatus() : lldb::eReturnStatusInvalid); + return ref().GetStatus(); } void SBCommandReturnObject::SetStatus(lldb::ReturnStatus status) { LLDB_RECORD_METHOD(void, SBCommandReturnObject, SetStatus, (lldb::ReturnStatus), status); - if (m_opaque_up) - m_opaque_up->SetStatus(status); + ref().SetStatus(status); } bool SBCommandReturnObject::Succeeded() { LLDB_RECORD_METHOD_NO_ARGS(bool, SBCommandReturnObject, Succeeded); - return (m_opaque_up ? m_opaque_up->Succeeded() : false); + return ref().Succeeded(); } bool SBCommandReturnObject::HasResult() { LLDB_RECORD_METHOD_NO_ARGS(bool, SBCommandReturnObject, HasResult); - return (m_opaque_up ? m_opaque_up->HasResult() : false); + return ref().HasResult(); } void SBCommandReturnObject::AppendMessage(const char *message) { LLDB_RECORD_METHOD(void, SBCommandReturnObject, AppendMessage, (const char *), message); - if (m_opaque_up) - m_opaque_up->AppendMessage(message); + ref().AppendMessage(message); } void SBCommandReturnObject::AppendWarning(const char *message) { LLDB_RECORD_METHOD(void, SBCommandReturnObject, AppendWarning, (const char *), message); - if (m_opaque_up) - m_opaque_up->AppendWarning(message); + ref().AppendWarning(message); } CommandReturnObject *SBCommandReturnObject::operator->() const { - return m_opaque_up.get(); + return &**m_opaque_up; } CommandReturnObject *SBCommandReturnObject::get() const { - return m_opaque_up.get(); + return &**m_opaque_up; } CommandReturnObject &SBCommandReturnObject::operator*() const { - assert(m_opaque_up.get()); - return *(m_opaque_up.get()); + return **m_opaque_up; } CommandReturnObject &SBCommandReturnObject::ref() const { - assert(m_opaque_up.get()); - return *(m_opaque_up.get()); -} - -void SBCommandReturnObject::SetLLDBObjectPtr(CommandReturnObject *ptr) { - if (m_opaque_up) - m_opaque_up.reset(ptr); + return **m_opaque_up; } bool SBCommandReturnObject::GetDescription(SBStream &description) { @@ -206,84 +233,99 @@ bool SBCommandReturnObject::GetDescription(SBStream &description) { Stream &strm = description.ref(); - if (m_opaque_up) { - description.Printf("Error: "); - lldb::ReturnStatus status = m_opaque_up->GetStatus(); - if (status == lldb::eReturnStatusStarted) - strm.PutCString("Started"); - else if (status == lldb::eReturnStatusInvalid) - strm.PutCString("Invalid"); - else if (m_opaque_up->Succeeded()) - strm.PutCString("Success"); - else - strm.PutCString("Fail"); - - if (GetOutputSize() > 0) - strm.Printf("\nOutput Message:\n%s", GetOutput()); - - if (GetErrorSize() > 0) - strm.Printf("\nError Message:\n%s", GetError()); - } else - strm.PutCString("No value"); + description.Printf("Error: "); + lldb::ReturnStatus status = ref().GetStatus(); + if (status == lldb::eReturnStatusStarted) + strm.PutCString("Started"); + else if (status == lldb::eReturnStatusInvalid) + strm.PutCString("Invalid"); + else if (ref().Succeeded()) + strm.PutCString("Success"); + else + strm.PutCString("Fail"); + + if (GetOutputSize() > 0) + strm.Printf("\nOutput Message:\n%s", GetOutput()); + + if (GetErrorSize() > 0) + strm.Printf("\nError Message:\n%s", GetError()); return true; } void SBCommandReturnObject::SetImmediateOutputFile(FILE *fh) { - LLDB_RECORD_METHOD(void, SBCommandReturnObject, SetImmediateOutputFile, - (FILE *), fh); + LLDB_RECORD_DUMMY(void, SBCommandReturnObject, SetImmediateOutputFile, + (FILE *), fh); SetImmediateOutputFile(fh, false); } void SBCommandReturnObject::SetImmediateErrorFile(FILE *fh) { - LLDB_RECORD_METHOD(void, SBCommandReturnObject, SetImmediateErrorFile, - (FILE *), fh); + LLDB_RECORD_DUMMY(void, SBCommandReturnObject, SetImmediateErrorFile, + (FILE *), fh); SetImmediateErrorFile(fh, false); } void SBCommandReturnObject::SetImmediateOutputFile(FILE *fh, bool transfer_ownership) { - LLDB_RECORD_METHOD(void, SBCommandReturnObject, SetImmediateOutputFile, - (FILE *, bool), fh, transfer_ownership); - - if (m_opaque_up) - m_opaque_up->SetImmediateOutputFile(fh, transfer_ownership); + LLDB_RECORD_DUMMY(void, SBCommandReturnObject, SetImmediateOutputFile, + (FILE *, bool), fh, transfer_ownership); + FileSP file = std::make_shared<NativeFile>(fh, transfer_ownership); + ref().SetImmediateOutputFile(file); } void SBCommandReturnObject::SetImmediateErrorFile(FILE *fh, bool transfer_ownership) { + LLDB_RECORD_DUMMY(void, SBCommandReturnObject, SetImmediateErrorFile, + (FILE *, bool), fh, transfer_ownership); + FileSP file = std::make_shared<NativeFile>(fh, transfer_ownership); + ref().SetImmediateErrorFile(file); +} + +void SBCommandReturnObject::SetImmediateOutputFile(SBFile file) { + LLDB_RECORD_METHOD(void, SBCommandReturnObject, SetImmediateOutputFile, + (SBFile), file); + ref().SetImmediateOutputFile(file.m_opaque_sp); +} + +void SBCommandReturnObject::SetImmediateErrorFile(SBFile file) { LLDB_RECORD_METHOD(void, SBCommandReturnObject, SetImmediateErrorFile, - (FILE *, bool), fh, transfer_ownership); + (SBFile), file); + ref().SetImmediateErrorFile(file.m_opaque_sp); +} - if (m_opaque_up) - m_opaque_up->SetImmediateErrorFile(fh, transfer_ownership); +void SBCommandReturnObject::SetImmediateOutputFile(FileSP file_sp) { + LLDB_RECORD_METHOD(void, SBCommandReturnObject, SetImmediateOutputFile, + (FileSP), file_sp); + SetImmediateOutputFile(SBFile(file_sp)); +} + +void SBCommandReturnObject::SetImmediateErrorFile(FileSP file_sp) { + LLDB_RECORD_METHOD(void, SBCommandReturnObject, SetImmediateErrorFile, + (FileSP), file_sp); + SetImmediateErrorFile(SBFile(file_sp)); } void SBCommandReturnObject::PutCString(const char *string, int len) { LLDB_RECORD_METHOD(void, SBCommandReturnObject, PutCString, (const char *, int), string, len); - if (m_opaque_up) { - if (len == 0 || string == nullptr || *string == 0) { - return; - } else if (len > 0) { - std::string buffer(string, len); - m_opaque_up->AppendMessage(buffer.c_str()); - } else - m_opaque_up->AppendMessage(string); - } + if (len == 0 || string == nullptr || *string == 0) { + return; + } else if (len > 0) { + std::string buffer(string, len); + ref().AppendMessage(buffer.c_str()); + } else + ref().AppendMessage(string); } const char *SBCommandReturnObject::GetOutput(bool only_if_no_immediate) { LLDB_RECORD_METHOD(const char *, SBCommandReturnObject, GetOutput, (bool), only_if_no_immediate); - if (!m_opaque_up) - return nullptr; if (!only_if_no_immediate || - m_opaque_up->GetImmediateOutputStream().get() == nullptr) + ref().GetImmediateOutputStream().get() == nullptr) return GetOutput(); return nullptr; } @@ -292,23 +334,17 @@ const char *SBCommandReturnObject::GetError(bool only_if_no_immediate) { LLDB_RECORD_METHOD(const char *, SBCommandReturnObject, GetError, (bool), only_if_no_immediate); - if (!m_opaque_up) - return nullptr; - if (!only_if_no_immediate || - m_opaque_up->GetImmediateErrorStream().get() == nullptr) + if (!only_if_no_immediate || ref().GetImmediateErrorStream().get() == nullptr) return GetError(); return nullptr; } size_t SBCommandReturnObject::Printf(const char *format, ...) { - if (m_opaque_up) { - va_list args; - va_start(args, format); - size_t result = m_opaque_up->GetOutputStream().PrintfVarArg(format, args); - va_end(args); - return result; - } - return 0; + va_list args; + va_start(args, format); + size_t result = ref().GetOutputStream().PrintfVarArg(format, args); + va_end(args); + return result; } void SBCommandReturnObject::SetError(lldb::SBError &error, @@ -317,20 +353,18 @@ void SBCommandReturnObject::SetError(lldb::SBError &error, (lldb::SBError &, const char *), error, fallback_error_cstr); - if (m_opaque_up) { - if (error.IsValid()) - m_opaque_up->SetError(error.ref(), fallback_error_cstr); - else if (fallback_error_cstr) - m_opaque_up->SetError(Status(), fallback_error_cstr); - } + if (error.IsValid()) + ref().SetError(error.ref(), fallback_error_cstr); + else if (fallback_error_cstr) + ref().SetError(Status(), fallback_error_cstr); } void SBCommandReturnObject::SetError(const char *error_cstr) { LLDB_RECORD_METHOD(void, SBCommandReturnObject, SetError, (const char *), error_cstr); - if (m_opaque_up && error_cstr) - m_opaque_up->SetError(error_cstr); + if (error_cstr) + ref().SetError(error_cstr); } namespace lldb_private { @@ -340,13 +374,11 @@ template <> void RegisterMethods<SBCommandReturnObject>(Registry &R) { LLDB_REGISTER_CONSTRUCTOR(SBCommandReturnObject, ()); LLDB_REGISTER_CONSTRUCTOR(SBCommandReturnObject, - (const lldb::SBCommandReturnObject &)); + (lldb_private::CommandReturnObject &)); LLDB_REGISTER_CONSTRUCTOR(SBCommandReturnObject, - (lldb_private::CommandReturnObject *)); - LLDB_REGISTER_METHOD(lldb_private::CommandReturnObject *, - SBCommandReturnObject, Release, ()); + (const lldb::SBCommandReturnObject &)); LLDB_REGISTER_METHOD( - const lldb::SBCommandReturnObject &, + lldb::SBCommandReturnObject &, SBCommandReturnObject, operator=,(const lldb::SBCommandReturnObject &)); LLDB_REGISTER_METHOD_CONST(bool, SBCommandReturnObject, IsValid, ()); LLDB_REGISTER_METHOD_CONST(bool, SBCommandReturnObject, operator bool, ()); @@ -356,6 +388,10 @@ void RegisterMethods<SBCommandReturnObject>(Registry &R) { LLDB_REGISTER_METHOD(size_t, SBCommandReturnObject, GetErrorSize, ()); LLDB_REGISTER_METHOD(size_t, SBCommandReturnObject, PutOutput, (FILE *)); LLDB_REGISTER_METHOD(size_t, SBCommandReturnObject, PutError, (FILE *)); + LLDB_REGISTER_METHOD(size_t, SBCommandReturnObject, PutOutput, (SBFile)); + LLDB_REGISTER_METHOD(size_t, SBCommandReturnObject, PutError, (SBFile)); + LLDB_REGISTER_METHOD(size_t, SBCommandReturnObject, PutOutput, (FileSP)); + LLDB_REGISTER_METHOD(size_t, SBCommandReturnObject, PutError, (FileSP)); LLDB_REGISTER_METHOD(void, SBCommandReturnObject, Clear, ()); LLDB_REGISTER_METHOD(lldb::ReturnStatus, SBCommandReturnObject, GetStatus, ()); @@ -374,6 +410,14 @@ void RegisterMethods<SBCommandReturnObject>(Registry &R) { LLDB_REGISTER_METHOD(void, SBCommandReturnObject, SetImmediateErrorFile, (FILE *)); LLDB_REGISTER_METHOD(void, SBCommandReturnObject, SetImmediateOutputFile, + (SBFile)); + LLDB_REGISTER_METHOD(void, SBCommandReturnObject, SetImmediateErrorFile, + (SBFile)); + LLDB_REGISTER_METHOD(void, SBCommandReturnObject, SetImmediateOutputFile, + (FileSP)); + LLDB_REGISTER_METHOD(void, SBCommandReturnObject, SetImmediateErrorFile, + (FileSP)); + LLDB_REGISTER_METHOD(void, SBCommandReturnObject, SetImmediateOutputFile, (FILE *, bool)); LLDB_REGISTER_METHOD(void, SBCommandReturnObject, SetImmediateErrorFile, (FILE *, bool)); diff --git a/source/API/SBCompileUnit.cpp b/source/API/SBCompileUnit.cpp index c9ca70645d95..581bda363507 100644 --- a/source/API/SBCompileUnit.cpp +++ b/source/API/SBCompileUnit.cpp @@ -14,8 +14,9 @@ #include "lldb/Symbol/CompileUnit.h" #include "lldb/Symbol/LineEntry.h" #include "lldb/Symbol/LineTable.h" -#include "lldb/Symbol/SymbolVendor.h" +#include "lldb/Symbol/SymbolFile.h" #include "lldb/Symbol/Type.h" +#include "lldb/Symbol/TypeList.h" using namespace lldb; using namespace lldb_private; @@ -137,13 +138,13 @@ lldb::SBTypeList SBCompileUnit::GetTypes(uint32_t type_mask) { if (!module_sp) return LLDB_RECORD_RESULT(sb_type_list); - SymbolVendor *vendor = module_sp->GetSymbolVendor(); - if (!vendor) + SymbolFile *symfile = module_sp->GetSymbolFile(); + if (!symfile) return LLDB_RECORD_RESULT(sb_type_list); TypeClass type_class = static_cast<TypeClass>(type_mask); TypeList type_list; - vendor->GetTypes(m_opaque_ptr, type_class, type_list); + symfile->GetTypes(m_opaque_ptr, type_class, type_list); sb_type_list.m_opaque_up->Append(type_list); return LLDB_RECORD_RESULT(sb_type_list); } diff --git a/source/API/SBDebugger.cpp b/source/API/SBDebugger.cpp index 634c4a929595..82dc60489008 100644 --- a/source/API/SBDebugger.cpp +++ b/source/API/SBDebugger.cpp @@ -18,6 +18,7 @@ #include "lldb/API/SBCommandReturnObject.h" #include "lldb/API/SBError.h" #include "lldb/API/SBEvent.h" +#include "lldb/API/SBFile.h" #include "lldb/API/SBFrame.h" #include "lldb/API/SBListener.h" #include "lldb/API/SBProcess.h" @@ -57,51 +58,6 @@ using namespace lldb; using namespace lldb_private; -/// Helper class for replaying commands through the reproducer. -class CommandLoader { -public: - CommandLoader(std::vector<std::string> files) : m_files(files) {} - - static std::unique_ptr<CommandLoader> Create() { - repro::Loader *loader = repro::Reproducer::Instance().GetLoader(); - if (!loader) - return {}; - - FileSpec file = loader->GetFile<repro::CommandProvider::Info>(); - if (!file) - return {}; - - auto error_or_file = llvm::MemoryBuffer::getFile(file.GetPath()); - if (auto err = error_or_file.getError()) - return {}; - - std::vector<std::string> files; - llvm::yaml::Input yin((*error_or_file)->getBuffer()); - yin >> files; - - if (auto err = yin.error()) - return {}; - - for (auto &file : files) { - FileSpec absolute_path = - loader->GetRoot().CopyByAppendingPathComponent(file); - file = absolute_path.GetPath(); - } - - return llvm::make_unique<CommandLoader>(std::move(files)); - } - - FILE *GetNextFile() { - if (m_index >= m_files.size()) - return nullptr; - return FileSystem::Instance().Fopen(m_files[m_index++].c_str(), "r"); - } - -private: - std::vector<std::string> m_files; - unsigned m_index = 0; -}; - static llvm::sys::DynamicLibrary LoadPlugin(const lldb::DebuggerSP &debugger_sp, const FileSpec &spec, Status &error) { @@ -200,11 +156,9 @@ lldb::SBError SBDebugger::InitializeWithErrorHandling() { LLDB_RECORD_STATIC_METHOD_NO_ARGS(lldb::SBError, SBDebugger, InitializeWithErrorHandling); - - SBError error; if (auto e = g_debugger_lifetime->Initialize( - llvm::make_unique<SystemInitializerFull>(), LoadPlugin)) { + std::make_unique<SystemInitializerFull>(), LoadPlugin)) { error.SetError(Status(std::move(e))); } return LLDB_RECORD_RESULT(error); @@ -219,7 +173,6 @@ void SBDebugger::Terminate() { void SBDebugger::Clear() { LLDB_RECORD_METHOD_NO_ARGS(void, SBDebugger, Clear); - if (m_opaque_sp) m_opaque_sp->ClearIOHandlers(); @@ -260,7 +213,6 @@ SBDebugger SBDebugger::Create(bool source_init_files, debugger.reset(Debugger::CreateInstance(callback, baton)); - SBCommandInterpreter interp = debugger.GetCommandInterpreter(); if (source_init_files) { interp.get()->SkipLLDBInitFiles(false); @@ -278,7 +230,6 @@ void SBDebugger::Destroy(SBDebugger &debugger) { LLDB_RECORD_STATIC_METHOD(void, SBDebugger, Destroy, (lldb::SBDebugger &), debugger); - Debugger::Destroy(debugger.m_opaque_sp); if (debugger.m_opaque_sp.get() != nullptr) @@ -335,86 +286,173 @@ void SBDebugger::SkipAppInitFiles(bool b) { m_opaque_sp->GetCommandInterpreter().SkipAppInitFiles(b); } -// Shouldn't really be settable after initialization as this could cause lots -// of problems; don't want users trying to switch modes in the middle of a -// debugging session. void SBDebugger::SetInputFileHandle(FILE *fh, bool transfer_ownership) { LLDB_RECORD_METHOD(void, SBDebugger, SetInputFileHandle, (FILE *, bool), fh, transfer_ownership); + SetInputFile((FileSP)std::make_shared<NativeFile>(fh, transfer_ownership)); +} - if (!m_opaque_sp) - return; +SBError SBDebugger::SetInputFile(FileSP file_sp) { + LLDB_RECORD_METHOD(SBError, SBDebugger, SetInputFile, (FileSP), file_sp); + return SetInputFile(SBFile(file_sp)); +} + +// Shouldn't really be settable after initialization as this could cause lots +// of problems; don't want users trying to switch modes in the middle of a +// debugging session. +SBError SBDebugger::SetInputFile(SBFile file) { + LLDB_RECORD_METHOD(SBError, SBDebugger, SetInputFile, (SBFile), file); + + SBError error; + if (!m_opaque_sp) { + error.ref().SetErrorString("invalid debugger"); + return error; + } repro::DataRecorder *recorder = nullptr; if (repro::Generator *g = repro::Reproducer::Instance().GetGenerator()) recorder = g->GetOrCreate<repro::CommandProvider>().GetNewDataRecorder(); - static std::unique_ptr<CommandLoader> loader = CommandLoader::Create(); - if (loader) - fh = loader->GetNextFile(); + FileSP file_sp = file.m_opaque_sp; + + static std::unique_ptr<repro::CommandLoader> loader = + repro::CommandLoader::Create(repro::Reproducer::Instance().GetLoader()); + if (loader) { + llvm::Optional<std::string> nextfile = loader->GetNextFile(); + FILE *fh = nextfile ? FileSystem::Instance().Fopen(nextfile->c_str(), "r") + : nullptr; + // FIXME Jonas Devlieghere: shouldn't this error be propagated out to the + // reproducer somehow if fh is NULL? + if (fh) { + file_sp = std::make_shared<NativeFile>(fh, true); + } + } + + if (!file_sp || !file_sp->IsValid()) { + error.ref().SetErrorString("invalid file"); + return error; + } + + m_opaque_sp->SetInputFile(file_sp, recorder); + return error; +} - m_opaque_sp->SetInputFileHandle(fh, transfer_ownership, recorder); +SBError SBDebugger::SetOutputFile(FileSP file_sp) { + LLDB_RECORD_METHOD(SBError, SBDebugger, SetOutputFile, (FileSP), file_sp); + return SetOutputFile(SBFile(file_sp)); } void SBDebugger::SetOutputFileHandle(FILE *fh, bool transfer_ownership) { LLDB_RECORD_METHOD(void, SBDebugger, SetOutputFileHandle, (FILE *, bool), fh, transfer_ownership); + SetOutputFile((FileSP)std::make_shared<NativeFile>(fh, transfer_ownership)); +} - if (m_opaque_sp) - m_opaque_sp->SetOutputFileHandle(fh, transfer_ownership); +SBError SBDebugger::SetOutputFile(SBFile file) { + LLDB_RECORD_METHOD(SBError, SBDebugger, SetOutputFile, (SBFile file), file); + SBError error; + if (!m_opaque_sp) { + error.ref().SetErrorString("invalid debugger"); + return error; + } + if (!file) { + error.ref().SetErrorString("invalid file"); + return error; + } + m_opaque_sp->SetOutputFile(file.m_opaque_sp); + return error; } void SBDebugger::SetErrorFileHandle(FILE *fh, bool transfer_ownership) { LLDB_RECORD_METHOD(void, SBDebugger, SetErrorFileHandle, (FILE *, bool), fh, transfer_ownership); + SetErrorFile((FileSP)std::make_shared<NativeFile>(fh, transfer_ownership)); +} +SBError SBDebugger::SetErrorFile(FileSP file_sp) { + LLDB_RECORD_METHOD(SBError, SBDebugger, SetErrorFile, (FileSP), file_sp); + return SetErrorFile(SBFile(file_sp)); +} - if (m_opaque_sp) - m_opaque_sp->SetErrorFileHandle(fh, transfer_ownership); +SBError SBDebugger::SetErrorFile(SBFile file) { + LLDB_RECORD_METHOD(SBError, SBDebugger, SetErrorFile, (SBFile file), file); + SBError error; + if (!m_opaque_sp) { + error.ref().SetErrorString("invalid debugger"); + return error; + } + if (!file) { + error.ref().SetErrorString("invalid file"); + return error; + } + m_opaque_sp->SetErrorFile(file.m_opaque_sp); + return error; } FILE *SBDebugger::GetInputFileHandle() { LLDB_RECORD_METHOD_NO_ARGS(FILE *, SBDebugger, GetInputFileHandle); - if (m_opaque_sp) { - StreamFileSP stream_file_sp(m_opaque_sp->GetInputFile()); - if (stream_file_sp) - return LLDB_RECORD_RESULT(stream_file_sp->GetFile().GetStream()); + File &file_sp = m_opaque_sp->GetInputFile(); + return LLDB_RECORD_RESULT(file_sp.GetStream()); } return nullptr; } +SBFile SBDebugger::GetInputFile() { + LLDB_RECORD_METHOD_NO_ARGS(SBFile, SBDebugger, GetInputFile); + if (m_opaque_sp) { + return LLDB_RECORD_RESULT(SBFile(m_opaque_sp->GetInputFileSP())); + } + return LLDB_RECORD_RESULT(SBFile()); +} + FILE *SBDebugger::GetOutputFileHandle() { LLDB_RECORD_METHOD_NO_ARGS(FILE *, SBDebugger, GetOutputFileHandle); - if (m_opaque_sp) { - StreamFileSP stream_file_sp(m_opaque_sp->GetOutputFile()); - if (stream_file_sp) - return LLDB_RECORD_RESULT(stream_file_sp->GetFile().GetStream()); + StreamFile &stream_file = m_opaque_sp->GetOutputStream(); + return LLDB_RECORD_RESULT(stream_file.GetFile().GetStream()); } return nullptr; } +SBFile SBDebugger::GetOutputFile() { + LLDB_RECORD_METHOD_NO_ARGS(SBFile, SBDebugger, GetOutputFile); + if (m_opaque_sp) { + SBFile file(m_opaque_sp->GetOutputStream().GetFileSP()); + return LLDB_RECORD_RESULT(file); + } + return LLDB_RECORD_RESULT(SBFile()); +} + FILE *SBDebugger::GetErrorFileHandle() { LLDB_RECORD_METHOD_NO_ARGS(FILE *, SBDebugger, GetErrorFileHandle); if (m_opaque_sp) { - StreamFileSP stream_file_sp(m_opaque_sp->GetErrorFile()); - if (stream_file_sp) - return LLDB_RECORD_RESULT(stream_file_sp->GetFile().GetStream()); + StreamFile &stream_file = m_opaque_sp->GetErrorStream(); + return LLDB_RECORD_RESULT(stream_file.GetFile().GetStream()); } return nullptr; } +SBFile SBDebugger::GetErrorFile() { + LLDB_RECORD_METHOD_NO_ARGS(SBFile, SBDebugger, GetErrorFile); + SBFile file; + if (m_opaque_sp) { + SBFile file(m_opaque_sp->GetErrorStream().GetFileSP()); + return LLDB_RECORD_RESULT(file); + } + return LLDB_RECORD_RESULT(SBFile()); +} + void SBDebugger::SaveInputTerminalState() { - LLDB_RECORD_METHOD_NO_ARGS(void, SBDebugger, SaveInputTerminalState); + LLDB_RECORD_DUMMY_NO_ARGS(void, SBDebugger, SaveInputTerminalState); if (m_opaque_sp) m_opaque_sp->SaveInputTerminalState(); } void SBDebugger::RestoreInputTerminalState() { - LLDB_RECORD_METHOD_NO_ARGS(void, SBDebugger, RestoreInputTerminalState); + LLDB_RECORD_DUMMY_NO_ARGS(void, SBDebugger, RestoreInputTerminalState); if (m_opaque_sp) m_opaque_sp->RestoreInputTerminalState(); @@ -423,12 +461,10 @@ SBCommandInterpreter SBDebugger::GetCommandInterpreter() { LLDB_RECORD_METHOD_NO_ARGS(lldb::SBCommandInterpreter, SBDebugger, GetCommandInterpreter); - SBCommandInterpreter sb_interpreter; if (m_opaque_sp) sb_interpreter.reset(&m_opaque_sp->GetCommandInterpreter()); - return LLDB_RECORD_RESULT(sb_interpreter); } @@ -446,10 +482,8 @@ void SBDebugger::HandleCommand(const char *command) { sb_interpreter.HandleCommand(command, result, false); - if (GetErrorFileHandle() != nullptr) - result.PutError(GetErrorFileHandle()); - if (GetOutputFileHandle() != nullptr) - result.PutOutput(GetOutputFileHandle()); + result.PutError(m_opaque_sp->GetErrorStream().GetFileSP()); + result.PutOutput(m_opaque_sp->GetOutputStream().GetFileSP()); if (!m_opaque_sp->GetAsyncExecution()) { SBProcess process(GetCommandInterpreter().GetProcess()); @@ -460,8 +494,7 @@ void SBDebugger::HandleCommand(const char *command) { while (lldb_listener_sp->GetEventForBroadcaster( process_sp.get(), event_sp, std::chrono::seconds(0))) { SBEvent event(event_sp); - HandleProcessEvent(process, event, GetOutputFileHandle(), - GetErrorFileHandle()); + HandleProcessEvent(process, event, GetOutputFile(), GetErrorFile()); } } } @@ -471,16 +504,25 @@ void SBDebugger::HandleCommand(const char *command) { SBListener SBDebugger::GetListener() { LLDB_RECORD_METHOD_NO_ARGS(lldb::SBListener, SBDebugger, GetListener); - SBListener sb_listener; if (m_opaque_sp) sb_listener.reset(m_opaque_sp->GetListener()); - return LLDB_RECORD_RESULT(sb_listener); } void SBDebugger::HandleProcessEvent(const SBProcess &process, + const SBEvent &event, SBFile out, + SBFile err) { + LLDB_RECORD_METHOD( + void, SBDebugger, HandleProcessEvent, + (const lldb::SBProcess &, const lldb::SBEvent &, SBFile, SBFile), process, + event, out, err); + + return HandleProcessEvent(process, event, out.m_opaque_sp, err.m_opaque_sp); +} + +void SBDebugger::HandleProcessEvent(const SBProcess &process, const SBEvent &event, FILE *out, FILE *err) { LLDB_RECORD_METHOD( @@ -488,6 +530,20 @@ void SBDebugger::HandleProcessEvent(const SBProcess &process, (const lldb::SBProcess &, const lldb::SBEvent &, FILE *, FILE *), process, event, out, err); + FileSP outfile = std::make_shared<NativeFile>(out, false); + FileSP errfile = std::make_shared<NativeFile>(err, false); + return HandleProcessEvent(process, event, outfile, errfile); +} + +void SBDebugger::HandleProcessEvent(const SBProcess &process, + const SBEvent &event, FileSP out_sp, + FileSP err_sp) { + + LLDB_RECORD_METHOD( + void, SBDebugger, HandleProcessEvent, + (const lldb::SBProcess &, const lldb::SBEvent &, FileSP, FileSP), process, + event, out_sp, err_sp); + if (!process.IsValid()) return; @@ -505,16 +561,16 @@ void SBDebugger::HandleProcessEvent(const SBProcess &process, (Process::eBroadcastBitSTDOUT | Process::eBroadcastBitStateChanged)) { // Drain stdout when we stop just in case we have any bytes while ((len = process.GetSTDOUT(stdio_buffer, sizeof(stdio_buffer))) > 0) - if (out != nullptr) - ::fwrite(stdio_buffer, 1, len, out); + if (out_sp) + out_sp->Write(stdio_buffer, len); } if (event_type & (Process::eBroadcastBitSTDERR | Process::eBroadcastBitStateChanged)) { // Drain stderr when we stop just in case we have any bytes while ((len = process.GetSTDERR(stdio_buffer, sizeof(stdio_buffer))) > 0) - if (err != nullptr) - ::fwrite(stdio_buffer, 1, len, err); + if (err_sp) + err_sp->Write(stdio_buffer, len); } if (event_type & Process::eBroadcastBitStateChanged) { @@ -525,7 +581,7 @@ void SBDebugger::HandleProcessEvent(const SBProcess &process, bool is_stopped = StateIsStoppedState(event_state); if (!is_stopped) - process.ReportEventState(event, out); + process.ReportEventState(event, out_sp); } } @@ -578,7 +634,8 @@ SBDebugger::GetScriptingLanguage(const char *script_language_name) { LLDB_RECORD_METHOD(lldb::ScriptLanguage, SBDebugger, GetScriptingLanguage, (const char *), script_language_name); - if (!script_language_name) return eScriptLanguageDefault; + if (!script_language_name) + return eScriptLanguageDefault; return OptionArgParser::ToScriptLanguage( llvm::StringRef(script_language_name), eScriptLanguageDefault, nullptr); } @@ -599,18 +656,18 @@ const char *SBDebugger::StateAsCString(StateType state) { static void AddBoolConfigEntry(StructuredData::Dictionary &dict, llvm::StringRef name, bool value, llvm::StringRef description) { - auto entry_up = llvm::make_unique<StructuredData::Dictionary>(); + auto entry_up = std::make_unique<StructuredData::Dictionary>(); entry_up->AddBooleanItem("value", value); entry_up->AddStringItem("description", description); dict.AddItem(name, std::move(entry_up)); } static void AddLLVMTargets(StructuredData::Dictionary &dict) { - auto array_up = llvm::make_unique<StructuredData::Array>(); + auto array_up = std::make_unique<StructuredData::Array>(); #define LLVM_TARGET(target) \ - array_up->AddItem(llvm::make_unique<StructuredData::String>(#target)); + array_up->AddItem(std::make_unique<StructuredData::String>(#target)); #include "llvm/Config/Targets.def" - auto entry_up = llvm::make_unique<StructuredData::Dictionary>(); + auto entry_up = std::make_unique<StructuredData::Dictionary>(); entry_up->AddItem("value", std::move(array_up)); entry_up->AddStringItem("description", "A list of configured LLVM targets."); dict.AddItem("targets", std::move(entry_up)); @@ -620,10 +677,17 @@ SBStructuredData SBDebugger::GetBuildConfiguration() { LLDB_RECORD_STATIC_METHOD_NO_ARGS(lldb::SBStructuredData, SBDebugger, GetBuildConfiguration); - auto config_up = llvm::make_unique<StructuredData::Dictionary>(); + auto config_up = std::make_unique<StructuredData::Dictionary>(); AddBoolConfigEntry( *config_up, "xml", XMLDocument::XMLEnabled(), "A boolean value that indicates if XML support is enabled in LLDB"); + bool have_curses = true; +#ifdef LLDB_DISABLE_CURSES + have_curses = false; +#endif + AddBoolConfigEntry( + *config_up, "curses", have_curses, + "A boolean value that indicates if curses support is enabled in LLDB"); AddLLVMTargets(*config_up); SBStructuredData data; @@ -635,7 +699,6 @@ bool SBDebugger::StateIsRunningState(StateType state) { LLDB_RECORD_STATIC_METHOD(bool, SBDebugger, StateIsRunningState, (lldb::StateType), state); - const bool result = lldb_private::StateIsRunningState(state); return result; @@ -645,7 +708,6 @@ bool SBDebugger::StateIsStoppedState(StateType state) { LLDB_RECORD_STATIC_METHOD(bool, SBDebugger, StateIsStoppedState, (lldb::StateType), state); - const bool result = lldb_private::StateIsStoppedState(state, false); return result; @@ -680,13 +742,13 @@ lldb::SBTarget SBDebugger::CreateTarget(const char *filename, } Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_API)); - if (log) - log->Printf("SBDebugger(%p)::CreateTarget (filename=\"%s\", triple=%s, " - "platform_name=%s, add_dependent_modules=%u, error=%s) => " - "SBTarget(%p)", - static_cast<void *>(m_opaque_sp.get()), filename, target_triple, - platform_name, add_dependent_modules, sb_error.GetCString(), - static_cast<void *>(target_sp.get())); + LLDB_LOGF(log, + "SBDebugger(%p)::CreateTarget (filename=\"%s\", triple=%s, " + "platform_name=%s, add_dependent_modules=%u, error=%s) => " + "SBTarget(%p)", + static_cast<void *>(m_opaque_sp.get()), filename, target_triple, + platform_name, add_dependent_modules, sb_error.GetCString(), + static_cast<void *>(target_sp.get())); return LLDB_RECORD_RESULT(sb_target); } @@ -710,11 +772,11 @@ SBDebugger::CreateTargetWithFileAndTargetTriple(const char *filename, } Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_API)); - if (log) - log->Printf("SBDebugger(%p)::CreateTargetWithFileAndTargetTriple " - "(filename=\"%s\", triple=%s) => SBTarget(%p)", - static_cast<void *>(m_opaque_sp.get()), filename, target_triple, - static_cast<void *>(target_sp.get())); + LLDB_LOGF(log, + "SBDebugger(%p)::CreateTargetWithFileAndTargetTriple " + "(filename=\"%s\", triple=%s) => SBTarget(%p)", + static_cast<void *>(m_opaque_sp.get()), filename, target_triple, + static_cast<void *>(target_sp.get())); return LLDB_RECORD_RESULT(sb_target); } @@ -743,11 +805,11 @@ SBTarget SBDebugger::CreateTargetWithFileAndArch(const char *filename, } } - if (log) - log->Printf("SBDebugger(%p)::CreateTargetWithFileAndArch (filename=\"%s\", " - "arch=%s) => SBTarget(%p)", - static_cast<void *>(m_opaque_sp.get()), filename, arch_cstr, - static_cast<void *>(target_sp.get())); + LLDB_LOGF(log, + "SBDebugger(%p)::CreateTargetWithFileAndArch (filename=\"%s\", " + "arch=%s) => SBTarget(%p)", + static_cast<void *>(m_opaque_sp.get()), filename, arch_cstr, + static_cast<void *>(target_sp.get())); return LLDB_RECORD_RESULT(sb_target); } @@ -772,11 +834,10 @@ SBTarget SBDebugger::CreateTarget(const char *filename) { } } Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_API)); - if (log) - log->Printf( - "SBDebugger(%p)::CreateTarget (filename=\"%s\") => SBTarget(%p)", - static_cast<void *>(m_opaque_sp.get()), filename, - static_cast<void *>(target_sp.get())); + LLDB_LOGF(log, + "SBDebugger(%p)::CreateTarget (filename=\"%s\") => SBTarget(%p)", + static_cast<void *>(m_opaque_sp.get()), filename, + static_cast<void *>(target_sp.get())); return LLDB_RECORD_RESULT(sb_target); } @@ -785,14 +846,12 @@ SBTarget SBDebugger::GetDummyTarget() { SBTarget sb_target; if (m_opaque_sp) { - sb_target.SetSP(m_opaque_sp->GetDummyTarget()->shared_from_this()); + sb_target.SetSP(m_opaque_sp->GetDummyTarget()->shared_from_this()); } Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_API)); - if (log) - log->Printf( - "SBDebugger(%p)::GetDummyTarget() => SBTarget(%p)", - static_cast<void *>(m_opaque_sp.get()), - static_cast<void *>(sb_target.GetSP().get())); + LLDB_LOGF(log, "SBDebugger(%p)::GetDummyTarget() => SBTarget(%p)", + static_cast<void *>(m_opaque_sp.get()), + static_cast<void *>(sb_target.GetSP().get())); return LLDB_RECORD_RESULT(sb_target); } @@ -814,10 +873,9 @@ bool SBDebugger::DeleteTarget(lldb::SBTarget &target) { } Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_API)); - if (log) - log->Printf("SBDebugger(%p)::DeleteTarget (SBTarget(%p)) => %i", - static_cast<void *>(m_opaque_sp.get()), - static_cast<void *>(target.m_opaque_sp.get()), result); + LLDB_LOGF(log, "SBDebugger(%p)::DeleteTarget (SBTarget(%p)) => %i", + static_cast<void *>(m_opaque_sp.get()), + static_cast<void *>(target.m_opaque_sp.get()), result); return result; } @@ -914,9 +972,9 @@ SBTarget SBDebugger::GetSelectedTarget() { if (log) { SBStream sstr; sb_target.GetDescription(sstr, eDescriptionLevelBrief); - log->Printf("SBDebugger(%p)::GetSelectedTarget () => SBTarget(%p): %s", - static_cast<void *>(m_opaque_sp.get()), - static_cast<void *>(target_sp.get()), sstr.GetData()); + LLDB_LOGF(log, "SBDebugger(%p)::GetSelectedTarget () => SBTarget(%p): %s", + static_cast<void *>(m_opaque_sp.get()), + static_cast<void *>(target_sp.get()), sstr.GetData()); } return LLDB_RECORD_RESULT(sb_target); @@ -935,9 +993,9 @@ void SBDebugger::SetSelectedTarget(SBTarget &sb_target) { if (log) { SBStream sstr; sb_target.GetDescription(sstr, eDescriptionLevelBrief); - log->Printf("SBDebugger(%p)::SetSelectedTarget () => SBTarget(%p): %s", - static_cast<void *>(m_opaque_sp.get()), - static_cast<void *>(target_sp.get()), sstr.GetData()); + LLDB_LOGF(log, "SBDebugger(%p)::SetSelectedTarget () => SBTarget(%p): %s", + static_cast<void *>(m_opaque_sp.get()), + static_cast<void *>(target_sp.get()), sstr.GetData()); } } @@ -951,11 +1009,10 @@ SBPlatform SBDebugger::GetSelectedPlatform() { if (debugger_sp) { sb_platform.SetSP(debugger_sp->GetPlatformList().GetSelectedPlatform()); } - if (log) - log->Printf("SBDebugger(%p)::GetSelectedPlatform () => SBPlatform(%p): %s", - static_cast<void *>(m_opaque_sp.get()), - static_cast<void *>(sb_platform.GetSP().get()), - sb_platform.GetName()); + LLDB_LOGF(log, "SBDebugger(%p)::GetSelectedPlatform () => SBPlatform(%p): %s", + static_cast<void *>(m_opaque_sp.get()), + static_cast<void *>(sb_platform.GetSP().get()), + sb_platform.GetName()); return LLDB_RECORD_RESULT(sb_platform); } @@ -970,11 +1027,10 @@ void SBDebugger::SetSelectedPlatform(SBPlatform &sb_platform) { debugger_sp->GetPlatformList().SetSelectedPlatform(sb_platform.GetSP()); } - if (log) - log->Printf("SBDebugger(%p)::SetSelectedPlatform (SBPlatform(%p) %s)", - static_cast<void *>(m_opaque_sp.get()), - static_cast<void *>(sb_platform.GetSP().get()), - sb_platform.GetName()); + LLDB_LOGF(log, "SBDebugger(%p)::SetSelectedPlatform (SBPlatform(%p) %s)", + static_cast<void *>(m_opaque_sp.get()), + static_cast<void *>(sb_platform.GetSP().get()), + sb_platform.GetName()); } uint32_t SBDebugger::GetNumPlatforms() { @@ -1018,7 +1074,7 @@ SBStructuredData SBDebugger::GetAvailablePlatformInfoAtIndex(uint32_t idx) { GetAvailablePlatformInfoAtIndex, (uint32_t), idx); SBStructuredData data; - auto platform_dict = llvm::make_unique<StructuredData::Dictionary>(); + auto platform_dict = std::make_unique<StructuredData::Dictionary>(); llvm::StringRef name_str("name"), desc_str("description"); if (idx == 0) { @@ -1062,7 +1118,7 @@ void SBDebugger::DispatchInput(const void *data, size_t data_len) { // Log *log(GetLogIfAllCategoriesSet (LIBLLDB_LOG_API)); // // if (log) - // log->Printf ("SBDebugger(%p)::DispatchInput (data=\"%.*s\", + // LLDB_LOGF(log, "SBDebugger(%p)::DispatchInput (data=\"%.*s\", // size_t=%" PRIu64 ")", // m_opaque_sp.get(), // (int) data_len, @@ -1074,7 +1130,7 @@ void SBDebugger::DispatchInput(const void *data, size_t data_len) { } void SBDebugger::DispatchInputInterrupt() { - LLDB_RECORD_METHOD_NO_ARGS(void, SBDebugger, DispatchInputInterrupt); + LLDB_RECORD_DUMMY_NO_ARGS(void, SBDebugger, DispatchInputInterrupt); if (m_opaque_sp) m_opaque_sp->DispatchInputInterrupt(); @@ -1234,8 +1290,7 @@ uint32_t SBDebugger::GetTerminalWidth() const { } void SBDebugger::SetTerminalWidth(uint32_t term_width) { - LLDB_RECORD_METHOD(void, SBDebugger, SetTerminalWidth, (uint32_t), - term_width); + LLDB_RECORD_DUMMY(void, SBDebugger, SetTerminalWidth, (uint32_t), term_width); if (m_opaque_sp) m_opaque_sp->SetTerminalWidth(term_width); @@ -1246,10 +1301,9 @@ const char *SBDebugger::GetPrompt() const { Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_API)); - if (log) - log->Printf("SBDebugger(%p)::GetPrompt () => \"%s\"", - static_cast<void *>(m_opaque_sp.get()), - (m_opaque_sp ? m_opaque_sp->GetPrompt().str().c_str() : "")); + LLDB_LOGF(log, "SBDebugger(%p)::GetPrompt () => \"%s\"", + static_cast<void *>(m_opaque_sp.get()), + (m_opaque_sp ? m_opaque_sp->GetPrompt().str().c_str() : "")); return (m_opaque_sp ? ConstString(m_opaque_sp->GetPrompt()).GetCString() : nullptr); @@ -1374,7 +1428,8 @@ bool SBDebugger::SetCurrentPlatformSDKRoot(const char *sysroot) { if (platform_sp) { if (log && sysroot) - log->Printf("SBDebugger::SetCurrentPlatformSDKRoot (\"%s\")", sysroot); + LLDB_LOGF(log, "SBDebugger::SetCurrentPlatformSDKRoot (\"%s\")", + sysroot); platform_sp->SetSDKRootDirectory(ConstString(sysroot)); return true; } @@ -1549,8 +1604,7 @@ void SBDebugger::SetLoggingCallback(lldb::LogOutputCallback log_callback, namespace lldb_private { namespace repro { -template <> -void RegisterMethods<SBInputReader>(Registry &R) { +template <> void RegisterMethods<SBInputReader>(Registry &R) { LLDB_REGISTER_METHOD(void, SBInputReader, SetIsDone, (bool)); LLDB_REGISTER_METHOD_CONST(bool, SBInputReader, IsActive, ()); } @@ -1559,6 +1613,10 @@ static void SetFileHandleRedirect(SBDebugger *, FILE *, bool) { // Do nothing. } +static SBError SetFileRedirect(SBDebugger *, SBFile file) { return SBError(); } + +static SBError SetFileRedirect(SBDebugger *, FileSP file) { return SBError(); } + static bool GetDefaultArchitectureRedirect(char *arch_name, size_t arch_name_len) { // The function is writing to its argument. Without the redirect it would @@ -1567,8 +1625,7 @@ static bool GetDefaultArchitectureRedirect(char *arch_name, return SBDebugger::GetDefaultArchitecture(buffer, arch_name_len); } -template <> -void RegisterMethods<SBDebugger>(Registry &R) { +template <> void RegisterMethods<SBDebugger>(Registry &R) { // Custom implementation. R.Register(&invoke<void (SBDebugger::*)( FILE *, bool)>::method<&SBDebugger::SetErrorFileHandle>::doit, @@ -1580,6 +1637,26 @@ void RegisterMethods<SBDebugger>(Registry &R) { &SBDebugger::GetDefaultArchitecture), &GetDefaultArchitectureRedirect); + R.Register(&invoke<SBError (SBDebugger::*)( + SBFile)>::method<&SBDebugger::SetInputFile>::doit, + &SetFileRedirect); + R.Register(&invoke<SBError (SBDebugger::*)( + SBFile)>::method<&SBDebugger::SetOutputFile>::doit, + &SetFileRedirect); + R.Register(&invoke<SBError (SBDebugger::*)( + SBFile)>::method<&SBDebugger::SetErrorFile>::doit, + &SetFileRedirect); + + R.Register(&invoke<SBError (SBDebugger::*)( + FileSP)>::method<&SBDebugger::SetInputFile>::doit, + &SetFileRedirect); + R.Register(&invoke<SBError (SBDebugger::*)( + FileSP)>::method<&SBDebugger::SetOutputFile>::doit, + &SetFileRedirect); + R.Register(&invoke<SBError (SBDebugger::*)( + FileSP)>::method<&SBDebugger::SetErrorFile>::doit, + &SetFileRedirect); + LLDB_REGISTER_CONSTRUCTOR(SBDebugger, ()); LLDB_REGISTER_CONSTRUCTOR(SBDebugger, (const lldb::DebuggerSP &)); LLDB_REGISTER_CONSTRUCTOR(SBDebugger, (const lldb::SBDebugger &)); @@ -1592,11 +1669,10 @@ void RegisterMethods<SBDebugger>(Registry &R) { LLDB_REGISTER_METHOD(void, SBDebugger, Clear, ()); LLDB_REGISTER_STATIC_METHOD(lldb::SBDebugger, SBDebugger, Create, ()); LLDB_REGISTER_STATIC_METHOD(lldb::SBDebugger, SBDebugger, Create, (bool)); - LLDB_REGISTER_STATIC_METHOD(void, SBDebugger, Destroy, - (lldb::SBDebugger &)); + LLDB_REGISTER_STATIC_METHOD(void, SBDebugger, Destroy, (lldb::SBDebugger &)); LLDB_REGISTER_STATIC_METHOD(void, SBDebugger, MemoryPressureDetected, ()); LLDB_REGISTER_METHOD_CONST(bool, SBDebugger, IsValid, ()); - LLDB_REGISTER_METHOD_CONST(bool, SBDebugger, operator bool, ()); + LLDB_REGISTER_METHOD_CONST(bool, SBDebugger, operator bool,()); LLDB_REGISTER_METHOD(void, SBDebugger, SetAsync, (bool)); LLDB_REGISTER_METHOD(bool, SBDebugger, GetAsync, ()); LLDB_REGISTER_METHOD(void, SBDebugger, SkipLLDBInitFiles, (bool)); @@ -1605,6 +1681,9 @@ void RegisterMethods<SBDebugger>(Registry &R) { LLDB_REGISTER_METHOD(FILE *, SBDebugger, GetInputFileHandle, ()); LLDB_REGISTER_METHOD(FILE *, SBDebugger, GetOutputFileHandle, ()); LLDB_REGISTER_METHOD(FILE *, SBDebugger, GetErrorFileHandle, ()); + LLDB_REGISTER_METHOD(SBFile, SBDebugger, GetInputFile, ()); + LLDB_REGISTER_METHOD(SBFile, SBDebugger, GetOutputFile, ()); + LLDB_REGISTER_METHOD(SBFile, SBDebugger, GetErrorFile, ()); LLDB_REGISTER_METHOD(void, SBDebugger, SaveInputTerminalState, ()); LLDB_REGISTER_METHOD(void, SBDebugger, RestoreInputTerminalState, ()); LLDB_REGISTER_METHOD(lldb::SBCommandInterpreter, SBDebugger, @@ -1614,8 +1693,13 @@ void RegisterMethods<SBDebugger>(Registry &R) { LLDB_REGISTER_METHOD( void, SBDebugger, HandleProcessEvent, (const lldb::SBProcess &, const lldb::SBEvent &, FILE *, FILE *)); - LLDB_REGISTER_METHOD(lldb::SBSourceManager, SBDebugger, GetSourceManager, - ()); + LLDB_REGISTER_METHOD( + void, SBDebugger, HandleProcessEvent, + (const lldb::SBProcess &, const lldb::SBEvent &, SBFile, SBFile)); + LLDB_REGISTER_METHOD( + void, SBDebugger, HandleProcessEvent, + (const lldb::SBProcess &, const lldb::SBEvent &, FileSP, FileSP)); + LLDB_REGISTER_METHOD(lldb::SBSourceManager, SBDebugger, GetSourceManager, ()); LLDB_REGISTER_STATIC_METHOD(bool, SBDebugger, SetDefaultArchitecture, (const char *)); LLDB_REGISTER_METHOD(lldb::ScriptLanguage, SBDebugger, GetScriptingLanguage, @@ -1635,8 +1719,7 @@ void RegisterMethods<SBDebugger>(Registry &R) { LLDB_REGISTER_METHOD(lldb::SBTarget, SBDebugger, CreateTargetWithFileAndTargetTriple, (const char *, const char *)); - LLDB_REGISTER_METHOD(lldb::SBTarget, SBDebugger, - CreateTargetWithFileAndArch, + LLDB_REGISTER_METHOD(lldb::SBTarget, SBDebugger, CreateTargetWithFileAndArch, (const char *, const char *)); LLDB_REGISTER_METHOD(lldb::SBTarget, SBDebugger, CreateTarget, (const char *)); @@ -1652,8 +1735,7 @@ void RegisterMethods<SBDebugger>(Registry &R) { (const char *, const char *)); LLDB_REGISTER_METHOD(uint32_t, SBDebugger, GetNumTargets, ()); LLDB_REGISTER_METHOD(lldb::SBTarget, SBDebugger, GetSelectedTarget, ()); - LLDB_REGISTER_METHOD(void, SBDebugger, SetSelectedTarget, - (lldb::SBTarget &)); + LLDB_REGISTER_METHOD(void, SBDebugger, SetSelectedTarget, (lldb::SBTarget &)); LLDB_REGISTER_METHOD(lldb::SBPlatform, SBDebugger, GetSelectedPlatform, ()); LLDB_REGISTER_METHOD(void, SBDebugger, SetSelectedPlatform, (lldb::SBPlatform &)); @@ -1673,8 +1755,8 @@ void RegisterMethods<SBDebugger>(Registry &R) { int &, bool &, bool &)); LLDB_REGISTER_METHOD(lldb::SBError, SBDebugger, RunREPL, (lldb::LanguageType, const char *)); - LLDB_REGISTER_STATIC_METHOD(lldb::SBDebugger, SBDebugger, - FindDebuggerWithID, (int)); + LLDB_REGISTER_STATIC_METHOD(lldb::SBDebugger, SBDebugger, FindDebuggerWithID, + (int)); LLDB_REGISTER_METHOD(const char *, SBDebugger, GetInstanceName, ()); LLDB_REGISTER_STATIC_METHOD(lldb::SBError, SBDebugger, SetInternalVariable, (const char *, const char *, const char *)); @@ -1726,5 +1808,5 @@ void RegisterMethods<SBDebugger>(Registry &R) { (const char *, const char **)); } -} -} +} // namespace repro +} // namespace lldb_private diff --git a/source/API/SBDeclaration.cpp b/source/API/SBDeclaration.cpp index a7790b293981..50db1770c612 100644 --- a/source/API/SBDeclaration.cpp +++ b/source/API/SBDeclaration.cpp @@ -32,7 +32,7 @@ SBDeclaration::SBDeclaration(const SBDeclaration &rhs) : m_opaque_up() { SBDeclaration::SBDeclaration(const lldb_private::Declaration *lldb_object_ptr) : m_opaque_up() { if (lldb_object_ptr) - m_opaque_up = llvm::make_unique<Declaration>(*lldb_object_ptr); + m_opaque_up = std::make_unique<Declaration>(*lldb_object_ptr); } const SBDeclaration &SBDeclaration::operator=(const SBDeclaration &rhs) { diff --git a/source/API/SBFile.cpp b/source/API/SBFile.cpp new file mode 100644 index 000000000000..f5a38efe4a77 --- /dev/null +++ b/source/API/SBFile.cpp @@ -0,0 +1,129 @@ +//===-- SBFile.cpp ------------------------------------------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#include "lldb/API/SBFile.h" +#include "SBReproducerPrivate.h" +#include "lldb/API/SBError.h" +#include "lldb/Host/File.h" + +using namespace lldb; +using namespace lldb_private; + +SBFile::~SBFile() {} + +SBFile::SBFile(FileSP file_sp) : m_opaque_sp(file_sp) { + LLDB_RECORD_DUMMY(void, SBfile, SBFile, (FileSP), file_sp); +} + +SBFile::SBFile() { LLDB_RECORD_CONSTRUCTOR_NO_ARGS(SBFile); } + +SBFile::SBFile(FILE *file, bool transfer_ownership) { + LLDB_RECORD_DUMMY(void, SBFile, (FILE *, bool), file, transfer_ownership); + m_opaque_sp = std::make_shared<NativeFile>(file, transfer_ownership); +} + +SBFile::SBFile(int fd, const char *mode, bool transfer_owndership) { + LLDB_RECORD_DUMMY(void, SBFile, (int, const char *, bool), fd, mode, + transfer_owndership); + auto options = File::GetOptionsFromMode(mode); + if (!options) { + llvm::consumeError(options.takeError()); + return; + } + m_opaque_sp = + std::make_shared<NativeFile>(fd, options.get(), transfer_owndership); +} + +SBError SBFile::Read(uint8_t *buf, size_t num_bytes, size_t *bytes_read) { + LLDB_RECORD_DUMMY(lldb::SBError, SBFile, Read, (uint8_t *, size_t, size_t *), + buf, num_bytes, bytes_read); + SBError error; + if (!m_opaque_sp) { + error.SetErrorString("invalid SBFile"); + *bytes_read = 0; + } else { + Status status = m_opaque_sp->Read(buf, num_bytes); + error.SetError(status); + *bytes_read = num_bytes; + } + return LLDB_RECORD_RESULT(error); +} + +SBError SBFile::Write(const uint8_t *buf, size_t num_bytes, + size_t *bytes_written) { + LLDB_RECORD_DUMMY(lldb::SBError, SBFile, Write, + (const uint8_t *, size_t, size_t *), buf, num_bytes, + bytes_written); + SBError error; + if (!m_opaque_sp) { + error.SetErrorString("invalid SBFile"); + *bytes_written = 0; + } else { + Status status = m_opaque_sp->Write(buf, num_bytes); + error.SetError(status); + *bytes_written = num_bytes; + } + return LLDB_RECORD_RESULT(error); +} + +SBError SBFile::Flush() { + LLDB_RECORD_METHOD_NO_ARGS(lldb::SBError, SBFile, Flush); + SBError error; + if (!m_opaque_sp) { + error.SetErrorString("invalid SBFile"); + } else { + Status status = m_opaque_sp->Flush(); + error.SetError(status); + } + return LLDB_RECORD_RESULT(error); +} + +bool SBFile::IsValid() const { + LLDB_RECORD_METHOD_CONST_NO_ARGS(bool, SBFile, IsValid); + return m_opaque_sp && m_opaque_sp->IsValid(); +} + +SBError SBFile::Close() { + LLDB_RECORD_METHOD_NO_ARGS(lldb::SBError, SBFile, Close); + SBError error; + if (m_opaque_sp) { + Status status = m_opaque_sp->Close(); + error.SetError(status); + } + return LLDB_RECORD_RESULT(error); +} + +SBFile::operator bool() const { + LLDB_RECORD_METHOD_CONST_NO_ARGS(bool, SBFile, operator bool); + return LLDB_RECORD_RESULT(IsValid()); +} + +bool SBFile::operator!() const { + LLDB_RECORD_METHOD_CONST_NO_ARGS(bool, SBFile, operator!); + return LLDB_RECORD_RESULT(!IsValid()); +} + +FileSP SBFile::GetFile() const { + LLDB_RECORD_METHOD_CONST_NO_ARGS(FileSP, SBFile, GetFile); + return m_opaque_sp; +} + +namespace lldb_private { +namespace repro { + +template <> void RegisterMethods<SBFile>(Registry &R) { + + LLDB_REGISTER_METHOD(lldb::SBError, SBFile, Flush, ()); + LLDB_REGISTER_METHOD_CONST(bool, SBFile, IsValid, ()); + LLDB_REGISTER_METHOD_CONST(bool, SBFile, operator bool,()); + LLDB_REGISTER_METHOD_CONST(bool, SBFile, operator!,()); + LLDB_REGISTER_METHOD_CONST(FileSP, SBFile, GetFile, ()); + LLDB_REGISTER_METHOD(lldb::SBError, SBFile, Close, ()); +} +} // namespace repro +} // namespace lldb_private diff --git a/source/API/SBFrame.cpp b/source/API/SBFrame.cpp index 9268f0f9bdbf..c0e272e1bcd4 100644 --- a/source/API/SBFrame.cpp +++ b/source/API/SBFrame.cpp @@ -1107,7 +1107,7 @@ lldb::SBValue SBFrame::EvaluateExpression(const char *expr, if (target->GetDisplayExpressionsInCrashlogs()) { StreamString frame_description; frame->DumpUsingSettingsFormat(&frame_description); - stack_trace = llvm::make_unique<llvm::PrettyStackTraceFormat>( + stack_trace = std::make_unique<llvm::PrettyStackTraceFormat>( "SBFrame::EvaluateExpression (expr = \"%s\", fetch_dynamic_value " "= %u) %s", expr, options.GetFetchDynamicValue(), @@ -1120,10 +1120,10 @@ lldb::SBValue SBFrame::EvaluateExpression(const char *expr, } } - if (expr_log) - expr_log->Printf("** [SBFrame::EvaluateExpression] Expression result is " - "%s, summary %s **", - expr_result.GetValue(), expr_result.GetSummary()); + LLDB_LOGF(expr_log, + "** [SBFrame::EvaluateExpression] Expression result is " + "%s, summary %s **", + expr_result.GetValue(), expr_result.GetSummary()); return LLDB_RECORD_RESULT(expr_result); } diff --git a/source/API/SBInstruction.cpp b/source/API/SBInstruction.cpp index fcf66fd25824..a9ef9fb59d24 100644 --- a/source/API/SBInstruction.cpp +++ b/source/API/SBInstruction.cpp @@ -11,6 +11,7 @@ #include "lldb/API/SBAddress.h" #include "lldb/API/SBFrame.h" +#include "lldb/API/SBFile.h" #include "lldb/API/SBInstruction.h" #include "lldb/API/SBStream.h" @@ -255,10 +256,21 @@ bool SBInstruction::GetDescription(lldb::SBStream &s) { return false; } -void SBInstruction::Print(FILE *out) { - LLDB_RECORD_METHOD(void, SBInstruction, Print, (FILE *), out); +void SBInstruction::Print(FILE *outp) { + LLDB_RECORD_METHOD(void, SBInstruction, Print, (FILE *), outp); + FileSP out = std::make_shared<NativeFile>(outp, /*take_ownership=*/false); + Print(out); +} + +void SBInstruction::Print(SBFile out) { + LLDB_RECORD_METHOD(void, SBInstruction, Print, (SBFile), out); + Print(out.m_opaque_sp); +} + +void SBInstruction::Print(FileSP out_sp) { + LLDB_RECORD_METHOD(void, SBInstruction, Print, (FileSP), out_sp); - if (out == nullptr) + if (!out_sp || !out_sp->IsValid()) return; lldb::InstructionSP inst_sp(GetOpaque()); @@ -269,7 +281,7 @@ void SBInstruction::Print(FILE *out) { if (module_sp) module_sp->ResolveSymbolContextForAddress(addr, eSymbolContextEverything, sc); - StreamFile out_stream(out, false); + StreamFile out_stream(out_sp); FormatEntity::Entry format; FormatEntity::Parse("${addr}: ", format); inst_sp->Dump(&out_stream, 0, true, false, nullptr, &sc, nullptr, &format, @@ -358,6 +370,8 @@ void RegisterMethods<SBInstruction>(Registry &R) { LLDB_REGISTER_METHOD(bool, SBInstruction, GetDescription, (lldb::SBStream &)); LLDB_REGISTER_METHOD(void, SBInstruction, Print, (FILE *)); + LLDB_REGISTER_METHOD(void, SBInstruction, Print, (SBFile)); + LLDB_REGISTER_METHOD(void, SBInstruction, Print, (FileSP)); LLDB_REGISTER_METHOD(bool, SBInstruction, EmulateWithFrame, (lldb::SBFrame &, uint32_t)); LLDB_REGISTER_METHOD(bool, SBInstruction, DumpEmulation, (const char *)); diff --git a/source/API/SBInstructionList.cpp b/source/API/SBInstructionList.cpp index cce923bf04a4..8b3855c0883b 100644 --- a/source/API/SBInstructionList.cpp +++ b/source/API/SBInstructionList.cpp @@ -11,8 +11,10 @@ #include "lldb/API/SBAddress.h" #include "lldb/API/SBInstruction.h" #include "lldb/API/SBStream.h" +#include "lldb/API/SBFile.h" #include "lldb/Core/Disassembler.h" #include "lldb/Core/Module.h" +#include "lldb/Core/StreamFile.h" #include "lldb/Symbol/SymbolContext.h" #include "lldb/Utility/Stream.h" @@ -118,21 +120,41 @@ void SBInstructionList::SetDisassembler(const lldb::DisassemblerSP &opaque_sp) { void SBInstructionList::Print(FILE *out) { LLDB_RECORD_METHOD(void, SBInstructionList, Print, (FILE *), out); - if (out == nullptr) return; + StreamFile stream(out, false); + GetDescription(stream); } -bool SBInstructionList::GetDescription(lldb::SBStream &description) { +void SBInstructionList::Print(SBFile out) { + LLDB_RECORD_METHOD(void, SBInstructionList, Print, (SBFile), out); + if (!out.IsValid()) + return; + StreamFile stream(out.m_opaque_sp); + GetDescription(stream); +} + +void SBInstructionList::Print(FileSP out_sp) { + LLDB_RECORD_METHOD(void, SBInstructionList, Print, (FileSP), out_sp); + if (!out_sp || !out_sp->IsValid()) + return; + StreamFile stream(out_sp); + GetDescription(stream); +} + +bool SBInstructionList::GetDescription(lldb::SBStream &stream) { LLDB_RECORD_METHOD(bool, SBInstructionList, GetDescription, - (lldb::SBStream &), description); + (lldb::SBStream &), stream); + return GetDescription(stream.ref()); +} + +bool SBInstructionList::GetDescription(Stream &sref) { if (m_opaque_sp) { size_t num_instructions = GetSize(); if (num_instructions) { // Call the ref() to make sure a stream is created if one deesn't exist // already inside description... - Stream &sref = description.ref(); const uint32_t max_opcode_byte_size = m_opaque_sp->GetInstructionList().GetMaxOpcocdeByteSize(); FormatEntity::Entry format; @@ -200,6 +222,8 @@ void RegisterMethods<SBInstructionList>(Registry &R) { LLDB_REGISTER_METHOD(void, SBInstructionList, AppendInstruction, (lldb::SBInstruction)); LLDB_REGISTER_METHOD(void, SBInstructionList, Print, (FILE *)); + LLDB_REGISTER_METHOD(void, SBInstructionList, Print, (SBFile)); + LLDB_REGISTER_METHOD(void, SBInstructionList, Print, (FileSP)); LLDB_REGISTER_METHOD(bool, SBInstructionList, GetDescription, (lldb::SBStream &)); LLDB_REGISTER_METHOD(bool, SBInstructionList, diff --git a/source/API/SBLineEntry.cpp b/source/API/SBLineEntry.cpp index 010a6057cd31..66884f763398 100644 --- a/source/API/SBLineEntry.cpp +++ b/source/API/SBLineEntry.cpp @@ -32,7 +32,7 @@ SBLineEntry::SBLineEntry(const SBLineEntry &rhs) : m_opaque_up() { SBLineEntry::SBLineEntry(const lldb_private::LineEntry *lldb_object_ptr) : m_opaque_up() { if (lldb_object_ptr) - m_opaque_up = llvm::make_unique<LineEntry>(*lldb_object_ptr); + m_opaque_up = std::make_unique<LineEntry>(*lldb_object_ptr); } const SBLineEntry &SBLineEntry::operator=(const SBLineEntry &rhs) { @@ -45,7 +45,7 @@ const SBLineEntry &SBLineEntry::operator=(const SBLineEntry &rhs) { } void SBLineEntry::SetLineEntry(const lldb_private::LineEntry &lldb_object_ref) { - m_opaque_up = llvm::make_unique<LineEntry>(lldb_object_ref); + m_opaque_up = std::make_unique<LineEntry>(lldb_object_ref); } SBLineEntry::~SBLineEntry() {} diff --git a/source/API/SBModule.cpp b/source/API/SBModule.cpp index 4bd32bce1c53..6cc6d2628ace 100644 --- a/source/API/SBModule.cpp +++ b/source/API/SBModule.cpp @@ -20,7 +20,6 @@ #include "lldb/Core/ValueObjectVariable.h" #include "lldb/Symbol/ObjectFile.h" #include "lldb/Symbol/SymbolFile.h" -#include "lldb/Symbol/SymbolVendor.h" #include "lldb/Symbol/Symtab.h" #include "lldb/Symbol/TypeSystem.h" #include "lldb/Symbol/VariableList.h" @@ -283,18 +282,14 @@ SBSymbolContextList SBModule::FindCompileUnits(const SBFileSpec &sb_file_spec) { SBSymbolContextList sb_sc_list; const ModuleSP module_sp(GetSP()); if (sb_file_spec.IsValid() && module_sp) { - const bool append = true; - module_sp->FindCompileUnits(*sb_file_spec, append, *sb_sc_list); + module_sp->FindCompileUnits(*sb_file_spec, *sb_sc_list); } return LLDB_RECORD_RESULT(sb_sc_list); } static Symtab *GetUnifiedSymbolTable(const lldb::ModuleSP &module_sp) { - if (module_sp) { - SymbolVendor *symbols = module_sp->GetSymbolVendor(); - if (symbols) - return symbols->GetSymtab(); - } + if (module_sp) + return module_sp->GetSymtab(); return nullptr; } @@ -302,11 +297,8 @@ size_t SBModule::GetNumSymbols() { LLDB_RECORD_METHOD_NO_ARGS(size_t, SBModule, GetNumSymbols); ModuleSP module_sp(GetSP()); - if (module_sp) { - Symtab *symtab = GetUnifiedSymbolTable(module_sp); - if (symtab) - return symtab->GetNumSymbols(); - } + if (Symtab *symtab = GetUnifiedSymbolTable(module_sp)) + return symtab->GetNumSymbols(); return 0; } @@ -349,8 +341,9 @@ lldb::SBSymbolContextList SBModule::FindSymbols(const char *name, Symtab *symtab = GetUnifiedSymbolTable(module_sp); if (symtab) { std::vector<uint32_t> matching_symbol_indexes; - const size_t num_matches = symtab->FindAllSymbolsWithNameAndType( - ConstString(name), symbol_type, matching_symbol_indexes); + symtab->FindAllSymbolsWithNameAndType(ConstString(name), symbol_type, + matching_symbol_indexes); + const size_t num_matches = matching_symbol_indexes.size(); if (num_matches) { SymbolContext sc; sc.module_sp = module_sp; @@ -372,7 +365,7 @@ size_t SBModule::GetNumSections() { ModuleSP module_sp(GetSP()); if (module_sp) { // Give the symbol vendor a chance to add to the unified section list. - module_sp->GetSymbolVendor(); + module_sp->GetSymbolFile(); SectionList *section_list = module_sp->GetSectionList(); if (section_list) return section_list->GetSize(); @@ -388,7 +381,7 @@ SBSection SBModule::GetSectionAtIndex(size_t idx) { ModuleSP module_sp(GetSP()); if (module_sp) { // Give the symbol vendor a chance to add to the unified section list. - module_sp->GetSymbolVendor(); + module_sp->GetSymbolFile(); SectionList *section_list = module_sp->GetSectionList(); if (section_list) @@ -405,12 +398,11 @@ lldb::SBSymbolContextList SBModule::FindFunctions(const char *name, lldb::SBSymbolContextList sb_sc_list; ModuleSP module_sp(GetSP()); if (name && module_sp) { - const bool append = true; const bool symbols_ok = true; const bool inlines_ok = true; FunctionNameType type = static_cast<FunctionNameType>(name_type_mask); module_sp->FindFunctions(ConstString(name), nullptr, type, symbols_ok, - inlines_ok, append, *sb_sc_list); + inlines_ok, *sb_sc_list); } return LLDB_RECORD_RESULT(sb_sc_list); } @@ -425,9 +417,9 @@ SBValueList SBModule::FindGlobalVariables(SBTarget &target, const char *name, ModuleSP module_sp(GetSP()); if (name && module_sp) { VariableList variable_list; - const uint32_t match_count = module_sp->FindGlobalVariables( - ConstString(name), nullptr, max_matches, variable_list); - + module_sp->FindGlobalVariables(ConstString(name), nullptr, max_matches, + variable_list); + const uint32_t match_count = variable_list.GetSize(); if (match_count > 0) { for (uint32_t i = 0; i < match_count; ++i) { lldb::ValueObjectSP valobj_sp; @@ -468,10 +460,13 @@ lldb::SBType SBModule::FindFirstType(const char *name_cstr) { sb_type = SBType(module_sp->FindFirstType(sc, name, exact_match)); if (!sb_type.IsValid()) { - TypeSystem *type_system = + auto type_system_or_err = module_sp->GetTypeSystemForLanguage(eLanguageTypeC); - if (type_system) - sb_type = SBType(type_system->GetBuiltinTypeByName(name)); + if (auto err = type_system_or_err.takeError()) { + llvm::consumeError(std::move(err)); + return LLDB_RECORD_RESULT(SBType()); + } + sb_type = SBType(type_system_or_err->GetBuiltinTypeByName(name)); } } return LLDB_RECORD_RESULT(sb_type); @@ -483,10 +478,14 @@ lldb::SBType SBModule::GetBasicType(lldb::BasicType type) { ModuleSP module_sp(GetSP()); if (module_sp) { - TypeSystem *type_system = + auto type_system_or_err = module_sp->GetTypeSystemForLanguage(eLanguageTypeC); - if (type_system) - return LLDB_RECORD_RESULT(SBType(type_system->GetBasicTypeFromAST(type))); + if (auto err = type_system_or_err.takeError()) { + llvm::consumeError(std::move(err)); + } else { + return LLDB_RECORD_RESULT( + SBType(type_system_or_err->GetBasicTypeFromAST(type))); + } } return LLDB_RECORD_RESULT(SBType()); } @@ -503,26 +502,28 @@ lldb::SBTypeList SBModule::FindTypes(const char *type) { const bool exact_match = false; ConstString name(type); llvm::DenseSet<SymbolFile *> searched_symbol_files; - const uint32_t num_matches = module_sp->FindTypes( - name, exact_match, UINT32_MAX, searched_symbol_files, type_list); + module_sp->FindTypes(name, exact_match, UINT32_MAX, searched_symbol_files, + type_list); - if (num_matches > 0) { - for (size_t idx = 0; idx < num_matches; idx++) { - TypeSP type_sp(type_list.GetTypeAtIndex(idx)); - if (type_sp) - retval.Append(SBType(type_sp)); - } - } else { - TypeSystem *type_system = + if (type_list.Empty()) { + auto type_system_or_err = module_sp->GetTypeSystemForLanguage(eLanguageTypeC); - if (type_system) { - CompilerType compiler_type = type_system->GetBuiltinTypeByName(name); + if (auto err = type_system_or_err.takeError()) { + llvm::consumeError(std::move(err)); + } else { + CompilerType compiler_type = + type_system_or_err->GetBuiltinTypeByName(name); if (compiler_type) retval.Append(SBType(compiler_type)); } + } else { + for (size_t idx = 0; idx < type_list.GetSize(); idx++) { + TypeSP type_sp(type_list.GetTypeAtIndex(idx)); + if (type_sp) + retval.Append(SBType(type_sp)); + } } } - return LLDB_RECORD_RESULT(retval); } @@ -532,9 +533,8 @@ lldb::SBType SBModule::GetTypeByID(lldb::user_id_t uid) { ModuleSP module_sp(GetSP()); if (module_sp) { - SymbolVendor *vendor = module_sp->GetSymbolVendor(); - if (vendor) { - Type *type_ptr = vendor->ResolveTypeUID(uid); + if (SymbolFile *symfile = module_sp->GetSymbolFile()) { + Type *type_ptr = symfile->ResolveTypeUID(uid); if (type_ptr) return LLDB_RECORD_RESULT(SBType(type_ptr->shared_from_this())); } @@ -551,13 +551,13 @@ lldb::SBTypeList SBModule::GetTypes(uint32_t type_mask) { ModuleSP module_sp(GetSP()); if (!module_sp) return LLDB_RECORD_RESULT(sb_type_list); - SymbolVendor *vendor = module_sp->GetSymbolVendor(); - if (!vendor) + SymbolFile *symfile = module_sp->GetSymbolFile(); + if (!symfile) return LLDB_RECORD_RESULT(sb_type_list); TypeClass type_class = static_cast<TypeClass>(type_mask); TypeList type_list; - vendor->GetTypes(nullptr, type_class, type_list); + symfile->GetTypes(nullptr, type_class, type_list); sb_type_list.m_opaque_up->Append(type_list); return LLDB_RECORD_RESULT(sb_type_list); } @@ -571,7 +571,7 @@ SBSection SBModule::FindSection(const char *sect_name) { ModuleSP module_sp(GetSP()); if (sect_name && module_sp) { // Give the symbol vendor a chance to add to the unified section list. - module_sp->GetSymbolVendor(); + module_sp->GetSymbolFile(); SectionList *section_list = module_sp->GetSectionList(); if (section_list) { ConstString const_sect_name(sect_name); @@ -653,9 +653,8 @@ lldb::SBFileSpec SBModule::GetSymbolFileSpec() const { lldb::SBFileSpec sb_file_spec; ModuleSP module_sp(GetSP()); if (module_sp) { - SymbolVendor *symbol_vendor_ptr = module_sp->GetSymbolVendor(); - if (symbol_vendor_ptr) - sb_file_spec.SetFileSpec(symbol_vendor_ptr->GetMainFileSpec()); + if (SymbolFile *symfile = module_sp->GetSymbolFile()) + sb_file_spec.SetFileSpec(symfile->GetObjectFile()->GetFileSpec()); } return LLDB_RECORD_RESULT(sb_file_spec); } diff --git a/source/API/SBProcess.cpp b/source/API/SBProcess.cpp index 4226ff77ecdc..45aaa0bd2d8a 100644 --- a/source/API/SBProcess.cpp +++ b/source/API/SBProcess.cpp @@ -29,11 +29,11 @@ #include "lldb/Utility/State.h" #include "lldb/Utility/Stream.h" - #include "lldb/API/SBBroadcaster.h" #include "lldb/API/SBCommandReturnObject.h" #include "lldb/API/SBDebugger.h" #include "lldb/API/SBEvent.h" +#include "lldb/API/SBFile.h" #include "lldb/API/SBFileSpec.h" #include "lldb/API/SBMemoryRegionInfo.h" #include "lldb/API/SBMemoryRegionInfoList.h" @@ -331,23 +331,34 @@ lldb::SBTrace SBProcess::StartTrace(SBTraceOptions &options, return LLDB_RECORD_RESULT(trace_instance); } +void SBProcess::ReportEventState(const SBEvent &event, SBFile out) const { + LLDB_RECORD_METHOD_CONST(void, SBProcess, ReportEventState, + (const SBEvent &, SBFile), event, out); + + return ReportEventState(event, out.m_opaque_sp); +} + void SBProcess::ReportEventState(const SBEvent &event, FILE *out) const { LLDB_RECORD_METHOD_CONST(void, SBProcess, ReportEventState, (const lldb::SBEvent &, FILE *), event, out); + FileSP outfile = std::make_shared<NativeFile>(out, false); + return ReportEventState(event, outfile); +} + +void SBProcess::ReportEventState(const SBEvent &event, FileSP out) const { + + LLDB_RECORD_METHOD_CONST(void, SBProcess, ReportEventState, + (const SBEvent &, FileSP), event, out); - if (out == nullptr) + if (!out || !out->IsValid()) return; ProcessSP process_sp(GetSP()); if (process_sp) { + StreamFile stream(out); const StateType event_state = SBProcess::GetStateFromEvent(event); - char message[1024]; - int message_len = ::snprintf( - message, sizeof(message), "Process %" PRIu64 " %s\n", + stream.Printf("Process %" PRIu64 " %s\n", process_sp->GetID(), SBDebugger::StateAsCString(event_state)); - - if (message_len > 0) - ::fwrite(message, 1, message_len, out); } } @@ -1180,6 +1191,9 @@ bool SBProcess::IsInstrumentationRuntimePresent( if (!process_sp) return false; + std::lock_guard<std::recursive_mutex> guard( + process_sp->GetTarget().GetAPIMutex()); + InstrumentationRuntimeSP runtime_sp = process_sp->GetInstrumentationRuntime(type); @@ -1307,6 +1321,10 @@ void RegisterMethods<SBProcess>(Registry &R) { (lldb::SBTraceOptions &, lldb::SBError &)); LLDB_REGISTER_METHOD_CONST(void, SBProcess, ReportEventState, (const lldb::SBEvent &, FILE *)); + LLDB_REGISTER_METHOD_CONST(void, SBProcess, ReportEventState, + (const lldb::SBEvent &, FileSP)); + LLDB_REGISTER_METHOD_CONST(void, SBProcess, ReportEventState, + (const lldb::SBEvent &, SBFile)); LLDB_REGISTER_METHOD( void, SBProcess, AppendEventStateReport, (const lldb::SBEvent &, lldb::SBCommandReturnObject &)); diff --git a/source/API/SBReproducer.cpp b/source/API/SBReproducer.cpp index 439ee5a70460..6e11b2c6366f 100644 --- a/source/API/SBReproducer.cpp +++ b/source/API/SBReproducer.cpp @@ -52,6 +52,7 @@ SBRegistry::SBRegistry() { RegisterMethods<SBEvent>(R); RegisterMethods<SBExecutionContext>(R); RegisterMethods<SBExpressionOptions>(R); + RegisterMethods<SBFile>(R); RegisterMethods<SBFileSpec>(R); RegisterMethods<SBFileSpecList>(R); RegisterMethods<SBFrame>(R); diff --git a/source/API/SBReproducerPrivate.h b/source/API/SBReproducerPrivate.h index 84b6ce967c0b..edd06941398f 100644 --- a/source/API/SBReproducerPrivate.h +++ b/source/API/SBReproducerPrivate.h @@ -40,7 +40,7 @@ public: SBProvider(const FileSpec &directory) : Provider(directory), m_stream(directory.CopyByAppendingPathComponent("sbapi.bin").GetPath(), - m_ec, llvm::sys::fs::OpenFlags::F_None), + m_ec, llvm::sys::fs::OpenFlags::OF_None), m_serializer(m_stream) {} Serializer &GetSerializer() { return m_serializer; } diff --git a/source/API/SBStream.cpp b/source/API/SBStream.cpp index ae652338e1ea..d57634d2947c 100644 --- a/source/API/SBStream.cpp +++ b/source/API/SBStream.cpp @@ -9,6 +9,7 @@ #include "lldb/API/SBStream.h" #include "SBReproducerPrivate.h" +#include "lldb/API/SBFile.h" #include "lldb/Core/StreamFile.h" #include "lldb/Host/FileSystem.h" #include "lldb/Utility/Status.h" @@ -82,33 +83,45 @@ void SBStream::RedirectToFile(const char *path, bool append) { if (!m_is_file) local_data = static_cast<StreamString *>(m_opaque_up.get())->GetString(); } - StreamFile *stream_file = new StreamFile; - uint32_t open_options = File::eOpenOptionWrite | File::eOpenOptionCanCreate; + auto open_options = File::eOpenOptionWrite | File::eOpenOptionCanCreate; if (append) open_options |= File::eOpenOptionAppend; else open_options |= File::eOpenOptionTruncate; - FileSystem::Instance().Open(stream_file->GetFile(), FileSpec(path), - open_options); - m_opaque_up.reset(stream_file); + llvm::Expected<FileUP> file = + FileSystem::Instance().Open(FileSpec(path), open_options); + if (!file) { + LLDB_LOG_ERROR(GetLogIfAllCategoriesSet(LIBLLDB_LOG_API), file.takeError(), + "Cannot open {1}: {0}", path); + return; + } - if (m_opaque_up) { - m_is_file = true; + m_opaque_up = std::make_unique<StreamFile>(std::move(file.get())); + m_is_file = true; - // If we had any data locally in our StreamString, then pass that along to - // the to new file we are redirecting to. - if (!local_data.empty()) - m_opaque_up->Write(&local_data[0], local_data.size()); - } else - m_is_file = false; + // If we had any data locally in our StreamString, then pass that along to + // the to new file we are redirecting to. + if (!local_data.empty()) + m_opaque_up->Write(&local_data[0], local_data.size()); } void SBStream::RedirectToFileHandle(FILE *fh, bool transfer_fh_ownership) { LLDB_RECORD_METHOD(void, SBStream, RedirectToFileHandle, (FILE *, bool), fh, transfer_fh_ownership); + FileSP file = std::make_unique<NativeFile>(fh, transfer_fh_ownership); + return RedirectToFile(file); +} - if (fh == nullptr) +void SBStream::RedirectToFile(SBFile file) { + LLDB_RECORD_METHOD(void, SBStream, RedirectToFile, (SBFile), file) + RedirectToFile(file.GetFile()); +} + +void SBStream::RedirectToFile(FileSP file_sp) { + LLDB_RECORD_METHOD(void, SBStream, RedirectToFile, (FileSP), file_sp); + + if (!file_sp || !file_sp->IsValid()) return; std::string local_data; @@ -118,17 +131,14 @@ void SBStream::RedirectToFileHandle(FILE *fh, bool transfer_fh_ownership) { if (!m_is_file) local_data = static_cast<StreamString *>(m_opaque_up.get())->GetString(); } - m_opaque_up.reset(new StreamFile(fh, transfer_fh_ownership)); - if (m_opaque_up) { - m_is_file = true; + m_opaque_up = std::make_unique<StreamFile>(file_sp); + m_is_file = true; - // If we had any data locally in our StreamString, then pass that along to - // the to new file we are redirecting to. - if (!local_data.empty()) - m_opaque_up->Write(&local_data[0], local_data.size()); - } else - m_is_file = false; + // If we had any data locally in our StreamString, then pass that along to + // the to new file we are redirecting to. + if (!local_data.empty()) + m_opaque_up->Write(&local_data[0], local_data.size()); } void SBStream::RedirectToFileDescriptor(int fd, bool transfer_fh_ownership) { @@ -143,16 +153,13 @@ void SBStream::RedirectToFileDescriptor(int fd, bool transfer_fh_ownership) { local_data = static_cast<StreamString *>(m_opaque_up.get())->GetString(); } - m_opaque_up.reset(new StreamFile(::fdopen(fd, "w"), transfer_fh_ownership)); - if (m_opaque_up) { - m_is_file = true; + m_opaque_up = std::make_unique<StreamFile>(fd, transfer_fh_ownership); + m_is_file = true; - // If we had any data locally in our StreamString, then pass that along to - // the to new file we are redirecting to. - if (!local_data.empty()) - m_opaque_up->Write(&local_data[0], local_data.size()); - } else - m_is_file = false; + // If we had any data locally in our StreamString, then pass that along to + // the to new file we are redirecting to. + if (!local_data.empty()) + m_opaque_up->Write(&local_data[0], local_data.size()); } lldb_private::Stream *SBStream::operator->() { return m_opaque_up.get(); } @@ -189,6 +196,8 @@ void RegisterMethods<SBStream>(Registry &R) { LLDB_REGISTER_METHOD(const char *, SBStream, GetData, ()); LLDB_REGISTER_METHOD(size_t, SBStream, GetSize, ()); LLDB_REGISTER_METHOD(void, SBStream, RedirectToFile, (const char *, bool)); + LLDB_REGISTER_METHOD(void, SBStream, RedirectToFile, (FileSP)); + LLDB_REGISTER_METHOD(void, SBStream, RedirectToFile, (SBFile)); LLDB_REGISTER_METHOD(void, SBStream, RedirectToFileHandle, (FILE *, bool)); LLDB_REGISTER_METHOD(void, SBStream, RedirectToFileDescriptor, (int, bool)); LLDB_REGISTER_METHOD(void, SBStream, Clear, ()); diff --git a/source/API/SBStringList.cpp b/source/API/SBStringList.cpp index 2f8bd55855a1..ac07b8faac4d 100644 --- a/source/API/SBStringList.cpp +++ b/source/API/SBStringList.cpp @@ -21,7 +21,7 @@ SBStringList::SBStringList() : m_opaque_up() { SBStringList::SBStringList(const lldb_private::StringList *lldb_strings_ptr) : m_opaque_up() { if (lldb_strings_ptr) - m_opaque_up = llvm::make_unique<StringList>(*lldb_strings_ptr); + m_opaque_up = std::make_unique<StringList>(*lldb_strings_ptr); } SBStringList::SBStringList(const SBStringList &rhs) : m_opaque_up() { diff --git a/source/API/SBSymbolContext.cpp b/source/API/SBSymbolContext.cpp index 365f0ccc2fbf..6e01e5535c32 100644 --- a/source/API/SBSymbolContext.cpp +++ b/source/API/SBSymbolContext.cpp @@ -27,7 +27,7 @@ SBSymbolContext::SBSymbolContext(const SymbolContext *sc_ptr) : m_opaque_up() { (const lldb_private::SymbolContext *), sc_ptr); if (sc_ptr) - m_opaque_up = llvm::make_unique<SymbolContext>(*sc_ptr); + m_opaque_up = std::make_unique<SymbolContext>(*sc_ptr); } SBSymbolContext::SBSymbolContext(const SBSymbolContext &rhs) : m_opaque_up() { @@ -51,7 +51,7 @@ const SBSymbolContext &SBSymbolContext::operator=(const SBSymbolContext &rhs) { void SBSymbolContext::SetSymbolContext(const SymbolContext *sc_ptr) { if (sc_ptr) - m_opaque_up = llvm::make_unique<SymbolContext>(*sc_ptr); + m_opaque_up = std::make_unique<SymbolContext>(*sc_ptr); else m_opaque_up->Clear(true); } diff --git a/source/API/SBTarget.cpp b/source/API/SBTarget.cpp index 5e87eb6273b3..1d13087eef69 100644 --- a/source/API/SBTarget.cpp +++ b/source/API/SBTarget.cpp @@ -44,11 +44,11 @@ #include "lldb/Core/ValueObjectList.h" #include "lldb/Core/ValueObjectVariable.h" #include "lldb/Host/Host.h" -#include "lldb/Symbol/ClangASTContext.h" #include "lldb/Symbol/DeclVendor.h" #include "lldb/Symbol/ObjectFile.h" #include "lldb/Symbol/SymbolFile.h" #include "lldb/Symbol/SymbolVendor.h" +#include "lldb/Symbol/TypeSystem.h" #include "lldb/Symbol/VariableList.h" #include "lldb/Target/ABI.h" #include "lldb/Target/Language.h" @@ -218,7 +218,7 @@ SBStructuredData SBTarget::GetStatistics() { if (!target_sp) return LLDB_RECORD_RESULT(data); - auto stats_up = llvm::make_unique<StructuredData::Dictionary>(); + auto stats_up = std::make_unique<StructuredData::Dictionary>(); int i = 0; for (auto &Entry : target_sp->GetStatistics()) { std::string Desc = lldb_private::GetStatDescription( @@ -960,8 +960,8 @@ lldb::SBBreakpoint SBTarget::BreakpointCreateByRegex( const LazyBool skip_prologue = eLazyBoolCalculate; sb_bp = target_sp->CreateFuncRegexBreakpoint( - module_list.get(), comp_unit_list.get(), regexp, symbol_language, - skip_prologue, internal, hardware); + module_list.get(), comp_unit_list.get(), std::move(regexp), + symbol_language, skip_prologue, internal, hardware); } return LLDB_RECORD_RESULT(sb_bp); @@ -1061,8 +1061,8 @@ lldb::SBBreakpoint SBTarget::BreakpointCreateBySourceRegex( } sb_bp = target_sp->CreateSourceRegexBreakpoint( - module_list.get(), source_file_list.get(), func_names_set, regexp, - false, hardware, move_to_nearest_code); + module_list.get(), source_file_list.get(), func_names_set, + std::move(regexp), false, hardware, move_to_nearest_code); } return LLDB_RECORD_RESULT(sb_bp); @@ -1653,11 +1653,8 @@ SBSymbolContextList SBTarget::FindCompileUnits(const SBFileSpec &sb_file_spec) { SBSymbolContextList sb_sc_list; const TargetSP target_sp(GetSP()); - if (target_sp && sb_file_spec.IsValid()) { - const bool append = true; - target_sp->GetImages().FindCompileUnits(*sb_file_spec, - append, *sb_sc_list); - } + if (target_sp && sb_file_spec.IsValid()) + target_sp->GetImages().FindCompileUnits(*sb_file_spec, *sb_sc_list); return LLDB_RECORD_RESULT(sb_sc_list); } @@ -1783,10 +1780,9 @@ lldb::SBSymbolContextList SBTarget::FindFunctions(const char *name, const bool symbols_ok = true; const bool inlines_ok = true; - const bool append = true; FunctionNameType mask = static_cast<FunctionNameType>(name_type_mask); target_sp->GetImages().FindFunctions(ConstString(name), mask, symbols_ok, - inlines_ok, append, *sb_sc_list); + inlines_ok, *sb_sc_list); return LLDB_RECORD_RESULT(sb_sc_list); } @@ -1806,17 +1802,16 @@ lldb::SBSymbolContextList SBTarget::FindGlobalFunctions(const char *name, switch (matchtype) { case eMatchTypeRegex: target_sp->GetImages().FindFunctions(RegularExpression(name_ref), true, - true, true, *sb_sc_list); + true, *sb_sc_list); break; case eMatchTypeStartsWith: regexstr = llvm::Regex::escape(name) + ".*"; target_sp->GetImages().FindFunctions(RegularExpression(regexstr), true, - true, true, *sb_sc_list); + true, *sb_sc_list); break; default: - target_sp->GetImages().FindFunctions(ConstString(name), - eFunctionNameTypeAny, true, true, - true, *sb_sc_list); + target_sp->GetImages().FindFunctions( + ConstString(name), eFunctionNameTypeAny, true, true, *sb_sc_list); break; } } @@ -1858,11 +1853,11 @@ lldb::SBType SBTarget::FindFirstType(const char *typename_cstr) { } // No matches, search for basic typename matches - ClangASTContext *clang_ast = target_sp->GetScratchClangASTContext(); - if (clang_ast) - return LLDB_RECORD_RESULT(SBType(ClangASTContext::GetBasicType( - clang_ast->getASTContext(), const_typename))); + for (auto *type_system : target_sp->GetScratchTypeSystems()) + if (auto type = type_system->GetBuiltinTypeByName(const_typename)) + return LLDB_RECORD_RESULT(SBType(type)); } + return LLDB_RECORD_RESULT(SBType()); } @@ -1872,10 +1867,9 @@ SBType SBTarget::GetBasicType(lldb::BasicType type) { TargetSP target_sp(GetSP()); if (target_sp) { - ClangASTContext *clang_ast = target_sp->GetScratchClangASTContext(); - if (clang_ast) - return LLDB_RECORD_RESULT(SBType( - ClangASTContext::GetBasicType(clang_ast->getASTContext(), type))); + for (auto *type_system : target_sp->GetScratchTypeSystems()) + if (auto compiler_type = type_system->GetBasicTypeFromAST(type)) + return LLDB_RECORD_RESULT(SBType(compiler_type)); } return LLDB_RECORD_RESULT(SBType()); } @@ -1892,16 +1886,13 @@ lldb::SBTypeList SBTarget::FindTypes(const char *typename_cstr) { bool exact_match = false; TypeList type_list; llvm::DenseSet<SymbolFile *> searched_symbol_files; - uint32_t num_matches = - images.FindTypes(nullptr, const_typename, exact_match, UINT32_MAX, - searched_symbol_files, type_list); + images.FindTypes(nullptr, const_typename, exact_match, UINT32_MAX, + searched_symbol_files, type_list); - if (num_matches > 0) { - for (size_t idx = 0; idx < num_matches; idx++) { - TypeSP type_sp(type_list.GetTypeAtIndex(idx)); - if (type_sp) - sb_type_list.Append(SBType(type_sp)); - } + for (size_t idx = 0; idx < type_list.GetSize(); idx++) { + TypeSP type_sp(type_list.GetTypeAtIndex(idx)); + if (type_sp) + sb_type_list.Append(SBType(type_sp)); } // Try the loaded language runtimes @@ -1918,10 +1909,10 @@ lldb::SBTypeList SBTarget::FindTypes(const char *typename_cstr) { if (sb_type_list.GetSize() == 0) { // No matches, search for basic typename matches - ClangASTContext *clang_ast = target_sp->GetScratchClangASTContext(); - if (clang_ast) - sb_type_list.Append(SBType(ClangASTContext::GetBasicType( - clang_ast->getASTContext(), const_typename))); + for (auto *type_system : target_sp->GetScratchTypeSystems()) + if (auto compiler_type = + type_system->GetBuiltinTypeByName(const_typename)) + sb_type_list.Append(SBType(compiler_type)); } } return LLDB_RECORD_RESULT(sb_type_list); @@ -1937,9 +1928,9 @@ SBValueList SBTarget::FindGlobalVariables(const char *name, TargetSP target_sp(GetSP()); if (name && target_sp) { VariableList variable_list; - const uint32_t match_count = target_sp->GetImages().FindGlobalVariables( - ConstString(name), max_matches, variable_list); - + target_sp->GetImages().FindGlobalVariables(ConstString(name), max_matches, + variable_list); + const uint32_t match_count = variable_list.GetSize(); if (match_count > 0) { ExecutionContextScope *exe_scope = target_sp->GetProcessSP().get(); if (exe_scope == nullptr) @@ -1974,20 +1965,20 @@ SBValueList SBTarget::FindGlobalVariables(const char *name, uint32_t match_count; switch (matchtype) { case eMatchTypeNormal: - match_count = target_sp->GetImages().FindGlobalVariables( - ConstString(name), max_matches, variable_list); + target_sp->GetImages().FindGlobalVariables(ConstString(name), max_matches, + variable_list); break; case eMatchTypeRegex: - match_count = target_sp->GetImages().FindGlobalVariables( - RegularExpression(name_ref), max_matches, variable_list); + target_sp->GetImages().FindGlobalVariables(RegularExpression(name_ref), + max_matches, variable_list); break; case eMatchTypeStartsWith: regexstr = llvm::Regex::escape(name) + ".*"; - match_count = target_sp->GetImages().FindGlobalVariables( - RegularExpression(regexstr), max_matches, variable_list); + target_sp->GetImages().FindGlobalVariables(RegularExpression(regexstr), + max_matches, variable_list); break; } - + match_count = variable_list.GetSize(); if (match_count > 0) { ExecutionContextScope *exe_scope = target_sp->GetProcessSP().get(); if (exe_scope == nullptr) @@ -2291,11 +2282,9 @@ lldb::SBSymbolContextList SBTarget::FindSymbols(const char *name, SBSymbolContextList sb_sc_list; if (name && name[0]) { TargetSP target_sp(GetSP()); - if (target_sp) { - bool append = true; + if (target_sp) target_sp->GetImages().FindSymbolsWithNameAndType( - ConstString(name), symbol_type, *sb_sc_list, append); - } + ConstString(name), symbol_type, *sb_sc_list); } return LLDB_RECORD_RESULT(sb_sc_list); } @@ -2355,10 +2344,10 @@ lldb::SBValue SBTarget::EvaluateExpression(const char *expr, expr_result.SetSP(expr_value_sp, options.GetFetchDynamicValue()); } } - if (expr_log) - expr_log->Printf("** [SBTarget::EvaluateExpression] Expression result is " - "%s, summary %s **", - expr_result.GetValue(), expr_result.GetSummary()); + LLDB_LOGF(expr_log, + "** [SBTarget::EvaluateExpression] Expression result is " + "%s, summary %s **", + expr_result.GetValue(), expr_result.GetSummary()); return LLDB_RECORD_RESULT(expr_result); } diff --git a/source/API/SBThread.cpp b/source/API/SBThread.cpp index 85e9a6b47955..8d4930bf6edb 100644 --- a/source/API/SBThread.cpp +++ b/source/API/SBThread.cpp @@ -16,6 +16,7 @@ #include "lldb/API/SBFrame.h" #include "lldb/API/SBProcess.h" #include "lldb/API/SBStream.h" +#include "lldb/API/SBStructuredData.h" #include "lldb/API/SBSymbolContext.h" #include "lldb/API/SBThreadCollection.h" #include "lldb/API/SBThreadPlan.h" @@ -23,6 +24,7 @@ #include "lldb/Breakpoint/BreakpointLocation.h" #include "lldb/Core/Debugger.h" #include "lldb/Core/StreamFile.h" +#include "lldb/Core/StructuredDataImpl.h" #include "lldb/Core/ValueObject.h" #include "lldb/Interpreter/CommandInterpreter.h" #include "lldb/Symbol/CompileUnit.h" @@ -965,9 +967,24 @@ SBError SBThread::StepUsingScriptedThreadPlan(const char *script_class_name) { } SBError SBThread::StepUsingScriptedThreadPlan(const char *script_class_name, + bool resume_immediately) { + LLDB_RECORD_METHOD(lldb::SBError, SBThread, StepUsingScriptedThreadPlan, + (const char *, bool), script_class_name, + resume_immediately); + + lldb::SBStructuredData no_data; + return LLDB_RECORD_RESULT( + StepUsingScriptedThreadPlan(script_class_name, + no_data, + resume_immediately)); +} + +SBError SBThread::StepUsingScriptedThreadPlan(const char *script_class_name, + SBStructuredData &args_data, bool resume_immediately) { LLDB_RECORD_METHOD(lldb::SBError, SBThread, StepUsingScriptedThreadPlan, - (const char *, bool), script_class_name, + (const char *, lldb::SBStructuredData &, bool), + script_class_name, args_data, resume_immediately); SBError error; @@ -982,8 +999,10 @@ SBError SBThread::StepUsingScriptedThreadPlan(const char *script_class_name, Thread *thread = exe_ctx.GetThreadPtr(); Status new_plan_status; + StructuredData::ObjectSP obj_sp = args_data.m_impl_up->GetObjectSP(); + ThreadPlanSP new_plan_sp = thread->QueueThreadPlanForStepScripted( - false, script_class_name, false, new_plan_status); + false, script_class_name, obj_sp, false, new_plan_status); if (new_plan_status.Fail()) { error.SetErrorString(new_plan_status.AsCString()); @@ -1460,6 +1479,8 @@ void RegisterMethods<SBThread>(Registry &R) { (const char *)); LLDB_REGISTER_METHOD(lldb::SBError, SBThread, StepUsingScriptedThreadPlan, (const char *, bool)); + LLDB_REGISTER_METHOD(lldb::SBError, SBThread, StepUsingScriptedThreadPlan, + (const char *, SBStructuredData &, bool)); LLDB_REGISTER_METHOD(lldb::SBError, SBThread, JumpToLine, (lldb::SBFileSpec &, uint32_t)); LLDB_REGISTER_METHOD(lldb::SBError, SBThread, ReturnFromFrame, diff --git a/source/API/SBThreadPlan.cpp b/source/API/SBThreadPlan.cpp index 8f6802fe9cef..eed4d1bfb9c4 100644 --- a/source/API/SBThreadPlan.cpp +++ b/source/API/SBThreadPlan.cpp @@ -11,10 +11,12 @@ #include "lldb/API/SBFileSpec.h" #include "lldb/API/SBStream.h" +#include "lldb/API/SBStructuredData.h" #include "lldb/API/SBSymbolContext.h" #include "lldb/Breakpoint/BreakpointLocation.h" #include "lldb/Core/Debugger.h" #include "lldb/Core/StreamFile.h" +#include "lldb/Core/StructuredDataImpl.h" #include "lldb/Interpreter/CommandInterpreter.h" #include "lldb/Symbol/CompileUnit.h" #include "lldb/Symbol/SymbolContext.h" @@ -67,7 +69,20 @@ SBThreadPlan::SBThreadPlan(lldb::SBThread &sb_thread, const char *class_name) { Thread *thread = sb_thread.get(); if (thread) - m_opaque_sp = std::make_shared<ThreadPlanPython>(*thread, class_name); + m_opaque_sp = std::make_shared<ThreadPlanPython>(*thread, class_name, + nullptr); +} + +SBThreadPlan::SBThreadPlan(lldb::SBThread &sb_thread, const char *class_name, + lldb::SBStructuredData &args_data) { + LLDB_RECORD_CONSTRUCTOR(SBThreadPlan, (lldb::SBThread &, const char *, + SBStructuredData &), + sb_thread, class_name, args_data); + + Thread *thread = sb_thread.get(); + if (thread) + m_opaque_sp = std::make_shared<ThreadPlanPython>(*thread, class_name, + args_data.m_impl_up.get()); } // Assignment operator @@ -368,9 +383,35 @@ SBThreadPlan::QueueThreadPlanForStepScripted(const char *script_class_name, if (m_opaque_sp) { Status plan_status; + StructuredData::ObjectSP empty_args; SBThreadPlan plan = SBThreadPlan(m_opaque_sp->GetThread().QueueThreadPlanForStepScripted( - false, script_class_name, false, plan_status)); + false, script_class_name, empty_args, false, plan_status)); + + if (plan_status.Fail()) + error.SetErrorString(plan_status.AsCString()); + + return LLDB_RECORD_RESULT(plan); + } else { + return LLDB_RECORD_RESULT(SBThreadPlan()); + } +} + +SBThreadPlan +SBThreadPlan::QueueThreadPlanForStepScripted(const char *script_class_name, + lldb::SBStructuredData &args_data, + SBError &error) { + LLDB_RECORD_METHOD(lldb::SBThreadPlan, SBThreadPlan, + QueueThreadPlanForStepScripted, + (const char *, lldb::SBStructuredData &, lldb::SBError &), + script_class_name, args_data, error); + + if (m_opaque_sp) { + Status plan_status; + StructuredData::ObjectSP args_obj = args_data.m_impl_up->GetObjectSP(); + SBThreadPlan plan = + SBThreadPlan(m_opaque_sp->GetThread().QueueThreadPlanForStepScripted( + false, script_class_name, args_obj, false, plan_status)); if (plan_status.Fail()) error.SetErrorString(plan_status.AsCString()); @@ -390,6 +431,8 @@ void RegisterMethods<SBThreadPlan>(Registry &R) { LLDB_REGISTER_CONSTRUCTOR(SBThreadPlan, (const lldb::ThreadPlanSP &)); LLDB_REGISTER_CONSTRUCTOR(SBThreadPlan, (const lldb::SBThreadPlan &)); LLDB_REGISTER_CONSTRUCTOR(SBThreadPlan, (lldb::SBThread &, const char *)); + LLDB_REGISTER_CONSTRUCTOR(SBThreadPlan, (lldb::SBThread &, const char *, + lldb::SBStructuredData &)); LLDB_REGISTER_METHOD(const lldb::SBThreadPlan &, SBThreadPlan, operator=,(const lldb::SBThreadPlan &)); LLDB_REGISTER_METHOD_CONST(bool, SBThreadPlan, IsValid, ()); @@ -433,6 +476,10 @@ void RegisterMethods<SBThreadPlan>(Registry &R) { LLDB_REGISTER_METHOD(lldb::SBThreadPlan, SBThreadPlan, QueueThreadPlanForStepScripted, (const char *, lldb::SBError &)); + LLDB_REGISTER_METHOD(lldb::SBThreadPlan, SBThreadPlan, + QueueThreadPlanForStepScripted, + (const char *, lldb::SBStructuredData &, + lldb::SBError &)); } } diff --git a/source/API/SBType.cpp b/source/API/SBType.cpp index 5402128b3fae..8efc701a79fb 100644 --- a/source/API/SBType.cpp +++ b/source/API/SBType.cpp @@ -799,7 +799,7 @@ const char *SBTypeMemberFunction::GetDemangledName() { if (m_opaque_sp) { ConstString mangled_str = m_opaque_sp->GetMangledName(); if (mangled_str) { - Mangled mangled(mangled_str, true); + Mangled mangled(mangled_str); return mangled.GetDemangledName(mangled.GuessLanguage()).GetCString(); } } diff --git a/source/API/SBTypeCategory.cpp b/source/API/SBTypeCategory.cpp index 43d5a3ab140f..1e4496575098 100644 --- a/source/API/SBTypeCategory.cpp +++ b/source/API/SBTypeCategory.cpp @@ -364,8 +364,8 @@ bool SBTypeCategory::AddTypeFormat(SBTypeNameSpecifier type_name, if (type_name.IsRegex()) m_opaque_sp->GetRegexTypeFormatsContainer()->Add( - lldb::RegularExpressionSP(new RegularExpression( - llvm::StringRef::withNullAsEmpty(type_name.GetName()))), + RegularExpression( + llvm::StringRef::withNullAsEmpty(type_name.GetName())), format.GetSP()); else m_opaque_sp->GetTypeFormatsContainer()->Add( @@ -443,8 +443,8 @@ bool SBTypeCategory::AddTypeSummary(SBTypeNameSpecifier type_name, if (type_name.IsRegex()) m_opaque_sp->GetRegexTypeSummariesContainer()->Add( - lldb::RegularExpressionSP(new RegularExpression( - llvm::StringRef::withNullAsEmpty(type_name.GetName()))), + RegularExpression( + llvm::StringRef::withNullAsEmpty(type_name.GetName())), summary.GetSP()); else m_opaque_sp->GetTypeSummariesContainer()->Add( @@ -488,8 +488,8 @@ bool SBTypeCategory::AddTypeFilter(SBTypeNameSpecifier type_name, if (type_name.IsRegex()) m_opaque_sp->GetRegexTypeFiltersContainer()->Add( - lldb::RegularExpressionSP(new RegularExpression( - llvm::StringRef::withNullAsEmpty(type_name.GetName()))), + RegularExpression( + llvm::StringRef::withNullAsEmpty(type_name.GetName())), filter.GetSP()); else m_opaque_sp->GetTypeFiltersContainer()->Add( @@ -567,8 +567,8 @@ bool SBTypeCategory::AddTypeSynthetic(SBTypeNameSpecifier type_name, if (type_name.IsRegex()) m_opaque_sp->GetRegexTypeSyntheticsContainer()->Add( - lldb::RegularExpressionSP(new RegularExpression( - llvm::StringRef::withNullAsEmpty(type_name.GetName()))), + RegularExpression( + llvm::StringRef::withNullAsEmpty(type_name.GetName())), synth.GetSP()); else m_opaque_sp->GetTypeSyntheticsContainer()->Add( diff --git a/source/API/SystemInitializerFull.cpp b/source/API/SystemInitializerFull.cpp index e7f2206b9a59..0acc496ff879 100644 --- a/source/API/SystemInitializerFull.cpp +++ b/source/API/SystemInitializerFull.cpp @@ -24,6 +24,7 @@ #include "Plugins/ABI/MacOSX-arm/ABIMacOSX_arm.h" #include "Plugins/ABI/MacOSX-arm64/ABIMacOSX_arm64.h" #include "Plugins/ABI/MacOSX-i386/ABIMacOSX_i386.h" +#include "Plugins/ABI/SysV-arc/ABISysV_arc.h" #include "Plugins/ABI/SysV-arm/ABISysV_arm.h" #include "Plugins/ABI/SysV-arm64/ABISysV_arm64.h" #include "Plugins/ABI/SysV-hexagon/ABISysV_hexagon.h" @@ -131,6 +132,39 @@ SystemInitializerFull::SystemInitializerFull() {} SystemInitializerFull::~SystemInitializerFull() {} +#define LLDB_PROCESS_AArch64(op) \ + ABIMacOSX_arm64::op(); \ + ABISysV_arm64::op(); +#define LLDB_PROCESS_ARM(op) \ + ABIMacOSX_arm::op(); \ + ABISysV_arm::op(); +#define LLDB_PROCESS_ARC(op) \ + ABISysV_arc::op(); +#define LLDB_PROCESS_Hexagon(op) ABISysV_hexagon::op(); +#define LLDB_PROCESS_Mips(op) \ + ABISysV_mips::op(); \ + ABISysV_mips64::op(); +#define LLDB_PROCESS_PowerPC(op) \ + ABISysV_ppc::op(); \ + ABISysV_ppc64::op(); +#define LLDB_PROCESS_SystemZ(op) ABISysV_s390x::op(); +#define LLDB_PROCESS_X86(op) \ + ABIMacOSX_i386::op(); \ + ABISysV_i386::op(); \ + ABISysV_x86_64::op(); \ + ABIWindows_x86_64::op(); + +#define LLDB_PROCESS_AMDGPU(op) +#define LLDB_PROCESS_AVR(op) +#define LLDB_PROCESS_BPF(op) +#define LLDB_PROCESS_Lanai(op) +#define LLDB_PROCESS_MSP430(op) +#define LLDB_PROCESS_NVPTX(op) +#define LLDB_PROCESS_RISCV(op) +#define LLDB_PROCESS_Sparc(op) +#define LLDB_PROCESS_WebAssembly(op) +#define LLDB_PROCESS_XCore(op) + llvm::Error SystemInitializerFull::Initialize() { if (auto e = SystemInitializerCommon::Initialize()) return e; @@ -174,20 +208,8 @@ llvm::Error SystemInitializerFull::Initialize() { ClangASTContext::Initialize(); - ABIMacOSX_i386::Initialize(); - ABIMacOSX_arm::Initialize(); - ABIMacOSX_arm64::Initialize(); - ABISysV_arm::Initialize(); - ABISysV_arm64::Initialize(); - ABISysV_hexagon::Initialize(); - ABISysV_i386::Initialize(); - ABISysV_x86_64::Initialize(); - ABISysV_ppc::Initialize(); - ABISysV_ppc64::Initialize(); - ABISysV_mips::Initialize(); - ABISysV_mips64::Initialize(); - ABISysV_s390x::Initialize(); - ABIWindows_x86_64::Initialize(); +#define LLVM_TARGET(t) LLDB_PROCESS_ ## t(Initialize) +#include "llvm/Config/Targets.def" ArchitectureArm::Initialize(); ArchitectureMips::Initialize(); @@ -288,20 +310,9 @@ void SystemInitializerFull::Terminate() { ArchitectureMips::Terminate(); ArchitecturePPC64::Terminate(); - ABIMacOSX_i386::Terminate(); - ABIMacOSX_arm::Terminate(); - ABIMacOSX_arm64::Terminate(); - ABISysV_arm::Terminate(); - ABISysV_arm64::Terminate(); - ABISysV_hexagon::Terminate(); - ABISysV_i386::Terminate(); - ABISysV_x86_64::Terminate(); - ABISysV_ppc::Terminate(); - ABISysV_ppc64::Terminate(); - ABISysV_mips::Terminate(); - ABISysV_mips64::Terminate(); - ABISysV_s390x::Terminate(); - ABIWindows_x86_64::Terminate(); +#define LLVM_TARGET(t) LLDB_PROCESS_ ## t(Terminate) +#include "llvm/Config/Targets.def" + DisassemblerLLVMC::Terminate(); JITLoaderGDB::Terminate(); diff --git a/source/API/Utils.h b/source/API/Utils.h index b1975e5421dd..ed81534d2d12 100644 --- a/source/API/Utils.h +++ b/source/API/Utils.h @@ -16,7 +16,7 @@ namespace lldb_private { template <typename T> std::unique_ptr<T> clone(const std::unique_ptr<T> &src) { if (src) - return llvm::make_unique<T>(*src); + return std::make_unique<T>(*src); return nullptr; } diff --git a/source/Breakpoint/Breakpoint.cpp b/source/Breakpoint/Breakpoint.cpp index 3c3841949b91..a112542803c4 100644 --- a/source/Breakpoint/Breakpoint.cpp +++ b/source/Breakpoint/Breakpoint.cpp @@ -496,10 +496,10 @@ void Breakpoint::ClearAllBreakpointSites() { void Breakpoint::ModulesChanged(ModuleList &module_list, bool load, bool delete_locations) { Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_BREAKPOINTS)); - if (log) - log->Printf("Breakpoint::ModulesChanged: num_modules: %zu load: %i " - "delete_locations: %i\n", - module_list.GetSize(), load, delete_locations); + LLDB_LOGF(log, + "Breakpoint::ModulesChanged: num_modules: %zu load: %i " + "delete_locations: %i\n", + module_list.GetSize(), load, delete_locations); std::lock_guard<std::recursive_mutex> guard(module_list.GetMutex()); if (load) { @@ -550,10 +550,10 @@ void Breakpoint::ModulesChanged(ModuleList &module_list, bool load, seen = true; if (!break_loc_sp->ResolveBreakpointSite()) { - if (log) - log->Printf("Warning: could not set breakpoint site for " - "breakpoint location %d of breakpoint %d.\n", - break_loc_sp->GetID(), GetID()); + LLDB_LOGF(log, + "Warning: could not set breakpoint site for " + "breakpoint location %d of breakpoint %d.\n", + break_loc_sp->GetID(), GetID()); } } } @@ -659,9 +659,8 @@ static bool SymbolContextsMightBeEquivalent(SymbolContext &old_sc, void Breakpoint::ModuleReplaced(ModuleSP old_module_sp, ModuleSP new_module_sp) { Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_BREAKPOINTS)); - if (log) - log->Printf("Breakpoint::ModulesReplaced for %s\n", - old_module_sp->GetSpecificationDescription().c_str()); + LLDB_LOGF(log, "Breakpoint::ModulesReplaced for %s\n", + old_module_sp->GetSpecificationDescription().c_str()); // First find all the locations that are in the old module BreakpointLocationCollection old_break_locs; diff --git a/source/Breakpoint/BreakpointIDList.cpp b/source/Breakpoint/BreakpointIDList.cpp index 1e695fae6995..de68c44ec6a4 100644 --- a/source/Breakpoint/BreakpointIDList.cpp +++ b/source/Breakpoint/BreakpointIDList.cpp @@ -122,7 +122,7 @@ void BreakpointIDList::FindAndReplaceIDRanges(Args &old_args, Target *target, for (size_t i = 0; i < old_args.size(); ++i) { bool is_range = false; - current_arg = old_args[i].ref; + current_arg = old_args[i].ref(); if (!allow_locations && current_arg.contains('.')) { result.AppendErrorWithFormat( "Breakpoint locations not allowed, saw location: %s.", @@ -146,16 +146,16 @@ void BreakpointIDList::FindAndReplaceIDRanges(Args &old_args, Target *target, } else names_found.insert(current_arg); } else if ((i + 2 < old_args.size()) && - BreakpointID::IsRangeIdentifier(old_args[i + 1].ref) && + BreakpointID::IsRangeIdentifier(old_args[i + 1].ref()) && BreakpointID::IsValidIDExpression(current_arg) && - BreakpointID::IsValidIDExpression(old_args[i + 2].ref)) { + BreakpointID::IsValidIDExpression(old_args[i + 2].ref())) { range_from = current_arg; - range_to = old_args[i + 2].ref; + range_to = old_args[i + 2].ref(); is_range = true; i = i + 2; } else { // See if user has specified id.* - llvm::StringRef tmp_str = old_args[i].ref; + llvm::StringRef tmp_str = old_args[i].ref(); size_t pos = tmp_str.find('.'); if (pos != llvm::StringRef::npos) { llvm::StringRef bp_id_str = tmp_str.substr(0, pos); diff --git a/source/Breakpoint/BreakpointLocation.cpp b/source/Breakpoint/BreakpointLocation.cpp index b718e2aeea5c..46b8f25c5668 100644 --- a/source/Breakpoint/BreakpointLocation.cpp +++ b/source/Breakpoint/BreakpointLocation.cpp @@ -257,9 +257,8 @@ bool BreakpointLocation::ConditionSaysStop(ExecutionContext &exe_ctx, condition_text, llvm::StringRef(), language, Expression::eResultTypeAny, EvaluateExpressionOptions(), nullptr, error)); if (error.Fail()) { - if (log) - log->Printf("Error getting condition expression: %s.", - error.AsCString()); + LLDB_LOGF(log, "Error getting condition expression: %s.", + error.AsCString()); m_user_expression_sp.reset(); return true; } @@ -312,8 +311,8 @@ bool BreakpointLocation::ConditionSaysStop(ExecutionContext &exe_ctx, ret = result_value_sp->IsLogicalTrue(error); if (log) { if (error.Success()) { - log->Printf("Condition successfully evaluated, result is %s.\n", - ret ? "true" : "false"); + LLDB_LOGF(log, "Condition successfully evaluated, result is %s.\n", + ret ? "true" : "false"); } else { error.SetErrorString( "Failed to get an integer result from the expression"); @@ -408,8 +407,8 @@ bool BreakpointLocation::ShouldStop(StoppointCallbackContext *context) { if (log) { StreamString s; GetDescription(&s, lldb::eDescriptionLevelVerbose); - log->Printf("Hit breakpoint location: %s, %s.\n", s.GetData(), - should_stop ? "stopping" : "continuing"); + LLDB_LOGF(log, "Hit breakpoint location: %s, %s.\n", s.GetData(), + should_stop ? "stopping" : "continuing"); } return should_stop; diff --git a/source/Breakpoint/BreakpointOptions.cpp b/source/Breakpoint/BreakpointOptions.cpp index f6f279dc382a..0d4c6173c3c5 100644 --- a/source/Breakpoint/BreakpointOptions.cpp +++ b/source/Breakpoint/BreakpointOptions.cpp @@ -309,7 +309,7 @@ std::unique_ptr<BreakpointOptions> BreakpointOptions::CreateFromStructuredData( } } - auto bp_options = llvm::make_unique<BreakpointOptions>( + auto bp_options = std::make_unique<BreakpointOptions>( condition_ref.str().c_str(), enabled, ignore_count, one_shot, auto_continue); if (cmd_data_up) { diff --git a/source/Breakpoint/BreakpointResolver.cpp b/source/Breakpoint/BreakpointResolver.cpp index b3224aa91753..e0a4e6ac6712 100644 --- a/source/Breakpoint/BreakpointResolver.cpp +++ b/source/Breakpoint/BreakpointResolver.cpp @@ -34,7 +34,8 @@ using namespace lldb; // BreakpointResolver: const char *BreakpointResolver::g_ty_to_name[] = {"FileAndLine", "Address", "SymbolName", "SourceRegex", - "Exception", "Unknown"}; + "Python", "Exception", + "Unknown"}; const char *BreakpointResolver::g_option_names[static_cast<uint32_t>( BreakpointResolver::OptionNames::LastOptionName)] = { @@ -294,18 +295,18 @@ void BreakpointResolver::AddLocation(SearchFilter &filter, Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_BREAKPOINTS)); Address line_start = sc.line_entry.range.GetBaseAddress(); if (!line_start.IsValid()) { - if (log) - log->Printf("error: Unable to set breakpoint %s at file address " - "0x%" PRIx64 "\n", - log_ident.str().c_str(), line_start.GetFileAddress()); + LLDB_LOGF(log, + "error: Unable to set breakpoint %s at file address " + "0x%" PRIx64 "\n", + log_ident.str().c_str(), line_start.GetFileAddress()); return; } if (!filter.AddressPasses(line_start)) { - if (log) - log->Printf("Breakpoint %s at file address 0x%" PRIx64 - " didn't pass the filter.\n", - log_ident.str().c_str(), line_start.GetFileAddress()); + LLDB_LOGF(log, + "Breakpoint %s at file address 0x%" PRIx64 + " didn't pass the filter.\n", + log_ident.str().c_str(), line_start.GetFileAddress()); } // If the line number is before the prologue end, move it there... @@ -329,8 +330,8 @@ void BreakpointResolver::AddLocation(SearchFilter &filter, if (log && bp_loc_sp && !m_breakpoint->IsInternal()) { StreamString s; bp_loc_sp->GetDescription(&s, lldb::eDescriptionLevelVerbose); - log->Printf("Added location (skipped prologue: %s): %s \n", - skipped_prologue ? "yes" : "no", s.GetData()); + LLDB_LOGF(log, "Added location (skipped prologue: %s): %s \n", + skipped_prologue ? "yes" : "no", s.GetData()); } } diff --git a/source/Breakpoint/BreakpointResolverAddress.cpp b/source/Breakpoint/BreakpointResolverAddress.cpp index 8a6fd6a2692c..b98568098b4b 100644 --- a/source/Breakpoint/BreakpointResolverAddress.cpp +++ b/source/Breakpoint/BreakpointResolverAddress.cpp @@ -120,10 +120,8 @@ void BreakpointResolverAddress::ResolveBreakpointInModules( BreakpointResolver::ResolveBreakpointInModules(filter, modules); } -Searcher::CallbackReturn -BreakpointResolverAddress::SearchCallback(SearchFilter &filter, - SymbolContext &context, Address *addr, - bool containing) { +Searcher::CallbackReturn BreakpointResolverAddress::SearchCallback( + SearchFilter &filter, SymbolContext &context, Address *addr) { assert(m_breakpoint != nullptr); if (filter.AddressPasses(m_addr)) { @@ -149,8 +147,7 @@ BreakpointResolverAddress::SearchCallback(SearchFilter &filter, bp_loc_sp->GetDescription(&s, lldb::eDescriptionLevelVerbose); Log *log( lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_BREAKPOINTS)); - if (log) - log->Printf("Added location: %s\n", s.GetData()); + LLDB_LOGF(log, "Added location: %s\n", s.GetData()); } } else { BreakpointLocationSP loc_sp = m_breakpoint->GetLocationAtIndex(0); diff --git a/source/Breakpoint/BreakpointResolverFileLine.cpp b/source/Breakpoint/BreakpointResolverFileLine.cpp index a6095be31647..2b26f65816bd 100644 --- a/source/Breakpoint/BreakpointResolverFileLine.cpp +++ b/source/Breakpoint/BreakpointResolverFileLine.cpp @@ -198,10 +198,8 @@ void BreakpointResolverFileLine::FilterContexts(SymbolContextList &sc_list, } } -Searcher::CallbackReturn -BreakpointResolverFileLine::SearchCallback(SearchFilter &filter, - SymbolContext &context, - Address *addr, bool containing) { +Searcher::CallbackReturn BreakpointResolverFileLine::SearchCallback( + SearchFilter &filter, SymbolContext &context, Address *addr) { SymbolContextList sc_list; assert(m_breakpoint != nullptr); diff --git a/source/Breakpoint/BreakpointResolverFileRegex.cpp b/source/Breakpoint/BreakpointResolverFileRegex.cpp index 0b2485245b72..3cb04263c6dc 100644 --- a/source/Breakpoint/BreakpointResolverFileRegex.cpp +++ b/source/Breakpoint/BreakpointResolverFileRegex.cpp @@ -20,11 +20,11 @@ using namespace lldb_private; // BreakpointResolverFileRegex: BreakpointResolverFileRegex::BreakpointResolverFileRegex( - Breakpoint *bkpt, RegularExpression ®ex, + Breakpoint *bkpt, RegularExpression regex, const std::unordered_set<std::string> &func_names, bool exact_match) : BreakpointResolver(bkpt, BreakpointResolver::FileRegexResolver), - m_regex(regex), m_exact_match(exact_match), m_function_names(func_names) { -} + m_regex(std::move(regex)), m_exact_match(exact_match), + m_function_names(func_names) {} BreakpointResolverFileRegex::~BreakpointResolverFileRegex() {} @@ -69,7 +69,8 @@ BreakpointResolver *BreakpointResolverFileRegex::CreateFromStructuredData( } } - return new BreakpointResolverFileRegex(bkpt, regex, names_set, exact_match); + return new BreakpointResolverFileRegex(bkpt, std::move(regex), names_set, + exact_match); } StructuredData::ObjectSP @@ -93,10 +94,8 @@ BreakpointResolverFileRegex::SerializeToStructuredData() { return WrapOptionsDict(options_dict_sp); } -Searcher::CallbackReturn -BreakpointResolverFileRegex::SearchCallback(SearchFilter &filter, - SymbolContext &context, - Address *addr, bool containing) { +Searcher::CallbackReturn BreakpointResolverFileRegex::SearchCallback( + SearchFilter &filter, SymbolContext &context, Address *addr) { assert(m_breakpoint != nullptr); if (!context.target_sp) diff --git a/source/Breakpoint/BreakpointResolverName.cpp b/source/Breakpoint/BreakpointResolverName.cpp index 3ad2e8867f2a..ba9c88c7eae8 100644 --- a/source/Breakpoint/BreakpointResolverName.cpp +++ b/source/Breakpoint/BreakpointResolverName.cpp @@ -31,7 +31,8 @@ BreakpointResolverName::BreakpointResolverName( m_class_name(), m_regex(), m_match_type(type), m_language(language), m_skip_prologue(skip_prologue) { if (m_match_type == Breakpoint::Regexp) { - if (!m_regex.Compile(llvm::StringRef::withNullAsEmpty(name_cstr))) { + m_regex = RegularExpression(llvm::StringRef::withNullAsEmpty(name_cstr)); + if (!m_regex.IsValid()) { Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_BREAKPOINTS)); if (log) @@ -70,12 +71,12 @@ BreakpointResolverName::BreakpointResolverName(Breakpoint *bkpt, } BreakpointResolverName::BreakpointResolverName(Breakpoint *bkpt, - RegularExpression &func_regex, + RegularExpression func_regex, lldb::LanguageType language, lldb::addr_t offset, bool skip_prologue) : BreakpointResolver(bkpt, BreakpointResolver::NameResolver, offset), - m_class_name(nullptr), m_regex(func_regex), + m_class_name(nullptr), m_regex(std::move(func_regex)), m_match_type(Breakpoint::Regexp), m_language(language), m_skip_prologue(skip_prologue) {} @@ -125,9 +126,8 @@ BreakpointResolver *BreakpointResolverName::CreateFromStructuredData( success = options_dict.GetValueForKeyAsString( GetKey(OptionNames::RegexString), regex_text); if (success) { - RegularExpression regex(regex_text); - return new BreakpointResolverName(bkpt, regex, language, offset, - skip_prologue); + return new BreakpointResolverName(bkpt, RegularExpression(regex_text), + language, offset, skip_prologue); } else { StructuredData::Array *names_array; success = options_dict.GetValueForKeyAsArray( @@ -250,8 +250,7 @@ void BreakpointResolverName::AddNameLookup(ConstString name, Searcher::CallbackReturn BreakpointResolverName::SearchCallback(SearchFilter &filter, - SymbolContext &context, Address *addr, - bool containing) { + SymbolContext &context, Address *addr) { SymbolContextList func_list; // SymbolContextList sym_list; @@ -272,7 +271,6 @@ BreakpointResolverName::SearchCallback(SearchFilter &filter, bool filter_by_language = (m_language != eLanguageTypeUnknown); const bool include_symbols = !filter_by_cu; const bool include_inlines = true; - const bool append = true; switch (m_match_type) { case Breakpoint::Exact: @@ -281,7 +279,7 @@ BreakpointResolverName::SearchCallback(SearchFilter &filter, const size_t start_func_idx = func_list.GetSize(); context.module_sp->FindFunctions( lookup.GetLookupName(), nullptr, lookup.GetNameTypeMask(), - include_symbols, include_inlines, append, func_list); + include_symbols, include_inlines, func_list); const size_t end_func_idx = func_list.GetSize(); @@ -295,7 +293,7 @@ BreakpointResolverName::SearchCallback(SearchFilter &filter, context.module_sp->FindFunctions( m_regex, !filter_by_cu, // include symbols only if we aren't filtering by CU - include_inlines, append, func_list); + include_inlines, func_list); } break; case Breakpoint::Glob: @@ -388,7 +386,7 @@ BreakpointResolverName::SearchCallback(SearchFilter &filter, if (log) { StreamString s; bp_loc_sp->GetDescription(&s, lldb::eDescriptionLevelVerbose); - log->Printf("Added location: %s\n", s.GetData()); + LLDB_LOGF(log, "Added location: %s\n", s.GetData()); } } } diff --git a/source/Breakpoint/BreakpointResolverScripted.cpp b/source/Breakpoint/BreakpointResolverScripted.cpp index 8363795a4d7f..288fd37c1c79 100644 --- a/source/Breakpoint/BreakpointResolverScripted.cpp +++ b/source/Breakpoint/BreakpointResolverScripted.cpp @@ -29,8 +29,7 @@ BreakpointResolverScripted::BreakpointResolverScripted( Breakpoint *bkpt, const llvm::StringRef class_name, lldb::SearchDepth depth, - StructuredDataImpl *args_data, - ScriptInterpreter &script_interp) + StructuredDataImpl *args_data) : BreakpointResolver(bkpt, BreakpointResolver::PythonResolver), m_class_name(class_name), m_depth(depth), m_args_ptr(args_data) { CreateImplementationIfNeeded(); @@ -68,45 +67,25 @@ BreakpointResolverScripted::CreateFromStructuredData( llvm::StringRef class_name; bool success; - if (!bkpt) - return nullptr; - success = options_dict.GetValueForKeyAsString( GetKey(OptionNames::PythonClassName), class_name); if (!success) { error.SetErrorString("BRFL::CFSD: Couldn't find class name entry."); return nullptr; } - lldb::SearchDepth depth; - int depth_as_int; - success = options_dict.GetValueForKeyAsInteger( - GetKey(OptionNames::SearchDepth), depth_as_int); - if (!success) { - error.SetErrorString("BRFL::CFSD: Couldn't find class name entry."); - return nullptr; - } - if (depth_as_int >= (int) OptionNames::LastOptionName) { - error.SetErrorString("BRFL::CFSD: Invalid value for search depth."); - return nullptr; - } - depth = (lldb::SearchDepth) depth_as_int; + // The Python function will actually provide the search depth, this is a + // placeholder. + lldb::SearchDepth depth = lldb::eSearchDepthTarget; StructuredDataImpl *args_data_impl = new StructuredDataImpl(); - StructuredData::Dictionary *args_dict = new StructuredData::Dictionary(); + StructuredData::Dictionary *args_dict = nullptr; success = options_dict.GetValueForKeyAsDictionary( GetKey(OptionNames::ScriptArgs), args_dict); if (success) { - // FIXME: The resolver needs a copy of the ARGS dict that it can own, - // so I need to make a copy constructor for the Dictionary so I can pass - // that to it here. For now the args are empty. - //StructuredData::Dictionary *dict_copy = new StructuredData::Dictionary(args_dict); - + args_data_impl->SetObjectSP(args_dict->shared_from_this()); } - ScriptInterpreter *script_interp = bkpt->GetTarget() - .GetDebugger() - .GetScriptInterpreter(); - return new BreakpointResolverScripted(bkpt, class_name, depth, args_data_impl, - *script_interp); + return new BreakpointResolverScripted(bkpt, class_name, depth, + args_data_impl); } StructuredData::ObjectSP @@ -116,6 +95,10 @@ BreakpointResolverScripted::SerializeToStructuredData() { options_dict_sp->AddStringItem(GetKey(OptionNames::PythonClassName), m_class_name); + if (m_args_ptr->IsValid()) + options_dict_sp->AddItem(GetKey(OptionNames::ScriptArgs), + m_args_ptr->GetObjectSP()); + return WrapOptionsDict(options_dict_sp); } @@ -123,10 +106,8 @@ ScriptInterpreter *BreakpointResolverScripted::GetScriptInterpreter() { return m_breakpoint->GetTarget().GetDebugger().GetScriptInterpreter(); } -Searcher::CallbackReturn -BreakpointResolverScripted::SearchCallback(SearchFilter &filter, - SymbolContext &context, Address *addr, - bool containing) { +Searcher::CallbackReturn BreakpointResolverScripted::SearchCallback( + SearchFilter &filter, SymbolContext &context, Address *addr) { assert(m_breakpoint != nullptr); bool should_continue = true; if (!m_implementation_sp) @@ -173,11 +154,10 @@ void BreakpointResolverScripted::Dump(Stream *s) const {} lldb::BreakpointResolverSP BreakpointResolverScripted::CopyForBreakpoint(Breakpoint &breakpoint) { - ScriptInterpreter *script_interp = GetScriptInterpreter(); // FIXME: Have to make a copy of the arguments from the m_args_ptr and then // pass that to the new resolver. lldb::BreakpointResolverSP ret_sp( - new BreakpointResolverScripted(&breakpoint, m_class_name, - m_depth, nullptr, *script_interp)); + new BreakpointResolverScripted(&breakpoint, m_class_name, m_depth, + nullptr)); return ret_sp; } diff --git a/source/Breakpoint/Watchpoint.cpp b/source/Breakpoint/Watchpoint.cpp index e8a926527d24..17dcda13e9b9 100644 --- a/source/Breakpoint/Watchpoint.cpp +++ b/source/Breakpoint/Watchpoint.cpp @@ -13,10 +13,11 @@ #include "lldb/Core/ValueObject.h" #include "lldb/Core/ValueObjectMemory.h" #include "lldb/Expression/UserExpression.h" -#include "lldb/Symbol/ClangASTContext.h" +#include "lldb/Symbol/TypeSystem.h" #include "lldb/Target/Process.h" #include "lldb/Target/Target.h" #include "lldb/Target/ThreadSpec.h" +#include "lldb/Utility/Log.h" #include "lldb/Utility/Stream.h" using namespace lldb; @@ -30,14 +31,22 @@ Watchpoint::Watchpoint(Target &target, lldb::addr_t addr, uint32_t size, m_watch_write(0), m_watch_was_read(0), m_watch_was_written(0), m_ignore_count(0), m_false_alarms(0), m_decl_str(), m_watch_spec_str(), m_type(), m_error(), m_options(), m_being_created(true) { + if (type && type->IsValid()) m_type = *type; else { // If we don't have a known type, then we force it to unsigned int of the // right size. - ClangASTContext *ast_context = target.GetScratchClangASTContext(); - m_type = ast_context->GetBuiltinTypeForEncodingAndBitSize(eEncodingUint, - 8 * size); + auto type_system_or_err = + target.GetScratchTypeSystemForLanguage(eLanguageTypeC); + if (auto err = type_system_or_err.takeError()) { + LLDB_LOG_ERROR( + lldb_private::GetLogIfAnyCategoriesSet(LIBLLDB_LOG_WATCHPOINTS), + std::move(err), "Failed to set type."); + } else { + m_type = type_system_or_err->GetBuiltinTypeForEncodingAndBitSize( + eEncodingUint, 8 * size); + } } // Set the initial value of the watched variable: diff --git a/source/Breakpoint/WatchpointOptions.cpp b/source/Breakpoint/WatchpointOptions.cpp index 7dd130a3072c..cd5ef930e5dc 100644 --- a/source/Breakpoint/WatchpointOptions.cpp +++ b/source/Breakpoint/WatchpointOptions.cpp @@ -170,9 +170,8 @@ void WatchpointOptions::CommandBaton::GetDescription( s->IndentMore(); if (data && data->user_source.GetSize() > 0) { - const size_t num_strings = data->user_source.GetSize(); - for (size_t i = 0; i < num_strings; ++i) { - s->Indent(data->user_source.GetStringAtIndex(i)); + for (const std::string &line : data->user_source) { + s->Indent(line); s->EOL(); } } else { diff --git a/source/Commands/CommandCompletions.cpp b/source/Commands/CommandCompletions.cpp index 5d2fb3d67f57..469a6bbbadf6 100644 --- a/source/Commands/CommandCompletions.cpp +++ b/source/Commands/CommandCompletions.cpp @@ -71,10 +71,9 @@ bool CommandCompletions::InvokeCommonCompletionCallbacks( return handled; } -int CommandCompletions::SourceFiles(CommandInterpreter &interpreter, - CompletionRequest &request, - SearchFilter *searcher) { - request.SetWordComplete(true); +void CommandCompletions::SourceFiles(CommandInterpreter &interpreter, + CompletionRequest &request, + SearchFilter *searcher) { // Find some way to switch "include support files..." SourceFileCompleter completer(interpreter, false, request); @@ -85,20 +84,18 @@ int CommandCompletions::SourceFiles(CommandInterpreter &interpreter, } else { completer.DoCompletion(searcher); } - return request.GetNumberOfMatches(); } -static int DiskFilesOrDirectories(const llvm::Twine &partial_name, - bool only_directories, StringList &matches, - TildeExpressionResolver &Resolver) { - matches.Clear(); - +static void DiskFilesOrDirectories(const llvm::Twine &partial_name, + bool only_directories, + CompletionRequest &request, + TildeExpressionResolver &Resolver) { llvm::SmallString<256> CompletionBuffer; llvm::SmallString<256> Storage; partial_name.toVector(CompletionBuffer); if (CompletionBuffer.size() >= PATH_MAX) - return matches.GetSize(); + return; namespace path = llvm::sys::path; @@ -126,10 +123,10 @@ static int DiskFilesOrDirectories(const llvm::Twine &partial_name, for (const auto &S : MatchSet) { Resolved = S.getKey(); path::append(Resolved, path::get_separator()); - matches.AppendString(Resolved); + request.AddCompletion(Resolved, "", CompletionMode::Partial); } } - return matches.GetSize(); + return; } // If there was no trailing slash, then we're done as soon as we resolve @@ -138,8 +135,8 @@ static int DiskFilesOrDirectories(const llvm::Twine &partial_name, if (FirstSep == llvm::StringRef::npos) { // Make sure it ends with a separator. path::append(CompletionBuffer, path::get_separator()); - matches.AppendString(CompletionBuffer); - return matches.GetSize(); + request.AddCompletion(CompletionBuffer, "", CompletionMode::Partial); + return; } // We want to keep the form the user typed, so we special case this to @@ -219,51 +216,56 @@ static int DiskFilesOrDirectories(const llvm::Twine &partial_name, path::append(CompletionBuffer, path::get_separator()); } - matches.AppendString(CompletionBuffer); + CompletionMode mode = + is_dir ? CompletionMode::Partial : CompletionMode::Normal; + request.AddCompletion(CompletionBuffer, "", mode); } +} - return matches.GetSize(); +static void DiskFilesOrDirectories(const llvm::Twine &partial_name, + bool only_directories, StringList &matches, + TildeExpressionResolver &Resolver) { + CompletionResult result; + std::string partial_name_str = partial_name.str(); + CompletionRequest request(partial_name_str, partial_name_str.size(), result); + DiskFilesOrDirectories(partial_name, only_directories, request, Resolver); + result.GetMatches(matches); } -static int DiskFilesOrDirectories(CompletionRequest &request, - bool only_directories) { - request.SetWordComplete(false); +static void DiskFilesOrDirectories(CompletionRequest &request, + bool only_directories) { StandardTildeExpressionResolver resolver; - StringList matches; DiskFilesOrDirectories(request.GetCursorArgumentPrefix(), only_directories, - matches, resolver); - request.AddCompletions(matches); - return request.GetNumberOfMatches(); + request, resolver); } -int CommandCompletions::DiskFiles(CommandInterpreter &interpreter, - CompletionRequest &request, - SearchFilter *searcher) { - return DiskFilesOrDirectories(request, /*only_dirs*/ false); +void CommandCompletions::DiskFiles(CommandInterpreter &interpreter, + CompletionRequest &request, + SearchFilter *searcher) { + DiskFilesOrDirectories(request, /*only_dirs*/ false); } -int CommandCompletions::DiskFiles(const llvm::Twine &partial_file_name, - StringList &matches, - TildeExpressionResolver &Resolver) { - return DiskFilesOrDirectories(partial_file_name, false, matches, Resolver); +void CommandCompletions::DiskFiles(const llvm::Twine &partial_file_name, + StringList &matches, + TildeExpressionResolver &Resolver) { + DiskFilesOrDirectories(partial_file_name, false, matches, Resolver); } -int CommandCompletions::DiskDirectories(CommandInterpreter &interpreter, - CompletionRequest &request, - SearchFilter *searcher) { - return DiskFilesOrDirectories(request, /*only_dirs*/ true); +void CommandCompletions::DiskDirectories(CommandInterpreter &interpreter, + CompletionRequest &request, + SearchFilter *searcher) { + DiskFilesOrDirectories(request, /*only_dirs*/ true); } -int CommandCompletions::DiskDirectories(const llvm::Twine &partial_file_name, - StringList &matches, - TildeExpressionResolver &Resolver) { - return DiskFilesOrDirectories(partial_file_name, true, matches, Resolver); +void CommandCompletions::DiskDirectories(const llvm::Twine &partial_file_name, + StringList &matches, + TildeExpressionResolver &Resolver) { + DiskFilesOrDirectories(partial_file_name, true, matches, Resolver); } -int CommandCompletions::Modules(CommandInterpreter &interpreter, - CompletionRequest &request, - SearchFilter *searcher) { - request.SetWordComplete(true); +void CommandCompletions::Modules(CommandInterpreter &interpreter, + CompletionRequest &request, + SearchFilter *searcher) { ModuleCompleter completer(interpreter, request); if (searcher == nullptr) { @@ -273,13 +275,11 @@ int CommandCompletions::Modules(CommandInterpreter &interpreter, } else { completer.DoCompletion(searcher); } - return request.GetNumberOfMatches(); } -int CommandCompletions::Symbols(CommandInterpreter &interpreter, - CompletionRequest &request, - SearchFilter *searcher) { - request.SetWordComplete(true); +void CommandCompletions::Symbols(CommandInterpreter &interpreter, + CompletionRequest &request, + SearchFilter *searcher) { SymbolCompleter completer(interpreter, request); if (searcher == nullptr) { @@ -289,12 +289,11 @@ int CommandCompletions::Symbols(CommandInterpreter &interpreter, } else { completer.DoCompletion(searcher); } - return request.GetNumberOfMatches(); } -int CommandCompletions::SettingsNames(CommandInterpreter &interpreter, - CompletionRequest &request, - SearchFilter *searcher) { +void CommandCompletions::SettingsNames(CommandInterpreter &interpreter, + CompletionRequest &request, + SearchFilter *searcher) { // Cache the full setting name list static StringList g_property_names; if (g_property_names.GetSize() == 0) { @@ -309,38 +308,27 @@ int CommandCompletions::SettingsNames(CommandInterpreter &interpreter, } } - size_t exact_matches_idx = SIZE_MAX; - StringList matches; - g_property_names.AutoComplete(request.GetCursorArgumentPrefix(), matches, - exact_matches_idx); - request.SetWordComplete(exact_matches_idx != SIZE_MAX); - request.AddCompletions(matches); - return request.GetNumberOfMatches(); + for (const std::string &s : g_property_names) + request.TryCompleteCurrentArg(s); } -int CommandCompletions::PlatformPluginNames(CommandInterpreter &interpreter, - CompletionRequest &request, - SearchFilter *searcher) { - StringList new_matches; - std::size_t num_matches = PluginManager::AutoCompletePlatformName( - request.GetCursorArgumentPrefix(), new_matches); - request.SetWordComplete(num_matches == 1); - request.AddCompletions(new_matches); - return request.GetNumberOfMatches(); +void CommandCompletions::PlatformPluginNames(CommandInterpreter &interpreter, + CompletionRequest &request, + SearchFilter *searcher) { + PluginManager::AutoCompletePlatformName(request.GetCursorArgumentPrefix(), + request); } -int CommandCompletions::ArchitectureNames(CommandInterpreter &interpreter, - CompletionRequest &request, - SearchFilter *searcher) { - const uint32_t num_matches = ArchSpec::AutoComplete(request); - request.SetWordComplete(num_matches == 1); - return num_matches; +void CommandCompletions::ArchitectureNames(CommandInterpreter &interpreter, + CompletionRequest &request, + SearchFilter *searcher) { + ArchSpec::AutoComplete(request); } -int CommandCompletions::VariablePath(CommandInterpreter &interpreter, - CompletionRequest &request, - SearchFilter *searcher) { - return Variable::AutoComplete(interpreter.GetExecutionContext(), request); +void CommandCompletions::VariablePath(CommandInterpreter &interpreter, + CompletionRequest &request, + SearchFilter *searcher) { + Variable::AutoComplete(interpreter.GetExecutionContext(), request); } CommandCompletions::Completer::Completer(CommandInterpreter &interpreter, @@ -368,8 +356,7 @@ lldb::SearchDepth CommandCompletions::SourceFileCompleter::GetDepth() { Searcher::CallbackReturn CommandCompletions::SourceFileCompleter::SearchCallback(SearchFilter &filter, SymbolContext &context, - Address *addr, - bool complete) { + Address *addr) { if (context.comp_unit != nullptr) { if (m_include_support_files) { FileSpecList supporting_files = context.comp_unit->GetSupportFiles(); @@ -411,15 +398,14 @@ CommandCompletions::SourceFileCompleter::SearchCallback(SearchFilter &filter, return Searcher::eCallbackReturnContinue; } -size_t -CommandCompletions::SourceFileCompleter::DoCompletion(SearchFilter *filter) { +void CommandCompletions::SourceFileCompleter::DoCompletion( + SearchFilter *filter) { filter->Search(*this); // Now convert the filelist to completions: for (size_t i = 0; i < m_matching_files.GetSize(); i++) { m_request.AddCompletion( m_matching_files.GetFileSpecAtIndex(i).GetFilename().GetCString()); } - return m_request.GetNumberOfMatches(); } // SymbolCompleter @@ -448,7 +434,7 @@ CommandCompletions::SymbolCompleter::SymbolCompleter( pos = regex_str.insert(pos, '\\'); pos = find_if(pos + 2, regex_str.end(), regex_chars); } - m_regex.Compile(regex_str); + m_regex = RegularExpression(regex_str); } lldb::SearchDepth CommandCompletions::SymbolCompleter::GetDepth() { @@ -456,22 +442,24 @@ lldb::SearchDepth CommandCompletions::SymbolCompleter::GetDepth() { } Searcher::CallbackReturn CommandCompletions::SymbolCompleter::SearchCallback( - SearchFilter &filter, SymbolContext &context, Address *addr, - bool complete) { + SearchFilter &filter, SymbolContext &context, Address *addr) { if (context.module_sp) { SymbolContextList sc_list; const bool include_symbols = true; const bool include_inlines = true; - const bool append = true; context.module_sp->FindFunctions(m_regex, include_symbols, include_inlines, - append, sc_list); + sc_list); SymbolContext sc; // Now add the functions & symbols to the list - only add if unique: for (uint32_t i = 0; i < sc_list.GetSize(); i++) { if (sc_list.GetContextAtIndex(i, sc)) { ConstString func_name = sc.GetFunctionName(Mangled::ePreferDemangled); - if (!func_name.IsEmpty()) + // Ensure that the function name matches the regex. This is more than a + // sanity check. It is possible that the demangled function name does + // not start with the prefix, for example when it's in an anonymous + // namespace. + if (!func_name.IsEmpty() && m_regex.Execute(func_name.GetStringRef())) m_match_set.insert(func_name); } } @@ -479,13 +467,11 @@ Searcher::CallbackReturn CommandCompletions::SymbolCompleter::SearchCallback( return Searcher::eCallbackReturnContinue; } -size_t CommandCompletions::SymbolCompleter::DoCompletion(SearchFilter *filter) { +void CommandCompletions::SymbolCompleter::DoCompletion(SearchFilter *filter) { filter->Search(*this); collection::iterator pos = m_match_set.begin(), end = m_match_set.end(); for (pos = m_match_set.begin(); pos != end; pos++) m_request.AddCompletion((*pos).GetCString()); - - return m_request.GetNumberOfMatches(); } // ModuleCompleter @@ -502,8 +488,7 @@ lldb::SearchDepth CommandCompletions::ModuleCompleter::GetDepth() { } Searcher::CallbackReturn CommandCompletions::ModuleCompleter::SearchCallback( - SearchFilter &filter, SymbolContext &context, Address *addr, - bool complete) { + SearchFilter &filter, SymbolContext &context, Address *addr) { if (context.module_sp) { const char *cur_file_name = context.module_sp->GetFileSpec().GetFilename().GetCString(); @@ -526,7 +511,6 @@ Searcher::CallbackReturn CommandCompletions::ModuleCompleter::SearchCallback( return Searcher::eCallbackReturnContinue; } -size_t CommandCompletions::ModuleCompleter::DoCompletion(SearchFilter *filter) { +void CommandCompletions::ModuleCompleter::DoCompletion(SearchFilter *filter) { filter->Search(*this); - return m_request.GetNumberOfMatches(); } diff --git a/source/Commands/CommandObjectApropos.cpp b/source/Commands/CommandObjectApropos.cpp index 957de475569c..7ba0b250fbd5 100644 --- a/source/Commands/CommandObjectApropos.cpp +++ b/source/Commands/CommandObjectApropos.cpp @@ -44,7 +44,7 @@ bool CommandObjectApropos::DoExecute(Args &args, CommandReturnObject &result) { const size_t argc = args.GetArgumentCount(); if (argc == 1) { - auto search_word = args[0].ref; + auto search_word = args[0].ref(); if (!search_word.empty()) { // The bulk of the work must be done inside the Command Interpreter, // since the command dictionary is private. @@ -63,13 +63,7 @@ bool CommandObjectApropos::DoExecute(Args &args, CommandReturnObject &result) { if (commands_found.GetSize() > 0) { result.AppendMessageWithFormat( "The following commands may relate to '%s':\n", args[0].c_str()); - size_t max_len = 0; - - for (size_t i = 0; i < commands_found.GetSize(); ++i) { - size_t len = strlen(commands_found.GetStringAtIndex(i)); - if (len > max_len) - max_len = len; - } + const size_t max_len = commands_found.GetMaxStringLength(); for (size_t i = 0; i < commands_found.GetSize(); ++i) m_interpreter.OutputFormattedHelpText( @@ -85,7 +79,7 @@ bool CommandObjectApropos::DoExecute(Args &args, CommandReturnObject &result) { const bool dump_qualified_name = true; result.AppendMessageWithFormatv( "\nThe following settings variables may relate to '{0}': \n\n", - args[0].ref); + args[0].ref()); for (size_t i = 0; i < num_properties; ++i) properties[i]->DumpDescription( m_interpreter, result.GetOutputStream(), 0, dump_qualified_name); diff --git a/source/Commands/CommandObjectBreakpoint.cpp b/source/Commands/CommandObjectBreakpoint.cpp index c33f3834cb13..ad699975b507 100644 --- a/source/Commands/CommandObjectBreakpoint.cpp +++ b/source/Commands/CommandObjectBreakpoint.cpp @@ -16,6 +16,7 @@ #include "lldb/Interpreter/CommandInterpreter.h" #include "lldb/Interpreter/CommandReturnObject.h" #include "lldb/Interpreter/OptionArgParser.h" +#include "lldb/Interpreter/OptionGroupPythonClassWithDict.h" #include "lldb/Interpreter/OptionValueBoolean.h" #include "lldb/Interpreter/OptionValueString.h" #include "lldb/Interpreter/OptionValueUInt64.h" @@ -44,21 +45,9 @@ static void AddBreakpointDescription(Stream *s, Breakpoint *bp, // Modifiable Breakpoint Options #pragma mark Modify::CommandOptions -static constexpr OptionDefinition g_breakpoint_modify_options[] = { - // clang-format off - { LLDB_OPT_SET_1, false, "ignore-count", 'i', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeCount, "Set the number of times this breakpoint is skipped before stopping." }, - { LLDB_OPT_SET_1, false, "one-shot", 'o', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeBoolean, "The breakpoint is deleted the first time it stop causes a stop." }, - { LLDB_OPT_SET_1, false, "thread-index", 'x', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeThreadIndex, "The breakpoint stops only for the thread whose index matches this argument." }, - { LLDB_OPT_SET_1, false, "thread-id", 't', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeThreadID, "The breakpoint stops only for the thread whose TID matches this argument." }, - { LLDB_OPT_SET_1, false, "thread-name", 'T', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeThreadName, "The breakpoint stops only for the thread whose thread name matches this argument." }, - { LLDB_OPT_SET_1, false, "queue-name", 'q', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeQueueName, "The breakpoint stops only for threads in the queue whose name is given by this argument." }, - { LLDB_OPT_SET_1, false, "condition", 'c', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeExpression, "The breakpoint stops only if this condition expression evaluates to true." }, - { LLDB_OPT_SET_1, false, "auto-continue",'G', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeBoolean, "The breakpoint will auto-continue after running its commands." }, - { LLDB_OPT_SET_2, false, "enable", 'e', OptionParser::eNoArgument, nullptr, {}, 0, eArgTypeNone, "Enable the breakpoint." }, - { LLDB_OPT_SET_3, false, "disable", 'd', OptionParser::eNoArgument, nullptr, {}, 0, eArgTypeNone, "Disable the breakpoint." }, - { LLDB_OPT_SET_4, false, "command", 'C', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeCommand, "A command to run when the breakpoint is hit, can be provided more than once, the commands will get run in order left to right." }, - // clang-format on -}; +#define LLDB_OPTIONS_breakpoint_modify +#include "CommandOptions.inc" + class lldb_private::BreakpointOptionGroup : public OptionGroup { public: @@ -153,9 +142,7 @@ public: } break; default: - error.SetErrorStringWithFormat("unrecognized option '%c'", - short_option); - break; + llvm_unreachable("Unimplemented option"); } return error; @@ -171,7 +158,7 @@ public: { if (!m_commands.empty()) { - auto cmd_data = llvm::make_unique<BreakpointOptions::CommandData>(); + auto cmd_data = std::make_unique<BreakpointOptions::CommandData>(); for (std::string &str : m_commands) cmd_data->user_source.AppendString(str); @@ -192,12 +179,9 @@ public: BreakpointOptions m_bp_opts; }; -static constexpr OptionDefinition g_breakpoint_dummy_options[] = { - // clang-format off - { LLDB_OPT_SET_1, false, "dummy-breakpoints", 'D', OptionParser::eNoArgument, nullptr, {}, 0, eArgTypeNone, "Act on Dummy breakpoints - i.e. breakpoints set before a file is provided, " - "which prime new targets." }, - // clang-format on -}; + +#define LLDB_OPTIONS_breakpoint_dummy +#include "CommandOptions.inc" class BreakpointDummyOptionGroup : public OptionGroup { @@ -221,9 +205,7 @@ public: m_use_dummy = true; break; default: - error.SetErrorStringWithFormat("unrecognized option '%c'", - short_option); - break; + llvm_unreachable("Unimplemented option"); } return error; @@ -237,88 +219,8 @@ public: }; -// If an additional option set beyond LLDB_OPTION_SET_10 is added, make sure to -// update the numbers passed to LLDB_OPT_SET_FROM_TO(...) appropriately. -#define LLDB_OPT_NOT_10 (LLDB_OPT_SET_FROM_TO(1, 11) & ~LLDB_OPT_SET_10) -#define LLDB_OPT_SKIP_PROLOGUE (LLDB_OPT_SET_1 | LLDB_OPT_SET_FROM_TO(3, 8)) -#define LLDB_OPT_FILE (LLDB_OPT_SET_FROM_TO(1, 11) & ~LLDB_OPT_SET_2 & ~LLDB_OPT_SET_10) -#define LLDB_OPT_OFFSET_APPLIES (LLDB_OPT_SET_FROM_TO(1, 8) & ~LLDB_OPT_SET_2) -#define LLDB_OPT_MOVE_TO_NEAREST_CODE (LLDB_OPT_SET_1 | LLDB_OPT_SET_9) -#define LLDB_OPT_EXPR_LANGUAGE (LLDB_OPT_SET_FROM_TO(3, 8)) - -static constexpr OptionDefinition g_breakpoint_set_options[] = { - // clang-format off - { LLDB_OPT_NOT_10, false, "shlib", 's', OptionParser::eRequiredArgument, nullptr, {}, CommandCompletions::eModuleCompletion, eArgTypeShlibName, "Set the breakpoint only in this shared library. Can repeat this option " - "multiple times to specify multiple shared libraries." }, - { LLDB_OPT_SET_ALL, false, "hardware", 'H', OptionParser::eNoArgument, nullptr, {}, 0, eArgTypeNone, "Require the breakpoint to use hardware breakpoints." }, - { LLDB_OPT_FILE, false, "file", 'f', OptionParser::eRequiredArgument, nullptr, {}, CommandCompletions::eSourceFileCompletion, eArgTypeFilename, "Specifies the source file in which to set this breakpoint. Note, by default " - "lldb only looks for files that are #included if they use the standard include " - "file extensions. To set breakpoints on .c/.cpp/.m/.mm files that are " - "#included, set target.inline-breakpoint-strategy to \"always\"." }, - { LLDB_OPT_SET_1, true, "line", 'l', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeLineNum, "Specifies the line number on which to set this breakpoint." }, - - // Comment out this option for the moment, as we don't actually use it, but - // will in the future. This way users won't see it, but the infrastructure is - // left in place. - // { 0, false, "column", 'C', OptionParser::eRequiredArgument, nullptr, "<column>", - // "Set the breakpoint by source location at this particular column."}, - - { LLDB_OPT_SET_2, true, "address", 'a', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeAddressOrExpression, "Set the breakpoint at the specified address. If the address maps uniquely to " - "a particular binary, then the address will be converted to a \"file\" " - "address, so that the breakpoint will track that binary+offset no matter where " - "the binary eventually loads. Alternately, if you also specify the module - " - "with the -s option - then the address will be treated as a file address in " - "that module, and resolved accordingly. Again, this will allow lldb to track " - "that offset on subsequent reloads. The module need not have been loaded at " - "the time you specify this breakpoint, and will get resolved when the module " - "is loaded." }, - { LLDB_OPT_SET_3, true, "name", 'n', OptionParser::eRequiredArgument, nullptr, {}, CommandCompletions::eSymbolCompletion, eArgTypeFunctionName, "Set the breakpoint by function name. Can be repeated multiple times to make " - "one breakpoint for multiple names" }, - { LLDB_OPT_SET_9, false, "source-regexp-function", 'X', OptionParser::eRequiredArgument, nullptr, {}, CommandCompletions::eSymbolCompletion, eArgTypeFunctionName, "When used with '-p' limits the source regex to source contained in the named " - "functions. Can be repeated multiple times." }, - { LLDB_OPT_SET_4, true, "fullname", 'F', OptionParser::eRequiredArgument, nullptr, {}, CommandCompletions::eSymbolCompletion, eArgTypeFullName, "Set the breakpoint by fully qualified function names. For C++ this means " - "namespaces and all arguments, and for Objective-C this means a full function " - "prototype with class and selector. Can be repeated multiple times to make " - "one breakpoint for multiple names." }, - { LLDB_OPT_SET_5, true, "selector", 'S', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeSelector, "Set the breakpoint by ObjC selector name. Can be repeated multiple times to " - "make one breakpoint for multiple Selectors." }, - { LLDB_OPT_SET_6, true, "method", 'M', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeMethod, "Set the breakpoint by C++ method names. Can be repeated multiple times to " - "make one breakpoint for multiple methods." }, - { LLDB_OPT_SET_7, true, "func-regex", 'r', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeRegularExpression, "Set the breakpoint by function name, evaluating a regular-expression to find " - "the function name(s)." }, - { LLDB_OPT_SET_8, true, "basename", 'b', OptionParser::eRequiredArgument, nullptr, {}, CommandCompletions::eSymbolCompletion, eArgTypeFunctionName, "Set the breakpoint by function basename (C++ namespaces and arguments will be " - "ignored). Can be repeated multiple times to make one breakpoint for multiple " - "symbols." }, - { LLDB_OPT_SET_9, true, "source-pattern-regexp", 'p', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeRegularExpression, "Set the breakpoint by specifying a regular expression which is matched " - "against the source text in a source file or files specified with the -f " - "option. The -f option can be specified more than once. If no source files " - "are specified, uses the current \"default source file\". If you want to " - "match against all source files, pass the \"--all-files\" option." }, - { LLDB_OPT_SET_9, false, "all-files", 'A', OptionParser::eNoArgument, nullptr, {}, 0, eArgTypeNone, "All files are searched for source pattern matches." }, - { LLDB_OPT_SET_11, true, "python-class", 'P', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypePythonClass, "The name of the class that implement a scripted breakpoint." }, - { LLDB_OPT_SET_11, false, "python-class-key", 'k', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeNone, "The key for a key/value pair passed to the class that implements a scripted breakpoint. Can be specified more than once." }, - { LLDB_OPT_SET_11, false, "python-class-value", 'v', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeNone, "The value for the previous key in the pair passed to the class that implements a scripted breakpoint. Can be specified more than once." }, - { LLDB_OPT_SET_10, true, "language-exception", 'E', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeLanguage, "Set the breakpoint on exceptions thrown by the specified language (without " - "options, on throw but not catch.)" }, - { LLDB_OPT_SET_10, false, "on-throw", 'w', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeBoolean, "Set the breakpoint on exception throW." }, - { LLDB_OPT_SET_10, false, "on-catch", 'h', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeBoolean, "Set the breakpoint on exception catcH." }, - - // Don't add this option till it actually does something useful... - // { LLDB_OPT_SET_10, false, "exception-typename", 'O', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeTypeName, - // "The breakpoint will only stop if an exception Object of this type is thrown. Can be repeated multiple times to stop for multiple object types" }, - - { LLDB_OPT_EXPR_LANGUAGE, false, "language", 'L', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeLanguage, "Specifies the Language to use when interpreting the breakpoint's expression " - "(note: currently only implemented for setting breakpoints on identifiers). " - "If not set the target.language setting is used." }, - { LLDB_OPT_SKIP_PROLOGUE, false, "skip-prologue", 'K', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeBoolean, "sKip the prologue if the breakpoint is at the beginning of a function. " - "If not set the target.skip-prologue setting is used." }, - { LLDB_OPT_SET_ALL, false, "breakpoint-name", 'N', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeBreakpointName, "Adds this to the list of names for this breakpoint." }, - { LLDB_OPT_OFFSET_APPLIES, false, "address-slide", 'R', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeAddress, "Add the specified offset to whatever address(es) the breakpoint resolves to. " - "At present this applies the offset directly as given, and doesn't try to align it to instruction boundaries." }, - { LLDB_OPT_MOVE_TO_NEAREST_CODE, false, "move-to-nearest-code", 'm', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeBoolean, "Move breakpoints to nearest code. If not set the target.move-to-nearest-code " - "setting is used." }, - // clang-format on -}; +#define LLDB_OPTIONS_breakpoint_set +#include "CommandOptions.inc" // CommandObjectBreakpointSet @@ -340,15 +242,18 @@ public: interpreter, "breakpoint set", "Sets a breakpoint or set of breakpoints in the executable.", "breakpoint set <cmd-options>"), - m_bp_opts(), m_options() { - // We're picking up all the normal options, commands and disable. - m_all_options.Append(&m_bp_opts, - LLDB_OPT_SET_1 | LLDB_OPT_SET_3 | LLDB_OPT_SET_4, - LLDB_OPT_SET_ALL); - m_all_options.Append(&m_dummy_options, LLDB_OPT_SET_1, LLDB_OPT_SET_ALL); - m_all_options.Append(&m_options); - m_all_options.Finalize(); - } + m_bp_opts(), m_python_class_options("scripted breakpoint", 'P'), + m_options() { + // We're picking up all the normal options, commands and disable. + m_all_options.Append(&m_python_class_options, LLDB_OPT_SET_1, + LLDB_OPT_SET_11); + m_all_options.Append(&m_bp_opts, + LLDB_OPT_SET_1 | LLDB_OPT_SET_3 | LLDB_OPT_SET_4, + LLDB_OPT_SET_ALL); + m_all_options.Append(&m_dummy_options, LLDB_OPT_SET_1, LLDB_OPT_SET_ALL); + m_all_options.Append(&m_options); + m_all_options.Finalize(); + } ~CommandObjectBreakpointSet() override = default; @@ -451,14 +356,6 @@ public: m_hardware = true; break; - case 'k': { - if (m_current_key.empty()) - m_current_key.assign(option_arg); - else - error.SetErrorStringWithFormat("Key: %s missing value.", - m_current_key.c_str()); - - } break; case 'K': { bool success; bool value; @@ -540,10 +437,6 @@ public: m_source_text_regexp.assign(option_arg); break; - case 'P': - m_python_class.assign(option_arg); - break; - case 'r': m_func_regexp.assign(option_arg); break; @@ -557,16 +450,6 @@ public: m_func_name_type_mask |= eFunctionNameTypeSelector; break; - case 'v': { - if (!m_current_key.empty()) { - m_extra_args_sp->AddStringItem(m_current_key, option_arg); - m_current_key.clear(); - } - else - error.SetErrorStringWithFormat("Value \"%s\" missing matching key.", - option_arg.str().c_str()); - } break; - case 'w': { bool success; m_throw_bp = OptionArgParser::ToBoolean(option_arg, true, &success); @@ -581,9 +464,7 @@ public: break; default: - error.SetErrorStringWithFormat("unrecognized option '%c'", - short_option); - break; + llvm_unreachable("Unimplemented option"); } return error; @@ -611,8 +492,6 @@ public: m_exception_extra_args.Clear(); m_move_to_nearest_code = eLazyBoolCalculate; m_source_regex_func_names.clear(); - m_python_class.clear(); - m_extra_args_sp = std::make_shared<StructuredData::Dictionary>(); m_current_key.clear(); } @@ -644,21 +523,12 @@ public: Args m_exception_extra_args; LazyBool m_move_to_nearest_code; std::unordered_set<std::string> m_source_regex_func_names; - std::string m_python_class; - StructuredData::DictionarySP m_extra_args_sp; std::string m_current_key; }; protected: bool DoExecute(Args &command, CommandReturnObject &result) override { - Target *target = GetSelectedOrDummyTarget(m_dummy_options.m_use_dummy); - - if (target == nullptr) { - result.AppendError("Invalid target. Must set target before setting " - "breakpoints (see 'target create' command)."); - result.SetStatus(eReturnStatusFailed); - return false; - } + Target &target = GetSelectedOrDummyTarget(m_dummy_options.m_use_dummy); // The following are the various types of breakpoints that could be set: // 1). -f -l -p [-s -g] (setting breakpoint by source location) @@ -673,7 +543,7 @@ protected: BreakpointSetType break_type = eSetTypeInvalid; - if (!m_options.m_python_class.empty()) + if (!m_python_class_options.GetClassName().empty()) break_type = eSetTypeScripted; else if (m_options.m_line_num != 0) break_type = eSetTypeFileAndLine; @@ -720,16 +590,11 @@ protected: // Only check for inline functions if LazyBool check_inlines = eLazyBoolCalculate; - bp_sp = target->CreateBreakpoint(&(m_options.m_modules), - file, - m_options.m_line_num, - m_options.m_column, - m_options.m_offset_addr, - check_inlines, - m_options.m_skip_prologue, - internal, - m_options.m_hardware, - m_options.m_move_to_nearest_code); + bp_sp = target.CreateBreakpoint( + &(m_options.m_modules), file, m_options.m_line_num, + m_options.m_column, m_options.m_offset_addr, check_inlines, + m_options.m_skip_prologue, internal, m_options.m_hardware, + m_options.m_move_to_nearest_code); } break; case eSetTypeAddress: // Breakpoint by address @@ -741,12 +606,11 @@ protected: if (num_modules_specified == 1) { const FileSpec *file_spec = m_options.m_modules.GetFileSpecPointerAtIndex(0); - bp_sp = target->CreateAddressInModuleBreakpoint(m_options.m_load_addr, - internal, file_spec, - m_options.m_hardware); + bp_sp = target.CreateAddressInModuleBreakpoint( + m_options.m_load_addr, internal, file_spec, m_options.m_hardware); } else if (num_modules_specified == 0) { - bp_sp = target->CreateBreakpoint(m_options.m_load_addr, internal, - m_options.m_hardware); + bp_sp = target.CreateBreakpoint(m_options.m_load_addr, internal, + m_options.m_hardware); } else { result.AppendError("Only one shared library can be specified for " "address breakpoints."); @@ -762,38 +626,29 @@ protected: if (name_type_mask == 0) name_type_mask = eFunctionNameTypeAuto; - bp_sp = target->CreateBreakpoint(&(m_options.m_modules), - &(m_options.m_filenames), - m_options.m_func_names, - name_type_mask, - m_options.m_language, - m_options.m_offset_addr, - m_options.m_skip_prologue, - internal, - m_options.m_hardware); + bp_sp = target.CreateBreakpoint( + &(m_options.m_modules), &(m_options.m_filenames), + m_options.m_func_names, name_type_mask, m_options.m_language, + m_options.m_offset_addr, m_options.m_skip_prologue, internal, + m_options.m_hardware); } break; case eSetTypeFunctionRegexp: // Breakpoint by regular expression function // name { RegularExpression regexp(m_options.m_func_regexp); - if (!regexp.IsValid()) { - char err_str[1024]; - regexp.GetErrorAsCString(err_str, sizeof(err_str)); + if (llvm::Error err = regexp.GetError()) { result.AppendErrorWithFormat( "Function name regular expression could not be compiled: \"%s\"", - err_str); + llvm::toString(std::move(err)).c_str()); result.SetStatus(eReturnStatusFailed); return false; } - bp_sp = target->CreateFuncRegexBreakpoint(&(m_options.m_modules), - &(m_options.m_filenames), - regexp, - m_options.m_language, - m_options.m_skip_prologue, - internal, - m_options.m_hardware); + bp_sp = target.CreateFuncRegexBreakpoint( + &(m_options.m_modules), &(m_options.m_filenames), std::move(regexp), + m_options.m_language, m_options.m_skip_prologue, internal, + m_options.m_hardware); } break; case eSetTypeSourceRegexp: // Breakpoint by regexp on source text. @@ -813,39 +668,29 @@ protected: } RegularExpression regexp(m_options.m_source_text_regexp); - if (!regexp.IsValid()) { - char err_str[1024]; - regexp.GetErrorAsCString(err_str, sizeof(err_str)); + if (llvm::Error err = regexp.GetError()) { result.AppendErrorWithFormat( "Source text regular expression could not be compiled: \"%s\"", - err_str); + llvm::toString(std::move(err)).c_str()); result.SetStatus(eReturnStatusFailed); return false; } - bp_sp = - target->CreateSourceRegexBreakpoint(&(m_options.m_modules), - &(m_options.m_filenames), - m_options - .m_source_regex_func_names, - regexp, - internal, - m_options.m_hardware, - m_options.m_move_to_nearest_code); + bp_sp = target.CreateSourceRegexBreakpoint( + &(m_options.m_modules), &(m_options.m_filenames), + m_options.m_source_regex_func_names, std::move(regexp), internal, + m_options.m_hardware, m_options.m_move_to_nearest_code); } break; case eSetTypeException: { Status precond_error; - bp_sp = target->CreateExceptionBreakpoint(m_options.m_exception_language, - m_options.m_catch_bp, - m_options.m_throw_bp, - internal, - &m_options - .m_exception_extra_args, - &precond_error); + bp_sp = target.CreateExceptionBreakpoint( + m_options.m_exception_language, m_options.m_catch_bp, + m_options.m_throw_bp, internal, &m_options.m_exception_extra_args, + &precond_error); if (precond_error.Fail()) { result.AppendErrorWithFormat( "Error setting extra exception arguments: %s", precond_error.AsCString()); - target->RemoveBreakpointByID(bp_sp->GetID()); + target.RemoveBreakpointByID(bp_sp->GetID()); result.SetStatus(eReturnStatusFailed); return false; } @@ -853,18 +698,15 @@ protected: case eSetTypeScripted: { Status error; - bp_sp = target->CreateScriptedBreakpoint(m_options.m_python_class, - &(m_options.m_modules), - &(m_options.m_filenames), - false, - m_options.m_hardware, - m_options.m_extra_args_sp, - &error); + bp_sp = target.CreateScriptedBreakpoint( + m_python_class_options.GetClassName().c_str(), &(m_options.m_modules), + &(m_options.m_filenames), false, m_options.m_hardware, + m_python_class_options.GetStructuredData(), &error); if (error.Fail()) { result.AppendErrorWithFormat( "Error setting extra exception arguments: %s", error.AsCString()); - target->RemoveBreakpointByID(bp_sp->GetID()); + target.RemoveBreakpointByID(bp_sp->GetID()); result.SetStatus(eReturnStatusFailed); return false; } @@ -880,11 +722,11 @@ protected: if (!m_options.m_breakpoint_names.empty()) { Status name_error; for (auto name : m_options.m_breakpoint_names) { - target->AddNameToBreakpoint(bp_sp, name.c_str(), name_error); + target.AddNameToBreakpoint(bp_sp, name.c_str(), name_error); if (name_error.Fail()) { result.AppendErrorWithFormat("Invalid breakpoint name: %s", name.c_str()); - target->RemoveBreakpointByID(bp_sp->GetID()); + target.RemoveBreakpointByID(bp_sp->GetID()); result.SetStatus(eReturnStatusFailed); return false; } @@ -897,7 +739,7 @@ protected: const bool show_locations = false; bp_sp->GetDescription(&output_stream, lldb::eDescriptionLevelInitial, show_locations); - if (target == GetDebugger().GetDummyTarget()) + if (&target == &GetDummyTarget()) output_stream.Printf("Breakpoint set in dummy target, will get copied " "into future targets.\n"); else { @@ -919,12 +761,12 @@ protected: } private: - bool GetDefaultFile(Target *target, FileSpec &file, + bool GetDefaultFile(Target &target, FileSpec &file, CommandReturnObject &result) { uint32_t default_line; // First use the Source Manager's default file. Then use the current stack // frame's file. - if (!target->GetSourceManager().GetDefaultFileAndLine(file, default_line)) { + if (!target.GetSourceManager().GetDefaultFileAndLine(file, default_line)) { StackFrame *cur_frame = m_exe_ctx.GetFramePtr(); if (cur_frame == nullptr) { result.AppendError( @@ -954,6 +796,7 @@ private: BreakpointOptionGroup m_bp_opts; BreakpointDummyOptionGroup m_dummy_options; + OptionGroupPythonClassWithDict m_python_class_options; CommandOptions m_options; OptionGroupOptions m_all_options; }; @@ -993,20 +836,15 @@ public: protected: bool DoExecute(Args &command, CommandReturnObject &result) override { - Target *target = GetSelectedOrDummyTarget(m_dummy_opts.m_use_dummy); - if (target == nullptr) { - result.AppendError("Invalid target. No existing target or breakpoints."); - result.SetStatus(eReturnStatusFailed); - return false; - } + Target &target = GetSelectedOrDummyTarget(m_dummy_opts.m_use_dummy); std::unique_lock<std::recursive_mutex> lock; - target->GetBreakpointList().GetListMutex(lock); + target.GetBreakpointList().GetListMutex(lock); BreakpointIDList valid_bp_ids; CommandObjectMultiwordBreakpoint::VerifyBreakpointOrLocationIDs( - command, target, result, &valid_bp_ids, + command, &target, result, &valid_bp_ids, BreakpointName::Permissions::PermissionKinds::disablePerm); if (result.Succeeded()) { @@ -1016,7 +854,7 @@ protected: if (cur_bp_id.GetBreakpointID() != LLDB_INVALID_BREAK_ID) { Breakpoint *bp = - target->GetBreakpointByID(cur_bp_id.GetBreakpointID()).get(); + target.GetBreakpointByID(cur_bp_id.GetBreakpointID()).get(); if (cur_bp_id.GetLocationID() != LLDB_INVALID_BREAK_ID) { BreakpointLocation *location = bp->FindLocationByID(cur_bp_id.GetLocationID()).get(); @@ -1062,17 +900,12 @@ public: protected: bool DoExecute(Args &command, CommandReturnObject &result) override { - Target *target = GetSelectedOrDummyTarget(); - if (target == nullptr) { - result.AppendError("Invalid target. No existing target or breakpoints."); - result.SetStatus(eReturnStatusFailed); - return false; - } + Target &target = GetSelectedOrDummyTarget(); std::unique_lock<std::recursive_mutex> lock; - target->GetBreakpointList().GetListMutex(lock); + target.GetBreakpointList().GetListMutex(lock); - const BreakpointList &breakpoints = target->GetBreakpointList(); + const BreakpointList &breakpoints = target.GetBreakpointList(); size_t num_breakpoints = breakpoints.GetSize(); @@ -1084,7 +917,7 @@ protected: if (command.empty()) { // No breakpoint selected; enable all currently set breakpoints. - target->EnableAllowedBreakpoints(); + target.EnableAllowedBreakpoints(); result.AppendMessageWithFormat("All breakpoints enabled. (%" PRIu64 " breakpoints)\n", (uint64_t)num_breakpoints); @@ -1093,7 +926,7 @@ protected: // Particular breakpoint selected; enable that breakpoint. BreakpointIDList valid_bp_ids; CommandObjectMultiwordBreakpoint::VerifyBreakpointOrLocationIDs( - command, target, result, &valid_bp_ids, + command, &target, result, &valid_bp_ids, BreakpointName::Permissions::PermissionKinds::disablePerm); if (result.Succeeded()) { @@ -1105,7 +938,7 @@ protected: if (cur_bp_id.GetBreakpointID() != LLDB_INVALID_BREAK_ID) { Breakpoint *breakpoint = - target->GetBreakpointByID(cur_bp_id.GetBreakpointID()).get(); + target.GetBreakpointByID(cur_bp_id.GetBreakpointID()).get(); if (cur_bp_id.GetLocationID() != LLDB_INVALID_BREAK_ID) { BreakpointLocation *location = breakpoint->FindLocationByID(cur_bp_id.GetLocationID()).get(); @@ -1175,17 +1008,11 @@ the second re-enables the first location."); protected: bool DoExecute(Args &command, CommandReturnObject &result) override { - Target *target = GetSelectedOrDummyTarget(); - if (target == nullptr) { - result.AppendError("Invalid target. No existing target or breakpoints."); - result.SetStatus(eReturnStatusFailed); - return false; - } - + Target &target = GetSelectedOrDummyTarget(); std::unique_lock<std::recursive_mutex> lock; - target->GetBreakpointList().GetListMutex(lock); + target.GetBreakpointList().GetListMutex(lock); - const BreakpointList &breakpoints = target->GetBreakpointList(); + const BreakpointList &breakpoints = target.GetBreakpointList(); size_t num_breakpoints = breakpoints.GetSize(); if (num_breakpoints == 0) { @@ -1196,7 +1023,7 @@ protected: if (command.empty()) { // No breakpoint selected; disable all currently set breakpoints. - target->DisableAllowedBreakpoints(); + target.DisableAllowedBreakpoints(); result.AppendMessageWithFormat("All breakpoints disabled. (%" PRIu64 " breakpoints)\n", (uint64_t)num_breakpoints); @@ -1206,7 +1033,7 @@ protected: BreakpointIDList valid_bp_ids; CommandObjectMultiwordBreakpoint::VerifyBreakpointOrLocationIDs( - command, target, result, &valid_bp_ids, + command, &target, result, &valid_bp_ids, BreakpointName::Permissions::PermissionKinds::disablePerm); if (result.Succeeded()) { @@ -1218,7 +1045,7 @@ protected: if (cur_bp_id.GetBreakpointID() != LLDB_INVALID_BREAK_ID) { Breakpoint *breakpoint = - target->GetBreakpointByID(cur_bp_id.GetBreakpointID()).get(); + target.GetBreakpointByID(cur_bp_id.GetBreakpointID()).get(); if (cur_bp_id.GetLocationID() != LLDB_INVALID_BREAK_ID) { BreakpointLocation *location = breakpoint->FindLocationByID(cur_bp_id.GetLocationID()).get(); @@ -1245,12 +1072,8 @@ protected: // CommandObjectBreakpointList #pragma mark List::CommandOptions -static constexpr OptionDefinition g_breakpoint_list_options[] = { - // FIXME: We need to add an "internal" command, and then add this sort of - // thing to it. But I need to see it for now, and don't want to wait. #define LLDB_OPTIONS_breakpoint_list #include "CommandOptions.inc" -}; #pragma mark List @@ -1311,9 +1134,7 @@ public: m_internal = true; break; default: - error.SetErrorStringWithFormat("unrecognized option '%c'", - short_option); - break; + llvm_unreachable("Unimplemented option"); } return error; @@ -1339,18 +1160,12 @@ public: protected: bool DoExecute(Args &command, CommandReturnObject &result) override { - Target *target = GetSelectedOrDummyTarget(m_options.m_use_dummy); - - if (target == nullptr) { - result.AppendError("Invalid target. No current target or breakpoints."); - result.SetStatus(eReturnStatusSuccessFinishNoResult); - return true; - } + Target &target = GetSelectedOrDummyTarget(m_options.m_use_dummy); const BreakpointList &breakpoints = - target->GetBreakpointList(m_options.m_internal); + target.GetBreakpointList(m_options.m_internal); std::unique_lock<std::recursive_mutex> lock; - target->GetBreakpointList(m_options.m_internal).GetListMutex(lock); + target.GetBreakpointList(m_options.m_internal).GetListMutex(lock); size_t num_breakpoints = breakpoints.GetSize(); @@ -1376,14 +1191,14 @@ protected: // Particular breakpoints selected; show info about that breakpoint. BreakpointIDList valid_bp_ids; CommandObjectMultiwordBreakpoint::VerifyBreakpointOrLocationIDs( - command, target, result, &valid_bp_ids, + command, &target, result, &valid_bp_ids, BreakpointName::Permissions::PermissionKinds::listPerm); if (result.Succeeded()) { for (size_t i = 0; i < valid_bp_ids.GetSize(); ++i) { BreakpointID cur_bp_id = valid_bp_ids.GetBreakpointIDAtIndex(i); Breakpoint *breakpoint = - target->GetBreakpointByID(cur_bp_id.GetBreakpointID()).get(); + target.GetBreakpointByID(cur_bp_id.GetBreakpointID()).get(); AddBreakpointDescription(&output_stream, breakpoint, m_options.m_level); } @@ -1404,12 +1219,8 @@ private: // CommandObjectBreakpointClear #pragma mark Clear::CommandOptions -static constexpr OptionDefinition g_breakpoint_clear_options[] = { - // clang-format off - { LLDB_OPT_SET_1, false, "file", 'f', OptionParser::eRequiredArgument, nullptr, {}, CommandCompletions::eSourceFileCompletion, eArgTypeFilename, "Specify the breakpoint by source location in this particular file." }, - { LLDB_OPT_SET_1, true, "line", 'l', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeLineNum, "Specify the breakpoint by source location at this particular line." } - // clang-format on -}; +#define LLDB_OPTIONS_breakpoint_clear +#include "CommandOptions.inc" #pragma mark Clear @@ -1449,9 +1260,7 @@ public: break; default: - error.SetErrorStringWithFormat("unrecognized option '%c'", - short_option); - break; + llvm_unreachable("Unimplemented option"); } return error; @@ -1474,12 +1283,7 @@ public: protected: bool DoExecute(Args &command, CommandReturnObject &result) override { - Target *target = GetSelectedOrDummyTarget(); - if (target == nullptr) { - result.AppendError("Invalid target. No existing target or breakpoints."); - result.SetStatus(eReturnStatusFailed); - return false; - } + Target &target = GetSelectedOrDummyTarget(); // The following are the various types of breakpoints that could be // cleared: @@ -1491,9 +1295,9 @@ protected: break_type = eClearTypeFileAndLine; std::unique_lock<std::recursive_mutex> lock; - target->GetBreakpointList().GetListMutex(lock); + target.GetBreakpointList().GetListMutex(lock); - BreakpointList &breakpoints = target->GetBreakpointList(); + BreakpointList &breakpoints = target.GetBreakpointList(); size_t num_breakpoints = breakpoints.GetSize(); // Early return if there's no breakpoint at all. @@ -1527,7 +1331,7 @@ protected: if (loc_coll.GetSize() == 0) { bp->GetDescription(&ss, lldb::eDescriptionLevelBrief); ss.EOL(); - target->RemoveBreakpointByID(bp->GetID()); + target.RemoveBreakpointByID(bp->GetID()); ++num_cleared; } } @@ -1557,12 +1361,8 @@ private: }; // CommandObjectBreakpointDelete -static constexpr OptionDefinition g_breakpoint_delete_options[] = { - // clang-format off - { LLDB_OPT_SET_1, false, "force", 'f', OptionParser::eNoArgument, nullptr, {}, 0, eArgTypeNone, "Delete all breakpoints without querying for confirmation." }, - { LLDB_OPT_SET_1, false, "dummy-breakpoints", 'D', OptionParser::eNoArgument, nullptr, {}, 0, eArgTypeNone, "Delete Dummy breakpoints - i.e. breakpoints set before a file is provided, which prime new targets." }, - // clang-format on -}; +#define LLDB_OPTIONS_breakpoint_delete +#include "CommandOptions.inc" #pragma mark Delete @@ -1607,9 +1407,7 @@ public: break; default: - error.SetErrorStringWithFormat("unrecognized option '%c'", - short_option); - break; + llvm_unreachable("Unimplemented option"); } return error; @@ -1631,18 +1429,12 @@ public: protected: bool DoExecute(Args &command, CommandReturnObject &result) override { - Target *target = GetSelectedOrDummyTarget(m_options.m_use_dummy); - - if (target == nullptr) { - result.AppendError("Invalid target. No existing target or breakpoints."); - result.SetStatus(eReturnStatusFailed); - return false; - } + Target &target = GetSelectedOrDummyTarget(m_options.m_use_dummy); std::unique_lock<std::recursive_mutex> lock; - target->GetBreakpointList().GetListMutex(lock); + target.GetBreakpointList().GetListMutex(lock); - const BreakpointList &breakpoints = target->GetBreakpointList(); + const BreakpointList &breakpoints = target.GetBreakpointList(); size_t num_breakpoints = breakpoints.GetSize(); @@ -1659,7 +1451,7 @@ protected: true)) { result.AppendMessage("Operation cancelled..."); } else { - target->RemoveAllowedBreakpoints(); + target.RemoveAllowedBreakpoints(); result.AppendMessageWithFormat( "All breakpoints removed. (%" PRIu64 " breakpoint%s)\n", (uint64_t)num_breakpoints, num_breakpoints > 1 ? "s" : ""); @@ -1669,7 +1461,7 @@ protected: // Particular breakpoint selected; disable that breakpoint. BreakpointIDList valid_bp_ids; CommandObjectMultiwordBreakpoint::VerifyBreakpointOrLocationIDs( - command, target, result, &valid_bp_ids, + command, &target, result, &valid_bp_ids, BreakpointName::Permissions::PermissionKinds::deletePerm); if (result.Succeeded()) { @@ -1682,7 +1474,7 @@ protected: if (cur_bp_id.GetBreakpointID() != LLDB_INVALID_BREAK_ID) { if (cur_bp_id.GetLocationID() != LLDB_INVALID_BREAK_ID) { Breakpoint *breakpoint = - target->GetBreakpointByID(cur_bp_id.GetBreakpointID()).get(); + target.GetBreakpointByID(cur_bp_id.GetBreakpointID()).get(); BreakpointLocation *location = breakpoint->FindLocationByID(cur_bp_id.GetLocationID()).get(); // It makes no sense to try to delete individual locations, so we @@ -1692,7 +1484,7 @@ protected: ++disable_count; } } else { - target->RemoveBreakpointByID(cur_bp_id.GetBreakpointID()); + target.RemoveBreakpointByID(cur_bp_id.GetBreakpointID()); ++delete_count; } } @@ -1711,15 +1503,9 @@ private: }; // CommandObjectBreakpointName +#define LLDB_OPTIONS_breakpoint_name +#include "CommandOptions.inc" -static constexpr OptionDefinition g_breakpoint_name_options[] = { - // clang-format off - {LLDB_OPT_SET_1, false, "name", 'N', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeBreakpointName, "Specifies a breakpoint name to use."}, - {LLDB_OPT_SET_2, false, "breakpoint-id", 'B', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeBreakpointID, "Specify a breakpoint ID to use."}, - {LLDB_OPT_SET_3, false, "dummy-breakpoints", 'D', OptionParser::eNoArgument, nullptr, {}, 0, eArgTypeNone, "Operate on Dummy breakpoints - i.e. breakpoints set before a file is provided, which prime new targets."}, - {LLDB_OPT_SET_4, false, "help-string", 'H', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeNone, "A help string describing the purpose of this name."}, - // clang-format on -}; class BreakpointNameOptionGroup : public OptionGroup { public: BreakpointNameOptionGroup() @@ -1760,9 +1546,7 @@ public: break; default: - error.SetErrorStringWithFormat("unrecognized short option '%c'", - short_option); - break; + llvm_unreachable("Unimplemented option"); } return error; } @@ -1781,13 +1565,8 @@ public: OptionValueString m_help_string; }; -static constexpr OptionDefinition g_breakpoint_access_options[] = { - // clang-format off - {LLDB_OPT_SET_1, false, "allow-list", 'L', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeBoolean, "Determines whether the breakpoint will show up in break list if not referred to explicitly."}, - {LLDB_OPT_SET_2, false, "allow-disable", 'A', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeBoolean, "Determines whether the breakpoint can be disabled by name or when all breakpoints are disabled."}, - {LLDB_OPT_SET_3, false, "allow-delete", 'D', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeBoolean, "Determines whether the breakpoint can be deleted by name or when all breakpoints are deleted."}, - // clang-format on -}; +#define LLDB_OPTIONS_breakpoint_access +#include "CommandOptions.inc" class BreakpointAccessOptionGroup : public OptionGroup { public: @@ -1835,7 +1614,8 @@ public: "invalid boolean value '%s' passed for -L option", option_arg.str().c_str()); } break; - + default: + llvm_unreachable("Unimplemented option"); } return error; @@ -1897,23 +1677,16 @@ protected: result.SetStatus(eReturnStatusFailed); return false; } - - Target *target = - GetSelectedOrDummyTarget(false); - if (target == nullptr) { - result.AppendError("Invalid target. No existing target or breakpoints."); - result.SetStatus(eReturnStatusFailed); - return false; - } + Target &target = GetSelectedOrDummyTarget(false); std::unique_lock<std::recursive_mutex> lock; - target->GetBreakpointList().GetListMutex(lock); + target.GetBreakpointList().GetListMutex(lock); // Make a pass through first to see that all the names are legal. for (auto &entry : command.entries()) { Status error; - if (!BreakpointID::StringIsBreakpointName(entry.ref, error)) + if (!BreakpointID::StringIsBreakpointName(entry.ref(), error)) { result.AppendErrorWithFormat("Invalid breakpoint name: %s - %s", entry.c_str(), error.AsCString()); @@ -1927,7 +1700,7 @@ protected: if (m_bp_id.m_breakpoint.OptionWasSet()) { lldb::break_id_t bp_id = m_bp_id.m_breakpoint.GetUInt64Value(); - bp_sp = target->GetBreakpointByID(bp_id); + bp_sp = target.GetBreakpointByID(bp_id); if (!bp_sp) { result.AppendErrorWithFormatv("Could not find specified breakpoint {0}", @@ -1940,18 +1713,17 @@ protected: Status error; for (auto &entry : command.entries()) { ConstString name(entry.c_str()); - BreakpointName *bp_name = target->FindBreakpointName(name, true, error); + BreakpointName *bp_name = target.FindBreakpointName(name, true, error); if (!bp_name) continue; if (m_bp_id.m_help_string.OptionWasSet()) bp_name->SetHelp(m_bp_id.m_help_string.GetStringValue().str().c_str()); if (bp_sp) - target->ConfigureBreakpointName(*bp_name, - *bp_sp->GetOptions(), + target.ConfigureBreakpointName(*bp_name, *bp_sp->GetOptions(), m_access_options.GetPermissions()); else - target->ConfigureBreakpointName(*bp_name, + target.ConfigureBreakpointName(*bp_name, m_bp_opts.GetBreakpointOptions(), m_access_options.GetPermissions()); } @@ -1996,19 +1768,13 @@ protected: return false; } - Target *target = + Target &target = GetSelectedOrDummyTarget(m_name_options.m_use_dummy.GetCurrentValue()); - if (target == nullptr) { - result.AppendError("Invalid target. No existing target or breakpoints."); - result.SetStatus(eReturnStatusFailed); - return false; - } - std::unique_lock<std::recursive_mutex> lock; - target->GetBreakpointList().GetListMutex(lock); + target.GetBreakpointList().GetListMutex(lock); - const BreakpointList &breakpoints = target->GetBreakpointList(); + const BreakpointList &breakpoints = target.GetBreakpointList(); size_t num_breakpoints = breakpoints.GetSize(); if (num_breakpoints == 0) { @@ -2020,7 +1786,7 @@ protected: // Particular breakpoint selected; disable that breakpoint. BreakpointIDList valid_bp_ids; CommandObjectMultiwordBreakpoint::VerifyBreakpointIDs( - command, target, result, &valid_bp_ids, + command, &target, result, &valid_bp_ids, BreakpointName::Permissions::PermissionKinds::listPerm); if (result.Succeeded()) { @@ -2037,7 +1803,7 @@ protected: lldb::break_id_t bp_id = valid_bp_ids.GetBreakpointIDAtIndex(index).GetBreakpointID(); BreakpointSP bp_sp = breakpoints.FindBreakpointByID(bp_id); - target->AddNameToBreakpoint(bp_sp, bp_name, error); + target.AddNameToBreakpoint(bp_sp, bp_name, error); } } @@ -2081,19 +1847,13 @@ protected: return false; } - Target *target = + Target &target = GetSelectedOrDummyTarget(m_name_options.m_use_dummy.GetCurrentValue()); - if (target == nullptr) { - result.AppendError("Invalid target. No existing target or breakpoints."); - result.SetStatus(eReturnStatusFailed); - return false; - } - std::unique_lock<std::recursive_mutex> lock; - target->GetBreakpointList().GetListMutex(lock); + target.GetBreakpointList().GetListMutex(lock); - const BreakpointList &breakpoints = target->GetBreakpointList(); + const BreakpointList &breakpoints = target.GetBreakpointList(); size_t num_breakpoints = breakpoints.GetSize(); if (num_breakpoints == 0) { @@ -2105,7 +1865,7 @@ protected: // Particular breakpoint selected; disable that breakpoint. BreakpointIDList valid_bp_ids; CommandObjectMultiwordBreakpoint::VerifyBreakpointIDs( - command, target, result, &valid_bp_ids, + command, &target, result, &valid_bp_ids, BreakpointName::Permissions::PermissionKinds::deletePerm); if (result.Succeeded()) { @@ -2120,7 +1880,7 @@ protected: lldb::break_id_t bp_id = valid_bp_ids.GetBreakpointIDAtIndex(index).GetBreakpointID(); BreakpointSP bp_sp = breakpoints.FindBreakpointByID(bp_id); - target->RemoveNameFromBreakpoint(bp_sp, bp_name); + target.RemoveNameFromBreakpoint(bp_sp, bp_name); } } @@ -2151,19 +1911,12 @@ public: protected: bool DoExecute(Args &command, CommandReturnObject &result) override { - Target *target = + Target &target = GetSelectedOrDummyTarget(m_name_options.m_use_dummy.GetCurrentValue()); - if (target == nullptr) { - result.AppendError("Invalid target. No existing target or breakpoints."); - result.SetStatus(eReturnStatusFailed); - return false; - } - - std::vector<std::string> name_list; if (command.empty()) { - target->GetBreakpointNames(name_list); + target.GetBreakpointNames(name_list); } else { for (const Args::ArgEntry &arg : command) { @@ -2178,9 +1931,8 @@ protected: const char *name = name_str.c_str(); // First print out the options for the name: Status error; - BreakpointName *bp_name = target->FindBreakpointName(ConstString(name), - false, - error); + BreakpointName *bp_name = + target.FindBreakpointName(ConstString(name), false, error); if (bp_name) { StreamString s; @@ -2191,9 +1943,9 @@ protected: } std::unique_lock<std::recursive_mutex> lock; - target->GetBreakpointList().GetListMutex(lock); + target.GetBreakpointList().GetListMutex(lock); - BreakpointList &breakpoints = target->GetBreakpointList(); + BreakpointList &breakpoints = target.GetBreakpointList(); bool any_set = false; for (BreakpointSP bp_sp : breakpoints.Breakpoints()) { if (bp_sp->MatchesName(name)) { @@ -2246,12 +1998,8 @@ public: // CommandObjectBreakpointRead #pragma mark Read::CommandOptions -static constexpr OptionDefinition g_breakpoint_read_options[] = { - // clang-format off - {LLDB_OPT_SET_ALL, true, "file", 'f', OptionParser::eRequiredArgument, nullptr, {}, CommandCompletions::eDiskFileCompletion, eArgTypeFilename, "The file from which to read the breakpoints." }, - {LLDB_OPT_SET_ALL, false, "breakpoint-name", 'N', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeBreakpointName, "Only read in breakpoints with this name."}, - // clang-format on -}; +#define LLDB_OPTIONS_breakpoint_read +#include "CommandOptions.inc" #pragma mark Read @@ -2301,9 +2049,7 @@ public: break; } default: - error.SetErrorStringWithFormat("unrecognized option '%c'", - short_option); - break; + llvm_unreachable("Unimplemented option"); } return error; @@ -2326,21 +2072,16 @@ public: protected: bool DoExecute(Args &command, CommandReturnObject &result) override { - Target *target = GetSelectedOrDummyTarget(); - if (target == nullptr) { - result.AppendError("Invalid target. No existing target or breakpoints."); - result.SetStatus(eReturnStatusFailed); - return false; - } + Target &target = GetSelectedOrDummyTarget(); std::unique_lock<std::recursive_mutex> lock; - target->GetBreakpointList().GetListMutex(lock); + target.GetBreakpointList().GetListMutex(lock); FileSpec input_spec(m_options.m_filename); FileSystem::Instance().Resolve(input_spec); BreakpointIDList new_bps; - Status error = target->CreateBreakpointsFromFile( - input_spec, m_options.m_names, new_bps); + Status error = target.CreateBreakpointsFromFile(input_spec, + m_options.m_names, new_bps); if (!error.Success()) { result.AppendError(error.AsCString()); @@ -2358,7 +2099,7 @@ protected: result.AppendMessage("New breakpoints:"); for (size_t i = 0; i < num_breakpoints; ++i) { BreakpointID bp_id = new_bps.GetBreakpointIDAtIndex(i); - Breakpoint *bp = target->GetBreakpointList() + Breakpoint *bp = target.GetBreakpointList() .FindBreakpointByID(bp_id.GetBreakpointID()) .get(); if (bp) @@ -2375,12 +2116,8 @@ private: // CommandObjectBreakpointWrite #pragma mark Write::CommandOptions -static constexpr OptionDefinition g_breakpoint_write_options[] = { - // clang-format off - { LLDB_OPT_SET_ALL, true, "file", 'f', OptionParser::eRequiredArgument, nullptr, {}, CommandCompletions::eDiskFileCompletion, eArgTypeFilename, "The file into which to write the breakpoints." }, - { LLDB_OPT_SET_ALL, false, "append",'a', OptionParser::eNoArgument, nullptr, {}, 0, eArgTypeNone, "Append to saved breakpoints file if it exists."}, - // clang-format on -}; +#define LLDB_OPTIONS_breakpoint_write +#include "CommandOptions.inc" #pragma mark Write class CommandObjectBreakpointWrite : public CommandObjectParsed { @@ -2423,9 +2160,7 @@ public: m_append = true; break; default: - error.SetErrorStringWithFormat("unrecognized option '%c'", - short_option); - break; + llvm_unreachable("Unimplemented option"); } return error; @@ -2448,20 +2183,15 @@ public: protected: bool DoExecute(Args &command, CommandReturnObject &result) override { - Target *target = GetSelectedOrDummyTarget(); - if (target == nullptr) { - result.AppendError("Invalid target. No existing target or breakpoints."); - result.SetStatus(eReturnStatusFailed); - return false; - } + Target &target = GetSelectedOrDummyTarget(); std::unique_lock<std::recursive_mutex> lock; - target->GetBreakpointList().GetListMutex(lock); + target.GetBreakpointList().GetListMutex(lock); BreakpointIDList valid_bp_ids; if (!command.empty()) { CommandObjectMultiwordBreakpoint::VerifyBreakpointIDs( - command, target, result, &valid_bp_ids, + command, &target, result, &valid_bp_ids, BreakpointName::Permissions::PermissionKinds::listPerm); if (!result.Succeeded()) { @@ -2471,8 +2201,8 @@ protected: } FileSpec file_spec(m_options.m_filename); FileSystem::Instance().Resolve(file_spec); - Status error = target->SerializeBreakpointsToFile(file_spec, valid_bp_ids, - m_options.m_append); + Status error = target.SerializeBreakpointsToFile(file_spec, valid_bp_ids, + m_options.m_append); if (!error.Success()) { result.AppendErrorWithFormat("error serializing breakpoints: %s.", error.AsCString()); diff --git a/source/Commands/CommandObjectBreakpointCommand.cpp b/source/Commands/CommandObjectBreakpointCommand.cpp index 3f9d83cd86a8..a6bcd1d8dc32 100644 --- a/source/Commands/CommandObjectBreakpointCommand.cpp +++ b/source/Commands/CommandObjectBreakpointCommand.cpp @@ -26,33 +26,33 @@ using namespace lldb; using namespace lldb_private; -// CommandObjectBreakpointCommandAdd - // FIXME: "script-type" needs to have its contents determined dynamically, so -// somebody can add a new scripting -// language to lldb and have it pickable here without having to change this -// enumeration by hand and rebuild lldb proper. - +// somebody can add a new scripting language to lldb and have it pickable here +// without having to change this enumeration by hand and rebuild lldb proper. static constexpr OptionEnumValueElement g_script_option_enumeration[] = { - {eScriptLanguageNone, "command", - "Commands are in the lldb command interpreter language"}, - {eScriptLanguagePython, "python", "Commands are in the Python language."}, - {eSortOrderByName, "default-script", - "Commands are in the default scripting language."} }; + { + eScriptLanguageNone, + "command", + "Commands are in the lldb command interpreter language", + }, + { + eScriptLanguagePython, + "python", + "Commands are in the Python language.", + }, + { + eSortOrderByName, + "default-script", + "Commands are in the default scripting language.", + }, +}; static constexpr OptionEnumValues ScriptOptionEnum() { return OptionEnumValues(g_script_option_enumeration); } -static constexpr OptionDefinition g_breakpoint_add_options[] = { - // clang-format off - { LLDB_OPT_SET_1, false, "one-liner", 'o', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeOneLiner, "Specify a one-line breakpoint command inline. Be sure to surround it with quotes." }, - { LLDB_OPT_SET_ALL, false, "stop-on-error", 'e', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeBoolean, "Specify whether breakpoint command execution should terminate on error." }, - { LLDB_OPT_SET_ALL, false, "script-type", 's', OptionParser::eRequiredArgument, nullptr, ScriptOptionEnum(), 0, eArgTypeNone, "Specify the language for the commands - if none is specified, the lldb command interpreter will be used." }, - { LLDB_OPT_SET_2, false, "python-function", 'F', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypePythonFunction, "Give the name of a Python function to run as command for this breakpoint. Be sure to give a module name if appropriate." }, - { LLDB_OPT_SET_ALL, false, "dummy-breakpoints", 'D', OptionParser::eNoArgument, nullptr, {}, 0, eArgTypeNone, "Sets Dummy breakpoints - i.e. breakpoints set before a file is provided, which prime new targets." }, - // clang-format on -}; +#define LLDB_OPTIONS_breakpoint_command_add +#include "CommandOptions.inc" class CommandObjectBreakpointCommandAdd : public CommandObjectParsed, public IOHandlerDelegateMultiline { @@ -221,7 +221,7 @@ are no syntax errors may indicate that a function was declared but never called. Options *GetOptions() override { return &m_options; } void IOHandlerActivated(IOHandler &io_handler, bool interactive) override { - StreamFileSP output_sp(io_handler.GetOutputStreamFile()); + StreamFileSP output_sp(io_handler.GetOutputStreamFileSP()); if (output_sp && interactive) { output_sp->PutCString(g_reader_instructions); output_sp->Flush(); @@ -238,7 +238,7 @@ are no syntax errors may indicate that a function was declared but never called. if (!bp_options) continue; - auto cmd_data = llvm::make_unique<BreakpointOptions::CommandData>(); + auto cmd_data = std::make_unique<BreakpointOptions::CommandData>(); cmd_data->user_source.SplitIntoLines(line.c_str(), line.size()); bp_options->SetCommandDataCallback(cmd_data); } @@ -260,7 +260,7 @@ are no syntax errors may indicate that a function was declared but never called. SetBreakpointCommandCallback(std::vector<BreakpointOptions *> &bp_options_vec, const char *oneliner) { for (auto bp_options : bp_options_vec) { - auto cmd_data = llvm::make_unique<BreakpointOptions::CommandData>(); + auto cmd_data = std::make_unique<BreakpointOptions::CommandData>(); cmd_data->user_source.AppendString(oneliner); cmd_data->stop_on_error = m_options.m_stop_on_error; @@ -291,7 +291,8 @@ are no syntax errors may indicate that a function was declared but never called. case 's': m_script_language = (lldb::ScriptLanguage)OptionArgParser::ToOptionEnum( - option_arg, g_breakpoint_add_options[option_idx].enum_values, + option_arg, + g_breakpoint_command_add_options[option_idx].enum_values, eScriptLanguageNone, error); if (m_script_language == eScriptLanguagePython || @@ -323,7 +324,7 @@ are no syntax errors may indicate that a function was declared but never called. break; default: - break; + llvm_unreachable("Unimplemented option"); } return error; } @@ -341,7 +342,7 @@ are no syntax errors may indicate that a function was declared but never called. } llvm::ArrayRef<OptionDefinition> GetDefinitions() override { - return llvm::makeArrayRef(g_breakpoint_add_options); + return llvm::makeArrayRef(g_breakpoint_command_add_options); } // Instance variables to hold the values for command options. @@ -360,16 +361,9 @@ are no syntax errors may indicate that a function was declared but never called. protected: bool DoExecute(Args &command, CommandReturnObject &result) override { - Target *target = GetSelectedOrDummyTarget(m_options.m_use_dummy); + Target &target = GetSelectedOrDummyTarget(m_options.m_use_dummy); - if (target == nullptr) { - result.AppendError("There is not a current executable; there are no " - "breakpoints to which to add commands"); - result.SetStatus(eReturnStatusFailed); - return false; - } - - const BreakpointList &breakpoints = target->GetBreakpointList(); + const BreakpointList &breakpoints = target.GetBreakpointList(); size_t num_breakpoints = breakpoints.GetSize(); if (num_breakpoints == 0) { @@ -388,7 +382,7 @@ protected: BreakpointIDList valid_bp_ids; CommandObjectMultiwordBreakpoint::VerifyBreakpointOrLocationIDs( - command, target, result, &valid_bp_ids, + command, &target, result, &valid_bp_ids, BreakpointName::Permissions::PermissionKinds::listPerm); m_bp_options_vec.clear(); @@ -400,7 +394,7 @@ protected: BreakpointID cur_bp_id = valid_bp_ids.GetBreakpointIDAtIndex(i); if (cur_bp_id.GetBreakpointID() != LLDB_INVALID_BREAK_ID) { Breakpoint *bp = - target->GetBreakpointByID(cur_bp_id.GetBreakpointID()).get(); + target.GetBreakpointByID(cur_bp_id.GetBreakpointID()).get(); BreakpointOptions *bp_options = nullptr; if (cur_bp_id.GetLocationID() == LLDB_INVALID_BREAK_ID) { // This breakpoint does not have an associated location. @@ -469,11 +463,8 @@ const char *CommandObjectBreakpointCommandAdd::g_reader_instructions = // CommandObjectBreakpointCommandDelete -static constexpr OptionDefinition g_breakpoint_delete_options[] = { - // clang-format off - { LLDB_OPT_SET_1, false, "dummy-breakpoints", 'D', OptionParser::eNoArgument, nullptr, {}, 0, eArgTypeNone, "Delete commands from Dummy breakpoints - i.e. breakpoints set before a file is provided, which prime new targets." }, - // clang-format on -}; +#define LLDB_OPTIONS_breakpoint_command_delete +#include "CommandOptions.inc" class CommandObjectBreakpointCommandDelete : public CommandObjectParsed { public: @@ -518,9 +509,7 @@ public: break; default: - error.SetErrorStringWithFormat("unrecognized option '%c'", - short_option); - break; + llvm_unreachable("Unimplemented option"); } return error; @@ -531,7 +520,7 @@ public: } llvm::ArrayRef<OptionDefinition> GetDefinitions() override { - return llvm::makeArrayRef(g_breakpoint_delete_options); + return llvm::makeArrayRef(g_breakpoint_command_delete_options); } // Instance variables to hold the values for command options. @@ -540,16 +529,9 @@ public: protected: bool DoExecute(Args &command, CommandReturnObject &result) override { - Target *target = GetSelectedOrDummyTarget(m_options.m_use_dummy); - - if (target == nullptr) { - result.AppendError("There is not a current executable; there are no " - "breakpoints from which to delete commands"); - result.SetStatus(eReturnStatusFailed); - return false; - } + Target &target = GetSelectedOrDummyTarget(m_options.m_use_dummy); - const BreakpointList &breakpoints = target->GetBreakpointList(); + const BreakpointList &breakpoints = target.GetBreakpointList(); size_t num_breakpoints = breakpoints.GetSize(); if (num_breakpoints == 0) { @@ -567,7 +549,7 @@ protected: BreakpointIDList valid_bp_ids; CommandObjectMultiwordBreakpoint::VerifyBreakpointOrLocationIDs( - command, target, result, &valid_bp_ids, + command, &target, result, &valid_bp_ids, BreakpointName::Permissions::PermissionKinds::listPerm); if (result.Succeeded()) { @@ -576,7 +558,7 @@ protected: BreakpointID cur_bp_id = valid_bp_ids.GetBreakpointIDAtIndex(i); if (cur_bp_id.GetBreakpointID() != LLDB_INVALID_BREAK_ID) { Breakpoint *bp = - target->GetBreakpointByID(cur_bp_id.GetBreakpointID()).get(); + target.GetBreakpointByID(cur_bp_id.GetBreakpointID()).get(); if (cur_bp_id.GetLocationID() != LLDB_INVALID_BREAK_ID) { BreakpointLocationSP bp_loc_sp( bp->FindLocationByID(cur_bp_id.GetLocationID())); @@ -607,10 +589,10 @@ private: class CommandObjectBreakpointCommandList : public CommandObjectParsed { public: CommandObjectBreakpointCommandList(CommandInterpreter &interpreter) - : CommandObjectParsed(interpreter, "list", "List the script or set of " - "commands to be executed when " - "the breakpoint is hit.", - nullptr) { + : CommandObjectParsed(interpreter, "list", + "List the script or set of commands to be " + "executed when the breakpoint is hit.", + nullptr, eCommandRequiresTarget) { CommandArgumentEntry arg; CommandArgumentData bp_id_arg; @@ -630,14 +612,7 @@ public: protected: bool DoExecute(Args &command, CommandReturnObject &result) override { - Target *target = GetDebugger().GetSelectedTarget().get(); - - if (target == nullptr) { - result.AppendError("There is not a current executable; there are no " - "breakpoints for which to list commands"); - result.SetStatus(eReturnStatusFailed); - return false; - } + Target *target = &GetSelectedTarget(); const BreakpointList &breakpoints = target->GetBreakpointList(); size_t num_breakpoints = breakpoints.GetSize(); @@ -657,7 +632,7 @@ protected: BreakpointIDList valid_bp_ids; CommandObjectMultiwordBreakpoint::VerifyBreakpointOrLocationIDs( - command, target, result, &valid_bp_ids, + command, target, result, &valid_bp_ids, BreakpointName::Permissions::PermissionKinds::listPerm); if (result.Succeeded()) { diff --git a/source/Commands/CommandObjectBugreport.cpp b/source/Commands/CommandObjectBugreport.cpp deleted file mode 100644 index 515cc9a113b1..000000000000 --- a/source/Commands/CommandObjectBugreport.cpp +++ /dev/null @@ -1,124 +0,0 @@ -//===-- CommandObjectBugreport.cpp ------------------------------*- C++ -*-===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// - -#include "CommandObjectBugreport.h" - -#include <cstdio> - - -#include "lldb/Interpreter/CommandInterpreter.h" -#include "lldb/Interpreter/CommandReturnObject.h" -#include "lldb/Interpreter/OptionGroupOutputFile.h" -#include "lldb/Target/Thread.h" - -using namespace lldb; -using namespace lldb_private; - -// "bugreport unwind" - -class CommandObjectBugreportUnwind : public CommandObjectParsed { -public: - CommandObjectBugreportUnwind(CommandInterpreter &interpreter) - : CommandObjectParsed( - interpreter, "bugreport unwind", - "Create a bugreport for a bug in the stack unwinding code.", - nullptr), - m_option_group(), m_outfile_options() { - m_option_group.Append(&m_outfile_options, LLDB_OPT_SET_ALL, - LLDB_OPT_SET_1 | LLDB_OPT_SET_2 | LLDB_OPT_SET_3); - m_option_group.Finalize(); - } - - ~CommandObjectBugreportUnwind() override {} - - Options *GetOptions() override { return &m_option_group; } - -protected: - bool DoExecute(Args &command, CommandReturnObject &result) override { - StringList commands; - commands.AppendString("thread backtrace"); - - Thread *thread = m_exe_ctx.GetThreadPtr(); - if (thread) { - char command_buffer[256]; - - uint32_t frame_count = thread->GetStackFrameCount(); - for (uint32_t i = 0; i < frame_count; ++i) { - StackFrameSP frame = thread->GetStackFrameAtIndex(i); - lldb::addr_t pc = frame->GetStackID().GetPC(); - - snprintf(command_buffer, sizeof(command_buffer), - "disassemble --bytes --address 0x%" PRIx64, pc); - commands.AppendString(command_buffer); - - snprintf(command_buffer, sizeof(command_buffer), - "image show-unwind --address 0x%" PRIx64, pc); - commands.AppendString(command_buffer); - } - } - - const FileSpec &outfile_spec = - m_outfile_options.GetFile().GetCurrentValue(); - if (outfile_spec) { - - uint32_t open_options = - File::eOpenOptionWrite | File::eOpenOptionCanCreate | - File::eOpenOptionAppend | File::eOpenOptionCloseOnExec; - - const bool append = m_outfile_options.GetAppend().GetCurrentValue(); - if (!append) - open_options |= File::eOpenOptionTruncate; - - StreamFileSP outfile_stream = std::make_shared<StreamFile>(); - File &file = outfile_stream->GetFile(); - Status error = - FileSystem::Instance().Open(file, outfile_spec, open_options); - if (error.Fail()) { - auto path = outfile_spec.GetPath(); - result.AppendErrorWithFormat("Failed to open file '%s' for %s: %s\n", - path.c_str(), append ? "append" : "write", - error.AsCString()); - result.SetStatus(eReturnStatusFailed); - return false; - } - - result.SetImmediateOutputStream(outfile_stream); - } - - CommandInterpreterRunOptions options; - options.SetStopOnError(false); - options.SetEchoCommands(true); - options.SetPrintResults(true); - options.SetPrintErrors(true); - options.SetAddToHistory(false); - m_interpreter.HandleCommands(commands, &m_exe_ctx, options, result); - - return result.Succeeded(); - } - -private: - OptionGroupOptions m_option_group; - OptionGroupOutputFile m_outfile_options; -}; - -#pragma mark CommandObjectMultiwordBugreport - -// CommandObjectMultiwordBugreport - -CommandObjectMultiwordBugreport::CommandObjectMultiwordBugreport( - CommandInterpreter &interpreter) - : CommandObjectMultiword( - interpreter, "bugreport", - "Commands for creating domain-specific bug reports.", - "bugreport <subcommand> [<subcommand-options>]") { - - LoadSubCommand( - "unwind", CommandObjectSP(new CommandObjectBugreportUnwind(interpreter))); -} - -CommandObjectMultiwordBugreport::~CommandObjectMultiwordBugreport() {} diff --git a/source/Commands/CommandObjectBugreport.h b/source/Commands/CommandObjectBugreport.h deleted file mode 100644 index 24ce6d237d56..000000000000 --- a/source/Commands/CommandObjectBugreport.h +++ /dev/null @@ -1,27 +0,0 @@ -//===-- CommandObjectBugreport.h --------------------------------*- C++ -*-===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// - -#ifndef liblldb_CommandObjectBugreport_h_ -#define liblldb_CommandObjectBugreport_h_ - -#include "lldb/Interpreter/CommandObjectMultiword.h" - -namespace lldb_private { - -// CommandObjectMultiwordBugreport - -class CommandObjectMultiwordBugreport : public CommandObjectMultiword { -public: - CommandObjectMultiwordBugreport(CommandInterpreter &interpreter); - - ~CommandObjectMultiwordBugreport() override; -}; - -} // namespace lldb_private - -#endif // liblldb_CommandObjectBugreport_h_ diff --git a/source/Commands/CommandObjectCommands.cpp b/source/Commands/CommandObjectCommands.cpp index 4092e76be6ac..259affbe6e0a 100644 --- a/source/Commands/CommandObjectCommands.cpp +++ b/source/Commands/CommandObjectCommands.cpp @@ -31,14 +31,8 @@ using namespace lldb_private; // CommandObjectCommandsSource -static constexpr OptionDefinition g_history_options[] = { - // clang-format off - { LLDB_OPT_SET_1, false, "count", 'c', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeUnsignedInteger, "How many history commands to print." }, - { LLDB_OPT_SET_1, false, "start-index", 's', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeUnsignedInteger, "Index at which to start printing history commands (or end to mean tail mode)." }, - { LLDB_OPT_SET_1, false, "end-index", 'e', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeUnsignedInteger, "Index at which to stop printing history commands." }, - { LLDB_OPT_SET_2, false, "clear", 'C', OptionParser::eNoArgument, nullptr, {}, 0, eArgTypeBoolean, "Clears the current command history." }, - // clang-format on -}; +#define LLDB_OPTIONS_history +#include "CommandOptions.inc" class CommandObjectCommandsHistory : public CommandObjectParsed { public: @@ -91,9 +85,7 @@ protected: m_clear.SetOptionWasSet(); break; default: - error.SetErrorStringWithFormat("unrecognized option '%c'", - short_option); - break; + llvm_unreachable("Unimplemented option"); } return error; @@ -188,13 +180,8 @@ protected: // CommandObjectCommandsSource -static constexpr OptionDefinition g_source_options[] = { - // clang-format off - { LLDB_OPT_SET_ALL, false, "stop-on-error", 'e', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeBoolean, "If true, stop executing commands on error." }, - { LLDB_OPT_SET_ALL, false, "stop-on-continue", 'c', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeBoolean, "If true, stop executing commands on continue." }, - { LLDB_OPT_SET_ALL, false, "silent-run", 's', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeBoolean, "If true don't echo commands while executing." }, - // clang-format on -}; +#define LLDB_OPTIONS_source +#include "CommandOptions.inc" class CommandObjectCommandsSource : public CommandObjectParsed { public: @@ -226,13 +213,12 @@ public: return ""; } - int HandleArgumentCompletion( - CompletionRequest &request, - OptionElementVector &opt_element_vector) override { + void + HandleArgumentCompletion(CompletionRequest &request, + OptionElementVector &opt_element_vector) override { CommandCompletions::InvokeCommonCompletionCallbacks( GetCommandInterpreter(), CommandCompletions::eDiskFileCompletion, request, nullptr); - return request.GetNumberOfMatches(); } Options *GetOptions() override { return &m_options; } @@ -265,9 +251,7 @@ protected: break; default: - error.SetErrorStringWithFormat("unrecognized option '%c'", - short_option); - break; + llvm_unreachable("Unimplemented option"); } return error; @@ -299,7 +283,7 @@ protected: return false; } - FileSpec cmd_file(command[0].ref); + FileSpec cmd_file(command[0].ref()); FileSystem::Instance().Resolve(cmd_file); ExecutionContext *exe_ctx = nullptr; // Just use the default context. @@ -343,12 +327,8 @@ protected: #pragma mark CommandObjectCommandsAlias // CommandObjectCommandsAlias -static constexpr OptionDefinition g_alias_options[] = { - // clang-format off - { LLDB_OPT_SET_ALL, false, "help", 'h', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeHelpText, "Help text for this command" }, - { LLDB_OPT_SET_ALL, false, "long-help", 'H', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeHelpText, "Long help text for this command" }, - // clang-format on -}; +#define LLDB_OPTIONS_alias +#include "CommandOptions.inc" static const char *g_python_command_instructions = "Enter your Python command(s). Type 'DONE' to end.\n" @@ -386,9 +366,7 @@ protected: break; default: - error.SetErrorStringWithFormat("invalid short option character '%c'", - short_option); - break; + llvm_unreachable("Unimplemented option"); } return error; @@ -568,7 +546,7 @@ protected: // Get the alias command. - auto alias_command = args[0].ref; + auto alias_command = args[0].ref(); if (alias_command.startswith("-")) { result.AppendError("aliases starting with a dash are not supported"); if (alias_command == "--help" || alias_command == "--long-help") { @@ -675,8 +653,8 @@ protected: } // Save these in std::strings since we're going to shift them off. - const std::string alias_command(args[0].ref); - const std::string actual_command(args[1].ref); + const std::string alias_command(args[0].ref()); + const std::string actual_command(args[1].ref()); args.Shift(); // Shift the alias command word off the argument vector. args.Shift(); // Shift the old command word off the argument vector. @@ -708,7 +686,7 @@ protected: OptionArgVectorSP(new OptionArgVector); while (cmd_obj->IsMultiwordObject() && !args.empty()) { - auto sub_command = args[0].ref; + auto sub_command = args[0].ref(); assert(!sub_command.empty()); subcommand_obj_sp = cmd_obj->GetSubcommandSP(sub_command); if (!subcommand_obj_sp) { @@ -802,7 +780,7 @@ protected: return false; } - auto command_name = args[0].ref; + auto command_name = args[0].ref(); cmd_obj = m_interpreter.GetCommandObject(command_name); if (!cmd_obj) { result.AppendErrorWithFormat( @@ -881,9 +859,10 @@ protected: "defined regular expression command names", GetCommandName().str().c_str()); result.SetStatus(eReturnStatusFailed); + return false; } - auto command_name = args[0].ref; + auto command_name = args[0].ref(); if (!m_interpreter.CommandExists(command_name)) { StreamString error_msg_stream; const bool generate_upropos = true; @@ -911,12 +890,8 @@ protected: // CommandObjectCommandsAddRegex -static constexpr OptionDefinition g_regex_options[] = { - // clang-format off - { LLDB_OPT_SET_1, false, "help" , 'h', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeNone, "The help text to display for this command." }, - { LLDB_OPT_SET_1, false, "syntax", 's', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeNone, "A syntax string showing the typical usage syntax." }, - // clang-format on -}; +#define LLDB_OPTIONS_regex +#include "CommandOptions.inc" #pragma mark CommandObjectCommandsAddRegex @@ -970,7 +945,7 @@ a number follows 'f':" protected: void IOHandlerActivated(IOHandler &io_handler, bool interactive) override { - StreamFileSP output_sp(io_handler.GetOutputStreamFile()); + StreamFileSP output_sp(io_handler.GetOutputStreamFileSP()); if (output_sp && interactive) { output_sp->PutCString("Enter one or more sed substitution commands in " "the form: 's/<regex>/<subst>/'.\nTerminate the " @@ -985,11 +960,9 @@ protected: if (m_regex_cmd_up) { StringList lines; if (lines.SplitIntoLines(data)) { - const size_t num_lines = lines.GetSize(); bool check_only = false; - for (size_t i = 0; i < num_lines; ++i) { - llvm::StringRef bytes_strref(lines[i]); - Status error = AppendRegexSubstitution(bytes_strref, check_only); + for (const std::string &line : lines) { + Status error = AppendRegexSubstitution(line, check_only); if (error.Fail()) { if (!GetDebugger().GetCommandInterpreter().GetBatchCommandMode()) { StreamSP out_stream = GetDebugger().GetAsyncOutputStream(); @@ -1015,8 +988,8 @@ protected: } Status error; - auto name = command[0].ref; - m_regex_cmd_up = llvm::make_unique<CommandObjectRegexCommand>( + auto name = command[0].ref(); + m_regex_cmd_up = std::make_unique<CommandObjectRegexCommand>( m_interpreter, name, m_options.GetHelp(), m_options.GetSyntax(), 10, 0, true); @@ -1040,7 +1013,7 @@ protected: } else { for (auto &entry : command.entries().drop_front()) { bool check_only = false; - error = AppendRegexSubstitution(entry.ref, check_only); + error = AppendRegexSubstitution(entry.ref(), check_only); if (error.Fail()) break; } @@ -1183,9 +1156,7 @@ private: m_syntax.assign(option_arg); break; default: - error.SetErrorStringWithFormat("unrecognized option '%c'", - short_option); - break; + llvm_unreachable("Unimplemented option"); } return error; @@ -1315,8 +1286,6 @@ public: bool IsRemovable() const override { return true; } - StructuredData::GenericSP GetImplementingObject() { return m_cmd_obj_sp; } - ScriptedCommandSynchronicity GetSynchronicity() { return m_synchro; } llvm::StringRef GetHelp() override { @@ -1385,12 +1354,8 @@ private: }; // CommandObjectCommandsScriptImport - -static constexpr OptionDefinition g_script_import_options[] = { - // clang-format off - { LLDB_OPT_SET_1, false, "allow-reload", 'r', OptionParser::eNoArgument, nullptr, {}, 0, eArgTypeNone, "Allow the script to be loaded even if it was already loaded before. This argument exists for backwards compatibility, but reloading is always allowed, whether you specify it or not." }, - // clang-format on -}; +#define LLDB_OPTIONS_script_import +#include "CommandOptions.inc" class CommandObjectCommandsScriptImport : public CommandObjectParsed { public: @@ -1415,13 +1380,12 @@ public: ~CommandObjectCommandsScriptImport() override = default; - int HandleArgumentCompletion( - CompletionRequest &request, - OptionElementVector &opt_element_vector) override { + void + HandleArgumentCompletion(CompletionRequest &request, + OptionElementVector &opt_element_vector) override { CommandCompletions::InvokeCommonCompletionCallbacks( GetCommandInterpreter(), CommandCompletions::eDiskFileCompletion, request, nullptr); - return request.GetNumberOfMatches(); } Options *GetOptions() override { return &m_options; } @@ -1443,9 +1407,7 @@ protected: m_allow_reload = true; break; default: - error.SetErrorStringWithFormat("unrecognized option '%c'", - short_option); - break; + llvm_unreachable("Unimplemented option"); } return error; @@ -1509,25 +1471,29 @@ protected: // CommandObjectCommandsScriptAdd static constexpr OptionEnumValueElement g_script_synchro_type[] = { - {eScriptedCommandSynchronicitySynchronous, "synchronous", - "Run synchronous"}, - {eScriptedCommandSynchronicityAsynchronous, "asynchronous", - "Run asynchronous"}, - {eScriptedCommandSynchronicityCurrentValue, "current", - "Do not alter current setting"} }; + { + eScriptedCommandSynchronicitySynchronous, + "synchronous", + "Run synchronous", + }, + { + eScriptedCommandSynchronicityAsynchronous, + "asynchronous", + "Run asynchronous", + }, + { + eScriptedCommandSynchronicityCurrentValue, + "current", + "Do not alter current setting", + }, +}; static constexpr OptionEnumValues ScriptSynchroType() { return OptionEnumValues(g_script_synchro_type); } -static constexpr OptionDefinition g_script_add_options[] = { - // clang-format off - { LLDB_OPT_SET_1, false, "function", 'f', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypePythonFunction, "Name of the Python function to bind to this command name." }, - { LLDB_OPT_SET_2, false, "class", 'c', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypePythonClass, "Name of the Python class to bind to this command name." }, - { LLDB_OPT_SET_1, false, "help" , 'h', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeHelpText, "The help text to display for this command." }, - { LLDB_OPT_SET_ALL, false, "synchronicity", 's', OptionParser::eRequiredArgument, nullptr, ScriptSynchroType(), 0, eArgTypeScriptedCommandSynchronicity, "Set the synchronicity of this command's executions with regard to LLDB event system." }, - // clang-format on -}; +#define LLDB_OPTIONS_script_add +#include "CommandOptions.inc" class CommandObjectCommandsScriptAdd : public CommandObjectParsed, public IOHandlerDelegateMultiline { @@ -1593,9 +1559,7 @@ protected: option_arg.str().c_str()); break; default: - error.SetErrorStringWithFormat("unrecognized option '%c'", - short_option); - break; + llvm_unreachable("Unimplemented option"); } return error; @@ -1621,7 +1585,7 @@ protected: }; void IOHandlerActivated(IOHandler &io_handler, bool interactive) override { - StreamFileSP output_sp(io_handler.GetOutputStreamFile()); + StreamFileSP output_sp(io_handler.GetOutputStreamFileSP()); if (output_sp && interactive) { output_sp->PutCString(g_python_command_instructions); output_sp->Flush(); @@ -1630,7 +1594,7 @@ protected: void IOHandlerInputComplete(IOHandler &io_handler, std::string &data) override { - StreamFileSP error_sp = io_handler.GetErrorStreamFile(); + StreamFileSP error_sp = io_handler.GetErrorStreamFileSP(); ScriptInterpreter *interpreter = GetDebugger().GetScriptInterpreter(); if (interpreter) { @@ -1692,7 +1656,7 @@ protected: } // Store the options in case we get multi-line input - m_cmd_name = command[0].ref; + m_cmd_name = command[0].ref(); m_short_help.assign(m_options.m_short_help); m_synchronicity = m_options.m_synchronicity; @@ -1761,6 +1725,12 @@ public: ~CommandObjectCommandsScriptList() override = default; bool DoExecute(Args &command, CommandReturnObject &result) override { + if (command.GetArgumentCount() != 0) { + result.AppendError("'command script list' doesn't take any arguments"); + result.SetStatus(eReturnStatusFailed); + return false; + } + m_interpreter.GetHelp(result, CommandInterpreter::eCommandTypesUserDef); result.SetStatus(eReturnStatusSuccessFinishResult); @@ -1781,6 +1751,12 @@ public: protected: bool DoExecute(Args &command, CommandReturnObject &result) override { + if (command.GetArgumentCount() != 0) { + result.AppendError("'command script clear' doesn't take any arguments"); + result.SetStatus(eReturnStatusFailed); + return false; + } + m_interpreter.RemoveAllUser(); result.SetStatus(eReturnStatusSuccessFinishResult); @@ -1822,7 +1798,7 @@ protected: return false; } - auto cmd_name = command[0].ref; + auto cmd_name = command[0].ref(); if (cmd_name.empty() || !m_interpreter.HasUserCommands() || !m_interpreter.UserCommandExists(cmd_name)) { diff --git a/source/Commands/CommandObjectDisassemble.cpp b/source/Commands/CommandObjectDisassemble.cpp index 5972555b2499..69e2d757b5fe 100644 --- a/source/Commands/CommandObjectDisassemble.cpp +++ b/source/Commands/CommandObjectDisassemble.cpp @@ -30,32 +30,8 @@ using namespace lldb; using namespace lldb_private; -static constexpr OptionDefinition g_disassemble_options[] = { - // clang-format off - { LLDB_OPT_SET_ALL, false, "bytes", 'b', OptionParser::eNoArgument, nullptr, {}, 0, eArgTypeNone, "Show opcode bytes when disassembling." }, - { LLDB_OPT_SET_ALL, false, "context", 'C', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeNumLines, "Number of context lines of source to show." }, - { LLDB_OPT_SET_ALL, false, "mixed", 'm', OptionParser::eNoArgument, nullptr, {}, 0, eArgTypeNone, "Enable mixed source and assembly display." }, - { LLDB_OPT_SET_ALL, false, "raw", 'r', OptionParser::eNoArgument, nullptr, {}, 0, eArgTypeNone, "Print raw disassembly with no symbol information." }, - { LLDB_OPT_SET_ALL, false, "plugin", 'P', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypePlugin, "Name of the disassembler plugin you want to use." }, - { LLDB_OPT_SET_ALL, false, "flavor", 'F', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeDisassemblyFlavor, "Name of the disassembly flavor you want to use. " - "Currently the only valid options are default, and for Intel " - "architectures, att and intel." }, - { LLDB_OPT_SET_ALL, false, "arch", 'A', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeArchitecture, "Specify the architecture to use from cross disassembly." }, - { LLDB_OPT_SET_1 | - LLDB_OPT_SET_2, true, "start-address", 's', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeAddressOrExpression, "Address at which to start disassembling." }, - { LLDB_OPT_SET_1, false, "end-address", 'e', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeAddressOrExpression, "Address at which to end disassembling." }, - { LLDB_OPT_SET_2 | - LLDB_OPT_SET_3 | - LLDB_OPT_SET_4 | - LLDB_OPT_SET_5, false, "count", 'c', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeNumLines, "Number of instructions to display." }, - { LLDB_OPT_SET_3, false, "name", 'n', OptionParser::eRequiredArgument, nullptr, {}, CommandCompletions::eSymbolCompletion, eArgTypeFunctionName, "Disassemble entire contents of the given function name." }, - { LLDB_OPT_SET_4, false, "frame", 'f', OptionParser::eNoArgument, nullptr, {}, 0, eArgTypeNone, "Disassemble from the start of the current frame's function." }, - { LLDB_OPT_SET_5, false, "pc", 'p', OptionParser::eNoArgument, nullptr, {}, 0, eArgTypeNone, "Disassemble around the current pc." }, - { LLDB_OPT_SET_6, false, "line", 'l', OptionParser::eNoArgument, nullptr, {}, 0, eArgTypeNone, "Disassemble the current frame's current source line instructions if there is debug line " - "table information, else disassemble around the pc." }, - { LLDB_OPT_SET_7, false, "address", 'a', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeAddressOrExpression, "Disassemble function containing this address." }, - // clang-format on -}; +#define LLDB_OPTIONS_disassemble +#include "CommandOptions.inc" CommandObjectDisassemble::CommandOptions::CommandOptions() : Options(), num_lines_context(0), num_instructions(0), func_name(), @@ -171,9 +147,7 @@ Status CommandObjectDisassemble::CommandOptions::SetOptionValue( } break; default: - error.SetErrorStringWithFormat("unrecognized short option '%c'", - short_option); - break; + llvm_unreachable("Unimplemented option"); } return error; @@ -238,20 +212,15 @@ CommandObjectDisassemble::CommandObjectDisassemble( "Disassemble specified instructions in the current target. " "Defaults to the current function for the current thread and " "stack frame.", - "disassemble [<cmd-options>]"), + "disassemble [<cmd-options>]", eCommandRequiresTarget), m_options() {} CommandObjectDisassemble::~CommandObjectDisassemble() = default; bool CommandObjectDisassemble::DoExecute(Args &command, CommandReturnObject &result) { - Target *target = GetDebugger().GetSelectedTarget().get(); - if (target == nullptr) { - result.AppendError("invalid target, create a debug target using the " - "'target create' command"); - result.SetStatus(eReturnStatusFailed); - return false; - } + Target *target = &GetSelectedTarget(); + if (!m_options.arch.IsValid()) m_options.arch = target->GetArchitecture(); @@ -541,7 +510,7 @@ bool CommandObjectDisassemble::DoExecute(Args &command, } else { result.AppendErrorWithFormat( "Failed to disassemble memory at 0x%8.8" PRIx64 ".\n", - m_options.start_addr); + cur_range.GetBaseAddress().GetLoadAddress(target)); result.SetStatus(eReturnStatusFailed); } if (print_sc_header) diff --git a/source/Commands/CommandObjectExpression.cpp b/source/Commands/CommandObjectExpression.cpp index 29e4ab695522..9bafdc149804 100644 --- a/source/Commands/CommandObjectExpression.cpp +++ b/source/Commands/CommandObjectExpression.cpp @@ -38,34 +38,24 @@ CommandObjectExpression::CommandOptions::CommandOptions() : OptionGroup() {} CommandObjectExpression::CommandOptions::~CommandOptions() = default; static constexpr OptionEnumValueElement g_description_verbosity_type[] = { - {eLanguageRuntimeDescriptionDisplayVerbosityCompact, "compact", - "Only show the description string"}, - {eLanguageRuntimeDescriptionDisplayVerbosityFull, "full", - "Show the full output, including persistent variable's name and type"} }; + { + eLanguageRuntimeDescriptionDisplayVerbosityCompact, + "compact", + "Only show the description string", + }, + { + eLanguageRuntimeDescriptionDisplayVerbosityFull, + "full", + "Show the full output, including persistent variable's name and type", + }, +}; static constexpr OptionEnumValues DescriptionVerbosityTypes() { return OptionEnumValues(g_description_verbosity_type); } -static constexpr OptionDefinition g_expression_options[] = { - // clang-format off - {LLDB_OPT_SET_1 | LLDB_OPT_SET_2, false, "all-threads", 'a', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeBoolean, "Should we run all threads if the execution doesn't complete on one thread."}, - {LLDB_OPT_SET_1 | LLDB_OPT_SET_2, false, "ignore-breakpoints", 'i', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeBoolean, "Ignore breakpoint hits while running expressions"}, - {LLDB_OPT_SET_1 | LLDB_OPT_SET_2, false, "timeout", 't', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeUnsignedInteger, "Timeout value (in microseconds) for running the expression."}, - {LLDB_OPT_SET_1 | LLDB_OPT_SET_2, false, "unwind-on-error", 'u', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeBoolean, "Clean up program state if the expression causes a crash, or raises a signal. " - "Note, unlike gdb hitting a breakpoint is controlled by another option (-i)."}, - {LLDB_OPT_SET_1 | LLDB_OPT_SET_2, false, "debug", 'g', OptionParser::eNoArgument, nullptr, {}, 0, eArgTypeNone, "When specified, debug the JIT code by setting a breakpoint on the first instruction " - "and forcing breakpoints to not be ignored (-i0) and no unwinding to happen on error (-u0)."}, - {LLDB_OPT_SET_1 | LLDB_OPT_SET_2, false, "language", 'l', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeLanguage, "Specifies the Language to use when parsing the expression. If not set the target.language " - "setting is used." }, - {LLDB_OPT_SET_1 | LLDB_OPT_SET_2, false, "apply-fixits", 'X', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeLanguage, "If true, simple fix-it hints will be automatically applied to the expression." }, - {LLDB_OPT_SET_1, false, "description-verbosity", 'v', OptionParser::eOptionalArgument, nullptr, DescriptionVerbosityTypes(), 0, eArgTypeDescriptionVerbosity, "How verbose should the output of this expression be, if the object description is asked for."}, - {LLDB_OPT_SET_1 | LLDB_OPT_SET_2, false, "top-level", 'p', OptionParser::eNoArgument, nullptr, {}, 0, eArgTypeNone, "Interpret the expression as a complete translation unit, without injecting it into the local " - "context. Allows declaration of persistent, top-level entities without a $ prefix."}, - {LLDB_OPT_SET_1 | LLDB_OPT_SET_2, false, "allow-jit", 'j', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeBoolean, "Controls whether the expression can fall back to being JITted if it's not supported by " - "the interpreter (defaults to true)."} - // clang-format on -}; +#define LLDB_OPTIONS_expression +#include "CommandOptions.inc" Status CommandObjectExpression::CommandOptions::SetOptionValue( uint32_t option_idx, llvm::StringRef option_arg, @@ -176,9 +166,7 @@ Status CommandObjectExpression::CommandOptions::SetOptionValue( } default: - error.SetErrorStringWithFormat("invalid short option character '%c'", - short_option); - break; + llvm_unreachable("Unimplemented option"); } return error; @@ -304,7 +292,7 @@ CommandObjectExpression::~CommandObjectExpression() = default; Options *CommandObjectExpression::GetOptions() { return &m_option_group; } -int CommandObjectExpression::HandleCompletion(CompletionRequest &request) { +void CommandObjectExpression::HandleCompletion(CompletionRequest &request) { EvaluateExpressionOptions options; options.SetCoerceToId(m_varobj_options.use_objc); options.SetLanguage(m_command_options.language); @@ -321,17 +309,14 @@ int CommandObjectExpression::HandleCompletion(CompletionRequest &request) { // This didn't work, so let's get out before we start doing things that // expect a valid frame pointer. if (m_interpreter.GetExecutionContext().GetFramePtr() == nullptr) - return 0; + return; ExecutionContext exe_ctx(m_interpreter.GetExecutionContext()); Target *target = exe_ctx.GetTargetPtr(); if (!target) - target = GetDummyTarget(); - - if (!target) - return 0; + target = &GetDummyTarget(); unsigned cursor_pos = request.GetRawCursorPos(); llvm::StringRef code = request.GetRawLine(); @@ -351,7 +336,7 @@ int CommandObjectExpression::HandleCompletion(CompletionRequest &request) { // exit. // FIXME: We should complete the options here. if (cursor_pos < raw_start) - return 0; + return; // Make the cursor_pos again relative to the start of the code string. assert(cursor_pos >= raw_start); @@ -364,10 +349,9 @@ int CommandObjectExpression::HandleCompletion(CompletionRequest &request) { code, llvm::StringRef(), language, UserExpression::eResultTypeAny, options, nullptr, error)); if (error.Fail()) - return 0; + return; expr->Complete(exe_ctx, request, cursor_pos); - return request.GetNumberOfMatches(); } static lldb_private::Status @@ -393,123 +377,116 @@ bool CommandObjectExpression::EvaluateExpression(llvm::StringRef expr, Target *target = exe_ctx.GetTargetPtr(); if (!target) - target = GetDummyTarget(); - - if (target) { - lldb::ValueObjectSP result_valobj_sp; - bool keep_in_memory = true; - StackFrame *frame = exe_ctx.GetFramePtr(); - - EvaluateExpressionOptions options; - options.SetCoerceToId(m_varobj_options.use_objc); - options.SetUnwindOnError(m_command_options.unwind_on_error); - options.SetIgnoreBreakpoints(m_command_options.ignore_breakpoints); - options.SetKeepInMemory(keep_in_memory); - options.SetUseDynamic(m_varobj_options.use_dynamic); - options.SetTryAllThreads(m_command_options.try_all_threads); - options.SetDebug(m_command_options.debug); - options.SetLanguage(m_command_options.language); - options.SetExecutionPolicy( - m_command_options.allow_jit - ? EvaluateExpressionOptions::default_execution_policy - : lldb_private::eExecutionPolicyNever); - - bool auto_apply_fixits; - if (m_command_options.auto_apply_fixits == eLazyBoolCalculate) - auto_apply_fixits = target->GetEnableAutoApplyFixIts(); - else - auto_apply_fixits = m_command_options.auto_apply_fixits == eLazyBoolYes; + target = &GetDummyTarget(); - options.SetAutoApplyFixIts(auto_apply_fixits); + lldb::ValueObjectSP result_valobj_sp; + bool keep_in_memory = true; + StackFrame *frame = exe_ctx.GetFramePtr(); + + EvaluateExpressionOptions options; + options.SetCoerceToId(m_varobj_options.use_objc); + options.SetUnwindOnError(m_command_options.unwind_on_error); + options.SetIgnoreBreakpoints(m_command_options.ignore_breakpoints); + options.SetKeepInMemory(keep_in_memory); + options.SetUseDynamic(m_varobj_options.use_dynamic); + options.SetTryAllThreads(m_command_options.try_all_threads); + options.SetDebug(m_command_options.debug); + options.SetLanguage(m_command_options.language); + options.SetExecutionPolicy( + m_command_options.allow_jit + ? EvaluateExpressionOptions::default_execution_policy + : lldb_private::eExecutionPolicyNever); + + bool auto_apply_fixits; + if (m_command_options.auto_apply_fixits == eLazyBoolCalculate) + auto_apply_fixits = target->GetEnableAutoApplyFixIts(); + else + auto_apply_fixits = m_command_options.auto_apply_fixits == eLazyBoolYes; - if (m_command_options.top_level) - options.SetExecutionPolicy(eExecutionPolicyTopLevel); + options.SetAutoApplyFixIts(auto_apply_fixits); - // If there is any chance we are going to stop and want to see what went - // wrong with our expression, we should generate debug info - if (!m_command_options.ignore_breakpoints || - !m_command_options.unwind_on_error) - options.SetGenerateDebugInfo(true); + if (m_command_options.top_level) + options.SetExecutionPolicy(eExecutionPolicyTopLevel); - if (m_command_options.timeout > 0) - options.SetTimeout(std::chrono::microseconds(m_command_options.timeout)); - else - options.SetTimeout(llvm::None); - - ExpressionResults success = target->EvaluateExpression( - expr, frame, result_valobj_sp, options, &m_fixed_expression); - - // We only tell you about the FixIt if we applied it. The compiler errors - // will suggest the FixIt if it parsed. - if (error_stream && !m_fixed_expression.empty() && - target->GetEnableNotifyAboutFixIts()) { - if (success == eExpressionCompleted) - error_stream->Printf( - " Fix-it applied, fixed expression was: \n %s\n", - m_fixed_expression.c_str()); - } + // If there is any chance we are going to stop and want to see what went + // wrong with our expression, we should generate debug info + if (!m_command_options.ignore_breakpoints || + !m_command_options.unwind_on_error) + options.SetGenerateDebugInfo(true); - if (result_valobj_sp) { - Format format = m_format_options.GetFormat(); - - if (result_valobj_sp->GetError().Success()) { - if (format != eFormatVoid) { - if (format != eFormatDefault) - result_valobj_sp->SetFormat(format); - - if (m_varobj_options.elem_count > 0) { - Status error(CanBeUsedForElementCountPrinting(*result_valobj_sp)); - if (error.Fail()) { - result->AppendErrorWithFormat( - "expression cannot be used with --element-count %s\n", - error.AsCString("")); - result->SetStatus(eReturnStatusFailed); - return false; - } + if (m_command_options.timeout > 0) + options.SetTimeout(std::chrono::microseconds(m_command_options.timeout)); + else + options.SetTimeout(llvm::None); + + ExpressionResults success = target->EvaluateExpression( + expr, frame, result_valobj_sp, options, &m_fixed_expression); + + // We only tell you about the FixIt if we applied it. The compiler errors + // will suggest the FixIt if it parsed. + if (error_stream && !m_fixed_expression.empty() && + target->GetEnableNotifyAboutFixIts()) { + if (success == eExpressionCompleted) + error_stream->Printf(" Fix-it applied, fixed expression was: \n %s\n", + m_fixed_expression.c_str()); + } + + if (result_valobj_sp) { + Format format = m_format_options.GetFormat(); + + if (result_valobj_sp->GetError().Success()) { + if (format != eFormatVoid) { + if (format != eFormatDefault) + result_valobj_sp->SetFormat(format); + + if (m_varobj_options.elem_count > 0) { + Status error(CanBeUsedForElementCountPrinting(*result_valobj_sp)); + if (error.Fail()) { + result->AppendErrorWithFormat( + "expression cannot be used with --element-count %s\n", + error.AsCString("")); + result->SetStatus(eReturnStatusFailed); + return false; } + } - DumpValueObjectOptions options(m_varobj_options.GetAsDumpOptions( - m_command_options.m_verbosity, format)); - options.SetVariableFormatDisplayLanguage( - result_valobj_sp->GetPreferredDisplayLanguage()); + DumpValueObjectOptions options(m_varobj_options.GetAsDumpOptions( + m_command_options.m_verbosity, format)); + options.SetVariableFormatDisplayLanguage( + result_valobj_sp->GetPreferredDisplayLanguage()); - result_valobj_sp->Dump(*output_stream, options); + result_valobj_sp->Dump(*output_stream, options); - if (result) - result->SetStatus(eReturnStatusSuccessFinishResult); + if (result) + result->SetStatus(eReturnStatusSuccessFinishResult); + } + } else { + if (result_valobj_sp->GetError().GetError() == + UserExpression::kNoResult) { + if (format != eFormatVoid && GetDebugger().GetNotifyVoid()) { + error_stream->PutCString("(void)\n"); } - } else { - if (result_valobj_sp->GetError().GetError() == - UserExpression::kNoResult) { - if (format != eFormatVoid && GetDebugger().GetNotifyVoid()) { - error_stream->PutCString("(void)\n"); - } - if (result) - result->SetStatus(eReturnStatusSuccessFinishResult); + if (result) + result->SetStatus(eReturnStatusSuccessFinishResult); + } else { + const char *error_cstr = result_valobj_sp->GetError().AsCString(); + if (error_cstr && error_cstr[0]) { + const size_t error_cstr_len = strlen(error_cstr); + const bool ends_with_newline = error_cstr[error_cstr_len - 1] == '\n'; + if (strstr(error_cstr, "error:") != error_cstr) + error_stream->PutCString("error: "); + error_stream->Write(error_cstr, error_cstr_len); + if (!ends_with_newline) + error_stream->EOL(); } else { - const char *error_cstr = result_valobj_sp->GetError().AsCString(); - if (error_cstr && error_cstr[0]) { - const size_t error_cstr_len = strlen(error_cstr); - const bool ends_with_newline = - error_cstr[error_cstr_len - 1] == '\n'; - if (strstr(error_cstr, "error:") != error_cstr) - error_stream->PutCString("error: "); - error_stream->Write(error_cstr, error_cstr_len); - if (!ends_with_newline) - error_stream->EOL(); - } else { - error_stream->PutCString("error: unknown error\n"); - } - - if (result) - result->SetStatus(eReturnStatusFailed); + error_stream->PutCString("error: unknown error\n"); } + + if (result) + result->SetStatus(eReturnStatusFailed); } } - } else { - error_stream->Printf("error: invalid execution context for expression\n"); - return false; } return true; @@ -521,8 +498,8 @@ void CommandObjectExpression::IOHandlerInputComplete(IOHandler &io_handler, // StreamSP output_stream = // io_handler.GetDebugger().GetAsyncOutputStream(); // StreamSP error_stream = io_handler.GetDebugger().GetAsyncErrorStream(); - StreamFileSP output_sp(io_handler.GetOutputStreamFile()); - StreamFileSP error_sp(io_handler.GetErrorStreamFile()); + StreamFileSP output_sp = io_handler.GetOutputStreamFileSP(); + StreamFileSP error_sp = io_handler.GetErrorStreamFileSP(); EvaluateExpression(line.c_str(), output_sp.get(), error_sp.get()); if (output_sp) @@ -560,7 +537,7 @@ void CommandObjectExpression::GetMultilineExpression() { 1, // Show line numbers starting at 1 *this, nullptr)); - StreamFileSP output_sp(io_handler_sp->GetOutputStreamFile()); + StreamFileSP output_sp = io_handler_sp->GetOutputStreamFileSP(); if (output_sp) { output_sp->PutCString( "Enter expressions, then terminate with an empty line to evaluate:\n"); @@ -675,11 +652,11 @@ bool CommandObjectExpression::DoExecute(llvm::StringRef command, } } - Target *target = GetSelectedOrDummyTarget(); + Target &target = GetSelectedOrDummyTarget(); if (EvaluateExpression(expr, &(result.GetOutputStream()), &(result.GetErrorStream()), &result)) { - if (!m_fixed_expression.empty() && target->GetEnableNotifyAboutFixIts()) { + if (!m_fixed_expression.empty() && target.GetEnableNotifyAboutFixIts()) { CommandHistory &history = m_interpreter.GetCommandHistory(); // FIXME: Can we figure out what the user actually typed (e.g. some alias // for expr???) @@ -694,12 +671,12 @@ bool CommandObjectExpression::DoExecute(llvm::StringRef command, history.AppendString(fixed_command); } // Increment statistics to record this expression evaluation success. - target->IncrementStats(StatisticKind::ExpressionSuccessful); + target.IncrementStats(StatisticKind::ExpressionSuccessful); return true; } // Increment statistics to record this expression evaluation failure. - target->IncrementStats(StatisticKind::ExpressionFailure); + target.IncrementStats(StatisticKind::ExpressionFailure); result.SetStatus(eReturnStatusFailed); return false; } diff --git a/source/Commands/CommandObjectExpression.h b/source/Commands/CommandObjectExpression.h index 89c8e1dbeceb..8ef764239069 100644 --- a/source/Commands/CommandObjectExpression.h +++ b/source/Commands/CommandObjectExpression.h @@ -54,7 +54,7 @@ public: Options *GetOptions() override; - int HandleCompletion(CompletionRequest &request) override; + void HandleCompletion(CompletionRequest &request) override; protected: // IOHandler::Delegate functions diff --git a/source/Commands/CommandObjectFrame.cpp b/source/Commands/CommandObjectFrame.cpp index ab6a07952f19..6a7facdaff35 100644 --- a/source/Commands/CommandObjectFrame.cpp +++ b/source/Commands/CommandObjectFrame.cpp @@ -23,7 +23,6 @@ #include "lldb/Interpreter/OptionGroupValueObjectDisplay.h" #include "lldb/Interpreter/OptionGroupVariable.h" #include "lldb/Interpreter/Options.h" -#include "lldb/Symbol/ClangASTContext.h" #include "lldb/Symbol/CompilerType.h" #include "lldb/Symbol/Function.h" #include "lldb/Symbol/ObjectFile.h" @@ -54,13 +53,8 @@ using namespace lldb_private; // CommandObjectFrameDiagnose -static constexpr OptionDefinition g_frame_diag_options[] = { - // clang-format off - { LLDB_OPT_SET_1, false, "register", 'r', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeRegisterName, "A register to diagnose." }, - { LLDB_OPT_SET_1, false, "address", 'a', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeAddress, "An address to diagnose." }, - { LLDB_OPT_SET_1, false, "offset", 'o', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeOffset, "An optional offset. Requires --register." } - // clang-format on -}; +#define LLDB_OPTIONS_frame_diag +#include "CommandOptions.inc" class CommandObjectFrameDiagnose : public CommandObjectParsed { public: @@ -98,9 +92,7 @@ public: } break; default: - error.SetErrorStringWithFormat("invalid short option character '%c'", - short_option); - break; + llvm_unreachable("Unimplemented option"); } return error; @@ -238,11 +230,8 @@ protected: // CommandObjectFrameSelect -static OptionDefinition g_frame_select_options[] = { - // clang-format off - { LLDB_OPT_SET_1, false, "relative", 'r', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeOffset, "A relative frame index offset from the current frame index." }, - // clang-format on -}; +#define LLDB_OPTIONS_frame_select +#include "CommandOptions.inc" class CommandObjectFrameSelect : public CommandObjectParsed { public: @@ -257,32 +246,32 @@ public: Status error; const int short_option = m_getopt_table[option_idx].val; switch (short_option) { - case 'r': - if (option_arg.getAsInteger(0, relative_frame_offset)) { - relative_frame_offset = INT32_MIN; + case 'r': { + int32_t offset = 0; + if (option_arg.getAsInteger(0, offset) || offset == INT32_MIN) { error.SetErrorStringWithFormat("invalid frame offset argument '%s'", option_arg.str().c_str()); - } + } else + relative_frame_offset = offset; break; + } default: - error.SetErrorStringWithFormat("invalid short option character '%c'", - short_option); - break; + llvm_unreachable("Unimplemented option"); } return error; } void OptionParsingStarting(ExecutionContext *execution_context) override { - relative_frame_offset = INT32_MIN; + relative_frame_offset.reset(); } llvm::ArrayRef<OptionDefinition> GetDefinitions() override { return llvm::makeArrayRef(g_frame_select_options); } - int32_t relative_frame_offset; + llvm::Optional<int32_t> relative_frame_offset; }; CommandObjectFrameSelect(CommandInterpreter &interpreter) @@ -320,15 +309,16 @@ protected: Thread *thread = m_exe_ctx.GetThreadPtr(); uint32_t frame_idx = UINT32_MAX; - if (m_options.relative_frame_offset != INT32_MIN) { + if (m_options.relative_frame_offset.hasValue()) { // The one and only argument is a signed relative frame index frame_idx = thread->GetSelectedFrameIndex(); if (frame_idx == UINT32_MAX) frame_idx = 0; - if (m_options.relative_frame_offset < 0) { - if (static_cast<int32_t>(frame_idx) >= -m_options.relative_frame_offset) - frame_idx += m_options.relative_frame_offset; + if (*m_options.relative_frame_offset < 0) { + if (static_cast<int32_t>(frame_idx) >= + -*m_options.relative_frame_offset) + frame_idx += *m_options.relative_frame_offset; else { if (frame_idx == 0) { // If you are already at the bottom of the stack, then just warn @@ -339,15 +329,15 @@ protected: } else frame_idx = 0; } - } else if (m_options.relative_frame_offset > 0) { + } else if (*m_options.relative_frame_offset > 0) { // I don't want "up 20" where "20" takes you past the top of the stack // to produce // an error, but rather to just go to the top. So I have to count the // stack here... const uint32_t num_frames = thread->GetStackFrameCount(); if (static_cast<int32_t>(num_frames - frame_idx) > - m_options.relative_frame_offset) - frame_idx += m_options.relative_frame_offset; + *m_options.relative_frame_offset) + frame_idx += *m_options.relative_frame_offset; else { if (frame_idx == num_frames - 1) { // If we are already at the top of the stack, just warn and don't @@ -371,7 +361,7 @@ protected: } if (command.GetArgumentCount() == 1) { - if (command[0].ref.getAsInteger(0, frame_idx)) { + if (command[0].ref().getAsInteger(0, frame_idx)) { result.AppendErrorWithFormat("invalid frame index argument '%s'.", command[0].c_str()); result.SetStatus(eReturnStatusFailed); @@ -460,14 +450,13 @@ public: Options *GetOptions() override { return &m_option_group; } - int HandleArgumentCompletion( - CompletionRequest &request, - OptionElementVector &opt_element_vector) override { + void + HandleArgumentCompletion(CompletionRequest &request, + OptionElementVector &opt_element_vector) override { // Arguments are the standard source file completer. CommandCompletions::InvokeCommonCompletionCallbacks( GetCommandInterpreter(), CommandCompletions::eVariablePathCompletion, request, nullptr); - return request.GetNumberOfMatches(); } protected: @@ -541,9 +530,9 @@ protected: for (auto &entry : command) { if (m_option_variable.use_regex) { const size_t regex_start_index = regex_var_list.GetSize(); - llvm::StringRef name_str = entry.ref; + llvm::StringRef name_str = entry.ref(); RegularExpression regex(name_str); - if (regex.Compile(name_str)) { + if (regex.IsValid()) { size_t num_matches = 0; const size_t num_new_regex_vars = variable_list->AppendVariablesIfUnique(regex, regex_var_list, @@ -582,9 +571,9 @@ protected: entry.c_str()); } } else { - char regex_error[1024]; - if (regex.GetErrorAsCString(regex_error, sizeof(regex_error))) - result.GetErrorStream().Printf("error: %s\n", regex_error); + if (llvm::Error err = regex.GetError()) + result.GetErrorStream().Printf( + "error: %s\n", llvm::toString(std::move(err)).c_str()); else result.GetErrorStream().Printf( "error: unknown regex error when compiling '%s'\n", @@ -600,7 +589,7 @@ protected: StackFrame::eExpressionPathOptionsInspectAnonymousUnions; lldb::VariableSP var_sp; valobj_sp = frame->GetValueForVariableExpressionPath( - entry.ref, m_varobj_options.use_dynamic, expr_path_options, + entry.ref(), m_varobj_options.use_dynamic, expr_path_options, var_sp, error); if (valobj_sp) { std::string scope_string; @@ -727,11 +716,11 @@ protected: // Increment statistics. bool res = result.Succeeded(); - Target *target = GetSelectedOrDummyTarget(); + Target &target = GetSelectedOrDummyTarget(); if (res) - target->IncrementStats(StatisticKind::FrameVarSuccess); + target.IncrementStats(StatisticKind::FrameVarSuccess); else - target->IncrementStats(StatisticKind::FrameVarFailure); + target.IncrementStats(StatisticKind::FrameVarFailure); return res; } @@ -744,14 +733,8 @@ protected: #pragma mark CommandObjectFrameRecognizer -static OptionDefinition g_frame_recognizer_add_options[] = { - // clang-format off - { LLDB_OPT_SET_ALL, false, "shlib", 's', OptionParser::eRequiredArgument, nullptr, {}, CommandCompletions::eModuleCompletion, eArgTypeShlibName, "Name of the module or shared library that this recognizer applies to." }, - { LLDB_OPT_SET_ALL, false, "function", 'n', OptionParser::eRequiredArgument, nullptr, {}, CommandCompletions::eSymbolCompletion, eArgTypeName, "Name of the function that this recognizer applies to." }, - { LLDB_OPT_SET_2, false, "python-class", 'l', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypePythonClass, "Give the name of a Python class to use for this frame recognizer." }, - { LLDB_OPT_SET_ALL, false, "regex", 'x', OptionParser::eNoArgument, nullptr, {}, 0, eArgTypeNone, "Function name and module name are actually regular expressions." } - // clang-format on -}; +#define LLDB_OPTIONS_frame_recognizer_add +#include "CommandOptions.inc" class CommandObjectFrameRecognizerAdd : public CommandObjectParsed { private: @@ -779,9 +762,7 @@ private: m_regex = true; break; default: - error.SetErrorStringWithFormat("unrecognized option '%c'", - short_option); - break; + llvm_unreachable("Unimplemented option"); } return error; diff --git a/source/Commands/CommandObjectGUI.cpp b/source/Commands/CommandObjectGUI.cpp index 21ed510d1264..fac2e9627783 100644 --- a/source/Commands/CommandObjectGUI.cpp +++ b/source/Commands/CommandObjectGUI.cpp @@ -28,9 +28,10 @@ bool CommandObjectGUI::DoExecute(Args &args, CommandReturnObject &result) { if (args.GetArgumentCount() == 0) { Debugger &debugger = GetDebugger(); - lldb::StreamFileSP input_sp = debugger.GetInputFile(); - if (input_sp && input_sp->GetFile().GetIsRealTerminal() && - input_sp->GetFile().GetIsInteractive()) { + File &input = debugger.GetInputFile(); + File &output = debugger.GetOutputFile(); + if (input.GetStream() && output.GetStream() && input.GetIsRealTerminal() && + input.GetIsInteractive()) { IOHandlerSP io_handler_sp(new IOHandlerCursesGUI(debugger)); if (io_handler_sp) debugger.PushIOHandler(io_handler_sp); diff --git a/source/Commands/CommandObjectHelp.cpp b/source/Commands/CommandObjectHelp.cpp index ab557919d0a0..c02a583bf9df 100644 --- a/source/Commands/CommandObjectHelp.cpp +++ b/source/Commands/CommandObjectHelp.cpp @@ -65,10 +65,8 @@ CommandObjectHelp::CommandObjectHelp(CommandInterpreter &interpreter) CommandObjectHelp::~CommandObjectHelp() = default; -static constexpr OptionDefinition g_help_options[] = { #define LLDB_OPTIONS_help #include "CommandOptions.inc" -}; llvm::ArrayRef<OptionDefinition> CommandObjectHelp::CommandOptions::GetDefinitions() { @@ -98,7 +96,7 @@ bool CommandObjectHelp::DoExecute(Args &command, CommandReturnObject &result) { // Get command object for the first command argument. Only search built-in // command dictionary. StringList matches; - auto command_name = command[0].ref; + auto command_name = command[0].ref(); cmd_obj = m_interpreter.GetCommandObject(command_name, &matches); if (cmd_obj != nullptr) { @@ -109,7 +107,7 @@ bool CommandObjectHelp::DoExecute(Args &command, CommandReturnObject &result) { // object that corresponds to the help command entered. std::string sub_command; for (auto &entry : command.entries().drop_front()) { - sub_command = entry.ref; + sub_command = entry.ref(); matches.Clear(); if (sub_cmd_obj->IsAlias()) sub_cmd_obj = @@ -203,24 +201,23 @@ bool CommandObjectHelp::DoExecute(Args &command, CommandReturnObject &result) { return result.Succeeded(); } -int CommandObjectHelp::HandleCompletion(CompletionRequest &request) { +void CommandObjectHelp::HandleCompletion(CompletionRequest &request) { // Return the completions of the commands in the help system: if (request.GetCursorIndex() == 0) { - return m_interpreter.HandleCompletionMatches(request); - } else { - CommandObject *cmd_obj = - m_interpreter.GetCommandObject(request.GetParsedLine()[0].ref); + m_interpreter.HandleCompletionMatches(request); + return; + } + CommandObject *cmd_obj = + m_interpreter.GetCommandObject(request.GetParsedLine()[0].ref()); - // The command that they are getting help on might be ambiguous, in which - // case we should complete that, otherwise complete with the command the - // user is getting help on... + // The command that they are getting help on might be ambiguous, in which + // case we should complete that, otherwise complete with the command the + // user is getting help on... - if (cmd_obj) { - request.GetParsedLine().Shift(); - request.SetCursorIndex(request.GetCursorIndex() - 1); - return cmd_obj->HandleCompletion(request); - } else { - return m_interpreter.HandleCompletionMatches(request); - } + if (cmd_obj) { + request.ShiftArguments(); + cmd_obj->HandleCompletion(request); + return; } + m_interpreter.HandleCompletionMatches(request); } diff --git a/source/Commands/CommandObjectHelp.h b/source/Commands/CommandObjectHelp.h index a641b19a46d0..52a00ac79ff9 100644 --- a/source/Commands/CommandObjectHelp.h +++ b/source/Commands/CommandObjectHelp.h @@ -23,7 +23,7 @@ public: ~CommandObjectHelp() override; - int HandleCompletion(CompletionRequest &request) override; + void HandleCompletion(CompletionRequest &request) override; static void GenerateAdditionalHelpAvenuesMessage( Stream *s, llvm::StringRef command, llvm::StringRef prefix, @@ -52,9 +52,7 @@ public: m_show_hidden = true; break; default: - error.SetErrorStringWithFormat("unrecognized option '%c'", - short_option); - break; + llvm_unreachable("Unimplemented option"); } return error; diff --git a/source/Commands/CommandObjectLog.cpp b/source/Commands/CommandObjectLog.cpp index 2ad61de1a3e9..31a876c3430e 100644 --- a/source/Commands/CommandObjectLog.cpp +++ b/source/Commands/CommandObjectLog.cpp @@ -31,20 +31,23 @@ using namespace lldb; using namespace lldb_private; -static constexpr OptionDefinition g_log_options[] = { - // clang-format off - { LLDB_OPT_SET_1, false, "file", 'f', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeFilename, "Set the destination file to log to." }, - { LLDB_OPT_SET_1, false, "threadsafe", 't', OptionParser::eNoArgument, nullptr, {}, 0, eArgTypeNone, "Enable thread safe logging to avoid interweaved log lines." }, - { LLDB_OPT_SET_1, false, "verbose", 'v', OptionParser::eNoArgument, nullptr, {}, 0, eArgTypeNone, "Enable verbose logging." }, - { LLDB_OPT_SET_1, false, "sequence", 's', OptionParser::eNoArgument, nullptr, {}, 0, eArgTypeNone, "Prepend all log lines with an increasing integer sequence id." }, - { LLDB_OPT_SET_1, false, "timestamp", 'T', OptionParser::eNoArgument, nullptr, {}, 0, eArgTypeNone, "Prepend all log lines with a timestamp." }, - { LLDB_OPT_SET_1, false, "pid-tid", 'p', OptionParser::eNoArgument, nullptr, {}, 0, eArgTypeNone, "Prepend all log lines with the process and thread ID that generates the log line." }, - { LLDB_OPT_SET_1, false, "thread-name",'n', OptionParser::eNoArgument, nullptr, {}, 0, eArgTypeNone, "Prepend all log lines with the thread name for the thread that generates the log line." }, - { LLDB_OPT_SET_1, false, "stack", 'S', OptionParser::eNoArgument, nullptr, {}, 0, eArgTypeNone, "Append a stack backtrace to each log line." }, - { LLDB_OPT_SET_1, false, "append", 'a', OptionParser::eNoArgument, nullptr, {}, 0, eArgTypeNone, "Append to the log file instead of overwriting." }, - { LLDB_OPT_SET_1, false, "file-function",'F',OptionParser::eNoArgument, nullptr, {}, 0, eArgTypeNone, "Prepend the names of files and function that generate the logs." }, - // clang-format on -}; +#define LLDB_OPTIONS_log +#include "CommandOptions.inc" + +/// Common completion logic for log enable/disable. +static void CompleteEnableDisable(CompletionRequest &request) { + size_t arg_index = request.GetCursorIndex(); + if (arg_index == 0) { // We got: log enable/disable x[tab] + for (llvm::StringRef channel : Log::ListChannels()) + request.TryCompleteCurrentArg(channel); + } else if (arg_index >= 1) { // We got: log enable/disable channel x[tab] + llvm::StringRef channel = request.GetParsedLine().GetArgumentAtIndex(0); + Log::ForEachChannelCategory( + channel, [&request](llvm::StringRef name, llvm::StringRef desc) { + request.TryCompleteCurrentArg(name, desc); + }); + } +} class CommandObjectLogEnable : public CommandObjectParsed { public: @@ -125,9 +128,7 @@ public: log_options |= LLDB_LOG_OPTION_PREPEND_FILE_FUNCTION; break; default: - error.SetErrorStringWithFormat("unrecognized option '%c'", - short_option); - break; + llvm_unreachable("Unimplemented option"); } return error; @@ -148,17 +149,24 @@ public: uint32_t log_options; }; + void + HandleArgumentCompletion(CompletionRequest &request, + OptionElementVector &opt_element_vector) override { + CompleteEnableDisable(request); + } + protected: bool DoExecute(Args &args, CommandReturnObject &result) override { if (args.GetArgumentCount() < 2) { result.AppendErrorWithFormat( "%s takes a log channel and one or more log types.\n", m_cmd_name.c_str()); + result.SetStatus(eReturnStatusFailed); return false; } // Store into a std::string since we're about to shift the channel off. - const std::string channel = args[0].ref; + const std::string channel = args[0].ref(); args.Shift(); // Shift off the channel char log_file[PATH_MAX]; if (m_options.log_file) @@ -215,16 +223,23 @@ public: ~CommandObjectLogDisable() override = default; + void + HandleArgumentCompletion(CompletionRequest &request, + OptionElementVector &opt_element_vector) override { + CompleteEnableDisable(request); + } + protected: bool DoExecute(Args &args, CommandReturnObject &result) override { if (args.empty()) { result.AppendErrorWithFormat( "%s takes a log channel and one or more log types.\n", m_cmd_name.c_str()); + result.SetStatus(eReturnStatusFailed); return false; } - const std::string channel = args[0].ref; + const std::string channel = args[0].ref(); args.Shift(); // Shift off the channel if (channel == "all") { Log::DisableAllLogChannels(); @@ -266,6 +281,13 @@ public: ~CommandObjectLogList() override = default; + void + HandleArgumentCompletion(CompletionRequest &request, + OptionElementVector &opt_element_vector) override { + for (llvm::StringRef channel : Log::ListChannels()) + request.TryCompleteCurrentArg(channel); + } + protected: bool DoExecute(Args &args, CommandReturnObject &result) override { std::string output; @@ -277,7 +299,7 @@ protected: bool success = true; for (const auto &entry : args.entries()) success = - success && Log::ListChannelCategories(entry.ref, output_stream); + success && Log::ListChannelCategories(entry.ref(), output_stream); if (success) result.SetStatus(eReturnStatusSuccessFinishResult); } @@ -303,7 +325,7 @@ protected: result.SetStatus(eReturnStatusFailed); if (args.GetArgumentCount() == 1) { - auto sub_command = args[0].ref; + auto sub_command = args[0].ref(); if (sub_command.equals_lower("enable")) { Timer::SetDisplayDepth(UINT32_MAX); @@ -320,8 +342,8 @@ protected: result.SetStatus(eReturnStatusSuccessFinishResult); } } else if (args.GetArgumentCount() == 2) { - auto sub_command = args[0].ref; - auto param = args[1].ref; + auto sub_command = args[0].ref(); + auto param = args[1].ref(); if (sub_command.equals_lower("enable")) { uint32_t depth; diff --git a/source/Commands/CommandObjectMemory.cpp b/source/Commands/CommandObjectMemory.cpp index 1afcac71318d..38bd3d179096 100644 --- a/source/Commands/CommandObjectMemory.cpp +++ b/source/Commands/CommandObjectMemory.cpp @@ -46,20 +46,8 @@ using namespace lldb; using namespace lldb_private; -static constexpr OptionDefinition g_read_memory_options[] = { - // clang-format off - {LLDB_OPT_SET_1, false, "num-per-line", 'l', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeNumberPerLine, "The number of items per line to display." }, - {LLDB_OPT_SET_2, false, "binary", 'b', OptionParser::eNoArgument, nullptr, {}, 0, eArgTypeNone, "If true, memory will be saved as binary. If false, the memory is saved save as an ASCII dump that " - "uses the format, size, count and number per line settings." }, - {LLDB_OPT_SET_3 | - LLDB_OPT_SET_4, true , "type", 't', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeName, "The name of a type to view memory as." }, - {LLDB_OPT_SET_4, false, "language", 'x', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeLanguage, "The language of the type to view memory as."}, - {LLDB_OPT_SET_3, false, "offset", 'E', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeCount, "How many elements of the specified type to skip before starting to display data." }, - {LLDB_OPT_SET_1 | - LLDB_OPT_SET_2 | - LLDB_OPT_SET_3, false, "force", 'r', OptionParser::eNoArgument, nullptr, {}, 0, eArgTypeNone, "Necessary if reading over target.max-memory-read-size bytes." }, - // clang-format on -}; +#define LLDB_OPTIONS_memory_read +#include "CommandOptions.inc" class OptionGroupReadMemory : public OptionGroup { public: @@ -70,13 +58,13 @@ public: ~OptionGroupReadMemory() override = default; llvm::ArrayRef<OptionDefinition> GetDefinitions() override { - return llvm::makeArrayRef(g_read_memory_options); + return llvm::makeArrayRef(g_memory_read_options); } Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_value, ExecutionContext *execution_context) override { Status error; - const int short_option = g_read_memory_options[option_idx].short_option; + const int short_option = g_memory_read_options[option_idx].short_option; switch (short_option) { case 'l': @@ -108,9 +96,7 @@ public: break; default: - error.SetErrorStringWithFormat("unrecognized short option '%c'", - short_option); - break; + llvm_unreachable("Unimplemented option"); } return error; } @@ -175,6 +161,7 @@ public: case eFormatOctal: case eFormatDecimal: case eFormatEnum: + case eFormatUnicode8: case eFormatUnicode16: case eFormatUnicode32: case eFormatUnsigned: @@ -606,7 +593,7 @@ protected: } if (argc > 0) - addr = OptionArgParser::ToAddress(&m_exe_ctx, command[0].ref, + addr = OptionArgParser::ToAddress(&m_exe_ctx, command[0].ref(), LLDB_INVALID_ADDRESS, &error); if (addr == LLDB_INVALID_ADDRESS) { @@ -618,7 +605,7 @@ protected: if (argc == 2) { lldb::addr_t end_addr = OptionArgParser::ToAddress( - &m_exe_ctx, command[1].ref, LLDB_INVALID_ADDRESS, nullptr); + &m_exe_ctx, command[1].ref(), LLDB_INVALID_ADDRESS, nullptr); if (end_addr == LLDB_INVALID_ADDRESS) { result.AppendError("invalid end address expression."); result.AppendError(error.AsCString()); @@ -778,26 +765,27 @@ protected: m_prev_varobj_options = m_varobj_options; m_prev_compiler_type = compiler_type; - StreamFile outfile_stream; - Stream *output_stream = nullptr; + std::unique_ptr<Stream> output_stream_storage; + Stream *output_stream_p = nullptr; const FileSpec &outfile_spec = m_outfile_options.GetFile().GetCurrentValue(); std::string path = outfile_spec.GetPath(); if (outfile_spec) { - uint32_t open_options = - File::eOpenOptionWrite | File::eOpenOptionCanCreate; + auto open_options = File::eOpenOptionWrite | File::eOpenOptionCanCreate; const bool append = m_outfile_options.GetAppend().GetCurrentValue(); if (append) open_options |= File::eOpenOptionAppend; - Status error = FileSystem::Instance().Open(outfile_stream.GetFile(), - outfile_spec, open_options); - if (error.Success()) { + auto outfile = FileSystem::Instance().Open(outfile_spec, open_options); + + if (outfile) { + auto outfile_stream_up = + std::make_unique<StreamFile>(std::move(outfile.get())); if (m_memory_options.m_output_as_binary) { const size_t bytes_written = - outfile_stream.Write(data_sp->GetBytes(), bytes_read); + outfile_stream_up->Write(data_sp->GetBytes(), bytes_read); if (bytes_written > 0) { result.GetOutputStream().Printf( "%zi bytes %s to '%s'\n", bytes_written, @@ -813,16 +801,19 @@ protected: } else { // We are going to write ASCII to the file just point the // output_stream to our outfile_stream... - output_stream = &outfile_stream; + output_stream_storage = std::move(outfile_stream_up); + output_stream_p = output_stream_storage.get(); } } else { - result.AppendErrorWithFormat("Failed to open file '%s' for %s.\n", + result.AppendErrorWithFormat("Failed to open file '%s' for %s:\n", path.c_str(), append ? "append" : "write"); + + result.AppendError(llvm::toString(outfile.takeError())); result.SetStatus(eReturnStatusFailed); return false; } } else { - output_stream = &result.GetOutputStream(); + output_stream_p = &result.GetOutputStream(); } ExecutionContextScope *exe_scope = m_exe_ctx.GetBestExecutionContextScope(); @@ -842,7 +833,7 @@ protected: DumpValueObjectOptions options(m_varobj_options.GetAsDumpOptions( eLanguageRuntimeDescriptionDisplayVerbosityFull, format)); - valobj_sp->Dump(*output_stream, options); + valobj_sp->Dump(*output_stream_p, options); } else { result.AppendErrorWithFormat( "failed to create a value object for: (%s) %s\n", @@ -882,13 +873,13 @@ protected: } } - assert(output_stream); + assert(output_stream_p); size_t bytes_dumped = DumpDataExtractor( - data, output_stream, 0, format, item_byte_size, item_count, + data, output_stream_p, 0, format, item_byte_size, item_count, num_per_line / target->GetArchitecture().GetDataByteSize(), addr, 0, 0, exe_scope); m_next_addr = addr + bytes_dumped; - output_stream->EOL(); + output_stream_p->EOL(); return true; } @@ -906,14 +897,8 @@ protected: CompilerType m_prev_compiler_type; }; -static constexpr OptionDefinition g_memory_find_option_table[] = { - // clang-format off - {LLDB_OPT_SET_1, true, "expression", 'e', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeExpression, "Evaluate an expression to obtain a byte pattern."}, - {LLDB_OPT_SET_2, true, "string", 's', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeName, "Use text to find a byte pattern."}, - {LLDB_OPT_SET_ALL, false, "count", 'c', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeCount, "How many times to perform the search."}, - {LLDB_OPT_SET_ALL, false, "dump-offset", 'o', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeOffset, "When dumping memory for a match, an offset from the match location to start dumping from."}, - // clang-format on -}; +#define LLDB_OPTIONS_memory_find +#include "CommandOptions.inc" // Find the specified data in memory class CommandObjectMemoryFind : public CommandObjectParsed { @@ -925,14 +910,13 @@ public: ~OptionGroupFindMemory() override = default; llvm::ArrayRef<OptionDefinition> GetDefinitions() override { - return llvm::makeArrayRef(g_memory_find_option_table); + return llvm::makeArrayRef(g_memory_find_options); } Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_value, ExecutionContext *execution_context) override { Status error; - const int short_option = - g_memory_find_option_table[option_idx].short_option; + const int short_option = g_memory_find_options[option_idx].short_option; switch (short_option) { case 'e': @@ -954,9 +938,7 @@ public: break; default: - error.SetErrorStringWithFormat("unrecognized short option '%c'", - short_option); - break; + llvm_unreachable("Unimplemented option"); } return error; } @@ -1056,13 +1038,13 @@ protected: Status error; lldb::addr_t low_addr = OptionArgParser::ToAddress( - &m_exe_ctx, command[0].ref, LLDB_INVALID_ADDRESS, &error); + &m_exe_ctx, command[0].ref(), LLDB_INVALID_ADDRESS, &error); if (low_addr == LLDB_INVALID_ADDRESS || error.Fail()) { result.AppendError("invalid low address"); return false; } lldb::addr_t high_addr = OptionArgParser::ToAddress( - &m_exe_ctx, command[1].ref, LLDB_INVALID_ADDRESS, &error); + &m_exe_ctx, command[1].ref(), LLDB_INVALID_ADDRESS, &error); if (high_addr == LLDB_INVALID_ADDRESS || error.Fail()) { result.AppendError("invalid high address"); return false; @@ -1203,12 +1185,8 @@ protected: OptionGroupFindMemory m_memory_options; }; -static constexpr OptionDefinition g_memory_write_option_table[] = { - // clang-format off - {LLDB_OPT_SET_1, true, "infile", 'i', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeFilename, "Write memory using the contents of a file."}, - {LLDB_OPT_SET_1, false, "offset", 'o', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeOffset, "Start writing bytes from an offset within the input file."}, - // clang-format on -}; +#define LLDB_OPTIONS_memory_write +#include "CommandOptions.inc" // Write memory to the inferior process class CommandObjectMemoryWrite : public CommandObjectParsed { @@ -1220,14 +1198,13 @@ public: ~OptionGroupWriteMemory() override = default; llvm::ArrayRef<OptionDefinition> GetDefinitions() override { - return llvm::makeArrayRef(g_memory_write_option_table); + return llvm::makeArrayRef(g_memory_write_options); } Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_value, ExecutionContext *execution_context) override { Status error; - const int short_option = - g_memory_write_option_table[option_idx].short_option; + const int short_option = g_memory_write_options[option_idx].short_option; switch (short_option) { case 'i': @@ -1249,9 +1226,7 @@ public: } break; default: - error.SetErrorStringWithFormat("unrecognized short option '%c'", - short_option); - break; + llvm_unreachable("Unimplemented option"); } return error; } @@ -1368,7 +1343,7 @@ protected: Status error; lldb::addr_t addr = OptionArgParser::ToAddress( - &m_exe_ctx, command[0].ref, LLDB_INVALID_ADDRESS, &error); + &m_exe_ctx, command[0].ref(), LLDB_INVALID_ADDRESS, &error); if (addr == LLDB_INVALID_ADDRESS) { result.AppendError("invalid address expression\n"); @@ -1435,6 +1410,7 @@ protected: case eFormatBytesWithASCII: case eFormatComplex: case eFormatEnum: + case eFormatUnicode8: case eFormatUnicode16: case eFormatUnicode32: case eFormatVectorOfChar: @@ -1470,10 +1446,10 @@ protected: // Be careful, getAsInteger with a radix of 16 rejects "0xab" so we // have to special case that: bool success = false; - if (entry.ref.startswith("0x")) - success = !entry.ref.getAsInteger(0, uval64); + if (entry.ref().startswith("0x")) + success = !entry.ref().getAsInteger(0, uval64); if (!success) - success = !entry.ref.getAsInteger(16, uval64); + success = !entry.ref().getAsInteger(16, uval64); if (!success) { result.AppendErrorWithFormat( "'%s' is not a valid hex string value.\n", entry.c_str()); @@ -1491,7 +1467,7 @@ protected: break; } case eFormatBoolean: - uval64 = OptionArgParser::ToBoolean(entry.ref, false, &success); + uval64 = OptionArgParser::ToBoolean(entry.ref(), false, &success); if (!success) { result.AppendErrorWithFormat( "'%s' is not a valid boolean string value.\n", entry.c_str()); @@ -1502,7 +1478,7 @@ protected: break; case eFormatBinary: - if (entry.ref.getAsInteger(2, uval64)) { + if (entry.ref().getAsInteger(2, uval64)) { result.AppendErrorWithFormat( "'%s' is not a valid binary string value.\n", entry.c_str()); result.SetStatus(eReturnStatusFailed); @@ -1521,10 +1497,10 @@ protected: case eFormatCharArray: case eFormatChar: case eFormatCString: { - if (entry.ref.empty()) + if (entry.ref().empty()) break; - size_t len = entry.ref.size(); + size_t len = entry.ref().size(); // Include the NULL for C strings... if (m_format_options.GetFormat() == eFormatCString) ++len; @@ -1541,7 +1517,7 @@ protected: break; } case eFormatDecimal: - if (entry.ref.getAsInteger(0, sval64)) { + if (entry.ref().getAsInteger(0, sval64)) { result.AppendErrorWithFormat( "'%s' is not a valid signed decimal value.\n", entry.c_str()); result.SetStatus(eReturnStatusFailed); @@ -1559,7 +1535,7 @@ protected: case eFormatUnsigned: - if (!entry.ref.getAsInteger(0, uval64)) { + if (!entry.ref().getAsInteger(0, uval64)) { result.AppendErrorWithFormat( "'%s' is not a valid unsigned decimal string value.\n", entry.c_str()); @@ -1577,7 +1553,7 @@ protected: break; case eFormatOctal: - if (entry.ref.getAsInteger(8, uval64)) { + if (entry.ref().getAsInteger(8, uval64)) { result.AppendErrorWithFormat( "'%s' is not a valid octal string value.\n", entry.c_str()); result.SetStatus(eReturnStatusFailed); @@ -1663,7 +1639,7 @@ protected: Status error; lldb::addr_t addr = OptionArgParser::ToAddress( - &m_exe_ctx, command[0].ref, LLDB_INVALID_ADDRESS, &error); + &m_exe_ctx, command[0].ref(), LLDB_INVALID_ADDRESS, &error); if (addr == LLDB_INVALID_ADDRESS) { result.AppendError("invalid address expression"); @@ -1728,7 +1704,7 @@ protected: result.SetStatus(eReturnStatusFailed); } else { if (command.GetArgumentCount() == 1) { - auto load_addr_str = command[0].ref; + auto load_addr_str = command[0].ref(); load_addr = OptionArgParser::ToAddress(&m_exe_ctx, load_addr_str, LLDB_INVALID_ADDRESS, &error); if (error.Fail() || load_addr == LLDB_INVALID_ADDRESS) { diff --git a/source/Commands/CommandObjectMultiword.cpp b/source/Commands/CommandObjectMultiword.cpp index 4011cceb8a26..03a3770d8df7 100644 --- a/source/Commands/CommandObjectMultiword.cpp +++ b/source/Commands/CommandObjectMultiword.cpp @@ -93,9 +93,11 @@ bool CommandObjectMultiword::Execute(const char *args_string, return result.Succeeded(); } - auto sub_command = args[0].ref; - if (sub_command.empty()) + auto sub_command = args[0].ref(); + if (sub_command.empty()) { + result.AppendError("Need to specify a non-empty subcommand."); return result.Succeeded(); + } if (sub_command.equals_lower("help")) { this->CommandObject::GenerateHelpText(result); @@ -136,9 +138,9 @@ bool CommandObjectMultiword::Execute(const char *args_string, if (num_subcmd_matches > 0) { error_msg.append(" Possible completions:"); - for (size_t i = 0; i < matches.GetSize(); i++) { + for (const std::string &match : matches) { error_msg.append("\n\t"); - error_msg.append(matches.GetStringAtIndex(i)); + error_msg.append(match); } } error_msg.append("\n"); @@ -179,12 +181,8 @@ void CommandObjectMultiword::GenerateHelpText(Stream &output_stream) { "'help <command> <subcommand>'.\n"); } -int CommandObjectMultiword::HandleCompletion(CompletionRequest &request) { - // Any of the command matches will provide a complete word, otherwise the - // individual completers will override this. - request.SetWordComplete(true); - - auto arg0 = request.GetParsedLine()[0].ref; +void CommandObjectMultiword::HandleCompletion(CompletionRequest &request) { + auto arg0 = request.GetParsedLine()[0].ref(); if (request.GetCursorIndex() == 0) { StringList new_matches, descriptions; AddNamesMatchingPartialString(m_subcommand_dict, arg0, new_matches, @@ -197,32 +195,28 @@ int CommandObjectMultiword::HandleCompletion(CompletionRequest &request) { StringList temp_matches; CommandObject *cmd_obj = GetSubcommandObject(arg0, &temp_matches); if (cmd_obj != nullptr) { - if (request.GetParsedLine().GetArgumentCount() == 1) { - request.SetWordComplete(true); - } else { + if (request.GetParsedLine().GetArgumentCount() != 1) { request.GetParsedLine().Shift(); - request.SetCursorCharPosition(0); - request.GetParsedLine().AppendArgument(llvm::StringRef()); - return cmd_obj->HandleCompletion(request); + request.AppendEmptyArgument(); + cmd_obj->HandleCompletion(request); } } } - return new_matches.GetSize(); - } else { - StringList new_matches; - CommandObject *sub_command_object = GetSubcommandObject(arg0, &new_matches); - if (sub_command_object == nullptr) { - request.AddCompletions(new_matches); - return request.GetNumberOfMatches(); - } else { - // Remove the one match that we got from calling GetSubcommandObject. - new_matches.DeleteStringAtIndex(0); - request.AddCompletions(new_matches); - request.GetParsedLine().Shift(); - request.SetCursorIndex(request.GetCursorIndex() - 1); - return sub_command_object->HandleCompletion(request); - } + return; } + + StringList new_matches; + CommandObject *sub_command_object = GetSubcommandObject(arg0, &new_matches); + if (sub_command_object == nullptr) { + request.AddCompletions(new_matches); + return; + } + + // Remove the one match that we got from calling GetSubcommandObject. + new_matches.DeleteStringAtIndex(0); + request.AddCompletions(new_matches); + request.ShiftArguments(); + sub_command_object->HandleCompletion(request); } const char *CommandObjectMultiword::GetRepeatCommand(Args ¤t_command_args, @@ -231,7 +225,7 @@ const char *CommandObjectMultiword::GetRepeatCommand(Args ¤t_command_args, if (current_command_args.GetArgumentCount() <= index) return nullptr; CommandObject *sub_command_object = - GetSubcommandObject(current_command_args[index].ref); + GetSubcommandObject(current_command_args[index].ref()); if (sub_command_object == nullptr) return nullptr; return sub_command_object->GetRepeatCommand(current_command_args, index); @@ -360,19 +354,17 @@ Options *CommandObjectProxy::GetOptions() { return nullptr; } -int CommandObjectProxy::HandleCompletion(CompletionRequest &request) { +void CommandObjectProxy::HandleCompletion(CompletionRequest &request) { CommandObject *proxy_command = GetProxyCommandObject(); if (proxy_command) - return proxy_command->HandleCompletion(request); - return 0; + proxy_command->HandleCompletion(request); } -int CommandObjectProxy::HandleArgumentCompletion( +void CommandObjectProxy::HandleArgumentCompletion( CompletionRequest &request, OptionElementVector &opt_element_vector) { CommandObject *proxy_command = GetProxyCommandObject(); if (proxy_command) - return proxy_command->HandleArgumentCompletion(request, opt_element_vector); - return 0; + proxy_command->HandleArgumentCompletion(request, opt_element_vector); } const char *CommandObjectProxy::GetRepeatCommand(Args ¤t_command_args, diff --git a/source/Commands/CommandObjectPlatform.cpp b/source/Commands/CommandObjectPlatform.cpp index 53549cdeee32..fbd13aa37bda 100644 --- a/source/Commands/CommandObjectPlatform.cpp +++ b/source/Commands/CommandObjectPlatform.cpp @@ -58,21 +58,8 @@ static mode_t ParsePermissionString(llvm::StringRef permissions) { return user | group | world; } -static constexpr OptionDefinition g_permissions_options[] = { - // clang-format off - {LLDB_OPT_SET_ALL, false, "permissions-value", 'v', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypePermissionsNumber, "Give out the numeric value for permissions (e.g. 757)"}, - {LLDB_OPT_SET_ALL, false, "permissions-string", 's', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypePermissionsString, "Give out the string value for permissions (e.g. rwxr-xr--)."}, - {LLDB_OPT_SET_ALL, false, "user-read", 'r', OptionParser::eNoArgument, nullptr, {}, 0, eArgTypeNone, "Allow user to read."}, - {LLDB_OPT_SET_ALL, false, "user-write", 'w', OptionParser::eNoArgument, nullptr, {}, 0, eArgTypeNone, "Allow user to write."}, - {LLDB_OPT_SET_ALL, false, "user-exec", 'x', OptionParser::eNoArgument, nullptr, {}, 0, eArgTypeNone, "Allow user to execute."}, - {LLDB_OPT_SET_ALL, false, "group-read", 'R', OptionParser::eNoArgument, nullptr, {}, 0, eArgTypeNone, "Allow group to read."}, - {LLDB_OPT_SET_ALL, false, "group-write", 'W', OptionParser::eNoArgument, nullptr, {}, 0, eArgTypeNone, "Allow group to write."}, - {LLDB_OPT_SET_ALL, false, "group-exec", 'X', OptionParser::eNoArgument, nullptr, {}, 0, eArgTypeNone, "Allow group to execute."}, - {LLDB_OPT_SET_ALL, false, "world-read", 'd', OptionParser::eNoArgument, nullptr, {}, 0, eArgTypeNone, "Allow world to read."}, - {LLDB_OPT_SET_ALL, false, "world-write", 't', OptionParser::eNoArgument, nullptr, {}, 0, eArgTypeNone, "Allow world to write."}, - {LLDB_OPT_SET_ALL, false, "world-exec", 'e', OptionParser::eNoArgument, nullptr, {}, 0, eArgTypeNone, "Allow world to execute."}, - // clang-format on -}; +#define LLDB_OPTIONS_permissions +#include "CommandOptions.inc" class OptionPermissions : public OptionGroup { public: @@ -130,8 +117,7 @@ public: m_permissions |= lldb::eFilePermissionsWorldExecute; break; default: - error.SetErrorStringWithFormat("unrecognized option '%c'", short_option); - break; + llvm_unreachable("Unimplemented option"); } return error; @@ -171,10 +157,9 @@ public: ~CommandObjectPlatformSelect() override = default; - int HandleCompletion(CompletionRequest &request) override { + void HandleCompletion(CompletionRequest &request) override { CommandCompletions::PlatformPluginNames(GetCommandInterpreter(), request, nullptr); - return request.GetNumberOfMatches(); } Options *GetOptions() override { return &m_option_group; } @@ -585,12 +570,8 @@ public: // "platform fread" -static constexpr OptionDefinition g_platform_fread_options[] = { - // clang-format off - { LLDB_OPT_SET_1, false, "offset", 'o', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeIndex, "Offset into the file at which to start reading." }, - { LLDB_OPT_SET_1, false, "count", 'c', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeCount, "Number of bytes to read from the file." }, - // clang-format on -}; +#define LLDB_OPTIONS_platform_fread +#include "CommandOptions.inc" class CommandObjectPlatformFRead : public CommandObjectParsed { public: @@ -650,9 +631,7 @@ protected: option_arg.str().c_str()); break; default: - error.SetErrorStringWithFormat("unrecognized option '%c'", - short_option); - break; + llvm_unreachable("Unimplemented option"); } return error; @@ -678,12 +657,8 @@ protected: // "platform fwrite" -static constexpr OptionDefinition g_platform_fwrite_options[] = { - // clang-format off - { LLDB_OPT_SET_1, false, "offset", 'o', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeIndex, "Offset into the file at which to start reading." }, - { LLDB_OPT_SET_1, false, "data", 'd', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeValue, "Text to write to the file." }, - // clang-format on -}; +#define LLDB_OPTIONS_platform_fwrite +#include "CommandOptions.inc" class CommandObjectPlatformFWrite : public CommandObjectParsed { public: @@ -740,9 +715,7 @@ protected: m_data.assign(option_arg); break; default: - error.SetErrorStringWithFormat("unrecognized option '%c'", - short_option); - break; + llvm_unreachable("Unimplemented option"); } return error; @@ -1056,24 +1029,9 @@ protected: // "platform process list" -static OptionDefinition g_platform_process_list_options[] = { - // clang-format off - { LLDB_OPT_SET_1, false, "pid", 'p', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypePid, "List the process info for a specific process ID." }, - { LLDB_OPT_SET_2, true, "name", 'n', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeProcessName, "Find processes with executable basenames that match a string." }, - { LLDB_OPT_SET_3, true, "ends-with", 'e', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeProcessName, "Find processes with executable basenames that end with a string." }, - { LLDB_OPT_SET_4, true, "starts-with", 's', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeProcessName, "Find processes with executable basenames that start with a string." }, - { LLDB_OPT_SET_5, true, "contains", 'c', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeProcessName, "Find processes with executable basenames that contain a string." }, - { LLDB_OPT_SET_6, true, "regex", 'r', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeRegularExpression, "Find processes with executable basenames that match a regular expression." }, - { LLDB_OPT_SET_FROM_TO(2, 6), false, "parent", 'P', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypePid, "Find processes that have a matching parent process ID." }, - { LLDB_OPT_SET_FROM_TO(2, 6), false, "uid", 'u', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeUnsignedInteger, "Find processes that have a matching user ID." }, - { LLDB_OPT_SET_FROM_TO(2, 6), false, "euid", 'U', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeUnsignedInteger, "Find processes that have a matching effective user ID." }, - { LLDB_OPT_SET_FROM_TO(2, 6), false, "gid", 'g', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeUnsignedInteger, "Find processes that have a matching group ID." }, - { LLDB_OPT_SET_FROM_TO(2, 6), false, "egid", 'G', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeUnsignedInteger, "Find processes that have a matching effective group ID." }, - { LLDB_OPT_SET_FROM_TO(2, 6), false, "arch", 'a', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeArchitecture, "Find processes that have a matching architecture." }, - { LLDB_OPT_SET_FROM_TO(1, 6), false, "show-args", 'A', OptionParser::eNoArgument, nullptr, {}, 0, eArgTypeNone, "Show process arguments instead of the process executable basename." }, - { LLDB_OPT_SET_FROM_TO(1, 6), false, "verbose", 'v', OptionParser::eNoArgument, nullptr, {}, 0, eArgTypeNone, "Enable verbose output." }, - // clang-format on -}; +static PosixPlatformCommandOptionValidator posix_validator; +#define LLDB_OPTIONS_platform_process_list +#include "CommandOptions.inc" class CommandObjectPlatformProcessList : public CommandObjectParsed { public: @@ -1195,23 +1153,6 @@ protected: public: CommandOptions() : Options(), match_info(), show_args(false), verbose(false) { - static llvm::once_flag g_once_flag; - llvm::call_once(g_once_flag, []() { - PosixPlatformCommandOptionValidator *posix_validator = - new PosixPlatformCommandOptionValidator(); - for (auto &Option : g_platform_process_list_options) { - switch (Option.short_option) { - case 'u': - case 'U': - case 'g': - case 'G': - Option.validator = posix_validator; - break; - default: - break; - } - } - }); } ~CommandOptions() override = default; @@ -1323,10 +1264,12 @@ protected: verbose = true; break; - default: - error.SetErrorStringWithFormat("unrecognized option '%c'", - short_option); + case 'x': + match_info.SetMatchAllUsers(true); break; + + default: + llvm_unreachable("Unimplemented option"); } return error; @@ -1397,9 +1340,9 @@ protected: Stream &ostrm = result.GetOutputStream(); for (auto &entry : args.entries()) { lldb::pid_t pid; - if (entry.ref.getAsInteger(0, pid)) { + if (entry.ref().getAsInteger(0, pid)) { result.AppendErrorWithFormat("invalid process ID argument '%s'", - entry.ref.str().c_str()); + entry.ref().str().c_str()); result.SetStatus(eReturnStatusFailed); break; } else { @@ -1436,14 +1379,8 @@ protected: } }; -static constexpr OptionDefinition g_platform_process_attach_options[] = { - // clang-format off - { LLDB_OPT_SET_ALL, false, "plugin", 'P', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypePlugin, "Name of the process plugin you want to use." }, - { LLDB_OPT_SET_1, false, "pid", 'p', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypePid, "The process ID of an existing process to attach to." }, - { LLDB_OPT_SET_2, false, "name", 'n', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeProcessName, "The name of the process to attach to." }, - { LLDB_OPT_SET_2, false, "waitfor", 'w', OptionParser::eNoArgument, nullptr, {}, 0, eArgTypeNone, "Wait for the process with <process-name> to launch." }, - // clang-format on -}; +#define LLDB_OPTIONS_platform_process_attach +#include "CommandOptions.inc" class CommandObjectPlatformProcessAttach : public CommandObjectParsed { public: @@ -1486,9 +1423,7 @@ public: break; default: - error.SetErrorStringWithFormat("invalid short option character '%c'", - short_option); - break; + llvm_unreachable("Unimplemented option"); } return error; } @@ -1501,7 +1436,7 @@ public: return llvm::makeArrayRef(g_platform_process_attach_options); } - bool HandleOptionArgumentCompletion( + void HandleOptionArgumentCompletion( CompletionRequest &request, OptionElementVector &opt_element_vector, int opt_element_index, CommandInterpreter &interpreter) override { int opt_arg_pos = opt_element_vector[opt_element_index].opt_arg_pos; @@ -1509,37 +1444,36 @@ public: // We are only completing the name option for now... - if (GetDefinitions()[opt_defs_index].short_option == 'n') { - // Are we in the name? + // Are we in the name? + if (GetDefinitions()[opt_defs_index].short_option != 'n') + return; - // Look to see if there is a -P argument provided, and if so use that - // plugin, otherwise use the default plugin. + // Look to see if there is a -P argument provided, and if so use that + // plugin, otherwise use the default plugin. - const char *partial_name = nullptr; - partial_name = request.GetParsedLine().GetArgumentAtIndex(opt_arg_pos); + const char *partial_name = nullptr; + partial_name = request.GetParsedLine().GetArgumentAtIndex(opt_arg_pos); - PlatformSP platform_sp(interpreter.GetPlatform(true)); - if (platform_sp) { - ProcessInstanceInfoList process_infos; - ProcessInstanceInfoMatch match_info; - if (partial_name) { - match_info.GetProcessInfo().GetExecutableFile().SetFile( - partial_name, FileSpec::Style::native); - match_info.SetNameMatchType(NameMatch::StartsWith); - } - platform_sp->FindProcesses(match_info, process_infos); - const uint32_t num_matches = process_infos.GetSize(); - if (num_matches > 0) { - for (uint32_t i = 0; i < num_matches; ++i) { - request.AddCompletion(llvm::StringRef( - process_infos.GetProcessNameAtIndex(i), - process_infos.GetProcessNameLengthAtIndex(i))); - } - } - } + PlatformSP platform_sp(interpreter.GetPlatform(true)); + if (!platform_sp) + return; + + ProcessInstanceInfoList process_infos; + ProcessInstanceInfoMatch match_info; + if (partial_name) { + match_info.GetProcessInfo().GetExecutableFile().SetFile( + partial_name, FileSpec::Style::native); + match_info.SetNameMatchType(NameMatch::StartsWith); } + platform_sp->FindProcesses(match_info, process_infos); + const uint32_t num_matches = process_infos.GetSize(); + if (num_matches == 0) + return; - return false; + for (uint32_t i = 0; i < num_matches; ++i) { + request.AddCompletion(process_infos.GetProcessNameAtIndex(i)); + } + return; } // Options table: Required for subclasses of Options. @@ -1615,11 +1549,8 @@ private: }; // "platform shell" -static constexpr OptionDefinition g_platform_shell_options[] = { - // clang-format off - { LLDB_OPT_SET_ALL, false, "timeout", 't', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeValue, "Seconds to wait for the remote host to finish running the command." }, - // clang-format on -}; +#define LLDB_OPTIONS_platform_shell +#include "CommandOptions.inc" class CommandObjectPlatformShell : public CommandObjectRaw { public: @@ -1650,9 +1581,7 @@ public: timeout = std::chrono::seconds(timeout_sec); break; default: - error.SetErrorStringWithFormat("invalid short option character '%c'", - short_option); - break; + llvm_unreachable("Unimplemented option"); } return error; diff --git a/source/Commands/CommandObjectPlugin.cpp b/source/Commands/CommandObjectPlugin.cpp index 89e01ba52027..b70885061385 100644 --- a/source/Commands/CommandObjectPlugin.cpp +++ b/source/Commands/CommandObjectPlugin.cpp @@ -37,13 +37,12 @@ public: ~CommandObjectPluginLoad() override = default; - int HandleArgumentCompletion( - CompletionRequest &request, - OptionElementVector &opt_element_vector) override { + void + HandleArgumentCompletion(CompletionRequest &request, + OptionElementVector &opt_element_vector) override { CommandCompletions::InvokeCommonCompletionCallbacks( GetCommandInterpreter(), CommandCompletions::eDiskFileCompletion, request, nullptr); - return request.GetNumberOfMatches(); } protected: @@ -58,7 +57,7 @@ protected: Status error; - FileSpec dylib_fspec(command[0].ref); + FileSpec dylib_fspec(command[0].ref()); FileSystem::Instance().Resolve(dylib_fspec); if (GetDebugger().LoadPlugin(dylib_fspec, error)) diff --git a/source/Commands/CommandObjectProcess.cpp b/source/Commands/CommandObjectProcess.cpp index b20a2d533332..e5aa78afabb3 100644 --- a/source/Commands/CommandObjectProcess.cpp +++ b/source/Commands/CommandObjectProcess.cpp @@ -127,14 +127,13 @@ public: ~CommandObjectProcessLaunch() override = default; - int HandleArgumentCompletion( - CompletionRequest &request, - OptionElementVector &opt_element_vector) override { + void + HandleArgumentCompletion(CompletionRequest &request, + OptionElementVector &opt_element_vector) override { CommandCompletions::InvokeCommonCompletionCallbacks( GetCommandInterpreter(), CommandCompletions::eDiskFileCompletion, request, nullptr); - return request.GetNumberOfMatches(); } Options *GetOptions() override { return &m_options; } @@ -255,16 +254,8 @@ protected: ProcessLaunchCommandOptions m_options; }; -static constexpr OptionDefinition g_process_attach_options[] = { - // clang-format off - { LLDB_OPT_SET_ALL, false, "continue", 'c', OptionParser::eNoArgument, nullptr, {}, 0, eArgTypeNone, "Immediately continue the process once attached." }, - { LLDB_OPT_SET_ALL, false, "plugin", 'P', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypePlugin, "Name of the process plugin you want to use." }, - { LLDB_OPT_SET_1, false, "pid", 'p', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypePid, "The process ID of an existing process to attach to." }, - { LLDB_OPT_SET_2, false, "name", 'n', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeProcessName, "The name of the process to attach to." }, - { LLDB_OPT_SET_2, false, "include-existing", 'i', OptionParser::eNoArgument, nullptr, {}, 0, eArgTypeNone, "Include existing processes when doing attach -w." }, - { LLDB_OPT_SET_2, false, "waitfor", 'w', OptionParser::eNoArgument, nullptr, {}, 0, eArgTypeNone, "Wait for the process with <process-name> to launch." }, - // clang-format on -}; +#define LLDB_OPTIONS_process_attach +#include "CommandOptions.inc" #pragma mark CommandObjectProcessAttach class CommandObjectProcessAttach : public CommandObjectProcessLaunchOrAttach { @@ -316,9 +307,7 @@ public: break; default: - error.SetErrorStringWithFormat("invalid short option character '%c'", - short_option); - break; + llvm_unreachable("Unimplemented option"); } return error; } @@ -331,7 +320,7 @@ public: return llvm::makeArrayRef(g_process_attach_options); } - bool HandleOptionArgumentCompletion( + void HandleOptionArgumentCompletion( CompletionRequest &request, OptionElementVector &opt_element_vector, int opt_element_index, CommandInterpreter &interpreter) override { int opt_arg_pos = opt_element_vector[opt_element_index].opt_arg_pos; @@ -339,37 +328,33 @@ public: // We are only completing the name option for now... - if (GetDefinitions()[opt_defs_index].short_option == 'n') { - // Are we in the name? - - // Look to see if there is a -P argument provided, and if so use that - // plugin, otherwise use the default plugin. - - const char *partial_name = nullptr; - partial_name = request.GetParsedLine().GetArgumentAtIndex(opt_arg_pos); - - PlatformSP platform_sp(interpreter.GetPlatform(true)); - if (platform_sp) { - ProcessInstanceInfoList process_infos; - ProcessInstanceInfoMatch match_info; - if (partial_name) { - match_info.GetProcessInfo().GetExecutableFile().SetFile( - partial_name, FileSpec::Style::native); - match_info.SetNameMatchType(NameMatch::StartsWith); - } - platform_sp->FindProcesses(match_info, process_infos); - const size_t num_matches = process_infos.GetSize(); - if (num_matches > 0) { - for (size_t i = 0; i < num_matches; ++i) { - request.AddCompletion(llvm::StringRef( - process_infos.GetProcessNameAtIndex(i), - process_infos.GetProcessNameLengthAtIndex(i))); - } - } - } + // Are we in the name? + if (GetDefinitions()[opt_defs_index].short_option != 'n') + return; + + // Look to see if there is a -P argument provided, and if so use that + // plugin, otherwise use the default plugin. + + const char *partial_name = nullptr; + partial_name = request.GetParsedLine().GetArgumentAtIndex(opt_arg_pos); + + PlatformSP platform_sp(interpreter.GetPlatform(true)); + if (!platform_sp) + return; + ProcessInstanceInfoList process_infos; + ProcessInstanceInfoMatch match_info; + if (partial_name) { + match_info.GetProcessInfo().GetExecutableFile().SetFile( + partial_name, FileSpec::Style::native); + match_info.SetNameMatchType(NameMatch::StartsWith); + } + platform_sp->FindProcesses(match_info, process_infos); + const size_t num_matches = process_infos.GetSize(); + if (num_matches == 0) + return; + for (size_t i = 0; i < num_matches; ++i) { + request.AddCompletion(process_infos.GetProcessNameAtIndex(i)); } - - return false; } // Instance variables to hold the values for command options. @@ -444,7 +429,6 @@ protected: result.AppendMessage(stream.GetString()); result.SetStatus(eReturnStatusSuccessFinishNoResult); result.SetDidChangeProcessState(true); - result.SetAbnormalStopWasExpected(true); } else { result.AppendError( "no error returned from Target::Attach, and target has no process"); @@ -505,11 +489,8 @@ protected: // CommandObjectProcessContinue -static constexpr OptionDefinition g_process_continue_options[] = { - // clang-format off - { LLDB_OPT_SET_ALL, false, "ignore-count",'i', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeUnsignedInteger, "Ignore <N> crossings of the breakpoint (if it exists) for the currently selected thread." } - // clang-format on -}; +#define LLDB_OPTIONS_process_continue +#include "CommandOptions.inc" #pragma mark CommandObjectProcessContinue @@ -550,9 +531,7 @@ protected: break; default: - error.SetErrorStringWithFormat("invalid short option character '%c'", - short_option); - break; + llvm_unreachable("Unimplemented option"); } return error; } @@ -666,11 +645,8 @@ protected: }; // CommandObjectProcessDetach -static constexpr OptionDefinition g_process_detach_options[] = { - // clang-format off - { LLDB_OPT_SET_1, false, "keep-stopped", 's', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeBoolean, "Whether or not the process should be kept stopped on detach (if possible)." }, - // clang-format on -}; +#define LLDB_OPTIONS_process_detach +#include "CommandOptions.inc" #pragma mark CommandObjectProcessDetach @@ -703,9 +679,7 @@ public: } break; default: - error.SetErrorStringWithFormat("invalid short option character '%c'", - short_option); - break; + llvm_unreachable("Unimplemented option"); } return error; } @@ -762,12 +736,8 @@ protected: }; // CommandObjectProcessConnect - -static constexpr OptionDefinition g_process_connect_options[] = { - // clang-format off - { LLDB_OPT_SET_ALL, false, "plugin", 'p', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypePlugin, "Name of the process plugin you want to use." }, - // clang-format on -}; +#define LLDB_OPTIONS_process_connect +#include "CommandOptions.inc" #pragma mark CommandObjectProcessConnect @@ -794,9 +764,7 @@ public: break; default: - error.SetErrorStringWithFormat("invalid short option character '%c'", - short_option); - break; + llvm_unreachable("Unimplemented option"); } return error; } @@ -887,12 +855,8 @@ public: }; // CommandObjectProcessLoad - -static constexpr OptionDefinition g_process_load_options[] = { - // clang-format off - { LLDB_OPT_SET_ALL, false, "install", 'i', OptionParser::eOptionalArgument, nullptr, {}, 0, eArgTypePath, "Install the shared library to the target. If specified without an argument then the library will installed in the current working directory." }, - // clang-format on -}; +#define LLDB_OPTIONS_process_load +#include "CommandOptions.inc" #pragma mark CommandObjectProcessLoad @@ -919,9 +883,7 @@ public: install_path.SetFile(option_arg, FileSpec::Style::native); break; default: - error.SetErrorStringWithFormat("invalid short option character '%c'", - short_option); - break; + llvm_unreachable("Unimplemented option"); } return error; } @@ -960,7 +922,7 @@ protected: for (auto &entry : command.entries()) { Status error; PlatformSP platform = process->GetTarget().GetPlatform(); - llvm::StringRef image_path = entry.ref; + llvm::StringRef image_path = entry.ref(); uint32_t image_token = LLDB_INVALID_IMAGE_TOKEN; if (!m_options.do_install) { @@ -1022,9 +984,9 @@ protected: for (auto &entry : command.entries()) { uint32_t image_token; - if (entry.ref.getAsInteger(0, image_token)) { + if (entry.ref().getAsInteger(0, image_token)) { result.AppendErrorWithFormat("invalid image index argument '%s'", - entry.ref.str().c_str()); + entry.ref().str().c_str()); result.SetStatus(eReturnStatusFailed); break; } else { @@ -1271,14 +1233,8 @@ public: }; // CommandObjectProcessHandle - -static constexpr OptionDefinition g_process_handle_options[] = { - // clang-format off - { LLDB_OPT_SET_1, false, "stop", 's', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeBoolean, "Whether or not the process should be stopped if the signal is received." }, - { LLDB_OPT_SET_1, false, "notify", 'n', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeBoolean, "Whether or not the debugger should notify the user if the signal is received." }, - { LLDB_OPT_SET_1, false, "pass", 'p', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeBoolean, "Whether or not the signal should be passed to the process." } - // clang-format on -}; +#define LLDB_OPTIONS_process_handle +#include "CommandOptions.inc" #pragma mark CommandObjectProcessHandle @@ -1306,9 +1262,7 @@ public: pass = option_arg; break; default: - error.SetErrorStringWithFormat("invalid short option character '%c'", - short_option); - break; + llvm_unreachable("Unimplemented option"); } return error; } @@ -1335,7 +1289,7 @@ public: "Manage LLDB handling of OS signals for the " "current target process. Defaults to showing " "current policy.", - nullptr), + nullptr, eCommandRequiresTarget), m_options() { SetHelpLong("\nIf no signals are specified, update them all. If no update " "option is specified, list the current values."); @@ -1420,15 +1374,7 @@ public: protected: bool DoExecute(Args &signal_args, CommandReturnObject &result) override { - TargetSP target_sp = GetDebugger().GetSelectedTarget(); - - if (!target_sp) { - result.AppendError("No current target;" - " cannot handle signals until you have a valid target " - "and process.\n"); - result.SetStatus(eReturnStatusFailed); - return false; - } + Target *target_sp = &GetSelectedTarget(); ProcessSP process_sp = target_sp->GetProcessSP(); diff --git a/source/Commands/CommandObjectRegister.cpp b/source/Commands/CommandObjectRegister.cpp index 34482a8b1e4f..13266f8fce35 100644 --- a/source/Commands/CommandObjectRegister.cpp +++ b/source/Commands/CommandObjectRegister.cpp @@ -32,14 +32,8 @@ using namespace lldb; using namespace lldb_private; // "register read" - -static constexpr OptionDefinition g_register_read_options[] = { - // clang-format off - { LLDB_OPT_SET_ALL, false, "alternate", 'A', OptionParser::eNoArgument, nullptr, {}, 0, eArgTypeNone, "Display register names using the alternate register name if there is one." }, - { LLDB_OPT_SET_1, false, "set", 's', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeIndex, "Specify which register sets to dump by index." }, - { LLDB_OPT_SET_2, false, "all", 'a', OptionParser::eNoArgument, nullptr, {}, 0, eArgTypeNone, "Show all register sets." }, - // clang-format on -}; +#define LLDB_OPTIONS_register_read +#include "CommandOptions.inc" class CommandObjectRegisterRead : public CommandObjectParsed { public: @@ -212,7 +206,7 @@ protected: // consistent towards the user and allow them to say reg read $rbx - // internally, however, we should be strict and not allow ourselves // to call our registers $rbx in our own API - auto arg_str = entry.ref; + auto arg_str = entry.ref(); arg_str.consume_front("$"); reg_info = reg_ctx->GetRegisterInfoByName(arg_str); @@ -278,9 +272,7 @@ protected: break; default: - error.SetErrorStringWithFormat("unrecognized short option '%c'", - short_option); - break; + llvm_unreachable("Unimplemented option"); } return error; } @@ -343,8 +335,8 @@ protected: "register write takes exactly 2 arguments: <reg-name> <value>"); result.SetStatus(eReturnStatusFailed); } else { - auto reg_name = command[0].ref; - auto value_str = command[1].ref; + auto reg_name = command[0].ref(); + auto value_str = command[1].ref(); // in most LLDB commands we accept $rbx as the name for register RBX - // and here we would reject it and non-existant. we should be more diff --git a/source/Commands/CommandObjectReproducer.cpp b/source/Commands/CommandObjectReproducer.cpp index 4b0e9e36d202..dc4579c20fc2 100644 --- a/source/Commands/CommandObjectReproducer.cpp +++ b/source/Commands/CommandObjectReproducer.cpp @@ -8,6 +8,8 @@ #include "CommandObjectReproducer.h" +#include "lldb/Host/OptionParser.h" +#include "lldb/Utility/GDBRemote.h" #include "lldb/Utility/Reproducer.h" #include "lldb/Interpreter/CommandInterpreter.h" @@ -16,7 +18,58 @@ #include "lldb/Interpreter/OptionGroupBoolean.h" using namespace lldb; +using namespace llvm; using namespace lldb_private; +using namespace lldb_private::repro; + +enum ReproducerProvider { + eReproducerProviderCommands, + eReproducerProviderFiles, + eReproducerProviderGDB, + eReproducerProviderVersion, + eReproducerProviderWorkingDirectory, + eReproducerProviderNone +}; + +static constexpr OptionEnumValueElement g_reproducer_provider_type[] = { + { + eReproducerProviderCommands, + "commands", + "Command Interpreter Commands", + }, + { + eReproducerProviderFiles, + "files", + "Files", + }, + { + eReproducerProviderGDB, + "gdb", + "GDB Remote Packets", + }, + { + eReproducerProviderVersion, + "version", + "Version", + }, + { + eReproducerProviderWorkingDirectory, + "cwd", + "Working Directory", + }, + { + eReproducerProviderNone, + "none", + "None", + }, +}; + +static constexpr OptionEnumValues ReproducerProviderType() { + return OptionEnumValues(g_reproducer_provider_type); +} + +#define LLDB_OPTIONS_reproducer +#include "CommandOptions.inc" class CommandObjectReproducerGenerate : public CommandObjectParsed { public: @@ -38,10 +91,10 @@ protected: return false; } - auto &r = repro::Reproducer::Instance(); + auto &r = Reproducer::Instance(); if (auto generator = r.GetGenerator()) { generator->Keep(); - } else if (r.GetLoader()) { + } else if (r.IsReplaying()) { // Make this operation a NOP in replay mode. result.SetStatus(eReturnStatusSuccessFinishNoResult); return result.Succeeded(); @@ -84,10 +137,10 @@ protected: return false; } - auto &r = repro::Reproducer::Instance(); - if (r.GetGenerator()) { + auto &r = Reproducer::Instance(); + if (r.IsCapturing()) { result.GetOutputStream() << "Reproducer is in capture mode.\n"; - } else if (r.GetLoader()) { + } else if (r.IsReplaying()) { result.GetOutputStream() << "Reproducer is in replay mode.\n"; } else { result.GetOutputStream() << "Reproducer is off.\n"; @@ -98,17 +151,235 @@ protected: } }; +static void SetError(CommandReturnObject &result, Error err) { + result.GetErrorStream().Printf("error: %s\n", + toString(std::move(err)).c_str()); + result.SetStatus(eReturnStatusFailed); +} + +class CommandObjectReproducerDump : public CommandObjectParsed { +public: + CommandObjectReproducerDump(CommandInterpreter &interpreter) + : CommandObjectParsed(interpreter, "reproducer dump", + "Dump the information contained in a reproducer. " + "If no reproducer is specified during replay, it " + "dumps the content of the current reproducer.", + nullptr) {} + + ~CommandObjectReproducerDump() override = default; + + Options *GetOptions() override { return &m_options; } + + class CommandOptions : public Options { + public: + CommandOptions() : Options(), file() {} + + ~CommandOptions() override = default; + + Status SetOptionValue(uint32_t option_idx, StringRef option_arg, + ExecutionContext *execution_context) override { + Status error; + const int short_option = m_getopt_table[option_idx].val; + + switch (short_option) { + case 'f': + file.SetFile(option_arg, FileSpec::Style::native); + FileSystem::Instance().Resolve(file); + break; + case 'p': + provider = (ReproducerProvider)OptionArgParser::ToOptionEnum( + option_arg, GetDefinitions()[option_idx].enum_values, 0, error); + if (!error.Success()) + error.SetErrorStringWithFormat("unrecognized value for provider '%s'", + option_arg.str().c_str()); + break; + default: + llvm_unreachable("Unimplemented option"); + } + + return error; + } + + void OptionParsingStarting(ExecutionContext *execution_context) override { + file.Clear(); + provider = eReproducerProviderNone; + } + + ArrayRef<OptionDefinition> GetDefinitions() override { + return makeArrayRef(g_reproducer_options); + } + + FileSpec file; + ReproducerProvider provider = eReproducerProviderNone; + }; + +protected: + bool DoExecute(Args &command, CommandReturnObject &result) override { + if (!command.empty()) { + result.AppendErrorWithFormat("'%s' takes no arguments", + m_cmd_name.c_str()); + return false; + } + + // If no reproducer path is specified, use the loader currently used for + // replay. Otherwise create a new loader just for dumping. + llvm::Optional<Loader> loader_storage; + Loader *loader = nullptr; + if (!m_options.file) { + loader = Reproducer::Instance().GetLoader(); + if (loader == nullptr) { + result.SetError( + "Not specifying a reproducer is only support during replay."); + result.SetStatus(eReturnStatusSuccessFinishNoResult); + return false; + } + } else { + loader_storage.emplace(m_options.file); + loader = &(*loader_storage); + if (Error err = loader->LoadIndex()) { + SetError(result, std::move(err)); + return false; + } + } + + // If we get here we should have a valid loader. + assert(loader); + + switch (m_options.provider) { + case eReproducerProviderFiles: { + FileSpec vfs_mapping = loader->GetFile<FileProvider::Info>(); + + // Read the VFS mapping. + ErrorOr<std::unique_ptr<MemoryBuffer>> buffer = + vfs::getRealFileSystem()->getBufferForFile(vfs_mapping.GetPath()); + if (!buffer) { + SetError(result, errorCodeToError(buffer.getError())); + return false; + } + + // Initialize a VFS from the given mapping. + IntrusiveRefCntPtr<vfs::FileSystem> vfs = vfs::getVFSFromYAML( + std::move(buffer.get()), nullptr, vfs_mapping.GetPath()); + + // Dump the VFS to a buffer. + std::string str; + raw_string_ostream os(str); + static_cast<vfs::RedirectingFileSystem &>(*vfs).dump(os); + os.flush(); + + // Return the string. + result.AppendMessage(str); + result.SetStatus(eReturnStatusSuccessFinishResult); + return true; + } + case eReproducerProviderVersion: { + Expected<std::string> version = loader->LoadBuffer<VersionProvider>(); + if (!version) { + SetError(result, version.takeError()); + return false; + } + result.AppendMessage(*version); + result.SetStatus(eReturnStatusSuccessFinishResult); + return true; + } + case eReproducerProviderWorkingDirectory: { + Expected<std::string> cwd = + loader->LoadBuffer<WorkingDirectoryProvider>(); + if (!cwd) { + SetError(result, cwd.takeError()); + return false; + } + result.AppendMessage(*cwd); + result.SetStatus(eReturnStatusSuccessFinishResult); + return true; + } + case eReproducerProviderCommands: { + // Create a new command loader. + std::unique_ptr<repro::CommandLoader> command_loader = + repro::CommandLoader::Create(loader); + if (!command_loader) { + SetError(result, + make_error<StringError>(llvm::inconvertibleErrorCode(), + "Unable to create command loader.")); + return false; + } + + // Iterate over the command files and dump them. + while (true) { + llvm::Optional<std::string> command_file = + command_loader->GetNextFile(); + if (!command_file) + break; + + auto command_buffer = llvm::MemoryBuffer::getFile(*command_file); + if (auto err = command_buffer.getError()) { + SetError(result, errorCodeToError(err)); + return false; + } + result.AppendMessage((*command_buffer)->getBuffer()); + } + + result.SetStatus(eReturnStatusSuccessFinishResult); + return true; + } + case eReproducerProviderGDB: { + FileSpec gdb_file = loader->GetFile<ProcessGDBRemoteProvider::Info>(); + auto error_or_file = MemoryBuffer::getFile(gdb_file.GetPath()); + if (auto err = error_or_file.getError()) { + SetError(result, errorCodeToError(err)); + return false; + } + + std::vector<GDBRemotePacket> packets; + yaml::Input yin((*error_or_file)->getBuffer()); + yin >> packets; + + if (auto err = yin.error()) { + SetError(result, errorCodeToError(err)); + return false; + } + + for (GDBRemotePacket &packet : packets) { + packet.Dump(result.GetOutputStream()); + } + + result.SetStatus(eReturnStatusSuccessFinishResult); + return true; + } + case eReproducerProviderNone: + result.SetError("No valid provider specified."); + return false; + } + + result.SetStatus(eReturnStatusSuccessFinishNoResult); + return result.Succeeded(); + } + +private: + CommandOptions m_options; +}; + CommandObjectReproducer::CommandObjectReproducer( CommandInterpreter &interpreter) : CommandObjectMultiword( interpreter, "reproducer", - "Commands to inspect and manipulate the reproducer functionality.", - "log <subcommand> [<command-options>]") { + "Commands for manipulating reproducers. Reproducers make it possible " + "to capture full debug sessions with all its dependencies. The " + "resulting reproducer is used to replay the debug session while " + "debugging the debugger.\n" + "Because reproducers need the whole the debug session from " + "beginning to end, you need to launch the debugger in capture or " + "replay mode, commonly though the command line driver.\n" + "Reproducers are unrelated record-replay debugging, as you cannot " + "interact with the debugger during replay.\n", + "reproducer <subcommand> [<subcommand-options>]") { LoadSubCommand( "generate", CommandObjectSP(new CommandObjectReproducerGenerate(interpreter))); LoadSubCommand("status", CommandObjectSP( new CommandObjectReproducerStatus(interpreter))); + LoadSubCommand("dump", + CommandObjectSP(new CommandObjectReproducerDump(interpreter))); } CommandObjectReproducer::~CommandObjectReproducer() = default; diff --git a/source/Commands/CommandObjectSettings.cpp b/source/Commands/CommandObjectSettings.cpp index 55a0002c5997..248a04613d7a 100644 --- a/source/Commands/CommandObjectSettings.cpp +++ b/source/Commands/CommandObjectSettings.cpp @@ -20,11 +20,8 @@ using namespace lldb; using namespace lldb_private; // CommandObjectSettingsSet - -static constexpr OptionDefinition g_settings_set_options[] = { #define LLDB_OPTIONS_settings_set #include "CommandOptions.inc" -}; class CommandObjectSettingsSet : public CommandObjectRaw { public: @@ -107,9 +104,7 @@ insert-before or insert-after."); m_global = true; break; default: - error.SetErrorStringWithFormat("unrecognized options '%c'", - short_option); - break; + llvm_unreachable("Unimplemented option"); } return error; @@ -129,15 +124,14 @@ insert-before or insert-after."); bool m_force; }; - int HandleArgumentCompletion( - CompletionRequest &request, - OptionElementVector &opt_element_vector) override { + void + HandleArgumentCompletion(CompletionRequest &request, + OptionElementVector &opt_element_vector) override { const size_t argc = request.GetParsedLine().GetArgumentCount(); const char *arg = nullptr; - int setting_var_idx; - for (setting_var_idx = 0; setting_var_idx < static_cast<int>(argc); - ++setting_var_idx) { + size_t setting_var_idx; + for (setting_var_idx = 0; setting_var_idx < argc; ++setting_var_idx) { arg = request.GetParsedLine().GetArgumentAtIndex(setting_var_idx); if (arg && arg[0] != '-') break; // We found our setting variable name index @@ -147,27 +141,27 @@ insert-before or insert-after."); CommandCompletions::InvokeCommonCompletionCallbacks( GetCommandInterpreter(), CommandCompletions::eSettingsNameCompletion, request, nullptr); - } else { + return; + } arg = request.GetParsedLine().GetArgumentAtIndex(request.GetCursorIndex()); - if (arg) { - if (arg[0] == '-') { - // Complete option name - } else { - // Complete setting value - const char *setting_var_name = - request.GetParsedLine().GetArgumentAtIndex(setting_var_idx); - Status error; - lldb::OptionValueSP value_sp(GetDebugger().GetPropertyValue( - &m_exe_ctx, setting_var_name, false, error)); - if (value_sp) { - value_sp->AutoComplete(m_interpreter, request); - } - } - } - } - return request.GetNumberOfMatches(); + if (!arg) + return; + + // Complete option name + if (arg[0] != '-') + return; + + // Complete setting value + const char *setting_var_name = + request.GetParsedLine().GetArgumentAtIndex(setting_var_idx); + Status error; + lldb::OptionValueSP value_sp(GetDebugger().GetPropertyValue( + &m_exe_ctx, setting_var_name, false, error)); + if (!value_sp) + return; + value_sp->AutoComplete(m_interpreter, request); } protected: @@ -210,16 +204,13 @@ protected: } // Split the raw command into var_name and value pair. - llvm::StringRef raw_str(command); - std::string var_value_string = raw_str.split(var_name).second.str(); - const char *var_value_cstr = - Args::StripSpaces(var_value_string, true, false, false); + llvm::StringRef var_value(command); + var_value = var_value.split(var_name).second.ltrim(); Status error; - if (m_options.m_global) { + if (m_options.m_global) error = GetDebugger().SetPropertyValue(nullptr, eVarSetOperationAssign, - var_name, var_value_cstr); - } + var_name, var_value); if (error.Success()) { // FIXME this is the same issue as the one in commands script import @@ -230,7 +221,7 @@ protected: ExecutionContext exe_ctx(m_exe_ctx); m_exe_ctx.Clear(); error = GetDebugger().SetPropertyValue(&exe_ctx, eVarSetOperationAssign, - var_name, var_value_cstr); + var_name, var_value); } if (error.Fail()) { @@ -274,13 +265,12 @@ public: ~CommandObjectSettingsShow() override = default; - int HandleArgumentCompletion( - CompletionRequest &request, - OptionElementVector &opt_element_vector) override { + void + HandleArgumentCompletion(CompletionRequest &request, + OptionElementVector &opt_element_vector) override { CommandCompletions::InvokeCommonCompletionCallbacks( GetCommandInterpreter(), CommandCompletions::eSettingsNameCompletion, request, nullptr); - return request.GetNumberOfMatches(); } protected: @@ -290,7 +280,7 @@ protected: if (!args.empty()) { for (const auto &arg : args) { Status error(GetDebugger().DumpPropertyValue( - &m_exe_ctx, result.GetOutputStream(), arg.ref, + &m_exe_ctx, result.GetOutputStream(), arg.ref(), OptionValue::eDumpGroupValue)); if (error.Success()) { result.GetOutputStream().EOL(); @@ -309,11 +299,8 @@ protected: }; // CommandObjectSettingsWrite -- Write settings to file - -static constexpr OptionDefinition g_settings_write_options[] = { #define LLDB_OPTIONS_settings_write #include "CommandOptions.inc" -}; class CommandObjectSettingsWrite : public CommandObjectParsed { public: @@ -363,9 +350,7 @@ public: m_append = true; break; default: - error.SetErrorStringWithFormat("unrecognized option '%c'", - short_option); - break; + llvm_unreachable("Unimplemented option"); } return error; @@ -390,12 +375,11 @@ protected: FileSpec file_spec(m_options.m_filename); FileSystem::Instance().Resolve(file_spec); std::string path(file_spec.GetPath()); - uint32_t options = File::OpenOptions::eOpenOptionWrite | - File::OpenOptions::eOpenOptionCanCreate; + auto options = File::eOpenOptionWrite | File::eOpenOptionCanCreate; if (m_options.m_append) - options |= File::OpenOptions::eOpenOptionAppend; + options |= File::eOpenOptionAppend; else - options |= File::OpenOptions::eOpenOptionTruncate; + options |= File::eOpenOptionTruncate; StreamFile out_file(path.c_str(), options, lldb::eFilePermissionsFileDefault); @@ -417,7 +401,7 @@ protected: for (const auto &arg : args) { Status error(GetDebugger().DumpPropertyValue( - &clean_ctx, out_file, arg.ref, OptionValue::eDumpGroupExport)); + &clean_ctx, out_file, arg.ref(), OptionValue::eDumpGroupExport)); if (!error.Success()) { result.AppendError(error.AsCString()); result.SetStatus(eReturnStatusFailed); @@ -432,11 +416,8 @@ private: }; // CommandObjectSettingsRead -- Read settings from file - -static constexpr OptionDefinition g_settings_read_options[] = { #define LLDB_OPTIONS_settings_read #include "CommandOptions.inc" -}; class CommandObjectSettingsRead : public CommandObjectParsed { public: @@ -467,9 +448,7 @@ public: m_filename.assign(option_arg); break; default: - error.SetErrorStringWithFormat("unrecognized option '%c'", - short_option); - break; + llvm_unreachable("Unimplemented option"); } return error; @@ -536,13 +515,12 @@ public: ~CommandObjectSettingsList() override = default; - int HandleArgumentCompletion( - CompletionRequest &request, - OptionElementVector &opt_element_vector) override { + void + HandleArgumentCompletion(CompletionRequest &request, + OptionElementVector &opt_element_vector) override { CommandCompletions::InvokeCommonCompletionCallbacks( GetCommandInterpreter(), CommandCompletions::eSettingsNameCompletion, request, nullptr); - return request.GetNumberOfMatches(); } protected: @@ -622,14 +600,15 @@ public: ~CommandObjectSettingsRemove() override = default; - int HandleArgumentCompletion( - CompletionRequest &request, - OptionElementVector &opt_element_vector) override { + bool WantsCompletion() override { return true; } + + void + HandleArgumentCompletion(CompletionRequest &request, + OptionElementVector &opt_element_vector) override { if (request.GetCursorIndex() < 2) CommandCompletions::InvokeCommonCompletionCallbacks( GetCommandInterpreter(), CommandCompletions::eSettingsNameCompletion, request, nullptr); - return request.GetNumberOfMatches(); } protected: @@ -645,8 +624,8 @@ protected: const size_t argc = cmd_args.GetArgumentCount(); if (argc == 0) { - result.AppendError("'settings set' takes an array or dictionary item, or " - "an array followed by one or more indexes, or a " + result.AppendError("'settings remove' takes an array or dictionary item, " + "or an array followed by one or more indexes, or a " "dictionary followed by one or more key names to " "remove"); result.SetStatus(eReturnStatusFailed); @@ -656,19 +635,17 @@ protected: const char *var_name = cmd_args.GetArgumentAtIndex(0); if ((var_name == nullptr) || (var_name[0] == '\0')) { result.AppendError( - "'settings set' command requires a valid variable name"); + "'settings remove' command requires a valid variable name"); result.SetStatus(eReturnStatusFailed); return false; } // Split the raw command into var_name and value pair. - llvm::StringRef raw_str(command); - std::string var_value_string = raw_str.split(var_name).second.str(); - const char *var_value_cstr = - Args::StripSpaces(var_value_string, true, true, false); + llvm::StringRef var_value(command); + var_value = var_value.split(var_name).second.trim(); Status error(GetDebugger().SetPropertyValue( - &m_exe_ctx, eVarSetOperationRemove, var_name, var_value_cstr)); + &m_exe_ctx, eVarSetOperationRemove, var_name, var_value)); if (error.Fail()) { result.AppendError(error.AsCString()); result.SetStatus(eReturnStatusFailed); @@ -735,16 +712,14 @@ public: // !WantsRawCommandString. bool WantsCompletion() override { return true; } - int HandleArgumentCompletion( - CompletionRequest &request, - OptionElementVector &opt_element_vector) override { + void + HandleArgumentCompletion(CompletionRequest &request, + OptionElementVector &opt_element_vector) override { // Attempting to complete variable name if (request.GetCursorIndex() < 2) CommandCompletions::InvokeCommonCompletionCallbacks( GetCommandInterpreter(), CommandCompletions::eSettingsNameCompletion, request, nullptr); - - return request.GetNumberOfMatches(); } protected: @@ -762,13 +737,11 @@ protected: } // Split the raw command into var_name, index_value, and value triple. - llvm::StringRef raw_str(command); - std::string var_value_string = raw_str.split(var_name).second.str(); - const char *var_value_cstr = - Args::StripSpaces(var_value_string, true, true, false); + llvm::StringRef var_value(command); + var_value = var_value.split(var_name).second.trim(); Status error(GetDebugger().SetPropertyValue( - &m_exe_ctx, eVarSetOperationReplace, var_name, var_value_cstr)); + &m_exe_ctx, eVarSetOperationReplace, var_name, var_value)); if (error.Fail()) { result.AppendError(error.AsCString()); result.SetStatus(eReturnStatusFailed); @@ -833,16 +806,14 @@ public: // !WantsRawCommandString. bool WantsCompletion() override { return true; } - int HandleArgumentCompletion( - CompletionRequest &request, - OptionElementVector &opt_element_vector) override { + void + HandleArgumentCompletion(CompletionRequest &request, + OptionElementVector &opt_element_vector) override { // Attempting to complete variable name if (request.GetCursorIndex() < 2) CommandCompletions::InvokeCommonCompletionCallbacks( GetCommandInterpreter(), CommandCompletions::eSettingsNameCompletion, request, nullptr); - - return request.GetNumberOfMatches(); } protected: @@ -868,13 +839,11 @@ protected: } // Split the raw command into var_name, index_value, and value triple. - llvm::StringRef raw_str(command); - std::string var_value_string = raw_str.split(var_name).second.str(); - const char *var_value_cstr = - Args::StripSpaces(var_value_string, true, true, false); + llvm::StringRef var_value(command); + var_value = var_value.split(var_name).second.trim(); Status error(GetDebugger().SetPropertyValue( - &m_exe_ctx, eVarSetOperationInsertBefore, var_name, var_value_cstr)); + &m_exe_ctx, eVarSetOperationInsertBefore, var_name, var_value)); if (error.Fail()) { result.AppendError(error.AsCString()); result.SetStatus(eReturnStatusFailed); @@ -936,16 +905,14 @@ public: // !WantsRawCommandString. bool WantsCompletion() override { return true; } - int HandleArgumentCompletion( - CompletionRequest &request, - OptionElementVector &opt_element_vector) override { + void + HandleArgumentCompletion(CompletionRequest &request, + OptionElementVector &opt_element_vector) override { // Attempting to complete variable name if (request.GetCursorIndex() < 2) CommandCompletions::InvokeCommonCompletionCallbacks( GetCommandInterpreter(), CommandCompletions::eSettingsNameCompletion, request, nullptr); - - return request.GetNumberOfMatches(); } protected: @@ -971,13 +938,11 @@ protected: } // Split the raw command into var_name, index_value, and value triple. - llvm::StringRef raw_str(command); - std::string var_value_string = raw_str.split(var_name).second.str(); - const char *var_value_cstr = - Args::StripSpaces(var_value_string, true, true, false); + llvm::StringRef var_value(command); + var_value = var_value.split(var_name).second.trim(); Status error(GetDebugger().SetPropertyValue( - &m_exe_ctx, eVarSetOperationInsertAfter, var_name, var_value_cstr)); + &m_exe_ctx, eVarSetOperationInsertAfter, var_name, var_value)); if (error.Fail()) { result.AppendError(error.AsCString()); result.SetStatus(eReturnStatusFailed); @@ -1028,16 +993,14 @@ public: // !WantsRawCommandString. bool WantsCompletion() override { return true; } - int HandleArgumentCompletion( - CompletionRequest &request, - OptionElementVector &opt_element_vector) override { + void + HandleArgumentCompletion(CompletionRequest &request, + OptionElementVector &opt_element_vector) override { // Attempting to complete variable name if (request.GetCursorIndex() < 2) CommandCompletions::InvokeCommonCompletionCallbacks( GetCommandInterpreter(), CommandCompletions::eSettingsNameCompletion, request, nullptr); - - return request.GetNumberOfMatches(); } protected: @@ -1065,13 +1028,11 @@ protected: // character string later on. // Split the raw command into var_name and value pair. - llvm::StringRef raw_str(command); - std::string var_value_string = raw_str.split(var_name).second.str(); - const char *var_value_cstr = - Args::StripSpaces(var_value_string, true, true, false); + llvm::StringRef var_value(command); + var_value = var_value.split(var_name).second.trim(); Status error(GetDebugger().SetPropertyValue( - &m_exe_ctx, eVarSetOperationAppend, var_name, var_value_cstr)); + &m_exe_ctx, eVarSetOperationAppend, var_name, var_value)); if (error.Fail()) { result.AppendError(error.AsCString()); result.SetStatus(eReturnStatusFailed); @@ -1107,16 +1068,14 @@ public: ~CommandObjectSettingsClear() override = default; - int HandleArgumentCompletion( - CompletionRequest &request, - OptionElementVector &opt_element_vector) override { + void + HandleArgumentCompletion(CompletionRequest &request, + OptionElementVector &opt_element_vector) override { // Attempting to complete variable name if (request.GetCursorIndex() < 2) CommandCompletions::InvokeCommonCompletionCallbacks( GetCommandInterpreter(), CommandCompletions::eSettingsNameCompletion, request, nullptr); - - return request.GetNumberOfMatches(); } protected: diff --git a/source/Commands/CommandObjectSource.cpp b/source/Commands/CommandObjectSource.cpp index 1b515d0f1099..78c8bc811926 100644 --- a/source/Commands/CommandObjectSource.cpp +++ b/source/Commands/CommandObjectSource.cpp @@ -33,18 +33,8 @@ using namespace lldb_private; #pragma mark CommandObjectSourceInfo // CommandObjectSourceInfo - debug line entries dumping command - -static constexpr OptionDefinition g_source_info_options[] = { - // clang-format off - { LLDB_OPT_SET_ALL, false, "count", 'c', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeCount, "The number of line entries to display." }, - { LLDB_OPT_SET_1 | LLDB_OPT_SET_2, false, "shlib", 's', OptionParser::eRequiredArgument, nullptr, {}, CommandCompletions::eModuleCompletion, eArgTypeShlibName, "Look up the source in the given module or shared library (can be specified more than once)." }, - { LLDB_OPT_SET_1, false, "file", 'f', OptionParser::eRequiredArgument, nullptr, {}, CommandCompletions::eSourceFileCompletion, eArgTypeFilename, "The file from which to display source." }, - { LLDB_OPT_SET_1, false, "line", 'l', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeLineNum, "The line number at which to start the displaying lines." }, - { LLDB_OPT_SET_1, false, "end-line", 'e', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeLineNum, "The line number at which to stop displaying lines." }, - { LLDB_OPT_SET_2, false, "name", 'n', OptionParser::eRequiredArgument, nullptr, {}, CommandCompletions::eSymbolCompletion, eArgTypeSymbol, "The name of a function whose source to display." }, - { LLDB_OPT_SET_3, false, "address", 'a', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeAddressOrExpression, "Lookup the address and display the source information for the corresponding file and line." }, - // clang-format on -}; +#define LLDB_OPTIONS_source_info +#include "CommandOptions.inc" class CommandObjectSourceInfo : public CommandObjectParsed { class CommandOptions : public Options { @@ -92,9 +82,7 @@ class CommandObjectSourceInfo : public CommandObjectParsed { modules.push_back(std::string(option_arg)); break; default: - error.SetErrorStringWithFormat("unrecognized short option '%c'", - short_option); - break; + llvm_unreachable("Unimplemented option"); } return error; @@ -404,17 +392,18 @@ protected: // const. ModuleList module_list = (m_module_list.GetSize() > 0) ? m_module_list : target->GetImages(); - size_t num_matches = - module_list.FindFunctions(name, eFunctionNameTypeAuto, - /*include_symbols=*/false, - /*include_inlines=*/true, - /*append=*/true, sc_list_funcs); + module_list.FindFunctions(name, eFunctionNameTypeAuto, + /*include_symbols=*/false, + /*include_inlines=*/true, sc_list_funcs); + size_t num_matches = sc_list_funcs.GetSize(); + if (!num_matches) { // If we didn't find any functions with that name, try searching for // symbols that line up exactly with function addresses. SymbolContextList sc_list_symbols; - size_t num_symbol_matches = module_list.FindFunctionSymbols( + module_list.FindFunctionSymbols( name, eFunctionNameTypeAuto, sc_list_symbols); + size_t num_symbol_matches = sc_list_symbols.GetSize(); for (size_t i = 0; i < num_symbol_matches; i++) { SymbolContext sc; sc_list_symbols.GetContextAtIndex(i, sc); @@ -592,7 +581,8 @@ protected: FileSpec module_file_spec(m_options.modules[i]); if (module_file_spec) { ModuleSpec module_spec(module_file_spec); - if (target->GetImages().FindModules(module_spec, m_module_list) == 0) + target->GetImages().FindModules(module_spec, m_module_list); + if (m_module_list.IsEmpty()) result.AppendWarningWithFormat("No module found for '%s'.\n", m_options.modules[i].c_str()); } @@ -643,19 +633,8 @@ protected: #pragma mark CommandObjectSourceList // CommandObjectSourceList - -static constexpr OptionDefinition g_source_list_options[] = { - // clang-format off - { LLDB_OPT_SET_ALL, false, "count", 'c', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeCount, "The number of source lines to display." }, - { LLDB_OPT_SET_1 | LLDB_OPT_SET_2, false, "shlib", 's', OptionParser::eRequiredArgument, nullptr, {}, CommandCompletions::eModuleCompletion, eArgTypeShlibName, "Look up the source file in the given shared library." }, - { LLDB_OPT_SET_ALL, false, "show-breakpoints", 'b', OptionParser::eNoArgument, nullptr, {}, 0, eArgTypeNone, "Show the line table locations from the debug information that indicate valid places to set source level breakpoints." }, - { LLDB_OPT_SET_1, false, "file", 'f', OptionParser::eRequiredArgument, nullptr, {}, CommandCompletions::eSourceFileCompletion, eArgTypeFilename, "The file from which to display source." }, - { LLDB_OPT_SET_1, false, "line", 'l', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeLineNum, "The line number at which to start the display source." }, - { LLDB_OPT_SET_2, false, "name", 'n', OptionParser::eRequiredArgument, nullptr, {}, CommandCompletions::eSymbolCompletion, eArgTypeSymbol, "The name of a function whose source to display." }, - { LLDB_OPT_SET_3, false, "address", 'a', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeAddressOrExpression, "Lookup the address and display the source information for the corresponding file and line." }, - { LLDB_OPT_SET_4, false, "reverse", 'r', OptionParser::eNoArgument, nullptr, {}, 0, eArgTypeNone, "Reverse the listing to look backwards from the last displayed block of source." }, - // clang-format on -}; +#define LLDB_OPTIONS_source_list +#include "CommandOptions.inc" class CommandObjectSourceList : public CommandObjectParsed { class CommandOptions : public Options { @@ -704,9 +683,7 @@ class CommandObjectSourceList : public CommandObjectParsed { reverse = true; break; default: - error.SetErrorStringWithFormat("unrecognized short option '%c'", - short_option); - break; + llvm_unreachable("Unimplemented option"); } return error; @@ -759,7 +736,7 @@ public: // the arguments directly. auto iter = llvm::find_if(current_command_args, [](const Args::ArgEntry &e) { - return e.ref == "-r" || e.ref == "--reverse"; + return e.ref() == "-r" || e.ref() == "--reverse"; }); if (iter == current_command_args.end()) return m_cmd_name.c_str(); @@ -897,13 +874,11 @@ protected: // these somewhere, there should probably be a module-filter-list that can be // passed to the various ModuleList::Find* calls, which would either be a // vector of string names or a ModuleSpecList. - size_t FindMatchingFunctions(Target *target, ConstString name, + void FindMatchingFunctions(Target *target, ConstString name, SymbolContextList &sc_list) { // Displaying the source for a symbol: bool include_inlines = true; - bool append = true; bool include_symbols = false; - size_t num_matches = 0; if (m_options.num_lines == 0) m_options.num_lines = 10; @@ -917,22 +892,20 @@ protected: ModuleSpec module_spec(module_file_spec); matching_modules.Clear(); target->GetImages().FindModules(module_spec, matching_modules); - num_matches += matching_modules.FindFunctions( + matching_modules.FindFunctions( name, eFunctionNameTypeAuto, include_symbols, include_inlines, - append, sc_list); + sc_list); } } } else { - num_matches = target->GetImages().FindFunctions( - name, eFunctionNameTypeAuto, include_symbols, include_inlines, append, - sc_list); + target->GetImages().FindFunctions(name, eFunctionNameTypeAuto, + include_symbols, include_inlines, + sc_list); } - return num_matches; } - size_t FindMatchingFunctionSymbols(Target *target, ConstString name, - SymbolContextList &sc_list) { - size_t num_matches = 0; + void FindMatchingFunctionSymbols(Target *target, ConstString name, + SymbolContextList &sc_list) { const size_t num_modules = m_options.modules.size(); if (num_modules > 0) { ModuleList matching_modules; @@ -942,15 +915,14 @@ protected: ModuleSpec module_spec(module_file_spec); matching_modules.Clear(); target->GetImages().FindModules(module_spec, matching_modules); - num_matches += matching_modules.FindFunctionSymbols( - name, eFunctionNameTypeAuto, sc_list); + matching_modules.FindFunctionSymbols(name, eFunctionNameTypeAuto, + sc_list); } } } else { - num_matches = target->GetImages().FindFunctionSymbols( - name, eFunctionNameTypeAuto, sc_list); + target->GetImages().FindFunctionSymbols(name, eFunctionNameTypeAuto, + sc_list); } - return num_matches; } bool DoExecute(Args &command, CommandReturnObject &result) override { @@ -970,13 +942,15 @@ protected: ConstString name(m_options.symbol_name.c_str()); // Displaying the source for a symbol. Search for function named name. - size_t num_matches = FindMatchingFunctions(target, name, sc_list); + FindMatchingFunctions(target, name, sc_list); + size_t num_matches = sc_list.GetSize(); if (!num_matches) { // If we didn't find any functions with that name, try searching for // symbols that line up exactly with function addresses. SymbolContextList sc_list_symbols; - size_t num_symbol_matches = - FindMatchingFunctionSymbols(target, name, sc_list_symbols); + FindMatchingFunctionSymbols(target, name, sc_list_symbols); + size_t num_symbol_matches =sc_list_symbols.GetSize(); + for (size_t i = 0; i < num_symbol_matches; i++) { SymbolContext sc; sc_list_symbols.GetContextAtIndex(i, sc); diff --git a/source/Commands/CommandObjectStats.cpp b/source/Commands/CommandObjectStats.cpp index a73c2a8e0409..e3a1f9433662 100644 --- a/source/Commands/CommandObjectStats.cpp +++ b/source/Commands/CommandObjectStats.cpp @@ -26,15 +26,15 @@ public: protected: bool DoExecute(Args &command, CommandReturnObject &result) override { - Target *target = GetSelectedOrDummyTarget(); + Target &target = GetSelectedOrDummyTarget(); - if (target->GetCollectingStats()) { + if (target.GetCollectingStats()) { result.AppendError("statistics already enabled"); result.SetStatus(eReturnStatusFailed); return false; } - target->SetCollectingStats(true); + target.SetCollectingStats(true); result.SetStatus(eReturnStatusSuccessFinishResult); return true; } @@ -51,15 +51,15 @@ public: protected: bool DoExecute(Args &command, CommandReturnObject &result) override { - Target *target = GetSelectedOrDummyTarget(); + Target &target = GetSelectedOrDummyTarget(); - if (!target->GetCollectingStats()) { + if (!target.GetCollectingStats()) { result.AppendError("need to enable statistics before disabling them"); result.SetStatus(eReturnStatusFailed); return false; } - target->SetCollectingStats(false); + target.SetCollectingStats(false); result.SetStatus(eReturnStatusSuccessFinishResult); return true; } @@ -75,10 +75,10 @@ public: protected: bool DoExecute(Args &command, CommandReturnObject &result) override { - Target *target = GetSelectedOrDummyTarget(); + Target &target = GetSelectedOrDummyTarget(); uint32_t i = 0; - for (auto &stat : target->GetStatistics()) { + for (auto &stat : target.GetStatistics()) { result.AppendMessageWithFormat( "%s : %u\n", lldb_private::GetStatDescription(static_cast<lldb_private::StatisticKind>(i)) diff --git a/source/Commands/CommandObjectTarget.cpp b/source/Commands/CommandObjectTarget.cpp index e913a28501f2..abf7895a7384 100644 --- a/source/Commands/CommandObjectTarget.cpp +++ b/source/Commands/CommandObjectTarget.cpp @@ -37,7 +37,6 @@ #include "lldb/Symbol/LocateSymbolFile.h" #include "lldb/Symbol/ObjectFile.h" #include "lldb/Symbol/SymbolFile.h" -#include "lldb/Symbol/SymbolVendor.h" #include "lldb/Symbol/UnwindPlan.h" #include "lldb/Symbol/VariableList.h" #include "lldb/Target/ABI.h" @@ -135,22 +134,27 @@ static uint32_t DumpTargetList(TargetList &target_list, } // Note that the negation in the argument name causes a slightly confusing -// mapping of the enum values, +// mapping of the enum values. static constexpr OptionEnumValueElement g_dependents_enumaration[] = { - {eLoadDependentsDefault, "default", - "Only load dependents when the target is an executable."}, - {eLoadDependentsNo, "true", - "Don't load dependents, even if the target is an executable."}, - {eLoadDependentsYes, "false", - "Load dependents, even if the target is not an executable."}}; - -static constexpr OptionDefinition g_dependents_options[] = { - {LLDB_OPT_SET_1, false, "no-dependents", 'd', - OptionParser::eOptionalArgument, nullptr, - OptionEnumValues(g_dependents_enumaration), 0, eArgTypeValue, - "Whether or not to load dependents when creating a target. If the option " - "is not specified, the value is implicitly 'default'. If the option is " - "specified but without a value, the value is implicitly 'true'."}}; + { + eLoadDependentsDefault, + "default", + "Only load dependents when the target is an executable.", + }, + { + eLoadDependentsNo, + "true", + "Don't load dependents, even if the target is an executable.", + }, + { + eLoadDependentsYes, + "false", + "Load dependents, even if the target is not an executable.", + }, +}; + +#define LLDB_OPTIONS_target_dependents +#include "CommandOptions.inc" class OptionGroupDependents : public OptionGroup { public: @@ -159,7 +163,7 @@ public: ~OptionGroupDependents() override {} llvm::ArrayRef<OptionDefinition> GetDefinitions() override { - return llvm::makeArrayRef(g_dependents_options); + return llvm::makeArrayRef(g_target_dependents_options); } Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_value, @@ -172,11 +176,13 @@ public: return error; } - const char short_option = g_dependents_options[option_idx].short_option; + const char short_option = + g_target_dependents_options[option_idx].short_option; if (short_option == 'd') { LoadDependentFiles tmp_load_dependents; tmp_load_dependents = (LoadDependentFiles)OptionArgParser::ToOptionEnum( - option_value, g_dependents_options[option_idx].enum_values, 0, error); + option_value, g_target_dependents_options[option_idx].enum_values, 0, + error); if (error.Success()) m_load_dependent_files = tmp_load_dependents; } else { @@ -252,13 +258,12 @@ public: Options *GetOptions() override { return &m_option_group; } - int HandleArgumentCompletion( - CompletionRequest &request, - OptionElementVector &opt_element_vector) override { + void + HandleArgumentCompletion(CompletionRequest &request, + OptionElementVector &opt_element_vector) override { CommandCompletions::InvokeCommonCompletionCallbacks( GetCommandInterpreter(), CommandCompletions::eDiskFileCompletion, request, nullptr); - return request.GetNumberOfMatches(); } protected: @@ -444,7 +449,8 @@ protected: } } else { result.AppendMessageWithFormat( - "Current executable set to '%s' (%s).\n", file_path, + "Current executable set to '%s' (%s).\n", + file_spec.GetPath().c_str(), target_sp->GetArchitecture().GetArchitectureName()); result.SetStatus(eReturnStatusSuccessFinishNoResult); } @@ -619,7 +625,7 @@ protected: for (auto &entry : args.entries()) { uint32_t target_idx; - if (entry.ref.getAsInteger(0, target_idx)) { + if (entry.ref().getAsInteger(0, target_idx)) { result.AppendErrorWithFormat("invalid target index '%s'\n", entry.c_str()); result.SetStatus(eReturnStatusFailed); @@ -792,12 +798,12 @@ public: static size_t GetVariableCallback(void *baton, const char *name, VariableList &variable_list) { + size_t old_size = variable_list.GetSize(); Target *target = static_cast<Target *>(baton); - if (target) { - return target->GetImages().FindGlobalVariables(ConstString(name), - UINT32_MAX, variable_list); - } - return 0; + if (target) + target->GetImages().FindGlobalVariables(ConstString(name), UINT32_MAX, + variable_list); + return variable_list.GetSize() - old_size; } Options *GetOptions() override { return &m_option_group; } @@ -860,8 +866,9 @@ protected: return false; } use_var_name = true; - matches = target->GetImages().FindGlobalVariables(regex, UINT32_MAX, - variable_list); + target->GetImages().FindGlobalVariables(regex, UINT32_MAX, + variable_list); + matches = variable_list.GetSize(); } else { Status error(Variable::GetValuesForVariableExpressionPath( arg, m_exe_ctx.GetBestExecutionContextScope(), @@ -936,7 +943,6 @@ protected: } } else { SymbolContextList sc_list; - const bool append = true; // We have one or more compile unit or shlib if (num_shlibs > 0) { for (size_t shlib_idx = 0; shlib_idx < num_shlibs; ++shlib_idx) { @@ -949,8 +955,7 @@ protected: if (num_compile_units > 0) { for (size_t cu_idx = 0; cu_idx < num_compile_units; ++cu_idx) module_sp->FindCompileUnits( - compile_units.GetFileSpecAtIndex(cu_idx), append, - sc_list); + compile_units.GetFileSpecAtIndex(cu_idx), sc_list); } else { SymbolContext sc; sc.module_sp = module_sp; @@ -968,7 +973,7 @@ protected: // units files that were specified for (size_t cu_idx = 0; cu_idx < num_compile_units; ++cu_idx) target->GetImages().FindCompileUnits( - compile_units.GetFileSpecAtIndex(cu_idx), append, sc_list); + compile_units.GetFileSpecAtIndex(cu_idx), sc_list); } const uint32_t num_scs = sc_list.GetSize(); @@ -1024,7 +1029,7 @@ public: : CommandObjectParsed(interpreter, "target modules search-paths add", "Add new image search paths substitution pairs to " "the current target.", - nullptr) { + nullptr, eCommandRequiresTarget) { CommandArgumentEntry arg; CommandArgumentData old_prefix_arg; CommandArgumentData new_prefix_arg; @@ -1053,41 +1058,37 @@ public: protected: bool DoExecute(Args &command, CommandReturnObject &result) override { - Target *target = GetDebugger().GetSelectedTarget().get(); - if (target) { - const size_t argc = command.GetArgumentCount(); - if (argc & 1) { - result.AppendError("add requires an even number of arguments\n"); - result.SetStatus(eReturnStatusFailed); - } else { - for (size_t i = 0; i < argc; i += 2) { - const char *from = command.GetArgumentAtIndex(i); - const char *to = command.GetArgumentAtIndex(i + 1); - - if (from[0] && to[0]) { - Log *log = lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_HOST); - if (log) { - log->Printf("target modules search path adding ImageSearchPath " - "pair: '%s' -> '%s'", - from, to); - } - bool last_pair = ((argc - i) == 2); - target->GetImageSearchPathList().Append( - ConstString(from), ConstString(to), - last_pair); // Notify if this is the last pair - result.SetStatus(eReturnStatusSuccessFinishNoResult); - } else { - if (from[0]) - result.AppendError("<path-prefix> can't be empty\n"); - else - result.AppendError("<new-path-prefix> can't be empty\n"); - result.SetStatus(eReturnStatusFailed); + Target *target = &GetSelectedTarget(); + const size_t argc = command.GetArgumentCount(); + if (argc & 1) { + result.AppendError("add requires an even number of arguments\n"); + result.SetStatus(eReturnStatusFailed); + } else { + for (size_t i = 0; i < argc; i += 2) { + const char *from = command.GetArgumentAtIndex(i); + const char *to = command.GetArgumentAtIndex(i + 1); + + if (from[0] && to[0]) { + Log *log = lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_HOST); + if (log) { + LLDB_LOGF(log, + "target modules search path adding ImageSearchPath " + "pair: '%s' -> '%s'", + from, to); } + bool last_pair = ((argc - i) == 2); + target->GetImageSearchPathList().Append( + ConstString(from), ConstString(to), + last_pair); // Notify if this is the last pair + result.SetStatus(eReturnStatusSuccessFinishNoResult); + } else { + if (from[0]) + result.AppendError("<path-prefix> can't be empty\n"); + else + result.AppendError("<new-path-prefix> can't be empty\n"); + result.SetStatus(eReturnStatusFailed); } } - } else { - result.AppendError("invalid target\n"); - result.SetStatus(eReturnStatusFailed); } return result.Succeeded(); } @@ -1101,21 +1102,17 @@ public: : CommandObjectParsed(interpreter, "target modules search-paths clear", "Clear all current image search path substitution " "pairs from the current target.", - "target modules search-paths clear") {} + "target modules search-paths clear", + eCommandRequiresTarget) {} ~CommandObjectTargetModulesSearchPathsClear() override = default; protected: bool DoExecute(Args &command, CommandReturnObject &result) override { - Target *target = GetDebugger().GetSelectedTarget().get(); - if (target) { - bool notify = true; - target->GetImageSearchPathList().Clear(notify); - result.SetStatus(eReturnStatusSuccessFinishNoResult); - } else { - result.AppendError("invalid target\n"); - result.SetStatus(eReturnStatusFailed); - } + Target *target = &GetSelectedTarget(); + bool notify = true; + target->GetImageSearchPathList().Clear(notify); + result.SetStatus(eReturnStatusSuccessFinishNoResult); return result.Succeeded(); } }; @@ -1128,7 +1125,7 @@ public: : CommandObjectParsed(interpreter, "target modules search-paths insert", "Insert a new image search path substitution pair " "into the current target at the specified index.", - nullptr) { + nullptr, eCommandRequiresTarget) { CommandArgumentEntry arg1; CommandArgumentEntry arg2; CommandArgumentData index_arg; @@ -1168,55 +1165,49 @@ public: protected: bool DoExecute(Args &command, CommandReturnObject &result) override { - Target *target = GetDebugger().GetSelectedTarget().get(); - if (target) { - size_t argc = command.GetArgumentCount(); - // check for at least 3 arguments and an odd number of parameters - if (argc >= 3 && argc & 1) { - bool success = false; + Target *target = &GetSelectedTarget(); + size_t argc = command.GetArgumentCount(); + // check for at least 3 arguments and an odd number of parameters + if (argc >= 3 && argc & 1) { + bool success = false; - uint32_t insert_idx = StringConvert::ToUInt32( - command.GetArgumentAtIndex(0), UINT32_MAX, 0, &success); + uint32_t insert_idx = StringConvert::ToUInt32( + command.GetArgumentAtIndex(0), UINT32_MAX, 0, &success); - if (!success) { - result.AppendErrorWithFormat( - "<index> parameter is not an integer: '%s'.\n", - command.GetArgumentAtIndex(0)); - result.SetStatus(eReturnStatusFailed); - return result.Succeeded(); - } + if (!success) { + result.AppendErrorWithFormat( + "<index> parameter is not an integer: '%s'.\n", + command.GetArgumentAtIndex(0)); + result.SetStatus(eReturnStatusFailed); + return result.Succeeded(); + } - // shift off the index - command.Shift(); - argc = command.GetArgumentCount(); + // shift off the index + command.Shift(); + argc = command.GetArgumentCount(); - for (uint32_t i = 0; i < argc; i += 2, ++insert_idx) { - const char *from = command.GetArgumentAtIndex(i); - const char *to = command.GetArgumentAtIndex(i + 1); + for (uint32_t i = 0; i < argc; i += 2, ++insert_idx) { + const char *from = command.GetArgumentAtIndex(i); + const char *to = command.GetArgumentAtIndex(i + 1); - if (from[0] && to[0]) { - bool last_pair = ((argc - i) == 2); - target->GetImageSearchPathList().Insert( - ConstString(from), ConstString(to), insert_idx, last_pair); - result.SetStatus(eReturnStatusSuccessFinishNoResult); - } else { - if (from[0]) - result.AppendError("<path-prefix> can't be empty\n"); - else - result.AppendError("<new-path-prefix> can't be empty\n"); - result.SetStatus(eReturnStatusFailed); - return false; - } + if (from[0] && to[0]) { + bool last_pair = ((argc - i) == 2); + target->GetImageSearchPathList().Insert( + ConstString(from), ConstString(to), insert_idx, last_pair); + result.SetStatus(eReturnStatusSuccessFinishNoResult); + } else { + if (from[0]) + result.AppendError("<path-prefix> can't be empty\n"); + else + result.AppendError("<new-path-prefix> can't be empty\n"); + result.SetStatus(eReturnStatusFailed); + return false; } - } else { - result.AppendError("insert requires at least three arguments\n"); - result.SetStatus(eReturnStatusFailed); - return result.Succeeded(); } - } else { - result.AppendError("invalid target\n"); + result.AppendError("insert requires at least three arguments\n"); result.SetStatus(eReturnStatusFailed); + return result.Succeeded(); } return result.Succeeded(); } @@ -1230,26 +1221,22 @@ public: : CommandObjectParsed(interpreter, "target modules search-paths list", "List all current image search path substitution " "pairs in the current target.", - "target modules search-paths list") {} + "target modules search-paths list", + eCommandRequiresTarget) {} ~CommandObjectTargetModulesSearchPathsList() override = default; protected: bool DoExecute(Args &command, CommandReturnObject &result) override { - Target *target = GetDebugger().GetSelectedTarget().get(); - if (target) { - if (command.GetArgumentCount() != 0) { - result.AppendError("list takes no arguments\n"); - result.SetStatus(eReturnStatusFailed); - return result.Succeeded(); - } - - target->GetImageSearchPathList().Dump(&result.GetOutputStream()); - result.SetStatus(eReturnStatusSuccessFinishResult); - } else { - result.AppendError("invalid target\n"); + Target *target = &GetSelectedTarget(); + if (command.GetArgumentCount() != 0) { + result.AppendError("list takes no arguments\n"); result.SetStatus(eReturnStatusFailed); + return result.Succeeded(); } + + target->GetImageSearchPathList().Dump(&result.GetOutputStream()); + result.SetStatus(eReturnStatusSuccessFinishResult); return result.Succeeded(); } }; @@ -1262,7 +1249,7 @@ public: : CommandObjectParsed( interpreter, "target modules search-paths query", "Transform a path using the first applicable image search path.", - nullptr) { + nullptr, eCommandRequiresTarget) { CommandArgumentEntry arg; CommandArgumentData path_arg; @@ -1282,26 +1269,21 @@ public: protected: bool DoExecute(Args &command, CommandReturnObject &result) override { - Target *target = GetDebugger().GetSelectedTarget().get(); - if (target) { - if (command.GetArgumentCount() != 1) { - result.AppendError("query requires one argument\n"); - result.SetStatus(eReturnStatusFailed); - return result.Succeeded(); - } - - ConstString orig(command.GetArgumentAtIndex(0)); - ConstString transformed; - if (target->GetImageSearchPathList().RemapPath(orig, transformed)) - result.GetOutputStream().Printf("%s\n", transformed.GetCString()); - else - result.GetOutputStream().Printf("%s\n", orig.GetCString()); - - result.SetStatus(eReturnStatusSuccessFinishResult); - } else { - result.AppendError("invalid target\n"); + Target *target = &GetSelectedTarget(); + if (command.GetArgumentCount() != 1) { + result.AppendError("query requires one argument\n"); result.SetStatus(eReturnStatusFailed); + return result.Succeeded(); } + + ConstString orig(command.GetArgumentAtIndex(0)); + ConstString transformed; + if (target->GetImageSearchPathList().RemapPath(orig, transformed)) + result.GetOutputStream().Printf("%s\n", transformed.GetCString()); + else + result.GetOutputStream().Printf("%s\n", orig.GetCString()); + + result.SetStatus(eReturnStatusSuccessFinishResult); return result.Succeeded(); } }; @@ -1439,15 +1421,11 @@ static size_t DumpModuleObjfileHeaders(Stream &strm, ModuleList &module_list) { static void DumpModuleSymtab(CommandInterpreter &interpreter, Stream &strm, Module *module, SortOrder sort_order) { - if (module) { - SymbolVendor *sym_vendor = module->GetSymbolVendor(); - if (sym_vendor) { - Symtab *symtab = sym_vendor->GetSymtab(); - if (symtab) - symtab->Dump(&strm, interpreter.GetExecutionContext().GetTargetPtr(), - sort_order); - } - } + if (!module) + return; + if (Symtab *symtab = module->GetSymtab()) + symtab->Dump(&strm, interpreter.GetExecutionContext().GetTargetPtr(), + sort_order); } static void DumpModuleSections(CommandInterpreter &interpreter, Stream &strm, @@ -1467,11 +1445,10 @@ static void DumpModuleSections(CommandInterpreter &interpreter, Stream &strm, } } -static bool DumpModuleSymbolVendor(Stream &strm, Module *module) { +static bool DumpModuleSymbolFile(Stream &strm, Module *module) { if (module) { - SymbolVendor *symbol_vendor = module->GetSymbolVendor(true); - if (symbol_vendor) { - symbol_vendor->Dump(&strm); + if (SymbolFile *symbol_file = module->GetSymbolFile(true)) { + symbol_file->Dump(strm); return true; } } @@ -1553,47 +1530,44 @@ static uint32_t LookupSymbolInModule(CommandInterpreter &interpreter, Stream &strm, Module *module, const char *name, bool name_is_regex, bool verbose) { - if (module) { - SymbolContext sc; + if (!module) + return 0; - SymbolVendor *sym_vendor = module->GetSymbolVendor(); - if (sym_vendor) { - Symtab *symtab = sym_vendor->GetSymtab(); - if (symtab) { - std::vector<uint32_t> match_indexes; - ConstString symbol_name(name); - uint32_t num_matches = 0; - if (name_is_regex) { - RegularExpression name_regexp(symbol_name.GetStringRef()); - num_matches = symtab->AppendSymbolIndexesMatchingRegExAndType( - name_regexp, eSymbolTypeAny, match_indexes); - } else { - num_matches = - symtab->AppendSymbolIndexesWithName(symbol_name, match_indexes); - } + Symtab *symtab = module->GetSymtab(); + if (!symtab) + return 0; - if (num_matches > 0) { - strm.Indent(); - strm.Printf("%u symbols match %s'%s' in ", num_matches, - name_is_regex ? "the regular expression " : "", name); - DumpFullpath(strm, &module->GetFileSpec(), 0); - strm.PutCString(":\n"); - strm.IndentMore(); - for (uint32_t i = 0; i < num_matches; ++i) { - Symbol *symbol = symtab->SymbolAtIndex(match_indexes[i]); - if (symbol && symbol->ValueIsAddress()) { - DumpAddress(interpreter.GetExecutionContext() - .GetBestExecutionContextScope(), - symbol->GetAddressRef(), verbose, strm); - } - } - strm.IndentLess(); - return num_matches; - } + SymbolContext sc; + std::vector<uint32_t> match_indexes; + ConstString symbol_name(name); + uint32_t num_matches = 0; + if (name_is_regex) { + RegularExpression name_regexp(symbol_name.GetStringRef()); + num_matches = symtab->AppendSymbolIndexesMatchingRegExAndType( + name_regexp, eSymbolTypeAny, match_indexes); + } else { + num_matches = + symtab->AppendSymbolIndexesWithName(symbol_name, match_indexes); + } + + if (num_matches > 0) { + strm.Indent(); + strm.Printf("%u symbols match %s'%s' in ", num_matches, + name_is_regex ? "the regular expression " : "", name); + DumpFullpath(strm, &module->GetFileSpec(), 0); + strm.PutCString(":\n"); + strm.IndentMore(); + for (uint32_t i = 0; i < num_matches; ++i) { + Symbol *symbol = symtab->SymbolAtIndex(match_indexes[i]); + if (symbol && symbol->ValueIsAddress()) { + DumpAddress( + interpreter.GetExecutionContext().GetBestExecutionContextScope(), + symbol->GetAddressRef(), verbose, strm); } } + strm.IndentLess(); } - return 0; + return num_matches; } static void DumpSymbolContextList(ExecutionContextScope *exe_scope, @@ -1623,19 +1597,17 @@ static size_t LookupFunctionInModule(CommandInterpreter &interpreter, bool verbose) { if (module && name && name[0]) { SymbolContextList sc_list; - const bool append = true; size_t num_matches = 0; if (name_is_regex) { RegularExpression function_name_regex((llvm::StringRef(name))); - num_matches = module->FindFunctions(function_name_regex, include_symbols, - include_inlines, append, sc_list); + module->FindFunctions(function_name_regex, include_symbols, + include_inlines, sc_list); } else { ConstString function_name(name); - num_matches = module->FindFunctions( - function_name, nullptr, eFunctionNameTypeAuto, include_symbols, - include_inlines, append, sc_list); + module->FindFunctions(function_name, nullptr, eFunctionNameTypeAuto, + include_symbols, include_inlines, sc_list); } - + num_matches = sc_list.GetSize(); if (num_matches) { strm.Indent(); strm.Printf("%" PRIu64 " match%s found in ", (uint64_t)num_matches, @@ -1654,75 +1626,30 @@ static size_t LookupFunctionInModule(CommandInterpreter &interpreter, static size_t LookupTypeInModule(CommandInterpreter &interpreter, Stream &strm, Module *module, const char *name_cstr, bool name_is_regex) { + TypeList type_list; if (module && name_cstr && name_cstr[0]) { - TypeList type_list; const uint32_t max_num_matches = UINT32_MAX; size_t num_matches = 0; bool name_is_fully_qualified = false; ConstString name(name_cstr); llvm::DenseSet<lldb_private::SymbolFile *> searched_symbol_files; - num_matches = - module->FindTypes(name, name_is_fully_qualified, max_num_matches, - searched_symbol_files, type_list); + module->FindTypes(name, name_is_fully_qualified, max_num_matches, + searched_symbol_files, type_list); - if (num_matches) { - strm.Indent(); - strm.Printf("%" PRIu64 " match%s found in ", (uint64_t)num_matches, - num_matches > 1 ? "es" : ""); - DumpFullpath(strm, &module->GetFileSpec(), 0); - strm.PutCString(":\n"); - for (TypeSP type_sp : type_list.Types()) { - if (type_sp) { - // Resolve the clang type so that any forward references to types - // that haven't yet been parsed will get parsed. - type_sp->GetFullCompilerType(); - type_sp->GetDescription(&strm, eDescriptionLevelFull, true); - // Print all typedef chains - TypeSP typedef_type_sp(type_sp); - TypeSP typedefed_type_sp(typedef_type_sp->GetTypedefType()); - while (typedefed_type_sp) { - strm.EOL(); - strm.Printf(" typedef '%s': ", - typedef_type_sp->GetName().GetCString()); - typedefed_type_sp->GetFullCompilerType(); - typedefed_type_sp->GetDescription(&strm, eDescriptionLevelFull, - true); - typedef_type_sp = typedefed_type_sp; - typedefed_type_sp = typedef_type_sp->GetTypedefType(); - } - } - strm.EOL(); - } - } - return num_matches; - } - return 0; -} - -static size_t LookupTypeHere(CommandInterpreter &interpreter, Stream &strm, - Module &module, const char *name_cstr, - bool name_is_regex) { - TypeList type_list; - const uint32_t max_num_matches = UINT32_MAX; - size_t num_matches = 1; - bool name_is_fully_qualified = false; + if (type_list.Empty()) + return 0; - ConstString name(name_cstr); - llvm::DenseSet<SymbolFile *> searched_symbol_files; - num_matches = module.FindTypes(name, name_is_fully_qualified, max_num_matches, - searched_symbol_files, type_list); - - if (num_matches) { strm.Indent(); - strm.PutCString("Best match found in "); - DumpFullpath(strm, &module.GetFileSpec(), 0); + strm.Printf("%" PRIu64 " match%s found in ", (uint64_t)num_matches, + num_matches > 1 ? "es" : ""); + DumpFullpath(strm, &module->GetFileSpec(), 0); strm.PutCString(":\n"); - - TypeSP type_sp(type_list.GetTypeAtIndex(0)); - if (type_sp) { - // Resolve the clang type so that any forward references to types that - // haven't yet been parsed will get parsed. + for (TypeSP type_sp : type_list.Types()) { + if (!type_sp) + continue; + // Resolve the clang type so that any forward references to types + // that haven't yet been parsed will get parsed. type_sp->GetFullCompilerType(); type_sp->GetDescription(&strm, eDescriptionLevelFull, true); // Print all typedef chains @@ -1740,7 +1667,50 @@ static size_t LookupTypeHere(CommandInterpreter &interpreter, Stream &strm, } strm.EOL(); } - return num_matches; + return type_list.GetSize(); +} + +static size_t LookupTypeHere(CommandInterpreter &interpreter, Stream &strm, + Module &module, const char *name_cstr, + bool name_is_regex) { + TypeList type_list; + const uint32_t max_num_matches = UINT32_MAX; + bool name_is_fully_qualified = false; + + ConstString name(name_cstr); + llvm::DenseSet<SymbolFile *> searched_symbol_files; + module.FindTypes(name, name_is_fully_qualified, max_num_matches, + searched_symbol_files, type_list); + + if (type_list.Empty()) + return 0; + + strm.Indent(); + strm.PutCString("Best match found in "); + DumpFullpath(strm, &module.GetFileSpec(), 0); + strm.PutCString(":\n"); + + TypeSP type_sp(type_list.GetTypeAtIndex(0)); + if (type_sp) { + // Resolve the clang type so that any forward references to types that + // haven't yet been parsed will get parsed. + type_sp->GetFullCompilerType(); + type_sp->GetDescription(&strm, eDescriptionLevelFull, true); + // Print all typedef chains + TypeSP typedef_type_sp(type_sp); + TypeSP typedefed_type_sp(typedef_type_sp->GetTypedefType()); + while (typedefed_type_sp) { + strm.EOL(); + strm.Printf(" typedef '%s': ", + typedef_type_sp->GetName().GetCString()); + typedefed_type_sp->GetFullCompilerType(); + typedefed_type_sp->GetDescription(&strm, eDescriptionLevelFull, true); + typedef_type_sp = typedefed_type_sp; + typedefed_type_sp = typedef_type_sp->GetTypedefType(); + } + } + strm.EOL(); + return type_list.GetSize(); } static uint32_t LookupFileAndLineInModule(CommandInterpreter &interpreter, @@ -1797,8 +1767,8 @@ static size_t FindModulesByName(Target *target, const char *module_name, } } else { if (target) { - const size_t num_matches = - target->GetImages().FindModules(module_spec, module_list); + target->GetImages().FindModules(module_spec, module_list); + const size_t num_matches = module_list.GetSize(); // Not found in our module list for our target, check the main shared // module list in case it is a extra file used somewhere else @@ -1825,8 +1795,9 @@ public: CommandObjectTargetModulesModuleAutoComplete(CommandInterpreter &interpreter, const char *name, const char *help, - const char *syntax) - : CommandObjectParsed(interpreter, name, help, syntax) { + const char *syntax, + uint32_t flags = 0) + : CommandObjectParsed(interpreter, name, help, syntax, flags) { CommandArgumentEntry arg; CommandArgumentData file_arg; @@ -1844,13 +1815,12 @@ public: ~CommandObjectTargetModulesModuleAutoComplete() override = default; - int HandleArgumentCompletion( - CompletionRequest &request, - OptionElementVector &opt_element_vector) override { + void + HandleArgumentCompletion(CompletionRequest &request, + OptionElementVector &opt_element_vector) override { CommandCompletions::InvokeCommonCompletionCallbacks( GetCommandInterpreter(), CommandCompletions::eModuleCompletion, request, nullptr); - return request.GetNumberOfMatches(); } }; @@ -1883,13 +1853,12 @@ public: ~CommandObjectTargetModulesSourceFileAutoComplete() override = default; - int HandleArgumentCompletion( - CompletionRequest &request, - OptionElementVector &opt_element_vector) override { + void + HandleArgumentCompletion(CompletionRequest &request, + OptionElementVector &opt_element_vector) override { CommandCompletions::InvokeCommonCompletionCallbacks( GetCommandInterpreter(), CommandCompletions::eSourceFileCompletion, request, nullptr); - return request.GetNumberOfMatches(); } }; @@ -1902,19 +1871,13 @@ public: : CommandObjectTargetModulesModuleAutoComplete( interpreter, "target modules dump objfile", "Dump the object file headers from one or more target modules.", - nullptr) {} + nullptr, eCommandRequiresTarget) {} ~CommandObjectTargetModulesDumpObjfile() override = default; protected: bool DoExecute(Args &command, CommandReturnObject &result) override { - Target *target = GetDebugger().GetSelectedTarget().get(); - if (target == nullptr) { - result.AppendError("invalid target, create a debug target using the " - "'target create' command"); - result.SetStatus(eReturnStatusFailed); - return false; - } + Target *target = &GetSelectedTarget(); uint32_t addr_byte_size = target->GetArchitecture().GetAddressByteSize(); result.GetOutputStream().SetAddressByteSize(addr_byte_size); @@ -1961,15 +1924,25 @@ protected: #pragma mark CommandObjectTargetModulesDumpSymtab static constexpr OptionEnumValueElement g_sort_option_enumeration[] = { - {eSortOrderNone, "none", - "No sorting, use the original symbol table order."}, - {eSortOrderByAddress, "address", "Sort output by symbol address."}, - {eSortOrderByName, "name", "Sort output by symbol name."} }; + { + eSortOrderNone, + "none", + "No sorting, use the original symbol table order.", + }, + { + eSortOrderByAddress, + "address", + "Sort output by symbol address.", + }, + { + eSortOrderByName, + "name", + "Sort output by symbol name.", + }, +}; -static constexpr OptionDefinition g_target_modules_dump_symtab_options[] = { #define LLDB_OPTIONS_target_modules_dump_symtab #include "CommandOptions.inc" -}; class CommandObjectTargetModulesDumpSymtab : public CommandObjectTargetModulesModuleAutoComplete { @@ -1977,7 +1950,8 @@ public: CommandObjectTargetModulesDumpSymtab(CommandInterpreter &interpreter) : CommandObjectTargetModulesModuleAutoComplete( interpreter, "target modules dump symtab", - "Dump the symbol table from one or more target modules.", nullptr), + "Dump the symbol table from one or more target modules.", nullptr, + eCommandRequiresTarget), m_options() {} ~CommandObjectTargetModulesDumpSymtab() override = default; @@ -2003,9 +1977,7 @@ public: break; default: - error.SetErrorStringWithFormat("invalid short option character '%c'", - short_option); - break; + llvm_unreachable("Unimplemented option"); } return error; } @@ -2023,82 +1995,75 @@ public: protected: bool DoExecute(Args &command, CommandReturnObject &result) override { - Target *target = GetDebugger().GetSelectedTarget().get(); - if (target == nullptr) { - result.AppendError("invalid target, create a debug target using the " - "'target create' command"); - result.SetStatus(eReturnStatusFailed); - return false; - } else { - uint32_t num_dumped = 0; + Target *target = &GetSelectedTarget(); + uint32_t num_dumped = 0; - uint32_t addr_byte_size = target->GetArchitecture().GetAddressByteSize(); - result.GetOutputStream().SetAddressByteSize(addr_byte_size); - result.GetErrorStream().SetAddressByteSize(addr_byte_size); + uint32_t addr_byte_size = target->GetArchitecture().GetAddressByteSize(); + result.GetOutputStream().SetAddressByteSize(addr_byte_size); + result.GetErrorStream().SetAddressByteSize(addr_byte_size); - if (command.GetArgumentCount() == 0) { - // Dump all sections for all modules images - std::lock_guard<std::recursive_mutex> guard( - target->GetImages().GetMutex()); - const size_t num_modules = target->GetImages().GetSize(); - if (num_modules > 0) { - result.GetOutputStream().Printf("Dumping symbol table for %" PRIu64 - " modules.\n", - (uint64_t)num_modules); - for (size_t image_idx = 0; image_idx < num_modules; ++image_idx) { - if (num_dumped > 0) { - result.GetOutputStream().EOL(); - result.GetOutputStream().EOL(); - } - if (m_interpreter.WasInterrupted()) - break; - num_dumped++; - DumpModuleSymtab( - m_interpreter, result.GetOutputStream(), - target->GetImages().GetModulePointerAtIndexUnlocked(image_idx), - m_options.m_sort_order); + if (command.GetArgumentCount() == 0) { + // Dump all sections for all modules images + std::lock_guard<std::recursive_mutex> guard( + target->GetImages().GetMutex()); + const size_t num_modules = target->GetImages().GetSize(); + if (num_modules > 0) { + result.GetOutputStream().Printf("Dumping symbol table for %" PRIu64 + " modules.\n", + (uint64_t)num_modules); + for (size_t image_idx = 0; image_idx < num_modules; ++image_idx) { + if (num_dumped > 0) { + result.GetOutputStream().EOL(); + result.GetOutputStream().EOL(); } - } else { - result.AppendError("the target has no associated executable images"); - result.SetStatus(eReturnStatusFailed); - return false; + if (m_interpreter.WasInterrupted()) + break; + num_dumped++; + DumpModuleSymtab( + m_interpreter, result.GetOutputStream(), + target->GetImages().GetModulePointerAtIndexUnlocked(image_idx), + m_options.m_sort_order); } } else { - // Dump specified images (by basename or fullpath) - const char *arg_cstr; - for (int arg_idx = 0; - (arg_cstr = command.GetArgumentAtIndex(arg_idx)) != nullptr; - ++arg_idx) { - ModuleList module_list; - const size_t num_matches = - FindModulesByName(target, arg_cstr, module_list, true); - if (num_matches > 0) { - for (size_t i = 0; i < num_matches; ++i) { - Module *module = module_list.GetModulePointerAtIndex(i); - if (module) { - if (num_dumped > 0) { - result.GetOutputStream().EOL(); - result.GetOutputStream().EOL(); - } - if (m_interpreter.WasInterrupted()) - break; - num_dumped++; - DumpModuleSymtab(m_interpreter, result.GetOutputStream(), - module, m_options.m_sort_order); + result.AppendError("the target has no associated executable images"); + result.SetStatus(eReturnStatusFailed); + return false; + } + } else { + // Dump specified images (by basename or fullpath) + const char *arg_cstr; + for (int arg_idx = 0; + (arg_cstr = command.GetArgumentAtIndex(arg_idx)) != nullptr; + ++arg_idx) { + ModuleList module_list; + const size_t num_matches = + FindModulesByName(target, arg_cstr, module_list, true); + if (num_matches > 0) { + for (size_t i = 0; i < num_matches; ++i) { + Module *module = module_list.GetModulePointerAtIndex(i); + if (module) { + if (num_dumped > 0) { + result.GetOutputStream().EOL(); + result.GetOutputStream().EOL(); } + if (m_interpreter.WasInterrupted()) + break; + num_dumped++; + DumpModuleSymtab(m_interpreter, result.GetOutputStream(), module, + m_options.m_sort_order); } - } else - result.AppendWarningWithFormat( - "Unable to find an image that matches '%s'.\n", arg_cstr); - } + } + } else + result.AppendWarningWithFormat( + "Unable to find an image that matches '%s'.\n", arg_cstr); } + } - if (num_dumped > 0) - result.SetStatus(eReturnStatusSuccessFinishResult); - else { - result.AppendError("no matching executable images found"); - result.SetStatus(eReturnStatusFailed); - } + if (num_dumped > 0) + result.SetStatus(eReturnStatusSuccessFinishResult); + else { + result.AppendError("no matching executable images found"); + result.SetStatus(eReturnStatusFailed); } return result.Succeeded(); } @@ -2118,82 +2083,75 @@ public: interpreter, "target modules dump sections", "Dump the sections from one or more target modules.", //"target modules dump sections [<file1> ...]") - nullptr) {} + nullptr, eCommandRequiresTarget) {} ~CommandObjectTargetModulesDumpSections() override = default; protected: bool DoExecute(Args &command, CommandReturnObject &result) override { - Target *target = GetDebugger().GetSelectedTarget().get(); - if (target == nullptr) { - result.AppendError("invalid target, create a debug target using the " - "'target create' command"); - result.SetStatus(eReturnStatusFailed); - return false; - } else { - uint32_t num_dumped = 0; + Target *target = &GetSelectedTarget(); + uint32_t num_dumped = 0; - uint32_t addr_byte_size = target->GetArchitecture().GetAddressByteSize(); - result.GetOutputStream().SetAddressByteSize(addr_byte_size); - result.GetErrorStream().SetAddressByteSize(addr_byte_size); + uint32_t addr_byte_size = target->GetArchitecture().GetAddressByteSize(); + result.GetOutputStream().SetAddressByteSize(addr_byte_size); + result.GetErrorStream().SetAddressByteSize(addr_byte_size); - if (command.GetArgumentCount() == 0) { - // Dump all sections for all modules images - const size_t num_modules = target->GetImages().GetSize(); - if (num_modules > 0) { - result.GetOutputStream().Printf("Dumping sections for %" PRIu64 - " modules.\n", - (uint64_t)num_modules); - for (size_t image_idx = 0; image_idx < num_modules; ++image_idx) { + if (command.GetArgumentCount() == 0) { + // Dump all sections for all modules images + const size_t num_modules = target->GetImages().GetSize(); + if (num_modules > 0) { + result.GetOutputStream().Printf("Dumping sections for %" PRIu64 + " modules.\n", + (uint64_t)num_modules); + for (size_t image_idx = 0; image_idx < num_modules; ++image_idx) { + if (m_interpreter.WasInterrupted()) + break; + num_dumped++; + DumpModuleSections( + m_interpreter, result.GetOutputStream(), + target->GetImages().GetModulePointerAtIndex(image_idx)); + } + } else { + result.AppendError("the target has no associated executable images"); + result.SetStatus(eReturnStatusFailed); + return false; + } + } else { + // Dump specified images (by basename or fullpath) + const char *arg_cstr; + for (int arg_idx = 0; + (arg_cstr = command.GetArgumentAtIndex(arg_idx)) != nullptr; + ++arg_idx) { + ModuleList module_list; + const size_t num_matches = + FindModulesByName(target, arg_cstr, module_list, true); + if (num_matches > 0) { + for (size_t i = 0; i < num_matches; ++i) { if (m_interpreter.WasInterrupted()) break; - num_dumped++; - DumpModuleSections( - m_interpreter, result.GetOutputStream(), - target->GetImages().GetModulePointerAtIndex(image_idx)); + Module *module = module_list.GetModulePointerAtIndex(i); + if (module) { + num_dumped++; + DumpModuleSections(m_interpreter, result.GetOutputStream(), + module); + } } } else { - result.AppendError("the target has no associated executable images"); - result.SetStatus(eReturnStatusFailed); - return false; - } - } else { - // Dump specified images (by basename or fullpath) - const char *arg_cstr; - for (int arg_idx = 0; - (arg_cstr = command.GetArgumentAtIndex(arg_idx)) != nullptr; - ++arg_idx) { - ModuleList module_list; - const size_t num_matches = - FindModulesByName(target, arg_cstr, module_list, true); - if (num_matches > 0) { - for (size_t i = 0; i < num_matches; ++i) { - if (m_interpreter.WasInterrupted()) - break; - Module *module = module_list.GetModulePointerAtIndex(i); - if (module) { - num_dumped++; - DumpModuleSections(m_interpreter, result.GetOutputStream(), - module); - } - } - } else { - // Check the global list - std::lock_guard<std::recursive_mutex> guard( - Module::GetAllocationModuleCollectionMutex()); + // Check the global list + std::lock_guard<std::recursive_mutex> guard( + Module::GetAllocationModuleCollectionMutex()); - result.AppendWarningWithFormat( - "Unable to find an image that matches '%s'.\n", arg_cstr); - } + result.AppendWarningWithFormat( + "Unable to find an image that matches '%s'.\n", arg_cstr); } } + } - if (num_dumped > 0) - result.SetStatus(eReturnStatusSuccessFinishResult); - else { - result.AppendError("no matching executable images found"); - result.SetStatus(eReturnStatusFailed); - } + if (num_dumped > 0) + result.SetStatus(eReturnStatusSuccessFinishResult); + else { + result.AppendError("no matching executable images found"); + result.SetStatus(eReturnStatusFailed); } return result.Succeeded(); } @@ -2211,19 +2169,13 @@ public: interpreter, "target modules dump ast", "Dump the clang ast for a given module's symbol file.", //"target modules dump ast [<file1> ...]") - nullptr) {} + nullptr, eCommandRequiresTarget) {} ~CommandObjectTargetModulesDumpClangAST() override = default; protected: bool DoExecute(Args &command, CommandReturnObject &result) override { - Target *target = GetDebugger().GetSelectedTarget().get(); - if (target == nullptr) { - result.AppendError("invalid target, create a debug target using the " - "'target create' command"); - result.SetStatus(eReturnStatusFailed); - return false; - } + Target *target = &GetSelectedTarget(); const size_t num_modules = target->GetImages().GetSize(); if (num_modules == 0) { @@ -2241,8 +2193,8 @@ protected: if (m_interpreter.WasInterrupted()) break; Module *m = target->GetImages().GetModulePointerAtIndex(image_idx); - SymbolFile *sf = m->GetSymbolVendor()->GetSymbolFile(); - sf->DumpClangAST(result.GetOutputStream()); + if (SymbolFile *sf = m->GetSymbolFile()) + sf->DumpClangAST(result.GetOutputStream()); } result.SetStatus(eReturnStatusSuccessFinishResult); return true; @@ -2267,8 +2219,8 @@ protected: if (m_interpreter.WasInterrupted()) break; Module *m = module_list.GetModulePointerAtIndex(i); - SymbolFile *sf = m->GetSymbolVendor()->GetSymbolFile(); - sf->DumpClangAST(result.GetOutputStream()); + if (SymbolFile *sf = m->GetSymbolFile()) + sf->DumpClangAST(result.GetOutputStream()); } } result.SetStatus(eReturnStatusSuccessFinishResult); @@ -2288,84 +2240,79 @@ public: interpreter, "target modules dump symfile", "Dump the debug symbol file for one or more target modules.", //"target modules dump symfile [<file1> ...]") - nullptr) {} + nullptr, eCommandRequiresTarget) {} ~CommandObjectTargetModulesDumpSymfile() override = default; protected: bool DoExecute(Args &command, CommandReturnObject &result) override { - Target *target = GetDebugger().GetSelectedTarget().get(); - if (target == nullptr) { - result.AppendError("invalid target, create a debug target using the " - "'target create' command"); - result.SetStatus(eReturnStatusFailed); - return false; - } else { - uint32_t num_dumped = 0; + Target *target = &GetSelectedTarget(); + uint32_t num_dumped = 0; - uint32_t addr_byte_size = target->GetArchitecture().GetAddressByteSize(); - result.GetOutputStream().SetAddressByteSize(addr_byte_size); - result.GetErrorStream().SetAddressByteSize(addr_byte_size); + uint32_t addr_byte_size = target->GetArchitecture().GetAddressByteSize(); + result.GetOutputStream().SetAddressByteSize(addr_byte_size); + result.GetErrorStream().SetAddressByteSize(addr_byte_size); - if (command.GetArgumentCount() == 0) { - // Dump all sections for all modules images - const ModuleList &target_modules = target->GetImages(); - std::lock_guard<std::recursive_mutex> guard(target_modules.GetMutex()); - const size_t num_modules = target_modules.GetSize(); - if (num_modules > 0) { - result.GetOutputStream().Printf("Dumping debug symbols for %" PRIu64 - " modules.\n", - (uint64_t)num_modules); - for (uint32_t image_idx = 0; image_idx < num_modules; ++image_idx) { - if (m_interpreter.WasInterrupted()) - break; - if (DumpModuleSymbolVendor( - result.GetOutputStream(), - target_modules.GetModulePointerAtIndexUnlocked(image_idx))) - num_dumped++; - } - } else { - result.AppendError("the target has no associated executable images"); - result.SetStatus(eReturnStatusFailed); - return false; + if (command.GetArgumentCount() == 0) { + // Dump all sections for all modules images + const ModuleList &target_modules = target->GetImages(); + std::lock_guard<std::recursive_mutex> guard(target_modules.GetMutex()); + const size_t num_modules = target_modules.GetSize(); + if (num_modules > 0) { + result.GetOutputStream().Printf("Dumping debug symbols for %" PRIu64 + " modules.\n", + (uint64_t)num_modules); + for (uint32_t image_idx = 0; image_idx < num_modules; ++image_idx) { + if (m_interpreter.WasInterrupted()) + break; + if (DumpModuleSymbolFile( + result.GetOutputStream(), + target_modules.GetModulePointerAtIndexUnlocked(image_idx))) + num_dumped++; } } else { - // Dump specified images (by basename or fullpath) - const char *arg_cstr; - for (int arg_idx = 0; - (arg_cstr = command.GetArgumentAtIndex(arg_idx)) != nullptr; - ++arg_idx) { - ModuleList module_list; - const size_t num_matches = - FindModulesByName(target, arg_cstr, module_list, true); - if (num_matches > 0) { - for (size_t i = 0; i < num_matches; ++i) { - if (m_interpreter.WasInterrupted()) - break; - Module *module = module_list.GetModulePointerAtIndex(i); - if (module) { - if (DumpModuleSymbolVendor(result.GetOutputStream(), module)) - num_dumped++; - } + result.AppendError("the target has no associated executable images"); + result.SetStatus(eReturnStatusFailed); + return false; + } + } else { + // Dump specified images (by basename or fullpath) + const char *arg_cstr; + for (int arg_idx = 0; + (arg_cstr = command.GetArgumentAtIndex(arg_idx)) != nullptr; + ++arg_idx) { + ModuleList module_list; + const size_t num_matches = + FindModulesByName(target, arg_cstr, module_list, true); + if (num_matches > 0) { + for (size_t i = 0; i < num_matches; ++i) { + if (m_interpreter.WasInterrupted()) + break; + Module *module = module_list.GetModulePointerAtIndex(i); + if (module) { + if (DumpModuleSymbolFile(result.GetOutputStream(), module)) + num_dumped++; } - } else - result.AppendWarningWithFormat( - "Unable to find an image that matches '%s'.\n", arg_cstr); - } + } + } else + result.AppendWarningWithFormat( + "Unable to find an image that matches '%s'.\n", arg_cstr); } + } - if (num_dumped > 0) - result.SetStatus(eReturnStatusSuccessFinishResult); - else { - result.AppendError("no matching executable images found"); - result.SetStatus(eReturnStatusFailed); - } + if (num_dumped > 0) + result.SetStatus(eReturnStatusSuccessFinishResult); + else { + result.AppendError("no matching executable images found"); + result.SetStatus(eReturnStatusFailed); } return result.Succeeded(); } }; #pragma mark CommandObjectTargetModulesDumpLineTable +#define LLDB_OPTIONS_target_modules_dump +#include "CommandOptions.inc" // Image debug line table dumping command @@ -2454,19 +2401,7 @@ protected: } llvm::ArrayRef<OptionDefinition> GetDefinitions() override { - static constexpr OptionDefinition g_options[] = { - {LLDB_OPT_SET_ALL, - false, - "verbose", - 'v', - OptionParser::eNoArgument, - nullptr, - {}, - 0, - eArgTypeNone, - "Enable verbose dump."}, - }; - return llvm::makeArrayRef(g_options); + return llvm::makeArrayRef(g_target_modules_dump_options); } bool m_verbose; @@ -2518,10 +2453,11 @@ public: CommandObjectTargetModulesAdd(CommandInterpreter &interpreter) : CommandObjectParsed(interpreter, "target modules add", "Add a new module to the current target's modules.", - "target modules add [<module>]"), - m_option_group(), - m_symbol_file(LLDB_OPT_SET_1, false, "symfile", 's', 0, - eArgTypeFilename, "Fullpath to a stand alone debug " + "target modules add [<module>]", + eCommandRequiresTarget), + m_option_group(), m_symbol_file(LLDB_OPT_SET_1, false, "symfile", 's', + 0, eArgTypeFilename, + "Fullpath to a stand alone debug " "symbols file for when debug symbols " "are not in the executable.") { m_option_group.Append(&m_uuid_option_group, LLDB_OPT_SET_ALL, @@ -2534,13 +2470,12 @@ public: Options *GetOptions() override { return &m_option_group; } - int HandleArgumentCompletion( - CompletionRequest &request, - OptionElementVector &opt_element_vector) override { + void + HandleArgumentCompletion(CompletionRequest &request, + OptionElementVector &opt_element_vector) override { CommandCompletions::InvokeCommonCompletionCallbacks( GetCommandInterpreter(), CommandCompletions::eDiskFileCompletion, request, nullptr); - return request.GetNumberOfMatches(); } protected: @@ -2549,125 +2484,117 @@ protected: OptionGroupFile m_symbol_file; bool DoExecute(Args &args, CommandReturnObject &result) override { - Target *target = GetDebugger().GetSelectedTarget().get(); - if (target == nullptr) { - result.AppendError("invalid target, create a debug target using the " - "'target create' command"); - result.SetStatus(eReturnStatusFailed); - return false; - } else { - bool flush = false; + Target *target = &GetSelectedTarget(); + bool flush = false; - const size_t argc = args.GetArgumentCount(); - if (argc == 0) { - if (m_uuid_option_group.GetOptionValue().OptionWasSet()) { - // We are given a UUID only, go locate the file - ModuleSpec module_spec; - module_spec.GetUUID() = - m_uuid_option_group.GetOptionValue().GetCurrentValue(); - if (m_symbol_file.GetOptionValue().OptionWasSet()) - module_spec.GetSymbolFileSpec() = - m_symbol_file.GetOptionValue().GetCurrentValue(); - if (Symbols::DownloadObjectAndSymbolFile(module_spec)) { - ModuleSP module_sp(target->GetOrCreateModule(module_spec, - true /* notify */)); - if (module_sp) { - result.SetStatus(eReturnStatusSuccessFinishResult); - return true; - } else { - StreamString strm; - module_spec.GetUUID().Dump(&strm); - if (module_spec.GetFileSpec()) { - if (module_spec.GetSymbolFileSpec()) { - result.AppendErrorWithFormat( - "Unable to create the executable or symbol file with " - "UUID %s with path %s and symbol file %s", - strm.GetData(), - module_spec.GetFileSpec().GetPath().c_str(), - module_spec.GetSymbolFileSpec().GetPath().c_str()); - } else { - result.AppendErrorWithFormat( - "Unable to create the executable or symbol file with " - "UUID %s with path %s", - strm.GetData(), - module_spec.GetFileSpec().GetPath().c_str()); - } - } else { - result.AppendErrorWithFormat("Unable to create the executable " - "or symbol file with UUID %s", - strm.GetData()); - } - result.SetStatus(eReturnStatusFailed); - return false; - } + const size_t argc = args.GetArgumentCount(); + if (argc == 0) { + if (m_uuid_option_group.GetOptionValue().OptionWasSet()) { + // We are given a UUID only, go locate the file + ModuleSpec module_spec; + module_spec.GetUUID() = + m_uuid_option_group.GetOptionValue().GetCurrentValue(); + if (m_symbol_file.GetOptionValue().OptionWasSet()) + module_spec.GetSymbolFileSpec() = + m_symbol_file.GetOptionValue().GetCurrentValue(); + if (Symbols::DownloadObjectAndSymbolFile(module_spec)) { + ModuleSP module_sp( + target->GetOrCreateModule(module_spec, true /* notify */)); + if (module_sp) { + result.SetStatus(eReturnStatusSuccessFinishResult); + return true; } else { StreamString strm; module_spec.GetUUID().Dump(&strm); - result.AppendErrorWithFormat( - "Unable to locate the executable or symbol file with UUID %s", - strm.GetData()); + if (module_spec.GetFileSpec()) { + if (module_spec.GetSymbolFileSpec()) { + result.AppendErrorWithFormat( + "Unable to create the executable or symbol file with " + "UUID %s with path %s and symbol file %s", + strm.GetData(), module_spec.GetFileSpec().GetPath().c_str(), + module_spec.GetSymbolFileSpec().GetPath().c_str()); + } else { + result.AppendErrorWithFormat( + "Unable to create the executable or symbol file with " + "UUID %s with path %s", + strm.GetData(), + module_spec.GetFileSpec().GetPath().c_str()); + } + } else { + result.AppendErrorWithFormat("Unable to create the executable " + "or symbol file with UUID %s", + strm.GetData()); + } result.SetStatus(eReturnStatusFailed); return false; } } else { - result.AppendError( - "one or more executable image paths must be specified"); + StreamString strm; + module_spec.GetUUID().Dump(&strm); + result.AppendErrorWithFormat( + "Unable to locate the executable or symbol file with UUID %s", + strm.GetData()); result.SetStatus(eReturnStatusFailed); return false; } } else { - for (auto &entry : args.entries()) { - if (entry.ref.empty()) - continue; + result.AppendError( + "one or more executable image paths must be specified"); + result.SetStatus(eReturnStatusFailed); + return false; + } + } else { + for (auto &entry : args.entries()) { + if (entry.ref().empty()) + continue; - FileSpec file_spec(entry.ref); - if (FileSystem::Instance().Exists(file_spec)) { - ModuleSpec module_spec(file_spec); - if (m_uuid_option_group.GetOptionValue().OptionWasSet()) - module_spec.GetUUID() = - m_uuid_option_group.GetOptionValue().GetCurrentValue(); - if (m_symbol_file.GetOptionValue().OptionWasSet()) - module_spec.GetSymbolFileSpec() = - m_symbol_file.GetOptionValue().GetCurrentValue(); - if (!module_spec.GetArchitecture().IsValid()) - module_spec.GetArchitecture() = target->GetArchitecture(); - Status error; - ModuleSP module_sp(target->GetOrCreateModule(module_spec, - true /* notify */, &error)); - if (!module_sp) { - const char *error_cstr = error.AsCString(); - if (error_cstr) - result.AppendError(error_cstr); - else - result.AppendErrorWithFormat("unsupported module: %s", - entry.c_str()); - result.SetStatus(eReturnStatusFailed); - return false; - } else { - flush = true; - } - result.SetStatus(eReturnStatusSuccessFinishResult); - } else { - std::string resolved_path = file_spec.GetPath(); + FileSpec file_spec(entry.ref()); + if (FileSystem::Instance().Exists(file_spec)) { + ModuleSpec module_spec(file_spec); + if (m_uuid_option_group.GetOptionValue().OptionWasSet()) + module_spec.GetUUID() = + m_uuid_option_group.GetOptionValue().GetCurrentValue(); + if (m_symbol_file.GetOptionValue().OptionWasSet()) + module_spec.GetSymbolFileSpec() = + m_symbol_file.GetOptionValue().GetCurrentValue(); + if (!module_spec.GetArchitecture().IsValid()) + module_spec.GetArchitecture() = target->GetArchitecture(); + Status error; + ModuleSP module_sp(target->GetOrCreateModule( + module_spec, true /* notify */, &error)); + if (!module_sp) { + const char *error_cstr = error.AsCString(); + if (error_cstr) + result.AppendError(error_cstr); + else + result.AppendErrorWithFormat("unsupported module: %s", + entry.c_str()); result.SetStatus(eReturnStatusFailed); - if (resolved_path != entry.ref) { - result.AppendErrorWithFormat( - "invalid module path '%s' with resolved path '%s'\n", - entry.ref.str().c_str(), resolved_path.c_str()); - break; - } - result.AppendErrorWithFormat("invalid module path '%s'\n", - entry.c_str()); + return false; + } else { + flush = true; + } + result.SetStatus(eReturnStatusSuccessFinishResult); + } else { + std::string resolved_path = file_spec.GetPath(); + result.SetStatus(eReturnStatusFailed); + if (resolved_path != entry.ref()) { + result.AppendErrorWithFormat( + "invalid module path '%s' with resolved path '%s'\n", + entry.ref().str().c_str(), resolved_path.c_str()); break; } + result.AppendErrorWithFormat("invalid module path '%s'\n", + entry.c_str()); + break; } } + } - if (flush) { - ProcessSP process = target->GetProcessSP(); - if (process) - process->Flush(); - } + if (flush) { + ProcessSP process = target->GetProcessSP(); + if (process) + process->Flush(); } return result.Succeeded(); @@ -2679,11 +2606,12 @@ class CommandObjectTargetModulesLoad public: CommandObjectTargetModulesLoad(CommandInterpreter &interpreter) : CommandObjectTargetModulesModuleAutoComplete( - interpreter, "target modules load", "Set the load addresses for " - "one or more sections in a " - "target module.", + interpreter, "target modules load", + "Set the load addresses for one or more sections in a target " + "module.", "target modules load [--file <module> --uuid <uuid>] <sect-name> " - "<address> [<sect-name> <address> ....]"), + "<address> [<sect-name> <address> ....]", + eCommandRequiresTarget), m_option_group(), m_file_option(LLDB_OPT_SET_1, false, "file", 'f', 0, eArgTypeName, "Fullpath or basename for module to load.", ""), @@ -2712,249 +2640,241 @@ public: protected: bool DoExecute(Args &args, CommandReturnObject &result) override { - Target *target = GetDebugger().GetSelectedTarget().get(); + Target *target = &GetSelectedTarget(); const bool load = m_load_option.GetOptionValue().GetCurrentValue(); const bool set_pc = m_pc_option.GetOptionValue().GetCurrentValue(); - if (target == nullptr) { - result.AppendError("invalid target, create a debug target using the " - "'target create' command"); - result.SetStatus(eReturnStatusFailed); - return false; - } else { - const size_t argc = args.GetArgumentCount(); - ModuleSpec module_spec; - bool search_using_module_spec = false; - - // Allow "load" option to work without --file or --uuid option. - if (load) { - if (!m_file_option.GetOptionValue().OptionWasSet() && - !m_uuid_option_group.GetOptionValue().OptionWasSet()) { - ModuleList &module_list = target->GetImages(); - if (module_list.GetSize() == 1) { - search_using_module_spec = true; - module_spec.GetFileSpec() = - module_list.GetModuleAtIndex(0)->GetFileSpec(); - } - } - } - if (m_file_option.GetOptionValue().OptionWasSet()) { - search_using_module_spec = true; - const char *arg_cstr = m_file_option.GetOptionValue().GetCurrentValue(); - const bool use_global_module_list = true; - ModuleList module_list; - const size_t num_matches = FindModulesByName( - target, arg_cstr, module_list, use_global_module_list); - if (num_matches == 1) { + const size_t argc = args.GetArgumentCount(); + ModuleSpec module_spec; + bool search_using_module_spec = false; + + // Allow "load" option to work without --file or --uuid option. + if (load) { + if (!m_file_option.GetOptionValue().OptionWasSet() && + !m_uuid_option_group.GetOptionValue().OptionWasSet()) { + ModuleList &module_list = target->GetImages(); + if (module_list.GetSize() == 1) { + search_using_module_spec = true; module_spec.GetFileSpec() = module_list.GetModuleAtIndex(0)->GetFileSpec(); - } else if (num_matches > 1) { - search_using_module_spec = false; - result.AppendErrorWithFormat( - "more than 1 module matched by name '%s'\n", arg_cstr); - result.SetStatus(eReturnStatusFailed); - } else { - search_using_module_spec = false; - result.AppendErrorWithFormat("no object file for module '%s'\n", - arg_cstr); - result.SetStatus(eReturnStatusFailed); } } + } - if (m_uuid_option_group.GetOptionValue().OptionWasSet()) { - search_using_module_spec = true; - module_spec.GetUUID() = - m_uuid_option_group.GetOptionValue().GetCurrentValue(); + if (m_file_option.GetOptionValue().OptionWasSet()) { + search_using_module_spec = true; + const char *arg_cstr = m_file_option.GetOptionValue().GetCurrentValue(); + const bool use_global_module_list = true; + ModuleList module_list; + const size_t num_matches = FindModulesByName( + target, arg_cstr, module_list, use_global_module_list); + if (num_matches == 1) { + module_spec.GetFileSpec() = + module_list.GetModuleAtIndex(0)->GetFileSpec(); + } else if (num_matches > 1) { + search_using_module_spec = false; + result.AppendErrorWithFormat( + "more than 1 module matched by name '%s'\n", arg_cstr); + result.SetStatus(eReturnStatusFailed); + } else { + search_using_module_spec = false; + result.AppendErrorWithFormat("no object file for module '%s'\n", + arg_cstr); + result.SetStatus(eReturnStatusFailed); } + } - if (search_using_module_spec) { - ModuleList matching_modules; - const size_t num_matches = - target->GetImages().FindModules(module_spec, matching_modules); - - char path[PATH_MAX]; - if (num_matches == 1) { - Module *module = matching_modules.GetModulePointerAtIndex(0); - if (module) { - ObjectFile *objfile = module->GetObjectFile(); - if (objfile) { - SectionList *section_list = module->GetSectionList(); - if (section_list) { - bool changed = false; - if (argc == 0) { - if (m_slide_option.GetOptionValue().OptionWasSet()) { - const addr_t slide = - m_slide_option.GetOptionValue().GetCurrentValue(); - const bool slide_is_offset = true; - module->SetLoadAddress(*target, slide, slide_is_offset, - changed); - } else { - result.AppendError("one or more section name + load " - "address pair must be specified"); - result.SetStatus(eReturnStatusFailed); - return false; - } + if (m_uuid_option_group.GetOptionValue().OptionWasSet()) { + search_using_module_spec = true; + module_spec.GetUUID() = + m_uuid_option_group.GetOptionValue().GetCurrentValue(); + } + + if (search_using_module_spec) { + ModuleList matching_modules; + target->GetImages().FindModules(module_spec, matching_modules); + const size_t num_matches = matching_modules.GetSize(); + + char path[PATH_MAX]; + if (num_matches == 1) { + Module *module = matching_modules.GetModulePointerAtIndex(0); + if (module) { + ObjectFile *objfile = module->GetObjectFile(); + if (objfile) { + SectionList *section_list = module->GetSectionList(); + if (section_list) { + bool changed = false; + if (argc == 0) { + if (m_slide_option.GetOptionValue().OptionWasSet()) { + const addr_t slide = + m_slide_option.GetOptionValue().GetCurrentValue(); + const bool slide_is_offset = true; + module->SetLoadAddress(*target, slide, slide_is_offset, + changed); } else { - if (m_slide_option.GetOptionValue().OptionWasSet()) { - result.AppendError("The \"--slide <offset>\" option can't " - "be used in conjunction with setting " - "section load addresses.\n"); - result.SetStatus(eReturnStatusFailed); - return false; - } + result.AppendError("one or more section name + load " + "address pair must be specified"); + result.SetStatus(eReturnStatusFailed); + return false; + } + } else { + if (m_slide_option.GetOptionValue().OptionWasSet()) { + result.AppendError("The \"--slide <offset>\" option can't " + "be used in conjunction with setting " + "section load addresses.\n"); + result.SetStatus(eReturnStatusFailed); + return false; + } - for (size_t i = 0; i < argc; i += 2) { - const char *sect_name = args.GetArgumentAtIndex(i); - const char *load_addr_cstr = args.GetArgumentAtIndex(i + 1); - if (sect_name && load_addr_cstr) { - ConstString const_sect_name(sect_name); - bool success = false; - addr_t load_addr = StringConvert::ToUInt64( - load_addr_cstr, LLDB_INVALID_ADDRESS, 0, &success); - if (success) { - SectionSP section_sp( - section_list->FindSectionByName(const_sect_name)); - if (section_sp) { - if (section_sp->IsThreadSpecific()) { - result.AppendErrorWithFormat( - "thread specific sections are not yet " - "supported (section '%s')\n", - sect_name); - result.SetStatus(eReturnStatusFailed); - break; - } else { - if (target->GetSectionLoadList() - .SetSectionLoadAddress(section_sp, - load_addr)) - changed = true; - result.AppendMessageWithFormat( - "section '%s' loaded at 0x%" PRIx64 "\n", - sect_name, load_addr); - } - } else { - result.AppendErrorWithFormat("no section found that " - "matches the section " - "name '%s'\n", - sect_name); + for (size_t i = 0; i < argc; i += 2) { + const char *sect_name = args.GetArgumentAtIndex(i); + const char *load_addr_cstr = args.GetArgumentAtIndex(i + 1); + if (sect_name && load_addr_cstr) { + ConstString const_sect_name(sect_name); + bool success = false; + addr_t load_addr = StringConvert::ToUInt64( + load_addr_cstr, LLDB_INVALID_ADDRESS, 0, &success); + if (success) { + SectionSP section_sp( + section_list->FindSectionByName(const_sect_name)); + if (section_sp) { + if (section_sp->IsThreadSpecific()) { + result.AppendErrorWithFormat( + "thread specific sections are not yet " + "supported (section '%s')\n", + sect_name); result.SetStatus(eReturnStatusFailed); break; + } else { + if (target->GetSectionLoadList() + .SetSectionLoadAddress(section_sp, load_addr)) + changed = true; + result.AppendMessageWithFormat( + "section '%s' loaded at 0x%" PRIx64 "\n", + sect_name, load_addr); } } else { - result.AppendErrorWithFormat( - "invalid load address string '%s'\n", - load_addr_cstr); + result.AppendErrorWithFormat("no section found that " + "matches the section " + "name '%s'\n", + sect_name); result.SetStatus(eReturnStatusFailed); break; } } else { - if (sect_name) - result.AppendError("section names must be followed by " - "a load address.\n"); - else - result.AppendError("one or more section name + load " - "address pair must be specified.\n"); + result.AppendErrorWithFormat( + "invalid load address string '%s'\n", load_addr_cstr); result.SetStatus(eReturnStatusFailed); break; } + } else { + if (sect_name) + result.AppendError("section names must be followed by " + "a load address.\n"); + else + result.AppendError("one or more section name + load " + "address pair must be specified.\n"); + result.SetStatus(eReturnStatusFailed); + break; } } + } - if (changed) { - target->ModulesDidLoad(matching_modules); - Process *process = m_exe_ctx.GetProcessPtr(); - if (process) - process->Flush(); + if (changed) { + target->ModulesDidLoad(matching_modules); + Process *process = m_exe_ctx.GetProcessPtr(); + if (process) + process->Flush(); + } + if (load) { + ProcessSP process = target->CalculateProcess(); + Address file_entry = objfile->GetEntryPointAddress(); + if (!process) { + result.AppendError("No process"); + return false; } - if (load) { - ProcessSP process = target->CalculateProcess(); - Address file_entry = objfile->GetEntryPointAddress(); - if (!process) { - result.AppendError("No process"); - return false; - } - if (set_pc && !file_entry.IsValid()) { - result.AppendError("No entry address in object file"); - return false; - } - std::vector<ObjectFile::LoadableData> loadables( - objfile->GetLoadableData(*target)); - if (loadables.size() == 0) { - result.AppendError("No loadable sections"); - return false; - } - Status error = process->WriteObjectFile(std::move(loadables)); - if (error.Fail()) { - result.AppendError(error.AsCString()); - return false; - } - if (set_pc) { - ThreadList &thread_list = process->GetThreadList(); - RegisterContextSP reg_context( - thread_list.GetSelectedThread()->GetRegisterContext()); - addr_t file_entry_addr = file_entry.GetLoadAddress(target); - if (!reg_context->SetPC(file_entry_addr)) { - result.AppendErrorWithFormat("failed to set PC value to " - "0x%" PRIx64 "\n", - file_entry_addr); - result.SetStatus(eReturnStatusFailed); - } + if (set_pc && !file_entry.IsValid()) { + result.AppendError("No entry address in object file"); + return false; + } + std::vector<ObjectFile::LoadableData> loadables( + objfile->GetLoadableData(*target)); + if (loadables.size() == 0) { + result.AppendError("No loadable sections"); + return false; + } + Status error = process->WriteObjectFile(std::move(loadables)); + if (error.Fail()) { + result.AppendError(error.AsCString()); + return false; + } + if (set_pc) { + ThreadList &thread_list = process->GetThreadList(); + RegisterContextSP reg_context( + thread_list.GetSelectedThread()->GetRegisterContext()); + addr_t file_entry_addr = file_entry.GetLoadAddress(target); + if (!reg_context->SetPC(file_entry_addr)) { + result.AppendErrorWithFormat("failed to set PC value to " + "0x%" PRIx64 "\n", + file_entry_addr); + result.SetStatus(eReturnStatusFailed); } } - } else { - module->GetFileSpec().GetPath(path, sizeof(path)); - result.AppendErrorWithFormat( - "no sections in object file '%s'\n", path); - result.SetStatus(eReturnStatusFailed); } } else { module->GetFileSpec().GetPath(path, sizeof(path)); - result.AppendErrorWithFormat("no object file for module '%s'\n", + result.AppendErrorWithFormat("no sections in object file '%s'\n", path); result.SetStatus(eReturnStatusFailed); } } else { - FileSpec *module_spec_file = module_spec.GetFileSpecPtr(); - if (module_spec_file) { - module_spec_file->GetPath(path, sizeof(path)); - result.AppendErrorWithFormat("invalid module '%s'.\n", path); - } else - result.AppendError("no module spec"); + module->GetFileSpec().GetPath(path, sizeof(path)); + result.AppendErrorWithFormat("no object file for module '%s'\n", + path); result.SetStatus(eReturnStatusFailed); } } else { - std::string uuid_str; + FileSpec *module_spec_file = module_spec.GetFileSpecPtr(); + if (module_spec_file) { + module_spec_file->GetPath(path, sizeof(path)); + result.AppendErrorWithFormat("invalid module '%s'.\n", path); + } else + result.AppendError("no module spec"); + result.SetStatus(eReturnStatusFailed); + } + } else { + std::string uuid_str; - if (module_spec.GetFileSpec()) - module_spec.GetFileSpec().GetPath(path, sizeof(path)); - else - path[0] = '\0'; + if (module_spec.GetFileSpec()) + module_spec.GetFileSpec().GetPath(path, sizeof(path)); + else + path[0] = '\0'; - if (module_spec.GetUUIDPtr()) - uuid_str = module_spec.GetUUID().GetAsString(); - if (num_matches > 1) { - result.AppendErrorWithFormat( - "multiple modules match%s%s%s%s:\n", path[0] ? " file=" : "", - path, !uuid_str.empty() ? " uuid=" : "", uuid_str.c_str()); - for (size_t i = 0; i < num_matches; ++i) { - if (matching_modules.GetModulePointerAtIndex(i) - ->GetFileSpec() - .GetPath(path, sizeof(path))) - result.AppendMessageWithFormat("%s\n", path); - } - } else { - result.AppendErrorWithFormat( - "no modules were found that match%s%s%s%s.\n", - path[0] ? " file=" : "", path, - !uuid_str.empty() ? " uuid=" : "", uuid_str.c_str()); + if (module_spec.GetUUIDPtr()) + uuid_str = module_spec.GetUUID().GetAsString(); + if (num_matches > 1) { + result.AppendErrorWithFormat( + "multiple modules match%s%s%s%s:\n", path[0] ? " file=" : "", + path, !uuid_str.empty() ? " uuid=" : "", uuid_str.c_str()); + for (size_t i = 0; i < num_matches; ++i) { + if (matching_modules.GetModulePointerAtIndex(i) + ->GetFileSpec() + .GetPath(path, sizeof(path))) + result.AppendMessageWithFormat("%s\n", path); } - result.SetStatus(eReturnStatusFailed); + } else { + result.AppendErrorWithFormat( + "no modules were found that match%s%s%s%s.\n", + path[0] ? " file=" : "", path, !uuid_str.empty() ? " uuid=" : "", + uuid_str.c_str()); } - } else { - result.AppendError("either the \"--file <module>\" or the \"--uuid " - "<uuid>\" option must be specified.\n"); result.SetStatus(eReturnStatusFailed); - return false; } + } else { + result.AppendError("either the \"--file <module>\" or the \"--uuid " + "<uuid>\" option must be specified.\n"); + result.SetStatus(eReturnStatusFailed); + return false; } return result.Succeeded(); } @@ -2968,26 +2888,8 @@ protected: }; // List images with associated information - -static constexpr OptionDefinition g_target_modules_list_options[] = { - // clang-format off - { LLDB_OPT_SET_1, false, "address", 'a', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeAddressOrExpression, "Display the image at this address." }, - { LLDB_OPT_SET_1, false, "arch", 'A', OptionParser::eOptionalArgument, nullptr, {}, 0, eArgTypeWidth, "Display the architecture when listing images." }, - { LLDB_OPT_SET_1, false, "triple", 't', OptionParser::eOptionalArgument, nullptr, {}, 0, eArgTypeWidth, "Display the triple when listing images." }, - { LLDB_OPT_SET_1, false, "header", 'h', OptionParser::eNoArgument, nullptr, {}, 0, eArgTypeNone, "Display the image base address as a load address if debugging, a file address otherwise." }, - { LLDB_OPT_SET_1, false, "offset", 'o', OptionParser::eNoArgument, nullptr, {}, 0, eArgTypeNone, "Display the image load address offset from the base file address (the slide amount)." }, - { LLDB_OPT_SET_1, false, "uuid", 'u', OptionParser::eNoArgument, nullptr, {}, 0, eArgTypeNone, "Display the UUID when listing images." }, - { LLDB_OPT_SET_1, false, "fullpath", 'f', OptionParser::eOptionalArgument, nullptr, {}, 0, eArgTypeWidth, "Display the fullpath to the image object file." }, - { LLDB_OPT_SET_1, false, "directory", 'd', OptionParser::eOptionalArgument, nullptr, {}, 0, eArgTypeWidth, "Display the directory with optional width for the image object file." }, - { LLDB_OPT_SET_1, false, "basename", 'b', OptionParser::eOptionalArgument, nullptr, {}, 0, eArgTypeWidth, "Display the basename with optional width for the image object file." }, - { LLDB_OPT_SET_1, false, "symfile", 's', OptionParser::eOptionalArgument, nullptr, {}, 0, eArgTypeWidth, "Display the fullpath to the image symbol file with optional width." }, - { LLDB_OPT_SET_1, false, "symfile-unique", 'S', OptionParser::eOptionalArgument, nullptr, {}, 0, eArgTypeWidth, "Display the symbol file with optional width only if it is different from the executable object file." }, - { LLDB_OPT_SET_1, false, "mod-time", 'm', OptionParser::eOptionalArgument, nullptr, {}, 0, eArgTypeWidth, "Display the modification time with optional width of the module." }, - { LLDB_OPT_SET_1, false, "ref-count", 'r', OptionParser::eOptionalArgument, nullptr, {}, 0, eArgTypeWidth, "Display the reference count if the module is still in the shared module cache." }, - { LLDB_OPT_SET_1, false, "pointer", 'p', OptionParser::eOptionalArgument, nullptr, {}, 0, eArgTypeNone, "Display the module pointer." }, - { LLDB_OPT_SET_1, false, "global", 'g', OptionParser::eNoArgument, nullptr, {}, 0, eArgTypeNone, "Display the modules from the global module list, not just the current target." } - // clang-format on -}; +#define LLDB_OPTIONS_target_modules_list +#include "CommandOptions.inc" class CommandObjectTargetModulesList : public CommandObjectParsed { public: @@ -3282,9 +3184,9 @@ protected: case 's': case 'S': { - const SymbolVendor *symbol_vendor = module->GetSymbolVendor(); - if (symbol_vendor) { - const FileSpec symfile_spec = symbol_vendor->GetMainFileSpec(); + if (const SymbolFile *symbol_file = module->GetSymbolFile()) { + const FileSpec symfile_spec = + symbol_file->GetObjectFile()->GetFileSpec(); if (format_char == 'S') { // Dump symbol file only if different from module file if (!symfile_spec || symfile_spec == module->GetFileSpec()) { @@ -3332,13 +3234,8 @@ protected: #pragma mark CommandObjectTargetModulesShowUnwind // Lookup unwind information in images - -static constexpr OptionDefinition g_target_modules_show_unwind_options[] = { - // clang-format off - { LLDB_OPT_SET_1, false, "name", 'n', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeFunctionName, "Show unwind instructions for a function or symbol name." }, - { LLDB_OPT_SET_2, false, "address", 'a', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeAddressOrExpression, "Show unwind instructions for a function or symbol containing an address" } - // clang-format on -}; +#define LLDB_OPTIONS_target_modules_show_unwind +#include "CommandOptions.inc" class CommandObjectTargetModulesShowUnwind : public CommandObjectParsed { public: @@ -3383,8 +3280,7 @@ public: break; default: - error.SetErrorStringWithFormat("unrecognized option %c.", short_option); - break; + llvm_unreachable("Unimplemented option"); } return error; @@ -3453,7 +3349,7 @@ protected: if (m_options.m_type == eLookupTypeFunctionOrSymbol) { ConstString function_name(m_options.m_str.c_str()); target->GetImages().FindFunctions(function_name, eFunctionNameTypeAuto, - true, false, true, sc_list); + true, false, sc_list); } else if (m_options.m_type == eLookupTypeAddress && target) { Address addr; if (target->GetSectionLoadList().ResolveLoadAddress(m_options.m_addr, @@ -3546,6 +3442,25 @@ protected: result.GetOutputStream().Printf("\n"); } + UnwindPlanSP of_unwind_sp = + func_unwinders_sp->GetObjectFileUnwindPlan(*target); + if (of_unwind_sp) { + result.GetOutputStream().Printf("object file UnwindPlan:\n"); + of_unwind_sp->Dump(result.GetOutputStream(), thread.get(), + LLDB_INVALID_ADDRESS); + result.GetOutputStream().Printf("\n"); + } + + UnwindPlanSP of_unwind_augmented_sp = + func_unwinders_sp->GetObjectFileAugmentedUnwindPlan(*target, + *thread); + if (of_unwind_augmented_sp) { + result.GetOutputStream().Printf("object file augmented UnwindPlan:\n"); + of_unwind_augmented_sp->Dump(result.GetOutputStream(), thread.get(), + LLDB_INVALID_ADDRESS); + result.GetOutputStream().Printf("\n"); + } + UnwindPlanSP ehframe_sp = func_unwinders_sp->GetEHFrameUnwindPlan(*target); if (ehframe_sp) { @@ -3643,24 +3558,8 @@ protected: }; // Lookup information in images - -static constexpr OptionDefinition g_target_modules_lookup_options[] = { - // clang-format off - { LLDB_OPT_SET_1, true, "address", 'a', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeAddressOrExpression, "Lookup an address in one or more target modules." }, - { LLDB_OPT_SET_1, false, "offset", 'o', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeOffset, "When looking up an address subtract <offset> from any addresses before doing the lookup." }, - /* FIXME: re-enable regex for types when the LookupTypeInModule actually uses the regex option: | LLDB_OPT_SET_6 */ - { LLDB_OPT_SET_2 | LLDB_OPT_SET_4 | LLDB_OPT_SET_5, false, "regex", 'r', OptionParser::eNoArgument, nullptr, {}, 0, eArgTypeNone, "The <name> argument for name lookups are regular expressions." }, - { LLDB_OPT_SET_2, true, "symbol", 's', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeSymbol, "Lookup a symbol by name in the symbol tables in one or more target modules." }, - { LLDB_OPT_SET_3, true, "file", 'f', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeFilename, "Lookup a file by fullpath or basename in one or more target modules." }, - { LLDB_OPT_SET_3, false, "line", 'l', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeLineNum, "Lookup a line number in a file (must be used in conjunction with --file)." }, - { LLDB_OPT_SET_FROM_TO(3,5), false, "no-inlines", 'i', OptionParser::eNoArgument, nullptr, {}, 0, eArgTypeNone, "Ignore inline entries (must be used in conjunction with --file or --function)." }, - { LLDB_OPT_SET_4, true, "function", 'F', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeFunctionName, "Lookup a function by name in the debug symbols in one or more target modules." }, - { LLDB_OPT_SET_5, true, "name", 'n', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeFunctionOrSymbol, "Lookup a function or symbol by name in one or more target modules." }, - { LLDB_OPT_SET_6, true, "type", 't', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeName, "Lookup a type by name in the debug symbols in one or more target modules." }, - { LLDB_OPT_SET_ALL, false, "verbose", 'v', OptionParser::eNoArgument, nullptr, {}, 0, eArgTypeNone, "Enable verbose lookup information." }, - { LLDB_OPT_SET_ALL, false, "all", 'A', OptionParser::eNoArgument, nullptr, {}, 0, eArgTypeNone, "Print all matches, not just the best match, if a best match is available." }, - // clang-format on -}; +#define LLDB_OPTIONS_target_modules_lookup +#include "CommandOptions.inc" class CommandObjectTargetModulesLookup : public CommandObjectParsed { public: @@ -3749,6 +3648,8 @@ public: case 'r': m_use_regex = true; break; + default: + llvm_unreachable("Unimplemented option"); } return error; @@ -3935,91 +3836,82 @@ public: protected: bool DoExecute(Args &command, CommandReturnObject &result) override { - Target *target = GetDebugger().GetSelectedTarget().get(); - if (target == nullptr) { - result.AppendError("invalid target, create a debug target using the " - "'target create' command"); - result.SetStatus(eReturnStatusFailed); - return false; - } else { - bool syntax_error = false; - uint32_t i; - uint32_t num_successful_lookups = 0; - uint32_t addr_byte_size = target->GetArchitecture().GetAddressByteSize(); - result.GetOutputStream().SetAddressByteSize(addr_byte_size); - result.GetErrorStream().SetAddressByteSize(addr_byte_size); - // Dump all sections for all modules images - - if (command.GetArgumentCount() == 0) { - ModuleSP current_module; + Target *target = &GetSelectedTarget(); + bool syntax_error = false; + uint32_t i; + uint32_t num_successful_lookups = 0; + uint32_t addr_byte_size = target->GetArchitecture().GetAddressByteSize(); + result.GetOutputStream().SetAddressByteSize(addr_byte_size); + result.GetErrorStream().SetAddressByteSize(addr_byte_size); + // Dump all sections for all modules images - // Where it is possible to look in the current symbol context first, - // try that. If this search was successful and --all was not passed, - // don't print anything else. - if (LookupHere(m_interpreter, result, syntax_error)) { - result.GetOutputStream().EOL(); - num_successful_lookups++; - if (!m_options.m_print_all) { - result.SetStatus(eReturnStatusSuccessFinishResult); - return result.Succeeded(); - } + if (command.GetArgumentCount() == 0) { + ModuleSP current_module; + + // Where it is possible to look in the current symbol context first, + // try that. If this search was successful and --all was not passed, + // don't print anything else. + if (LookupHere(m_interpreter, result, syntax_error)) { + result.GetOutputStream().EOL(); + num_successful_lookups++; + if (!m_options.m_print_all) { + result.SetStatus(eReturnStatusSuccessFinishResult); + return result.Succeeded(); } + } - // Dump all sections for all other modules + // Dump all sections for all other modules - const ModuleList &target_modules = target->GetImages(); - std::lock_guard<std::recursive_mutex> guard(target_modules.GetMutex()); - const size_t num_modules = target_modules.GetSize(); - if (num_modules > 0) { - for (i = 0; i < num_modules && !syntax_error; ++i) { - Module *module_pointer = - target_modules.GetModulePointerAtIndexUnlocked(i); - - if (module_pointer != current_module.get() && - LookupInModule( - m_interpreter, - target_modules.GetModulePointerAtIndexUnlocked(i), result, - syntax_error)) { - result.GetOutputStream().EOL(); - num_successful_lookups++; - } + const ModuleList &target_modules = target->GetImages(); + std::lock_guard<std::recursive_mutex> guard(target_modules.GetMutex()); + const size_t num_modules = target_modules.GetSize(); + if (num_modules > 0) { + for (i = 0; i < num_modules && !syntax_error; ++i) { + Module *module_pointer = + target_modules.GetModulePointerAtIndexUnlocked(i); + + if (module_pointer != current_module.get() && + LookupInModule(m_interpreter, + target_modules.GetModulePointerAtIndexUnlocked(i), + result, syntax_error)) { + result.GetOutputStream().EOL(); + num_successful_lookups++; } - } else { - result.AppendError("the target has no associated executable images"); - result.SetStatus(eReturnStatusFailed); - return false; } } else { - // Dump specified images (by basename or fullpath) - const char *arg_cstr; - for (i = 0; (arg_cstr = command.GetArgumentAtIndex(i)) != nullptr && - !syntax_error; - ++i) { - ModuleList module_list; - const size_t num_matches = - FindModulesByName(target, arg_cstr, module_list, false); - if (num_matches > 0) { - for (size_t j = 0; j < num_matches; ++j) { - Module *module = module_list.GetModulePointerAtIndex(j); - if (module) { - if (LookupInModule(m_interpreter, module, result, - syntax_error)) { - result.GetOutputStream().EOL(); - num_successful_lookups++; - } + result.AppendError("the target has no associated executable images"); + result.SetStatus(eReturnStatusFailed); + return false; + } + } else { + // Dump specified images (by basename or fullpath) + const char *arg_cstr; + for (i = 0; (arg_cstr = command.GetArgumentAtIndex(i)) != nullptr && + !syntax_error; + ++i) { + ModuleList module_list; + const size_t num_matches = + FindModulesByName(target, arg_cstr, module_list, false); + if (num_matches > 0) { + for (size_t j = 0; j < num_matches; ++j) { + Module *module = module_list.GetModulePointerAtIndex(j); + if (module) { + if (LookupInModule(m_interpreter, module, result, syntax_error)) { + result.GetOutputStream().EOL(); + num_successful_lookups++; } } - } else - result.AppendWarningWithFormat( - "Unable to find an image that matches '%s'.\n", arg_cstr); - } + } + } else + result.AppendWarningWithFormat( + "Unable to find an image that matches '%s'.\n", arg_cstr); } - - if (num_successful_lookups > 0) - result.SetStatus(eReturnStatusSuccessFinishResult); - else - result.SetStatus(eReturnStatusFailed); } + + if (num_successful_lookups > 0) + result.SetStatus(eReturnStatusSuccessFinishResult); + else + result.SetStatus(eReturnStatusFailed); return result.Succeeded(); } @@ -4129,13 +4021,12 @@ public: ~CommandObjectTargetSymbolsAdd() override = default; - int HandleArgumentCompletion( - CompletionRequest &request, - OptionElementVector &opt_element_vector) override { + void + HandleArgumentCompletion(CompletionRequest &request, + OptionElementVector &opt_element_vector) override { CommandCompletions::InvokeCommonCompletionCallbacks( GetCommandInterpreter(), CommandCompletions::eDiskFileCompletion, request, nullptr); - return request.GetNumberOfMatches(); } Options *GetOptions() override { return &m_option_group; } @@ -4173,8 +4064,9 @@ protected: // It has a UUID, look for this UUID in the target modules ModuleSpec symfile_uuid_module_spec; symfile_uuid_module_spec.GetUUID() = symfile_module_spec.GetUUID(); - num_matches = target->GetImages().FindModules( - symfile_uuid_module_spec, matching_module_list); + target->GetImages().FindModules(symfile_uuid_module_spec, + matching_module_list); + num_matches = matching_module_list.GetSize(); } } @@ -4192,8 +4084,9 @@ protected: ModuleSpec symfile_uuid_module_spec; symfile_uuid_module_spec.GetUUID() = symfile_module_spec.GetUUID(); - num_matches = target->GetImages().FindModules( - symfile_uuid_module_spec, matching_module_list); + target->GetImages().FindModules(symfile_uuid_module_spec, + matching_module_list); + num_matches = matching_module_list.GetSize(); } } } @@ -4202,9 +4095,10 @@ protected: // Just try to match up the file by basename if we have no matches at // this point - if (num_matches == 0) - num_matches = - target->GetImages().FindModules(module_spec, matching_module_list); + if (num_matches == 0) { + target->GetImages().FindModules(module_spec, matching_module_list); + num_matches = matching_module_list.GetSize(); + } while (num_matches == 0) { ConstString filename_no_extension( @@ -4221,8 +4115,8 @@ protected: // Replace basename with one less extension module_spec.GetFileSpec().GetFilename() = filename_no_extension; - num_matches = - target->GetImages().FindModules(module_spec, matching_module_list); + target->GetImages().FindModules(module_spec, matching_module_list); + num_matches = matching_module_list.GetSize(); } if (num_matches > 1) { @@ -4238,48 +4132,44 @@ protected: // decides to create it! module_sp->SetSymbolFileFileSpec(symbol_fspec); - SymbolVendor *symbol_vendor = - module_sp->GetSymbolVendor(true, &result.GetErrorStream()); - if (symbol_vendor) { - SymbolFile *symbol_file = symbol_vendor->GetSymbolFile(); - - if (symbol_file) { - ObjectFile *object_file = symbol_file->GetObjectFile(); - - if (object_file && object_file->GetFileSpec() == symbol_fspec) { - // Provide feedback that the symfile has been successfully added. - const FileSpec &module_fs = module_sp->GetFileSpec(); - result.AppendMessageWithFormat( - "symbol file '%s' has been added to '%s'\n", symfile_path, - module_fs.GetPath().c_str()); - - // Let clients know something changed in the module if it is - // currently loaded - ModuleList module_list; - module_list.Append(module_sp); - target->SymbolsDidLoad(module_list); - - // Make sure we load any scripting resources that may be embedded - // in the debug info files in case the platform supports that. - Status error; - StreamString feedback_stream; - module_sp->LoadScriptingResourceInTarget(target, error, - &feedback_stream); - if (error.Fail() && error.AsCString()) - result.AppendWarningWithFormat( - "unable to load scripting data for module %s - error " - "reported was %s", - module_sp->GetFileSpec() - .GetFileNameStrippingExtension() - .GetCString(), - error.AsCString()); - else if (feedback_stream.GetSize()) - result.AppendWarningWithFormat("%s", feedback_stream.GetData()); - - flush = true; - result.SetStatus(eReturnStatusSuccessFinishResult); - return true; - } + SymbolFile *symbol_file = + module_sp->GetSymbolFile(true, &result.GetErrorStream()); + if (symbol_file) { + ObjectFile *object_file = symbol_file->GetObjectFile(); + + if (object_file && object_file->GetFileSpec() == symbol_fspec) { + // Provide feedback that the symfile has been successfully added. + const FileSpec &module_fs = module_sp->GetFileSpec(); + result.AppendMessageWithFormat( + "symbol file '%s' has been added to '%s'\n", symfile_path, + module_fs.GetPath().c_str()); + + // Let clients know something changed in the module if it is + // currently loaded + ModuleList module_list; + module_list.Append(module_sp); + target->SymbolsDidLoad(module_list); + + // Make sure we load any scripting resources that may be embedded + // in the debug info files in case the platform supports that. + Status error; + StreamString feedback_stream; + module_sp->LoadScriptingResourceInTarget(target, error, + &feedback_stream); + if (error.Fail() && error.AsCString()) + result.AppendWarningWithFormat( + "unable to load scripting data for module %s - error " + "reported was %s", + module_sp->GetFileSpec() + .GetFileNameStrippingExtension() + .GetCString(), + error.AsCString()); + else if (feedback_stream.GetSize()) + result.AppendWarningWithFormat("%s", feedback_stream.GetData()); + + flush = true; + result.SetStatus(eReturnStatusSuccessFinishResult); + return true; } } // Clear the symbol file spec if anything went wrong @@ -4430,9 +4320,9 @@ protected: PlatformSP platform_sp(target->GetPlatform()); for (auto &entry : args.entries()) { - if (!entry.ref.empty()) { + if (!entry.ref().empty()) { auto &symbol_file_spec = module_spec.GetSymbolFileSpec(); - symbol_file_spec.SetFile(entry.ref, FileSpec::Style::native); + symbol_file_spec.SetFile(entry.ref(), FileSpec::Style::native); FileSystem::Instance().Resolve(symbol_file_spec); if (file_option_set) { module_spec.GetFileSpec() = @@ -4456,7 +4346,7 @@ protected: } else { std::string resolved_symfile_path = module_spec.GetSymbolFileSpec().GetPath(); - if (resolved_symfile_path != entry.ref) { + if (resolved_symfile_path != entry.ref()) { result.AppendErrorWithFormat( "invalid module path '%s' with resolved path '%s'\n", entry.c_str(), resolved_symfile_path.c_str()); @@ -4511,23 +4401,8 @@ private: #pragma mark CommandObjectTargetStopHookAdd // CommandObjectTargetStopHookAdd - -static constexpr OptionDefinition g_target_stop_hook_add_options[] = { - // clang-format off - { LLDB_OPT_SET_ALL, false, "one-liner", 'o', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeOneLiner, "Add a command for the stop hook. Can be specified more than once, and commands will be run in the order they appear." }, - { LLDB_OPT_SET_ALL, false, "shlib", 's', OptionParser::eRequiredArgument, nullptr, {}, CommandCompletions::eModuleCompletion, eArgTypeShlibName, "Set the module within which the stop-hook is to be run." }, - { LLDB_OPT_SET_ALL, false, "thread-index", 'x', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeThreadIndex, "The stop hook is run only for the thread whose index matches this argument." }, - { LLDB_OPT_SET_ALL, false, "thread-id", 't', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeThreadID, "The stop hook is run only for the thread whose TID matches this argument." }, - { LLDB_OPT_SET_ALL, false, "thread-name", 'T', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeThreadName, "The stop hook is run only for the thread whose thread name matches this argument." }, - { LLDB_OPT_SET_ALL, false, "queue-name", 'q', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeQueueName, "The stop hook is run only for threads in the queue whose name is given by this argument." }, - { LLDB_OPT_SET_1, false, "file", 'f', OptionParser::eRequiredArgument, nullptr, {}, CommandCompletions::eSourceFileCompletion, eArgTypeFilename, "Specify the source file within which the stop-hook is to be run." }, - { LLDB_OPT_SET_1, false, "start-line", 'l', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeLineNum, "Set the start of the line range for which the stop-hook is to be run." }, - { LLDB_OPT_SET_1, false, "end-line", 'e', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeLineNum, "Set the end of the line range for which the stop-hook is to be run." }, - { LLDB_OPT_SET_2, false, "classname", 'c', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeClassName, "Specify the class within which the stop-hook is to be run." }, - { LLDB_OPT_SET_3, false, "name", 'n', OptionParser::eRequiredArgument, nullptr, {}, CommandCompletions::eSymbolCompletion, eArgTypeFunctionName, "Set the function name within which the stop hook will be run." }, - { LLDB_OPT_SET_ALL, false, "auto-continue",'G', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeBoolean, "The breakpoint will auto-continue after running its commands." }, - // clang-format on -}; +#define LLDB_OPTIONS_target_stop_hook_add +#include "CommandOptions.inc" class CommandObjectTargetStopHookAdd : public CommandObjectParsed, public IOHandlerDelegateMultiline { @@ -4636,8 +4511,7 @@ public: break; default: - error.SetErrorStringWithFormat("unrecognized option %c.", short_option); - break; + llvm_unreachable("Unimplemented option"); } return error; } @@ -4698,7 +4572,7 @@ public: protected: void IOHandlerActivated(IOHandler &io_handler, bool interactive) override { - StreamFileSP output_sp(io_handler.GetOutputStreamFile()); + StreamFileSP output_sp(io_handler.GetOutputStreamFileSP()); if (output_sp && interactive) { output_sp->PutCString( "Enter your stop hook command(s). Type 'DONE' to end.\n"); @@ -4710,7 +4584,7 @@ protected: std::string &line) override { if (m_stop_hook_sp) { if (line.empty()) { - StreamFileSP error_sp(io_handler.GetErrorStreamFile()); + StreamFileSP error_sp(io_handler.GetErrorStreamFileSP()); if (error_sp) { error_sp->Printf("error: stop hook #%" PRIu64 " aborted, no commands.\n", @@ -4722,7 +4596,7 @@ protected: target->RemoveStopHookByID(m_stop_hook_sp->GetID()); } else { m_stop_hook_sp->GetCommandPointer()->SplitIntoLines(line); - StreamFileSP output_sp(io_handler.GetOutputStreamFile()); + StreamFileSP output_sp(io_handler.GetOutputStreamFileSP()); if (output_sp) { output_sp->Printf("Stop hook #%" PRIu64 " added.\n", m_stop_hook_sp->GetID()); @@ -4737,52 +4611,50 @@ protected: bool DoExecute(Args &command, CommandReturnObject &result) override { m_stop_hook_sp.reset(); - Target *target = GetSelectedOrDummyTarget(); - if (target) { - Target::StopHookSP new_hook_sp = target->CreateStopHook(); - - // First step, make the specifier. - std::unique_ptr<SymbolContextSpecifier> specifier_up; - if (m_options.m_sym_ctx_specified) { - specifier_up.reset( - new SymbolContextSpecifier(GetDebugger().GetSelectedTarget())); - - if (!m_options.m_module_name.empty()) { - specifier_up->AddSpecification( - m_options.m_module_name.c_str(), - SymbolContextSpecifier::eModuleSpecified); - } + Target &target = GetSelectedOrDummyTarget(); + Target::StopHookSP new_hook_sp = target.CreateStopHook(); - if (!m_options.m_class_name.empty()) { - specifier_up->AddSpecification( - m_options.m_class_name.c_str(), - SymbolContextSpecifier::eClassOrNamespaceSpecified); - } + // First step, make the specifier. + std::unique_ptr<SymbolContextSpecifier> specifier_up; + if (m_options.m_sym_ctx_specified) { + specifier_up.reset( + new SymbolContextSpecifier(GetDebugger().GetSelectedTarget())); - if (!m_options.m_file_name.empty()) { - specifier_up->AddSpecification( - m_options.m_file_name.c_str(), - SymbolContextSpecifier::eFileSpecified); - } + if (!m_options.m_module_name.empty()) { + specifier_up->AddSpecification( + m_options.m_module_name.c_str(), + SymbolContextSpecifier::eModuleSpecified); + } - if (m_options.m_line_start != 0) { - specifier_up->AddLineSpecification( - m_options.m_line_start, - SymbolContextSpecifier::eLineStartSpecified); - } + if (!m_options.m_class_name.empty()) { + specifier_up->AddSpecification( + m_options.m_class_name.c_str(), + SymbolContextSpecifier::eClassOrNamespaceSpecified); + } - if (m_options.m_line_end != UINT_MAX) { - specifier_up->AddLineSpecification( - m_options.m_line_end, SymbolContextSpecifier::eLineEndSpecified); - } + if (!m_options.m_file_name.empty()) { + specifier_up->AddSpecification(m_options.m_file_name.c_str(), + SymbolContextSpecifier::eFileSpecified); + } - if (!m_options.m_function_name.empty()) { - specifier_up->AddSpecification( - m_options.m_function_name.c_str(), - SymbolContextSpecifier::eFunctionSpecified); - } + if (m_options.m_line_start != 0) { + specifier_up->AddLineSpecification( + m_options.m_line_start, + SymbolContextSpecifier::eLineStartSpecified); } + if (m_options.m_line_end != UINT_MAX) { + specifier_up->AddLineSpecification( + m_options.m_line_end, SymbolContextSpecifier::eLineEndSpecified); + } + + if (!m_options.m_function_name.empty()) { + specifier_up->AddSpecification( + m_options.m_function_name.c_str(), + SymbolContextSpecifier::eFunctionSpecified); + } + } + if (specifier_up) new_hook_sp->SetSpecifier(specifier_up.release()); @@ -4825,10 +4697,6 @@ protected: // into our IOHandlerDelegate functions } result.SetStatus(eReturnStatusSuccessFinishNoResult); - } else { - result.AppendError("invalid target\n"); - result.SetStatus(eReturnStatusFailed); - } return result.Succeeded(); } @@ -4853,43 +4721,37 @@ public: protected: bool DoExecute(Args &command, CommandReturnObject &result) override { - Target *target = GetSelectedOrDummyTarget(); - if (target) { - // FIXME: see if we can use the breakpoint id style parser? - size_t num_args = command.GetArgumentCount(); - if (num_args == 0) { - if (!m_interpreter.Confirm("Delete all stop hooks?", true)) { + Target &target = GetSelectedOrDummyTarget(); + // FIXME: see if we can use the breakpoint id style parser? + size_t num_args = command.GetArgumentCount(); + if (num_args == 0) { + if (!m_interpreter.Confirm("Delete all stop hooks?", true)) { + result.SetStatus(eReturnStatusFailed); + return false; + } else { + target.RemoveAllStopHooks(); + } + } else { + bool success; + for (size_t i = 0; i < num_args; i++) { + lldb::user_id_t user_id = StringConvert::ToUInt32( + command.GetArgumentAtIndex(i), 0, 0, &success); + if (!success) { + result.AppendErrorWithFormat("invalid stop hook id: \"%s\".\n", + command.GetArgumentAtIndex(i)); result.SetStatus(eReturnStatusFailed); return false; - } else { - target->RemoveAllStopHooks(); } - } else { - bool success; - for (size_t i = 0; i < num_args; i++) { - lldb::user_id_t user_id = StringConvert::ToUInt32( - command.GetArgumentAtIndex(i), 0, 0, &success); - if (!success) { - result.AppendErrorWithFormat("invalid stop hook id: \"%s\".\n", - command.GetArgumentAtIndex(i)); - result.SetStatus(eReturnStatusFailed); - return false; - } - success = target->RemoveStopHookByID(user_id); - if (!success) { - result.AppendErrorWithFormat("unknown stop hook id: \"%s\".\n", - command.GetArgumentAtIndex(i)); - result.SetStatus(eReturnStatusFailed); - return false; - } + success = target.RemoveStopHookByID(user_id); + if (!success) { + result.AppendErrorWithFormat("unknown stop hook id: \"%s\".\n", + command.GetArgumentAtIndex(i)); + result.SetStatus(eReturnStatusFailed); + return false; } } - result.SetStatus(eReturnStatusSuccessFinishNoResult); - } else { - result.AppendError("invalid target\n"); - result.SetStatus(eReturnStatusFailed); } - + result.SetStatus(eReturnStatusSuccessFinishNoResult); return result.Succeeded(); } }; @@ -4910,38 +4772,33 @@ public: protected: bool DoExecute(Args &command, CommandReturnObject &result) override { - Target *target = GetSelectedOrDummyTarget(); - if (target) { - // FIXME: see if we can use the breakpoint id style parser? - size_t num_args = command.GetArgumentCount(); - bool success; + Target &target = GetSelectedOrDummyTarget(); + // FIXME: see if we can use the breakpoint id style parser? + size_t num_args = command.GetArgumentCount(); + bool success; - if (num_args == 0) { - target->SetAllStopHooksActiveState(m_enable); - } else { - for (size_t i = 0; i < num_args; i++) { - lldb::user_id_t user_id = StringConvert::ToUInt32( - command.GetArgumentAtIndex(i), 0, 0, &success); - if (!success) { - result.AppendErrorWithFormat("invalid stop hook id: \"%s\".\n", - command.GetArgumentAtIndex(i)); - result.SetStatus(eReturnStatusFailed); - return false; - } - success = target->SetStopHookActiveStateByID(user_id, m_enable); - if (!success) { - result.AppendErrorWithFormat("unknown stop hook id: \"%s\".\n", - command.GetArgumentAtIndex(i)); - result.SetStatus(eReturnStatusFailed); - return false; - } + if (num_args == 0) { + target.SetAllStopHooksActiveState(m_enable); + } else { + for (size_t i = 0; i < num_args; i++) { + lldb::user_id_t user_id = StringConvert::ToUInt32( + command.GetArgumentAtIndex(i), 0, 0, &success); + if (!success) { + result.AppendErrorWithFormat("invalid stop hook id: \"%s\".\n", + command.GetArgumentAtIndex(i)); + result.SetStatus(eReturnStatusFailed); + return false; + } + success = target.SetStopHookActiveStateByID(user_id, m_enable); + if (!success) { + result.AppendErrorWithFormat("unknown stop hook id: \"%s\".\n", + command.GetArgumentAtIndex(i)); + result.SetStatus(eReturnStatusFailed); + return false; } } - result.SetStatus(eReturnStatusSuccessFinishNoResult); - } else { - result.AppendError("invalid target\n"); - result.SetStatus(eReturnStatusFailed); } + result.SetStatus(eReturnStatusSuccessFinishNoResult); return result.Succeeded(); } @@ -4964,19 +4821,14 @@ public: protected: bool DoExecute(Args &command, CommandReturnObject &result) override { - Target *target = GetSelectedOrDummyTarget(); - if (!target) { - result.AppendError("invalid target\n"); - result.SetStatus(eReturnStatusFailed); - return result.Succeeded(); - } + Target &target = GetSelectedOrDummyTarget(); - size_t num_hooks = target->GetNumStopHooks(); + size_t num_hooks = target.GetNumStopHooks(); if (num_hooks == 0) { result.GetOutputStream().PutCString("No stop hooks.\n"); } else { for (size_t i = 0; i < num_hooks; i++) { - Target::StopHookSP this_hook = target->GetStopHookAtIndex(i); + Target::StopHookSP this_hook = target.GetStopHookAtIndex(i); if (i > 0) result.GetOutputStream().PutCString("\n"); this_hook->GetDescription(&(result.GetOutputStream()), diff --git a/source/Commands/CommandObjectThread.cpp b/source/Commands/CommandObjectThread.cpp index ed7cf0a1a48d..8c5274553902 100644 --- a/source/Commands/CommandObjectThread.cpp +++ b/source/Commands/CommandObjectThread.cpp @@ -16,6 +16,7 @@ #include "lldb/Interpreter/CommandInterpreter.h" #include "lldb/Interpreter/CommandReturnObject.h" #include "lldb/Interpreter/OptionArgParser.h" +#include "lldb/Interpreter/OptionGroupPythonClassWithDict.h" #include "lldb/Interpreter/Options.h" #include "lldb/Symbol/CompileUnit.h" #include "lldb/Symbol/Function.h" @@ -237,11 +238,8 @@ protected: }; // CommandObjectThreadBacktrace - -static constexpr OptionDefinition g_thread_backtrace_options[] = { #define LLDB_OPTIONS_thread_backtrace #include "CommandOptions.inc" -}; class CommandObjectThreadBacktrace : public CommandObjectIterateOverThreads { public: @@ -284,9 +282,7 @@ public: "invalid boolean value for option '%c'", short_option); } break; default: - error.SetErrorStringWithFormat("invalid short option character '%c'", - short_option); - break; + llvm_unreachable("Unimplemented option"); } return error; } @@ -403,134 +399,125 @@ static constexpr OptionEnumValues TriRunningModes() { return OptionEnumValues(g_tri_running_mode); } -static constexpr OptionDefinition g_thread_step_scope_options[] = { #define LLDB_OPTIONS_thread_step_scope #include "CommandOptions.inc" -}; -class CommandObjectThreadStepWithTypeAndScope : public CommandObjectParsed { +class ThreadStepScopeOptionGroup : public OptionGroup { public: - class CommandOptions : public Options { - public: - CommandOptions() : Options() { - // Keep default values of all options in one place: OptionParsingStarting - // () - OptionParsingStarting(nullptr); - } - - ~CommandOptions() override = default; - - Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg, - ExecutionContext *execution_context) override { - Status error; - const int short_option = m_getopt_table[option_idx].val; - - switch (short_option) { - case 'a': { - bool success; - bool avoid_no_debug = - OptionArgParser::ToBoolean(option_arg, true, &success); - if (!success) - error.SetErrorStringWithFormat( - "invalid boolean value for option '%c'", short_option); - else { - m_step_in_avoid_no_debug = - avoid_no_debug ? eLazyBoolYes : eLazyBoolNo; - } - } break; - - case 'A': { - bool success; - bool avoid_no_debug = - OptionArgParser::ToBoolean(option_arg, true, &success); - if (!success) - error.SetErrorStringWithFormat( - "invalid boolean value for option '%c'", short_option); - else { - m_step_out_avoid_no_debug = - avoid_no_debug ? eLazyBoolYes : eLazyBoolNo; - } - } break; - - case 'c': - if (option_arg.getAsInteger(0, m_step_count)) - error.SetErrorStringWithFormat("invalid step count '%s'", - option_arg.str().c_str()); - break; - - case 'C': - m_class_name.clear(); - m_class_name.assign(option_arg); - break; - - case 'm': { - auto enum_values = GetDefinitions()[option_idx].enum_values; - m_run_mode = (lldb::RunMode)OptionArgParser::ToOptionEnum( - option_arg, enum_values, eOnlyDuringStepping, error); - } break; - - case 'e': - if (option_arg == "block") { - m_end_line_is_block_end = true; - break; - } - if (option_arg.getAsInteger(0, m_end_line)) - error.SetErrorStringWithFormat("invalid end line number '%s'", - option_arg.str().c_str()); - break; + ThreadStepScopeOptionGroup() : OptionGroup() { + // Keep default values of all options in one place: OptionParsingStarting + // () + OptionParsingStarting(nullptr); + } - case 'r': - m_avoid_regexp.clear(); - m_avoid_regexp.assign(option_arg); - break; + ~ThreadStepScopeOptionGroup() override = default; - case 't': - m_step_in_target.clear(); - m_step_in_target.assign(option_arg); - break; + llvm::ArrayRef<OptionDefinition> GetDefinitions() override { + return llvm::makeArrayRef(g_thread_step_scope_options); + } - default: - error.SetErrorStringWithFormat("invalid short option character '%c'", - short_option); + Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg, + ExecutionContext *execution_context) override { + Status error; + const int short_option + = g_thread_step_scope_options[option_idx].short_option; + + switch (short_option) { + case 'a': { + bool success; + bool avoid_no_debug = + OptionArgParser::ToBoolean(option_arg, true, &success); + if (!success) + error.SetErrorStringWithFormat( + "invalid boolean value for option '%c'", short_option); + else { + m_step_in_avoid_no_debug = + avoid_no_debug ? eLazyBoolYes : eLazyBoolNo; + } + } break; + + case 'A': { + bool success; + bool avoid_no_debug = + OptionArgParser::ToBoolean(option_arg, true, &success); + if (!success) + error.SetErrorStringWithFormat( + "invalid boolean value for option '%c'", short_option); + else { + m_step_out_avoid_no_debug = + avoid_no_debug ? eLazyBoolYes : eLazyBoolNo; + } + } break; + + case 'c': + if (option_arg.getAsInteger(0, m_step_count)) + error.SetErrorStringWithFormat("invalid step count '%s'", + option_arg.str().c_str()); + break; + + case 'm': { + auto enum_values = GetDefinitions()[option_idx].enum_values; + m_run_mode = (lldb::RunMode)OptionArgParser::ToOptionEnum( + option_arg, enum_values, eOnlyDuringStepping, error); + } break; + + case 'e': + if (option_arg == "block") { + m_end_line_is_block_end = true; break; } - return error; - } - - void OptionParsingStarting(ExecutionContext *execution_context) override { - m_step_in_avoid_no_debug = eLazyBoolCalculate; - m_step_out_avoid_no_debug = eLazyBoolCalculate; - m_run_mode = eOnlyDuringStepping; - - // Check if we are in Non-Stop mode - TargetSP target_sp = - execution_context ? execution_context->GetTargetSP() : TargetSP(); - if (target_sp && target_sp->GetNonStopModeEnabled()) - m_run_mode = eOnlyThisThread; + if (option_arg.getAsInteger(0, m_end_line)) + error.SetErrorStringWithFormat("invalid end line number '%s'", + option_arg.str().c_str()); + break; + case 'r': m_avoid_regexp.clear(); + m_avoid_regexp.assign(option_arg); + break; + + case 't': m_step_in_target.clear(); - m_class_name.clear(); - m_step_count = 1; - m_end_line = LLDB_INVALID_LINE_NUMBER; - m_end_line_is_block_end = false; - } + m_step_in_target.assign(option_arg); + break; - llvm::ArrayRef<OptionDefinition> GetDefinitions() override { - return llvm::makeArrayRef(g_thread_step_scope_options); + default: + llvm_unreachable("Unimplemented option"); } + return error; + } - // Instance variables to hold the values for command options. - LazyBool m_step_in_avoid_no_debug; - LazyBool m_step_out_avoid_no_debug; - RunMode m_run_mode; - std::string m_avoid_regexp; - std::string m_step_in_target; - std::string m_class_name; - uint32_t m_step_count; - uint32_t m_end_line; - bool m_end_line_is_block_end; - }; + void OptionParsingStarting(ExecutionContext *execution_context) override { + m_step_in_avoid_no_debug = eLazyBoolCalculate; + m_step_out_avoid_no_debug = eLazyBoolCalculate; + m_run_mode = eOnlyDuringStepping; + + // Check if we are in Non-Stop mode + TargetSP target_sp = + execution_context ? execution_context->GetTargetSP() : TargetSP(); + if (target_sp && target_sp->GetNonStopModeEnabled()) + m_run_mode = eOnlyThisThread; + + m_avoid_regexp.clear(); + m_step_in_target.clear(); + m_step_count = 1; + m_end_line = LLDB_INVALID_LINE_NUMBER; + m_end_line_is_block_end = false; + } + + // Instance variables to hold the values for command options. + LazyBool m_step_in_avoid_no_debug; + LazyBool m_step_out_avoid_no_debug; + RunMode m_run_mode; + std::string m_avoid_regexp; + std::string m_step_in_target; + uint32_t m_step_count; + uint32_t m_end_line; + bool m_end_line_is_block_end; +}; + +class CommandObjectThreadStepWithTypeAndScope : public CommandObjectParsed { +public: CommandObjectThreadStepWithTypeAndScope(CommandInterpreter &interpreter, const char *name, const char *help, @@ -542,7 +529,8 @@ public: eCommandTryTargetAPILock | eCommandProcessMustBeLaunched | eCommandProcessMustBePaused), - m_step_type(step_type), m_step_scope(step_scope), m_options() { + m_step_type(step_type), m_step_scope(step_scope), m_options(), + m_class_options("scripted step", 'C') { CommandArgumentEntry arg; CommandArgumentData thread_id_arg; @@ -556,11 +544,19 @@ public: // Push the data for the first argument into the m_arguments vector. m_arguments.push_back(arg); + + if (step_type == eStepTypeScripted) { + m_all_options.Append(&m_class_options, LLDB_OPT_SET_1, LLDB_OPT_SET_1); + } + m_all_options.Append(&m_options); + m_all_options.Finalize(); } ~CommandObjectThreadStepWithTypeAndScope() override = default; - Options *GetOptions() override { return &m_options; } + Options *GetOptions() override { + return &m_all_options; + } protected: bool DoExecute(Args &command, CommandReturnObject &result) override { @@ -600,15 +596,15 @@ protected: } if (m_step_type == eStepTypeScripted) { - if (m_options.m_class_name.empty()) { + if (m_class_options.GetClassName().empty()) { result.AppendErrorWithFormat("empty class name for scripted step."); result.SetStatus(eReturnStatusFailed); return false; } else if (!GetDebugger().GetScriptInterpreter()->CheckObjectExists( - m_options.m_class_name.c_str())) { + m_class_options.GetClassName().c_str())) { result.AppendErrorWithFormat( "class for scripted step: \"%s\" does not exist.", - m_options.m_class_name.c_str()); + m_class_options.GetClassName().c_str()); result.SetStatus(eReturnStatusFailed); return false; } @@ -724,7 +720,8 @@ protected: m_options.m_step_out_avoid_no_debug); } else if (m_step_type == eStepTypeScripted) { new_plan_sp = thread->QueueThreadPlanForStepScripted( - abort_other_plans, m_options.m_class_name.c_str(), + abort_other_plans, m_class_options.GetClassName().c_str(), + m_class_options.GetStructuredData(), bool_stop_other_threads, new_plan_status); } else { result.AppendError("step type is not supported"); @@ -792,7 +789,9 @@ protected: protected: StepType m_step_type; StepScope m_step_scope; - CommandOptions m_options; + ThreadStepScopeOptionGroup m_options; + OptionGroupPythonClassWithDict m_class_options; + OptionGroupOptions m_all_options; }; // CommandObjectThreadContinue @@ -828,13 +827,6 @@ public: bool DoExecute(Args &command, CommandReturnObject &result) override { bool synchronous_execution = m_interpreter.GetSynchronous(); - if (!GetDebugger().GetSelectedTarget()) { - result.AppendError("invalid target, create a debug target using the " - "'target create' command"); - result.SetStatus(eReturnStatusFailed); - return false; - } - Process *process = m_exe_ctx.GetProcessPtr(); if (process == nullptr) { result.AppendError("no process exists. Cannot continue"); @@ -856,7 +848,7 @@ public: std::vector<Thread *> resume_threads; for (auto &entry : command.entries()) { uint32_t thread_idx; - if (entry.ref.getAsInteger(0, thread_idx)) { + if (entry.ref().getAsInteger(0, thread_idx)) { result.AppendErrorWithFormat( "invalid thread index argument: \"%s\".\n", entry.c_str()); result.SetStatus(eReturnStatusFailed); @@ -983,10 +975,8 @@ static constexpr OptionEnumValues DuoRunningModes() { return OptionEnumValues(g_duo_running_mode); } -static constexpr OptionDefinition g_thread_until_options[] = { #define LLDB_OPTIONS_thread_until #include "CommandOptions.inc" -}; class CommandObjectThreadUntil : public CommandObjectParsed { public: @@ -1044,9 +1034,7 @@ public: } } break; default: - error.SetErrorStringWithFormat("invalid short option character '%c'", - short_option); - break; + llvm_unreachable("Unimplemented option"); } return error; } @@ -1104,13 +1092,7 @@ protected: bool DoExecute(Args &command, CommandReturnObject &result) override { bool synchronous_execution = m_interpreter.GetSynchronous(); - Target *target = GetDebugger().GetSelectedTarget().get(); - if (target == nullptr) { - result.AppendError("invalid target, create a debug target using the " - "'target create' command"); - result.SetStatus(eReturnStatusFailed); - return false; - } + Target *target = &GetSelectedTarget(); Process *process = m_exe_ctx.GetProcessPtr(); if (process == nullptr) { @@ -1402,11 +1384,8 @@ protected: }; // CommandObjectThreadInfo - -static constexpr OptionDefinition g_thread_info_options[] = { #define LLDB_OPTIONS_thread_info #include "CommandOptions.inc" -}; class CommandObjectThreadInfo : public CommandObjectIterateOverThreads { public: @@ -1436,7 +1415,7 @@ public: break; default: - return Status("invalid short option character '%c'", short_option); + llvm_unreachable("Unimplemented option"); } return error; } @@ -1536,11 +1515,8 @@ class CommandObjectThreadException : public CommandObjectIterateOverThreads { }; // CommandObjectThreadReturn - -static constexpr OptionDefinition g_thread_return_options[] = { #define LLDB_OPTIONS_thread_return #include "CommandOptions.inc" -}; class CommandObjectThreadReturn : public CommandObjectRaw { public: @@ -1573,9 +1549,7 @@ public: } } break; default: - error.SetErrorStringWithFormat("invalid short option character '%c'", - short_option); - break; + llvm_unreachable("Unimplemented option"); } return error; } @@ -1711,11 +1685,8 @@ protected: }; // CommandObjectThreadJump - -static constexpr OptionDefinition g_thread_jump_options[] = { #define LLDB_OPTIONS_thread_jump #include "CommandOptions.inc" -}; class CommandObjectThreadJump : public CommandObjectParsed { public: @@ -1760,7 +1731,7 @@ public: m_force = true; break; default: - return Status("invalid short option character '%c'", short_option); + llvm_unreachable("Unimplemented option"); } return error; } @@ -1854,11 +1825,8 @@ protected: // Next are the subcommands of CommandObjectMultiwordThreadPlan // CommandObjectThreadPlanList - -static constexpr OptionDefinition g_thread_plan_list_options[] = { #define LLDB_OPTIONS_thread_plan_list #include "CommandOptions.inc" -}; class CommandObjectThreadPlanList : public CommandObjectIterateOverThreads { public: @@ -1885,9 +1853,7 @@ public: m_verbose = true; break; default: - error.SetErrorStringWithFormat("invalid short option character '%c'", - short_option); - break; + llvm_unreachable("Unimplemented option"); } return error; } @@ -2102,7 +2068,11 @@ CommandObjectMultiwordThread::CommandObjectMultiwordThread( "step-scripted", CommandObjectSP(new CommandObjectThreadStepWithTypeAndScope( interpreter, "thread step-scripted", - "Step as instructed by the script class passed in the -C option.", + "Step as instructed by the script class passed in the -C option. " + "You can also specify a dictionary of key (-k) and value (-v) pairs " + "that will be used to populate an SBStructuredData Dictionary, which " + "will be passed to the constructor of the class implementing the " + "scripted step. See the Python Reference for more details.", nullptr, eStepTypeScripted, eStepScopeSource))); LoadSubCommand("plan", CommandObjectSP(new CommandObjectMultiwordThreadPlan( diff --git a/source/Commands/CommandObjectType.cpp b/source/Commands/CommandObjectType.cpp index 98a43f50b1b1..5e31fd5e8bce 100644 --- a/source/Commands/CommandObjectType.cpp +++ b/source/Commands/CommandObjectType.cpp @@ -80,9 +80,9 @@ static bool WarnOnPotentialUnquotedUnsignedType(Args &command, return false; for (auto entry : llvm::enumerate(command.entries().drop_back())) { - if (entry.value().ref != "unsigned") + if (entry.value().ref() != "unsigned") continue; - auto next = command.entries()[entry.index() + 1].ref; + auto next = command.entries()[entry.index() + 1].ref(); if (next == "int" || next == "short" || next == "char" || next == "long") { result.AppendWarningWithFormat( "unsigned %s being treated as two types. if you meant the combined " @@ -95,10 +95,8 @@ static bool WarnOnPotentialUnquotedUnsignedType(Args &command, return false; } -static constexpr OptionDefinition g_type_summary_add_options[] = { #define LLDB_OPTIONS_type_summary_add #include "CommandOptions.inc" -}; class CommandObjectTypeSummaryAdd : public CommandObjectParsed, public IOHandlerDelegateMultiline { @@ -153,7 +151,7 @@ public: "for\n" " internal_dict: an LLDB support object not to be used\"\"\"\n"; - StreamFileSP output_sp(io_handler.GetOutputStreamFile()); + StreamFileSP output_sp(io_handler.GetOutputStreamFileSP()); if (output_sp && interactive) { output_sp->PutCString(g_summary_addreader_instructions); output_sp->Flush(); @@ -162,7 +160,7 @@ public: void IOHandlerInputComplete(IOHandler &io_handler, std::string &data) override { - StreamFileSP error_sp = io_handler.GetErrorStreamFile(); + StreamFileSP error_sp = io_handler.GetErrorStreamFileSP(); #ifndef LLDB_DISABLE_PYTHON ScriptInterpreter *interpreter = GetDebugger().GetScriptInterpreter(); @@ -197,9 +195,7 @@ public: Status error; - for (size_t i = 0; i < options->m_target_types.GetSize(); i++) { - const char *type_name = - options->m_target_types.GetStringAtIndex(i); + for (const std::string &type_name : options->m_target_types) { CommandObjectTypeSummaryAdd::AddSummary( ConstString(type_name), script_format, (options->m_regex @@ -282,10 +278,8 @@ static const char *g_synth_addreader_instructions = " '''Optional'''\n" "class synthProvider:\n"; -static constexpr OptionDefinition g_type_synth_add_options[] = { #define LLDB_OPTIONS_type_synth_add #include "CommandOptions.inc" -}; class CommandObjectTypeSynthAdd : public CommandObjectParsed, public IOHandlerDelegateMultiline { @@ -329,9 +323,7 @@ private: m_regex = true; break; default: - error.SetErrorStringWithFormat("unrecognized option '%c'", - short_option); - break; + llvm_unreachable("Unimplemented option"); } return error; @@ -391,7 +383,7 @@ protected: } void IOHandlerActivated(IOHandler &io_handler, bool interactive) override { - StreamFileSP output_sp(io_handler.GetOutputStreamFile()); + StreamFileSP output_sp(io_handler.GetOutputStreamFileSP()); if (output_sp && interactive) { output_sp->PutCString(g_synth_addreader_instructions); output_sp->Flush(); @@ -400,7 +392,7 @@ protected: void IOHandlerInputComplete(IOHandler &io_handler, std::string &data) override { - StreamFileSP error_sp = io_handler.GetErrorStreamFile(); + StreamFileSP error_sp = io_handler.GetErrorStreamFileSP(); #ifndef LLDB_DISABLE_PYTHON ScriptInterpreter *interpreter = GetDebugger().GetScriptInterpreter(); @@ -441,13 +433,10 @@ protected: Status error; - for (size_t i = 0; i < options->m_target_types.GetSize(); i++) { - const char *type_name = - options->m_target_types.GetStringAtIndex(i); - ConstString const_type_name(type_name); - if (const_type_name) { + for (const std::string &type_name : options->m_target_types) { + if (!type_name.empty()) { if (!CommandObjectTypeSynthAdd::AddSynth( - const_type_name, synth_provider, + ConstString(type_name), synth_provider, options->m_regex ? CommandObjectTypeSynthAdd::eRegexSynth : CommandObjectTypeSynthAdd::eRegularSynth, @@ -503,10 +492,8 @@ public: // CommandObjectTypeFormatAdd -static constexpr OptionDefinition g_type_format_add_options[] = { #define LLDB_OPTIONS_type_format_add #include "CommandOptions.inc" -}; class CommandObjectTypeFormatAdd : public CommandObjectParsed { private: @@ -559,9 +546,7 @@ private: m_custom_type_name.assign(option_value); break; default: - error.SetErrorStringWithFormat("unrecognized option '%c'", - short_option); - break; + llvm_unreachable("Unimplemented option"); } return error; @@ -694,25 +679,26 @@ protected: WarnOnPotentialUnquotedUnsignedType(command, result); for (auto &arg_entry : command.entries()) { - if (arg_entry.ref.empty()) { + if (arg_entry.ref().empty()) { result.AppendError("empty typenames not allowed"); result.SetStatus(eReturnStatusFailed); return false; } - ConstString typeCS(arg_entry.ref); + ConstString typeCS(arg_entry.ref()); if (m_command_options.m_regex) { - RegularExpressionSP typeRX(new RegularExpression()); - if (!typeRX->Compile(arg_entry.ref)) { + RegularExpression typeRX(arg_entry.ref()); + if (!typeRX.IsValid()) { result.AppendError( "regex format error (maybe this is not really a regex?)"); result.SetStatus(eReturnStatusFailed); return false; } category_sp->GetRegexTypeSummariesContainer()->Delete(typeCS); - category_sp->GetRegexTypeFormatsContainer()->Add(typeRX, entry); + category_sp->GetRegexTypeFormatsContainer()->Add(std::move(typeRX), + entry); } else - category_sp->GetTypeFormatsContainer()->Add(typeCS, entry); + category_sp->GetTypeFormatsContainer()->Add(std::move(typeCS), entry); } result.SetStatus(eReturnStatusSuccessFinishNoResult); @@ -720,10 +706,8 @@ protected: } }; -static constexpr OptionDefinition g_type_formatter_delete_options[] = { #define LLDB_OPTIONS_type_formatter_delete #include "CommandOptions.inc" -}; class CommandObjectTypeFormatterDelete : public CommandObjectParsed { protected: @@ -749,9 +733,7 @@ protected: m_language = Language::GetLanguageTypeFromString(option_arg); break; default: - error.SetErrorStringWithFormat("unrecognized option '%c'", - short_option); - break; + llvm_unreachable("Unimplemented option"); } return error; @@ -859,10 +841,8 @@ protected: } }; -static constexpr OptionDefinition g_type_formatter_clear_options[] = { #define LLDB_OPTIONS_type_formatter_clear #include "CommandOptions.inc" -}; class CommandObjectTypeFormatterClear : public CommandObjectParsed { private: @@ -882,9 +862,7 @@ private: m_delete_all = true; break; default: - error.SetErrorStringWithFormat("unrecognized option '%c'", - short_option); - break; + llvm_unreachable("Unimplemented option"); } return error; @@ -971,11 +949,8 @@ public: "type format clear", "Delete all existing format styles.") {} }; - -static constexpr OptionDefinition g_type_formatter_list_options[] = { #define LLDB_OPTIONS_type_formatter_list #include "CommandOptions.inc" -}; template <typename FormatterType> class CommandObjectTypeFormatterList : public CommandObjectParsed { @@ -1005,9 +980,7 @@ class CommandObjectTypeFormatterList : public CommandObjectParsed { m_category_language.SetOptionWasSet(); break; default: - error.SetErrorStringWithFormat("unrecognized option '%c'", - short_option); - break; + llvm_unreachable("Unimplemented option"); } return error; @@ -1061,9 +1034,9 @@ protected: std::unique_ptr<RegularExpression> formatter_regex; if (m_options.m_category_regex.OptionWasSet()) { - category_regex.reset(new RegularExpression()); - if (!category_regex->Compile( - m_options.m_category_regex.GetCurrentValueAsRef())) { + category_regex.reset(new RegularExpression( + m_options.m_category_regex.GetCurrentValueAsRef())); + if (!category_regex->IsValid()) { result.AppendErrorWithFormat( "syntax error in category regular expression '%s'", m_options.m_category_regex.GetCurrentValueAsRef().str().c_str()); @@ -1074,8 +1047,9 @@ protected: if (argc == 1) { const char *arg = command.GetArgumentAtIndex(0); - formatter_regex.reset(new RegularExpression()); - if (!formatter_regex->Compile(llvm::StringRef::withNullAsEmpty(arg))) { + formatter_regex.reset( + new RegularExpression(llvm::StringRef::withNullAsEmpty(arg))); + if (!formatter_regex->IsValid()) { result.AppendErrorWithFormat("syntax error in regular expression '%s'", arg); result.SetStatus(eReturnStatusFailed); @@ -1116,13 +1090,13 @@ protected: foreach .SetWithRegex([&result, &formatter_regex, &any_printed]( - RegularExpressionSP regex_sp, + const RegularExpression ®ex, const FormatterSharedPointer &format_sp) -> bool { if (formatter_regex) { bool escape = true; - if (regex_sp->GetText() == formatter_regex->GetText()) { + if (regex.GetText() == formatter_regex->GetText()) { escape = false; - } else if (formatter_regex->Execute(regex_sp->GetText())) { + } else if (formatter_regex->Execute(regex.GetText())) { escape = false; } @@ -1132,7 +1106,7 @@ protected: any_printed = true; result.GetOutputStream().Printf("%s: %s\n", - regex_sp->GetText().str().c_str(), + regex.GetText().str().c_str(), format_sp->GetDescription().c_str()); return true; }); @@ -1257,8 +1231,7 @@ Status CommandObjectTypeSummaryAdd::CommandOptions::SetOptionValue( m_flags.SetHideItemNames(true); break; default: - error.SetErrorStringWithFormat("unrecognized option '%c'", short_option); - break; + llvm_unreachable("Unimplemented option"); } return error; @@ -1355,13 +1328,13 @@ bool CommandObjectTypeSummaryAdd::Execute_ScriptSummary( m_options.m_name, m_options.m_category); for (auto &entry : command.entries()) { - if (entry.ref.empty()) { + if (entry.ref().empty()) { result.AppendError("empty typenames not allowed"); result.SetStatus(eReturnStatusFailed); return false; } - options->m_target_types << entry.ref; + options->m_target_types << entry.ref(); } m_interpreter.GetPythonCommandsFromIOHandler( @@ -1382,7 +1355,7 @@ bool CommandObjectTypeSummaryAdd::Execute_ScriptSummary( for (auto &entry : command.entries()) { CommandObjectTypeSummaryAdd::AddSummary( - ConstString(entry.ref), script_format, + ConstString(entry.ref()), script_format, (m_options.m_regex ? eRegexSummary : eRegularSummary), m_options.m_category, &error); if (error.Fail()) { @@ -1455,12 +1428,12 @@ bool CommandObjectTypeSummaryAdd::Execute_StringSummary( // now I have a valid format, let's add it to every type Status error; for (auto &arg_entry : command.entries()) { - if (arg_entry.ref.empty()) { + if (arg_entry.ref().empty()) { result.AppendError("empty typenames not allowed"); result.SetStatus(eReturnStatusFailed); return false; } - ConstString typeCS(arg_entry.ref); + ConstString typeCS(arg_entry.ref()); AddSummary(typeCS, entry, (m_options.m_regex ? eRegexSummary : eRegularSummary), @@ -1647,8 +1620,8 @@ bool CommandObjectTypeSummaryAdd::AddSummary(ConstString type_name, } if (type == eRegexSummary) { - RegularExpressionSP typeRX(new RegularExpression()); - if (!typeRX->Compile(type_name.GetStringRef())) { + RegularExpression typeRX(type_name.GetStringRef()); + if (!typeRX.IsValid()) { if (error) error->SetErrorString( "regex format error (maybe this is not really a regex?)"); @@ -1656,7 +1629,7 @@ bool CommandObjectTypeSummaryAdd::AddSummary(ConstString type_name, } category->GetRegexTypeSummariesContainer()->Delete(type_name); - category->GetRegexTypeSummariesContainer()->Add(typeRX, entry); + category->GetRegexTypeSummariesContainer()->Add(std::move(typeRX), entry); return true; } else if (type == eNamedSummary) { @@ -1664,7 +1637,7 @@ bool CommandObjectTypeSummaryAdd::AddSummary(ConstString type_name, DataVisualization::NamedSummaryFormats::Add(type_name, entry); return true; } else { - category->GetTypeSummariesContainer()->Add(type_name, entry); + category->GetTypeSummariesContainer()->Add(std::move(type_name), entry); return true; } } @@ -1731,11 +1704,8 @@ protected: }; // CommandObjectTypeCategoryDefine - -static constexpr OptionDefinition g_type_category_define_options[] = { #define LLDB_OPTIONS_type_category_define #include "CommandOptions.inc" -}; class CommandObjectTypeCategoryDefine : public CommandObjectParsed { class CommandOptions : public Options { @@ -1759,9 +1729,7 @@ class CommandObjectTypeCategoryDefine : public CommandObjectParsed { error = m_cate_language.SetValueFromString(option_arg); break; default: - error.SetErrorStringWithFormat("unrecognized option '%c'", - short_option); - break; + llvm_unreachable("Unimplemented option"); } return error; @@ -1818,7 +1786,7 @@ protected: for (auto &entry : command.entries()) { TypeCategoryImplSP category_sp; - if (DataVisualization::Categories::GetCategory(ConstString(entry.ref), + if (DataVisualization::Categories::GetCategory(ConstString(entry.ref()), category_sp) && category_sp) { category_sp->AddLanguage(m_options.m_cate_language.GetCurrentValue()); @@ -1834,11 +1802,8 @@ protected: }; // CommandObjectTypeCategoryEnable - -static constexpr OptionDefinition g_type_category_enable_options[] = { #define LLDB_OPTIONS_type_category_enable #include "CommandOptions.inc" -}; class CommandObjectTypeCategoryEnable : public CommandObjectParsed { class CommandOptions : public Options { @@ -1862,9 +1827,7 @@ class CommandObjectTypeCategoryEnable : public CommandObjectParsed { } break; default: - error.SetErrorStringWithFormat("unrecognized option '%c'", - short_option); - break; + llvm_unreachable("Unimplemented option"); } return error; @@ -2006,11 +1969,8 @@ protected: }; // CommandObjectTypeCategoryDisable - -OptionDefinition constexpr g_type_category_disable_options[] = { #define LLDB_OPTIONS_type_category_disable #include "CommandOptions.inc" -}; class CommandObjectTypeCategoryDisable : public CommandObjectParsed { class CommandOptions : public Options { @@ -2034,9 +1994,7 @@ class CommandObjectTypeCategoryDisable : public CommandObjectParsed { } break; default: - error.SetErrorStringWithFormat("unrecognized option '%c'", - short_option); - break; + llvm_unreachable("Unimplemented option"); } return error; @@ -2142,9 +2100,9 @@ protected: std::unique_ptr<RegularExpression> regex; if (argc == 1) { - regex.reset(new RegularExpression()); const char *arg = command.GetArgumentAtIndex(0); - if (!regex->Compile(llvm::StringRef::withNullAsEmpty(arg))) { + regex.reset(new RegularExpression(llvm::StringRef::withNullAsEmpty(arg))); + if (!regex->IsValid()) { result.AppendErrorWithFormat( "syntax error in category regular expression '%s'", arg); result.SetStatus(eReturnStatusFailed); @@ -2270,13 +2228,13 @@ bool CommandObjectTypeSynthAdd::Execute_HandwritePython( m_options.m_cascade, m_options.m_regex, m_options.m_category); for (auto &entry : command.entries()) { - if (entry.ref.empty()) { + if (entry.ref().empty()) { result.AppendError("empty typenames not allowed"); result.SetStatus(eReturnStatusFailed); return false; } - options->m_target_types << entry.ref; + options->m_target_types << entry.ref(); } m_interpreter.GetPythonCommandsFromIOHandler( @@ -2335,13 +2293,13 @@ bool CommandObjectTypeSynthAdd::Execute_PythonClass( Status error; for (auto &arg_entry : command.entries()) { - if (arg_entry.ref.empty()) { + if (arg_entry.ref().empty()) { result.AppendError("empty typenames not allowed"); result.SetStatus(eReturnStatusFailed); return false; } - ConstString typeCS(arg_entry.ref); + ConstString typeCS(arg_entry.ref()); if (!AddSynth(typeCS, entry, m_options.m_regex ? eRegexSynth : eRegularSynth, m_options.m_category, &error)) { @@ -2396,8 +2354,8 @@ bool CommandObjectTypeSynthAdd::AddSynth(ConstString type_name, } if (type == eRegexSynth) { - RegularExpressionSP typeRX(new RegularExpression()); - if (!typeRX->Compile(type_name.GetStringRef())) { + RegularExpression typeRX(type_name.GetStringRef()); + if (!typeRX.IsValid()) { if (error) error->SetErrorString( "regex format error (maybe this is not really a regex?)"); @@ -2405,21 +2363,18 @@ bool CommandObjectTypeSynthAdd::AddSynth(ConstString type_name, } category->GetRegexTypeSyntheticsContainer()->Delete(type_name); - category->GetRegexTypeSyntheticsContainer()->Add(typeRX, entry); + category->GetRegexTypeSyntheticsContainer()->Add(std::move(typeRX), entry); return true; } else { - category->GetTypeSyntheticsContainer()->Add(type_name, entry); + category->GetTypeSyntheticsContainer()->Add(std::move(type_name), entry); return true; } } #endif // LLDB_DISABLE_PYTHON - -static constexpr OptionDefinition g_type_filter_add_options[] = { #define LLDB_OPTIONS_type_filter_add #include "CommandOptions.inc" -}; class CommandObjectTypeFilterAdd : public CommandObjectParsed { private: @@ -2461,9 +2416,7 @@ private: m_regex = true; break; default: - error.SetErrorStringWithFormat("unrecognized option '%c'", - short_option); - break; + llvm_unreachable("Unimplemented option"); } return error; @@ -2527,8 +2480,8 @@ private: } if (type == eRegexFilter) { - RegularExpressionSP typeRX(new RegularExpression()); - if (!typeRX->Compile(type_name.GetStringRef())) { + RegularExpression typeRX(type_name.GetStringRef()); + if (!typeRX.IsValid()) { if (error) error->SetErrorString( "regex format error (maybe this is not really a regex?)"); @@ -2536,11 +2489,11 @@ private: } category->GetRegexTypeFiltersContainer()->Delete(type_name); - category->GetRegexTypeFiltersContainer()->Add(typeRX, entry); + category->GetRegexTypeFiltersContainer()->Add(std::move(typeRX), entry); return true; } else { - category->GetTypeFiltersContainer()->Add(type_name, entry); + category->GetTypeFiltersContainer()->Add(std::move(type_name), entry); return true; } } @@ -2641,13 +2594,13 @@ protected: WarnOnPotentialUnquotedUnsignedType(command, result); for (auto &arg_entry : command.entries()) { - if (arg_entry.ref.empty()) { + if (arg_entry.ref().empty()) { result.AppendError("empty typenames not allowed"); result.SetStatus(eReturnStatusFailed); return false; } - ConstString typeCS(arg_entry.ref); + ConstString typeCS(arg_entry.ref()); if (!AddFilter(typeCS, entry, m_options.m_regex ? eRegexFilter : eRegularFilter, m_options.m_category, &error)) { @@ -2663,10 +2616,8 @@ protected: }; // "type lookup" -static constexpr OptionDefinition g_type_lookup_options[] = { #define LLDB_OPTIONS_type_lookup #include "CommandOptions.inc" -}; class CommandObjectTypeLookup : public CommandObjectRaw { protected: @@ -2717,9 +2668,7 @@ protected: break; default: - error.SetErrorStringWithFormat("invalid short option character '%c'", - short_option); - break; + llvm_unreachable("Unimplemented option"); } return error; diff --git a/source/Commands/CommandObjectWatchpoint.cpp b/source/Commands/CommandObjectWatchpoint.cpp index 98e758b7ef6a..44dfb29b19b5 100644 --- a/source/Commands/CommandObjectWatchpoint.cpp +++ b/source/Commands/CommandObjectWatchpoint.cpp @@ -40,11 +40,6 @@ static void AddWatchpointDescription(Stream *s, Watchpoint *wp, static bool CheckTargetForWatchpointOperations(Target *target, CommandReturnObject &result) { - if (target == nullptr) { - result.AppendError("Invalid target. No existing target or watchpoints."); - result.SetStatus(eReturnStatusFailed); - return false; - } bool process_is_valid = target->GetProcessSP() && target->GetProcessSP()->IsAlive(); if (!process_is_valid) { @@ -94,12 +89,12 @@ bool CommandObjectMultiwordWatchpoint::VerifyWatchpointIDs( // Go through the arguments and make a canonical form of arg list containing // only numbers with possible "-" in between. for (auto &entry : args.entries()) { - if ((idx = WithRSAIndex(entry.ref)) == -1) { - StrRefArgs.push_back(entry.ref); + if ((idx = WithRSAIndex(entry.ref())) == -1) { + StrRefArgs.push_back(entry.ref()); continue; } // The Arg contains the range specifier, split it, then. - std::tie(first, second) = entry.ref.split(RSA[idx]); + std::tie(first, second) = entry.ref().split(RSA[idx]); if (!first.empty()) StrRefArgs.push_back(first); StrRefArgs.push_back(Minus); @@ -146,11 +141,8 @@ bool CommandObjectMultiwordWatchpoint::VerifyWatchpointIDs( // CommandObjectWatchpointList::Options #pragma mark List::CommandOptions - -static constexpr OptionDefinition g_watchpoint_list_options[] = { #define LLDB_OPTIONS_watchpoint_list #include "CommandOptions.inc" -}; #pragma mark List @@ -159,7 +151,8 @@ public: CommandObjectWatchpointList(CommandInterpreter &interpreter) : CommandObjectParsed( interpreter, "watchpoint list", - "List all watchpoints at configurable levels of detail.", nullptr), + "List all watchpoints at configurable levels of detail.", nullptr, + eCommandRequiresTarget), m_options() { CommandArgumentEntry arg; CommandObject::AddIDsArgumentData(arg, eArgTypeWatchpointID, @@ -199,9 +192,7 @@ public: m_level = lldb::eDescriptionLevelVerbose; break; default: - error.SetErrorStringWithFormat("unrecognized option '%c'", - short_option); - break; + llvm_unreachable("Unimplemented option"); } return error; @@ -222,12 +213,7 @@ public: protected: bool DoExecute(Args &command, CommandReturnObject &result) override { - Target *target = GetDebugger().GetSelectedTarget().get(); - if (target == nullptr) { - result.AppendError("Invalid target. No current target or watchpoints."); - result.SetStatus(eReturnStatusSuccessFinishNoResult); - return true; - } + Target *target = &GetSelectedTarget(); if (target->GetProcessSP() && target->GetProcessSP()->IsAlive()) { uint32_t num_supported_hardware_watchpoints; @@ -297,7 +283,7 @@ public: : CommandObjectParsed(interpreter, "enable", "Enable the specified disabled watchpoint(s). If " "no watchpoints are specified, enable all of them.", - nullptr) { + nullptr, eCommandRequiresTarget) { CommandArgumentEntry arg; CommandObject::AddIDsArgumentData(arg, eArgTypeWatchpointID, eArgTypeWatchpointIDRange); @@ -310,7 +296,7 @@ public: protected: bool DoExecute(Args &command, CommandReturnObject &result) override { - Target *target = GetDebugger().GetSelectedTarget().get(); + Target *target = &GetSelectedTarget(); if (!CheckTargetForWatchpointOperations(target, result)) return false; @@ -367,7 +353,7 @@ public: "Disable the specified watchpoint(s) without " "removing it/them. If no watchpoints are " "specified, disable them all.", - nullptr) { + nullptr, eCommandRequiresTarget) { CommandArgumentEntry arg; CommandObject::AddIDsArgumentData(arg, eArgTypeWatchpointID, eArgTypeWatchpointIDRange); @@ -380,7 +366,7 @@ public: protected: bool DoExecute(Args &command, CommandReturnObject &result) override { - Target *target = GetDebugger().GetSelectedTarget().get(); + Target *target = &GetSelectedTarget(); if (!CheckTargetForWatchpointOperations(target, result)) return false; @@ -439,7 +425,7 @@ public: : CommandObjectParsed(interpreter, "watchpoint delete", "Delete the specified watchpoint(s). If no " "watchpoints are specified, delete them all.", - nullptr) { + nullptr, eCommandRequiresTarget) { CommandArgumentEntry arg; CommandObject::AddIDsArgumentData(arg, eArgTypeWatchpointID, eArgTypeWatchpointIDRange); @@ -452,7 +438,7 @@ public: protected: bool DoExecute(Args &command, CommandReturnObject &result) override { - Target *target = GetDebugger().GetSelectedTarget().get(); + Target *target = &GetSelectedTarget(); if (!CheckTargetForWatchpointOperations(target, result)) return false; @@ -507,10 +493,8 @@ protected: // CommandObjectWatchpointIgnore #pragma mark Ignore::CommandOptions -static constexpr OptionDefinition g_watchpoint_ignore_options[] = { #define LLDB_OPTIONS_watchpoint_ignore #include "CommandOptions.inc" -}; class CommandObjectWatchpointIgnore : public CommandObjectParsed { public: @@ -518,7 +502,7 @@ public: : CommandObjectParsed(interpreter, "watchpoint ignore", "Set ignore count on the specified watchpoint(s). " "If no watchpoints are specified, set them all.", - nullptr), + nullptr, eCommandRequiresTarget), m_options() { CommandArgumentEntry arg; CommandObject::AddIDsArgumentData(arg, eArgTypeWatchpointID, @@ -550,9 +534,7 @@ public: option_arg.str().c_str()); break; default: - error.SetErrorStringWithFormat("unrecognized option '%c'", - short_option); - break; + llvm_unreachable("Unimplemented option"); } return error; @@ -573,7 +555,7 @@ public: protected: bool DoExecute(Args &command, CommandReturnObject &result) override { - Target *target = GetDebugger().GetSelectedTarget().get(); + Target *target = &GetSelectedTarget(); if (!CheckTargetForWatchpointOperations(target, result)) return false; @@ -625,11 +607,8 @@ private: // CommandObjectWatchpointModify #pragma mark Modify::CommandOptions - -static constexpr OptionDefinition g_watchpoint_modify_options[] = { #define LLDB_OPTIONS_watchpoint_modify #include "CommandOptions.inc" -}; #pragma mark Modify @@ -643,7 +622,7 @@ public: "If no watchpoint is specified, act on the last created " "watchpoint. " "Passing an empty argument clears the modification.", - nullptr), + nullptr, eCommandRequiresTarget), m_options() { CommandArgumentEntry arg; CommandObject::AddIDsArgumentData(arg, eArgTypeWatchpointID, @@ -674,9 +653,7 @@ public: m_condition_passed = true; break; default: - error.SetErrorStringWithFormat("unrecognized option '%c'", - short_option); - break; + llvm_unreachable("Unimplemented option"); } return error; @@ -699,7 +676,7 @@ public: protected: bool DoExecute(Args &command, CommandReturnObject &result) override { - Target *target = GetDebugger().GetSelectedTarget().get(); + Target *target = &GetSelectedTarget(); if (!CheckTargetForWatchpointOperations(target, result)) return false; @@ -808,12 +785,12 @@ corresponding to the byte size of the data type."); protected: static size_t GetVariableCallback(void *baton, const char *name, VariableList &variable_list) { + size_t old_size = variable_list.GetSize(); Target *target = static_cast<Target *>(baton); - if (target) { - return target->GetImages().FindGlobalVariables(ConstString(name), - UINT32_MAX, variable_list); - } - return 0; + if (target) + target->GetImages().FindGlobalVariables(ConstString(name), UINT32_MAX, + variable_list); + return variable_list.GetSize() - old_size; } bool DoExecute(Args &command, CommandReturnObject &result) override { diff --git a/source/Commands/CommandObjectWatchpointCommand.cpp b/source/Commands/CommandObjectWatchpointCommand.cpp index 2be0b5b154e0..5683381efc85 100644 --- a/source/Commands/CommandObjectWatchpointCommand.cpp +++ b/source/Commands/CommandObjectWatchpointCommand.cpp @@ -24,28 +24,33 @@ using namespace lldb; using namespace lldb_private; -// CommandObjectWatchpointCommandAdd - // FIXME: "script-type" needs to have its contents determined dynamically, so -// somebody can add a new scripting -// language to lldb and have it pickable here without having to change this -// enumeration by hand and rebuild lldb proper. - +// somebody can add a new scripting language to lldb and have it pickable here +// without having to change this enumeration by hand and rebuild lldb proper. static constexpr OptionEnumValueElement g_script_option_enumeration[] = { - {eScriptLanguageNone, "command", - "Commands are in the lldb command interpreter language"}, - {eScriptLanguagePython, "python", "Commands are in the Python language."}, - {eSortOrderByName, "default-script", - "Commands are in the default scripting language."} }; + { + eScriptLanguageNone, + "command", + "Commands are in the lldb command interpreter language", + }, + { + eScriptLanguagePython, + "python", + "Commands are in the Python language.", + }, + { + eSortOrderByName, + "default-script", + "Commands are in the default scripting language.", + }, +}; static constexpr OptionEnumValues ScriptOptionEnum() { return OptionEnumValues(g_script_option_enumeration); } -static constexpr OptionDefinition g_watchpoint_command_add_options[] = { #define LLDB_OPTIONS_watchpoint_command_add #include "CommandOptions.inc" -}; class CommandObjectWatchpointCommandAdd : public CommandObjectParsed, public IOHandlerDelegateMultiline { @@ -54,7 +59,7 @@ public: : CommandObjectParsed(interpreter, "add", "Add a set of LLDB commands to a watchpoint, to be " "executed whenever the watchpoint is hit.", - nullptr), + nullptr, eCommandRequiresTarget), IOHandlerDelegateMultiline("DONE", IOHandlerDelegate::Completion::LLDBCommand), m_options() { @@ -202,7 +207,7 @@ are no syntax errors may indicate that a function was declared but never called. Options *GetOptions() override { return &m_options; } void IOHandlerActivated(IOHandler &io_handler, bool interactive) override { - StreamFileSP output_sp(io_handler.GetOutputStreamFile()); + StreamFileSP output_sp(io_handler.GetOutputStreamFileSP()); if (output_sp && interactive) { output_sp->PutCString( "Enter your debugger command(s). Type 'DONE' to end.\n"); @@ -349,7 +354,7 @@ are no syntax errors may indicate that a function was declared but never called. break; default: - break; + llvm_unreachable("Unimplemented option"); } return error; } @@ -384,14 +389,7 @@ are no syntax errors may indicate that a function was declared but never called. protected: bool DoExecute(Args &command, CommandReturnObject &result) override { - Target *target = GetDebugger().GetSelectedTarget().get(); - - if (target == nullptr) { - result.AppendError("There is not a current executable; there are no " - "watchpoints to which to add commands"); - result.SetStatus(eReturnStatusFailed); - return false; - } + Target *target = &GetSelectedTarget(); const WatchpointList &watchpoints = target->GetWatchpointList(); size_t num_watchpoints = watchpoints.GetSize(); @@ -481,7 +479,7 @@ public: CommandObjectWatchpointCommandDelete(CommandInterpreter &interpreter) : CommandObjectParsed(interpreter, "delete", "Delete the set of commands from a watchpoint.", - nullptr) { + nullptr, eCommandRequiresTarget) { CommandArgumentEntry arg; CommandArgumentData wp_id_arg; @@ -501,14 +499,7 @@ public: protected: bool DoExecute(Args &command, CommandReturnObject &result) override { - Target *target = GetDebugger().GetSelectedTarget().get(); - - if (target == nullptr) { - result.AppendError("There is not a current executable; there are no " - "watchpoints from which to delete commands"); - result.SetStatus(eReturnStatusFailed); - return false; - } + Target *target = &GetSelectedTarget(); const WatchpointList &watchpoints = target->GetWatchpointList(); size_t num_watchpoints = watchpoints.GetSize(); @@ -557,10 +548,10 @@ protected: class CommandObjectWatchpointCommandList : public CommandObjectParsed { public: CommandObjectWatchpointCommandList(CommandInterpreter &interpreter) - : CommandObjectParsed(interpreter, "list", "List the script or set of " - "commands to be executed when " - "the watchpoint is hit.", - nullptr) { + : CommandObjectParsed(interpreter, "list", + "List the script or set of commands to be executed " + "when the watchpoint is hit.", + nullptr, eCommandRequiresTarget) { CommandArgumentEntry arg; CommandArgumentData wp_id_arg; @@ -580,14 +571,7 @@ public: protected: bool DoExecute(Args &command, CommandReturnObject &result) override { - Target *target = GetDebugger().GetSelectedTarget().get(); - - if (target == nullptr) { - result.AppendError("There is not a current executable; there are no " - "watchpoints for which to list commands"); - result.SetStatus(eReturnStatusFailed); - return false; - } + Target *target = &GetSelectedTarget(); const WatchpointList &watchpoints = target->GetWatchpointList(); size_t num_watchpoints = watchpoints.GetSize(); diff --git a/source/Commands/Options.td b/source/Commands/Options.td index 9cfbcd2d4ebf..87f5506c305f 100644 --- a/source/Commands/Options.td +++ b/source/Commands/Options.td @@ -38,6 +38,8 @@ let Command = "settings read" in { } let Command = "breakpoint list" in { + // FIXME: We need to add an "internal" command, and then add this sort of + // thing to it. But I need to see it for now, and don't want to wait. def blist_internal : Option<"internal", "i">, Desc<"Show debugger internal breakpoints">; def blist_brief : Option<"brief", "b">, Group<1>, @@ -52,6 +54,823 @@ let Command = "breakpoint list" in { "provided, which prime new targets.">; } +let Command = "breakpoint modify" in { + def breakpoint_modify_ignore_count : Option<"ignore-count", "i">, Group<1>, + Arg<"Count">, + Desc<"Set the number of times this breakpoint is skipped before stopping.">; + def breakpoint_modify_one_shot : Option<"one-shot", "o">, Group<1>, + Arg<"Boolean">, + Desc<"The breakpoint is deleted the first time it stop causes a stop.">; + def breakpoint_modify_thread_index : Option<"thread-index", "x">, Group<1>, + Arg<"ThreadIndex">, Desc<"The breakpoint stops only for the thread whose " + "index matches this argument.">; + def breakpoint_modify_thread_id : Option<"thread-id", "t">, Group<1>, + Arg<"ThreadID">, Desc<"The breakpoint stops only for the thread whose TID " + "matches this argument.">; + def breakpoint_modify_thread_name : Option<"thread-name", "T">, Group<1>, + Arg<"ThreadName">, Desc<"The breakpoint stops only for the thread whose " + "thread name matches this argument.">; + def breakpoint_modify_queue_name : Option<"queue-name", "q">, Group<1>, + Arg<"QueueName">, Desc<"The breakpoint stops only for threads in the queue " + "whose name is given by this argument.">; + def breakpoint_modify_condition : Option<"condition", "c">, Group<1>, + Arg<"Expression">, Desc<"The breakpoint stops only if this condition " + "expression evaluates to true.">; + def breakpoint_modify_auto_continue : Option<"auto-continue", "G">, Group<1>, + Arg<"Boolean">, + Desc<"The breakpoint will auto-continue after running its commands.">; + def breakpoint_modify_enable : Option<"enable", "e">, Group<2>, + Desc<"Enable the breakpoint.">; + def breakpoint_modify_disable : Option<"disable", "d">, Group<3>, + Desc<"Disable the breakpoint.">; + def breakpoint_modify_command : Option<"command", "C">, Group<4>, + Arg<"Command">, + Desc<"A command to run when the breakpoint is hit, can be provided more " + "than once, the commands will get run in order left to right.">; +} + +let Command = "breakpoint dummy" in { + def breakpoint_dummy_options_dummy_breakpoints : + Option<"dummy-breakpoints", "D">, Group<1>, + Desc<"Act on Dummy breakpoints - i.e. breakpoints set before a file is " + "provided, which prime new targets.">; +} + +let Command = "breakpoint set" in { + def breakpoint_set_shlib : Option<"shlib", "s">, Arg<"ShlibName">, + Completion<"Module">, Groups<[1,2,3,4,5,6,7,8,9,11]>, // *not* in group 10 + Desc<"Set the breakpoint only in this shared library. Can repeat this " + "option multiple times to specify multiple shared libraries.">; + def breakpoint_set_hardware : Option<"hardware", "H">, + Desc<"Require the breakpoint to use hardware breakpoints.">; + def breakpoint_set_file : Option<"file", "f">, Arg<"Filename">, + Completion<"SourceFile">, Groups<[1,3,4,5,6,7,8,9,11]>, + Desc<"Specifies the source file in which to set this breakpoint. Note, by " + "default lldb only looks for files that are #included if they use the " + "standard include file extensions. To set breakpoints on .c/.cpp/.m/.mm " + "files that are #included, set target.inline-breakpoint-strategy to " + "\"always\".">; + def breakpoint_set_line : Option<"line", "l">, Group<1>, Arg<"LineNum">, + Required, + Desc<"Specifies the line number on which to set this breakpoint.">; + def breakpoint_set_address : Option<"address", "a">, Group<2>, + Arg<"AddressOrExpression">, Required, + Desc<"Set the breakpoint at the specified address. If the address maps " + "uniquely toa particular binary, then the address will be converted to " + "a \"file\"address, so that the breakpoint will track that binary+offset " + "no matter where the binary eventually loads. Alternately, if you also " + "specify the module - with the -s option - then the address will be " + "treated as a file address in that module, and resolved accordingly. " + "Again, this will allow lldb to track that offset on subsequent reloads. " + " The module need not have been loaded at the time you specify this " + "breakpoint, and will get resolved when the module is loaded.">; + def breakpoint_set_name : Option<"name", "n">, Group<3>, Arg<"FunctionName">, + Completion<"Symbol">, Required, + Desc<"Set the breakpoint by function name. Can be repeated multiple times " + "to makeone breakpoint for multiple names">; + def breakpoint_set_source_regexp_function : + Option<"source-regexp-function", "X">, Group<9>, Arg<"FunctionName">, + Completion<"Symbol">, + Desc<"When used with '-p' limits the source regex to source contained in " + "the namedfunctions. Can be repeated multiple times.">; + def breakpoint_set_fullname : Option<"fullname", "F">, Group<4>, + Arg<"FullName">, Required, Completion<"Symbol">, + Desc<"Set the breakpoint by fully qualified function names. For C++ this " + "means namespaces and all arguments, and for Objective-C this means a full " + "functionprototype with class and selector. Can be repeated multiple times" + " to make one breakpoint for multiple names.">; + def breakpoint_set_selector : Option<"selector", "S">, Group<5>, + Arg<"Selector">, Required, + Desc<"Set the breakpoint by ObjC selector name. Can be repeated multiple " + "times tomake one breakpoint for multiple Selectors.">; + def breakpoint_set_method : Option<"method", "M">, Group<6>, Arg<"Method">, + Required, Desc<"Set the breakpoint by C++ method names. Can be repeated " + "multiple times tomake one breakpoint for multiple methods.">; + def breakpoint_set_func_regex : Option<"func-regex", "r">, Group<7>, + Arg<"RegularExpression">, Required, Desc<"Set the breakpoint by function " + "name, evaluating a regular-expression to findthe function name(s).">; + def breakpoint_set_basename : Option<"basename", "b">, Group<8>, + Arg<"FunctionName">, Required, Completion<"Symbol">, + Desc<"Set the breakpoint by function basename (C++ namespaces and arguments" + " will beignored). Can be repeated multiple times to make one breakpoint " + "for multiplesymbols.">; + def breakpoint_set_source_pattern_regexp : + Option<"source-pattern-regexp", "p">, Group<9>, Arg<"RegularExpression">, + Required, Desc<"Set the breakpoint by specifying a regular expression which" + " is matched against the source text in a source file or files specified " + "with the -f can be specified more than once. If no source files " + "are specified, uses the current \"default source file\". If you want to " + "match against all source files, pass the \"--all-files\" option.">; + def breakpoint_set_all_files : Option<"all-files", "A">, Group<9>, + Desc<"All files are searched for source pattern matches.">; + def breakpoint_set_language_exception : Option<"language-exception", "E">, + Group<10>, Arg<"Language">, Required, + Desc<"Set the breakpoint on exceptions thrown by the specified language " + "(without options, on throw but not catch.)">; + def breakpoint_set_on_throw : Option<"on-throw", "w">, Group<10>, + Arg<"Boolean">, Desc<"Set the breakpoint on exception throW.">; + def breakpoint_set_on_catch : Option<"on-catch", "h">, Group<10>, + Arg<"Boolean">, Desc<"Set the breakpoint on exception catcH.">; + def breakpoint_set_language : Option<"language", "L">, GroupRange<3, 8>, + Arg<"Language">, + Desc<"Specifies the Language to use when interpreting the breakpoint's " + "expression (note: currently only implemented for setting breakpoints on " + "identifiers). If not set the target.language setting is used.">; + def breakpoint_set_skip_prologue : Option<"skip-prologue", "K">, + Arg<"Boolean">, Groups<[1,3,4,5,6,7,8]>, + Desc<"sKip the prologue if the breakpoint is at the beginning of a " + "function. If not set the target.skip-prologue setting is used.">; + def breakpoint_set_breakpoint_name : Option<"breakpoint-name", "N">, + Arg<"BreakpointName">, + Desc<"Adds this to the list of names for this breakpoint.">; + def breakpoint_set_address_slide : Option<"address-slide", "R">, + Arg<"Address">, Groups<[1,3,4,5,6,7,8]>, + Desc<"Add the specified offset to whatever address(es) the breakpoint " + "resolves to. At present this applies the offset directly as given, and " + "doesn't try to align it to instruction boundaries.">; + def breakpoint_set_move_to_nearest_code : Option<"move-to-nearest-code", "m">, + Groups<[1, 9]>, Arg<"Boolean">, + Desc<"Move breakpoints to nearest code. If not set the " + "target.move-to-nearest-codesetting is used.">; + /* Don't add this option till it actually does something useful... + def breakpoint_set_exception_typename : Option<"exception-typename", "O">, + Arg<"TypeName">, Desc<"The breakpoint will only stop if an " + "exception Object of this type is thrown. Can be repeated multiple times " + "to stop for multiple object types">; + */ +} + +let Command = "breakpoint clear" in { + def breakpoint_clear_file : Option<"file", "f">, Group<1>, Arg<"Filename">, + Completion<"SourceFile">, + Desc<"Specify the breakpoint by source location in this particular file.">; + def breakpoint_clear_line : Option<"line", "l">, Group<1>, Arg<"LineNum">, + Required, + Desc<"Specify the breakpoint by source location at this particular line.">; +} + +let Command = "breakpoint delete" in { + def breakpoint_delete_force : Option<"force", "f">, Group<1>, + Desc<"Delete all breakpoints without querying for confirmation.">; + def breakpoint_delete_dummy_breakpoints : Option<"dummy-breakpoints", "D">, + Group<1>, Desc<"Delete Dummy breakpoints - i.e. breakpoints set before a " + "file is provided, which prime new targets.">; +} + +let Command = "breakpoint name" in { + def breakpoint_name_name : Option<"name", "N">, Group<1>, + Arg<"BreakpointName">, Desc<"Specifies a breakpoint name to use.">; + def breakpoint_name_breakpoint_id : Option<"breakpoint-id", "B">, Group<2>, + Arg<"BreakpointID">, Desc<"Specify a breakpoint ID to use.">; + def breakpoint_name_dummy_breakpoints : Option<"dummy-breakpoints", "D">, + Group<3>, Desc<"Operate on Dummy breakpoints - i.e. breakpoints set before " + "a file is provided, which prime new targets.">; + def breakpoint_name_help_string : Option<"help-string", "H">, Group<4>, + Arg<"None">, Desc<"A help string describing the purpose of this name.">; +} + +let Command = "breakpoint access" in { + def breakpoint_access_allow_list : Option<"allow-list", "L">, Group<1>, + Arg<"Boolean">, Desc<"Determines whether the breakpoint will show up in " + "break list if not referred to explicitly.">; + def breakpoint_access_allow_disable : Option<"allow-disable", "A">, Group<2>, + Arg<"Boolean">, Desc<"Determines whether the breakpoint can be disabled by " + "name or when all breakpoints are disabled.">; + def breakpoint_access_allow_delete : Option<"allow-delete", "D">, Group<3>, + Arg<"Boolean">, Desc<"Determines whether the breakpoint can be deleted by " + "name or when all breakpoints are deleted.">; +} + +let Command = "breakpoint read" in { + def breakpoint_read_file : Option<"file", "f">, Arg<"Filename">, Required, + Completion<"DiskFile">, + Desc<"The file from which to read the breakpoints.">; + def breakpoint_read_breakpoint_name : Option<"breakpoint-name", "N">, + Arg<"BreakpointName">, Desc<"Only read in breakpoints with this name.">; +} + +let Command = "breakpoint write" in { + def breakpoint_write_file : Option<"file", "f">, Arg<"Filename">, Required, + Completion<"DiskFile">, + Desc<"The file into which to write the breakpoints.">; + def breakpoint_write_append : Option<"append", "a">, + Desc<"Append to saved breakpoints file if it exists.">; +} + +let Command = "breakpoint command add" in { + def breakpoint_add_one_liner : Option<"one-liner", "o">, Group<1>, + Arg<"OneLiner">, Desc<"Specify a one-line breakpoint command inline. Be " + "sure to surround it with quotes.">; + def breakpoint_add_stop_on_error : Option<"stop-on-error", "e">, + Arg<"Boolean">, Desc<"Specify whether breakpoint command execution should " + "terminate on error.">; + def breakpoint_add_script_type : Option<"script-type", "s">, + EnumArg<"None", "ScriptOptionEnum()">, + Desc<"Specify the language for the commands - if none is specified, the " + "lldb command interpreter will be used.">; + def breakpoint_add_python_function : Option<"python-function", "F">, + Group<2>, Arg<"PythonFunction">, + Desc<"Give the name of a Python function to run as command for this " + "breakpoint. Be sure to give a module name if appropriate.">; + def breakpoint_add_dummy_breakpoints : Option<"dummy-breakpoints", "D">, + Desc<"Sets Dummy breakpoints - i.e. breakpoints set before a file is " + "provided, which prime new targets.">; +} + +let Command = "breakpoint command delete" in { + def breakpoint_command_delete_dummy_breakpoints : + Option<"dummy-breakpoints", "D">, Group<1>, + Desc<"Delete commands from Dummy breakpoints - i.e. breakpoints set before " + "a file is provided, which prime new targets.">; +} + +let Command = "disassemble" in { + def disassemble_options_bytes : Option<"bytes", "b">, + Desc<"Show opcode bytes when disassembling.">; + def disassemble_options_context : Option<"context", "C">, Arg<"NumLines">, + Desc<"Number of context lines of source to show.">; + def disassemble_options_mixed : Option<"mixed", "m">, + Desc<"Enable mixed source and assembly display.">; + def disassemble_options_raw : Option<"raw", "r">, + Desc<"Print raw disassembly with no symbol information.">; + def disassemble_options_plugin : Option<"plugin", "P">, Arg<"Plugin">, + Desc<"Name of the disassembler plugin you want to use.">; + def disassemble_options_flavor : Option<"flavor", "F">, + Arg<"DisassemblyFlavor">, Desc<"Name of the disassembly flavor you want to " + "use. Currently the only valid options are default, and for Intel " + "architectures, att and intel.">; + def disassemble_options_arch : Option<"arch", "A">, Arg<"Architecture">, + Desc<"Specify the architecture to use from cross disassembly.">; + def disassemble_options_start_address : Option<"start-address", "s">, + Groups<[1,2]>, Arg<"AddressOrExpression">, Required, + Desc<"Address at which to start disassembling.">; + def disassemble_options_end_address : Option<"end-address", "e">, Group<1>, + Arg<"AddressOrExpression">, Desc<"Address at which to end disassembling.">; + def disassemble_options_count : Option<"count", "c">, Groups<[2,3,4,5]>, + Arg<"NumLines">, Desc<"Number of instructions to display.">; + def disassemble_options_name : Option<"name", "n">, Group<3>, + Arg<"FunctionName">, Completion<"Symbol">, + Desc<"Disassemble entire contents of the given function name.">; + def disassemble_options_frame : Option<"frame", "f">, Group<4>, + Desc<"Disassemble from the start of the current frame's function.">; + def disassemble_options_pc : Option<"pc", "p">, Group<5>, + Desc<"Disassemble around the current pc.">; + def disassemble_options_line : Option<"line", "l">, Group<6>, + Desc<"Disassemble the current frame's current source line instructions if" + "there is debug line table information, else disassemble around the pc.">; + def disassemble_options_address : Option<"address", "a">, Group<7>, + Arg<"AddressOrExpression">, + Desc<"Disassemble function containing this address.">; +} + +let Command = "expression" in { + def expression_options_all_threads : Option<"all-threads", "a">, + Groups<[1,2]>, Arg<"Boolean">, Desc<"Should we run all threads if the " + "execution doesn't complete on one thread.">; + def expression_options_ignore_breakpoints : Option<"ignore-breakpoints", "i">, + Groups<[1,2]>, Arg<"Boolean">, + Desc<"Ignore breakpoint hits while running expressions">; + def expression_options_timeout : Option<"timeout", "t">, Groups<[1,2]>, + Arg<"UnsignedInteger">, + Desc<"Timeout value (in microseconds) for running the expression.">; + def expression_options_unwind_on_error : Option<"unwind-on-error", "u">, + Groups<[1,2]>, Arg<"Boolean">, + Desc<"Clean up program state if the expression causes a crash, or raises a " + "signal. Note, unlike gdb hitting a breakpoint is controlled by another " + "option (-i).">; + def expression_options_debug : Option<"debug", "g">, Groups<[1,2]>, + Desc<"When specified, debug the JIT code by setting a breakpoint on the " + "first instruction and forcing breakpoints to not be ignored (-i0) and no " + "unwinding to happen on error (-u0).">; + def expression_options_language : Option<"language", "l">, Groups<[1,2]>, + Arg<"Language">, Desc<"Specifies the Language to use when parsing the " + "expression. If not set the target.language setting is used.">; + def expression_options_apply_fixits : Option<"apply-fixits", "X">, + Groups<[1,2]>, Arg<"Language">, Desc<"If true, simple fix-it hints will be " + "automatically applied to the expression.">; + def expression_options_description_verbosity : + Option<"description-verbosity", "v">, Group<1>, + OptionalEnumArg<"DescriptionVerbosity", "DescriptionVerbosityTypes()">, + Desc<"How verbose should the output of this expression be, if the object " + "description is asked for.">; + def expression_options_top_level : Option<"top-level", "p">, Groups<[1,2]>, + Desc<"Interpret the expression as a complete translation unit, without " + "injecting it into the local context. Allows declaration of persistent, " + "top-level entities without a $ prefix.">; + def expression_options_allow_jit : Option<"allow-jit", "j">, Groups<[1,2]>, + Arg<"Boolean">, + Desc<"Controls whether the expression can fall back to being JITted if it's" + "not supported by the interpreter (defaults to true).">; +} + +let Command = "frame diag" in { + def frame_diag_register : Option<"register", "r">, Group<1>, + Arg<"RegisterName">, Desc<"A register to diagnose.">; + def frame_diag_address : Option<"address", "a">, Group<1>, Arg<"Address">, + Desc<"An address to diagnose.">; + def frame_diag_offset : Option<"offset", "o">, Group<1>, Arg<"Offset">, + Desc<"An optional offset. Requires --register.">; +} + +let Command = "frame select" in { + def frame_select_relative : Option<"relative", "r">, Group<1>, Arg<"Offset">, + Desc<"A relative frame index offset from the current frame index.">; +} + +let Command = "frame recognizer add" in { + def frame_recognizer_shlib : Option<"shlib", "s">, Arg<"ShlibName">, + Completion<"Module">, + Desc<"Name of the module or shared library that this recognizer applies " + "to.">; + def frame_recognizer_function : Option<"function", "n">, Arg<"Name">, + Completion<"Symbol">, + Desc<"Name of the function that this recognizer applies to.">; + def frame_recognizer_python_class : Option<"python-class", "l">, Group<2>, + Arg<"PythonClass">, + Desc<"Give the name of a Python class to use for this frame recognizer.">; + def frame_recognizer_regex : Option<"regex", "x">, + Desc<"Function name and module name are actually regular expressions.">; +} + +let Command = "history" in { + def history_count : Option<"count", "c">, Group<1>, Arg<"UnsignedInteger">, + Desc<"How many history commands to print.">; + def history_start_index : Option<"start-index", "s">, Group<1>, + Arg<"UnsignedInteger">, Desc<"Index at which to start printing history " + "commands (or end to mean tail mode).">; + def history_end_index : Option<"end-index", "e">, Group<1>, + Arg<"UnsignedInteger">, + Desc<"Index at which to stop printing history commands.">; + def history_clear : Option<"clear", "C">, Group<2>, + Desc<"Clears the current command history.">; +} + +let Command = "log" in { + def log_file : Option<"file", "f">, Group<1>, Arg<"Filename">, + Desc<"Set the destination file to log to.">; + def log_threadsafe : Option<"threadsafe", "t">, Group<1>, + Desc<"Enable thread safe logging to avoid interweaved log lines.">; + def log_verbose : Option<"verbose", "v">, Group<1>, + Desc<"Enable verbose logging.">; + def log_sequence : Option<"sequence", "s">, Group<1>, + Desc<"Prepend all log lines with an increasing integer sequence id.">; + def log_timestamp : Option<"timestamp", "T">, Group<1>, + Desc<"Prepend all log lines with a timestamp.">; + def log_pid_tid : Option<"pid-tid", "p">, Group<1>, + Desc<"Prepend all log lines with the process and thread ID that generates " + "the log line.">; + def log_thread_name : Option<"thread-name", "n">, Group<1>, + Desc<"Prepend all log lines with the thread name for the thread that " + "generates the log line.">; + + def log_stack : Option<"stack", "S">, Group<1>, + Desc<"Append a stack backtrace to each log line.">; + def log_append : Option<"append", "a">, Group<1>, + Desc<"Append to the log file instead of overwriting.">; + def log_file_function : Option<"file-function", "F">, Group<1>, + Desc<"Prepend the names of files and function that generate the logs.">; +} + +let Command = "reproducer" in { + def reproducer_provider : Option<"provider", "p">, Group<1>, + EnumArg<"None", "ReproducerProviderType()">, + Required, Desc<"The reproducer provider to dump.">; + def reproducer_file : Option<"file", "f">, Group<1>, Arg<"Filename">, + Desc<"The reproducer path. If a reproducer is replayed and no path is " + "provided, that reproducer is dumped.">; +} + +let Command = "memory read" in { + def memory_read_num_per_line : Option<"num-per-line", "l">, Group<1>, + Arg<"NumberPerLine">, Desc<"The number of items per line to display.">; + def memory_read_binary : Option<"binary", "b">, Group<2>, + Desc<"If true, memory will be saved as binary. If false, the memory is " + "saved save as an ASCII dump that uses the format, size, count and number " + "per line settings.">; + def memory_read_type : Option<"type", "t">, Groups<[3,4]>, Arg<"Name">, + Required, Desc<"The name of a type to view memory as.">; + def memory_read_language : Option<"language", "x">, Group<4>, Arg<"Language">, + Desc<"The language of the type to view memory as.">; + def memory_read_offset : Option<"offset", "E">, Group<3>, Arg<"Count">, + Desc<"How many elements of the specified type to skip before starting to " + "display data.">; + def memory_read_force : Option<"force", "r">, Groups<[1,2,3]>, + Desc<"Necessary if reading over target.max-memory-read-size bytes.">; +} + +let Command = "memory find" in { + def memory_find_expression : Option<"expression", "e">, Group<1>, + Arg<"Expression">, Required, + Desc<"Evaluate an expression to obtain a byte pattern.">; + def memory_find_string : Option<"string", "s">, Group<2>, Arg<"Name">, + Required, Desc<"Use text to find a byte pattern.">; + def memory_find_count : Option<"count", "c">, Arg<"Count">, + Desc<"How many times to perform the search.">; + def memory_find_dump_offset : Option<"dump-offset", "o">, Arg<"Offset">, + Desc<"When dumping memory for a match, an offset from the match location to" + " start dumping from.">; +} + +let Command = "memory write" in { + def memory_write_infile : Option<"infile", "i">, Group<1>, Arg<"Filename">, + Required, Desc<"Write memory using the contents of a file.">; + def memory_write_offset : Option<"offset", "o">, Group<1>, Arg<"Offset">, + Desc<"Start writing bytes from an offset within the input file.">; +} + +let Command = "register read" in { + def register_read_alternate : Option<"alternate", "A">, + Desc<"Display register names using the alternate register name if there " + "is one.">; + def register_read_set : Option<"set", "s">, Group<1>, Arg<"Index">, + Desc<"Specify which register sets to dump by index.">; + def register_read_all : Option<"all", "a">, Group<2>, + Desc<"Show all register sets.">; +} + +let Command = "source" in { + def source_stop_on_error : Option<"stop-on-error", "e">, Arg<"Boolean">, + Desc<"If true, stop executing commands on error.">; + def source_stop_on_continue : Option<"stop-on-continue", "c">, Arg<"Boolean">, + Desc<"If true, stop executing commands on continue.">; + def source_silent_run : Option<"silent-run", "s">, Arg<"Boolean">, + Desc<"If true don't echo commands while executing.">; +} + +let Command = "alias" in { + def alias_help : Option<"help", "h">, Arg<"HelpText">, + Desc<"Help text for this command">; + def alias_long_help : Option<"long-help", "H">, Arg<"HelpText">, + Desc<"Long help text for this command">; +} + +let Command = "regex" in { + def regex_help : Option<"help", "h">, Group<1>, Arg<"None">, + Desc<"The help text to display for this command.">; + def regex_syntax : Option<"syntax", "s">, Group<1>, Arg<"None">, + Desc<"A syntax string showing the typical usage syntax.">; +} + +let Command = "permissions" in { + def permissions_permissions_value : Option<"permissions-value", "v">, + Arg<"PermissionsNumber">, + Desc<"Give out the numeric value for permissions (e.g. 757)">; + def permissions_permissions_string : Option<"permissions-string", "s">, + Arg<"PermissionsString">, + Desc<"Give out the string value for permissions (e.g. rwxr-xr--).">; + def permissions_user_read : Option<"user-read", "r">, + Desc<"Allow user to read.">; + def permissions_user_write : Option<"user-write", "w">, + Desc<"Allow user to write.">; + def permissions_user_exec : Option<"user-exec", "x">, + Desc<"Allow user to execute.">; + def permissions_group_read : Option<"group-read", "R">, + Desc<"Allow group to read.">; + def permissions_group_write : Option<"group-write", "W">, + Desc<"Allow group to write.">; + def permissions_group_exec : Option<"group-exec", "X">, + Desc<"Allow group to execute.">; + def permissions_world_read : Option<"world-read", "d">, + Desc<"Allow world to read.">; + def permissions_world_write : Option<"world-write", "t">, + Desc<"Allow world to write.">; + def permissions_world_exec : Option<"world-exec", "e">, + Desc<"Allow world to execute.">; +} + +let Command = "platform fread" in { + def platform_fread_offset : Option<"offset", "o">, Group<1>, Arg<"Index">, + Desc<"Offset into the file at which to start reading.">; + def platform_fread_count : Option<"count", "c">, Group<1>, Arg<"Count">, + Desc<"Number of bytes to read from the file.">; +} + +let Command = "platform fwrite" in { + def platform_fwrite_offset : Option<"offset", "o">, Group<1>, Arg<"Index">, + Desc<"Offset into the file at which to start reading.">; + def platform_fwrite_data : Option<"data", "d">, Group<1>, Arg<"Value">, + Desc<"Text to write to the file.">; +} + +let Command = "platform process list" in { + def platform_process_list_pid : Option<"pid", "p">, Group<1>, Arg<"Pid">, + Desc<"List the process info for a specific process ID.">; + def platform_process_list_name : Option<"name", "n">, Group<2>, + Arg<"ProcessName">, Required, + Desc<"Find processes with executable basenames that match a string.">; + def platform_process_list_ends_with : Option<"ends-with", "e">, Group<3>, + Arg<"ProcessName">, Required, + Desc<"Find processes with executable basenames that end with a string.">; + def platform_process_list_starts_with : Option<"starts-with", "s">, Group<4>, + Arg<"ProcessName">, Required, + Desc<"Find processes with executable basenames that start with a string.">; + def platform_process_list_contains : Option<"contains", "c">, Group<5>, + Arg<"ProcessName">, Required, + Desc<"Find processes with executable basenames that contain a string.">; + def platform_process_list_regex : Option<"regex", "r">, Group<6>, + Arg<"RegularExpression">, Required, + Desc<"Find processes with executable basenames that match a regular " + "expression.">; + def platform_process_list_parent : Option<"parent", "P">, GroupRange<2, 6>, + Arg<"Pid">, Desc<"Find processes that have a matching parent process ID.">; + def platform_process_list_uid : Option<"uid", "u">, GroupRange<2, 6>, + Arg<"UnsignedInteger">, Validator<"&posix_validator">, + Desc<"Find processes that have a matching user ID.">; + def platform_process_list_euid : Option<"euid", "U">, GroupRange<2, 6>, + Arg<"UnsignedInteger">, Validator<"&posix_validator">, + Desc<"Find processes that have a matching effective user ID.">; + def platform_process_list_gid : Option<"gid", "g">, GroupRange<2, 6>, + Arg<"UnsignedInteger">, Validator<"&posix_validator">, + Desc<"Find processes that have a matching group ID.">; + def platform_process_list_egid : Option<"egid", "G">, GroupRange<2, 6>, + Arg<"UnsignedInteger">, Validator<"&posix_validator">, + Desc<"Find processes that have a matching effective group ID.">; + def platform_process_list_arch : Option<"arch", "a">, GroupRange<2, 6>, + Arg<"Architecture">, + Desc<"Find processes that have a matching architecture.">; + def platform_process_list_show_args : Option<"show-args", "A">, + GroupRange<1, 6>, + Desc<"Show process arguments instead of the process executable basename.">; + def platform_process_list_all_users: Option<"all-users", "x">, + GroupRange<1,6>, + Desc<"Show processes matching all user IDs.">; + def platform_process_list_verbose : Option<"verbose", "v">, GroupRange<1, 6>, + Desc<"Enable verbose output.">; +} + +let Command = "platform process attach" in { + def platform_process_attach_plugin : Option<"plugin", "P">, Arg<"Plugin">, + Desc<"Name of the process plugin you want to use.">; + def platform_process_attach_pid : Option<"pid", "p">, Group<1>, Arg<"Pid">, + Desc<"The process ID of an existing process to attach to.">; + def platform_process_attach_name : Option<"name", "n">, Group<2>, + Arg<"ProcessName">, Desc<"The name of the process to attach to.">; + def platform_process_attach_waitfor : Option<"waitfor", "w">, Group<2>, + Desc<"Wait for the process with <process-name> to launch.">; +} + +let Command = "platform shell" in { + def platform_shell_timeout : Option<"timeout", "t">, Arg<"Value">, + Desc<"Seconds to wait for the remote host to finish running the command.">; +} + +let Command = "process attach" in { + def process_attach_continue : Option<"continue", "c">, + Desc<"Immediately continue the process once attached.">; + def process_attach_plugin : Option<"plugin", "P">, Arg<"Plugin">, + Desc<"Name of the process plugin you want to use.">; + def process_attach_pid : Option<"pid", "p">, Group<1>, Arg<"Pid">, + Desc<"The process ID of an existing process to attach to.">; + def process_attach_name : Option<"name", "n">, Group<2>, Arg<"ProcessName">, + Desc<"The name of the process to attach to.">; + def process_attach_include_existing : Option<"include-existing", "i">, + Group<2>, Desc<"Include existing processes when doing attach -w.">; + def process_attach_waitfor : Option<"waitfor", "w">, Group<2>, + Desc<"Wait for the process with <process-name> to launch.">; +} + +let Command = "process continue" in { + def process_continue_ignore_count : Option<"ignore-count", "i">, + Arg<"UnsignedInteger">, Desc<"Ignore <N> crossings of the breakpoint (if it" + " exists) for the currently selected thread.">; +} + +let Command = "process detach" in { + def process_detach_keep_stopped : Option<"keep-stopped", "s">, Group<1>, + Arg<"Boolean">, Desc<"Whether or not the process should be kept stopped on" + " detach (if possible).">; +} + +let Command = "process connect" in { + def process_connect_plugin : Option<"plugin", "p">, Arg<"Plugin">, + Desc<"Name of the process plugin you want to use.">; +} + +let Command = "process load" in { + def process_load_install : Option<"install", "i">, OptionalArg<"Path">, + Desc<"Install the shared library to the target. If specified without an " + "argument then the library will installed in the current working " + "directory.">; +} + +let Command = "process handle" in { + def process_handle_stop : Option<"stop", "s">, Group<1>, Arg<"Boolean">, + Desc<"Whether or not the process should be stopped if the signal is " + "received.">; + def process_handle_notify : Option<"notify", "n">, Group<1>, Arg<"Boolean">, + Desc<"Whether or not the debugger should notify the user if the signal is " + "received.">; + def process_handle_pass : Option<"pass", "p">, Group<1>, Arg<"Boolean">, + Desc<"Whether or not the signal should be passed to the process.">; +} + +let Command = "script import" in { + def script_import_allow_reload : Option<"allow-reload", "r">, Group<1>, + Desc<"Allow the script to be loaded even if it was already loaded before. " + "This argument exists for backwards compatibility, but reloading is always " + "allowed, whether you specify it or not.">; +} + +let Command = "script add" in { + def script_add_function : Option<"function", "f">, Group<1>, + Arg<"PythonFunction">, + Desc<"Name of the Python function to bind to this command name.">; + def script_add_class : Option<"class", "c">, Group<2>, Arg<"PythonClass">, + Desc<"Name of the Python class to bind to this command name.">; + def script_add_help : Option<"help", "h">, Group<1>, Arg<"HelpText">, + Desc<"The help text to display for this command.">; + def script_add_synchronicity : Option<"synchronicity", "s">, + EnumArg<"ScriptedCommandSynchronicity", "ScriptSynchroType()">, + Desc<"Set the synchronicity of this command's executions with regard to " + "LLDB event system.">; +} +let Command = "source info" in { + def source_info_count : Option<"count", "c">, Arg<"Count">, + Desc<"The number of line entries to display.">; + def source_info_shlib : Option<"shlib", "s">, Groups<[1,2]>, Arg<"ShlibName">, + Completion<"Module">, Desc<"Look up the source in the given module or " + "shared library (can be specified more than once).">; + def source_info_file : Option<"file", "f">, Group<1>, Arg<"Filename">, + Completion<"SourceFile">, Desc<"The file from which to display source.">; + def source_info_line : Option<"line", "l">, Group<1>, Arg<"LineNum">, + Desc<"The line number at which to start the displaying lines.">; + def source_info_end_line : Option<"end-line", "e">, Group<1>, Arg<"LineNum">, + Desc<"The line number at which to stop displaying lines.">; + def source_info_name : Option<"name", "n">, Group<2>, Arg<"Symbol">, + Completion<"Symbol">, + Desc<"The name of a function whose source to display.">; + def source_info_address : Option<"address", "a">, Group<3>, + Arg<"AddressOrExpression">, Desc<"Lookup the address and display the source" + " information for the corresponding file and line.">; +} + +let Command = "source list" in { + def source_list_count : Option<"count", "c">, Arg<"Count">, + Desc<"The number of source lines to display.">; + def source_list_shlib : Option<"shlib", "s">, Groups<[1,2]>, Arg<"ShlibName">, + Completion<"Module">, + Desc<"Look up the source file in the given shared library.">; + def source_list_show_breakpoints : Option<"show-breakpoints", "b">, + Desc<"Show the line table locations from the debug information that " + "indicate valid places to set source level breakpoints.">; + def source_list_file : Option<"file", "f">, Group<1>, Arg<"Filename">, + Completion<"SourceFile">, Desc<"The file from which to display source.">; + def source_list_line : Option<"line", "l">, Group<1>, Arg<"LineNum">, + Desc<"The line number at which to start the display source.">; + def source_list_name : Option<"name", "n">, Group<2>, Arg<"Symbol">, + Completion<"Symbol">, + Desc<"The name of a function whose source to display.">; + def source_list_address : Option<"address", "a">, Group<3>, + Arg<"AddressOrExpression">, Desc<"Lookup the address and display the source" + " information for the corresponding file and line.">; + def source_list_reverse : Option<"reverse", "r">, Group<4>, Desc<"Reverse the" + " listing to look backwards from the last displayed block of source.">; +} + +let Command = "target dependents" in { + def dependents_no_dependents : Option<"no-dependents", "d">, Group<1>, + OptionalEnumArg<"Value", "OptionEnumValues(g_dependents_enumaration)">, + Desc<"Whether or not to load dependents when creating a target. If the " + "option is not specified, the value is implicitly 'default'. If the " + "option is specified but without a value, the value is implicitly " + "'true'.">; +} + +let Command = "target modules dump" in { + def target_modules_dump_verbose : Option<"verbose", "v">, + Desc<"Enable verbose dump.">; +} + +let Command = "target modules list" in { + def target_modules_list_address : Option<"address", "a">, Group<1>, + Arg<"AddressOrExpression">, Desc<"Display the image at this address.">; + def target_modules_list_arch : Option<"arch", "A">, Group<1>, + OptionalArg<"Width">, Desc<"Display the architecture when listing images.">; + def target_modules_list_triple : Option<"triple", "t">, Group<1>, + OptionalArg<"Width">, Desc<"Display the triple when listing images.">; + def target_modules_list_header : Option<"header", "h">, Group<1>, + Desc<"Display the image base address as a load address if debugging, a file" + " address otherwise.">; + def target_modules_list_offset : Option<"offset", "o">, Group<1>, + Desc<"Display the image load address offset from the base file address " + "(the slide amount).">; + def target_modules_list_uuid : Option<"uuid", "u">, Group<1>, + Desc<"Display the UUID when listing images.">; + def target_modules_list_fullpath : Option<"fullpath", "f">, Group<1>, + OptionalArg<"Width">, + Desc<"Display the fullpath to the image object file.">; + def target_modules_list_directory : Option<"directory", "d">, Group<1>, + OptionalArg<"Width">, Desc<"Display the directory with optional width for " + "the image object file.">; + def target_modules_list_basename : Option<"basename", "b">, Group<1>, + OptionalArg<"Width">, Desc<"Display the basename with optional width for " + "the image object file.">; + def target_modules_list_symfile : Option<"symfile", "s">, Group<1>, + OptionalArg<"Width">, Desc<"Display the fullpath to the image symbol file " + "with optional width.">; + def target_modules_list_symfile_unique : Option<"symfile-unique", "S">, + Group<1>, OptionalArg<"Width">, Desc<"Display the symbol file with optional" + " width only if it is different from the executable object file.">; + def target_modules_list_mod_time : Option<"mod-time", "m">, Group<1>, + OptionalArg<"Width">, Desc<"Display the modification time with optional " + "width of the module.">; + def target_modules_list_ref_count : Option<"ref-count", "r">, Group<1>, + OptionalArg<"Width">, Desc<"Display the reference count if the module is " + "still in the shared module cache.">; + def target_modules_list_pointer : Option<"pointer", "p">, Group<1>, + OptionalArg<"None">, Desc<"Display the module pointer.">; + def target_modules_list_global : Option<"global", "g">, Group<1>, + Desc<"Display the modules from the global module list, not just the " + "current target.">; +} + +let Command = "target modules show unwind" in { + def target_modules_show_unwind_name : Option<"name", "n">, Group<1>, + Arg<"FunctionName">, + Desc<"Show unwind instructions for a function or symbol name.">; + def target_modules_show_unwind_address : Option<"address", "a">, Group<2>, + Arg<"AddressOrExpression">, Desc<"Show unwind instructions for a function " + "or symbol containing an address">; +} + +let Command = "target modules lookup" in { + def target_modules_lookup_address : Option<"address", "a">, Group<1>, + Arg<"AddressOrExpression">, Required, Desc<"Lookup an address in one or " + "more target modules.">; + def target_modules_lookup_offset : Option<"offset", "o">, Group<1>, + Arg<"Offset">, Desc<"When looking up an address subtract <offset> from any " + "addresses before doing the lookup.">; + // FIXME: re-enable regex for types when the LookupTypeInModule actually uses + // the regex option by adding to group 6. + def target_modules_lookup_regex : Option<"regex", "r">, Groups<[2,4,5]>, + Desc<"The <name> argument for name lookups are regular expressions.">; + def target_modules_lookup_symbol : Option<"symbol", "s">, Group<2>, + Arg<"Symbol">, Required, Desc<"Lookup a symbol by name in the symbol tables" + " in one or more target modules.">; + def target_modules_lookup_file : Option<"file", "f">, Group<3>, + Arg<"Filename">, Required, Desc<"Lookup a file by fullpath or basename in " + "one or more target modules.">; + def target_modules_lookup_line : Option<"line", "l">, Group<3>, + Arg<"LineNum">, Desc<"Lookup a line number in a file (must be used in " + "conjunction with --file).">; + def target_modules_lookup_no_inlines : Option<"no-inlines", "i">, + GroupRange<3,5>, + Desc<"Ignore inline entries (must be used in conjunction with --file or " + "--function).">; + def target_modules_lookup_function : Option<"function", "F">, Group<4>, + Arg<"FunctionName">, Required, Desc<"Lookup a function by name in the debug" + " symbols in one or more target modules.">; + def target_modules_lookup_name : Option<"name", "n">, Group<5>, + Arg<"FunctionOrSymbol">, Required, Desc<"Lookup a function or symbol by " + "name in one or more target modules.">; + def target_modules_lookup_type : Option<"type", "t">, Group<6>, Arg<"Name">, + Required, Desc<"Lookup a type by name in the debug symbols in one or more " + "target modules.">; + def target_modules_lookup_verbose : Option<"verbose", "v">, + Desc<"Enable verbose lookup information.">; + def target_modules_lookup_all : Option<"all", "A">, Desc<"Print all matches, " + "not just the best match, if a best match is available.">; +} + +let Command = "target stop hook add" in { + def target_stop_hook_add_one_liner : Option<"one-liner", "o">, + Arg<"OneLiner">, Desc<"Add a command for the stop hook. Can be specified " + "more than once, and commands will be run in the order they appear.">; + def target_stop_hook_add_shlib : Option<"shlib", "s">, Arg<"ShlibName">, + Completion<"Module">, + Desc<"Set the module within which the stop-hook is to be run.">; + def target_stop_hook_add_thread_index : Option<"thread-index", "x">, + Arg<"ThreadIndex">, Desc<"The stop hook is run only for the thread whose " + "index matches this argument.">; + def target_stop_hook_add_thread_id : Option<"thread-id", "t">, + Arg<"ThreadID">, Desc<"The stop hook is run only for the thread whose TID " + "matches this argument.">; + def target_stop_hook_add_thread_name : Option<"thread-name", "T">, + Arg<"ThreadName">, Desc<"The stop hook is run only for the thread whose " + "thread name matches this argument.">; + def target_stop_hook_add_queue_name : Option<"queue-name", "q">, + Arg<"QueueName">, Desc<"The stop hook is run only for threads in the queue " + "whose name is given by this argument.">; + def target_stop_hook_add_file : Option<"file", "f">, Group<1>, + Arg<"Filename">, Desc<"Specify the source file within which the stop-hook " + "is to be run.">, Completion<"SourceFile">; + def target_stop_hook_add_start_line : Option<"start-line", "l">, Group<1>, + Arg<"LineNum">, Desc<"Set the start of the line range for which the " + "stop-hook is to be run.">; + def target_stop_hook_add_end_line : Option<"end-line", "e">, Group<1>, + Arg<"LineNum">, Desc<"Set the end of the line range for which the stop-hook" + " is to be run.">; + def target_stop_hook_add_classname : Option<"classname", "c">, Group<2>, + Arg<"ClassName">, + Desc<"Specify the class within which the stop-hook is to be run.">; + def target_stop_hook_add_name : Option<"name", "n">, Group<3>, + Arg<"FunctionName">, Desc<"Set the function name within which the stop hook" + " will be run.">, Completion<"Symbol">; + def target_stop_hook_add_auto_continue : Option<"auto-continue", "G">, + Arg<"Boolean">, Desc<"The breakpoint will auto-continue after running its" + " commands.">; +} + let Command = "thread backtrace" in { def thread_backtrace_count : Option<"count", "c">, Group<1>, Arg<"Count">, Desc<"How many frames to display (-1 for all)">; diff --git a/source/Commands/OptionsBase.td b/source/Commands/OptionsBase.td index a81563ed28c2..f6967f067bf4 100644 --- a/source/Commands/OptionsBase.td +++ b/source/Commands/OptionsBase.td @@ -41,15 +41,19 @@ // - `OptionalArg`: Sets the argument type and marks it as optional. // - `Arg`: Sets the argument type and marks it as required. // - `EnumArg`: Sets the argument type to an enum and marks it as required. +// - `OptionalEnumArg`: Same as EnumArg but marks it as optional. // See argument_type field for more info. //////////////////////////////////////////////////////////////////////////////// // Field: validator // Default value: 0 (No validator for option) -// Set by: Nothing. This is currently only set after initialization in LLDB. +// Set by: +// - `Validator`: Sets the value to a given validator (which has to exist in +// the surrounding code. //////////////////////////////////////////////////////////////////////////////// // Field: enum_values // Default value: {} (No enum associated with this option) // Set by: +// - `OptionalEnumArg`: // - `EnumArg`: Sets the argument type and assigns it a enum holding the valid // values. The enum needs to be a variable in the including code. // Marks the option as required (see option_has_arg). @@ -82,12 +86,14 @@ // Example: def foo : Option<"foo", "f">, Arg<"Pid">; // Sets the argument type to eArgTypePid and marks option as // required (see option_has_arg). +// - `OptionalEnumArg`: // - `EnumArg`: Sets the argument type and assigns it a enum holding the valid // values. The enum needs to be a variable in the including code. // Marks the option as required (see option_has_arg). // Example: def foo : Option<"foo", "f">, // EnumArg<"SortOrder", // "OptionEnumValues(g_sort_option_enumeration)">; +// Use `OptionalEnumArg` for having an option enum argument. //////////////////////////////////////////////////////////////////////////////// // Field: usage_text // Default value: "" @@ -150,6 +156,13 @@ class EnumArg<string type, string enum> { string ArgEnum = enum; } +// Gives the option an required argument. +class OptionalEnumArg<string type, string enum> { + string ArgType = type; + string ArgEnum = enum; + bit OptionalArg = 1; +} + // Sets the available completions for the given option. class Completions<list<string> completions> { list<string> Completions = completions; @@ -158,3 +171,8 @@ class Completions<list<string> completions> { class Completion<string completion> { list<string> Completions = [completion]; } + +// Sets the validator for a given option. +class Validator<string validator> { + string Validator = validator; +} diff --git a/source/Core/Address.cpp b/source/Core/Address.cpp index 0da83eb98edb..a3912bef5a6e 100644 --- a/source/Core/Address.cpp +++ b/source/Core/Address.cpp @@ -261,6 +261,24 @@ bool Address::ResolveAddressUsingFileSections(addr_t file_addr, return false; // Failed to resolve this address to a section offset value } +/// if "addr_range_ptr" is not NULL, then fill in with the address range of the function. +bool Address::ResolveFunctionScope(SymbolContext &sym_ctx, + AddressRange *addr_range_ptr) { + constexpr SymbolContextItem resolve_scope = + eSymbolContextFunction | eSymbolContextSymbol; + + if (!(CalculateSymbolContext(&sym_ctx, resolve_scope) & resolve_scope)) { + if (addr_range_ptr) + addr_range_ptr->Clear(); + return false; + } + + if (!addr_range_ptr) + return true; + + return sym_ctx.GetAddressRange(resolve_scope, 0, false, *addr_range_ptr); +} + ModuleSP Address::GetModule() const { lldb::ModuleSP module_sp; SectionSP section_sp(GetSection()); @@ -475,23 +493,19 @@ bool Address::Dump(Stream *s, ExecutionContextScope *exe_scope, DumpStyle style, switch (sect_type) { case eSectionTypeData: if (module_sp) { - SymbolVendor *sym_vendor = module_sp->GetSymbolVendor(); - if (sym_vendor) { - Symtab *symtab = sym_vendor->GetSymtab(); - if (symtab) { - const addr_t file_Addr = GetFileAddress(); - Symbol *symbol = - symtab->FindSymbolContainingFileAddress(file_Addr); - if (symbol) { - const char *symbol_name = symbol->GetName().AsCString(); - if (symbol_name) { - s->PutCString(symbol_name); - addr_t delta = - file_Addr - symbol->GetAddressRef().GetFileAddress(); - if (delta) - s->Printf(" + %" PRIu64, delta); - showed_info = true; - } + if (Symtab *symtab = module_sp->GetSymtab()) { + const addr_t file_Addr = GetFileAddress(); + Symbol *symbol = + symtab->FindSymbolContainingFileAddress(file_Addr); + if (symbol) { + const char *symbol_name = symbol->GetName().AsCString(); + if (symbol_name) { + s->PutCString(symbol_name); + addr_t delta = + file_Addr - symbol->GetAddressRef().GetFileAddress(); + if (delta) + s->Printf(" + %" PRIu64, delta); + showed_info = true; } } } @@ -985,10 +999,9 @@ AddressClass Address::GetAddressClass() const { if (module_sp) { ObjectFile *obj_file = module_sp->GetObjectFile(); if (obj_file) { - // Give the symbol vendor a chance to add to the unified section list - // and to symtab from symbol file - if (SymbolVendor *vendor = module_sp->GetSymbolVendor()) - vendor->GetSymtab(); + // Give the symbol file a chance to add to the unified section list + // and to the symtab. + module_sp->GetSymtab(); return obj_file->GetAddressClass(GetFileAddress()); } } diff --git a/source/Core/AddressResolverFileLine.cpp b/source/Core/AddressResolverFileLine.cpp index 24c0222d6ec2..4a14260c6c72 100644 --- a/source/Core/AddressResolverFileLine.cpp +++ b/source/Core/AddressResolverFileLine.cpp @@ -38,8 +38,7 @@ AddressResolverFileLine::~AddressResolverFileLine() {} Searcher::CallbackReturn AddressResolverFileLine::SearchCallback(SearchFilter &filter, - SymbolContext &context, Address *addr, - bool containing) { + SymbolContext &context, Address *addr) { SymbolContextList sc_list; uint32_t sc_list_size; CompileUnit *cu = context.comp_unit; @@ -60,15 +59,15 @@ AddressResolverFileLine::SearchCallback(SearchFilter &filter, if (log) { StreamString s; // new_bp_loc->GetDescription (&s, lldb::eDescriptionLevelVerbose); - // log->Printf ("Added address: %s\n", s.GetData()); + // LLDB_LOGF(log, "Added address: %s\n", s.GetData()); } } else { - if (log) - log->Printf( - "error: Unable to resolve address at file address 0x%" PRIx64 - " for %s:%d\n", - line_start.GetFileAddress(), - m_file_spec.GetFilename().AsCString("<Unknown>"), m_line_number); + LLDB_LOGF(log, + "error: Unable to resolve address at file address 0x%" PRIx64 + " for %s:%d\n", + line_start.GetFileAddress(), + m_file_spec.GetFilename().AsCString("<Unknown>"), + m_line_number); } } } diff --git a/source/Core/AddressResolverName.cpp b/source/Core/AddressResolverName.cpp index e861368c0a25..6b9b7b2de723 100644 --- a/source/Core/AddressResolverName.cpp +++ b/source/Core/AddressResolverName.cpp @@ -36,7 +36,8 @@ AddressResolverName::AddressResolverName(const char *func_name, : AddressResolver(), m_func_name(func_name), m_class_name(nullptr), m_regex(), m_match_type(type) { if (m_match_type == AddressResolver::Regexp) { - if (!m_regex.Compile(m_func_name.GetStringRef())) { + m_regex = RegularExpression(m_func_name.GetStringRef()); + if (!m_regex.IsValid()) { Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_BREAKPOINTS)); if (log) @@ -46,9 +47,9 @@ AddressResolverName::AddressResolverName(const char *func_name, } } -AddressResolverName::AddressResolverName(RegularExpression &func_regex) +AddressResolverName::AddressResolverName(RegularExpression func_regex) : AddressResolver(), m_func_name(nullptr), m_class_name(nullptr), - m_regex(func_regex), m_match_type(AddressResolver::Regexp) {} + m_regex(std::move(func_regex)), m_match_type(AddressResolver::Regexp) {} AddressResolverName::AddressResolverName(const char *class_name, const char *method, @@ -66,8 +67,7 @@ AddressResolverName::~AddressResolverName() = default; Searcher::CallbackReturn AddressResolverName::SearchCallback(SearchFilter &filter, - SymbolContext &context, Address *addr, - bool containing) { + SymbolContext &context, Address *addr) { SymbolContextList func_list; SymbolContextList sym_list; @@ -86,7 +86,6 @@ AddressResolverName::SearchCallback(SearchFilter &filter, const bool include_symbols = false; const bool include_inlines = true; - const bool append = false; switch (m_match_type) { case AddressResolver::Exact: if (context.module_sp) { @@ -94,7 +93,7 @@ AddressResolverName::SearchCallback(SearchFilter &filter, eSymbolTypeCode, sym_list); context.module_sp->FindFunctions(m_func_name, nullptr, eFunctionNameTypeAuto, include_symbols, - include_inlines, append, func_list); + include_inlines, func_list); } break; @@ -103,7 +102,7 @@ AddressResolverName::SearchCallback(SearchFilter &filter, context.module_sp->FindSymbolsMatchingRegExAndType( m_regex, eSymbolTypeCode, sym_list); context.module_sp->FindFunctions(m_regex, include_symbols, - include_inlines, append, func_list); + include_inlines, func_list); } break; diff --git a/source/Core/Communication.cpp b/source/Core/Communication.cpp index a67cb925d648..0afd897a2093 100644 --- a/source/Core/Communication.cpp +++ b/source/Core/Communication.cpp @@ -46,9 +46,10 @@ Communication::Communication(const char *name) m_callback(nullptr), m_callback_baton(nullptr), m_close_on_eof(true) { - lldb_private::LogIfAnyCategoriesSet( - LIBLLDB_LOG_OBJECT | LIBLLDB_LOG_COMMUNICATION, - "%p Communication::Communication (name = %s)", this, name); + + LLDB_LOG(lldb_private::GetLogIfAnyCategoriesSet(LIBLLDB_LOG_OBJECT | + LIBLLDB_LOG_COMMUNICATION), + "{0} Communication::Communication (name = {1})", this, name); SetEventName(eBroadcastBitDisconnected, "disconnected"); SetEventName(eBroadcastBitReadThreadGotBytes, "got bytes"); @@ -61,10 +62,10 @@ Communication::Communication(const char *name) } Communication::~Communication() { - lldb_private::LogIfAnyCategoriesSet( - LIBLLDB_LOG_OBJECT | LIBLLDB_LOG_COMMUNICATION, - "%p Communication::~Communication (name = %s)", this, - GetBroadcasterName().AsCString()); + LLDB_LOG(lldb_private::GetLogIfAnyCategoriesSet(LIBLLDB_LOG_OBJECT | + LIBLLDB_LOG_COMMUNICATION), + "{0} Communication::~Communication (name = {1})", this, + GetBroadcasterName().AsCString()); Clear(); } @@ -77,9 +78,8 @@ void Communication::Clear() { ConnectionStatus Communication::Connect(const char *url, Status *error_ptr) { Clear(); - lldb_private::LogIfAnyCategoriesSet(LIBLLDB_LOG_COMMUNICATION, - "%p Communication::Connect (url = %s)", - this, url); + LLDB_LOG(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_COMMUNICATION), + "{0} Communication::Connect (url = {1})", this, url); lldb::ConnectionSP connection_sp(m_connection_sp); if (connection_sp) @@ -90,8 +90,8 @@ ConnectionStatus Communication::Connect(const char *url, Status *error_ptr) { } ConnectionStatus Communication::Disconnect(Status *error_ptr) { - lldb_private::LogIfAnyCategoriesSet(LIBLLDB_LOG_COMMUNICATION, - "%p Communication::Disconnect ()", this); + LLDB_LOG(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_COMMUNICATION), + "{0} Communication::Disconnect ()", this); lldb::ConnectionSP connection_sp(m_connection_sp); if (connection_sp) { @@ -173,11 +173,10 @@ size_t Communication::Write(const void *src, size_t src_len, lldb::ConnectionSP connection_sp(m_connection_sp); std::lock_guard<std::mutex> guard(m_write_mutex); - lldb_private::LogIfAnyCategoriesSet( - LIBLLDB_LOG_COMMUNICATION, - "%p Communication::Write (src = %p, src_len = %" PRIu64 - ") connection = %p", - this, src, (uint64_t)src_len, connection_sp.get()); + LLDB_LOG(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_COMMUNICATION), + "{0} Communication::Write (src = {1}, src_len = %" PRIu64 + ") connection = {2}", + this, src, (uint64_t)src_len, connection_sp.get()); if (connection_sp) return connection_sp->Write(src, src_len, status, error_ptr); @@ -195,8 +194,8 @@ bool Communication::StartReadThread(Status *error_ptr) { if (m_read_thread.IsJoinable()) return true; - lldb_private::LogIfAnyCategoriesSet( - LIBLLDB_LOG_COMMUNICATION, "%p Communication::StartReadThread ()", this); + LLDB_LOG(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_COMMUNICATION), + "{0} Communication::StartReadThread ()", this); char thread_name[1024]; snprintf(thread_name, sizeof(thread_name), "<lldb.comm.%s>", @@ -228,8 +227,8 @@ bool Communication::StopReadThread(Status *error_ptr) { if (!m_read_thread.IsJoinable()) return true; - lldb_private::LogIfAnyCategoriesSet( - LIBLLDB_LOG_COMMUNICATION, "%p Communication::StopReadThread ()", this); + LLDB_LOG(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_COMMUNICATION), + "{0} Communication::StopReadThread ()", this); m_read_thread_enabled = false; @@ -270,11 +269,10 @@ size_t Communication::GetCachedBytes(void *dst, size_t dst_len) { void Communication::AppendBytesToCache(const uint8_t *bytes, size_t len, bool broadcast, ConnectionStatus status) { - lldb_private::LogIfAnyCategoriesSet( - LIBLLDB_LOG_COMMUNICATION, - "%p Communication::AppendBytesToCache (src = %p, src_len = %" PRIu64 - ", broadcast = %i)", - this, bytes, (uint64_t)len, broadcast); + LLDB_LOG(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_COMMUNICATION), + "{0} Communication::AppendBytesToCache (src = {1}, src_len = {2}, " + "broadcast = {3})", + this, bytes, (uint64_t)len, broadcast); if ((bytes == nullptr || len == 0) && (status != lldb::eConnectionStatusEndOfFile)) return; @@ -310,8 +308,7 @@ lldb::thread_result_t Communication::ReadThread(lldb::thread_arg_t p) { Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_COMMUNICATION)); - if (log) - log->Printf("%p Communication::ReadThread () thread starting...", p); + LLDB_LOGF(log, "%p Communication::ReadThread () thread starting...", p); uint8_t buf[1024]; @@ -366,7 +363,7 @@ lldb::thread_result_t Communication::ReadThread(lldb::thread_arg_t p) { } log = lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_COMMUNICATION); if (log) - log->Printf("%p Communication::ReadThread () thread exiting...", p); + LLDB_LOGF(log, "%p Communication::ReadThread () thread exiting...", p); comm->m_read_thread_did_exit = true; // Let clients know that this thread is exiting diff --git a/source/Core/CoreProperties.td b/source/Core/CoreProperties.td new file mode 100644 index 000000000000..014927c65c6f --- /dev/null +++ b/source/Core/CoreProperties.td @@ -0,0 +1,118 @@ +include "../../include/lldb/Core/PropertiesBase.td" + +let Definition = "modulelist" in { + def EnableExternalLookup: Property<"enable-external-lookup", "Boolean">, + Global, + DefaultTrue, + Desc<"Control the use of external tools and repositories to locate symbol files. Directories listed in target.debug-file-search-paths and directory of the executable are always checked first for separate debug info files. Then depending on this setting: On macOS, Spotlight would be also used to locate a matching .dSYM bundle based on the UUID of the executable. On NetBSD, directory /usr/libdata/debug would be also searched. On platforms other than NetBSD directory /usr/lib/debug would be also searched.">; + def ClangModulesCachePath: Property<"clang-modules-cache-path", "FileSpec">, + Global, + DefaultStringValue<"">, + Desc<"The path to the clang modules cache directory (-fmodules-cache-path).">; +} + +let Definition = "debugger" in { + def AutoConfirm: Property<"auto-confirm", "Boolean">, + Global, + DefaultFalse, + Desc<"If true all confirmation prompts will receive their default reply.">; + def DisassemblyFormat: Property<"disassembly-format", "FormatEntity">, + Global, + DefaultStringValue<"{${function.initial-function}{${module.file.basename}`}{${function.name-without-args}}:\\\\n}{${function.changed}\\\\n{${module.file.basename}`}{${function.name-without-args}}:\\\\n}{${current-pc-arrow} }${addr-file-or-load}{ <${function.concrete-only-addr-offset-no-padding}>}: ">, + Desc<"The default disassembly format string to use when disassembling instruction sequences.">; + def FrameFormat: Property<"frame-format", "FormatEntity">, + Global, + DefaultStringValue<"frame #${frame.index}: ${ansi.fg.yellow}${frame.pc}${ansi.normal}{ ${module.file.basename}{`${function.name-with-args}{${frame.no-debug}${function.pc-offset}}}}{ at ${ansi.fg.cyan}${line.file.basename}${ansi.normal}:${ansi.fg.yellow}${line.number}${ansi.normal}{:${ansi.fg.yellow}${line.column}${ansi.normal}}}{${function.is-optimized} [opt]}{${frame.is-artificial} [artificial]}\\\\n">, + Desc<"The default frame format string to use when displaying stack frame information for threads.">; + def NotiftVoid: Property<"notify-void", "Boolean">, + Global, + DefaultFalse, + Desc<"Notify the user explicitly if an expression returns void (default: false).">; + def Prompt: Property<"prompt", "String">, + Global, + DefaultEnumValue<"OptionValueString::eOptionEncodeCharacterEscapeSequences">, + DefaultStringValue<"(lldb) ">, + Desc<"The debugger command line prompt displayed for the user.">; + def ScriptLanguage: Property<"script-lang", "Enum">, + Global, + DefaultEnumValue<"eScriptLanguagePython">, + EnumValues<"OptionEnumValues(g_language_enumerators)">, + Desc<"The script language to be used for evaluating user-written scripts.">; + def StopDisassemblyCount: Property<"stop-disassembly-count", "SInt64">, + Global, + DefaultUnsignedValue<4>, + Desc<"The number of disassembly lines to show when displaying a stopped context.">; + def StopDisassemblyDisplay: Property<"stop-disassembly-display", "Enum">, + Global, + DefaultEnumValue<"Debugger::eStopDisassemblyTypeNoDebugInfo">, + EnumValues<"OptionEnumValues(g_show_disassembly_enum_values)">, + Desc<"Control when to display disassembly when displaying a stopped context.">; + def StopLineCountAfter: Property<"stop-line-count-after", "SInt64">, + Global, + DefaultUnsignedValue<3>, + Desc<"The number of sources lines to display that come after the current source line when displaying a stopped context.">; + def StopLineCountBefore: Property<"stop-line-count-before", "SInt64">, + Global, + DefaultUnsignedValue<3>, + Desc<"The number of sources lines to display that come before the current source line when displaying a stopped context.">; + def HighlightSource: Property<"highlight-source", "Boolean">, + Global, + DefaultTrue, + Desc<"If true, LLDB will highlight the displayed source code.">; + def StopShowColumn: Property<"stop-show-column", "Enum">, + DefaultEnumValue<"eStopShowColumnAnsiOrCaret">, + EnumValues<"OptionEnumValues(s_stop_show_column_values)">, + Desc<"If true, LLDB will use the column information from the debug info to mark the current position when displaying a stopped context.">; + def StopShowColumnAnsiPrefix: Property<"stop-show-column-ansi-prefix", "String">, + Global, + DefaultStringValue<"${ansi.underline}">, + Desc<"When displaying the column marker in a color-enabled (i.e. ANSI) terminal, use the ANSI terminal code specified in this format at the immediately before the column to be marked.">; + def StopShowColumnAnsiSuffix: Property<"stop-show-column-ansi-suffix", "String">, + Global, + DefaultStringValue<"${ansi.normal}">, + Desc<"When displaying the column marker in a color-enabled (i.e. ANSI) terminal, use the ANSI terminal code specified in this format immediately after the column to be marked.">; + def TerminalWidth: Property<"term-width", "SInt64">, + Global, + DefaultUnsignedValue<80>, + Desc<"The maximum number of columns to use for displaying text.">; + def ThreadFormat: Property<"thread-format", "FormatEntity">, + Global, + DefaultStringValue<"thread #${thread.index}: tid = ${thread.id%tid}{, ${frame.pc}}{ ${module.file.basename}{`${function.name-with-args}{${frame.no-debug}${function.pc-offset}}}}{ at ${ansi.fg.cyan}${line.file.basename}${ansi.normal}:${ansi.fg.yellow}${line.number}${ansi.normal}{:${ansi.fg.yellow}${line.column}${ansi.normal}}}{, name = ${ansi.fg.green}'${thread.name}'${ansi.normal}}{, queue = ${ansi.fg.green}'${thread.queue}'${ansi.normal}}{, activity = ${ansi.fg.green}'${thread.info.activity.name}'${ansi.normal}}{, ${thread.info.trace_messages} messages}{, stop reason = ${ansi.fg.red}${thread.stop-reason}${ansi.normal}}{\\\\nReturn value: ${thread.return-value}}{\\\\nCompleted expression: ${thread.completed-expression}}\\\\n">, + Desc<"The default thread format string to use when displaying thread information.">; + def ThreadStopFormat: Property<"thread-stop-format", "FormatEntity">, + Global, + DefaultStringValue<"thread #${thread.index}{, name = '${thread.name}'}{, queue = ${ansi.fg.green}'${thread.queue}'${ansi.normal}}{, activity = ${ansi.fg.green}'${thread.info.activity.name}'${ansi.normal}}{, ${thread.info.trace_messages} messages}{, stop reason = ${ansi.fg.red}${thread.stop-reason}${ansi.normal}}{\\\\nReturn value: ${thread.return-value}}{\\\\nCompleted expression: ${thread.completed-expression}}\\\\n">, + Desc<"The default thread format string to use when displaying thread information as part of the stop display.">; + def UseExternalEditor: Property<"use-external-editor", "Boolean">, + Global, + DefaultFalse, + Desc<"Whether to use an external editor or not.">; + def UseColor: Property<"use-color", "Boolean">, + Global, + DefaultTrue, + Desc<"Whether to use Ansi color codes or not.">; + def AutoOneLineSummaries: Property<"auto-one-line-summaries", "Boolean">, + Global, + DefaultTrue, + Desc<"If true, LLDB will automatically display small structs in one-liner format (default: true).">; + def AutoIndent: Property<"auto-indent", "Boolean">, + Global, + DefaultTrue, + Desc<"If true, LLDB will auto indent/outdent code. Currently only supported in the REPL (default: true).">; + def PrintDecls: Property<"print-decls", "Boolean">, + Global, + DefaultTrue, + Desc<"If true, LLDB will print the values of variables declared in an expression. Currently only supported in the REPL (default: true).">; + def TabSize: Property<"tab-size", "UInt64">, + Global, + DefaultUnsignedValue<4>, + Desc<"The tab size to use when indenting code in multi-line input mode (default: 4).">; + def EscapeNonPrintables: Property<"escape-non-printables", "Boolean">, + Global, + DefaultTrue, + Desc<"If true, LLDB will automatically escape non-printable and escape characters when formatting strings.">; + def FrameFormatUnique: Property<"frame-format-unique", "FormatEntity">, + Global, + DefaultStringValue<"frame #${frame.index}: ${ansi.fg.yellow}${frame.pc}${ansi.normal}{ ${module.file.basename}{`${function.name-without-args}{${frame.no-debug}${function.pc-offset}}}}{ at ${ansi.fg.cyan}${line.file.basename}${ansi.normal}:${ansi.fg.yellow}${line.number}${ansi.normal}{:${ansi.fg.yellow}${line.column}${ansi.normal}}}{${function.is-optimized} [opt]}{${frame.is-artificial} [artificial]}\\\\n">, + Desc<"The default frame format string to use when displaying stack frameinformation for threads from thread backtrace unique.">; +} diff --git a/source/Core/Debugger.cpp b/source/Core/Debugger.cpp index 1a69fc582d0c..18397d00dcaa 100644 --- a/source/Core/Debugger.cpp +++ b/source/Core/Debugger.cpp @@ -93,22 +93,47 @@ static DebuggerList *g_debugger_list_ptr = nullptr; // NOTE: intentional leak to avoid issues with C++ destructor chain static constexpr OptionEnumValueElement g_show_disassembly_enum_values[] = { - {Debugger::eStopDisassemblyTypeNever, "never", - "Never show disassembly when displaying a stop context."}, - {Debugger::eStopDisassemblyTypeNoDebugInfo, "no-debuginfo", - "Show disassembly when there is no debug information."}, - {Debugger::eStopDisassemblyTypeNoSource, "no-source", - "Show disassembly when there is no source information, or the source file " - "is missing when displaying a stop context."}, - {Debugger::eStopDisassemblyTypeAlways, "always", - "Always show disassembly when displaying a stop context."} }; + { + Debugger::eStopDisassemblyTypeNever, + "never", + "Never show disassembly when displaying a stop context.", + }, + { + Debugger::eStopDisassemblyTypeNoDebugInfo, + "no-debuginfo", + "Show disassembly when there is no debug information.", + }, + { + Debugger::eStopDisassemblyTypeNoSource, + "no-source", + "Show disassembly when there is no source information, or the source " + "file " + "is missing when displaying a stop context.", + }, + { + Debugger::eStopDisassemblyTypeAlways, + "always", + "Always show disassembly when displaying a stop context.", + }, +}; static constexpr OptionEnumValueElement g_language_enumerators[] = { - {eScriptLanguageNone, "none", "Disable scripting languages."}, - {eScriptLanguagePython, "python", - "Select python as the default scripting language."}, - {eScriptLanguageDefault, "default", - "Select the lldb default as the default scripting language."} }; + { + eScriptLanguageNone, + "none", + "Disable scripting languages.", + }, + { + eScriptLanguagePython, + "python", + "Select python as the default scripting language.", + }, + { + eScriptLanguageDefault, + "default", + "Select the lldb default as the default scripting language.", + }, +}; #define MODULE_WITH_FUNC \ "{ " \ @@ -189,133 +214,39 @@ static constexpr OptionEnumValueElement g_language_enumerators[] = { // without-args}}:\n}{${current-pc-arrow} }{${addr-file-or-load}}: static constexpr OptionEnumValueElement s_stop_show_column_values[] = { - {eStopShowColumnAnsiOrCaret, "ansi-or-caret", - "Highlight the stop column with ANSI terminal codes when color/ANSI mode " - "is enabled; otherwise, fall back to using a text-only caret (^) as if " - "\"caret-only\" mode was selected."}, - {eStopShowColumnAnsi, "ansi", "Highlight the stop column with ANSI " - "terminal codes when running LLDB with " - "color/ANSI enabled."}, - {eStopShowColumnCaret, "caret", - "Highlight the stop column with a caret character (^) underneath the stop " - "column. This method introduces a new line in source listings that " - "display thread stop locations."}, - {eStopShowColumnNone, "none", "Do not highlight the stop column."}}; - -static constexpr PropertyDefinition g_properties[] = { - {"auto-confirm", OptionValue::eTypeBoolean, true, false, nullptr, {}, - "If true all confirmation prompts will receive their default reply."}, - {"disassembly-format", OptionValue::eTypeFormatEntity, true, 0, - DEFAULT_DISASSEMBLY_FORMAT, {}, - "The default disassembly format " - "string to use when disassembling " - "instruction sequences."}, - {"frame-format", OptionValue::eTypeFormatEntity, true, 0, - DEFAULT_FRAME_FORMAT, {}, - "The default frame format string to use " - "when displaying stack frame information " - "for threads."}, - {"notify-void", OptionValue::eTypeBoolean, true, false, nullptr, {}, - "Notify the user explicitly if an expression returns void (default: " - "false)."}, - {"prompt", OptionValue::eTypeString, true, - OptionValueString::eOptionEncodeCharacterEscapeSequences, "(lldb) ", {}, - "The debugger command line prompt displayed for the user."}, - {"script-lang", OptionValue::eTypeEnum, true, eScriptLanguagePython, - nullptr, OptionEnumValues(g_language_enumerators), - "The script language to be used for evaluating user-written scripts."}, - {"stop-disassembly-count", OptionValue::eTypeSInt64, true, 4, nullptr, {}, - "The number of disassembly lines to show when displaying a " - "stopped context."}, - {"stop-disassembly-display", OptionValue::eTypeEnum, true, - Debugger::eStopDisassemblyTypeNoDebugInfo, nullptr, - OptionEnumValues(g_show_disassembly_enum_values), - "Control when to display disassembly when displaying a stopped context."}, - {"stop-line-count-after", OptionValue::eTypeSInt64, true, 3, nullptr, {}, - "The number of sources lines to display that come after the " - "current source line when displaying a stopped context."}, - {"stop-line-count-before", OptionValue::eTypeSInt64, true, 3, nullptr, {}, - "The number of sources lines to display that come before the " - "current source line when displaying a stopped context."}, - {"highlight-source", OptionValue::eTypeBoolean, true, true, nullptr, {}, - "If true, LLDB will highlight the displayed source code."}, - {"stop-show-column", OptionValue::eTypeEnum, false, - eStopShowColumnAnsiOrCaret, nullptr, OptionEnumValues(s_stop_show_column_values), - "If true, LLDB will use the column information from the debug info to " - "mark the current position when displaying a stopped context."}, - {"stop-show-column-ansi-prefix", OptionValue::eTypeString, true, 0, - "${ansi.underline}", {}, - "When displaying the column marker in a color-enabled (i.e. ANSI) " - "terminal, use the ANSI terminal code specified in this format at the " - "immediately before the column to be marked."}, - {"stop-show-column-ansi-suffix", OptionValue::eTypeString, true, 0, - "${ansi.normal}", {}, - "When displaying the column marker in a color-enabled (i.e. ANSI) " - "terminal, use the ANSI terminal code specified in this format " - "immediately after the column to be marked."}, - {"term-width", OptionValue::eTypeSInt64, true, 80, nullptr, {}, - "The maximum number of columns to use for displaying text."}, - {"thread-format", OptionValue::eTypeFormatEntity, true, 0, - DEFAULT_THREAD_FORMAT, {}, - "The default thread format string to use " - "when displaying thread information."}, - {"thread-stop-format", OptionValue::eTypeFormatEntity, true, 0, - DEFAULT_THREAD_STOP_FORMAT, {}, - "The default thread format " - "string to use when displaying thread " - "information as part of the stop display."}, - {"use-external-editor", OptionValue::eTypeBoolean, true, false, nullptr, {}, - "Whether to use an external editor or not."}, - {"use-color", OptionValue::eTypeBoolean, true, true, nullptr, {}, - "Whether to use Ansi color codes or not."}, - {"auto-one-line-summaries", OptionValue::eTypeBoolean, true, true, nullptr, - {}, - "If true, LLDB will automatically display small structs in " - "one-liner format (default: true)."}, - {"auto-indent", OptionValue::eTypeBoolean, true, true, nullptr, {}, - "If true, LLDB will auto indent/outdent code. Currently only supported in " - "the REPL (default: true)."}, - {"print-decls", OptionValue::eTypeBoolean, true, true, nullptr, {}, - "If true, LLDB will print the values of variables declared in an " - "expression. Currently only supported in the REPL (default: true)."}, - {"tab-size", OptionValue::eTypeUInt64, true, 4, nullptr, {}, - "The tab size to use when indenting code in multi-line input mode " - "(default: 4)."}, - {"escape-non-printables", OptionValue::eTypeBoolean, true, true, nullptr, - {}, - "If true, LLDB will automatically escape non-printable and " - "escape characters when formatting strings."}, - {"frame-format-unique", OptionValue::eTypeFormatEntity, true, 0, - DEFAULT_FRAME_FORMAT_NO_ARGS, {}, - "The default frame format string to use when displaying stack frame" - "information for threads from thread backtrace unique."}}; + { + eStopShowColumnAnsiOrCaret, + "ansi-or-caret", + "Highlight the stop column with ANSI terminal codes when color/ANSI " + "mode is enabled; otherwise, fall back to using a text-only caret (^) " + "as if \"caret-only\" mode was selected.", + }, + { + eStopShowColumnAnsi, + "ansi", + "Highlight the stop column with ANSI terminal codes when running LLDB " + "with color/ANSI enabled.", + }, + { + eStopShowColumnCaret, + "caret", + "Highlight the stop column with a caret character (^) underneath the " + "stop column. This method introduces a new line in source listings " + "that display thread stop locations.", + }, + { + eStopShowColumnNone, + "none", + "Do not highlight the stop column.", + }, +}; + +#define LLDB_PROPERTIES_debugger +#include "CoreProperties.inc" enum { - ePropertyAutoConfirm = 0, - ePropertyDisassemblyFormat, - ePropertyFrameFormat, - ePropertyNotiftVoid, - ePropertyPrompt, - ePropertyScriptLanguage, - ePropertyStopDisassemblyCount, - ePropertyStopDisassemblyDisplay, - ePropertyStopLineCountAfter, - ePropertyStopLineCountBefore, - ePropertyHighlightSource, - ePropertyStopShowColumn, - ePropertyStopShowColumnAnsiPrefix, - ePropertyStopShowColumnAnsiSuffix, - ePropertyTerminalWidth, - ePropertyThreadFormat, - ePropertyThreadStopFormat, - ePropertyUseExternalEditor, - ePropertyUseColor, - ePropertyAutoOneLineSummaries, - ePropertyAutoIndent, - ePropertyPrintDecls, - ePropertyTabSize, - ePropertyEscapeNonPrintables, - ePropertyFrameFormatUnique, +#define LLDB_PROPERTIES_debugger +#include "CorePropertiesEnum.inc" }; LoadPluginCallbackType Debugger::g_load_plugin_callback = nullptr; @@ -324,8 +255,16 @@ Status Debugger::SetPropertyValue(const ExecutionContext *exe_ctx, VarSetOperationType op, llvm::StringRef property_path, llvm::StringRef value) { - bool is_load_script = (property_path == "target.load-script-from-symbol-file"); - bool is_escape_non_printables = (property_path == "escape-non-printables"); + bool is_load_script = + (property_path == "target.load-script-from-symbol-file"); + // These properties might change how we visualize data. + bool invalidate_data_vis = (property_path == "escape-non-printables"); + invalidate_data_vis |= + (property_path == "target.max-zero-padding-in-float-format"); + if (invalidate_data_vis) { + DataVisualization::ForceUpdate(); + } + TargetSP target_sp; LoadScriptFromSymFile load_script_old_value; if (is_load_script && exe_ctx->GetTargetSP()) { @@ -336,18 +275,18 @@ Status Debugger::SetPropertyValue(const ExecutionContext *exe_ctx, Status error(Properties::SetPropertyValue(exe_ctx, op, property_path, value)); if (error.Success()) { // FIXME it would be nice to have "on-change" callbacks for properties - if (property_path == g_properties[ePropertyPrompt].name) { + if (property_path == g_debugger_properties[ePropertyPrompt].name) { llvm::StringRef new_prompt = GetPrompt(); - std::string str = lldb_utility::ansi::FormatAnsiTerminalCodes( + std::string str = lldb_private::ansi::FormatAnsiTerminalCodes( new_prompt, GetUseColor()); if (str.length()) new_prompt = str; GetCommandInterpreter().UpdatePrompt(new_prompt); - auto bytes = llvm::make_unique<EventDataBytes>(new_prompt); + auto bytes = std::make_unique<EventDataBytes>(new_prompt); auto prompt_change_event_sp = std::make_shared<Event>( CommandInterpreter::eBroadcastBitResetPrompt, bytes.release()); GetCommandInterpreter().BroadcastEvent(prompt_change_event_sp); - } else if (property_path == g_properties[ePropertyUseColor].name) { + } else if (property_path == g_debugger_properties[ePropertyUseColor].name) { // use-color changed. Ping the prompt so it can reset the ansi terminal // codes. SetPrompt(GetPrompt()); @@ -358,18 +297,14 @@ Status Debugger::SetPropertyValue(const ExecutionContext *exe_ctx, std::list<Status> errors; StreamString feedback_stream; if (!target_sp->LoadScriptingResources(errors, &feedback_stream)) { - StreamFileSP stream_sp(GetErrorFile()); - if (stream_sp) { - for (auto error : errors) { - stream_sp->Printf("%s\n", error.AsCString()); - } - if (feedback_stream.GetSize()) - stream_sp->PutCString(feedback_stream.GetString()); + Stream &s = GetErrorStream(); + for (auto error : errors) { + s.Printf("%s\n", error.AsCString()); } + if (feedback_stream.GetSize()) + s.PutCString(feedback_stream.GetString()); } } - } else if (is_escape_non_printables) { - DataVisualization::ForceUpdate(); } } return error; @@ -378,7 +313,7 @@ Status Debugger::SetPropertyValue(const ExecutionContext *exe_ctx, bool Debugger::GetAutoConfirm() const { const uint32_t idx = ePropertyAutoConfirm; return m_collection_sp->GetPropertyAtIndexAsBoolean( - nullptr, idx, g_properties[idx].default_uint_value != 0); + nullptr, idx, g_debugger_properties[idx].default_uint_value != 0); } const FormatEntity::Entry *Debugger::GetDisassemblyFormat() const { @@ -399,13 +334,13 @@ const FormatEntity::Entry *Debugger::GetFrameFormatUnique() const { bool Debugger::GetNotifyVoid() const { const uint32_t idx = ePropertyNotiftVoid; return m_collection_sp->GetPropertyAtIndexAsBoolean( - nullptr, idx, g_properties[idx].default_uint_value != 0); + nullptr, idx, g_debugger_properties[idx].default_uint_value != 0); } llvm::StringRef Debugger::GetPrompt() const { const uint32_t idx = ePropertyPrompt; return m_collection_sp->GetPropertyAtIndexAsString( - nullptr, idx, g_properties[idx].default_cstr_value); + nullptr, idx, g_debugger_properties[idx].default_cstr_value); } void Debugger::SetPrompt(llvm::StringRef p) { @@ -413,7 +348,7 @@ void Debugger::SetPrompt(llvm::StringRef p) { m_collection_sp->SetPropertyAtIndexAsString(nullptr, idx, p); llvm::StringRef new_prompt = GetPrompt(); std::string str = - lldb_utility::ansi::FormatAnsiTerminalCodes(new_prompt, GetUseColor()); + lldb_private::ansi::FormatAnsiTerminalCodes(new_prompt, GetUseColor()); if (str.length()) new_prompt = str; GetCommandInterpreter().UpdatePrompt(new_prompt); @@ -437,7 +372,7 @@ const FormatEntity::Entry *Debugger::GetThreadStopFormat() const { lldb::ScriptLanguage Debugger::GetScriptLanguage() const { const uint32_t idx = ePropertyScriptLanguage; return (lldb::ScriptLanguage)m_collection_sp->GetPropertyAtIndexAsEnumeration( - nullptr, idx, g_properties[idx].default_uint_value); + nullptr, idx, g_debugger_properties[idx].default_uint_value); } bool Debugger::SetScriptLanguage(lldb::ScriptLanguage script_lang) { @@ -449,7 +384,7 @@ bool Debugger::SetScriptLanguage(lldb::ScriptLanguage script_lang) { uint32_t Debugger::GetTerminalWidth() const { const uint32_t idx = ePropertyTerminalWidth; return m_collection_sp->GetPropertyAtIndexAsSInt64( - nullptr, idx, g_properties[idx].default_uint_value); + nullptr, idx, g_debugger_properties[idx].default_uint_value); } bool Debugger::SetTerminalWidth(uint32_t term_width) { @@ -460,7 +395,7 @@ bool Debugger::SetTerminalWidth(uint32_t term_width) { bool Debugger::GetUseExternalEditor() const { const uint32_t idx = ePropertyUseExternalEditor; return m_collection_sp->GetPropertyAtIndexAsBoolean( - nullptr, idx, g_properties[idx].default_uint_value != 0); + nullptr, idx, g_debugger_properties[idx].default_uint_value != 0); } bool Debugger::SetUseExternalEditor(bool b) { @@ -471,7 +406,7 @@ bool Debugger::SetUseExternalEditor(bool b) { bool Debugger::GetUseColor() const { const uint32_t idx = ePropertyUseColor; return m_collection_sp->GetPropertyAtIndexAsBoolean( - nullptr, idx, g_properties[idx].default_uint_value != 0); + nullptr, idx, g_debugger_properties[idx].default_uint_value != 0); } bool Debugger::SetUseColor(bool b) { @@ -484,13 +419,13 @@ bool Debugger::SetUseColor(bool b) { bool Debugger::GetHighlightSource() const { const uint32_t idx = ePropertyHighlightSource; return m_collection_sp->GetPropertyAtIndexAsBoolean( - nullptr, idx, g_properties[idx].default_uint_value); + nullptr, idx, g_debugger_properties[idx].default_uint_value); } StopShowColumn Debugger::GetStopShowColumn() const { const uint32_t idx = ePropertyStopShowColumn; return (lldb::StopShowColumn)m_collection_sp->GetPropertyAtIndexAsEnumeration( - nullptr, idx, g_properties[idx].default_uint_value); + nullptr, idx, g_debugger_properties[idx].default_uint_value); } llvm::StringRef Debugger::GetStopShowColumnAnsiPrefix() const { @@ -507,20 +442,20 @@ uint32_t Debugger::GetStopSourceLineCount(bool before) const { const uint32_t idx = before ? ePropertyStopLineCountBefore : ePropertyStopLineCountAfter; return m_collection_sp->GetPropertyAtIndexAsSInt64( - nullptr, idx, g_properties[idx].default_uint_value); + nullptr, idx, g_debugger_properties[idx].default_uint_value); } Debugger::StopDisassemblyType Debugger::GetStopDisassemblyDisplay() const { const uint32_t idx = ePropertyStopDisassemblyDisplay; return (Debugger::StopDisassemblyType) m_collection_sp->GetPropertyAtIndexAsEnumeration( - nullptr, idx, g_properties[idx].default_uint_value); + nullptr, idx, g_debugger_properties[idx].default_uint_value); } uint32_t Debugger::GetDisassemblyLineCount() const { const uint32_t idx = ePropertyStopDisassemblyCount; return m_collection_sp->GetPropertyAtIndexAsSInt64( - nullptr, idx, g_properties[idx].default_uint_value); + nullptr, idx, g_debugger_properties[idx].default_uint_value); } bool Debugger::GetAutoOneLineSummaries() const { @@ -556,7 +491,7 @@ bool Debugger::SetPrintDecls(bool b) { uint32_t Debugger::GetTabSize() const { const uint32_t idx = ePropertyTabSize; return m_collection_sp->GetPropertyAtIndexAsUInt64( - nullptr, idx, g_properties[idx].default_uint_value); + nullptr, idx, g_debugger_properties[idx].default_uint_value); } bool Debugger::SetTabSize(uint32_t tab_size) { @@ -717,8 +652,7 @@ void Debugger::Destroy(DebuggerSP &debugger_sp) { } } -DebuggerSP -Debugger::FindDebuggerWithInstanceName(ConstString instance_name) { +DebuggerSP Debugger::FindDebuggerWithInstanceName(ConstString instance_name) { DebuggerSP debugger_sp; if (g_debugger_list_ptr && g_debugger_list_mutex_ptr) { std::lock_guard<std::recursive_mutex> guard(*g_debugger_list_mutex_ptr); @@ -764,16 +698,16 @@ TargetSP Debugger::FindTargetWithProcess(Process *process) { Debugger::Debugger(lldb::LogOutputCallback log_callback, void *baton) : UserID(g_unique_id++), Properties(std::make_shared<OptionValueProperties>()), - m_input_file_sp(std::make_shared<StreamFile>(stdin, false)), - m_output_file_sp(std::make_shared<StreamFile>(stdout, false)), - m_error_file_sp(std::make_shared<StreamFile>(stderr, false)), + m_input_file_sp(std::make_shared<NativeFile>(stdin, false)), + m_output_stream_sp(std::make_shared<StreamFile>(stdout, false)), + m_error_stream_sp(std::make_shared<StreamFile>(stderr, false)), m_input_recorder(nullptr), m_broadcaster_manager_sp(BroadcasterManager::MakeBroadcasterManager()), m_terminal_state(), m_target_list(*this), m_platform_list(), m_listener_sp(Listener::MakeListener("lldb.Debugger")), m_source_manager_up(), m_source_file_cache(), m_command_interpreter_up( - llvm::make_unique<CommandInterpreter>(*this, false)), + std::make_unique<CommandInterpreter>(*this, false)), m_script_interpreter_sp(), m_input_reader_stack(), m_instance_name(), m_loaded_plugins(), m_event_handler_thread(), m_io_handler_thread(), m_sync_broadcaster(nullptr, "lldb.debugger.sync"), @@ -790,7 +724,10 @@ Debugger::Debugger(lldb::LogOutputCallback log_callback, void *baton) assert(default_platform_sp); m_platform_list.Append(default_platform_sp, true); - m_collection_sp->Initialize(g_properties); + m_dummy_target_sp = m_target_list.GetDummyTarget(*this); + assert(m_dummy_target_sp.get() && "Couldn't construct dummy target?"); + + m_collection_sp->Initialize(g_debugger_properties); m_collection_sp->AppendProperty( ConstString("target"), ConstString("Settings specify to debugging targets."), true, @@ -818,7 +755,7 @@ Debugger::Debugger(lldb::LogOutputCallback log_callback, void *baton) if (term && !strcmp(term, "dumb")) SetUseColor(false); // Turn off use-color if we don't write to a terminal with color support. - if (!m_output_file_sp->GetFile().GetIsTerminalWithColors()) + if (!GetOutputFile().GetIsTerminalWithColors()) SetUseColor(false); #if defined(_WIN32) && defined(ENABLE_VIRTUAL_TERMINAL_PROCESSING) @@ -859,8 +796,7 @@ void Debugger::Clear() { // Close the input file _before_ we close the input read communications // class as it does NOT own the input file, our m_input_file does. m_terminal_state.Clear(); - if (m_input_file_sp) - m_input_file_sp->GetFile().Close(); + GetInputFile().Close(); m_command_interpreter_up->Clear(); }); @@ -885,57 +821,29 @@ void Debugger::SetAsyncExecution(bool async_execution) { repro::DataRecorder *Debugger::GetInputRecorder() { return m_input_recorder; } -void Debugger::SetInputFileHandle(FILE *fh, bool tranfer_ownership, - repro::DataRecorder *recorder) { +void Debugger::SetInputFile(FileSP file_sp, repro::DataRecorder *recorder) { + assert(file_sp && file_sp->IsValid()); m_input_recorder = recorder; - if (m_input_file_sp) - m_input_file_sp->GetFile().SetStream(fh, tranfer_ownership); - else - m_input_file_sp = std::make_shared<StreamFile>(fh, tranfer_ownership); - - File &in_file = m_input_file_sp->GetFile(); - if (!in_file.IsValid()) - in_file.SetStream(stdin, true); - + m_input_file_sp = file_sp; // Save away the terminal state if that is relevant, so that we can restore // it in RestoreInputState. SaveInputTerminalState(); } -void Debugger::SetOutputFileHandle(FILE *fh, bool tranfer_ownership) { - if (m_output_file_sp) - m_output_file_sp->GetFile().SetStream(fh, tranfer_ownership); - else - m_output_file_sp = std::make_shared<StreamFile>(fh, tranfer_ownership); - - File &out_file = m_output_file_sp->GetFile(); - if (!out_file.IsValid()) - out_file.SetStream(stdout, false); - - // Do not create the ScriptInterpreter just for setting the output file - // handle as the constructor will know how to do the right thing on its own. - if (ScriptInterpreter *script_interpreter = - GetScriptInterpreter(/*can_create=*/false)) - script_interpreter->ResetOutputFileHandle(fh); +void Debugger::SetOutputFile(FileSP file_sp) { + assert(file_sp && file_sp->IsValid()); + m_output_stream_sp = std::make_shared<StreamFile>(file_sp); } -void Debugger::SetErrorFileHandle(FILE *fh, bool tranfer_ownership) { - if (m_error_file_sp) - m_error_file_sp->GetFile().SetStream(fh, tranfer_ownership); - else - m_error_file_sp = std::make_shared<StreamFile>(fh, tranfer_ownership); - - File &err_file = m_error_file_sp->GetFile(); - if (!err_file.IsValid()) - err_file.SetStream(stderr, false); +void Debugger::SetErrorFile(FileSP file_sp) { + assert(file_sp && file_sp->IsValid()); + m_error_stream_sp = std::make_shared<StreamFile>(file_sp); } void Debugger::SaveInputTerminalState() { - if (m_input_file_sp) { - File &in_file = m_input_file_sp->GetFile(); - if (in_file.GetDescriptor() != File::kInvalidDescriptor) - m_terminal_state.Save(in_file.GetDescriptor(), true); - } + int fd = GetInputFile().GetDescriptor(); + if (fd != File::kInvalidDescriptor) + m_terminal_state.Save(fd, true); } void Debugger::RestoreInputTerminalState() { m_terminal_state.Restore(); } @@ -1016,8 +924,9 @@ bool Debugger::CheckTopIOHandlerTypes(IOHandler::Type top_type, } void Debugger::PrintAsync(const char *s, size_t len, bool is_stdout) { - lldb::StreamFileSP stream = is_stdout ? GetOutputFile() : GetErrorFile(); - m_input_reader_stack.PrintAsync(stream.get(), s, len); + lldb_private::StreamFile &stream = + is_stdout ? GetOutputStream() : GetErrorStream(); + m_input_reader_stack.PrintAsync(&stream, s, len); } ConstString Debugger::GetTopIOHandlerControlSequence(char ch) { @@ -1054,8 +963,7 @@ void Debugger::RunIOHandler(const IOHandlerSP &reader_sp) { } } -void Debugger::AdoptTopIOHandlerFilesIfInvalid(StreamFileSP &in, - StreamFileSP &out, +void Debugger::AdoptTopIOHandlerFilesIfInvalid(FileSP &in, StreamFileSP &out, StreamFileSP &err) { // Before an IOHandler runs, it must have in/out/err streams. This function // is called when one ore more of the streams are nullptr. We use the top @@ -1065,37 +973,34 @@ void Debugger::AdoptTopIOHandlerFilesIfInvalid(StreamFileSP &in, std::lock_guard<std::recursive_mutex> guard(m_input_reader_stack.GetMutex()); IOHandlerSP top_reader_sp(m_input_reader_stack.Top()); // If no STDIN has been set, then set it appropriately - if (!in) { + if (!in || !in->IsValid()) { if (top_reader_sp) - in = top_reader_sp->GetInputStreamFile(); + in = top_reader_sp->GetInputFileSP(); else - in = GetInputFile(); - + in = GetInputFileSP(); // If there is nothing, use stdin if (!in) - in = std::make_shared<StreamFile>(stdin, false); + in = std::make_shared<NativeFile>(stdin, false); } // If no STDOUT has been set, then set it appropriately - if (!out) { + if (!out || !out->GetFile().IsValid()) { if (top_reader_sp) - out = top_reader_sp->GetOutputStreamFile(); + out = top_reader_sp->GetOutputStreamFileSP(); else - out = GetOutputFile(); - + out = GetOutputStreamSP(); // If there is nothing, use stdout if (!out) out = std::make_shared<StreamFile>(stdout, false); } // If no STDERR has been set, then set it appropriately - if (!err) { + if (!err || !err->GetFile().IsValid()) { if (top_reader_sp) - err = top_reader_sp->GetErrorStreamFile(); + err = top_reader_sp->GetErrorStreamFileSP(); else - err = GetErrorFile(); - + err = GetErrorStreamSP(); // If there is nothing, use stderr if (!err) - err = std::make_shared<StreamFile>(stdout, false); + err = std::make_shared<StreamFile>(stderr, false); } } @@ -1263,15 +1168,15 @@ bool Debugger::EnableLog(llvm::StringRef channel, LLDB_LOG_OPTION_PREPEND_TIMESTAMP | LLDB_LOG_OPTION_PREPEND_THREAD_NAME; } else if (log_file.empty()) { log_stream_sp = std::make_shared<llvm::raw_fd_ostream>( - GetOutputFile()->GetFile().GetDescriptor(), !should_close, unbuffered); + GetOutputFile().GetDescriptor(), !should_close, unbuffered); } else { auto pos = m_log_streams.find(log_file); if (pos != m_log_streams.end()) log_stream_sp = pos->second.lock(); if (!log_stream_sp) { - llvm::sys::fs::OpenFlags flags = llvm::sys::fs::F_Text; + llvm::sys::fs::OpenFlags flags = llvm::sys::fs::OF_Text; if (log_options & LLDB_LOG_OPTION_APPEND) - flags |= llvm::sys::fs::F_Append; + flags |= llvm::sys::fs::OF_Append; int FD; if (std::error_code ec = llvm::sys::fs::openFileForWrite( log_file, FD, llvm::sys::fs::CD_CreateAlways, flags)) { @@ -1308,7 +1213,7 @@ ScriptInterpreter *Debugger::GetScriptInterpreter(bool can_create) { SourceManager &Debugger::GetSourceManager() { if (!m_source_manager_up) - m_source_manager_up = llvm::make_unique<SourceManager>(shared_from_this()); + m_source_manager_up = std::make_unique<SourceManager>(shared_from_this()); return *m_source_manager_up; } @@ -1360,60 +1265,23 @@ void Debugger::HandleBreakpointEvent(const EventSP &event_sp) { // } } -size_t Debugger::GetProcessSTDOUT(Process *process, Stream *stream) { - size_t total_bytes = 0; - if (stream == nullptr) - stream = GetOutputFile().get(); +void Debugger::FlushProcessOutput(Process &process, bool flush_stdout, + bool flush_stderr) { + const auto &flush = [&](Stream &stream, + size_t (Process::*get)(char *, size_t, Status &)) { + Status error; + size_t len; + char buffer[1024]; + while ((len = (process.*get)(buffer, sizeof(buffer), error)) > 0) + stream.Write(buffer, len); + stream.Flush(); + }; - if (stream) { - // The process has stuff waiting for stdout; get it and write it out to the - // appropriate place. - if (process == nullptr) { - TargetSP target_sp = GetTargetList().GetSelectedTarget(); - if (target_sp) - process = target_sp->GetProcessSP().get(); - } - if (process) { - Status error; - size_t len; - char stdio_buffer[1024]; - while ((len = process->GetSTDOUT(stdio_buffer, sizeof(stdio_buffer), - error)) > 0) { - stream->Write(stdio_buffer, len); - total_bytes += len; - } - } - stream->Flush(); - } - return total_bytes; -} - -size_t Debugger::GetProcessSTDERR(Process *process, Stream *stream) { - size_t total_bytes = 0; - if (stream == nullptr) - stream = GetOutputFile().get(); - - if (stream) { - // The process has stuff waiting for stderr; get it and write it out to the - // appropriate place. - if (process == nullptr) { - TargetSP target_sp = GetTargetList().GetSelectedTarget(); - if (target_sp) - process = target_sp->GetProcessSP().get(); - } - if (process) { - Status error; - size_t len; - char stdio_buffer[1024]; - while ((len = process->GetSTDERR(stdio_buffer, sizeof(stdio_buffer), - error)) > 0) { - stream->Write(stdio_buffer, len); - total_bytes += len; - } - } - stream->Flush(); - } - return total_bytes; + std::lock_guard<std::mutex> guard(m_output_flush_mutex); + if (flush_stdout) + flush(*GetAsyncOutputStream(), &Process::GetSTDOUT); + if (flush_stderr) + flush(*GetAsyncErrorStream(), &Process::GetSTDERR); } // This function handles events that were broadcast by the process. @@ -1453,15 +1321,9 @@ void Debugger::HandleProcessEvent(const EventSP &event_sp) { pop_process_io_handler); } - // Now display and STDOUT - if (got_stdout || got_state_changed) { - GetProcessSTDOUT(process_sp.get(), output_stream_sp.get()); - } - - // Now display and STDERR - if (got_stderr || got_state_changed) { - GetProcessSTDERR(process_sp.get(), error_stream_sp.get()); - } + // Now display STDOUT and STDERR + FlushProcessOutput(*process_sp, got_stdout || got_state_changed, + got_stderr || got_state_changed); // Give structured data events an opportunity to display. if (got_structured_data) { @@ -1638,8 +1500,9 @@ bool Debugger::StartEventHandlerThread() { eBroadcastBitEventThreadIsListening); auto thread_name = - full_name.GetLength() < llvm::get_max_thread_name_length() ? - full_name.AsCString() : "dbg.evt-handler"; + full_name.GetLength() < llvm::get_max_thread_name_length() + ? full_name.AsCString() + : "dbg.evt-handler"; // Use larger 8MB stack for this thread llvm::Expected<HostThread> event_handler_thread = @@ -1700,8 +1563,7 @@ bool Debugger::StartIOHandlerThread() { void Debugger::StopIOHandlerThread() { if (m_io_handler_thread.IsJoinable()) { - if (m_input_file_sp) - m_input_file_sp->GetFile().Close(); + GetInputFile().Close(); m_io_handler_thread.Join(nullptr); } } @@ -1714,10 +1576,6 @@ void Debugger::JoinIOHandlerThread() { } } -Target *Debugger::GetDummyTarget() { - return m_target_list.GetDummyTarget(*this).get(); -} - Target *Debugger::GetSelectedOrDummyTarget(bool prefer_dummy) { Target *target = nullptr; if (!prefer_dummy) { @@ -1734,13 +1592,11 @@ Status Debugger::RunREPL(LanguageType language, const char *repl_options) { FileSpec repl_executable; if (language == eLanguageTypeUnknown) { - std::set<LanguageType> repl_languages; - - Language::GetLanguagesSupportingREPLs(repl_languages); + LanguageSet repl_languages = Language::GetLanguagesSupportingREPLs(); - if (repl_languages.size() == 1) { - language = *repl_languages.begin(); - } else if (repl_languages.empty()) { + if (auto single_lang = repl_languages.GetSingularLanguage()) { + language = *single_lang; + } else if (repl_languages.Empty()) { err.SetErrorStringWithFormat( "LLDB isn't configured with REPL support for any languages."); return err; diff --git a/source/Core/Disassembler.cpp b/source/Core/Disassembler.cpp index af7cf82d470a..89ae25cbad64 100644 --- a/source/Core/Disassembler.cpp +++ b/source/Core/Disassembler.cpp @@ -158,52 +158,58 @@ size_t Disassembler::Disassemble(Debugger &debugger, const ArchSpec &arch, return success_count; } -bool Disassembler::Disassemble(Debugger &debugger, const ArchSpec &arch, - const char *plugin_name, const char *flavor, - const ExecutionContext &exe_ctx, - ConstString name, Module *module, - uint32_t num_instructions, - bool mixed_source_and_assembly, - uint32_t num_mixed_context_lines, - uint32_t options, Stream &strm) { +bool Disassembler::Disassemble( + Debugger &debugger, const ArchSpec &arch, const char *plugin_name, + const char *flavor, const ExecutionContext &exe_ctx, ConstString name, + Module *module, uint32_t num_instructions, bool mixed_source_and_assembly, + uint32_t num_mixed_context_lines, uint32_t options, Stream &strm) { + // If no name is given there's nothing to disassemble. + if (!name) + return false; + + const bool include_symbols = true; + const bool include_inlines = true; + + // Find functions matching the given name. SymbolContextList sc_list; - if (name) { - const bool include_symbols = true; - const bool include_inlines = true; - if (module) { - module->FindFunctions(name, nullptr, eFunctionNameTypeAuto, - include_symbols, include_inlines, true, sc_list); - } else if (exe_ctx.GetTargetPtr()) { - exe_ctx.GetTargetPtr()->GetImages().FindFunctions( - name, eFunctionNameTypeAuto, include_symbols, include_inlines, false, - sc_list); - } + if (module) { + module->FindFunctions(name, nullptr, eFunctionNameTypeAuto, include_symbols, + include_inlines, sc_list); + } else if (exe_ctx.GetTargetPtr()) { + exe_ctx.GetTargetPtr()->GetImages().FindFunctions( + name, eFunctionNameTypeAuto, include_symbols, include_inlines, sc_list); } - if (sc_list.GetSize()) { - return Disassemble(debugger, arch, plugin_name, flavor, exe_ctx, sc_list, - num_instructions, mixed_source_and_assembly, - num_mixed_context_lines, options, strm); - } - return false; + // If no functions were found there's nothing to disassemble. + if (sc_list.IsEmpty()) + return false; + + return Disassemble(debugger, arch, plugin_name, flavor, exe_ctx, sc_list, + num_instructions, mixed_source_and_assembly, + num_mixed_context_lines, options, strm); } lldb::DisassemblerSP Disassembler::DisassembleRange( const ArchSpec &arch, const char *plugin_name, const char *flavor, const ExecutionContext &exe_ctx, const AddressRange &range, bool prefer_file_cache) { - lldb::DisassemblerSP disasm_sp; - if (range.GetByteSize() > 0 && range.GetBaseAddress().IsValid()) { - disasm_sp = Disassembler::FindPluginForTarget(exe_ctx.GetTargetSP(), arch, - flavor, plugin_name); - - if (disasm_sp) { - size_t bytes_disassembled = disasm_sp->ParseInstructions( - &exe_ctx, range, nullptr, prefer_file_cache); - if (bytes_disassembled == 0) - disasm_sp.reset(); - } - } + if (range.GetByteSize() <= 0) + return {}; + + if (!range.GetBaseAddress().IsValid()) + return {}; + + lldb::DisassemblerSP disasm_sp = Disassembler::FindPluginForTarget( + exe_ctx.GetTargetSP(), arch, flavor, plugin_name); + + if (!disasm_sp) + return {}; + + const size_t bytes_disassembled = + disasm_sp->ParseInstructions(&exe_ctx, range, nullptr, prefer_file_cache); + if (bytes_disassembled == 0) + return {}; + return disasm_sp; } @@ -212,20 +218,20 @@ Disassembler::DisassembleBytes(const ArchSpec &arch, const char *plugin_name, const char *flavor, const Address &start, const void *src, size_t src_len, uint32_t num_instructions, bool data_from_file) { - lldb::DisassemblerSP disasm_sp; + if (!src) + return {}; - if (src) { - disasm_sp = Disassembler::FindPlugin(arch, flavor, plugin_name); + lldb::DisassemblerSP disasm_sp = + Disassembler::FindPlugin(arch, flavor, plugin_name); - if (disasm_sp) { - DataExtractor data(src, src_len, arch.GetByteOrder(), - arch.GetAddressByteSize()); + if (!disasm_sp) + return {}; - (void)disasm_sp->DecodeInstructions(start, data, 0, num_instructions, - false, data_from_file); - } - } + DataExtractor data(src, src_len, arch.GetByteOrder(), + arch.GetAddressByteSize()); + (void)disasm_sp->DecodeInstructions(start, data, 0, num_instructions, false, + data_from_file); return disasm_sp; } @@ -237,27 +243,28 @@ bool Disassembler::Disassemble(Debugger &debugger, const ArchSpec &arch, bool mixed_source_and_assembly, uint32_t num_mixed_context_lines, uint32_t options, Stream &strm) { - if (disasm_range.GetByteSize()) { - lldb::DisassemblerSP disasm_sp(Disassembler::FindPluginForTarget( - exe_ctx.GetTargetSP(), arch, flavor, plugin_name)); - - if (disasm_sp) { - AddressRange range; - ResolveAddress(exe_ctx, disasm_range.GetBaseAddress(), - range.GetBaseAddress()); - range.SetByteSize(disasm_range.GetByteSize()); - const bool prefer_file_cache = false; - size_t bytes_disassembled = disasm_sp->ParseInstructions( - &exe_ctx, range, &strm, prefer_file_cache); - if (bytes_disassembled == 0) - return false; - - return PrintInstructions(disasm_sp.get(), debugger, arch, exe_ctx, - num_instructions, mixed_source_and_assembly, - num_mixed_context_lines, options, strm); - } - } - return false; + if (!disasm_range.GetByteSize()) + return false; + + lldb::DisassemblerSP disasm_sp(Disassembler::FindPluginForTarget( + exe_ctx.GetTargetSP(), arch, flavor, plugin_name)); + + if (!disasm_sp) + return false; + + AddressRange range; + ResolveAddress(exe_ctx, disasm_range.GetBaseAddress(), + range.GetBaseAddress()); + range.SetByteSize(disasm_range.GetByteSize()); + const bool prefer_file_cache = false; + size_t bytes_disassembled = + disasm_sp->ParseInstructions(&exe_ctx, range, &strm, prefer_file_cache); + if (bytes_disassembled == 0) + return false; + + return PrintInstructions(disasm_sp.get(), debugger, arch, exe_ctx, + num_instructions, mixed_source_and_assembly, + num_mixed_context_lines, options, strm); } bool Disassembler::Disassemble(Debugger &debugger, const ArchSpec &arch, @@ -268,42 +275,51 @@ bool Disassembler::Disassemble(Debugger &debugger, const ArchSpec &arch, bool mixed_source_and_assembly, uint32_t num_mixed_context_lines, uint32_t options, Stream &strm) { - if (num_instructions > 0) { - lldb::DisassemblerSP disasm_sp(Disassembler::FindPluginForTarget( - exe_ctx.GetTargetSP(), arch, flavor, plugin_name)); - if (disasm_sp) { - Address addr; - ResolveAddress(exe_ctx, start_address, addr); - const bool prefer_file_cache = false; - size_t bytes_disassembled = disasm_sp->ParseInstructions( - &exe_ctx, addr, num_instructions, prefer_file_cache); - if (bytes_disassembled == 0) - return false; - return PrintInstructions(disasm_sp.get(), debugger, arch, exe_ctx, - num_instructions, mixed_source_and_assembly, - num_mixed_context_lines, options, strm); - } - } - return false; + if (num_instructions == 0) + return false; + + lldb::DisassemblerSP disasm_sp(Disassembler::FindPluginForTarget( + exe_ctx.GetTargetSP(), arch, flavor, plugin_name)); + if (!disasm_sp) + return false; + + Address addr; + ResolveAddress(exe_ctx, start_address, addr); + + const bool prefer_file_cache = false; + size_t bytes_disassembled = disasm_sp->ParseInstructions( + &exe_ctx, addr, num_instructions, prefer_file_cache); + if (bytes_disassembled == 0) + return false; + + return PrintInstructions(disasm_sp.get(), debugger, arch, exe_ctx, + num_instructions, mixed_source_and_assembly, + num_mixed_context_lines, options, strm); } Disassembler::SourceLine Disassembler::GetFunctionDeclLineEntry(const SymbolContext &sc) { + if (!sc.function) + return {}; + + if (!sc.line_entry.IsValid()) + return {}; + + LineEntry prologue_end_line = sc.line_entry; + FileSpec func_decl_file; + uint32_t func_decl_line; + sc.function->GetStartLineSourceInfo(func_decl_file, func_decl_line); + + if (func_decl_file != prologue_end_line.file && + func_decl_file != prologue_end_line.original_file) + return {}; + SourceLine decl_line; - if (sc.function && sc.line_entry.IsValid()) { - LineEntry prologue_end_line = sc.line_entry; - FileSpec func_decl_file; - uint32_t func_decl_line; - sc.function->GetStartLineSourceInfo(func_decl_file, func_decl_line); - if (func_decl_file == prologue_end_line.file || - func_decl_file == prologue_end_line.original_file) { - decl_line.file = func_decl_file; - decl_line.line = func_decl_line; - // TODO do we care about column on these entries? If so, we need to - // plumb that through GetStartLineSourceInfo. - decl_line.column = 0; - } - } + decl_line.file = func_decl_file; + decl_line.line = func_decl_line; + // TODO: Do we care about column on these entries? If so, we need to plumb + // that through GetStartLineSourceInfo. + decl_line.column = 0; return decl_line; } @@ -355,12 +371,9 @@ bool Disassembler::ElideMixedSourceAndDisassemblyLine( const char *function_name = sc.GetFunctionName(Mangled::ePreferDemangledWithoutArguments) .GetCString(); - if (function_name) { - RegularExpression::Match regex_match(1); - if (avoid_regex->Execute(function_name, ®ex_match)) { - // skip this source line - return true; - } + if (function_name && avoid_regex->Execute(function_name)) { + // skip this source line + return true; } } // don't skip this source line @@ -793,10 +806,9 @@ OptionValueSP Instruction::ReadArray(FILE *in_file, Stream *out_stream, std::string value; static RegularExpression g_reg_exp( llvm::StringRef("^[ \t]*([^ \t]+)[ \t]*$")); - RegularExpression::Match regex_match(1); - bool reg_exp_success = g_reg_exp.Execute(line, ®ex_match); - if (reg_exp_success) - regex_match.GetMatchAtIndex(line.c_str(), 1, value); + llvm::SmallVector<llvm::StringRef, 2> matches; + if (g_reg_exp.Execute(line, &matches)) + value = matches[1].str(); else value = line; @@ -856,14 +868,15 @@ OptionValueSP Instruction::ReadDictionary(FILE *in_file, Stream *out_stream) { if (!line.empty()) { static RegularExpression g_reg_exp(llvm::StringRef( "^[ \t]*([a-zA-Z_][a-zA-Z0-9_]*)[ \t]*=[ \t]*(.*)[ \t]*$")); - RegularExpression::Match regex_match(2); - bool reg_exp_success = g_reg_exp.Execute(line, ®ex_match); + llvm::SmallVector<llvm::StringRef, 3> matches; + + bool reg_exp_success = g_reg_exp.Execute(line, &matches); std::string key; std::string value; if (reg_exp_success) { - regex_match.GetMatchAtIndex(line.c_str(), 1, key); - regex_match.GetMatchAtIndex(line.c_str(), 2, value); + key = matches[1].str(); + value = matches[2].str(); } else { out_stream->Printf("Instruction::ReadDictionary: Failure executing " "regular expression.\n"); diff --git a/source/Core/DumpDataExtractor.cpp b/source/Core/DumpDataExtractor.cpp index aa84370e223a..12e98de2675c 100644 --- a/source/Core/DumpDataExtractor.cpp +++ b/source/Core/DumpDataExtractor.cpp @@ -14,20 +14,18 @@ #include "lldb/Core/Address.h" #include "lldb/Core/Disassembler.h" #include "lldb/Core/ModuleList.h" -#include "lldb/Symbol/ClangASTContext.h" #include "lldb/Target/ExecutionContext.h" #include "lldb/Target/ExecutionContextScope.h" #include "lldb/Target/SectionLoadList.h" #include "lldb/Target/Target.h" #include "lldb/Utility/DataExtractor.h" +#include "lldb/Utility/Log.h" #include "lldb/Utility/Stream.h" -#include "clang/AST/ASTContext.h" -#include "clang/AST/CanonicalType.h" - #include "llvm/ADT/APFloat.h" #include "llvm/ADT/APInt.h" #include "llvm/ADT/ArrayRef.h" +#include "llvm/ADT/Optional.h" #include "llvm/ADT/SmallVector.h" #include <limits> @@ -64,8 +62,12 @@ static float half2float(uint16_t half) { return u.f * ldexpf(1, -112); } -static bool GetAPInt(const DataExtractor &data, lldb::offset_t *offset_ptr, - lldb::offset_t byte_size, llvm::APInt &result) { +static llvm::Optional<llvm::APInt> GetAPInt(const DataExtractor &data, + lldb::offset_t *offset_ptr, + lldb::offset_t byte_size) { + if (byte_size == 0) + return llvm::None; + llvm::SmallVector<uint64_t, 2> uint64_array; lldb::offset_t bytes_left = byte_size; uint64_t u64; @@ -81,8 +83,7 @@ static bool GetAPInt(const DataExtractor &data, lldb::offset_t *offset_ptr, } uint64_array.push_back(u64); } - result = llvm::APInt(byte_size * 8, llvm::ArrayRef<uint64_t>(uint64_array)); - return true; + return llvm::APInt(byte_size * 8, llvm::ArrayRef<uint64_t>(uint64_array)); } else if (byte_order == lldb::eByteOrderBig) { lldb::offset_t be_offset = *offset_ptr + byte_size; lldb::offset_t temp_offset; @@ -101,18 +102,17 @@ static bool GetAPInt(const DataExtractor &data, lldb::offset_t *offset_ptr, uint64_array.push_back(u64); } *offset_ptr += byte_size; - result = llvm::APInt(byte_size * 8, llvm::ArrayRef<uint64_t>(uint64_array)); - return true; + return llvm::APInt(byte_size * 8, llvm::ArrayRef<uint64_t>(uint64_array)); } - return false; + return llvm::None; } static lldb::offset_t DumpAPInt(Stream *s, const DataExtractor &data, lldb::offset_t offset, lldb::offset_t byte_size, bool is_signed, unsigned radix) { - llvm::APInt apint; - if (GetAPInt(data, &offset, byte_size, apint)) { - std::string apint_str(apint.toString(radix, is_signed)); + llvm::Optional<llvm::APInt> apint = GetAPInt(data, &offset, byte_size); + if (apint.hasValue()) { + std::string apint_str(apint.getValue().toString(radix, is_signed)); switch (radix) { case 2: s->Write("0b", 2); @@ -555,49 +555,31 @@ lldb::offset_t lldb_private::DumpDataExtractor( if (exe_scope) target_sp = exe_scope->CalculateTarget(); if (target_sp) { - ClangASTContext *clang_ast = target_sp->GetScratchClangASTContext(); - if (clang_ast) { - clang::ASTContext *ast = clang_ast->getASTContext(); - if (ast) { - llvm::SmallVector<char, 256> sv; - // Show full precision when printing float values - const unsigned format_precision = 0; - const unsigned format_max_padding = 100; - size_t item_bit_size = item_byte_size * 8; - - if (item_bit_size == ast->getTypeSize(ast->FloatTy)) { - llvm::APInt apint(item_bit_size, - DE.GetMaxU64(&offset, item_byte_size)); - llvm::APFloat apfloat(ast->getFloatTypeSemantics(ast->FloatTy), - apint); - apfloat.toString(sv, format_precision, format_max_padding); - } else if (item_bit_size == ast->getTypeSize(ast->DoubleTy)) { - llvm::APInt apint; - if (GetAPInt(DE, &offset, item_byte_size, apint)) { - llvm::APFloat apfloat(ast->getFloatTypeSemantics(ast->DoubleTy), - apint); - apfloat.toString(sv, format_precision, format_max_padding); - } - } else if (item_bit_size == ast->getTypeSize(ast->LongDoubleTy)) { - const auto &semantics = - ast->getFloatTypeSemantics(ast->LongDoubleTy); - - offset_t byte_size = item_byte_size; - if (&semantics == &llvm::APFloatBase::x87DoubleExtended()) - byte_size = (llvm::APFloat::getSizeInBits(semantics) + 7) / 8; - - llvm::APInt apint; - if (GetAPInt(DE, &offset, byte_size, apint)) { - llvm::APFloat apfloat(semantics, apint); - apfloat.toString(sv, format_precision, format_max_padding); - } - } else if (item_bit_size == ast->getTypeSize(ast->HalfTy)) { - llvm::APInt apint(item_bit_size, DE.GetU16(&offset)); - llvm::APFloat apfloat(ast->getFloatTypeSemantics(ast->HalfTy), - apint); - apfloat.toString(sv, format_precision, format_max_padding); - } - + auto type_system_or_err = + target_sp->GetScratchTypeSystemForLanguage(eLanguageTypeC); + if (!type_system_or_err) { + llvm::consumeError(type_system_or_err.takeError()); + } else { + auto &type_system = *type_system_or_err; + llvm::SmallVector<char, 256> sv; + // Show full precision when printing float values + const unsigned format_precision = 0; + const unsigned format_max_padding = + target_sp->GetMaxZeroPaddingInFloatFormat(); + + const auto &semantics = + type_system.GetFloatTypeSemantics(item_byte_size); + + // Recalculate the byte size in case of a difference. This is possible + // when item_byte_size is 16 (128-bit), because you could get back the + // x87DoubleExtended semantics which has a byte size of 10 (80-bit). + const size_t semantics_byte_size = + (llvm::APFloat::getSizeInBits(semantics) + 7) / 8; + llvm::Optional<llvm::APInt> apint = + GetAPInt(DE, &offset, semantics_byte_size); + if (apint.hasValue()) { + llvm::APFloat apfloat(semantics, apint.getValue()); + apfloat.toString(sv, format_precision, format_max_padding); if (!sv.empty()) { s->Printf("%*.*s", (int)sv.size(), (int)sv.size(), sv.data()); used_upfloat = true; diff --git a/source/Core/FileLineResolver.cpp b/source/Core/FileLineResolver.cpp index 3cba1c7e8143..01df295398a8 100644 --- a/source/Core/FileLineResolver.cpp +++ b/source/Core/FileLineResolver.cpp @@ -33,7 +33,7 @@ FileLineResolver::~FileLineResolver() {} Searcher::CallbackReturn FileLineResolver::SearchCallback(SearchFilter &filter, SymbolContext &context, - Address *addr, bool containing) { + Address *addr) { CompileUnit *cu = context.comp_unit; if (m_inlines || diff --git a/source/Core/FormatEntity.cpp b/source/Core/FormatEntity.cpp index 1ffbed2cd64e..c90828f40989 100644 --- a/source/Core/FormatEntity.cpp +++ b/source/Core/FormatEntity.cpp @@ -514,24 +514,24 @@ static bool ScanBracketedRange(llvm::StringRef subpath, close_bracket_index = llvm::StringRef::npos; const size_t open_bracket_index = subpath.find('['); if (open_bracket_index == llvm::StringRef::npos) { - if (log) - log->Printf("[ScanBracketedRange] no bracketed range, skipping entirely"); + LLDB_LOGF(log, + "[ScanBracketedRange] no bracketed range, skipping entirely"); return false; } close_bracket_index = subpath.find(']', open_bracket_index + 1); if (close_bracket_index == llvm::StringRef::npos) { - if (log) - log->Printf("[ScanBracketedRange] no bracketed range, skipping entirely"); + LLDB_LOGF(log, + "[ScanBracketedRange] no bracketed range, skipping entirely"); return false; } else { var_name_final_if_array_range = subpath.data() + open_bracket_index; if (close_bracket_index - open_bracket_index == 1) { - if (log) - log->Printf( - "[ScanBracketedRange] '[]' detected.. going from 0 to end of data"); + LLDB_LOGF( + log, + "[ScanBracketedRange] '[]' detected.. going from 0 to end of data"); index_lower = 0; } else { const size_t separator_index = subpath.find('-', open_bracket_index + 1); @@ -540,22 +540,21 @@ static bool ScanBracketedRange(llvm::StringRef subpath, const char *index_lower_cstr = subpath.data() + open_bracket_index + 1; index_lower = ::strtoul(index_lower_cstr, nullptr, 0); index_higher = index_lower; - if (log) - log->Printf("[ScanBracketedRange] [%" PRId64 - "] detected, high index is same", - index_lower); + LLDB_LOGF(log, + "[ScanBracketedRange] [%" PRId64 + "] detected, high index is same", + index_lower); } else { const char *index_lower_cstr = subpath.data() + open_bracket_index + 1; const char *index_higher_cstr = subpath.data() + separator_index + 1; index_lower = ::strtoul(index_lower_cstr, nullptr, 0); index_higher = ::strtoul(index_higher_cstr, nullptr, 0); - if (log) - log->Printf("[ScanBracketedRange] [%" PRId64 "-%" PRId64 "] detected", - index_lower, index_higher); + LLDB_LOGF(log, + "[ScanBracketedRange] [%" PRId64 "-%" PRId64 "] detected", + index_lower, index_higher); } if (index_lower > index_higher && index_higher > 0) { - if (log) - log->Printf("[ScanBracketedRange] swapping indices"); + LLDB_LOGF(log, "[ScanBracketedRange] swapping indices"); const int64_t temp = index_lower; index_lower = index_higher; index_higher = temp; @@ -627,9 +626,8 @@ static ValueObjectSP ExpandIndexedExpression(ValueObject *valobj, size_t index, const char *ptr_deref_format = "[%d]"; std::string ptr_deref_buffer(10, 0); ::sprintf(&ptr_deref_buffer[0], ptr_deref_format, index); - if (log) - log->Printf("[ExpandIndexedExpression] name to deref: %s", - ptr_deref_buffer.c_str()); + LLDB_LOGF(log, "[ExpandIndexedExpression] name to deref: %s", + ptr_deref_buffer.c_str()); ValueObject::GetValueForExpressionPathOptions options; ValueObject::ExpressionPathEndResultType final_value_type; ValueObject::ExpressionPathScanEndReason reason_to_stop; @@ -640,15 +638,15 @@ static ValueObjectSP ExpandIndexedExpression(ValueObject *valobj, size_t index, ptr_deref_buffer.c_str(), &reason_to_stop, &final_value_type, options, &what_next); if (!item) { - if (log) - log->Printf("[ExpandIndexedExpression] ERROR: why stopping = %d," - " final_value_type %d", - reason_to_stop, final_value_type); + LLDB_LOGF(log, + "[ExpandIndexedExpression] ERROR: why stopping = %d," + " final_value_type %d", + reason_to_stop, final_value_type); } else { - if (log) - log->Printf("[ExpandIndexedExpression] ALL RIGHT: why stopping = %d," - " final_value_type %d", - reason_to_stop, final_value_type); + LLDB_LOGF(log, + "[ExpandIndexedExpression] ALL RIGHT: why stopping = %d," + " final_value_type %d", + reason_to_stop, final_value_type); } return item; } @@ -770,9 +768,8 @@ static bool DumpValue(Stream &s, const SymbolContext *sc, const std::string &expr_path = entry.string; - if (log) - log->Printf("[Debugger::FormatPrompt] symbol to expand: %s", - expr_path.c_str()); + LLDB_LOGF(log, "[Debugger::FormatPrompt] symbol to expand: %s", + expr_path.c_str()); target = valobj @@ -781,16 +778,16 @@ static bool DumpValue(Stream &s, const SymbolContext *sc, .get(); if (!target) { - if (log) - log->Printf("[Debugger::FormatPrompt] ERROR: why stopping = %d," - " final_value_type %d", - reason_to_stop, final_value_type); + LLDB_LOGF(log, + "[Debugger::FormatPrompt] ERROR: why stopping = %d," + " final_value_type %d", + reason_to_stop, final_value_type); return false; } else { - if (log) - log->Printf("[Debugger::FormatPrompt] ALL RIGHT: why stopping = %d," - " final_value_type %d", - reason_to_stop, final_value_type); + LLDB_LOGF(log, + "[Debugger::FormatPrompt] ALL RIGHT: why stopping = %d," + " final_value_type %d", + reason_to_stop, final_value_type); target = target ->GetQualifiedRepresentationIfAvailable( target->GetDynamicValueType(), true) @@ -814,18 +811,16 @@ static bool DumpValue(Stream &s, const SymbolContext *sc, Status error; target = target->Dereference(error).get(); if (error.Fail()) { - if (log) - log->Printf("[Debugger::FormatPrompt] ERROR: %s\n", - error.AsCString("unknown")); + LLDB_LOGF(log, "[Debugger::FormatPrompt] ERROR: %s\n", + error.AsCString("unknown")); return false; } do_deref_pointer = false; } if (!target) { - if (log) - log->Printf("[Debugger::FormatPrompt] could not calculate target for " - "prompt expression"); + LLDB_LOGF(log, "[Debugger::FormatPrompt] could not calculate target for " + "prompt expression"); return false; } @@ -860,18 +855,16 @@ static bool DumpValue(Stream &s, const SymbolContext *sc, // exceptions { StreamString str_temp; - if (log) - log->Printf( - "[Debugger::FormatPrompt] I am into array || pointer && !range"); + LLDB_LOGF(log, + "[Debugger::FormatPrompt] I am into array || pointer && !range"); if (target->HasSpecialPrintableRepresentation(val_obj_display, custom_format)) { // try to use the special cases bool success = target->DumpPrintableRepresentation( str_temp, val_obj_display, custom_format); - if (log) - log->Printf("[Debugger::FormatPrompt] special cases did%s match", - success ? "" : "n't"); + LLDB_LOGF(log, "[Debugger::FormatPrompt] special cases did%s match", + success ? "" : "n't"); // should not happen if (success) @@ -909,17 +902,16 @@ static bool DumpValue(Stream &s, const SymbolContext *sc, } if (!is_array_range) { - if (log) - log->Printf("[Debugger::FormatPrompt] dumping ordinary printable output"); + LLDB_LOGF(log, + "[Debugger::FormatPrompt] dumping ordinary printable output"); return target->DumpPrintableRepresentation(s, val_obj_display, custom_format); } else { - if (log) - log->Printf("[Debugger::FormatPrompt] checking if I can handle as array"); + LLDB_LOGF(log, + "[Debugger::FormatPrompt] checking if I can handle as array"); if (!is_array && !is_pointer) return false; - if (log) - log->Printf("[Debugger::FormatPrompt] handle as array"); + LLDB_LOGF(log, "[Debugger::FormatPrompt] handle as array"); StreamString special_directions_stream; llvm::StringRef special_directions; if (close_bracket_index != llvm::StringRef::npos && @@ -965,15 +957,15 @@ static bool DumpValue(Stream &s, const SymbolContext *sc, .get(); if (!item) { - if (log) - log->Printf("[Debugger::FormatPrompt] ERROR in getting child item at " - "index %" PRId64, - index); + LLDB_LOGF(log, + "[Debugger::FormatPrompt] ERROR in getting child item at " + "index %" PRId64, + index); } else { - if (log) - log->Printf( - "[Debugger::FormatPrompt] special_directions for child item: %s", - special_directions.data() ? special_directions.data() : ""); + LLDB_LOGF( + log, + "[Debugger::FormatPrompt] special_directions for child item: %s", + special_directions.data() ? special_directions.data() : ""); } if (special_directions.empty()) { @@ -2354,34 +2346,31 @@ static void AddMatches(const FormatEntity::Entry::Definition *def, } } -size_t FormatEntity::AutoComplete(CompletionRequest &request) { - llvm::StringRef str = request.GetCursorArgumentPrefix().str(); - - request.SetWordComplete(false); - str = str.drop_front(request.GetMatchStartPoint()); +void FormatEntity::AutoComplete(CompletionRequest &request) { + llvm::StringRef str = request.GetCursorArgumentPrefix(); const size_t dollar_pos = str.rfind('$'); if (dollar_pos == llvm::StringRef::npos) - return 0; + return; // Hitting TAB after $ at the end of the string add a "{" if (dollar_pos == str.size() - 1) { std::string match = str.str(); match.append("{"); request.AddCompletion(match); - return 1; + return; } if (str[dollar_pos + 1] != '{') - return 0; + return; const size_t close_pos = str.find('}', dollar_pos + 2); if (close_pos != llvm::StringRef::npos) - return 0; + return; const size_t format_pos = str.find('%', dollar_pos + 2); if (format_pos != llvm::StringRef::npos) - return 0; + return; llvm::StringRef partial_variable(str.substr(dollar_pos + 2)); if (partial_variable.empty()) { @@ -2389,7 +2378,7 @@ size_t FormatEntity::AutoComplete(CompletionRequest &request) { StringList new_matches; AddMatches(&g_root, str, llvm::StringRef(), new_matches); request.AddCompletions(new_matches); - return request.GetNumberOfMatches(); + return; } // We have a partially specified variable, find it @@ -2397,7 +2386,7 @@ size_t FormatEntity::AutoComplete(CompletionRequest &request) { const FormatEntity::Entry::Definition *entry_def = FindEntry(partial_variable, &g_root, remainder); if (!entry_def) - return 0; + return; const size_t n = entry_def->num_children; @@ -2409,7 +2398,6 @@ size_t FormatEntity::AutoComplete(CompletionRequest &request) { } else { // "${thread.id" <TAB> request.AddCompletion(MakeMatch(str, "}")); - request.SetWordComplete(true); } } else if (remainder.equals(".")) { // "${thread." <TAB> @@ -2423,5 +2411,4 @@ size_t FormatEntity::AutoComplete(CompletionRequest &request) { AddMatches(entry_def, str, remainder, new_matches); request.AddCompletions(new_matches); } - return request.GetNumberOfMatches(); } diff --git a/source/Core/Highlighter.cpp b/source/Core/Highlighter.cpp index 0b0aa969bf65..c3c614aac210 100644 --- a/source/Core/Highlighter.cpp +++ b/source/Core/Highlighter.cpp @@ -13,6 +13,7 @@ #include "lldb/Utility/StreamString.h" using namespace lldb_private; +using namespace lldb_private::ansi; void HighlightStyle::ColorStyle::Apply(Stream &s, llvm::StringRef value) const { s << m_prefix << value << m_suffix; @@ -20,8 +21,8 @@ void HighlightStyle::ColorStyle::Apply(Stream &s, llvm::StringRef value) const { void HighlightStyle::ColorStyle::Set(llvm::StringRef prefix, llvm::StringRef suffix) { - m_prefix = lldb_utility::ansi::FormatAnsiTerminalCodes(prefix); - m_suffix = lldb_utility::ansi::FormatAnsiTerminalCodes(suffix); + m_prefix = FormatAnsiTerminalCodes(prefix); + m_suffix = FormatAnsiTerminalCodes(suffix); } void DefaultHighlighter::Highlight(const HighlightStyle &options, diff --git a/source/Core/IOHandler.cpp b/source/Core/IOHandler.cpp index b30308490cca..46be29f6fbf9 100644 --- a/source/Core/IOHandler.cpp +++ b/source/Core/IOHandler.cpp @@ -52,7 +52,7 @@ #include "llvm/ADT/StringRef.h" -#ifdef _MSC_VER +#ifdef _WIN32 #include "lldb/Host/windows/windows.h" #endif @@ -70,10 +70,14 @@ using namespace lldb; using namespace lldb_private; +using llvm::None; +using llvm::Optional; +using llvm::StringRef; + IOHandler::IOHandler(Debugger &debugger, IOHandler::Type type) : IOHandler(debugger, type, - StreamFileSP(), // Adopt STDIN from top input reader + FileSP(), // Adopt STDIN from top input reader StreamFileSP(), // Adopt STDOUT from top input reader StreamFileSP(), // Adopt STDERR from top input reader 0, // Flags @@ -81,7 +85,7 @@ IOHandler::IOHandler(Debugger &debugger, IOHandler::Type type) ) {} IOHandler::IOHandler(Debugger &debugger, IOHandler::Type type, - const lldb::StreamFileSP &input_sp, + const lldb::FileSP &input_sp, const lldb::StreamFileSP &output_sp, const lldb::StreamFileSP &error_sp, uint32_t flags, repro::DataRecorder *data_recorder) @@ -98,7 +102,7 @@ IOHandler::IOHandler(Debugger &debugger, IOHandler::Type type, IOHandler::~IOHandler() = default; int IOHandler::GetInputFD() { - return (m_input_sp ? m_input_sp->GetFile().GetDescriptor() : -1); + return (m_input_sp ? m_input_sp->GetDescriptor() : -1); } int IOHandler::GetOutputFD() { @@ -110,7 +114,7 @@ int IOHandler::GetErrorFD() { } FILE *IOHandler::GetInputFILE() { - return (m_input_sp ? m_input_sp->GetFile().GetStream() : nullptr); + return (m_input_sp ? m_input_sp->GetStream() : nullptr); } FILE *IOHandler::GetOutputFILE() { @@ -121,18 +125,18 @@ FILE *IOHandler::GetErrorFILE() { return (m_error_sp ? m_error_sp->GetFile().GetStream() : nullptr); } -StreamFileSP &IOHandler::GetInputStreamFile() { return m_input_sp; } +FileSP &IOHandler::GetInputFileSP() { return m_input_sp; } -StreamFileSP &IOHandler::GetOutputStreamFile() { return m_output_sp; } +StreamFileSP &IOHandler::GetOutputStreamFileSP() { return m_output_sp; } -StreamFileSP &IOHandler::GetErrorStreamFile() { return m_error_sp; } +StreamFileSP &IOHandler::GetErrorStreamFileSP() { return m_error_sp; } bool IOHandler::GetIsInteractive() { - return GetInputStreamFile()->GetFile().GetIsInteractive(); + return GetInputFileSP() ? GetInputFileSP()->GetIsInteractive() : false; } bool IOHandler::GetIsRealTerminal() { - return GetInputStreamFile()->GetFile().GetIsRealTerminal(); + return GetInputFileSP() ? GetInputFileSP()->GetIsRealTerminal() : false; } void IOHandler::SetPopped(bool b) { m_popped.SetValue(b, eBroadcastOnChange); } @@ -170,18 +174,11 @@ IOHandlerConfirm::IOHandlerConfirm(Debugger &debugger, llvm::StringRef prompt, IOHandlerConfirm::~IOHandlerConfirm() = default; -int IOHandlerConfirm::IOHandlerComplete( - IOHandler &io_handler, const char *current_line, const char *cursor, - const char *last_char, int skip_first_n_matches, int max_matches, - StringList &matches, StringList &descriptions) { - if (current_line == cursor) { - if (m_default_response) { - matches.AppendString("y"); - } else { - matches.AppendString("n"); - } - } - return matches.GetSize(); +void IOHandlerConfirm::IOHandlerComplete(IOHandler &io_handler, + CompletionRequest &request) { + if (request.GetRawCursorPos() != 0) + return; + request.AddCompletion(m_default_response ? "y" : "n"); } void IOHandlerConfirm::IOHandlerInputComplete(IOHandler &io_handler, @@ -219,47 +216,20 @@ void IOHandlerConfirm::IOHandlerInputComplete(IOHandler &io_handler, } } -int IOHandlerDelegate::IOHandlerComplete( - IOHandler &io_handler, const char *current_line, const char *cursor, - const char *last_char, int skip_first_n_matches, int max_matches, - StringList &matches, StringList &descriptions) { +void IOHandlerDelegate::IOHandlerComplete(IOHandler &io_handler, + CompletionRequest &request) { switch (m_completion) { case Completion::None: break; - case Completion::LLDBCommand: - return io_handler.GetDebugger().GetCommandInterpreter().HandleCompletion( - current_line, cursor, last_char, skip_first_n_matches, max_matches, - matches, descriptions); - case Completion::Expression: { - CompletionResult result; - CompletionRequest request(current_line, current_line - cursor, - skip_first_n_matches, max_matches, result); + io_handler.GetDebugger().GetCommandInterpreter().HandleCompletion(request); + break; + case Completion::Expression: CommandCompletions::InvokeCommonCompletionCallbacks( io_handler.GetDebugger().GetCommandInterpreter(), CommandCompletions::eVariablePathCompletion, request, nullptr); - result.GetMatches(matches); - result.GetDescriptions(descriptions); - - size_t num_matches = request.GetNumberOfMatches(); - if (num_matches > 0) { - std::string common_prefix; - matches.LongestCommonPrefix(common_prefix); - const size_t partial_name_len = request.GetCursorArgumentPrefix().size(); - - // If we matched a unique single command, add a space... Only do this if - // the completer told us this was a complete word, however... - if (num_matches == 1 && request.GetWordComplete()) { - common_prefix.push_back(' '); - } - common_prefix.erase(0, partial_name_len); - matches.InsertStringAtIndex(0, std::move(common_prefix)); - } - return num_matches; - } break; + break; } - - return 0; } IOHandlerEditline::IOHandlerEditline( @@ -269,7 +239,7 @@ IOHandlerEditline::IOHandlerEditline( bool multi_line, bool color_prompts, uint32_t line_number_start, IOHandlerDelegate &delegate, repro::DataRecorder *data_recorder) : IOHandlerEditline(debugger, type, - StreamFileSP(), // Inherit input from top input reader + FileSP(), // Inherit input from top input reader StreamFileSP(), // Inherit output from top input reader StreamFileSP(), // Inherit error from top input reader 0, // Flags @@ -278,9 +248,9 @@ IOHandlerEditline::IOHandlerEditline( line_number_start, delegate, data_recorder) {} IOHandlerEditline::IOHandlerEditline( - Debugger &debugger, IOHandler::Type type, - const lldb::StreamFileSP &input_sp, const lldb::StreamFileSP &output_sp, - const lldb::StreamFileSP &error_sp, uint32_t flags, + Debugger &debugger, IOHandler::Type type, const lldb::FileSP &input_sp, + const lldb::StreamFileSP &output_sp, const lldb::StreamFileSP &error_sp, + uint32_t flags, const char *editline_name, // Used for saving history files llvm::StringRef prompt, llvm::StringRef continuation_prompt, bool multi_line, bool color_prompts, uint32_t line_number_start, @@ -300,7 +270,8 @@ IOHandlerEditline::IOHandlerEditline( #ifndef LLDB_DISABLE_LIBEDIT bool use_editline = false; - use_editline = m_input_sp->GetFile().GetIsRealTerminal(); + use_editline = GetInputFILE() && GetOutputFILE() && GetErrorFILE() && + m_input_sp && m_input_sp->GetIsRealTerminal(); if (use_editline) { m_editline_up.reset(new Editline(editline_name, GetInputFILE(), @@ -339,92 +310,119 @@ void IOHandlerEditline::Deactivate() { m_delegate.IOHandlerDeactivated(*this); } +// Split out a line from the buffer, if there is a full one to get. +static Optional<std::string> SplitLine(std::string &line_buffer) { + size_t pos = line_buffer.find('\n'); + if (pos == std::string::npos) + return None; + std::string line = StringRef(line_buffer.c_str(), pos).rtrim("\n\r"); + line_buffer = line_buffer.substr(pos + 1); + return line; +} + +// If the final line of the file ends without a end-of-line, return +// it as a line anyway. +static Optional<std::string> SplitLineEOF(std::string &line_buffer) { + if (llvm::all_of(line_buffer, isspace)) + return None; + std::string line = std::move(line_buffer); + line_buffer.clear(); + return line; +} + bool IOHandlerEditline::GetLine(std::string &line, bool &interrupted) { #ifndef LLDB_DISABLE_LIBEDIT if (m_editline_up) { bool b = m_editline_up->GetLine(line, interrupted); - if (m_data_recorder) + if (b && m_data_recorder) m_data_recorder->Record(line, true); return b; - } else { + } #endif - line.clear(); - FILE *in = GetInputFILE(); - if (in) { - if (GetIsInteractive()) { - const char *prompt = nullptr; + line.clear(); - if (m_multi_line && m_curr_line_idx > 0) - prompt = GetContinuationPrompt(); + if (GetIsInteractive()) { + const char *prompt = nullptr; - if (prompt == nullptr) - prompt = GetPrompt(); + if (m_multi_line && m_curr_line_idx > 0) + prompt = GetContinuationPrompt(); - if (prompt && prompt[0]) { - FILE *out = GetOutputFILE(); - if (out) { - ::fprintf(out, "%s", prompt); - ::fflush(out); - } - } + if (prompt == nullptr) + prompt = GetPrompt(); + + if (prompt && prompt[0]) { + if (m_output_sp) { + m_output_sp->Printf("%s", prompt); + m_output_sp->Flush(); } - char buffer[256]; - bool done = false; - bool got_line = false; - m_editing = true; - while (!done) { + } + } + + Optional<std::string> got_line = SplitLine(m_line_buffer); + + if (!got_line && !m_input_sp) { + // No more input file, we are done... + SetIsDone(true); + return false; + } + + FILE *in = GetInputFILE(); + char buffer[256]; + + if (!got_line && !in && m_input_sp) { + // there is no FILE*, fall back on just reading bytes from the stream. + while (!got_line) { + size_t bytes_read = sizeof(buffer); + Status error = m_input_sp->Read((void *)buffer, bytes_read); + if (error.Success() && !bytes_read) { + got_line = SplitLineEOF(m_line_buffer); + break; + } + if (error.Fail()) + break; + m_line_buffer += StringRef(buffer, bytes_read); + got_line = SplitLine(m_line_buffer); + } + } + + if (!got_line && in) { + m_editing = true; + while (!got_line) { + char *r = fgets(buffer, sizeof(buffer), in); #ifdef _WIN32 - // ReadFile on Windows is supposed to set ERROR_OPERATION_ABORTED - // according to the docs on MSDN. However, this has evidently been a - // known bug since Windows 8. Therefore, we can't detect if a signal - // interrupted in the fgets. So pressing ctrl-c causes the repl to end - // and the process to exit. A temporary workaround is just to attempt to - // fgets twice until this bug is fixed. - if (fgets(buffer, sizeof(buffer), in) == nullptr && - fgets(buffer, sizeof(buffer), in) == nullptr) { -#else - if (fgets(buffer, sizeof(buffer), in) == nullptr) { + // ReadFile on Windows is supposed to set ERROR_OPERATION_ABORTED + // according to the docs on MSDN. However, this has evidently been a + // known bug since Windows 8. Therefore, we can't detect if a signal + // interrupted in the fgets. So pressing ctrl-c causes the repl to end + // and the process to exit. A temporary workaround is just to attempt to + // fgets twice until this bug is fixed. + if (r == nullptr) + r = fgets(buffer, sizeof(buffer), in); + // this is the equivalent of EINTR for Windows + if (r == nullptr && GetLastError() == ERROR_OPERATION_ABORTED) + continue; #endif - const int saved_errno = errno; - if (feof(in)) - done = true; - else if (ferror(in)) { - if (saved_errno != EINTR) - done = true; - } - } else { - got_line = true; - size_t buffer_len = strlen(buffer); - assert(buffer[buffer_len] == '\0'); - char last_char = buffer[buffer_len - 1]; - if (last_char == '\r' || last_char == '\n') { - done = true; - // Strip trailing newlines - while (last_char == '\r' || last_char == '\n') { - --buffer_len; - if (buffer_len == 0) - break; - last_char = buffer[buffer_len - 1]; - } - } - line.append(buffer, buffer_len); - } + if (r == nullptr) { + if (ferror(in) && errno == EINTR) + continue; + if (feof(in)) + got_line = SplitLineEOF(m_line_buffer); + break; } - m_editing = false; - if (m_data_recorder && got_line) - m_data_recorder->Record(line, true); - // We might have gotten a newline on a line by itself make sure to return - // true in this case. - return got_line; - } else { - // No more input file, we are done... - SetIsDone(true); + m_line_buffer += buffer; + got_line = SplitLine(m_line_buffer); } - return false; -#ifndef LLDB_DISABLE_LIBEDIT + m_editing = false; } -#endif + + if (got_line) { + line = got_line.getValue(); + if (m_data_recorder) + m_data_recorder->Record(line, true); + } + + return (bool)got_line; } #ifndef LLDB_DISABLE_LIBEDIT @@ -445,16 +443,11 @@ int IOHandlerEditline::FixIndentationCallback(Editline *editline, *editline_reader, lines, cursor_position); } -int IOHandlerEditline::AutoCompleteCallback( - const char *current_line, const char *cursor, const char *last_char, - int skip_first_n_matches, int max_matches, StringList &matches, - StringList &descriptions, void *baton) { +void IOHandlerEditline::AutoCompleteCallback(CompletionRequest &request, + void *baton) { IOHandlerEditline *editline_reader = (IOHandlerEditline *)baton; if (editline_reader) - return editline_reader->m_delegate.IOHandlerComplete( - *editline_reader, current_line, cursor, last_char, skip_first_n_matches, - max_matches, matches, descriptions); - return 0; + editline_reader->m_delegate.IOHandlerComplete(*editline_reader, request); } #endif @@ -526,10 +519,11 @@ bool IOHandlerEditline::GetLines(StringList &lines, bool &interrupted) { // Show line numbers if we are asked to std::string line; if (m_base_line_number > 0 && GetIsInteractive()) { - FILE *out = GetOutputFILE(); - if (out) - ::fprintf(out, "%u%s", m_base_line_number + (uint32_t)lines.GetSize(), - GetPrompt() == nullptr ? " " : ""); + if (m_output_sp) { + m_output_sp->Printf("%u%s", + m_base_line_number + (uint32_t)lines.GetSize(), + GetPrompt() == nullptr ? " " : ""); + } } m_curr_line_idx = lines.GetSize(); @@ -615,7 +609,7 @@ void IOHandlerEditline::PrintAsync(Stream *stream, const char *s, size_t len) { else #endif { -#ifdef _MSC_VER +#ifdef _WIN32 const char *prompt = GetPrompt(); if (prompt) { // Back up over previous prompt using Windows API @@ -630,9 +624,9 @@ void IOHandlerEditline::PrintAsync(Stream *stream, const char *s, size_t len) { } #endif IOHandler::PrintAsync(stream, s, len); -#ifdef _MSC_VER +#ifdef _WIN32 if (prompt) - IOHandler::PrintAsync(GetOutputStreamFile().get(), prompt, + IOHandler::PrintAsync(GetOutputStreamFileSP().get(), prompt, strlen(prompt)); #endif } @@ -952,16 +946,9 @@ public: } void PutChar(int ch) { ::waddch(m_window, ch); } void PutCString(const char *s, int len = -1) { ::waddnstr(m_window, s, len); } - void Refresh() { ::wrefresh(m_window); } - void DeferredRefresh() { - // We are using panels, so we don't need to call this... - //::wnoutrefresh(m_window); - } void SetBackground(int color_pair_idx) { ::wbkgd(m_window, COLOR_PAIR(color_pair_idx)); } - void UnderlineOn() { AttributeOn(A_UNDERLINE); } - void UnderlineOff() { AttributeOff(A_UNDERLINE); } void PutCStringTruncated(const char *s, int right_pad) { int bytes_left = GetWidth() - GetCursorX(); @@ -1213,19 +1200,6 @@ public: return eKeyNotHandled; } - bool SetActiveWindow(Window *window) { - const size_t num_subwindows = m_subwindows.size(); - for (size_t i = 0; i < num_subwindows; ++i) { - if (m_subwindows[i].get() == window) { - m_prev_active_window_idx = m_curr_active_window_idx; - ::top_panel(window->m_panel); - m_curr_active_window_idx = i; - return true; - } - } - return false; - } - WindowSP GetActiveWindow() { if (!m_subwindows.empty()) { if (m_curr_active_window_idx >= m_subwindows.size()) { @@ -1257,8 +1231,6 @@ public: void SetCanBeActive(bool b) { m_can_activate = b; } - const WindowDelegateSP &GetDelegate() const { return m_delegate_sp; } - void SetDelegate(const WindowDelegateSP &delegate_sp) { m_delegate_sp = delegate_sp; } @@ -1410,12 +1382,8 @@ public: int GetKeyValue() const { return m_key_value; } - void SetKeyValue(int key_value) { m_key_value = key_value; } - std::string &GetName() { return m_name; } - std::string &GetKeyName() { return m_key_name; } - int GetDrawWidth() const { return m_max_submenu_name_length + m_max_submenu_key_name_length + 8; } @@ -1569,7 +1537,6 @@ bool Menu::WindowDelegateDraw(Window &window, bool force) { menu->DrawMenuTitle(window, false); } window.PutCString(" |"); - window.DeferredRefresh(); } break; case Menu::Type::Item: { @@ -1592,7 +1559,6 @@ bool Menu::WindowDelegateDraw(Window &window, bool force) { submenus[i]->DrawMenuTitle(window, is_selected); } window.MoveCursor(cursor_x, cursor_y); - window.DeferredRefresh(); } break; default: @@ -1898,8 +1864,6 @@ public: return m_window_sp; } - WindowDelegates &GetWindowDelegates() { return m_window_delegates; } - protected: WindowSP m_window_sp; WindowDelegates m_window_delegates; @@ -1936,9 +1900,7 @@ struct Row { return 0; } - void Expand() { - expanded = true; - } + void Expand() { expanded = true; } std::vector<Row> &GetChildren() { ProcessSP process_sp = value.GetProcessSP(); @@ -2293,8 +2255,6 @@ public: m_selected_item = nullptr; } - window.DeferredRefresh(); - return true; // Drawing handled } @@ -2644,14 +2604,12 @@ protected: class ValueObjectListDelegate : public WindowDelegate { public: ValueObjectListDelegate() - : m_rows(), m_selected_row(nullptr), - m_selected_row_idx(0), m_first_visible_row(0), m_num_rows(0), - m_max_x(0), m_max_y(0) {} + : m_rows(), m_selected_row(nullptr), m_selected_row_idx(0), + m_first_visible_row(0), m_num_rows(0), m_max_x(0), m_max_y(0) {} ValueObjectListDelegate(ValueObjectList &valobj_list) - : m_rows(), m_selected_row(nullptr), - m_selected_row_idx(0), m_first_visible_row(0), m_num_rows(0), - m_max_x(0), m_max_y(0) { + : m_rows(), m_selected_row(nullptr), m_selected_row_idx(0), + m_first_visible_row(0), m_num_rows(0), m_max_x(0), m_max_y(0) { SetValues(valobj_list); } @@ -2694,8 +2652,6 @@ public: DisplayRows(window, m_rows, g_options); - window.DeferredRefresh(); - // Get the selected row m_selected_row = GetRowForRowIndex(m_selected_row_idx); // Keep the cursor on the selected row so the highlight and the cursor are @@ -3800,7 +3756,6 @@ public: window.Printf(" with status = %i", exit_status); } } - window.DeferredRefresh(); return true; } @@ -4258,7 +4213,6 @@ public: } } } - window.DeferredRefresh(); return true; // Drawing handled } diff --git a/source/Core/Mangled.cpp b/source/Core/Mangled.cpp index c6759cc944ca..b06656aa3fb7 100644 --- a/source/Core/Mangled.cpp +++ b/source/Core/Mangled.cpp @@ -8,13 +8,6 @@ #include "lldb/Core/Mangled.h" -#if defined(_WIN32) -#include "lldb/Host/windows/windows.h" - -#include <dbghelp.h> -#pragma comment(lib, "dbghelp.lib") -#endif - #include "lldb/Core/RichManglingContext.h" #include "lldb/Utility/ConstString.h" #include "lldb/Utility/Log.h" @@ -39,25 +32,6 @@ #include <string.h> using namespace lldb_private; -#if defined(_MSC_VER) -static DWORD safeUndecorateName(const char *Mangled, char *Demangled, - DWORD DemangledLength) { - static std::mutex M; - std::lock_guard<std::mutex> Lock(M); - return ::UnDecorateSymbolName( - Mangled, Demangled, DemangledLength, - UNDNAME_NO_ACCESS_SPECIFIERS | // Strip public, private, protected - // keywords - UNDNAME_NO_ALLOCATION_LANGUAGE | // Strip __thiscall, __stdcall, - // etc keywords - UNDNAME_NO_THROW_SIGNATURES | // Strip throw() specifications - UNDNAME_NO_MEMBER_TYPE | // Strip virtual, static, etc - // specifiers - UNDNAME_NO_MS_KEYWORDS // Strip all MS extension keywords - ); -} -#endif - static inline Mangled::ManglingScheme cstring_mangling_scheme(const char *s) { if (s) { if (s[0] == '?') @@ -124,21 +98,6 @@ get_demangled_name_without_arguments(ConstString mangled, } #pragma mark Mangled -// Default constructor -Mangled::Mangled() : m_mangled(), m_demangled() {} - -// Constructor with an optional string and a boolean indicating if it is the -// mangled version. -Mangled::Mangled(ConstString s, bool mangled) - : m_mangled(), m_demangled() { - if (s) - SetValue(s, mangled); -} - -Mangled::Mangled(llvm::StringRef name, bool is_mangled) { - if (!name.empty()) - SetValue(ConstString(name), is_mangled); -} Mangled::Mangled(ConstString s) : m_mangled(), m_demangled() { if (s) @@ -150,9 +109,6 @@ Mangled::Mangled(llvm::StringRef name) { SetValue(ConstString(name)); } -// Destructor -Mangled::~Mangled() {} - // Convert to pointer operator. This allows code to check any Mangled objects // to see if they contain anything valid using code such as: // @@ -218,28 +174,20 @@ void Mangled::SetValue(ConstString name) { // Local helpers for different demangling implementations. static char *GetMSVCDemangledStr(const char *M) { -#if defined(_MSC_VER) - const size_t demangled_length = 2048; - char *demangled_cstr = static_cast<char *>(::malloc(demangled_length)); - ::ZeroMemory(demangled_cstr, demangled_length); - DWORD result = safeUndecorateName(M, demangled_cstr, demangled_length); + char *demangled_cstr = llvm::microsoftDemangle( + M, nullptr, nullptr, nullptr, + llvm::MSDemangleFlags(llvm::MSDF_NoAccessSpecifier | + llvm::MSDF_NoCallingConvention | + llvm::MSDF_NoMemberType)); if (Log *log = lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_DEMANGLE)) { if (demangled_cstr && demangled_cstr[0]) - log->Printf("demangled msvc: %s -> \"%s\"", M, demangled_cstr); + LLDB_LOGF(log, "demangled msvc: %s -> \"%s\"", M, demangled_cstr); else - log->Printf("demangled msvc: %s -> error: 0x%lu", M, result); + LLDB_LOGF(log, "demangled msvc: %s -> error", M); } - if (result != 0) { - return demangled_cstr; - } else { - ::free(demangled_cstr); - return nullptr; - } -#else - return nullptr; -#endif + return demangled_cstr; } static char *GetItaniumDemangledStr(const char *M) { @@ -261,9 +209,9 @@ static char *GetItaniumDemangledStr(const char *M) { if (Log *log = lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_DEMANGLE)) { if (demangled_cstr) - log->Printf("demangled itanium: %s -> \"%s\"", M, demangled_cstr); + LLDB_LOGF(log, "demangled itanium: %s -> \"%s\"", M, demangled_cstr); else - log->Printf("demangled itanium: %s -> error: failed to demangle", M); + LLDB_LOGF(log, "demangled itanium: %s -> error: failed to demangle", M); } return demangled_cstr; diff --git a/source/Core/Module.cpp b/source/Core/Module.cpp index 153d5a740936..aef3f3e3b4b0 100644 --- a/source/Core/Module.cpp +++ b/source/Core/Module.cpp @@ -137,14 +137,15 @@ Module::Module(const ModuleSpec &module_spec) Log *log(lldb_private::GetLogIfAnyCategoriesSet(LIBLLDB_LOG_OBJECT | LIBLLDB_LOG_MODULES)); if (log != nullptr) - log->Printf("%p Module::Module((%s) '%s%s%s%s')", static_cast<void *>(this), - module_spec.GetArchitecture().GetArchitectureName(), - module_spec.GetFileSpec().GetPath().c_str(), - module_spec.GetObjectName().IsEmpty() ? "" : "(", - module_spec.GetObjectName().IsEmpty() - ? "" - : module_spec.GetObjectName().AsCString(""), - module_spec.GetObjectName().IsEmpty() ? "" : ")"); + LLDB_LOGF(log, "%p Module::Module((%s) '%s%s%s%s')", + static_cast<void *>(this), + module_spec.GetArchitecture().GetArchitectureName(), + module_spec.GetFileSpec().GetPath().c_str(), + module_spec.GetObjectName().IsEmpty() ? "" : "(", + module_spec.GetObjectName().IsEmpty() + ? "" + : module_spec.GetObjectName().AsCString(""), + module_spec.GetObjectName().IsEmpty() ? "" : ")"); // First extract all module specifications from the file using the local file // path. If there are no specifications, then don't fill anything in @@ -164,7 +165,7 @@ Module::Module(const ModuleSpec &module_spec) if (!modules_specs.FindMatchingModuleSpec(module_spec, matching_module_spec)) { if (log) { - log->Printf("Found local object file but the specs didn't match"); + LLDB_LOGF(log, "Found local object file but the specs didn't match"); } return; } @@ -235,11 +236,11 @@ Module::Module(const FileSpec &file_spec, const ArchSpec &arch, Log *log(lldb_private::GetLogIfAnyCategoriesSet(LIBLLDB_LOG_OBJECT | LIBLLDB_LOG_MODULES)); if (log != nullptr) - log->Printf("%p Module::Module((%s) '%s%s%s%s')", static_cast<void *>(this), - m_arch.GetArchitectureName(), m_file.GetPath().c_str(), - m_object_name.IsEmpty() ? "" : "(", - m_object_name.IsEmpty() ? "" : m_object_name.AsCString(""), - m_object_name.IsEmpty() ? "" : ")"); + LLDB_LOGF(log, "%p Module::Module((%s) '%s%s%s%s')", + static_cast<void *>(this), m_arch.GetArchitectureName(), + m_file.GetPath().c_str(), m_object_name.IsEmpty() ? "" : "(", + m_object_name.IsEmpty() ? "" : m_object_name.AsCString(""), + m_object_name.IsEmpty() ? "" : ")"); } Module::Module() @@ -267,11 +268,11 @@ Module::~Module() { Log *log(lldb_private::GetLogIfAnyCategoriesSet(LIBLLDB_LOG_OBJECT | LIBLLDB_LOG_MODULES)); if (log != nullptr) - log->Printf("%p Module::~Module((%s) '%s%s%s%s')", - static_cast<void *>(this), m_arch.GetArchitectureName(), - m_file.GetPath().c_str(), m_object_name.IsEmpty() ? "" : "(", - m_object_name.IsEmpty() ? "" : m_object_name.AsCString(""), - m_object_name.IsEmpty() ? "" : ")"); + LLDB_LOGF(log, "%p Module::~Module((%s) '%s%s%s%s')", + static_cast<void *>(this), m_arch.GetArchitectureName(), + m_file.GetPath().c_str(), m_object_name.IsEmpty() ? "" : "(", + m_object_name.IsEmpty() ? "" : m_object_name.AsCString(""), + m_object_name.IsEmpty() ? "" : ")"); // Release any auto pointers before we start tearing down our member // variables since the object file and symbol files might need to make // function calls back into this module object. The ordering is important @@ -291,7 +292,7 @@ ObjectFile *Module::GetMemoryObjectFile(const lldb::ProcessSP &process_sp, std::lock_guard<std::recursive_mutex> guard(m_mutex); if (process_sp) { m_did_load_objfile = true; - auto data_up = llvm::make_unique<DataBufferHeap>(size_to_read, 0); + auto data_up = std::make_unique<DataBufferHeap>(size_to_read, 0); Status readmem_error; const size_t bytes_read = process_sp->ReadMemory(header_addr, data_up->GetBytes(), @@ -352,7 +353,8 @@ void Module::SetUUID(const lldb_private::UUID &uuid) { } } -TypeSystem *Module::GetTypeSystemForLanguage(LanguageType language) { +llvm::Expected<TypeSystem &> +Module::GetTypeSystemForLanguage(LanguageType language) { return m_type_system_map.GetTypeSystemForLanguage(language, this, true); } @@ -364,7 +366,7 @@ void Module::ParseAllDebugSymbols() { SymbolContext sc; sc.module_sp = shared_from_this(); - SymbolVendor *symbols = GetSymbolVendor(); + SymbolFile *symbols = GetSymbolFile(); for (size_t cu_idx = 0; cu_idx < num_comp_units; cu_idx++) { sc.comp_unit = symbols->GetCompileUnitAtIndex(cu_idx).get(); @@ -404,8 +406,7 @@ size_t Module::GetNumCompileUnits() { static Timer::Category func_cat(LLVM_PRETTY_FUNCTION); Timer scoped_timer(func_cat, "Module::GetNumCompileUnits (module = %p)", static_cast<void *>(this)); - SymbolVendor *symbols = GetSymbolVendor(); - if (symbols) + if (SymbolFile *symbols = GetSymbolFile()) return symbols->GetNumCompileUnits(); return 0; } @@ -416,8 +417,7 @@ CompUnitSP Module::GetCompileUnitAtIndex(size_t index) { CompUnitSP cu_sp; if (index < num_comp_units) { - SymbolVendor *symbols = GetSymbolVendor(); - if (symbols) + if (SymbolFile *symbols = GetSymbolFile()) cu_sp = symbols->GetCompileUnitAtIndex(index); } return cu_sp; @@ -455,8 +455,8 @@ uint32_t Module::ResolveSymbolContextForAddress( sc.module_sp = shared_from_this(); resolved_flags |= eSymbolContextModule; - SymbolVendor *sym_vendor = GetSymbolVendor(); - if (!sym_vendor) + SymbolFile *symfile = GetSymbolFile(); + if (!symfile) return resolved_flags; // Resolve the compile unit, function, block, line table or line entry if @@ -467,14 +467,14 @@ uint32_t Module::ResolveSymbolContextForAddress( resolve_scope & eSymbolContextLineEntry || resolve_scope & eSymbolContextVariable) { resolved_flags |= - sym_vendor->ResolveSymbolContext(so_addr, resolve_scope, sc); + symfile->ResolveSymbolContext(so_addr, resolve_scope, sc); } // Resolve the symbol if requested, but don't re-look it up if we've // already found it. if (resolve_scope & eSymbolContextSymbol && !(resolved_flags & eSymbolContextSymbol)) { - Symtab *symtab = sym_vendor->GetSymtab(); + Symtab *symtab = symfile->GetSymtab(); if (symtab && so_addr.IsSectionOffset()) { Symbol *matching_symbol = nullptr; @@ -507,18 +507,15 @@ uint32_t Module::ResolveSymbolContextForAddress( // files on MacOSX have an unstripped symbol table inside of them. ObjectFile *symtab_objfile = symtab->GetObjectFile(); if (symtab_objfile && symtab_objfile->IsStripped()) { - SymbolFile *symfile = sym_vendor->GetSymbolFile(); - if (symfile) { - ObjectFile *symfile_objfile = symfile->GetObjectFile(); - if (symfile_objfile != symtab_objfile) { - Symtab *symfile_symtab = symfile_objfile->GetSymtab(); - if (symfile_symtab) { - Symbol *symbol = - symfile_symtab->FindSymbolContainingFileAddress( - so_addr.GetFileAddress()); - if (symbol && !symbol->IsSynthetic()) { - sc.symbol = symbol; - } + ObjectFile *symfile_objfile = symfile->GetObjectFile(); + if (symfile_objfile != symtab_objfile) { + Symtab *symfile_symtab = symfile_objfile->GetSymtab(); + if (symfile_symtab) { + Symbol *symbol = + symfile_symtab->FindSymbolContainingFileAddress( + so_addr.GetFileAddress()); + if (symbol && !symbol->IsSynthetic()) { + sc.symbol = symbol; } } } @@ -590,40 +587,29 @@ uint32_t Module::ResolveSymbolContextsForFileSpec( const uint32_t initial_count = sc_list.GetSize(); - SymbolVendor *symbols = GetSymbolVendor(); - if (symbols) + if (SymbolFile *symbols = GetSymbolFile()) symbols->ResolveSymbolContext(file_spec, line, check_inlines, resolve_scope, sc_list); return sc_list.GetSize() - initial_count; } -size_t Module::FindGlobalVariables(ConstString name, - const CompilerDeclContext *parent_decl_ctx, - size_t max_matches, - VariableList &variables) { - SymbolVendor *symbols = GetSymbolVendor(); - if (symbols) - return symbols->FindGlobalVariables(name, parent_decl_ctx, max_matches, - variables); - return 0; +void Module::FindGlobalVariables(ConstString name, + const CompilerDeclContext *parent_decl_ctx, + size_t max_matches, VariableList &variables) { + if (SymbolFile *symbols = GetSymbolFile()) + symbols->FindGlobalVariables(name, parent_decl_ctx, max_matches, variables); } -size_t Module::FindGlobalVariables(const RegularExpression ®ex, - size_t max_matches, - VariableList &variables) { - SymbolVendor *symbols = GetSymbolVendor(); +void Module::FindGlobalVariables(const RegularExpression ®ex, + size_t max_matches, VariableList &variables) { + SymbolFile *symbols = GetSymbolFile(); if (symbols) - return symbols->FindGlobalVariables(regex, max_matches, variables); - return 0; + symbols->FindGlobalVariables(regex, max_matches, variables); } -size_t Module::FindCompileUnits(const FileSpec &path, bool append, - SymbolContextList &sc_list) { - if (!append) - sc_list.Clear(); - - const size_t start_size = sc_list.GetSize(); +void Module::FindCompileUnits(const FileSpec &path, + SymbolContextList &sc_list) { const size_t num_compile_units = GetNumCompileUnits(); SymbolContext sc; sc.module_sp = shared_from_this(); @@ -635,7 +621,6 @@ size_t Module::FindCompileUnits(const FileSpec &path, bool append, sc_list.Append(sc); } } - return sc_list.GetSize() - start_size; } Module::LookupInfo::LookupInfo(ConstString name, @@ -798,18 +783,15 @@ void Module::LookupInfo::Prune(SymbolContextList &sc_list, } } -size_t Module::FindFunctions(ConstString name, - const CompilerDeclContext *parent_decl_ctx, - FunctionNameType name_type_mask, - bool include_symbols, bool include_inlines, - bool append, SymbolContextList &sc_list) { - if (!append) - sc_list.Clear(); - +void Module::FindFunctions(ConstString name, + const CompilerDeclContext *parent_decl_ctx, + FunctionNameType name_type_mask, + bool include_symbols, bool include_inlines, + SymbolContextList &sc_list) { const size_t old_size = sc_list.GetSize(); // Find all the functions (not symbols, but debug information functions... - SymbolVendor *symbols = GetSymbolVendor(); + SymbolFile *symbols = GetSymbolFile(); if (name_type_mask & eFunctionNameTypeAuto) { LookupInfo lookup_info(name, name_type_mask, eLanguageTypeUnknown); @@ -817,7 +799,7 @@ size_t Module::FindFunctions(ConstString name, if (symbols) { symbols->FindFunctions(lookup_info.GetLookupName(), parent_decl_ctx, lookup_info.GetNameTypeMask(), include_inlines, - append, sc_list); + sc_list); // Now check our symbol table for symbols that are code symbols if // requested @@ -836,7 +818,7 @@ size_t Module::FindFunctions(ConstString name, } else { if (symbols) { symbols->FindFunctions(name, parent_decl_ctx, name_type_mask, - include_inlines, append, sc_list); + include_inlines, sc_list); // Now check our symbol table for symbols that are code symbols if // requested @@ -847,21 +829,15 @@ size_t Module::FindFunctions(ConstString name, } } } - - return sc_list.GetSize() - old_size; } -size_t Module::FindFunctions(const RegularExpression ®ex, - bool include_symbols, bool include_inlines, - bool append, SymbolContextList &sc_list) { - if (!append) - sc_list.Clear(); - +void Module::FindFunctions(const RegularExpression ®ex, bool include_symbols, + bool include_inlines, + SymbolContextList &sc_list) { const size_t start_size = sc_list.GetSize(); - SymbolVendor *symbols = GetSymbolVendor(); - if (symbols) { - symbols->FindFunctions(regex, include_inlines, append, sc_list); + if (SymbolFile *symbols = GetSymbolFile()) { + symbols->FindFunctions(regex, include_inlines, sc_list); // Now check our symbol table for symbols that are code symbols if // requested @@ -923,7 +899,6 @@ size_t Module::FindFunctions(const RegularExpression ®ex, } } } - return sc_list.GetSize() - start_size; } void Module::FindAddressesForLine(const lldb::TargetSP target_sp, @@ -945,57 +920,49 @@ void Module::FindAddressesForLine(const lldb::TargetSP target_sp, } } -size_t Module::FindTypes_Impl( +void Module::FindTypes_Impl( ConstString name, const CompilerDeclContext *parent_decl_ctx, - bool append, size_t max_matches, + size_t max_matches, llvm::DenseSet<lldb_private::SymbolFile *> &searched_symbol_files, TypeMap &types) { static Timer::Category func_cat(LLVM_PRETTY_FUNCTION); Timer scoped_timer(func_cat, LLVM_PRETTY_FUNCTION); - SymbolVendor *symbols = GetSymbolVendor(); - if (symbols) - return symbols->FindTypes(name, parent_decl_ctx, append, max_matches, - searched_symbol_files, types); - return 0; + if (SymbolFile *symbols = GetSymbolFile()) + symbols->FindTypes(name, parent_decl_ctx, max_matches, + searched_symbol_files, types); } -size_t Module::FindTypesInNamespace(ConstString type_name, - const CompilerDeclContext *parent_decl_ctx, - size_t max_matches, TypeList &type_list) { - const bool append = true; +void Module::FindTypesInNamespace(ConstString type_name, + const CompilerDeclContext *parent_decl_ctx, + size_t max_matches, TypeList &type_list) { TypeMap types_map; llvm::DenseSet<lldb_private::SymbolFile *> searched_symbol_files; - size_t num_types = - FindTypes_Impl(type_name, parent_decl_ctx, append, max_matches, - searched_symbol_files, types_map); - if (num_types > 0) { + FindTypes_Impl(type_name, parent_decl_ctx, max_matches, searched_symbol_files, + types_map); + if (types_map.GetSize()) { SymbolContext sc; sc.module_sp = shared_from_this(); sc.SortTypeList(types_map, type_list); } - return num_types; } lldb::TypeSP Module::FindFirstType(const SymbolContext &sc, ConstString name, bool exact_match) { TypeList type_list; llvm::DenseSet<lldb_private::SymbolFile *> searched_symbol_files; - const size_t num_matches = - FindTypes(name, exact_match, 1, searched_symbol_files, type_list); - if (num_matches) + FindTypes(name, exact_match, 1, searched_symbol_files, type_list); + if (type_list.GetSize()) return type_list.GetTypeAtIndex(0); return TypeSP(); } -size_t Module::FindTypes( +void Module::FindTypes( ConstString name, bool exact_match, size_t max_matches, llvm::DenseSet<lldb_private::SymbolFile *> &searched_symbol_files, TypeList &types) { - size_t num_matches = 0; const char *type_name_cstr = name.GetCString(); llvm::StringRef type_scope; llvm::StringRef type_basename; - const bool append = true; TypeClass type_class = eTypeClassAny; TypeMap typesmap; @@ -1008,58 +975,66 @@ size_t Module::FindTypes( exact_match = type_scope.consume_front("::"); ConstString type_basename_const_str(type_basename); - if (FindTypes_Impl(type_basename_const_str, nullptr, append, max_matches, - searched_symbol_files, typesmap)) { + FindTypes_Impl(type_basename_const_str, nullptr, max_matches, + searched_symbol_files, typesmap); + if (typesmap.GetSize()) typesmap.RemoveMismatchedTypes(type_scope, type_basename, type_class, exact_match); - num_matches = typesmap.GetSize(); - } } else { // The type is not in a namespace/class scope, just search for it by // basename if (type_class != eTypeClassAny && !type_basename.empty()) { // The "type_name_cstr" will have been modified if we have a valid type // class prefix (like "struct", "class", "union", "typedef" etc). - FindTypes_Impl(ConstString(type_basename), nullptr, append, UINT_MAX, + FindTypes_Impl(ConstString(type_basename), nullptr, UINT_MAX, searched_symbol_files, typesmap); typesmap.RemoveMismatchedTypes(type_scope, type_basename, type_class, exact_match); - num_matches = typesmap.GetSize(); } else { - num_matches = FindTypes_Impl(name, nullptr, append, UINT_MAX, - searched_symbol_files, typesmap); + FindTypes_Impl(name, nullptr, UINT_MAX, searched_symbol_files, typesmap); if (exact_match) { std::string name_str(name.AsCString("")); typesmap.RemoveMismatchedTypes(type_scope, name_str, type_class, exact_match); - num_matches = typesmap.GetSize(); } } } - if (num_matches > 0) { + if (typesmap.GetSize()) { SymbolContext sc; sc.module_sp = shared_from_this(); sc.SortTypeList(typesmap, types); } - return num_matches; } -SymbolVendor *Module::GetSymbolVendor(bool can_create, - lldb_private::Stream *feedback_strm) { - if (!m_did_load_symbol_vendor.load()) { +void Module::FindTypes(llvm::ArrayRef<CompilerContext> pattern, + LanguageSet languages, TypeMap &types) { + static Timer::Category func_cat(LLVM_PRETTY_FUNCTION); + Timer scoped_timer(func_cat, LLVM_PRETTY_FUNCTION); + if (SymbolFile *symbols = GetSymbolFile()) + symbols->FindTypes(pattern, languages, types); +} + +SymbolFile *Module::GetSymbolFile(bool can_create, Stream *feedback_strm) { + if (!m_did_load_symfile.load()) { std::lock_guard<std::recursive_mutex> guard(m_mutex); - if (!m_did_load_symbol_vendor.load() && can_create) { + if (!m_did_load_symfile.load() && can_create) { ObjectFile *obj_file = GetObjectFile(); if (obj_file != nullptr) { static Timer::Category func_cat(LLVM_PRETTY_FUNCTION); Timer scoped_timer(func_cat, LLVM_PRETTY_FUNCTION); m_symfile_up.reset( SymbolVendor::FindPlugin(shared_from_this(), feedback_strm)); - m_did_load_symbol_vendor = true; + m_did_load_symfile = true; } } } - return m_symfile_up.get(); + return m_symfile_up ? m_symfile_up->GetSymbolFile() : nullptr; +} + +Symtab *Module::GetSymtab() { + if (SymbolFile *symbols = GetSymbolFile()) + return symbols->GetSymtab(); + return nullptr; } void Module::SetFileSpecAndObjectName(const FileSpec &file, @@ -1232,20 +1207,12 @@ void Module::Dump(Stream *s) { if (objfile) objfile->Dump(s); - SymbolVendor *symbols = GetSymbolVendor(); - if (symbols) - symbols->Dump(s); + if (SymbolFile *symbols = GetSymbolFile()) + symbols->Dump(*s); s->IndentLess(); } -TypeList *Module::GetTypeList() { - SymbolVendor *symbols = GetSymbolVendor(); - if (symbols) - return &symbols->GetTypeList(); - return nullptr; -} - ConstString Module::GetObjectName() const { return m_object_name; } ObjectFile *Module::GetObjectFile() { @@ -1295,9 +1262,8 @@ void Module::SectionFileAddressesChanged() { ObjectFile *obj_file = GetObjectFile(); if (obj_file) obj_file->SectionFileAddressesChanged(); - SymbolVendor *sym_vendor = GetSymbolVendor(); - if (sym_vendor != nullptr) - sym_vendor->SectionFileAddressesChanged(); + if (SymbolFile *symbols = GetSymbolFile()) + symbols->SectionFileAddressesChanged(); } UnwindTable &Module::GetUnwindTable() { @@ -1308,7 +1274,7 @@ UnwindTable &Module::GetUnwindTable() { SectionList *Module::GetUnifiedSectionList() { if (!m_sections_up) - m_sections_up = llvm::make_unique<SectionList>(); + m_sections_up = std::make_unique<SectionList>(); return m_sections_up.get(); } @@ -1318,13 +1284,9 @@ const Symbol *Module::FindFirstSymbolWithNameAndType(ConstString name, Timer scoped_timer( func_cat, "Module::FindFirstSymbolWithNameAndType (name = %s, type = %i)", name.AsCString(), symbol_type); - SymbolVendor *sym_vendor = GetSymbolVendor(); - if (sym_vendor) { - Symtab *symtab = sym_vendor->GetSymtab(); - if (symtab) - return symtab->FindFirstSymbolWithNameAndType( - name, symbol_type, Symtab::eDebugAny, Symtab::eVisibilityAny); - } + if (Symtab *symtab = GetSymtab()) + return symtab->FindFirstSymbolWithNameAndType( + name, symbol_type, Symtab::eDebugAny, Symtab::eVisibilityAny); return nullptr; } void Module::SymbolIndicesToSymbolContextList( @@ -1345,23 +1307,18 @@ void Module::SymbolIndicesToSymbolContextList( } } -size_t Module::FindFunctionSymbols(ConstString name, +void Module::FindFunctionSymbols(ConstString name, uint32_t name_type_mask, SymbolContextList &sc_list) { static Timer::Category func_cat(LLVM_PRETTY_FUNCTION); Timer scoped_timer(func_cat, "Module::FindSymbolsFunctions (name = %s, mask = 0x%8.8x)", name.AsCString(), name_type_mask); - SymbolVendor *sym_vendor = GetSymbolVendor(); - if (sym_vendor) { - Symtab *symtab = sym_vendor->GetSymtab(); - if (symtab) - return symtab->FindFunctionSymbols(name, name_type_mask, sc_list); - } - return 0; + if (Symtab *symtab = GetSymtab()) + symtab->FindFunctionSymbols(name, name_type_mask, sc_list); } -size_t Module::FindSymbolsWithNameAndType(ConstString name, +void Module::FindSymbolsWithNameAndType(ConstString name, SymbolType symbol_type, SymbolContextList &sc_list) { // No need to protect this call using m_mutex all other method calls are @@ -1371,22 +1328,16 @@ size_t Module::FindSymbolsWithNameAndType(ConstString name, Timer scoped_timer( func_cat, "Module::FindSymbolsWithNameAndType (name = %s, type = %i)", name.AsCString(), symbol_type); - const size_t initial_size = sc_list.GetSize(); - SymbolVendor *sym_vendor = GetSymbolVendor(); - if (sym_vendor) { - Symtab *symtab = sym_vendor->GetSymtab(); - if (symtab) { - std::vector<uint32_t> symbol_indexes; - symtab->FindAllSymbolsWithNameAndType(name, symbol_type, symbol_indexes); - SymbolIndicesToSymbolContextList(symtab, symbol_indexes, sc_list); - } + if (Symtab *symtab = GetSymtab()) { + std::vector<uint32_t> symbol_indexes; + symtab->FindAllSymbolsWithNameAndType(name, symbol_type, symbol_indexes); + SymbolIndicesToSymbolContextList(symtab, symbol_indexes, sc_list); } - return sc_list.GetSize() - initial_size; } -size_t Module::FindSymbolsMatchingRegExAndType(const RegularExpression ®ex, - SymbolType symbol_type, - SymbolContextList &sc_list) { +void Module::FindSymbolsMatchingRegExAndType(const RegularExpression ®ex, + SymbolType symbol_type, + SymbolContextList &sc_list) { // No need to protect this call using m_mutex all other method calls are // already thread safe. @@ -1395,35 +1346,27 @@ size_t Module::FindSymbolsMatchingRegExAndType(const RegularExpression ®ex, func_cat, "Module::FindSymbolsMatchingRegExAndType (regex = %s, type = %i)", regex.GetText().str().c_str(), symbol_type); - const size_t initial_size = sc_list.GetSize(); - SymbolVendor *sym_vendor = GetSymbolVendor(); - if (sym_vendor) { - Symtab *symtab = sym_vendor->GetSymtab(); - if (symtab) { - std::vector<uint32_t> symbol_indexes; - symtab->FindAllSymbolsMatchingRexExAndType( - regex, symbol_type, Symtab::eDebugAny, Symtab::eVisibilityAny, - symbol_indexes); - SymbolIndicesToSymbolContextList(symtab, symbol_indexes, sc_list); - } + if (Symtab *symtab = GetSymtab()) { + std::vector<uint32_t> symbol_indexes; + symtab->FindAllSymbolsMatchingRexExAndType( + regex, symbol_type, Symtab::eDebugAny, Symtab::eVisibilityAny, + symbol_indexes); + SymbolIndicesToSymbolContextList(symtab, symbol_indexes, sc_list); } - return sc_list.GetSize() - initial_size; } void Module::PreloadSymbols() { std::lock_guard<std::recursive_mutex> guard(m_mutex); - SymbolVendor * sym_vendor = GetSymbolVendor(); - if (!sym_vendor) { + SymbolFile *sym_file = GetSymbolFile(); + if (!sym_file) return; - } + // Prime the symbol file first, since it adds symbols to the symbol table. - if (SymbolFile *symbol_file = sym_vendor->GetSymbolFile()) { - symbol_file->PreloadSymbols(); - } + sym_file->PreloadSymbols(); + // Now we can prime the symbol table. - if (Symtab * symtab = sym_vendor->GetSymtab()) { + if (Symtab *symtab = sym_file->GetSymtab()) symtab->PreloadSymbols(); - } } void Module::SetSymbolFileFileSpec(const FileSpec &file) { @@ -1433,7 +1376,7 @@ void Module::SetSymbolFileFileSpec(const FileSpec &file) { // Remove any sections in the unified section list that come from the // current symbol vendor. SectionList *section_list = GetSectionList(); - SymbolFile *symbol_file = m_symfile_up->GetSymbolFile(); + SymbolFile *symbol_file = GetSymbolFile(); if (section_list && symbol_file) { ObjectFile *obj_file = symbol_file->GetObjectFile(); // Make sure we have an object file and that the symbol vendor's objfile @@ -1489,7 +1432,7 @@ void Module::SetSymbolFileFileSpec(const FileSpec &file) { } m_symfile_spec = file; m_symfile_up.reset(); - m_did_load_symbol_vendor = false; + m_did_load_symfile = false; } bool Module::IsExecutable() { @@ -1654,6 +1597,26 @@ bool Module::RemapSourceFile(llvm::StringRef path, return m_source_mappings.RemapPath(path, new_path); } +bool Module::MergeArchitecture(const ArchSpec &arch_spec) { + if (!arch_spec.IsValid()) + return false; + LLDB_LOG(GetLogIfAllCategoriesSet(LIBLLDB_LOG_OBJECT | LIBLLDB_LOG_MODULES), + "module has arch %s, merging/replacing with arch %s", + m_arch.GetTriple().getTriple().c_str(), + arch_spec.GetTriple().getTriple().c_str()); + if (!m_arch.IsCompatibleMatch(arch_spec)) { + // The new architecture is different, we just need to replace it. + return SetArchitecture(arch_spec); + } + + // Merge bits from arch_spec into "merged_arch" and set our architecture. + ArchSpec merged_arch(m_arch); + merged_arch.MergeFrom(arch_spec); + // SetArchitecture() is a no-op if m_arch is already valid. + m_arch = ArchSpec(); + return SetArchitecture(merged_arch); +} + llvm::VersionTuple Module::GetVersion() { if (ObjectFile *obj_file = GetObjectFile()) return obj_file->GetVersion(); diff --git a/source/Core/ModuleList.cpp b/source/Core/ModuleList.cpp index 9d795f9e5586..b0567a902fd7 100644 --- a/source/Core/ModuleList.cpp +++ b/source/Core/ModuleList.cpp @@ -17,6 +17,7 @@ #include "lldb/Symbol/LocateSymbolFile.h" #include "lldb/Symbol/ObjectFile.h" #include "lldb/Symbol/SymbolContext.h" +#include "lldb/Symbol/TypeList.h" #include "lldb/Symbol/VariableList.h" #include "lldb/Utility/ArchSpec.h" #include "lldb/Utility/ConstString.h" @@ -56,40 +57,26 @@ class SymbolFile; namespace lldb_private { class Target; } -namespace lldb_private { -class TypeList; -} using namespace lldb; using namespace lldb_private; namespace { -static constexpr PropertyDefinition g_properties[] = { - {"enable-external-lookup", OptionValue::eTypeBoolean, true, true, nullptr, - {}, - "Control the use of external tools and repositories to locate symbol " - "files. Directories listed in target.debug-file-search-paths and " - "directory of the executable are always checked first for separate debug " - "info files. Then depending on this setting: " - "On macOS, Spotlight would be also used to locate a matching .dSYM " - "bundle based on the UUID of the executable. " - "On NetBSD, directory /usr/libdata/debug would be also searched. " - "On platforms other than NetBSD directory /usr/lib/debug would be " - "also searched." - }, - {"clang-modules-cache-path", OptionValue::eTypeFileSpec, true, 0, nullptr, - {}, - "The path to the clang modules cache directory (-fmodules-cache-path)."}}; - -enum { ePropertyEnableExternalLookup, ePropertyClangModulesCachePath }; +#define LLDB_PROPERTIES_modulelist +#include "CoreProperties.inc" + +enum { +#define LLDB_PROPERTIES_modulelist +#include "CorePropertiesEnum.inc" +}; } // namespace ModuleListProperties::ModuleListProperties() { m_collection_sp = std::make_shared<OptionValueProperties>(ConstString("symbols")); - m_collection_sp->Initialize(g_properties); + m_collection_sp->Initialize(g_modulelist_properties); llvm::SmallString<128> path; clang::driver::Driver::getDefaultModuleCachePath(path); @@ -99,7 +86,7 @@ ModuleListProperties::ModuleListProperties() { bool ModuleListProperties::GetEnableExternalLookup() const { const uint32_t idx = ePropertyEnableExternalLookup; return m_collection_sp->GetPropertyAtIndexAsBoolean( - nullptr, idx, g_properties[idx].default_uint_value != 0); + nullptr, idx, g_modulelist_properties[idx].default_uint_value != 0); } bool ModuleListProperties::SetEnableExternalLookup(bool new_value) { @@ -135,9 +122,9 @@ ModuleList::ModuleList(ModuleList::Notifier *notifier) const ModuleList &ModuleList::operator=(const ModuleList &rhs) { if (this != &rhs) { std::lock(m_modules_mutex, rhs.m_modules_mutex); - std::lock_guard<std::recursive_mutex> lhs_guard(m_modules_mutex, + std::lock_guard<std::recursive_mutex> lhs_guard(m_modules_mutex, std::adopt_lock); - std::lock_guard<std::recursive_mutex> rhs_guard(rhs.m_modules_mutex, + std::lock_guard<std::recursive_mutex> rhs_guard(rhs.m_modules_mutex, std::adopt_lock); m_modules = rhs.m_modules; } @@ -155,8 +142,8 @@ void ModuleList::AppendImpl(const ModuleSP &module_sp, bool use_notifier) { } } -void ModuleList::Append(const ModuleSP &module_sp, bool notify) { - AppendImpl(module_sp, notify); +void ModuleList::Append(const ModuleSP &module_sp, bool notify) { + AppendImpl(module_sp, notify); } void ModuleList::ReplaceEquivalent(const ModuleSP &module_sp) { @@ -339,14 +326,10 @@ ModuleSP ModuleList::GetModuleAtIndexUnlocked(size_t idx) const { return module_sp; } -size_t ModuleList::FindFunctions(ConstString name, - FunctionNameType name_type_mask, - bool include_symbols, bool include_inlines, - bool append, - SymbolContextList &sc_list) const { - if (!append) - sc_list.Clear(); - +void ModuleList::FindFunctions(ConstString name, + FunctionNameType name_type_mask, + bool include_symbols, bool include_inlines, + SymbolContextList &sc_list) const { const size_t old_size = sc_list.GetSize(); if (name_type_mask & eFunctionNameTypeAuto) { @@ -357,7 +340,7 @@ size_t ModuleList::FindFunctions(ConstString name, for (pos = m_modules.begin(); pos != end; ++pos) { (*pos)->FindFunctions(lookup_info.GetLookupName(), nullptr, lookup_info.GetNameTypeMask(), include_symbols, - include_inlines, true, sc_list); + include_inlines, sc_list); } const size_t new_size = sc_list.GetSize(); @@ -369,15 +352,14 @@ size_t ModuleList::FindFunctions(ConstString name, collection::const_iterator pos, end = m_modules.end(); for (pos = m_modules.begin(); pos != end; ++pos) { (*pos)->FindFunctions(name, nullptr, name_type_mask, include_symbols, - include_inlines, true, sc_list); + include_inlines, sc_list); } } - return sc_list.GetSize() - old_size; } -size_t ModuleList::FindFunctionSymbols(ConstString name, - lldb::FunctionNameType name_type_mask, - SymbolContextList &sc_list) { +void ModuleList::FindFunctionSymbols(ConstString name, + lldb::FunctionNameType name_type_mask, + SymbolContextList &sc_list) { const size_t old_size = sc_list.GetSize(); if (name_type_mask & eFunctionNameTypeAuto) { @@ -401,96 +383,66 @@ size_t ModuleList::FindFunctionSymbols(ConstString name, (*pos)->FindFunctionSymbols(name, name_type_mask, sc_list); } } - - return sc_list.GetSize() - old_size; } -size_t ModuleList::FindFunctions(const RegularExpression &name, - bool include_symbols, bool include_inlines, - bool append, SymbolContextList &sc_list) { - const size_t old_size = sc_list.GetSize(); - +void ModuleList::FindFunctions(const RegularExpression &name, + bool include_symbols, bool include_inlines, + SymbolContextList &sc_list) { std::lock_guard<std::recursive_mutex> guard(m_modules_mutex); collection::const_iterator pos, end = m_modules.end(); for (pos = m_modules.begin(); pos != end; ++pos) { - (*pos)->FindFunctions(name, include_symbols, include_inlines, append, - sc_list); + (*pos)->FindFunctions(name, include_symbols, include_inlines, sc_list); } - - return sc_list.GetSize() - old_size; } -size_t ModuleList::FindCompileUnits(const FileSpec &path, bool append, - SymbolContextList &sc_list) const { - if (!append) - sc_list.Clear(); - +void ModuleList::FindCompileUnits(const FileSpec &path, + SymbolContextList &sc_list) const { std::lock_guard<std::recursive_mutex> guard(m_modules_mutex); collection::const_iterator pos, end = m_modules.end(); for (pos = m_modules.begin(); pos != end; ++pos) { - (*pos)->FindCompileUnits(path, true, sc_list); + (*pos)->FindCompileUnits(path, sc_list); } - - return sc_list.GetSize(); } -size_t ModuleList::FindGlobalVariables(ConstString name, - size_t max_matches, - VariableList &variable_list) const { - size_t initial_size = variable_list.GetSize(); +void ModuleList::FindGlobalVariables(ConstString name, size_t max_matches, + VariableList &variable_list) const { std::lock_guard<std::recursive_mutex> guard(m_modules_mutex); collection::const_iterator pos, end = m_modules.end(); for (pos = m_modules.begin(); pos != end; ++pos) { (*pos)->FindGlobalVariables(name, nullptr, max_matches, variable_list); } - return variable_list.GetSize() - initial_size; } -size_t ModuleList::FindGlobalVariables(const RegularExpression ®ex, - size_t max_matches, - VariableList &variable_list) const { - size_t initial_size = variable_list.GetSize(); +void ModuleList::FindGlobalVariables(const RegularExpression ®ex, + size_t max_matches, + VariableList &variable_list) const { std::lock_guard<std::recursive_mutex> guard(m_modules_mutex); collection::const_iterator pos, end = m_modules.end(); for (pos = m_modules.begin(); pos != end; ++pos) { (*pos)->FindGlobalVariables(regex, max_matches, variable_list); } - return variable_list.GetSize() - initial_size; } -size_t ModuleList::FindSymbolsWithNameAndType(ConstString name, - SymbolType symbol_type, - SymbolContextList &sc_list, - bool append) const { +void ModuleList::FindSymbolsWithNameAndType(ConstString name, + SymbolType symbol_type, + SymbolContextList &sc_list) const { std::lock_guard<std::recursive_mutex> guard(m_modules_mutex); - if (!append) - sc_list.Clear(); - size_t initial_size = sc_list.GetSize(); - collection::const_iterator pos, end = m_modules.end(); for (pos = m_modules.begin(); pos != end; ++pos) (*pos)->FindSymbolsWithNameAndType(name, symbol_type, sc_list); - return sc_list.GetSize() - initial_size; } -size_t ModuleList::FindSymbolsMatchingRegExAndType( +void ModuleList::FindSymbolsMatchingRegExAndType( const RegularExpression ®ex, lldb::SymbolType symbol_type, - SymbolContextList &sc_list, bool append) const { + SymbolContextList &sc_list) const { std::lock_guard<std::recursive_mutex> guard(m_modules_mutex); - if (!append) - sc_list.Clear(); - size_t initial_size = sc_list.GetSize(); - collection::const_iterator pos, end = m_modules.end(); for (pos = m_modules.begin(); pos != end; ++pos) (*pos)->FindSymbolsMatchingRegExAndType(regex, symbol_type, sc_list); - return sc_list.GetSize() - initial_size; } -size_t ModuleList::FindModules(const ModuleSpec &module_spec, - ModuleList &matching_module_list) const { - size_t existing_matches = matching_module_list.GetSize(); - +void ModuleList::FindModules(const ModuleSpec &module_spec, + ModuleList &matching_module_list) const { std::lock_guard<std::recursive_mutex> guard(m_modules_mutex); collection::const_iterator pos, end = m_modules.end(); for (pos = m_modules.begin(); pos != end; ++pos) { @@ -498,7 +450,6 @@ size_t ModuleList::FindModules(const ModuleSpec &module_spec, if (module_sp->MatchesModuleSpec(module_spec)) matching_module_list.Append(module_sp); } - return matching_module_list.GetSize() - existing_matches; } ModuleSP ModuleList::FindModule(const Module *module_ptr) const { @@ -536,44 +487,36 @@ ModuleSP ModuleList::FindModule(const UUID &uuid) const { return module_sp; } -size_t -ModuleList::FindTypes(Module *search_first, ConstString name, - bool name_is_fully_qualified, size_t max_matches, - llvm::DenseSet<SymbolFile *> &searched_symbol_files, - TypeList &types) const { +void ModuleList::FindTypes(Module *search_first, ConstString name, + bool name_is_fully_qualified, size_t max_matches, + llvm::DenseSet<SymbolFile *> &searched_symbol_files, + TypeList &types) const { std::lock_guard<std::recursive_mutex> guard(m_modules_mutex); - size_t total_matches = 0; collection::const_iterator pos, end = m_modules.end(); if (search_first) { for (pos = m_modules.begin(); pos != end; ++pos) { if (search_first == pos->get()) { - total_matches += - search_first->FindTypes(name, name_is_fully_qualified, max_matches, - searched_symbol_files, types); + search_first->FindTypes(name, name_is_fully_qualified, max_matches, + searched_symbol_files, types); - if (total_matches >= max_matches) - break; + if (types.GetSize() >= max_matches) + return; } } } - if (total_matches < max_matches) { - for (pos = m_modules.begin(); pos != end; ++pos) { - // Search the module if the module is not equal to the one in the symbol - // context "sc". If "sc" contains a empty module shared pointer, then the - // comparison will always be true (valid_module_ptr != nullptr). - if (search_first != pos->get()) - total_matches += - (*pos)->FindTypes(name, name_is_fully_qualified, max_matches, - searched_symbol_files, types); - - if (total_matches >= max_matches) - break; - } - } + for (pos = m_modules.begin(); pos != end; ++pos) { + // Search the module if the module is not equal to the one in the symbol + // context "sc". If "sc" contains a empty module shared pointer, then the + // comparison will always be true (valid_module_ptr != nullptr). + if (search_first != pos->get()) + (*pos)->FindTypes(name, name_is_fully_qualified, max_matches, + searched_symbol_files, types); - return total_matches; + if (types.GetSize() >= max_matches) + return; + } } bool ModuleList::FindSourceFile(const FileSpec &orig_spec, @@ -641,11 +584,11 @@ void ModuleList::LogUUIDAndPaths(Log *log, const char *prefix_cstr) { for (pos = begin; pos != end; ++pos) { Module *module = pos->get(); const FileSpec &module_file_spec = module->GetFileSpec(); - log->Printf("%s[%u] %s (%s) \"%s\"", prefix_cstr ? prefix_cstr : "", - (uint32_t)std::distance(begin, pos), - module->GetUUID().GetAsString().c_str(), - module->GetArchitecture().GetArchitectureName(), - module_file_spec.GetPath().c_str()); + LLDB_LOGF(log, "%s[%u] %s (%s) \"%s\"", prefix_cstr ? prefix_cstr : "", + (uint32_t)std::distance(begin, pos), + module->GetUUID().GetAsString().c_str(), + module->GetArchitecture().GetArchitectureName(), + module_file_spec.GetPath().c_str()); } } } @@ -757,9 +700,9 @@ bool ModuleList::ModuleIsInCache(const Module *module_ptr) { return false; } -size_t ModuleList::FindSharedModules(const ModuleSpec &module_spec, - ModuleList &matching_module_list) { - return GetSharedModuleList().FindModules(module_spec, matching_module_list); +void ModuleList::FindSharedModules(const ModuleSpec &module_spec, + ModuleList &matching_module_list) { + GetSharedModuleList().FindModules(module_spec, matching_module_list); } size_t ModuleList::RemoveOrphanSharedModules(bool mandatory) { @@ -794,8 +737,9 @@ Status ModuleList::GetSharedModule(const ModuleSpec &module_spec, // mutex list. if (!always_create) { ModuleList matching_module_list; - const size_t num_matching_modules = - shared_module_list.FindModules(module_spec, matching_module_list); + shared_module_list.FindModules(module_spec, matching_module_list); + const size_t num_matching_modules = matching_module_list.GetSize(); + if (num_matching_modules > 0) { for (size_t module_idx = 0; module_idx < num_matching_modules; ++module_idx) { @@ -808,8 +752,9 @@ Status ModuleList::GetSharedModule(const ModuleSpec &module_spec, Log *log(lldb_private::GetLogIfAnyCategoriesSet(LIBLLDB_LOG_MODULES)); if (log != nullptr) - log->Printf("module changed: %p, removing from global module list", - static_cast<void *>(module_sp.get())); + LLDB_LOGF(log, + "module changed: %p, removing from global module list", + static_cast<void *>(module_sp.get())); shared_module_list.Remove(module_sp); module_sp.reset(); @@ -945,8 +890,8 @@ Status ModuleList::GetSharedModule(const ModuleSpec &module_spec, platform_module_spec.GetSymbolFileSpec() = located_binary_modulespec.GetSymbolFileSpec(); ModuleList matching_module_list; - if (shared_module_list.FindModules(platform_module_spec, - matching_module_list) > 0) { + shared_module_list.FindModules(platform_module_spec, matching_module_list); + if (!matching_module_list.IsEmpty()) { module_sp = matching_module_list.GetModuleAtIndex(0); // If we didn't have a UUID in mind when looking for the object file, diff --git a/source/Core/PluginManager.cpp b/source/Core/PluginManager.cpp index 24cadcd85bf5..80b64fb832fa 100644 --- a/source/Core/PluginManager.cpp +++ b/source/Core/PluginManager.cpp @@ -1341,10 +1341,10 @@ PluginManager::GetPlatformCreateCallbackForPluginName(ConstString name) { return nullptr; } -size_t PluginManager::AutoCompletePlatformName(llvm::StringRef name, - StringList &matches) { +void PluginManager::AutoCompletePlatformName(llvm::StringRef name, + CompletionRequest &request) { if (name.empty()) - return matches.GetSize(); + return; std::lock_guard<std::recursive_mutex> guard(GetPlatformInstancesMutex()); PlatformInstances &instances = GetPlatformInstances(); @@ -1354,9 +1354,8 @@ size_t PluginManager::AutoCompletePlatformName(llvm::StringRef name, for (pos = instances.begin(); pos != end; ++pos) { llvm::StringRef plugin_name(pos->name.GetCString()); if (plugin_name.startswith(name_sref)) - matches.AppendString(plugin_name.data()); + request.AddCompletion(plugin_name.data()); } - return matches.GetSize(); } #pragma mark Process @@ -2084,12 +2083,11 @@ PluginManager::GetInstrumentationRuntimeCreateCallbackForPluginName( #pragma mark TypeSystem struct TypeSystemInstance { - TypeSystemInstance() : name(), description(), create_callback(nullptr) {} - ConstString name; std::string description; TypeSystemCreateInstance create_callback; - TypeSystemEnumerateSupportedLanguages enumerate_callback; + LanguageSet supported_languages_for_types; + LanguageSet supported_languages_for_expressions; }; typedef std::vector<TypeSystemInstance> TypeSystemInstances; @@ -2104,11 +2102,11 @@ static TypeSystemInstances &GetTypeSystemInstances() { return g_instances; } -bool PluginManager::RegisterPlugin(ConstString name, - const char *description, - TypeSystemCreateInstance create_callback, - TypeSystemEnumerateSupportedLanguages - enumerate_supported_languages_callback) { +bool PluginManager::RegisterPlugin( + ConstString name, const char *description, + TypeSystemCreateInstance create_callback, + LanguageSet supported_languages_for_types, + LanguageSet supported_languages_for_expressions) { if (create_callback) { TypeSystemInstance instance; assert((bool)name); @@ -2116,7 +2114,8 @@ bool PluginManager::RegisterPlugin(ConstString name, if (description && description[0]) instance.description = description; instance.create_callback = create_callback; - instance.enumerate_callback = enumerate_supported_languages_callback; + instance.supported_languages_for_types = supported_languages_for_types; + instance.supported_languages_for_expressions = supported_languages_for_expressions; std::lock_guard<std::recursive_mutex> guard(GetTypeSystemMutex()); GetTypeSystemInstances().push_back(instance); } @@ -2164,30 +2163,22 @@ PluginManager::GetTypeSystemCreateCallbackForPluginName( return nullptr; } -TypeSystemEnumerateSupportedLanguages -PluginManager::GetTypeSystemEnumerateSupportedLanguagesCallbackAtIndex( - uint32_t idx) { +LanguageSet PluginManager::GetAllTypeSystemSupportedLanguagesForTypes() { std::lock_guard<std::recursive_mutex> guard(GetTypeSystemMutex()); + LanguageSet all; TypeSystemInstances &instances = GetTypeSystemInstances(); - if (idx < instances.size()) - return instances[idx].enumerate_callback; - return nullptr; + for (unsigned i = 0; i < instances.size(); ++i) + all.bitvector |= instances[i].supported_languages_for_types.bitvector; + return all; } -TypeSystemEnumerateSupportedLanguages -PluginManager::GetTypeSystemEnumerateSupportedLanguagesCallbackForPluginName( - ConstString name) { - if (name) { - std::lock_guard<std::recursive_mutex> guard(GetTypeSystemMutex()); - TypeSystemInstances &instances = GetTypeSystemInstances(); - - TypeSystemInstances::iterator pos, end = instances.end(); - for (pos = instances.begin(); pos != end; ++pos) { - if (name == pos->name) - return pos->enumerate_callback; - } - } - return nullptr; +LanguageSet PluginManager::GetAllTypeSystemSupportedLanguagesForExpressions() { + std::lock_guard<std::recursive_mutex> guard(GetTypeSystemMutex()); + LanguageSet all; + TypeSystemInstances &instances = GetTypeSystemInstances(); + for (unsigned i = 0; i < instances.size(); ++i) + all.bitvector |= instances[i].supported_languages_for_expressions.bitvector; + return all; } #pragma mark REPL @@ -2198,7 +2189,7 @@ struct REPLInstance { ConstString name; std::string description; REPLCreateInstance create_callback; - REPLEnumerateSupportedLanguages enumerate_languages_callback; + LanguageSet supported_languages; }; typedef std::vector<REPLInstance> REPLInstances; @@ -2213,10 +2204,9 @@ static REPLInstances &GetREPLInstances() { return g_instances; } -bool PluginManager::RegisterPlugin( - ConstString name, const char *description, - REPLCreateInstance create_callback, - REPLEnumerateSupportedLanguages enumerate_languages_callback) { +bool PluginManager::RegisterPlugin(ConstString name, const char *description, + REPLCreateInstance create_callback, + LanguageSet supported_languages) { if (create_callback) { REPLInstance instance; assert((bool)name); @@ -2224,7 +2214,7 @@ bool PluginManager::RegisterPlugin( if (description && description[0]) instance.description = description; instance.create_callback = create_callback; - instance.enumerate_languages_callback = enumerate_languages_callback; + instance.supported_languages = supported_languages; std::lock_guard<std::recursive_mutex> guard(GetREPLMutex()); GetREPLInstances().push_back(instance); } @@ -2270,29 +2260,13 @@ PluginManager::GetREPLCreateCallbackForPluginName(ConstString name) { return nullptr; } -REPLEnumerateSupportedLanguages -PluginManager::GetREPLEnumerateSupportedLanguagesCallbackAtIndex(uint32_t idx) { +LanguageSet PluginManager::GetREPLAllTypeSystemSupportedLanguages() { std::lock_guard<std::recursive_mutex> guard(GetREPLMutex()); + LanguageSet all; REPLInstances &instances = GetREPLInstances(); - if (idx < instances.size()) - return instances[idx].enumerate_languages_callback; - return nullptr; -} - -REPLEnumerateSupportedLanguages -PluginManager::GetREPLSystemEnumerateSupportedLanguagesCallbackForPluginName( - ConstString name) { - if (name) { - std::lock_guard<std::recursive_mutex> guard(GetREPLMutex()); - REPLInstances &instances = GetREPLInstances(); - - REPLInstances::iterator pos, end = instances.end(); - for (pos = instances.begin(); pos != end; ++pos) { - if (name == pos->name) - return pos->enumerate_languages_callback; - } - } - return nullptr; + for (unsigned i = 0; i < instances.size(); ++i) + all.bitvector |= instances[i].supported_languages.bitvector; + return all; } #pragma mark PluginManager diff --git a/source/Core/SearchFilter.cpp b/source/Core/SearchFilter.cpp index 531fa078de29..e02b4f66b58c 100644 --- a/source/Core/SearchFilter.cpp +++ b/source/Core/SearchFilter.cpp @@ -13,7 +13,7 @@ #include "lldb/Core/ModuleList.h" #include "lldb/Symbol/CompileUnit.h" #include "lldb/Symbol/SymbolContext.h" -#include "lldb/Symbol/SymbolVendor.h" +#include "lldb/Symbol/SymbolFile.h" #include "lldb/Target/Target.h" #include "lldb/Utility/ConstString.h" #include "lldb/Utility/Status.h" @@ -209,7 +209,7 @@ void SearchFilter::Search(Searcher &searcher) { empty_sc.target_sp = m_target_sp; if (searcher.GetDepth() == lldb::eSearchDepthTarget) - searcher.SearchCallback(*this, empty_sc, nullptr, false); + searcher.SearchCallback(*this, empty_sc, nullptr); else DoModuleIteration(empty_sc, searcher); } @@ -222,7 +222,7 @@ void SearchFilter::SearchInModuleList(Searcher &searcher, ModuleList &modules) { empty_sc.target_sp = m_target_sp; if (searcher.GetDepth() == lldb::eSearchDepthTarget) - searcher.SearchCallback(*this, empty_sc, nullptr, false); + searcher.SearchCallback(*this, empty_sc, nullptr); else { std::lock_guard<std::recursive_mutex> guard(modules.GetMutex()); const size_t numModules = modules.GetSize(); @@ -252,7 +252,7 @@ SearchFilter::DoModuleIteration(const SymbolContext &context, if (context.module_sp) { if (searcher.GetDepth() == lldb::eSearchDepthModule) { SymbolContext matchingContext(context.module_sp.get()); - searcher.SearchCallback(*this, matchingContext, nullptr, false); + searcher.SearchCallback(*this, matchingContext, nullptr); } else { return DoCUIteration(context.module_sp, context, searcher); } @@ -272,7 +272,7 @@ SearchFilter::DoModuleIteration(const SymbolContext &context, SymbolContext matchingContext(m_target_sp, module_sp); Searcher::CallbackReturn shouldContinue = - searcher.SearchCallback(*this, matchingContext, nullptr, false); + searcher.SearchCallback(*this, matchingContext, nullptr); if (shouldContinue == Searcher::eCallbackReturnStop || shouldContinue == Searcher::eCallbackReturnPop) return shouldContinue; @@ -306,7 +306,7 @@ SearchFilter::DoCUIteration(const ModuleSP &module_sp, SymbolContext matchingContext(m_target_sp, module_sp, cu_sp.get()); shouldContinue = - searcher.SearchCallback(*this, matchingContext, nullptr, false); + searcher.SearchCallback(*this, matchingContext, nullptr); if (shouldContinue == Searcher::eCallbackReturnPop) return Searcher::eCallbackReturnContinue; @@ -316,10 +316,10 @@ SearchFilter::DoCUIteration(const ModuleSP &module_sp, // First make sure this compile unit's functions are parsed // since CompUnit::ForeachFunction only iterates over already // parsed functions. - SymbolVendor *sym_vendor = module_sp->GetSymbolVendor(); - if (!sym_vendor) + SymbolFile *sym_file = module_sp->GetSymbolFile(); + if (!sym_file) continue; - if (!sym_vendor->ParseFunctions(*cu_sp)) + if (!sym_file->ParseFunctions(*cu_sp)) continue; // If we got any functions, use ForeachFunction to do the iteration. cu_sp->ForeachFunction([&](const FunctionSP &func_sp) { @@ -328,9 +328,8 @@ SearchFilter::DoCUIteration(const ModuleSP &module_sp, if (searcher.GetDepth() == lldb::eSearchDepthFunction) { SymbolContext matchingContext(m_target_sp, module_sp, cu_sp.get(), func_sp.get()); - shouldContinue = searcher.SearchCallback(*this, - matchingContext, - nullptr, false); + shouldContinue = + searcher.SearchCallback(*this, matchingContext, nullptr); } else { shouldContinue = DoFunctionIteration(func_sp.get(), context, searcher); @@ -343,7 +342,7 @@ SearchFilter::DoCUIteration(const ModuleSP &module_sp, } else { if (CompUnitPasses(*context.comp_unit)) { SymbolContext matchingContext(m_target_sp, module_sp, context.comp_unit); - return searcher.SearchCallback(*this, matchingContext, nullptr, false); + return searcher.SearchCallback(*this, matchingContext, nullptr); } } return Searcher::eCallbackReturnContinue; @@ -431,7 +430,7 @@ void SearchFilterByModule::Search(Searcher &searcher) { if (searcher.GetDepth() == lldb::eSearchDepthTarget) { SymbolContext empty_sc; empty_sc.target_sp = m_target_sp; - searcher.SearchCallback(*this, empty_sc, nullptr, false); + searcher.SearchCallback(*this, empty_sc, nullptr); } // If the module file spec is a full path, then we can just find the one @@ -568,7 +567,7 @@ void SearchFilterByModuleList::Search(Searcher &searcher) { if (searcher.GetDepth() == lldb::eSearchDepthTarget) { SymbolContext empty_sc; empty_sc.target_sp = m_target_sp; - searcher.SearchCallback(*this, empty_sc, nullptr, false); + searcher.SearchCallback(*this, empty_sc, nullptr); } // If the module file spec is a full path, then we can just find the one @@ -640,7 +639,7 @@ SearchFilterSP SearchFilterByModuleList::CreateFromStructuredData( "SFBM::CFSD: filter module item %zu not a string.", i); return nullptr; } - modules.Append(FileSpec(module)); + modules.EmplaceBack(module); } } @@ -703,7 +702,7 @@ lldb::SearchFilterSP SearchFilterByModuleListAndCU::CreateFromStructuredData( "SFBM::CFSD: filter module item %zu not a string.", i); return result_sp; } - modules.Append(FileSpec(module)); + modules.EmplaceBack(module); } } @@ -725,7 +724,7 @@ lldb::SearchFilterSP SearchFilterByModuleListAndCU::CreateFromStructuredData( "SFBM::CFSD: filter cu item %zu not a string.", i); return nullptr; } - cus.Append(FileSpec(cu)); + cus.EmplaceBack(cu); } return std::make_shared<SearchFilterByModuleListAndCU>( @@ -777,7 +776,7 @@ void SearchFilterByModuleListAndCU::Search(Searcher &searcher) { if (searcher.GetDepth() == lldb::eSearchDepthTarget) { SymbolContext empty_sc; empty_sc.target_sp = m_target_sp; - searcher.SearchCallback(*this, empty_sc, nullptr, false); + searcher.SearchCallback(*this, empty_sc, nullptr); } // If the module file spec is a full path, then we can just find the one diff --git a/source/Core/Section.cpp b/source/Core/Section.cpp index f30ddd2c18c3..7615dc1d65c7 100644 --- a/source/Core/Section.cpp +++ b/source/Core/Section.cpp @@ -269,7 +269,7 @@ bool Section::ResolveContainedAddress(addr_t offset, Address &so_addr, bool Section::ContainsFileAddress(addr_t vm_addr) const { const addr_t file_addr = GetFileAddress(); - if (file_addr != LLDB_INVALID_ADDRESS) { + if (file_addr != LLDB_INVALID_ADDRESS && !IsThreadSpecific()) { if (file_addr <= vm_addr) { const addr_t offset = (vm_addr - file_addr) * m_target_byte_size; return offset < GetByteSize(); @@ -417,10 +417,6 @@ lldb::offset_t Section::GetSectionData(DataExtractor §ion_data) { #pragma mark SectionList -SectionList::SectionList() : m_sections() {} - -SectionList::~SectionList() {} - SectionList &SectionList::operator=(const SectionList &rhs) { if (this != &rhs) m_sections = rhs.m_sections; diff --git a/source/Core/SourceManager.cpp b/source/Core/SourceManager.cpp index 87065ab62425..42741e4ba4fe 100644 --- a/source/Core/SourceManager.cpp +++ b/source/Core/SourceManager.cpp @@ -324,10 +324,10 @@ bool SourceManager::GetDefaultFileAndLine(FileSpec &file_spec, uint32_t &line) { ConstString main_name("main"); bool symbols_okay = false; // Force it to be a debug symbol. bool inlines_okay = true; - bool append = false; - size_t num_matches = executable_ptr->FindFunctions( - main_name, nullptr, lldb::eFunctionNameTypeBase, inlines_okay, - symbols_okay, append, sc_list); + executable_ptr->FindFunctions(main_name, nullptr, + lldb::eFunctionNameTypeBase, inlines_okay, + symbols_okay, sc_list); + size_t num_matches = sc_list.GetSize(); for (size_t idx = 0; idx < num_matches; idx++) { SymbolContext sc; sc_list.GetContextAtIndex(idx, sc); diff --git a/source/Core/StreamFile.cpp b/source/Core/StreamFile.cpp index ce6e1ea2c18f..2ddb39659d66 100644 --- a/source/Core/StreamFile.cpp +++ b/source/Core/StreamFile.cpp @@ -8,6 +8,7 @@ #include "lldb/Core/StreamFile.h" #include "lldb/Host/FileSystem.h" +#include "lldb/Utility/Log.h" #include <stdio.h> @@ -15,35 +16,55 @@ using namespace lldb; using namespace lldb_private; // StreamFile constructor -StreamFile::StreamFile() : Stream(), m_file() {} +StreamFile::StreamFile() : Stream() { m_file_sp = std::make_shared<File>(); } StreamFile::StreamFile(uint32_t flags, uint32_t addr_size, ByteOrder byte_order) - : Stream(flags, addr_size, byte_order), m_file() {} - -StreamFile::StreamFile(int fd, bool transfer_ownership) - : Stream(), m_file(fd, transfer_ownership) {} + : Stream(flags, addr_size, byte_order) { + m_file_sp = std::make_shared<File>(); +} -StreamFile::StreamFile(FILE *fh, bool transfer_ownership) - : Stream(), m_file(fh, transfer_ownership) {} +StreamFile::StreamFile(int fd, bool transfer_ownership) : Stream() { + m_file_sp = + std::make_shared<NativeFile>(fd, File::eOpenOptionWrite, transfer_ownership); +} -StreamFile::StreamFile(const char *path) : Stream(), m_file() { - FileSystem::Instance().Open(m_file, FileSpec(path), - File::eOpenOptionWrite | - File::eOpenOptionCanCreate | - File::eOpenOptionCloseOnExec); +StreamFile::StreamFile(FILE *fh, bool transfer_ownership) : Stream() { + m_file_sp = std::make_shared<NativeFile>(fh, transfer_ownership); } -StreamFile::StreamFile(const char *path, uint32_t options, uint32_t permissions) - : Stream(), m_file() { +StreamFile::StreamFile(const char *path) : Stream() { + auto file = FileSystem::Instance().Open( + FileSpec(path), File::eOpenOptionWrite | File::eOpenOptionCanCreate | + File::eOpenOptionCloseOnExec); + if (file) + m_file_sp = std::move(file.get()); + else { + // TODO refactor this so the error gets popagated up instead of logged here. + LLDB_LOG_ERROR(GetLogIfAllCategoriesSet(LIBLLDB_LOG_HOST), file.takeError(), + "Cannot open {1}: {0}", path); + m_file_sp = std::make_shared<File>(); + } +} - FileSystem::Instance().Open(m_file, FileSpec(path), options, permissions); +StreamFile::StreamFile(const char *path, File::OpenOptions options, + uint32_t permissions) + : Stream() { + auto file = FileSystem::Instance().Open(FileSpec(path), options, permissions); + if (file) + m_file_sp = std::move(file.get()); + else { + // TODO refactor this so the error gets popagated up instead of logged here. + LLDB_LOG_ERROR(GetLogIfAllCategoriesSet(LIBLLDB_LOG_HOST), file.takeError(), + "Cannot open {1}: {0}", path); + m_file_sp = std::make_shared<File>(); + } } StreamFile::~StreamFile() {} -void StreamFile::Flush() { m_file.Flush(); } +void StreamFile::Flush() { m_file_sp->Flush(); } size_t StreamFile::WriteImpl(const void *s, size_t length) { - m_file.Write(s, length); + m_file_sp->Write(s, length); return length; } diff --git a/source/Core/Value.cpp b/source/Core/Value.cpp index fdb4adb5f431..3124b9338b36 100644 --- a/source/Core/Value.cpp +++ b/source/Core/Value.cpp @@ -314,7 +314,7 @@ bool Value::GetData(DataExtractor &data) { } Status Value::GetValueAsData(ExecutionContext *exe_ctx, DataExtractor &data, - uint32_t data_offset, Module *module) { + Module *module) { data.Clear(); Status error; @@ -520,13 +520,12 @@ Status Value::GetValueAsData(ExecutionContext *exe_ctx, DataExtractor &data, // Make sure we have enough room within "data", and if we don't make // something large enough that does - if (!data.ValidOffsetForDataOfSize(data_offset, byte_size)) { - auto data_sp = - std::make_shared<DataBufferHeap>(data_offset + byte_size, '\0'); + if (!data.ValidOffsetForDataOfSize(0, byte_size)) { + auto data_sp = std::make_shared<DataBufferHeap>(byte_size, '\0'); data.SetData(data_sp); } - uint8_t *dst = const_cast<uint8_t *>(data.PeekData(data_offset, byte_size)); + uint8_t *dst = const_cast<uint8_t *>(data.PeekData(0, byte_size)); if (dst != nullptr) { if (address_type == eAddressTypeHost) { // The address is an address in this process, so just copy it. @@ -597,7 +596,7 @@ Scalar &Value::ResolveValue(ExecutionContext *exe_ctx) { { DataExtractor data; lldb::addr_t addr = m_value.ULongLong(LLDB_INVALID_ADDRESS); - Status error(GetValueAsData(exe_ctx, data, 0, nullptr)); + Status error(GetValueAsData(exe_ctx, data, nullptr)); if (error.Success()) { Scalar scalar; if (compiler_type.GetValueAsScalar(data, 0, data.GetByteSize(), diff --git a/source/Core/ValueObject.cpp b/source/Core/ValueObject.cpp index 297365b4ecbd..74176eeace3a 100644 --- a/source/Core/ValueObject.cpp +++ b/source/Core/ValueObject.cpp @@ -73,7 +73,6 @@ class SymbolContextScope; using namespace lldb; using namespace lldb_private; -using namespace lldb_utility; static user_id_t g_value_obj_uid = 0; @@ -226,12 +225,12 @@ bool ValueObject::UpdateValueIfNeeded(bool update_format) { bool ValueObject::UpdateFormatsIfNeeded() { Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_DATAFORMATTERS)); - if (log) - log->Printf("[%s %p] checking for FormatManager revisions. ValueObject " - "rev: %d - Global rev: %d", - GetName().GetCString(), static_cast<void *>(this), - m_last_format_mgr_revision, - DataVisualization::GetCurrentRevision()); + LLDB_LOGF(log, + "[%s %p] checking for FormatManager revisions. ValueObject " + "rev: %d - Global rev: %d", + GetName().GetCString(), static_cast<void *>(this), + m_last_format_mgr_revision, + DataVisualization::GetCurrentRevision()); bool any_change = false; @@ -811,7 +810,7 @@ size_t ValueObject::GetPointeeData(DataExtractor &data, uint32_t item_idx, uint64_t ValueObject::GetData(DataExtractor &data, Status &error) { UpdateValueIfNeeded(false); ExecutionContext exe_ctx(GetExecutionContextRef()); - error = m_value.GetValueAsData(&exe_ctx, data, 0, GetModule().get()); + error = m_value.GetValueAsData(&exe_ctx, data, GetModule().get()); if (error.Fail()) { if (m_data.GetByteSize()) { data = m_data; @@ -1672,16 +1671,7 @@ bool ValueObject::IsRuntimeSupportValue() { if (!GetVariable() || !GetVariable()->IsArtificial()) return false; - LanguageType lang = eLanguageTypeUnknown; - if (auto *sym_ctx_scope = GetSymbolContextScope()) { - if (auto *func = sym_ctx_scope->CalculateSymbolContextFunction()) - lang = func->GetLanguage(); - else if (auto *comp_unit = - sym_ctx_scope->CalculateSymbolContextCompileUnit()) - lang = comp_unit->GetLanguage(); - } - - if (auto *runtime = process->GetLanguageRuntime(lang)) + if (auto *runtime = process->GetLanguageRuntime(GetVariable()->GetLanguage())) if (runtime->IsWhitelistedRuntimeValue(GetName())) return false; @@ -2726,9 +2716,9 @@ ValueObjectSP ValueObject::CreateConstantValue(ConstString name) { if (IsBitfield()) { Value v(Scalar(GetValueAsUnsigned(UINT64_MAX))); - m_error = v.GetValueAsData(&exe_ctx, data, 0, GetModule().get()); + m_error = v.GetValueAsData(&exe_ctx, data, GetModule().get()); } else - m_error = m_value.GetValueAsData(&exe_ctx, data, 0, GetModule().get()); + m_error = m_value.GetValueAsData(&exe_ctx, data, GetModule().get()); valobj_sp = ValueObjectConstResult::Create( exe_ctx.GetBestExecutionContextScope(), GetCompilerType(), name, data, @@ -3310,32 +3300,32 @@ lldb::ValueObjectSP ValueObjectManager::GetSP() { lldb::ProcessSP process_sp = GetProcessSP(); if (!process_sp) return lldb::ValueObjectSP(); - + const uint32_t current_stop_id = process_sp->GetLastNaturalStopID(); if (current_stop_id == m_stop_id) return m_user_valobj_sp; - + m_stop_id = current_stop_id; - + if (!m_root_valobj_sp) { m_user_valobj_sp.reset(); return m_root_valobj_sp; } - + m_user_valobj_sp = m_root_valobj_sp; - + if (m_use_dynamic != lldb::eNoDynamicValues) { lldb::ValueObjectSP dynamic_sp = m_user_valobj_sp->GetDynamicValue(m_use_dynamic); if (dynamic_sp) m_user_valobj_sp = dynamic_sp; } - + if (m_use_synthetic) { lldb::ValueObjectSP synthetic_sp = m_user_valobj_sp->GetSyntheticValue(m_use_synthetic); if (synthetic_sp) m_user_valobj_sp = synthetic_sp; } - + return m_user_valobj_sp; } diff --git a/source/Core/ValueObjectCast.cpp b/source/Core/ValueObjectCast.cpp index 6ccda8c32915..3a74b6a7fe18 100644 --- a/source/Core/ValueObjectCast.cpp +++ b/source/Core/ValueObjectCast.cpp @@ -79,7 +79,7 @@ bool ValueObjectCast::UpdateValue() { m_value.GetScalar() != old_value.GetScalar()); } ExecutionContext exe_ctx(GetExecutionContextRef()); - m_error = m_value.GetValueAsData(&exe_ctx, m_data, 0, GetModule().get()); + m_error = m_value.GetValueAsData(&exe_ctx, m_data, GetModule().get()); SetValueDidChange(m_parent->GetValueDidChange()); return true; } diff --git a/source/Core/ValueObjectChild.cpp b/source/Core/ValueObjectChild.cpp index 01f2e20dd0bc..6b4ada154d68 100644 --- a/source/Core/ValueObjectChild.cpp +++ b/source/Core/ValueObjectChild.cpp @@ -175,6 +175,30 @@ bool ValueObjectChild::UpdateValue() { // Set this object's scalar value to the address of its value by // adding its byte offset to the parent address m_value.GetScalar() += GetByteOffset(); + + // If a bitfield doesn't fit into the child_byte_size'd + // window at child_byte_offset, move the window forward + // until it fits. The problem here is that Value has no + // notion of bitfields and thus the Value's DataExtractor + // is sized like the bitfields CompilerType; a sequence of + // bitfields, however, can be larger than their underlying + // type. + if (m_bitfield_bit_offset) { + const bool thread_and_frame_only_if_stopped = true; + ExecutionContext exe_ctx(GetExecutionContextRef().Lock( + thread_and_frame_only_if_stopped)); + if (auto type_bit_size = GetCompilerType().GetBitSize( + exe_ctx.GetBestExecutionContextScope())) { + uint64_t bitfield_end = + m_bitfield_bit_size + m_bitfield_bit_offset; + if (bitfield_end > *type_bit_size) { + uint64_t overhang_bytes = + (bitfield_end - *type_bit_size + 7) / 8; + m_value.GetScalar() += overhang_bytes; + m_bitfield_bit_offset -= overhang_bytes * 8; + } + } + } } } break; @@ -203,7 +227,7 @@ bool ValueObjectChild::UpdateValue() { if (GetCompilerType().GetTypeInfo() & lldb::eTypeHasValue) { Value &value = is_instance_ptr_base ? m_parent->GetValue() : m_value; m_error = - value.GetValueAsData(&exe_ctx, m_data, 0, GetModule().get()); + value.GetValueAsData(&exe_ctx, m_data, GetModule().get()); } else { m_error.Clear(); // No value so nothing to read... } diff --git a/source/Core/ValueObjectConstResult.cpp b/source/Core/ValueObjectConstResult.cpp index a1b2cac96874..71620698da2a 100644 --- a/source/Core/ValueObjectConstResult.cpp +++ b/source/Core/ValueObjectConstResult.cpp @@ -182,7 +182,7 @@ ValueObjectConstResult::ValueObjectConstResult(ExecutionContextScope *exe_scope, m_name = name; ExecutionContext exe_ctx; exe_scope->CalculateExecutionContext(exe_ctx); - m_error = m_value.GetValueAsData(&exe_ctx, m_data, 0, module); + m_error = m_value.GetValueAsData(&exe_ctx, m_data, module); } ValueObjectConstResult::~ValueObjectConstResult() {} diff --git a/source/Core/ValueObjectDynamicValue.cpp b/source/Core/ValueObjectDynamicValue.cpp index 90b46d1f170d..59037e2b6b25 100644 --- a/source/Core/ValueObjectDynamicValue.cpp +++ b/source/Core/ValueObjectDynamicValue.cpp @@ -199,7 +199,7 @@ bool ValueObjectDynamicValue::UpdateValue() { ClearDynamicTypeInformation(); m_dynamic_type_info.Clear(); m_value = m_parent->GetValue(); - m_error = m_value.GetValueAsData(&exe_ctx, m_data, 0, GetModule().get()); + m_error = m_value.GetValueAsData(&exe_ctx, m_data, GetModule().get()); return m_error.Success(); } @@ -243,13 +243,13 @@ bool ValueObjectDynamicValue::UpdateValue() { m_value.SetValueType(value_type); if (has_changed_type && log) - log->Printf("[%s %p] has a new dynamic type %s", GetName().GetCString(), - static_cast<void *>(this), GetTypeName().GetCString()); + LLDB_LOGF(log, "[%s %p] has a new dynamic type %s", GetName().GetCString(), + static_cast<void *>(this), GetTypeName().GetCString()); if (m_address.IsValid() && m_dynamic_type_info) { // The variable value is in the Scalar value inside the m_value. We can // point our m_data right to it. - m_error = m_value.GetValueAsData(&exe_ctx, m_data, 0, GetModule().get()); + m_error = m_value.GetValueAsData(&exe_ctx, m_data, GetModule().get()); if (m_error.Success()) { if (!CanProvideValue()) { // this value object represents an aggregate type whose children have diff --git a/source/Core/ValueObjectMemory.cpp b/source/Core/ValueObjectMemory.cpp index 95d4330ee0c6..1a316bf3e7b0 100644 --- a/source/Core/ValueObjectMemory.cpp +++ b/source/Core/ValueObjectMemory.cpp @@ -168,7 +168,7 @@ bool ValueObjectMemory::UpdateValue() { case Value::eValueTypeScalar: // The variable value is in the Scalar value inside the m_value. We can // point our m_data right to it. - m_error = m_value.GetValueAsData(&exe_ctx, m_data, 0, GetModule().get()); + m_error = m_value.GetValueAsData(&exe_ctx, m_data, GetModule().get()); break; case Value::eValueTypeFileAddress: @@ -209,7 +209,7 @@ bool ValueObjectMemory::UpdateValue() { value.SetCompilerType(m_compiler_type); } - m_error = value.GetValueAsData(&exe_ctx, m_data, 0, GetModule().get()); + m_error = value.GetValueAsData(&exe_ctx, m_data, GetModule().get()); } break; } diff --git a/source/Core/ValueObjectRegister.cpp b/source/Core/ValueObjectRegister.cpp index 75a254fbbc21..7e97df6d2a34 100644 --- a/source/Core/ValueObjectRegister.cpp +++ b/source/Core/ValueObjectRegister.cpp @@ -18,6 +18,7 @@ #include "lldb/Target/StackFrame.h" #include "lldb/Target/Target.h" #include "lldb/Utility/DataExtractor.h" +#include "lldb/Utility/Log.h" #include "lldb/Utility/Scalar.h" #include "lldb/Utility/Status.h" #include "lldb/Utility/Stream.h" @@ -256,15 +257,19 @@ ValueObjectRegister::~ValueObjectRegister() {} CompilerType ValueObjectRegister::GetCompilerTypeImpl() { if (!m_compiler_type.IsValid()) { ExecutionContext exe_ctx(GetExecutionContextRef()); - Target *target = exe_ctx.GetTargetPtr(); - if (target) { - Module *exe_module = target->GetExecutableModulePointer(); - if (exe_module) { - TypeSystem *type_system = + if (auto *target = exe_ctx.GetTargetPtr()) { + if (auto *exe_module = target->GetExecutableModulePointer()) { + auto type_system_or_err = exe_module->GetTypeSystemForLanguage(eLanguageTypeC); - if (type_system) - m_compiler_type = type_system->GetBuiltinTypeForEncodingAndBitSize( - m_reg_info.encoding, m_reg_info.byte_size * 8); + if (auto err = type_system_or_err.takeError()) { + LLDB_LOG_ERROR( + lldb_private::GetLogIfAnyCategoriesSet(LIBLLDB_LOG_TYPES), + std::move(err), "Unable to get CompilerType from TypeSystem"); + } else { + m_compiler_type = + type_system_or_err->GetBuiltinTypeForEncodingAndBitSize( + m_reg_info.encoding, m_reg_info.byte_size * 8); + } } } } diff --git a/source/Core/ValueObjectSyntheticFilter.cpp b/source/Core/ValueObjectSyntheticFilter.cpp index 400473235759..a6bf35eac70a 100644 --- a/source/Core/ValueObjectSyntheticFilter.cpp +++ b/source/Core/ValueObjectSyntheticFilter.cpp @@ -87,20 +87,18 @@ size_t ValueObjectSynthetic::CalculateNumChildren(uint32_t max) { if (max < UINT32_MAX) { size_t num_children = m_synth_filter_up->CalculateNumChildren(max); - if (log) - log->Printf("[ValueObjectSynthetic::CalculateNumChildren] for VO of name " - "%s and type %s, the filter returned %zu child values", - GetName().AsCString(), GetTypeName().AsCString(), - num_children); + LLDB_LOGF(log, + "[ValueObjectSynthetic::CalculateNumChildren] for VO of name " + "%s and type %s, the filter returned %zu child values", + GetName().AsCString(), GetTypeName().AsCString(), num_children); return num_children; } else { size_t num_children = (m_synthetic_children_count = m_synth_filter_up->CalculateNumChildren(max)); - if (log) - log->Printf("[ValueObjectSynthetic::CalculateNumChildren] for VO of name " - "%s and type %s, the filter returned %zu child values", - GetName().AsCString(), GetTypeName().AsCString(), - num_children); + LLDB_LOGF(log, + "[ValueObjectSynthetic::CalculateNumChildren] for VO of name " + "%s and type %s, the filter returned %zu child values", + GetName().AsCString(), GetTypeName().AsCString(), num_children); return num_children; } } @@ -142,7 +140,7 @@ void ValueObjectSynthetic::CreateSynthFilter() { } m_synth_filter_up = (m_synth_sp->GetFrontEnd(*valobj_for_frontend)); if (!m_synth_filter_up) - m_synth_filter_up = llvm::make_unique<DummySyntheticFrontEnd>(*m_parent); + m_synth_filter_up = std::make_unique<DummySyntheticFrontEnd>(*m_parent); } bool ValueObjectSynthetic::UpdateValue() { @@ -163,21 +161,21 @@ bool ValueObjectSynthetic::UpdateValue() { // <rdar://problem/12424824> ConstString new_parent_type_name = m_parent->GetTypeName(); if (new_parent_type_name != m_parent_type_name) { - if (log) - log->Printf("[ValueObjectSynthetic::UpdateValue] name=%s, type changed " - "from %s to %s, recomputing synthetic filter", - GetName().AsCString(), m_parent_type_name.AsCString(), - new_parent_type_name.AsCString()); + LLDB_LOGF(log, + "[ValueObjectSynthetic::UpdateValue] name=%s, type changed " + "from %s to %s, recomputing synthetic filter", + GetName().AsCString(), m_parent_type_name.AsCString(), + new_parent_type_name.AsCString()); m_parent_type_name = new_parent_type_name; CreateSynthFilter(); } // let our backend do its update if (!m_synth_filter_up->Update()) { - if (log) - log->Printf("[ValueObjectSynthetic::UpdateValue] name=%s, synthetic " - "filter said caches are stale - clearing", - GetName().AsCString()); + LLDB_LOGF(log, + "[ValueObjectSynthetic::UpdateValue] name=%s, synthetic " + "filter said caches are stale - clearing", + GetName().AsCString()); // filter said that cached values are stale m_children_byindex.Clear(); m_name_toindex.Clear(); @@ -190,10 +188,10 @@ bool ValueObjectSynthetic::UpdateValue() { m_synthetic_children_count = UINT32_MAX; m_might_have_children = eLazyBoolCalculate; } else { - if (log) - log->Printf("[ValueObjectSynthetic::UpdateValue] name=%s, synthetic " - "filter said caches are still valid", - GetName().AsCString()); + LLDB_LOGF(log, + "[ValueObjectSynthetic::UpdateValue] name=%s, synthetic " + "filter said caches are still valid", + GetName().AsCString()); } m_provides_value = eLazyBoolCalculate; @@ -201,18 +199,18 @@ bool ValueObjectSynthetic::UpdateValue() { lldb::ValueObjectSP synth_val(m_synth_filter_up->GetSyntheticValue()); if (synth_val && synth_val->CanProvideValue()) { - if (log) - log->Printf("[ValueObjectSynthetic::UpdateValue] name=%s, synthetic " - "filter said it can provide a value", - GetName().AsCString()); + LLDB_LOGF(log, + "[ValueObjectSynthetic::UpdateValue] name=%s, synthetic " + "filter said it can provide a value", + GetName().AsCString()); m_provides_value = eLazyBoolYes; CopyValueData(synth_val.get()); } else { - if (log) - log->Printf("[ValueObjectSynthetic::UpdateValue] name=%s, synthetic " - "filter said it will not provide a value", - GetName().AsCString()); + LLDB_LOGF(log, + "[ValueObjectSynthetic::UpdateValue] name=%s, synthetic " + "filter said it will not provide a value", + GetName().AsCString()); m_provides_value = eLazyBoolNo; CopyValueData(m_parent); @@ -226,32 +224,32 @@ lldb::ValueObjectSP ValueObjectSynthetic::GetChildAtIndex(size_t idx, bool can_create) { Log *log = GetLogIfAllCategoriesSet(LIBLLDB_LOG_DATAFORMATTERS); - if (log) - log->Printf("[ValueObjectSynthetic::GetChildAtIndex] name=%s, retrieving " - "child at index %zu", - GetName().AsCString(), idx); + LLDB_LOGF(log, + "[ValueObjectSynthetic::GetChildAtIndex] name=%s, retrieving " + "child at index %zu", + GetName().AsCString(), idx); UpdateValueIfNeeded(); ValueObject *valobj; if (!m_children_byindex.GetValueForKey(idx, valobj)) { if (can_create && m_synth_filter_up != nullptr) { - if (log) - log->Printf("[ValueObjectSynthetic::GetChildAtIndex] name=%s, child at " - "index %zu not cached and will be created", - GetName().AsCString(), idx); + LLDB_LOGF(log, + "[ValueObjectSynthetic::GetChildAtIndex] name=%s, child at " + "index %zu not cached and will be created", + GetName().AsCString(), idx); lldb::ValueObjectSP synth_guy = m_synth_filter_up->GetChildAtIndex(idx); - if (log) - log->Printf( - "[ValueObjectSynthetic::GetChildAtIndex] name=%s, child at index " - "%zu created as %p (is " - "synthetic: %s)", - GetName().AsCString(), idx, static_cast<void *>(synth_guy.get()), - synth_guy.get() - ? (synth_guy->IsSyntheticChildrenGenerated() ? "yes" : "no") - : "no"); + LLDB_LOGF( + log, + "[ValueObjectSynthetic::GetChildAtIndex] name=%s, child at index " + "%zu created as %p (is " + "synthetic: %s)", + GetName().AsCString(), idx, static_cast<void *>(synth_guy.get()), + synth_guy.get() + ? (synth_guy->IsSyntheticChildrenGenerated() ? "yes" : "no") + : "no"); if (!synth_guy) return synth_guy; @@ -263,20 +261,20 @@ lldb::ValueObjectSP ValueObjectSynthetic::GetChildAtIndex(size_t idx, GetPreferredDisplayLanguage()); return synth_guy; } else { - if (log) - log->Printf("[ValueObjectSynthetic::GetChildAtIndex] name=%s, child at " - "index %zu not cached and cannot " - "be created (can_create = %s, synth_filter = %p)", - GetName().AsCString(), idx, can_create ? "yes" : "no", - static_cast<void *>(m_synth_filter_up.get())); + LLDB_LOGF(log, + "[ValueObjectSynthetic::GetChildAtIndex] name=%s, child at " + "index %zu not cached and cannot " + "be created (can_create = %s, synth_filter = %p)", + GetName().AsCString(), idx, can_create ? "yes" : "no", + static_cast<void *>(m_synth_filter_up.get())); return lldb::ValueObjectSP(); } } else { - if (log) - log->Printf("[ValueObjectSynthetic::GetChildAtIndex] name=%s, child at " - "index %zu cached as %p", - GetName().AsCString(), idx, static_cast<void *>(valobj)); + LLDB_LOGF(log, + "[ValueObjectSynthetic::GetChildAtIndex] name=%s, child at " + "index %zu cached as %p", + GetName().AsCString(), idx, static_cast<void *>(valobj)); return valobj->GetSP(); } @@ -322,7 +320,7 @@ lldb::ValueObjectSP ValueObjectSynthetic::GetNonSyntheticValue() { void ValueObjectSynthetic::CopyValueData(ValueObject *source) { m_value = (source->UpdateValueIfNeeded(), source->GetValue()); ExecutionContext exe_ctx(GetExecutionContextRef()); - m_error = m_value.GetValueAsData(&exe_ctx, m_data, 0, GetModule().get()); + m_error = m_value.GetValueAsData(&exe_ctx, m_data, GetModule().get()); } bool ValueObjectSynthetic::CanProvideValue() { diff --git a/source/Core/ValueObjectVariable.cpp b/source/Core/ValueObjectVariable.cpp index 5aee82493b28..33f9d5410843 100644 --- a/source/Core/ValueObjectVariable.cpp +++ b/source/Core/ValueObjectVariable.cpp @@ -221,7 +221,7 @@ bool ValueObjectVariable::UpdateValue() { // The variable value is in the Scalar value inside the m_value. We can // point our m_data right to it. m_error = - m_value.GetValueAsData(&exe_ctx, m_data, 0, GetModule().get()); + m_value.GetValueAsData(&exe_ctx, m_data, GetModule().get()); break; case Value::eValueTypeFileAddress: @@ -250,7 +250,7 @@ bool ValueObjectVariable::UpdateValue() { Value value(m_value); value.SetContext(Value::eContextTypeVariable, variable); m_error = - value.GetValueAsData(&exe_ctx, m_data, 0, GetModule().get()); + value.GetValueAsData(&exe_ctx, m_data, GetModule().get()); SetValueDidChange(value_type != old_value.GetValueType() || m_value.GetScalar() != old_value.GetScalar()); diff --git a/source/DataFormatters/FormatManager.cpp b/source/DataFormatters/FormatManager.cpp index dd2808a7cf7c..1eac372d79ec 100644 --- a/source/DataFormatters/FormatManager.cpp +++ b/source/DataFormatters/FormatManager.cpp @@ -30,7 +30,7 @@ struct FormatInfo { // current format }; -static FormatInfo g_format_infos[] = { +static constexpr FormatInfo g_format_infos[] = { {eFormatDefault, '\0', "default"}, {eFormatBoolean, 'B', "boolean"}, {eFormatBinary, 'b', "binary"}, @@ -69,7 +69,13 @@ static FormatInfo g_format_infos[] = { {eFormatAddressInfo, 'A', "address"}, {eFormatHexFloat, '\0', "hex float"}, {eFormatInstruction, 'i', "instruction"}, - {eFormatVoid, 'v', "void"}}; + {eFormatVoid, 'v', "void"}, + {eFormatUnicode8, 'u', "unicode8"}, +}; + +static_assert((sizeof(g_format_infos) / sizeof(g_format_infos[0])) == + kNumFormats, + "All formats must have a corresponding info entry."); static uint32_t g_num_format_infos = llvm::array_lengthof(g_format_infos); @@ -630,30 +636,29 @@ FormatManager::GetFormat(ValueObject &valobj, TypeFormatImplSP retval; Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_DATAFORMATTERS)); if (match_data.GetTypeForCache()) { - if (log) - log->Printf( - "\n\n[FormatManager::GetFormat] Looking into cache for type %s", - match_data.GetTypeForCache().AsCString("<invalid>")); + LLDB_LOGF(log, + "\n\n[FormatManager::GetFormat] Looking into cache for type %s", + match_data.GetTypeForCache().AsCString("<invalid>")); if (m_format_cache.GetFormat(match_data.GetTypeForCache(), retval)) { if (log) { - log->Printf( - "[FormatManager::GetFormat] Cache search success. Returning."); + LLDB_LOGF( + log, "[FormatManager::GetFormat] Cache search success. Returning."); LLDB_LOGV(log, "Cache hits: {0} - Cache Misses: {1}", m_format_cache.GetCacheHits(), m_format_cache.GetCacheMisses()); } return retval; } - if (log) - log->Printf( - "[FormatManager::GetFormat] Cache search failed. Going normal route"); + LLDB_LOGF( + log, + "[FormatManager::GetFormat] Cache search failed. Going normal route"); } retval = m_categories_map.GetFormat(match_data); if (!retval) { - if (log) - log->Printf("[FormatManager::GetFormat] Search failed. Giving language a " - "chance."); + LLDB_LOGF(log, + "[FormatManager::GetFormat] Search failed. Giving language a " + "chance."); for (lldb::LanguageType lang_type : match_data.GetCandidateLanguages()) { if (LanguageCategory *lang_category = GetCategoryForLanguage(lang_type)) { if (lang_category->Get(match_data, retval)) @@ -661,24 +666,22 @@ FormatManager::GetFormat(ValueObject &valobj, } } if (retval) { - if (log) - log->Printf( - "[FormatManager::GetFormat] Language search success. Returning."); + LLDB_LOGF( + log, + "[FormatManager::GetFormat] Language search success. Returning."); return retval; } } if (!retval) { - if (log) - log->Printf("[FormatManager::GetFormat] Search failed. Giving hardcoded " - "a chance."); + LLDB_LOGF(log, "[FormatManager::GetFormat] Search failed. Giving hardcoded " + "a chance."); retval = GetHardcodedFormat(match_data); } if (match_data.GetTypeForCache() && (!retval || !retval->NonCacheable())) { - if (log) - log->Printf("[FormatManager::GetFormat] Caching %p for type %s", - static_cast<void *>(retval.get()), - match_data.GetTypeForCache().AsCString("<invalid>")); + LLDB_LOGF(log, "[FormatManager::GetFormat] Caching %p for type %s", + static_cast<void *>(retval.get()), + match_data.GetTypeForCache().AsCString("<invalid>")); m_format_cache.SetFormat(match_data.GetTypeForCache(), retval); } LLDB_LOGV(log, "Cache hits: {0} - Cache Misses: {1}", @@ -708,30 +711,29 @@ FormatManager::GetSummaryFormat(ValueObject &valobj, TypeSummaryImplSP retval; Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_DATAFORMATTERS)); if (match_data.GetTypeForCache()) { - if (log) - log->Printf("\n\n[FormatManager::GetSummaryFormat] Looking into cache " - "for type %s", - match_data.GetTypeForCache().AsCString("<invalid>")); + LLDB_LOGF(log, + "\n\n[FormatManager::GetSummaryFormat] Looking into cache " + "for type %s", + match_data.GetTypeForCache().AsCString("<invalid>")); if (m_format_cache.GetSummary(match_data.GetTypeForCache(), retval)) { if (log) { - log->Printf("[FormatManager::GetSummaryFormat] Cache search success. " - "Returning."); + LLDB_LOGF(log, + "[FormatManager::GetSummaryFormat] Cache search success. " + "Returning."); LLDB_LOGV(log, "Cache hits: {0} - Cache Misses: {1}", m_format_cache.GetCacheHits(), m_format_cache.GetCacheMisses()); } return retval; } - if (log) - log->Printf("[FormatManager::GetSummaryFormat] Cache search failed. " - "Going normal route"); + LLDB_LOGF(log, "[FormatManager::GetSummaryFormat] Cache search failed. " + "Going normal route"); } retval = m_categories_map.GetSummaryFormat(match_data); if (!retval) { - if (log) - log->Printf("[FormatManager::GetSummaryFormat] Search failed. Giving " - "language a chance."); + LLDB_LOGF(log, "[FormatManager::GetSummaryFormat] Search failed. Giving " + "language a chance."); for (lldb::LanguageType lang_type : match_data.GetCandidateLanguages()) { if (LanguageCategory *lang_category = GetCategoryForLanguage(lang_type)) { if (lang_category->Get(match_data, retval)) @@ -739,24 +741,21 @@ FormatManager::GetSummaryFormat(ValueObject &valobj, } } if (retval) { - if (log) - log->Printf("[FormatManager::GetSummaryFormat] Language search " - "success. Returning."); + LLDB_LOGF(log, "[FormatManager::GetSummaryFormat] Language search " + "success. Returning."); return retval; } } if (!retval) { - if (log) - log->Printf("[FormatManager::GetSummaryFormat] Search failed. Giving " - "hardcoded a chance."); + LLDB_LOGF(log, "[FormatManager::GetSummaryFormat] Search failed. Giving " + "hardcoded a chance."); retval = GetHardcodedSummaryFormat(match_data); } if (match_data.GetTypeForCache() && (!retval || !retval->NonCacheable())) { - if (log) - log->Printf("[FormatManager::GetSummaryFormat] Caching %p for type %s", - static_cast<void *>(retval.get()), - match_data.GetTypeForCache().AsCString("<invalid>")); + LLDB_LOGF(log, "[FormatManager::GetSummaryFormat] Caching %p for type %s", + static_cast<void *>(retval.get()), + match_data.GetTypeForCache().AsCString("<invalid>")); m_format_cache.SetSummary(match_data.GetTypeForCache(), retval); } LLDB_LOGV(log, "Cache hits: {0} - Cache Misses: {1}", @@ -786,30 +785,29 @@ FormatManager::GetSyntheticChildren(ValueObject &valobj, SyntheticChildrenSP retval; Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_DATAFORMATTERS)); if (match_data.GetTypeForCache()) { - if (log) - log->Printf("\n\n[FormatManager::GetSyntheticChildren] Looking into " - "cache for type %s", - match_data.GetTypeForCache().AsCString("<invalid>")); + LLDB_LOGF(log, + "\n\n[FormatManager::GetSyntheticChildren] Looking into " + "cache for type %s", + match_data.GetTypeForCache().AsCString("<invalid>")); if (m_format_cache.GetSynthetic(match_data.GetTypeForCache(), retval)) { if (log) { - log->Printf("[FormatManager::GetSyntheticChildren] Cache search " - "success. Returning."); + LLDB_LOGF(log, "[FormatManager::GetSyntheticChildren] Cache search " + "success. Returning."); LLDB_LOGV(log, "Cache hits: {0} - Cache Misses: {1}", m_format_cache.GetCacheHits(), m_format_cache.GetCacheMisses()); } return retval; } - if (log) - log->Printf("[FormatManager::GetSyntheticChildren] Cache search failed. " - "Going normal route"); + LLDB_LOGF(log, "[FormatManager::GetSyntheticChildren] Cache search failed. " + "Going normal route"); } retval = m_categories_map.GetSyntheticChildren(match_data); if (!retval) { - if (log) - log->Printf("[FormatManager::GetSyntheticChildren] Search failed. Giving " - "language a chance."); + LLDB_LOGF(log, + "[FormatManager::GetSyntheticChildren] Search failed. Giving " + "language a chance."); for (lldb::LanguageType lang_type : match_data.GetCandidateLanguages()) { if (LanguageCategory *lang_category = GetCategoryForLanguage(lang_type)) { if (lang_category->Get(match_data, retval)) @@ -817,25 +815,23 @@ FormatManager::GetSyntheticChildren(ValueObject &valobj, } } if (retval) { - if (log) - log->Printf("[FormatManager::GetSyntheticChildren] Language search " - "success. Returning."); + LLDB_LOGF(log, "[FormatManager::GetSyntheticChildren] Language search " + "success. Returning."); return retval; } } if (!retval) { - if (log) - log->Printf("[FormatManager::GetSyntheticChildren] Search failed. Giving " - "hardcoded a chance."); + LLDB_LOGF(log, + "[FormatManager::GetSyntheticChildren] Search failed. Giving " + "hardcoded a chance."); retval = GetHardcodedSyntheticChildren(match_data); } if (match_data.GetTypeForCache() && (!retval || !retval->NonCacheable())) { - if (log) - log->Printf( - "[FormatManager::GetSyntheticChildren] Caching %p for type %s", - static_cast<void *>(retval.get()), - match_data.GetTypeForCache().AsCString("<invalid>")); + LLDB_LOGF(log, + "[FormatManager::GetSyntheticChildren] Caching %p for type %s", + static_cast<void *>(retval.get()), + match_data.GetTypeForCache().AsCString("<invalid>")); m_format_cache.SetSynthetic(match_data.GetTypeForCache(), retval); } LLDB_LOGV(log, "Cache hits: {0} - Cache Misses: {1}", @@ -851,13 +847,13 @@ FormatManager::GetValidator(ValueObject &valobj, TypeValidatorImplSP retval; Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_DATAFORMATTERS)); if (match_data.GetTypeForCache()) { - if (log) - log->Printf( - "\n\n[FormatManager::GetValidator] Looking into cache for type %s", - match_data.GetTypeForCache().AsCString("<invalid>")); + LLDB_LOGF( + log, "\n\n[FormatManager::GetValidator] Looking into cache for type %s", + match_data.GetTypeForCache().AsCString("<invalid>")); if (m_format_cache.GetValidator(match_data.GetTypeForCache(), retval)) { if (log) { - log->Printf( + LLDB_LOGF( + log, "[FormatManager::GetValidator] Cache search success. Returning."); LLDB_LOGV(log, "Cache hits: {0} - Cache Misses: {1}", m_format_cache.GetCacheHits(), @@ -865,16 +861,14 @@ FormatManager::GetValidator(ValueObject &valobj, } return retval; } - if (log) - log->Printf("[FormatManager::GetValidator] Cache search failed. Going " - "normal route"); + LLDB_LOGF(log, "[FormatManager::GetValidator] Cache search failed. Going " + "normal route"); } retval = m_categories_map.GetValidator(match_data); if (!retval) { - if (log) - log->Printf("[FormatManager::GetValidator] Search failed. Giving " - "language a chance."); + LLDB_LOGF(log, "[FormatManager::GetValidator] Search failed. Giving " + "language a chance."); for (lldb::LanguageType lang_type : match_data.GetCandidateLanguages()) { if (LanguageCategory *lang_category = GetCategoryForLanguage(lang_type)) { if (lang_category->Get(match_data, retval)) @@ -882,24 +876,21 @@ FormatManager::GetValidator(ValueObject &valobj, } } if (retval) { - if (log) - log->Printf("[FormatManager::GetValidator] Language search success. " - "Returning."); + LLDB_LOGF(log, "[FormatManager::GetValidator] Language search success. " + "Returning."); return retval; } } if (!retval) { - if (log) - log->Printf("[FormatManager::GetValidator] Search failed. Giving " - "hardcoded a chance."); + LLDB_LOGF(log, "[FormatManager::GetValidator] Search failed. Giving " + "hardcoded a chance."); retval = GetHardcodedValidator(match_data); } if (match_data.GetTypeForCache() && (!retval || !retval->NonCacheable())) { - if (log) - log->Printf("[FormatManager::GetValidator] Caching %p for type %s", - static_cast<void *>(retval.get()), - match_data.GetTypeForCache().AsCString("<invalid>")); + LLDB_LOGF(log, "[FormatManager::GetValidator] Caching %p for type %s", + static_cast<void *>(retval.get()), + match_data.GetTypeForCache().AsCString("<invalid>")); m_format_cache.SetValidator(match_data.GetTypeForCache(), retval); } LLDB_LOGV(log, "Cache hits: {0} - Cache Misses: {1}", @@ -961,10 +952,7 @@ void FormatManager::LoadSystemFormatters() { lldb::TypeSummaryImplSP string_array_format( new StringSummaryFormat(string_array_flags, "${var%s}")); - lldb::RegularExpressionSP any_size_char_arr( - new RegularExpression(llvm::StringRef("char \\[[0-9]+\\]"))); - lldb::RegularExpressionSP any_size_wchar_arr( - new RegularExpression(llvm::StringRef("wchar_t \\[[0-9]+\\]"))); + RegularExpression any_size_char_arr(llvm::StringRef("char \\[[0-9]+\\]")); TypeCategoryImpl::SharedPointer sys_category_sp = GetCategory(m_system_category_name); @@ -973,8 +961,8 @@ void FormatManager::LoadSystemFormatters() { string_format); sys_category_sp->GetTypeSummariesContainer()->Add( ConstString("unsigned char *"), string_format); - sys_category_sp->GetRegexTypeSummariesContainer()->Add(any_size_char_arr, - string_array_format); + sys_category_sp->GetRegexTypeSummariesContainer()->Add( + std::move(any_size_char_arr), string_array_format); lldb::TypeSummaryImplSP ostype_summary( new StringSummaryFormat(TypeSummaryImpl::Flags() diff --git a/source/DataFormatters/FormattersHelpers.cpp b/source/DataFormatters/FormattersHelpers.cpp index 8f007df03faa..b2a5a17595c8 100644 --- a/source/DataFormatters/FormattersHelpers.cpp +++ b/source/DataFormatters/FormattersHelpers.cpp @@ -29,10 +29,10 @@ void lldb_private::formatters::AddFormat( if (regex) category_sp->GetRegexTypeFormatsContainer()->Add( - RegularExpressionSP(new RegularExpression(type_name.GetStringRef())), - format_sp); + RegularExpression(type_name.GetStringRef()), format_sp); else - category_sp->GetTypeFormatsContainer()->Add(type_name, format_sp); + category_sp->GetTypeFormatsContainer()->Add(std::move(type_name), + format_sp); } void lldb_private::formatters::AddSummary( @@ -40,10 +40,10 @@ void lldb_private::formatters::AddSummary( ConstString type_name, bool regex) { if (regex) category_sp->GetRegexTypeSummariesContainer()->Add( - RegularExpressionSP(new RegularExpression(type_name.GetStringRef())), - summary_sp); + RegularExpression(type_name.GetStringRef()), summary_sp); else - category_sp->GetTypeSummariesContainer()->Add(type_name, summary_sp); + category_sp->GetTypeSummariesContainer()->Add(std::move(type_name), + summary_sp); } void lldb_private::formatters::AddStringSummary( @@ -53,10 +53,10 @@ void lldb_private::formatters::AddStringSummary( if (regex) category_sp->GetRegexTypeSummariesContainer()->Add( - RegularExpressionSP(new RegularExpression(type_name.GetStringRef())), - summary_sp); + RegularExpression(type_name.GetStringRef()), summary_sp); else - category_sp->GetTypeSummariesContainer()->Add(type_name, summary_sp); + category_sp->GetTypeSummariesContainer()->Add(std::move(type_name), + summary_sp); } void lldb_private::formatters::AddOneLineSummary( @@ -67,10 +67,10 @@ void lldb_private::formatters::AddOneLineSummary( if (regex) category_sp->GetRegexTypeSummariesContainer()->Add( - RegularExpressionSP(new RegularExpression(type_name.GetStringRef())), - summary_sp); + RegularExpression(type_name.GetStringRef()), summary_sp); else - category_sp->GetTypeSummariesContainer()->Add(type_name, summary_sp); + category_sp->GetTypeSummariesContainer()->Add(std::move(type_name), + summary_sp); } void lldb_private::formatters::AddCXXSummary( @@ -81,10 +81,10 @@ void lldb_private::formatters::AddCXXSummary( new CXXFunctionSummaryFormat(flags, funct, description)); if (regex) category_sp->GetRegexTypeSummariesContainer()->Add( - RegularExpressionSP(new RegularExpression(type_name.GetStringRef())), - summary_sp); + RegularExpression(type_name.GetStringRef()), summary_sp); else - category_sp->GetTypeSummariesContainer()->Add(type_name, summary_sp); + category_sp->GetTypeSummariesContainer()->Add(std::move(type_name), + summary_sp); } void lldb_private::formatters::AddCXXSynthetic( @@ -96,10 +96,10 @@ void lldb_private::formatters::AddCXXSynthetic( new CXXSyntheticChildren(flags, description, generator)); if (regex) category_sp->GetRegexTypeSyntheticsContainer()->Add( - RegularExpressionSP(new RegularExpression(type_name.GetStringRef())), - synth_sp); + RegularExpression(type_name.GetStringRef()), synth_sp); else - category_sp->GetTypeSyntheticsContainer()->Add(type_name, synth_sp); + category_sp->GetTypeSyntheticsContainer()->Add(std::move(type_name), + synth_sp); } void lldb_private::formatters::AddFilter( @@ -111,10 +111,10 @@ void lldb_private::formatters::AddFilter( filter_sp->AddExpressionPath(child); if (regex) category_sp->GetRegexTypeFiltersContainer()->Add( - RegularExpressionSP(new RegularExpression(type_name.GetStringRef())), - filter_sp); + RegularExpression(type_name.GetStringRef()), filter_sp); else - category_sp->GetTypeFiltersContainer()->Add(type_name, filter_sp); + category_sp->GetTypeFiltersContainer()->Add(std::move(type_name), + filter_sp); } size_t lldb_private::formatters::ExtractIndexFromString(const char *item_name) { diff --git a/source/DataFormatters/TypeCategoryMap.cpp b/source/DataFormatters/TypeCategoryMap.cpp index 69757c9844e1..b1075e9878d8 100644 --- a/source/DataFormatters/TypeCategoryMap.cpp +++ b/source/DataFormatters/TypeCategoryMap.cpp @@ -180,7 +180,8 @@ TypeCategoryMap::GetFormat(FormattersMatchData &match_data) { if (log) { for (auto match : match_data.GetMatchesVector()) { - log->Printf( + LLDB_LOGF( + log, "[CategoryMap::GetFormat] candidate match = %s %s %s %s reason = " "%" PRIu32, match.GetTypeName().GetCString(), @@ -194,18 +195,16 @@ TypeCategoryMap::GetFormat(FormattersMatchData &match_data) { for (begin = m_active_categories.begin(); begin != end; begin++) { lldb::TypeCategoryImplSP category_sp = *begin; lldb::TypeFormatImplSP current_format; - if (log) - log->Printf("[TypeCategoryMap::GetFormat] Trying to use category %s", - category_sp->GetName()); + LLDB_LOGF(log, "[TypeCategoryMap::GetFormat] Trying to use category %s", + category_sp->GetName()); if (!category_sp->Get(match_data.GetValueObject(), match_data.GetMatchesVector(), current_format, &reason_why)) continue; return current_format; } - if (log) - log->Printf( - "[TypeCategoryMap::GetFormat] nothing found - returning empty SP"); + LLDB_LOGF(log, + "[TypeCategoryMap::GetFormat] nothing found - returning empty SP"); return lldb::TypeFormatImplSP(); } @@ -220,7 +219,8 @@ TypeCategoryMap::GetSummaryFormat(FormattersMatchData &match_data) { if (log) { for (auto match : match_data.GetMatchesVector()) { - log->Printf( + LLDB_LOGF( + log, "[CategoryMap::GetSummaryFormat] candidate match = %s %s %s %s " "reason = %" PRIu32, match.GetTypeName().GetCString(), @@ -234,18 +234,17 @@ TypeCategoryMap::GetSummaryFormat(FormattersMatchData &match_data) { for (begin = m_active_categories.begin(); begin != end; begin++) { lldb::TypeCategoryImplSP category_sp = *begin; lldb::TypeSummaryImplSP current_format; - if (log) - log->Printf("[CategoryMap::GetSummaryFormat] Trying to use category %s", - category_sp->GetName()); + LLDB_LOGF(log, "[CategoryMap::GetSummaryFormat] Trying to use category %s", + category_sp->GetName()); if (!category_sp->Get(match_data.GetValueObject(), match_data.GetMatchesVector(), current_format, &reason_why)) continue; return current_format; } - if (log) - log->Printf( - "[CategoryMap::GetSummaryFormat] nothing found - returning empty SP"); + LLDB_LOGF( + log, + "[CategoryMap::GetSummaryFormat] nothing found - returning empty SP"); return lldb::TypeSummaryImplSP(); } @@ -261,7 +260,8 @@ TypeCategoryMap::GetSyntheticChildren(FormattersMatchData &match_data) { if (log) { for (auto match : match_data.GetMatchesVector()) { - log->Printf( + LLDB_LOGF( + log, "[CategoryMap::GetSyntheticChildren] candidate match = %s %s %s %s " "reason = %" PRIu32, match.GetTypeName().GetCString(), @@ -275,19 +275,18 @@ TypeCategoryMap::GetSyntheticChildren(FormattersMatchData &match_data) { for (begin = m_active_categories.begin(); begin != end; begin++) { lldb::TypeCategoryImplSP category_sp = *begin; lldb::SyntheticChildrenSP current_format; - if (log) - log->Printf( - "[CategoryMap::GetSyntheticChildren] Trying to use category %s", - category_sp->GetName()); + LLDB_LOGF(log, + "[CategoryMap::GetSyntheticChildren] Trying to use category %s", + category_sp->GetName()); if (!category_sp->Get(match_data.GetValueObject(), match_data.GetMatchesVector(), current_format, &reason_why)) continue; return current_format; } - if (log) - log->Printf("[CategoryMap::GetSyntheticChildren] nothing found - returning " - "empty SP"); + LLDB_LOGF(log, + "[CategoryMap::GetSyntheticChildren] nothing found - returning " + "empty SP"); return lldb::SyntheticChildrenSP(); } @@ -302,7 +301,8 @@ TypeCategoryMap::GetValidator(FormattersMatchData &match_data) { if (log) { for (auto match : match_data.GetMatchesVector()) { - log->Printf( + LLDB_LOGF( + log, "[CategoryMap::GetValidator] candidate match = %s %s %s %s reason = " "%" PRIu32, match.GetTypeName().GetCString(), @@ -316,18 +316,16 @@ TypeCategoryMap::GetValidator(FormattersMatchData &match_data) { for (begin = m_active_categories.begin(); begin != end; begin++) { lldb::TypeCategoryImplSP category_sp = *begin; lldb::TypeValidatorImplSP current_format; - if (log) - log->Printf("[CategoryMap::GetValidator] Trying to use category %s", - category_sp->GetName()); + LLDB_LOGF(log, "[CategoryMap::GetValidator] Trying to use category %s", + category_sp->GetName()); if (!category_sp->Get(match_data.GetValueObject(), match_data.GetMatchesVector(), current_format, &reason_why)) continue; return current_format; } - if (log) - log->Printf( - "[CategoryMap::GetValidator] nothing found - returning empty SP"); + LLDB_LOGF(log, + "[CategoryMap::GetValidator] nothing found - returning empty SP"); return lldb::TypeValidatorImplSP(); } diff --git a/source/DataFormatters/TypeFormat.cpp b/source/DataFormatters/TypeFormat.cpp index b526e9a744bc..b272c2e8dc3b 100644 --- a/source/DataFormatters/TypeFormat.cpp +++ b/source/DataFormatters/TypeFormat.cpp @@ -164,7 +164,7 @@ bool TypeFormatImpl_EnumType::FormatObject(ValueObject *valobj, llvm::DenseSet<lldb_private::SymbolFile *> searched_symbol_files; images.FindTypes(nullptr, m_enum_type, false, UINT32_MAX, searched_symbol_files, types); - if (types.GetSize() == 0) + if (types.Empty()) return false; for (lldb::TypeSP type_sp : types.Types()) { if (!type_sp) diff --git a/source/DataFormatters/ValueObjectPrinter.cpp b/source/DataFormatters/ValueObjectPrinter.cpp index 409cffed9b0f..fa43c677a194 100644 --- a/source/DataFormatters/ValueObjectPrinter.cpp +++ b/source/DataFormatters/ValueObjectPrinter.cpp @@ -456,7 +456,7 @@ bool ValueObjectPrinter::PrintObjectDescriptionIfNeeded(bool value_printed, if (object_desc[object_end] == '\n') m_stream->Printf("%s", object_desc); else - m_stream->Printf("%s\n", object_desc); + m_stream->Printf("%s\n", object_desc); return true; } else if (!value_printed && !summary_printed) return true; @@ -751,34 +751,30 @@ bool ValueObjectPrinter::PrintChildrenOneLiner(bool hide_names) { void ValueObjectPrinter::PrintChildrenIfNeeded(bool value_printed, bool summary_printed) { - // this flag controls whether we tried to display a description for this - // object and failed if that happens, we want to display the children, if any + // This flag controls whether we tried to display a description for this + // object and failed if that happens, we want to display the children if any. bool is_failed_description = !PrintObjectDescriptionIfNeeded(value_printed, summary_printed); - auto curr_ptr_depth = m_ptr_depth; - bool print_children = + DumpValueObjectOptions::PointerDepth curr_ptr_depth = m_ptr_depth; + const bool print_children = ShouldPrintChildren(is_failed_description, curr_ptr_depth); - bool print_oneline = + const bool print_oneline = (curr_ptr_depth.CanAllowExpansion() || m_options.m_show_types || !m_options.m_allow_oneliner_mode || m_options.m_flat_output || (m_options.m_pointer_as_array) || m_options.m_show_location) ? false : DataVisualization::ShouldPrintAsOneLiner(*m_valobj); - bool is_instance_ptr = IsInstancePointer(); - uint64_t instance_ptr_value = LLDB_INVALID_ADDRESS; - - if (print_children && is_instance_ptr) { - instance_ptr_value = m_valobj->GetValueAsUnsigned(0); + if (print_children && IsInstancePointer()) { + uint64_t instance_ptr_value = m_valobj->GetValueAsUnsigned(0); if (m_printed_instance_pointers->count(instance_ptr_value)) { - // we already printed this instance-is-pointer thing, so don't expand it + // We already printed this instance-is-pointer thing, so don't expand it. m_stream->PutCString(" {...}\n"); - - // we're done here - get out fast return; - } else - m_printed_instance_pointers->emplace( - instance_ptr_value); // remember this guy for future reference + } else { + // Remember this guy for future reference. + m_printed_instance_pointers->emplace(instance_ptr_value); + } } if (print_children) { diff --git a/source/DataFormatters/VectorType.cpp b/source/DataFormatters/VectorType.cpp index 18880f72ef2e..26fc03a4cdc2 100644 --- a/source/DataFormatters/VectorType.cpp +++ b/source/DataFormatters/VectorType.cpp @@ -15,6 +15,7 @@ #include "lldb/Target/Target.h" #include "lldb/Utility/LLDBAssert.h" +#include "lldb/Utility/Log.h" using namespace lldb; using namespace lldb_private; @@ -219,13 +220,20 @@ public: CompilerType parent_type(m_backend.GetCompilerType()); CompilerType element_type; parent_type.IsVectorType(&element_type, nullptr); - TargetSP target_sp(m_backend.GetTargetSP()); - m_child_type = ::GetCompilerTypeForFormat( - m_parent_format, element_type, - target_sp - ? target_sp->GetScratchTypeSystemForLanguage(nullptr, - lldb::eLanguageTypeC) - : nullptr); + TypeSystem *type_system = nullptr; + if (auto target_sp = m_backend.GetTargetSP()) { + auto type_system_or_err = + target_sp->GetScratchTypeSystemForLanguage(lldb::eLanguageTypeC); + if (auto err = type_system_or_err.takeError()) { + LLDB_LOG_ERROR( + lldb_private::GetLogIfAnyCategoriesSet(LIBLLDB_LOG_DATAFORMATTERS), + std::move(err), "Unable to update from scratch TypeSystem"); + } else { + type_system = &type_system_or_err.get(); + } + } + m_child_type = + ::GetCompilerTypeForFormat(m_parent_format, element_type, type_system); m_num_children = ::CalculateNumChildren(parent_type, m_child_type); m_item_format = GetItemFormatForFormat(m_parent_format, m_child_type); return false; diff --git a/source/Expression/DWARFExpression.cpp b/source/Expression/DWARFExpression.cpp index a9d365325d9e..3789d9147737 100644 --- a/source/Expression/DWARFExpression.cpp +++ b/source/Expression/DWARFExpression.cpp @@ -33,6 +33,7 @@ #include "lldb/Target/RegisterContext.h" #include "lldb/Target/StackFrame.h" #include "lldb/Target/StackID.h" +#include "lldb/Target/Target.h" #include "lldb/Target/Thread.h" #include "Plugins/SymbolFile/DWARF/DWARFUnit.h" @@ -59,12 +60,9 @@ DWARFExpression::DWARFExpression() DWARFExpression::DWARFExpression(lldb::ModuleSP module_sp, const DataExtractor &data, - const DWARFUnit *dwarf_cu, - lldb::offset_t data_offset, - lldb::offset_t data_length) - : m_module_wp(), m_data(data, data_offset, data_length), - m_dwarf_cu(dwarf_cu), m_reg_kind(eRegisterKindDWARF), - m_loclist_slide(LLDB_INVALID_ADDRESS) { + const DWARFUnit *dwarf_cu) + : m_module_wp(), m_data(data), m_dwarf_cu(dwarf_cu), + m_reg_kind(eRegisterKindDWARF), m_loclist_slide(LLDB_INVALID_ADDRESS) { if (module_sp) m_module_wp = module_sp; } @@ -90,387 +88,10 @@ void DWARFExpression::DumpLocation(Stream *s, lldb::offset_t offset, lldb::offset_t length, lldb::DescriptionLevel level, ABI *abi) const { - if (!m_data.ValidOffsetForDataOfSize(offset, length)) - return; - const lldb::offset_t start_offset = offset; - const lldb::offset_t end_offset = offset + length; - while (m_data.ValidOffset(offset) && offset < end_offset) { - const lldb::offset_t op_offset = offset; - const uint8_t op = m_data.GetU8(&offset); - - switch (level) { - default: - break; - - case lldb::eDescriptionLevelBrief: - if (op_offset > start_offset) - s->PutChar(' '); - break; - - case lldb::eDescriptionLevelFull: - case lldb::eDescriptionLevelVerbose: - if (op_offset > start_offset) - s->EOL(); - s->Indent(); - if (level == lldb::eDescriptionLevelFull) - break; - // Fall through for verbose and print offset and DW_OP prefix.. - s->Printf("0x%8.8" PRIx64 ": %s", op_offset, - op >= DW_OP_APPLE_uninit ? "DW_OP_APPLE_" : "DW_OP_"); - break; - } - - switch (op) { - case DW_OP_addr: - *s << "DW_OP_addr(" << m_data.GetAddress(&offset) << ") "; - break; // 0x03 1 address - case DW_OP_deref: - *s << "DW_OP_deref"; - break; // 0x06 - case DW_OP_const1u: - s->Printf("DW_OP_const1u(0x%2.2x)", m_data.GetU8(&offset)); - break; // 0x08 1 1-byte constant - case DW_OP_const1s: - s->Printf("DW_OP_const1s(0x%2.2x)", m_data.GetU8(&offset)); - break; // 0x09 1 1-byte constant - case DW_OP_const2u: - s->Printf("DW_OP_const2u(0x%4.4x)", m_data.GetU16(&offset)); - break; // 0x0a 1 2-byte constant - case DW_OP_const2s: - s->Printf("DW_OP_const2s(0x%4.4x)", m_data.GetU16(&offset)); - break; // 0x0b 1 2-byte constant - case DW_OP_const4u: - s->Printf("DW_OP_const4u(0x%8.8x)", m_data.GetU32(&offset)); - break; // 0x0c 1 4-byte constant - case DW_OP_const4s: - s->Printf("DW_OP_const4s(0x%8.8x)", m_data.GetU32(&offset)); - break; // 0x0d 1 4-byte constant - case DW_OP_const8u: - s->Printf("DW_OP_const8u(0x%16.16" PRIx64 ")", m_data.GetU64(&offset)); - break; // 0x0e 1 8-byte constant - case DW_OP_const8s: - s->Printf("DW_OP_const8s(0x%16.16" PRIx64 ")", m_data.GetU64(&offset)); - break; // 0x0f 1 8-byte constant - case DW_OP_constu: - s->Printf("DW_OP_constu(0x%" PRIx64 ")", m_data.GetULEB128(&offset)); - break; // 0x10 1 ULEB128 constant - case DW_OP_consts: - s->Printf("DW_OP_consts(0x%" PRId64 ")", m_data.GetSLEB128(&offset)); - break; // 0x11 1 SLEB128 constant - case DW_OP_dup: - s->PutCString("DW_OP_dup"); - break; // 0x12 - case DW_OP_drop: - s->PutCString("DW_OP_drop"); - break; // 0x13 - case DW_OP_over: - s->PutCString("DW_OP_over"); - break; // 0x14 - case DW_OP_pick: - s->Printf("DW_OP_pick(0x%2.2x)", m_data.GetU8(&offset)); - break; // 0x15 1 1-byte stack index - case DW_OP_swap: - s->PutCString("DW_OP_swap"); - break; // 0x16 - case DW_OP_rot: - s->PutCString("DW_OP_rot"); - break; // 0x17 - case DW_OP_xderef: - s->PutCString("DW_OP_xderef"); - break; // 0x18 - case DW_OP_abs: - s->PutCString("DW_OP_abs"); - break; // 0x19 - case DW_OP_and: - s->PutCString("DW_OP_and"); - break; // 0x1a - case DW_OP_div: - s->PutCString("DW_OP_div"); - break; // 0x1b - case DW_OP_minus: - s->PutCString("DW_OP_minus"); - break; // 0x1c - case DW_OP_mod: - s->PutCString("DW_OP_mod"); - break; // 0x1d - case DW_OP_mul: - s->PutCString("DW_OP_mul"); - break; // 0x1e - case DW_OP_neg: - s->PutCString("DW_OP_neg"); - break; // 0x1f - case DW_OP_not: - s->PutCString("DW_OP_not"); - break; // 0x20 - case DW_OP_or: - s->PutCString("DW_OP_or"); - break; // 0x21 - case DW_OP_plus: - s->PutCString("DW_OP_plus"); - break; // 0x22 - case DW_OP_plus_uconst: // 0x23 1 ULEB128 addend - s->Printf("DW_OP_plus_uconst(0x%" PRIx64 ")", - m_data.GetULEB128(&offset)); - break; - - case DW_OP_shl: - s->PutCString("DW_OP_shl"); - break; // 0x24 - case DW_OP_shr: - s->PutCString("DW_OP_shr"); - break; // 0x25 - case DW_OP_shra: - s->PutCString("DW_OP_shra"); - break; // 0x26 - case DW_OP_xor: - s->PutCString("DW_OP_xor"); - break; // 0x27 - case DW_OP_skip: - s->Printf("DW_OP_skip(0x%4.4x)", m_data.GetU16(&offset)); - break; // 0x2f 1 signed 2-byte constant - case DW_OP_bra: - s->Printf("DW_OP_bra(0x%4.4x)", m_data.GetU16(&offset)); - break; // 0x28 1 signed 2-byte constant - case DW_OP_eq: - s->PutCString("DW_OP_eq"); - break; // 0x29 - case DW_OP_ge: - s->PutCString("DW_OP_ge"); - break; // 0x2a - case DW_OP_gt: - s->PutCString("DW_OP_gt"); - break; // 0x2b - case DW_OP_le: - s->PutCString("DW_OP_le"); - break; // 0x2c - case DW_OP_lt: - s->PutCString("DW_OP_lt"); - break; // 0x2d - case DW_OP_ne: - s->PutCString("DW_OP_ne"); - break; // 0x2e - - case DW_OP_lit0: // 0x30 - case DW_OP_lit1: // 0x31 - case DW_OP_lit2: // 0x32 - case DW_OP_lit3: // 0x33 - case DW_OP_lit4: // 0x34 - case DW_OP_lit5: // 0x35 - case DW_OP_lit6: // 0x36 - case DW_OP_lit7: // 0x37 - case DW_OP_lit8: // 0x38 - case DW_OP_lit9: // 0x39 - case DW_OP_lit10: // 0x3A - case DW_OP_lit11: // 0x3B - case DW_OP_lit12: // 0x3C - case DW_OP_lit13: // 0x3D - case DW_OP_lit14: // 0x3E - case DW_OP_lit15: // 0x3F - case DW_OP_lit16: // 0x40 - case DW_OP_lit17: // 0x41 - case DW_OP_lit18: // 0x42 - case DW_OP_lit19: // 0x43 - case DW_OP_lit20: // 0x44 - case DW_OP_lit21: // 0x45 - case DW_OP_lit22: // 0x46 - case DW_OP_lit23: // 0x47 - case DW_OP_lit24: // 0x48 - case DW_OP_lit25: // 0x49 - case DW_OP_lit26: // 0x4A - case DW_OP_lit27: // 0x4B - case DW_OP_lit28: // 0x4C - case DW_OP_lit29: // 0x4D - case DW_OP_lit30: // 0x4E - case DW_OP_lit31: - s->Printf("DW_OP_lit%i", op - DW_OP_lit0); - break; // 0x4f - - case DW_OP_reg0: // 0x50 - case DW_OP_reg1: // 0x51 - case DW_OP_reg2: // 0x52 - case DW_OP_reg3: // 0x53 - case DW_OP_reg4: // 0x54 - case DW_OP_reg5: // 0x55 - case DW_OP_reg6: // 0x56 - case DW_OP_reg7: // 0x57 - case DW_OP_reg8: // 0x58 - case DW_OP_reg9: // 0x59 - case DW_OP_reg10: // 0x5A - case DW_OP_reg11: // 0x5B - case DW_OP_reg12: // 0x5C - case DW_OP_reg13: // 0x5D - case DW_OP_reg14: // 0x5E - case DW_OP_reg15: // 0x5F - case DW_OP_reg16: // 0x60 - case DW_OP_reg17: // 0x61 - case DW_OP_reg18: // 0x62 - case DW_OP_reg19: // 0x63 - case DW_OP_reg20: // 0x64 - case DW_OP_reg21: // 0x65 - case DW_OP_reg22: // 0x66 - case DW_OP_reg23: // 0x67 - case DW_OP_reg24: // 0x68 - case DW_OP_reg25: // 0x69 - case DW_OP_reg26: // 0x6A - case DW_OP_reg27: // 0x6B - case DW_OP_reg28: // 0x6C - case DW_OP_reg29: // 0x6D - case DW_OP_reg30: // 0x6E - case DW_OP_reg31: // 0x6F - { - uint32_t reg_num = op - DW_OP_reg0; - if (abi) { - RegisterInfo reg_info; - if (abi->GetRegisterInfoByKind(m_reg_kind, reg_num, reg_info)) { - if (reg_info.name) { - s->PutCString(reg_info.name); - break; - } else if (reg_info.alt_name) { - s->PutCString(reg_info.alt_name); - break; - } - } - } - s->Printf("DW_OP_reg%u", reg_num); - break; - } break; - - case DW_OP_breg0: - case DW_OP_breg1: - case DW_OP_breg2: - case DW_OP_breg3: - case DW_OP_breg4: - case DW_OP_breg5: - case DW_OP_breg6: - case DW_OP_breg7: - case DW_OP_breg8: - case DW_OP_breg9: - case DW_OP_breg10: - case DW_OP_breg11: - case DW_OP_breg12: - case DW_OP_breg13: - case DW_OP_breg14: - case DW_OP_breg15: - case DW_OP_breg16: - case DW_OP_breg17: - case DW_OP_breg18: - case DW_OP_breg19: - case DW_OP_breg20: - case DW_OP_breg21: - case DW_OP_breg22: - case DW_OP_breg23: - case DW_OP_breg24: - case DW_OP_breg25: - case DW_OP_breg26: - case DW_OP_breg27: - case DW_OP_breg28: - case DW_OP_breg29: - case DW_OP_breg30: - case DW_OP_breg31: { - uint32_t reg_num = op - DW_OP_breg0; - int64_t reg_offset = m_data.GetSLEB128(&offset); - if (abi) { - RegisterInfo reg_info; - if (abi->GetRegisterInfoByKind(m_reg_kind, reg_num, reg_info)) { - if (reg_info.name) { - s->Printf("[%s%+" PRIi64 "]", reg_info.name, reg_offset); - break; - } else if (reg_info.alt_name) { - s->Printf("[%s%+" PRIi64 "]", reg_info.alt_name, reg_offset); - break; - } - } - } - s->Printf("DW_OP_breg%i(0x%" PRIx64 ")", reg_num, reg_offset); - } break; - - case DW_OP_regx: // 0x90 1 ULEB128 register - { - uint32_t reg_num = m_data.GetULEB128(&offset); - if (abi) { - RegisterInfo reg_info; - if (abi->GetRegisterInfoByKind(m_reg_kind, reg_num, reg_info)) { - if (reg_info.name) { - s->PutCString(reg_info.name); - break; - } else if (reg_info.alt_name) { - s->PutCString(reg_info.alt_name); - break; - } - } - } - s->Printf("DW_OP_regx(%" PRIu32 ")", reg_num); - break; - } break; - case DW_OP_fbreg: // 0x91 1 SLEB128 offset - s->Printf("DW_OP_fbreg(%" PRIi64 ")", m_data.GetSLEB128(&offset)); - break; - case DW_OP_bregx: // 0x92 2 ULEB128 register followed by SLEB128 offset - { - uint32_t reg_num = m_data.GetULEB128(&offset); - int64_t reg_offset = m_data.GetSLEB128(&offset); - if (abi) { - RegisterInfo reg_info; - if (abi->GetRegisterInfoByKind(m_reg_kind, reg_num, reg_info)) { - if (reg_info.name) { - s->Printf("[%s%+" PRIi64 "]", reg_info.name, reg_offset); - break; - } else if (reg_info.alt_name) { - s->Printf("[%s%+" PRIi64 "]", reg_info.alt_name, reg_offset); - break; - } - } - } - s->Printf("DW_OP_bregx(reg=%" PRIu32 ",offset=%" PRIi64 ")", reg_num, - reg_offset); - } break; - case DW_OP_piece: // 0x93 1 ULEB128 size of piece addressed - s->Printf("DW_OP_piece(0x%" PRIx64 ")", m_data.GetULEB128(&offset)); - break; - case DW_OP_deref_size: // 0x94 1 1-byte size of data retrieved - s->Printf("DW_OP_deref_size(0x%2.2x)", m_data.GetU8(&offset)); - break; - case DW_OP_xderef_size: // 0x95 1 1-byte size of data retrieved - s->Printf("DW_OP_xderef_size(0x%2.2x)", m_data.GetU8(&offset)); - break; - case DW_OP_nop: - s->PutCString("DW_OP_nop"); - break; // 0x96 - case DW_OP_push_object_address: - s->PutCString("DW_OP_push_object_address"); - break; // 0x97 DWARF3 - case DW_OP_call2: // 0x98 DWARF3 1 2-byte offset of DIE - s->Printf("DW_OP_call2(0x%4.4x)", m_data.GetU16(&offset)); - break; - case DW_OP_call4: // 0x99 DWARF3 1 4-byte offset of DIE - s->Printf("DW_OP_call4(0x%8.8x)", m_data.GetU32(&offset)); - break; - case DW_OP_call_ref: // 0x9a DWARF3 1 4- or 8-byte offset of DIE - s->Printf("DW_OP_call_ref(0x%8.8" PRIx64 ")", m_data.GetAddress(&offset)); - break; - case DW_OP_form_tls_address: - s->PutCString("DW_OP_form_tls_address"); // 0x9b - break; - case DW_OP_GNU_addr_index: // 0xfb - s->Printf("DW_OP_GNU_addr_index(0x%" PRIx64 ")", - m_data.GetULEB128(&offset)); - break; - case DW_OP_addrx: - s->Printf("DW_OP_addrx(0x%" PRIx64 ")", - m_data.GetULEB128(&offset)); - break; - case DW_OP_GNU_const_index: // 0xfc - s->Printf("DW_OP_GNU_const_index(0x%" PRIx64 ")", - m_data.GetULEB128(&offset)); - break; - case DW_OP_GNU_push_tls_address: - s->PutCString("DW_OP_GNU_push_tls_address"); // 0xe0 - break; - case DW_OP_APPLE_uninit: - s->PutCString("DW_OP_APPLE_uninit"); // 0xF0 - break; - } - } + llvm::DWARFExpression(DataExtractor(m_data, offset, length).GetAsLLVM(), + llvm::dwarf::DWARF_VERSION, m_data.GetAddressByteSize()) + .print(s->AsRawOstream(), abi ? &abi->GetMCRegisterInfo() : nullptr, + nullptr); } void DWARFExpression::SetLocationListSlide(addr_t slide) { @@ -583,6 +204,8 @@ static bool ReadRegisterValueAsScalar(RegisterContext *reg_ctx, return false; } +/// Return the length in bytes of the set of operands for \p op. No guarantees +/// are made on the state of \p data after this call. static offset_t GetOpcodeDataSize(const DataExtractor &data, const lldb::offset_t data_offset, const uint8_t op) { @@ -779,6 +402,12 @@ static offset_t GetOpcodeDataSize(const DataExtractor &data, return offset - data_offset; } + case DW_OP_entry_value: // 0xa3 ULEB128 size + variable-length block + { + uint64_t subexpr_len = data.GetULEB128(&offset); + return (offset - data_offset) + subexpr_len; + } + default: break; } @@ -1007,6 +636,11 @@ bool DWARFExpression::LocationListContainsAddress( if (lo_pc == 0 && hi_pc == 0) break; + if ((m_data.GetAddressByteSize() == 4 && (lo_pc == UINT32_MAX)) || + (m_data.GetAddressByteSize() == 8 && (lo_pc == UINT64_MAX))) { + loclist_base_addr = hi_pc + m_loclist_slide; + continue; + } lo_pc += loclist_base_addr - m_loclist_slide; hi_pc += loclist_base_addr - m_loclist_slide; @@ -1042,6 +676,12 @@ bool DWARFExpression::GetLocation(addr_t base_addr, addr_t pc, if (lo_pc == 0 && hi_pc == 0) break; + if ((m_data.GetAddressByteSize() == 4 && (lo_pc == UINT32_MAX)) || + (m_data.GetAddressByteSize() == 8 && (lo_pc == UINT64_MAX))) { + curr_base_addr = hi_pc + m_loclist_slide; + continue; + } + lo_pc += curr_base_addr - m_loclist_slide; hi_pc += curr_base_addr - m_loclist_slide; @@ -1074,6 +714,216 @@ bool DWARFExpression::DumpLocationForAddress(Stream *s, return false; } +static bool Evaluate_DW_OP_entry_value(std::vector<Value> &stack, + ExecutionContext *exe_ctx, + RegisterContext *reg_ctx, + const DataExtractor &opcodes, + lldb::offset_t &opcode_offset, + Status *error_ptr, Log *log) { + // DW_OP_entry_value(sub-expr) describes the location a variable had upon + // function entry: this variable location is presumed to be optimized out at + // the current PC value. The caller of the function may have call site + // information that describes an alternate location for the variable (e.g. a + // constant literal, or a spilled stack value) in the parent frame. + // + // Example (this is pseudo-code & pseudo-DWARF, but hopefully illustrative): + // + // void child(int &sink, int x) { + // ... + // /* "x" gets optimized out. */ + // + // /* The location of "x" here is: DW_OP_entry_value($reg2). */ + // ++sink; + // } + // + // void parent() { + // int sink; + // + // /* + // * The callsite information emitted here is: + // * + // * DW_TAG_call_site + // * DW_AT_return_pc ... (for "child(sink, 123);") + // * DW_TAG_call_site_parameter (for "sink") + // * DW_AT_location ($reg1) + // * DW_AT_call_value ($SP - 8) + // * DW_TAG_call_site_parameter (for "x") + // * DW_AT_location ($reg2) + // * DW_AT_call_value ($literal 123) + // * + // * DW_TAG_call_site + // * DW_AT_return_pc ... (for "child(sink, 456);") + // * ... + // */ + // child(sink, 123); + // child(sink, 456); + // } + // + // When the program stops at "++sink" within `child`, the debugger determines + // the call site by analyzing the return address. Once the call site is found, + // the debugger determines which parameter is referenced by DW_OP_entry_value + // and evaluates the corresponding location for that parameter in `parent`. + + // 1. Find the function which pushed the current frame onto the stack. + if ((!exe_ctx || !exe_ctx->HasTargetScope()) || !reg_ctx) { + LLDB_LOG(log, "Evaluate_DW_OP_entry_value: no exe/reg context"); + return false; + } + + StackFrame *current_frame = exe_ctx->GetFramePtr(); + Thread *thread = exe_ctx->GetThreadPtr(); + if (!current_frame || !thread) { + LLDB_LOG(log, "Evaluate_DW_OP_entry_value: no current frame/thread"); + return false; + } + + Target &target = exe_ctx->GetTargetRef(); + StackFrameSP parent_frame = nullptr; + addr_t return_pc = LLDB_INVALID_ADDRESS; + uint32_t current_frame_idx = current_frame->GetFrameIndex(); + uint32_t num_frames = thread->GetStackFrameCount(); + for (uint32_t parent_frame_idx = current_frame_idx + 1; + parent_frame_idx < num_frames; ++parent_frame_idx) { + parent_frame = thread->GetStackFrameAtIndex(parent_frame_idx); + // Require a valid sequence of frames. + if (!parent_frame) + break; + + // Record the first valid return address, even if this is an inlined frame, + // in order to look up the associated call edge in the first non-inlined + // parent frame. + if (return_pc == LLDB_INVALID_ADDRESS) { + return_pc = parent_frame->GetFrameCodeAddress().GetLoadAddress(&target); + LLDB_LOG(log, + "Evaluate_DW_OP_entry_value: immediate ancestor with pc = {0:x}", + return_pc); + } + + // If we've found an inlined frame, skip it (these have no call site + // parameters). + if (parent_frame->IsInlined()) + continue; + + // We've found the first non-inlined parent frame. + break; + } + if (!parent_frame || !parent_frame->GetRegisterContext()) { + LLDB_LOG(log, "Evaluate_DW_OP_entry_value: no parent frame with reg ctx"); + return false; + } + + Function *parent_func = + parent_frame->GetSymbolContext(eSymbolContextFunction).function; + if (!parent_func) { + LLDB_LOG(log, "Evaluate_DW_OP_entry_value: no parent function"); + return false; + } + + // 2. Find the call edge in the parent function responsible for creating the + // current activation. + Function *current_func = + current_frame->GetSymbolContext(eSymbolContextFunction).function; + if (!current_func) { + LLDB_LOG(log, "Evaluate_DW_OP_entry_value: no current function"); + return false; + } + + CallEdge *call_edge = nullptr; + ModuleList &modlist = target.GetImages(); + if (!parent_frame->IsArtificial()) { + // If the parent frame is not artificial, the current activation may be + // produced by an ambiguous tail call. In this case, refuse to proceed. + call_edge = parent_func->GetCallEdgeForReturnAddress(return_pc, target); + if (!call_edge) { + LLDB_LOG(log, + "Evaluate_DW_OP_entry_value: no call edge for retn-pc = {0:x} " + "in parent frame {1}", + return_pc, parent_func->GetName()); + return false; + } + Function *callee_func = call_edge->GetCallee(modlist); + if (callee_func != current_func) { + LLDB_LOG(log, "Evaluate_DW_OP_entry_value: ambiguous call sequence, " + "can't find real parent frame"); + return false; + } + } else { + // The StackFrameList solver machinery has deduced that an unambiguous tail + // call sequence that produced the current activation. The first edge in + // the parent that points to the current function must be valid. + for (CallEdge &edge : parent_func->GetTailCallingEdges()) { + if (edge.GetCallee(modlist) == current_func) { + call_edge = &edge; + break; + } + } + } + if (!call_edge) { + LLDB_LOG(log, "Evaluate_DW_OP_entry_value: no unambiguous edge from parent " + "to current function"); + return false; + } + + // 3. Attempt to locate the DW_OP_entry_value expression in the set of + // available call site parameters. If found, evaluate the corresponding + // parameter in the context of the parent frame. + const uint32_t subexpr_len = opcodes.GetULEB128(&opcode_offset); + const void *subexpr_data = opcodes.GetData(&opcode_offset, subexpr_len); + if (!subexpr_data) { + LLDB_LOG(log, "Evaluate_DW_OP_entry_value: subexpr could not be read"); + return false; + } + + const CallSiteParameter *matched_param = nullptr; + for (const CallSiteParameter ¶m : call_edge->GetCallSiteParameters()) { + DataExtractor param_subexpr_extractor; + if (!param.LocationInCallee.GetExpressionData(param_subexpr_extractor)) + continue; + lldb::offset_t param_subexpr_offset = 0; + const void *param_subexpr_data = + param_subexpr_extractor.GetData(¶m_subexpr_offset, subexpr_len); + if (!param_subexpr_data || + param_subexpr_extractor.BytesLeft(param_subexpr_offset) != 0) + continue; + + // At this point, the DW_OP_entry_value sub-expression and the callee-side + // expression in the call site parameter are known to have the same length. + // Check whether they are equal. + // + // Note that an equality check is sufficient: the contents of the + // DW_OP_entry_value subexpression are only used to identify the right call + // site parameter in the parent, and do not require any special handling. + if (memcmp(subexpr_data, param_subexpr_data, subexpr_len) == 0) { + matched_param = ¶m; + break; + } + } + if (!matched_param) { + LLDB_LOG(log, + "Evaluate_DW_OP_entry_value: no matching call site param found"); + return false; + } + + // TODO: Add support for DW_OP_push_object_address within a DW_OP_entry_value + // subexpresion whenever llvm does. + Value result; + ExecutionContext parent_exe_ctx = *exe_ctx; + parent_exe_ctx.SetFrameSP(parent_frame); + const DWARFExpression ¶m_expr = matched_param->LocationInCaller; + if (!param_expr.Evaluate(&parent_exe_ctx, + parent_frame->GetRegisterContext().get(), + /*loclist_base_addr=*/LLDB_INVALID_ADDRESS, + /*initial_value_ptr=*/nullptr, + /*object_address_ptr=*/nullptr, result, error_ptr)) { + LLDB_LOG(log, + "Evaluate_DW_OP_entry_value: call site param evaluation failed"); + return false; + } + + stack.push_back(result); + return true; +} + bool DWARFExpression::Evaluate(ExecutionContextScope *exe_scope, lldb::addr_t loclist_base_load_addr, const Value *initial_value_ptr, @@ -1128,6 +978,13 @@ bool DWARFExpression::Evaluate(ExecutionContext *exe_ctx, if (lo_pc == 0 && hi_pc == 0) break; + if ((m_data.GetAddressByteSize() == 4 && + (lo_pc == UINT32_MAX)) || + (m_data.GetAddressByteSize() == 8 && + (lo_pc == UINT64_MAX))) { + curr_loclist_base_load_addr = hi_pc + m_loclist_slide; + continue; + } lo_pc += curr_loclist_base_load_addr - m_loclist_slide; hi_pc += curr_loclist_base_load_addr - m_loclist_slide; @@ -1135,9 +992,9 @@ bool DWARFExpression::Evaluate(ExecutionContext *exe_ctx, if (length > 0 && lo_pc <= pc && pc < hi_pc) { return DWARFExpression::Evaluate( - exe_ctx, reg_ctx, module_sp, m_data, m_dwarf_cu, offset, length, - m_reg_kind, initial_value_ptr, object_address_ptr, result, - error_ptr); + exe_ctx, reg_ctx, module_sp, + DataExtractor(m_data, offset, length), m_dwarf_cu, m_reg_kind, + initial_value_ptr, object_address_ptr, result, error_ptr); } offset += length; } @@ -1148,20 +1005,19 @@ bool DWARFExpression::Evaluate(ExecutionContext *exe_ctx, } // Not a location list, just a single expression. - return DWARFExpression::Evaluate( - exe_ctx, reg_ctx, module_sp, m_data, m_dwarf_cu, 0, m_data.GetByteSize(), - m_reg_kind, initial_value_ptr, object_address_ptr, result, error_ptr); + return DWARFExpression::Evaluate(exe_ctx, reg_ctx, module_sp, m_data, + m_dwarf_cu, m_reg_kind, initial_value_ptr, + object_address_ptr, result, error_ptr); } bool DWARFExpression::Evaluate( ExecutionContext *exe_ctx, RegisterContext *reg_ctx, lldb::ModuleSP module_sp, const DataExtractor &opcodes, - const DWARFUnit *dwarf_cu, const lldb::offset_t opcodes_offset, - const lldb::offset_t opcodes_length, const lldb::RegisterKind reg_kind, + const DWARFUnit *dwarf_cu, const lldb::RegisterKind reg_kind, const Value *initial_value_ptr, const Value *object_address_ptr, Value &result, Status *error_ptr) { - if (opcodes_length == 0) { + if (opcodes.GetByteSize() == 0) { if (error_ptr) error_ptr->SetErrorString( "no location, value may have been optimized out"); @@ -1182,8 +1038,7 @@ bool DWARFExpression::Evaluate( if (initial_value_ptr) stack.push_back(*initial_value_ptr); - lldb::offset_t offset = opcodes_offset; - const lldb::offset_t end_offset = opcodes_offset + opcodes_length; + lldb::offset_t offset = 0; Value tmp; uint32_t reg_num; @@ -1191,30 +1046,24 @@ bool DWARFExpression::Evaluate( uint64_t op_piece_offset = 0; Value pieces; // Used for DW_OP_piece - // Make sure all of the data is available in opcodes. - if (!opcodes.ValidOffsetForDataOfSize(opcodes_offset, opcodes_length)) { - if (error_ptr) - error_ptr->SetErrorString( - "invalid offset and/or length for opcodes buffer."); - return false; - } Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_EXPRESSIONS)); - while (opcodes.ValidOffset(offset) && offset < end_offset) { + while (opcodes.ValidOffset(offset)) { const lldb::offset_t op_offset = offset; const uint8_t op = opcodes.GetU8(&offset); if (log && log->GetVerbose()) { size_t count = stack.size(); - log->Printf("Stack before operation has %" PRIu64 " values:", - (uint64_t)count); + LLDB_LOGF(log, "Stack before operation has %" PRIu64 " values:", + (uint64_t)count); for (size_t i = 0; i < count; ++i) { StreamString new_value; new_value.Printf("[%" PRIu64 "]", (uint64_t)i); stack[i].Dump(&new_value); - log->Printf(" %s", new_value.GetData()); + LLDB_LOGF(log, " %s", new_value.GetData()); } - log->Printf("0x%8.8" PRIx64 ": %s", op_offset, DW_OP_value_to_name(op)); + LLDB_LOGF(log, "0x%8.8" PRIx64 ": %s", op_offset, + DW_OP_value_to_name(op)); } switch (op) { @@ -1945,7 +1794,7 @@ bool DWARFExpression::Evaluate( case DW_OP_skip: { int16_t skip_offset = (int16_t)opcodes.GetU16(&offset); lldb::offset_t new_offset = offset + skip_offset; - if (new_offset >= opcodes_offset && new_offset < end_offset) + if (opcodes.ValidOffset(new_offset)) offset = new_offset; else { if (error_ptr) @@ -1974,7 +1823,7 @@ bool DWARFExpression::Evaluate( Scalar zero(0); if (tmp.ResolveValue(exe_ctx) != zero) { lldb::offset_t new_offset = offset + bra_offset; - if (new_offset >= opcodes_offset && new_offset < end_offset) + if (opcodes.ValidOffset(new_offset)) offset = new_offset; else { if (error_ptr) @@ -2570,6 +2419,83 @@ bool DWARFExpression::Evaluate( stack.back().SetValueType(Value::eValueTypeScalar); break; + // OPCODE: DW_OP_convert + // OPERANDS: 1 + // A ULEB128 that is either a DIE offset of a + // DW_TAG_base_type or 0 for the generic (pointer-sized) type. + // + // DESCRIPTION: Pop the top stack element, convert it to a + // different type, and push the result. + case DW_OP_convert: { + if (stack.size() < 1) { + if (error_ptr) + error_ptr->SetErrorString( + "Expression stack needs at least 1 item for DW_OP_convert."); + return false; + } + const uint64_t die_offset = opcodes.GetULEB128(&offset); + Scalar::Type type = Scalar::e_void; + uint64_t bit_size; + if (die_offset == 0) { + // The generic type has the size of an address on the target + // machine and an unspecified signedness. Scalar has no + // "unspecified signedness", so we use unsigned types. + if (!module_sp) { + if (error_ptr) + error_ptr->SetErrorString("No module"); + return false; + } + bit_size = module_sp->GetArchitecture().GetAddressByteSize() * 8; + if (!bit_size) { + if (error_ptr) + error_ptr->SetErrorString("unspecified architecture"); + return false; + } + type = Scalar::GetBestTypeForBitSize(bit_size, false); + } else { + // Retrieve the type DIE that the value is being converted to. + // FIXME: the constness has annoying ripple effects. + DWARFDIE die = const_cast<DWARFUnit *>(dwarf_cu)->GetDIE(die_offset); + if (!die) { + if (error_ptr) + error_ptr->SetErrorString("Cannot resolve DW_OP_convert type DIE"); + return false; + } + uint64_t encoding = + die.GetAttributeValueAsUnsigned(DW_AT_encoding, DW_ATE_hi_user); + bit_size = die.GetAttributeValueAsUnsigned(DW_AT_byte_size, 0) * 8; + if (!bit_size) + bit_size = die.GetAttributeValueAsUnsigned(DW_AT_bit_size, 0); + if (!bit_size) { + if (error_ptr) + error_ptr->SetErrorString("Unsupported type size in DW_OP_convert"); + return false; + } + switch (encoding) { + case DW_ATE_signed: + case DW_ATE_signed_char: + type = Scalar::GetBestTypeForBitSize(bit_size, true); + break; + case DW_ATE_unsigned: + case DW_ATE_unsigned_char: + type = Scalar::GetBestTypeForBitSize(bit_size, false); + break; + default: + if (error_ptr) + error_ptr->SetErrorString("Unsupported encoding in DW_OP_convert"); + return false; + } + } + if (type == Scalar::e_void) { + if (error_ptr) + error_ptr->SetErrorString("Unsupported pointer size"); + return false; + } + Scalar &top = stack.back().ResolveValue(exe_ctx); + top.TruncOrExtendTo(type, bit_size); + break; + } + // OPCODE: DW_OP_call_frame_cfa // OPERANDS: None // DESCRIPTION: Specifies a DWARF expression that pushes the value of @@ -2685,10 +2611,19 @@ bool DWARFExpression::Evaluate( stack.push_back(Scalar(value)); } break; - default: - if (log) - log->Printf("Unhandled opcode %s in DWARFExpression.", + case DW_OP_entry_value: { + if (!Evaluate_DW_OP_entry_value(stack, exe_ctx, reg_ctx, opcodes, offset, + error_ptr, log)) { + LLDB_ERRORF(error_ptr, "Could not evaluate %s.", DW_OP_value_to_name(op)); + return false; + } + break; + } + + default: + LLDB_LOGF(log, "Unhandled opcode %s in DWARFExpression.", + DW_OP_value_to_name(op)); break; } } @@ -2706,13 +2641,13 @@ bool DWARFExpression::Evaluate( } else { if (log && log->GetVerbose()) { size_t count = stack.size(); - log->Printf("Stack after operation has %" PRIu64 " values:", - (uint64_t)count); + LLDB_LOGF(log, "Stack after operation has %" PRIu64 " values:", + (uint64_t)count); for (size_t i = 0; i < count; ++i) { StreamString new_value; new_value.Printf("[%" PRIu64 "]", (uint64_t)i); stack[i].Dump(&new_value); - log->Printf(" %s", new_value.GetData()); + LLDB_LOGF(log, " %s", new_value.GetData()); } } result = stack.back(); @@ -2720,29 +2655,6 @@ bool DWARFExpression::Evaluate( return true; // Return true on success } -size_t DWARFExpression::LocationListSize(const DWARFUnit *dwarf_cu, - const DataExtractor &debug_loc_data, - lldb::offset_t offset) { - const lldb::offset_t debug_loc_offset = offset; - while (debug_loc_data.ValidOffset(offset)) { - lldb::addr_t start_addr = LLDB_INVALID_ADDRESS; - lldb::addr_t end_addr = LLDB_INVALID_ADDRESS; - if (!AddressRangeForLocationListEntry(dwarf_cu, debug_loc_data, &offset, - start_addr, end_addr)) - break; - - if (start_addr == 0 && end_addr == 0) - break; - - uint16_t loc_length = debug_loc_data.GetU16(&offset); - offset += loc_length; - } - - if (offset > debug_loc_offset) - return offset - debug_loc_offset; - return 0; -} - bool DWARFExpression::AddressRangeForLocationListEntry( const DWARFUnit *dwarf_cu, const DataExtractor &debug_loc_data, lldb::offset_t *offset_ptr, lldb::addr_t &low_pc, lldb::addr_t &high_pc) { @@ -2823,6 +2735,11 @@ static bool print_dwarf_exp_op(Stream &s, const DataExtractor &data, s.Printf("%" PRIu64 " %" PRIi64, uint, sint); return true; } + if (opcode_class == DRC_TWOOPERANDS && opcode == DW_OP_entry_value) { + uint = data.GetULEB128(offset_ptr); + s.Printf("%" PRIu64 " ", uint); + return true; + } if (opcode_class != DRC_ONEOPERAND) { s.Printf("UNKNOWN OP %u", opcode); return false; @@ -2923,6 +2840,7 @@ static bool print_dwarf_exp_op(Stream &s, const DataExtractor &data, case DW_OP_regx: case DW_OP_GNU_addr_index: case DW_OP_GNU_const_index: + case DW_OP_entry_value: size = 128; break; default: diff --git a/source/Expression/DiagnosticManager.cpp b/source/Expression/DiagnosticManager.cpp index 53d85f8a6d54..48eba3586d30 100644 --- a/source/Expression/DiagnosticManager.cpp +++ b/source/Expression/DiagnosticManager.cpp @@ -47,7 +47,7 @@ static const char *StringForSeverity(DiagnosticSeverity severity) { std::string DiagnosticManager::GetString(char separator) { std::string ret; - for (const Diagnostic *diagnostic : Diagnostics()) { + for (const auto &diagnostic : Diagnostics()) { ret.append(StringForSeverity(diagnostic->GetSeverity())); ret.append(diagnostic->GetMessage()); ret.push_back(separator); @@ -70,19 +70,9 @@ size_t DiagnosticManager::Printf(DiagnosticSeverity severity, return result; } -size_t DiagnosticManager::PutString(DiagnosticSeverity severity, - llvm::StringRef str) { +void DiagnosticManager::PutString(DiagnosticSeverity severity, + llvm::StringRef str) { if (str.empty()) - return 0; + return; AddDiagnostic(str, severity, eDiagnosticOriginLLDB); - return str.size(); -} - -void DiagnosticManager::CopyDiagnostics(DiagnosticManager &otherDiagnostics) { - for (const DiagnosticList::value_type &other_diagnostic: - otherDiagnostics.Diagnostics()) { - AddDiagnostic( - other_diagnostic->GetMessage(), other_diagnostic->GetSeverity(), - other_diagnostic->getKind(), other_diagnostic->GetCompilerID()); - } } diff --git a/source/Expression/ExpressionVariable.cpp b/source/Expression/ExpressionVariable.cpp index 97305dcf5a02..ed8da0ad8675 100644 --- a/source/Expression/ExpressionVariable.cpp +++ b/source/Expression/ExpressionVariable.cpp @@ -45,8 +45,7 @@ void PersistentExpressionState::RegisterExecutionUnit( m_execution_units.insert(execution_unit_sp); - if (log) - log->Printf("Registering JITted Functions:\n"); + LLDB_LOGF(log, "Registering JITted Functions:\n"); for (const IRExecutionUnit::JittedFunction &jitted_function : execution_unit_sp->GetJittedFunctions()) { @@ -55,15 +54,13 @@ void PersistentExpressionState::RegisterExecutionUnit( jitted_function.m_remote_addr != LLDB_INVALID_ADDRESS) { m_symbol_map[jitted_function.m_name.GetCString()] = jitted_function.m_remote_addr; - if (log) - log->Printf(" Function: %s at 0x%" PRIx64 ".", - jitted_function.m_name.GetCString(), - jitted_function.m_remote_addr); + LLDB_LOGF(log, " Function: %s at 0x%" PRIx64 ".", + jitted_function.m_name.GetCString(), + jitted_function.m_remote_addr); } } - if (log) - log->Printf("Registering JIIted Symbols:\n"); + LLDB_LOGF(log, "Registering JIIted Symbols:\n"); for (const IRExecutionUnit::JittedGlobalVariable &global_var : execution_unit_sp->GetJittedGlobalVariables()) { @@ -74,9 +71,8 @@ void PersistentExpressionState::RegisterExecutionUnit( Mangled mangler(global_var.m_name); mangler.GetDemangledName(lldb::eLanguageTypeUnknown); m_symbol_map[global_var.m_name.GetCString()] = global_var.m_remote_addr; - if (log) - log->Printf(" Symbol: %s at 0x%" PRIx64 ".", - global_var.m_name.GetCString(), global_var.m_remote_addr); + LLDB_LOGF(log, " Symbol: %s at 0x%" PRIx64 ".", + global_var.m_name.GetCString(), global_var.m_remote_addr); } } } diff --git a/source/Expression/FunctionCaller.cpp b/source/Expression/FunctionCaller.cpp index 618c1a13212c..203cfff63d80 100644 --- a/source/Expression/FunctionCaller.cpp +++ b/source/Expression/FunctionCaller.cpp @@ -217,9 +217,8 @@ bool FunctionCaller::InsertFunction(ExecutionContext &exe_ctx, return false; Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_STEP)); - if (log) - log->Printf("Call Address: 0x%" PRIx64 " Struct Address: 0x%" PRIx64 ".\n", - m_jit_start_addr, args_addr_ref); + LLDB_LOGF(log, "Call Address: 0x%" PRIx64 " Struct Address: 0x%" PRIx64 ".\n", + m_jit_start_addr, args_addr_ref); return true; } @@ -231,10 +230,10 @@ lldb::ThreadPlanSP FunctionCaller::GetThreadPlanToCallFunction( Log *log(lldb_private::GetLogIfAnyCategoriesSet(LIBLLDB_LOG_EXPRESSIONS | LIBLLDB_LOG_STEP)); - if (log) - log->Printf("-- [FunctionCaller::GetThreadPlanToCallFunction] Creating " - "thread plan to call function \"%s\" --", - m_name.c_str()); + LLDB_LOGF(log, + "-- [FunctionCaller::GetThreadPlanToCallFunction] Creating " + "thread plan to call function \"%s\" --", + m_name.c_str()); // FIXME: Use the errors Stream for better error reporting. Thread *thread = exe_ctx.GetThreadPtr(); @@ -271,10 +270,10 @@ bool FunctionCaller::FetchFunctionResults(ExecutionContext &exe_ctx, Log *log(lldb_private::GetLogIfAnyCategoriesSet(LIBLLDB_LOG_EXPRESSIONS | LIBLLDB_LOG_STEP)); - if (log) - log->Printf("-- [FunctionCaller::FetchFunctionResults] Fetching function " - "results for \"%s\"--", - m_name.c_str()); + LLDB_LOGF(log, + "-- [FunctionCaller::FetchFunctionResults] Fetching function " + "results for \"%s\"--", + m_name.c_str()); Process *process = exe_ctx.GetProcessPtr(); @@ -341,10 +340,9 @@ lldb::ExpressionResults FunctionCaller::ExecuteFunction( Log *log(lldb_private::GetLogIfAnyCategoriesSet(LIBLLDB_LOG_EXPRESSIONS | LIBLLDB_LOG_STEP)); - if (log) - log->Printf( - "== [FunctionCaller::ExecuteFunction] Executing function \"%s\" ==", - m_name.c_str()); + LLDB_LOGF(log, + "== [FunctionCaller::ExecuteFunction] Executing function \"%s\" ==", + m_name.c_str()); lldb::ThreadPlanSP call_plan_sp = GetThreadPlanToCallFunction( exe_ctx, args_addr, real_options, diagnostic_manager); @@ -362,13 +360,15 @@ lldb::ExpressionResults FunctionCaller::ExecuteFunction( if (log) { if (return_value != lldb::eExpressionCompleted) { - log->Printf("== [FunctionCaller::ExecuteFunction] Execution of \"%s\" " - "completed abnormally ==", - m_name.c_str()); + LLDB_LOGF(log, + "== [FunctionCaller::ExecuteFunction] Execution of \"%s\" " + "completed abnormally ==", + m_name.c_str()); } else { - log->Printf("== [FunctionCaller::ExecuteFunction] Execution of \"%s\" " - "completed normally ==", - m_name.c_str()); + LLDB_LOGF(log, + "== [FunctionCaller::ExecuteFunction] Execution of \"%s\" " + "completed normally ==", + m_name.c_str()); } } diff --git a/source/Expression/IRExecutionUnit.cpp b/source/Expression/IRExecutionUnit.cpp index 25404ad313e1..b10628e10cc5 100644 --- a/source/Expression/IRExecutionUnit.cpp +++ b/source/Expression/IRExecutionUnit.cpp @@ -122,10 +122,10 @@ Status IRExecutionUnit::DisassembleFunction(Stream &stream, return ret; } - if (log) - log->Printf("Found function, has local address 0x%" PRIx64 - " and remote address 0x%" PRIx64, - (uint64_t)func_local_addr, (uint64_t)func_remote_addr); + LLDB_LOGF(log, + "Found function, has local address 0x%" PRIx64 + " and remote address 0x%" PRIx64, + (uint64_t)func_local_addr, (uint64_t)func_remote_addr); std::pair<lldb::addr_t, lldb::addr_t> func_range; @@ -138,9 +138,8 @@ Status IRExecutionUnit::DisassembleFunction(Stream &stream, return ret; } - if (log) - log->Printf("Function's code range is [0x%" PRIx64 "+0x%" PRIx64 "]", - func_range.first, func_range.second); + LLDB_LOGF(log, "Function's code range is [0x%" PRIx64 "+0x%" PRIx64 "]", + func_range.first, func_range.second); Target *target = exe_ctx.GetTargetPtr(); if (!target) { @@ -188,7 +187,7 @@ Status IRExecutionUnit::DisassembleFunction(Stream &stream, target->GetArchitecture().GetAddressByteSize()); if (log) { - log->Printf("Function data has contents:"); + LLDB_LOGF(log, "Function data has contents:"); extractor.PutToLog(log, 0, extractor.GetByteSize(), func_remote_addr, 16, DataExtractor::TypeUInt8); } @@ -255,7 +254,7 @@ void IRExecutionUnit::GetRunnableInfo(Status &error, lldb::addr_t &func_addr, oss.flush(); - log->Printf("Module being sent to JIT: \n%s", s.c_str()); + LLDB_LOGF(log, "Module being sent to JIT: \n%s", s.c_str()); } m_module_up->getContext().setInlineAsmDiagnosticHandler(ReportInlineAsmError, @@ -317,7 +316,7 @@ void IRExecutionUnit::GetRunnableInfo(Status &error, lldb::addr_t &func_addr, }; if (process_sp->GetTarget().GetEnableSaveObjects()) { - m_object_cache_up = llvm::make_unique<ObjectDumper>(); + m_object_cache_up = std::make_unique<ObjectDumper>(); m_execution_engine_up->setObjectCache(m_object_cache_up.get()); } @@ -433,20 +432,20 @@ void IRExecutionUnit::GetRunnableInfo(Status &error, lldb::addr_t &func_addr, } if (log) { - log->Printf("Code can be run in the target."); + LLDB_LOGF(log, "Code can be run in the target."); StreamString disassembly_stream; Status err = DisassembleFunction(disassembly_stream, process_sp); if (!err.Success()) { - log->Printf("Couldn't disassemble function : %s", - err.AsCString("unknown error")); + LLDB_LOGF(log, "Couldn't disassemble function : %s", + err.AsCString("unknown error")); } else { - log->Printf("Function disassembly:\n%s", disassembly_stream.GetData()); + LLDB_LOGF(log, "Function disassembly:\n%s", disassembly_stream.GetData()); } - log->Printf("Sections: "); + LLDB_LOGF(log, "Sections: "); for (AllocationRecord &record : m_records) { if (record.m_process_address != LLDB_INVALID_ADDRESS) { record.dump(log); @@ -599,11 +598,10 @@ uint8_t *IRExecutionUnit::MemoryManager::allocateCodeSection( GetSectionTypeFromSectionName(SectionName, AllocationKind::Code), Size, Alignment, SectionID, SectionName.str().c_str())); - if (log) { - log->Printf("IRExecutionUnit::allocateCodeSection(Size=0x%" PRIx64 - ", Alignment=%u, SectionID=%u) = %p", - (uint64_t)Size, Alignment, SectionID, (void *)return_value); - } + LLDB_LOGF(log, + "IRExecutionUnit::allocateCodeSection(Size=0x%" PRIx64 + ", Alignment=%u, SectionID=%u) = %p", + (uint64_t)Size, Alignment, SectionID, (void *)return_value); if (m_parent.m_reported_allocations) { Status err; @@ -631,11 +629,10 @@ uint8_t *IRExecutionUnit::MemoryManager::allocateDataSection( (uintptr_t)return_value, permissions, GetSectionTypeFromSectionName(SectionName, AllocationKind::Data), Size, Alignment, SectionID, SectionName.str().c_str())); - if (log) { - log->Printf("IRExecutionUnit::allocateDataSection(Size=0x%" PRIx64 - ", Alignment=%u, SectionID=%u) = %p", - (uint64_t)Size, Alignment, SectionID, (void *)return_value); - } + LLDB_LOGF(log, + "IRExecutionUnit::allocateDataSection(Size=0x%" PRIx64 + ", Alignment=%u, SectionID=%u) = %p", + (uint64_t)Size, Alignment, SectionID, (void *)return_value); if (m_parent.m_reported_allocations) { Status err; @@ -661,11 +658,7 @@ FindBestAlternateMangledName(ConstString demangled, if (!sym_ctx.module_sp) return ConstString(); - SymbolVendor *sym_vendor = sym_ctx.module_sp->GetSymbolVendor(); - if (!sym_vendor) - return ConstString(); - - lldb_private::SymbolFile *sym_file = sym_vendor->GetSymbolFile(); + lldb_private::SymbolFile *sym_file = sym_ctx.module_sp->GetSymbolFile(); if (!sym_file) return ConstString(); @@ -676,7 +669,7 @@ FindBestAlternateMangledName(ConstString demangled, std::vector<ConstString> param_matches; for (size_t i = 0; i < alternates.size(); i++) { ConstString alternate_mangled_name = alternates[i]; - Mangled mangled(alternate_mangled_name, true); + Mangled mangled(alternate_mangled_name); ConstString demangled = mangled.GetDemangledName(lang_type); CPlusPlusLanguage::MethodName alternate_cpp_name(demangled); @@ -724,7 +717,7 @@ void IRExecutionUnit::CollectCandidateCPlusPlusNames( ConstString name = C_spec.name; if (CPlusPlusLanguage::IsCPPMangledName(name.GetCString())) { - Mangled mangled(name, true); + Mangled mangled(name); ConstString demangled = mangled.GetDemangledName(lldb::eLanguageTypeC_plus_plus); @@ -861,7 +854,6 @@ lldb::addr_t IRExecutionUnit::FindInSymbols( sc.module_sp->FindFunctions(spec.name, nullptr, spec.mask, true, // include_symbols false, // include_inlines - true, // append sc_list); } @@ -877,7 +869,6 @@ lldb::addr_t IRExecutionUnit::FindInSymbols( sc.target_sp->GetImages().FindFunctions(spec.name, spec.mask, true, // include_symbols false, // include_inlines - true, // append sc_list); } @@ -1042,17 +1033,15 @@ IRExecutionUnit::MemoryManager::GetSymbolAddressAndPresence( lldb::addr_t ret = m_parent.FindSymbol(name_cs, missing_weak); if (ret == LLDB_INVALID_ADDRESS) { - if (log) - log->Printf( - "IRExecutionUnit::getSymbolAddress(Name=\"%s\") = <not found>", - Name.c_str()); + LLDB_LOGF(log, + "IRExecutionUnit::getSymbolAddress(Name=\"%s\") = <not found>", + Name.c_str()); m_parent.ReportSymbolLookupError(name_cs); return 0; } else { - if (log) - log->Printf("IRExecutionUnit::getSymbolAddress(Name=\"%s\") = %" PRIx64, - Name.c_str(), ret); + LLDB_LOGF(log, "IRExecutionUnit::getSymbolAddress(Name=\"%s\") = %" PRIx64, + Name.c_str(), ret); return ret; } } @@ -1075,15 +1064,14 @@ IRExecutionUnit::GetRemoteAddressForLocal(lldb::addr_t local_address) { lldb::addr_t ret = record.m_process_address + (local_address - record.m_host_address); - if (log) { - log->Printf( - "IRExecutionUnit::GetRemoteAddressForLocal() found 0x%" PRIx64 - " in [0x%" PRIx64 "..0x%" PRIx64 "], and returned 0x%" PRIx64 - " from [0x%" PRIx64 "..0x%" PRIx64 "].", - local_address, (uint64_t)record.m_host_address, - (uint64_t)record.m_host_address + (uint64_t)record.m_size, ret, - record.m_process_address, record.m_process_address + record.m_size); - } + LLDB_LOGF(log, + "IRExecutionUnit::GetRemoteAddressForLocal() found 0x%" PRIx64 + " in [0x%" PRIx64 "..0x%" PRIx64 "], and returned 0x%" PRIx64 + " from [0x%" PRIx64 "..0x%" PRIx64 "].", + local_address, (uint64_t)record.m_host_address, + (uint64_t)record.m_host_address + (uint64_t)record.m_size, ret, + record.m_process_address, + record.m_process_address + record.m_size); return ret; } @@ -1210,10 +1198,11 @@ void IRExecutionUnit::AllocationRecord::dump(Log *log) { if (!log) return; - log->Printf("[0x%llx+0x%llx]->0x%llx (alignment %d, section ID %d, name %s)", - (unsigned long long)m_host_address, (unsigned long long)m_size, - (unsigned long long)m_process_address, (unsigned)m_alignment, - (unsigned)m_section_id, m_name.c_str()); + LLDB_LOGF(log, + "[0x%llx+0x%llx]->0x%llx (alignment %d, section ID %d, name %s)", + (unsigned long long)m_host_address, (unsigned long long)m_size, + (unsigned long long)m_process_address, (unsigned)m_alignment, + (unsigned)m_section_id, m_name.c_str()); } lldb::ByteOrder IRExecutionUnit::GetByteOrder() const { diff --git a/source/Expression/IRInterpreter.cpp b/source/Expression/IRInterpreter.cpp index 5a9814d15362..856c9a0244fb 100644 --- a/source/Expression/IRInterpreter.cpp +++ b/source/Expression/IRInterpreter.cpp @@ -327,10 +327,11 @@ public: lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_EXPRESSIONS)); if (log) { - log->Printf("Made an allocation for argument %s", - PrintValue(value).c_str()); - log->Printf(" Data region : %llx", (unsigned long long)address); - log->Printf(" Ref region : %llx", (unsigned long long)data_address); + LLDB_LOGF(log, "Made an allocation for argument %s", + PrintValue(value).c_str()); + LLDB_LOGF(log, " Data region : %llx", (unsigned long long)address); + LLDB_LOGF(log, " Ref region : %llx", + (unsigned long long)data_address); } return true; @@ -494,8 +495,7 @@ bool IRInterpreter::CanInterpret(llvm::Module &module, llvm::Function &function, ++fi) { if (fi->begin() != fi->end()) { if (saw_function_with_body) { - if (log) - log->Printf("More than one function in the module has a body"); + LLDB_LOGF(log, "More than one function in the module has a body"); error.SetErrorToGenericError(); error.SetErrorString(too_many_functions_error); return false; @@ -510,8 +510,7 @@ bool IRInterpreter::CanInterpret(llvm::Module &module, llvm::Function &function, ++ii) { switch (ii->getOpcode()) { default: { - if (log) - log->Printf("Unsupported instruction: %s", PrintValue(&*ii).c_str()); + LLDB_LOGF(log, "Unsupported instruction: %s", PrintValue(&*ii).c_str()); error.SetErrorToGenericError(); error.SetErrorString(unsupported_opcode_error); return false; @@ -532,9 +531,8 @@ bool IRInterpreter::CanInterpret(llvm::Module &module, llvm::Function &function, } if (!CanIgnoreCall(call_inst) && !support_function_calls) { - if (log) - log->Printf("Unsupported instruction: %s", - PrintValue(&*ii).c_str()); + LLDB_LOGF(log, "Unsupported instruction: %s", + PrintValue(&*ii).c_str()); error.SetErrorToGenericError(); error.SetErrorString(unsupported_opcode_error); return false; @@ -553,9 +551,8 @@ bool IRInterpreter::CanInterpret(llvm::Module &module, llvm::Function &function, switch (icmp_inst->getPredicate()) { default: { - if (log) - log->Printf("Unsupported ICmp predicate: %s", - PrintValue(&*ii).c_str()); + LLDB_LOGF(log, "Unsupported ICmp predicate: %s", + PrintValue(&*ii).c_str()); error.SetErrorToGenericError(); error.SetErrorString(unsupported_opcode_error); @@ -605,9 +602,8 @@ bool IRInterpreter::CanInterpret(llvm::Module &module, llvm::Function &function, default: break; case Type::VectorTyID: { - if (log) - log->Printf("Unsupported operand type: %s", - PrintType(operand_type).c_str()); + LLDB_LOGF(log, "Unsupported operand type: %s", + PrintType(operand_type).c_str()); error.SetErrorString(unsupported_operand_error); return false; } @@ -618,18 +614,16 @@ bool IRInterpreter::CanInterpret(llvm::Module &module, llvm::Function &function, // we can just fall back to the JIT rather than // choking. if (operand_type->getPrimitiveSizeInBits() > 64) { - if (log) - log->Printf("Unsupported operand type: %s", - PrintType(operand_type).c_str()); + LLDB_LOGF(log, "Unsupported operand type: %s", + PrintType(operand_type).c_str()); error.SetErrorString(unsupported_operand_error); return false; } if (Constant *constant = llvm::dyn_cast<Constant>(operand)) { if (!CanResolveConstant(constant)) { - if (log) - log->Printf("Unsupported constant: %s", - PrintValue(constant).c_str()); + LLDB_LOGF(log, "Unsupported constant: %s", + PrintValue(constant).c_str()); error.SetErrorString(unsupported_operand_error); return false; } @@ -659,8 +653,8 @@ bool IRInterpreter::Interpret(llvm::Module &module, llvm::Function &function, oss.flush(); - log->Printf("Module as passed in to IRInterpreter::Interpret: \n\"%s\"", - s.c_str()); + LLDB_LOGF(log, "Module as passed in to IRInterpreter::Interpret: \n\"%s\"", + s.c_str()); } DataLayout data_layout(&module); @@ -694,8 +688,7 @@ bool IRInterpreter::Interpret(llvm::Module &module, llvm::Function &function, while (frame.m_ii != frame.m_ie && (++num_insts < 4096)) { const Instruction *inst = &*frame.m_ii; - if (log) - log->Printf("Interpreting %s", PrintValue(inst).c_str()); + LLDB_LOGF(log, "Interpreting %s", PrintValue(inst).c_str()); switch (inst->getOpcode()) { default: @@ -717,10 +710,10 @@ bool IRInterpreter::Interpret(llvm::Module &module, llvm::Function &function, const BinaryOperator *bin_op = dyn_cast<BinaryOperator>(inst); if (!bin_op) { - if (log) - log->Printf( - "getOpcode() returns %s, but instruction is not a BinaryOperator", - inst->getOpcodeName()); + LLDB_LOGF( + log, + "getOpcode() returns %s, but instruction is not a BinaryOperator", + inst->getOpcodeName()); error.SetErrorToGenericError(); error.SetErrorString(interpreter_internal_error); return false; @@ -733,16 +726,14 @@ bool IRInterpreter::Interpret(llvm::Module &module, llvm::Function &function, lldb_private::Scalar R; if (!frame.EvaluateValue(L, lhs, module)) { - if (log) - log->Printf("Couldn't evaluate %s", PrintValue(lhs).c_str()); + LLDB_LOGF(log, "Couldn't evaluate %s", PrintValue(lhs).c_str()); error.SetErrorToGenericError(); error.SetErrorString(bad_value_error); return false; } if (!frame.EvaluateValue(R, rhs, module)) { - if (log) - log->Printf("Couldn't evaluate %s", PrintValue(rhs).c_str()); + LLDB_LOGF(log, "Couldn't evaluate %s", PrintValue(rhs).c_str()); error.SetErrorToGenericError(); error.SetErrorString(bad_value_error); return false; @@ -806,28 +797,26 @@ bool IRInterpreter::Interpret(llvm::Module &module, llvm::Function &function, frame.AssignValue(inst, result, module); if (log) { - log->Printf("Interpreted a %s", inst->getOpcodeName()); - log->Printf(" L : %s", frame.SummarizeValue(lhs).c_str()); - log->Printf(" R : %s", frame.SummarizeValue(rhs).c_str()); - log->Printf(" = : %s", frame.SummarizeValue(inst).c_str()); + LLDB_LOGF(log, "Interpreted a %s", inst->getOpcodeName()); + LLDB_LOGF(log, " L : %s", frame.SummarizeValue(lhs).c_str()); + LLDB_LOGF(log, " R : %s", frame.SummarizeValue(rhs).c_str()); + LLDB_LOGF(log, " = : %s", frame.SummarizeValue(inst).c_str()); } } break; case Instruction::Alloca: { const AllocaInst *alloca_inst = dyn_cast<AllocaInst>(inst); if (!alloca_inst) { - if (log) - log->Printf("getOpcode() returns Alloca, but instruction is not an " - "AllocaInst"); + LLDB_LOGF(log, "getOpcode() returns Alloca, but instruction is not an " + "AllocaInst"); error.SetErrorToGenericError(); error.SetErrorString(interpreter_internal_error); return false; } if (alloca_inst->isArrayAllocation()) { - if (log) - log->Printf( - "AllocaInsts are not handled if isArrayAllocation() is true"); + LLDB_LOGF(log, + "AllocaInsts are not handled if isArrayAllocation() is true"); error.SetErrorToGenericError(); error.SetErrorString(unsupported_opcode_error); return false; @@ -846,8 +835,7 @@ bool IRInterpreter::Interpret(llvm::Module &module, llvm::Function &function, lldb::addr_t R = frame.Malloc(T); if (R == LLDB_INVALID_ADDRESS) { - if (log) - log->Printf("Couldn't allocate memory for an AllocaInst"); + LLDB_LOGF(log, "Couldn't allocate memory for an AllocaInst"); error.SetErrorToGenericError(); error.SetErrorString(memory_allocation_error); return false; @@ -856,8 +844,8 @@ bool IRInterpreter::Interpret(llvm::Module &module, llvm::Function &function, lldb::addr_t P = frame.Malloc(Tptr); if (P == LLDB_INVALID_ADDRESS) { - if (log) - log->Printf("Couldn't allocate the result pointer for an AllocaInst"); + LLDB_LOGF(log, + "Couldn't allocate the result pointer for an AllocaInst"); error.SetErrorToGenericError(); error.SetErrorString(memory_allocation_error); return false; @@ -868,8 +856,7 @@ bool IRInterpreter::Interpret(llvm::Module &module, llvm::Function &function, execution_unit.WritePointerToMemory(P, R, write_error); if (!write_error.Success()) { - if (log) - log->Printf("Couldn't write the result pointer for an AllocaInst"); + LLDB_LOGF(log, "Couldn't write the result pointer for an AllocaInst"); error.SetErrorToGenericError(); error.SetErrorString(memory_write_error); lldb_private::Status free_error; @@ -881,9 +868,9 @@ bool IRInterpreter::Interpret(llvm::Module &module, llvm::Function &function, frame.m_values[alloca_inst] = P; if (log) { - log->Printf("Interpreted an AllocaInst"); - log->Printf(" R : 0x%" PRIx64, R); - log->Printf(" P : 0x%" PRIx64, P); + LLDB_LOGF(log, "Interpreted an AllocaInst"); + LLDB_LOGF(log, " R : 0x%" PRIx64, R); + LLDB_LOGF(log, " P : 0x%" PRIx64, P); } } break; case Instruction::BitCast: @@ -891,10 +878,9 @@ bool IRInterpreter::Interpret(llvm::Module &module, llvm::Function &function, const CastInst *cast_inst = dyn_cast<CastInst>(inst); if (!cast_inst) { - if (log) - log->Printf( - "getOpcode() returns %s, but instruction is not a BitCastInst", - cast_inst->getOpcodeName()); + LLDB_LOGF( + log, "getOpcode() returns %s, but instruction is not a BitCastInst", + cast_inst->getOpcodeName()); error.SetErrorToGenericError(); error.SetErrorString(interpreter_internal_error); return false; @@ -905,8 +891,7 @@ bool IRInterpreter::Interpret(llvm::Module &module, llvm::Function &function, lldb_private::Scalar S; if (!frame.EvaluateValue(S, source, module)) { - if (log) - log->Printf("Couldn't evaluate %s", PrintValue(source).c_str()); + LLDB_LOGF(log, "Couldn't evaluate %s", PrintValue(source).c_str()); error.SetErrorToGenericError(); error.SetErrorString(bad_value_error); return false; @@ -918,10 +903,9 @@ bool IRInterpreter::Interpret(llvm::Module &module, llvm::Function &function, const CastInst *cast_inst = dyn_cast<CastInst>(inst); if (!cast_inst) { - if (log) - log->Printf( - "getOpcode() returns %s, but instruction is not a BitCastInst", - cast_inst->getOpcodeName()); + LLDB_LOGF( + log, "getOpcode() returns %s, but instruction is not a BitCastInst", + cast_inst->getOpcodeName()); error.SetErrorToGenericError(); error.SetErrorString(interpreter_internal_error); return false; @@ -932,8 +916,7 @@ bool IRInterpreter::Interpret(llvm::Module &module, llvm::Function &function, lldb_private::Scalar S; if (!frame.EvaluateValue(S, source, module)) { - if (log) - log->Printf("Couldn't evaluate %s", PrintValue(source).c_str()); + LLDB_LOGF(log, "Couldn't evaluate %s", PrintValue(source).c_str()); error.SetErrorToGenericError(); error.SetErrorString(bad_value_error); return false; @@ -949,9 +932,8 @@ bool IRInterpreter::Interpret(llvm::Module &module, llvm::Function &function, const BranchInst *br_inst = dyn_cast<BranchInst>(inst); if (!br_inst) { - if (log) - log->Printf( - "getOpcode() returns Br, but instruction is not a BranchInst"); + LLDB_LOGF( + log, "getOpcode() returns Br, but instruction is not a BranchInst"); error.SetErrorToGenericError(); error.SetErrorString(interpreter_internal_error); return false; @@ -963,8 +945,7 @@ bool IRInterpreter::Interpret(llvm::Module &module, llvm::Function &function, lldb_private::Scalar C; if (!frame.EvaluateValue(C, condition, module)) { - if (log) - log->Printf("Couldn't evaluate %s", PrintValue(condition).c_str()); + LLDB_LOGF(log, "Couldn't evaluate %s", PrintValue(condition).c_str()); error.SetErrorToGenericError(); error.SetErrorString(bad_value_error); return false; @@ -976,14 +957,15 @@ bool IRInterpreter::Interpret(llvm::Module &module, llvm::Function &function, frame.Jump(br_inst->getSuccessor(1)); if (log) { - log->Printf("Interpreted a BrInst with a condition"); - log->Printf(" cond : %s", frame.SummarizeValue(condition).c_str()); + LLDB_LOGF(log, "Interpreted a BrInst with a condition"); + LLDB_LOGF(log, " cond : %s", + frame.SummarizeValue(condition).c_str()); } } else { frame.Jump(br_inst->getSuccessor(0)); if (log) { - log->Printf("Interpreted a BrInst with no condition"); + LLDB_LOGF(log, "Interpreted a BrInst with no condition"); } } } @@ -992,17 +974,16 @@ bool IRInterpreter::Interpret(llvm::Module &module, llvm::Function &function, const PHINode *phi_inst = dyn_cast<PHINode>(inst); if (!phi_inst) { - if (log) - log->Printf( - "getOpcode() returns PHI, but instruction is not a PHINode"); + LLDB_LOGF(log, + "getOpcode() returns PHI, but instruction is not a PHINode"); error.SetErrorToGenericError(); error.SetErrorString(interpreter_internal_error); return false; } if (!frame.m_prev_bb) { - if (log) - log->Printf("Encountered PHI node without having jumped from another " - "basic block"); + LLDB_LOGF(log, + "Encountered PHI node without having jumped from another " + "basic block"); error.SetErrorToGenericError(); error.SetErrorString(interpreter_internal_error); return false; @@ -1011,8 +992,7 @@ bool IRInterpreter::Interpret(llvm::Module &module, llvm::Function &function, Value *value = phi_inst->getIncomingValueForBlock(frame.m_prev_bb); lldb_private::Scalar result; if (!frame.EvaluateValue(result, value, module)) { - if (log) - log->Printf("Couldn't evaluate %s", PrintValue(value).c_str()); + LLDB_LOGF(log, "Couldn't evaluate %s", PrintValue(value).c_str()); error.SetErrorToGenericError(); error.SetErrorString(bad_value_error); return false; @@ -1020,18 +1000,17 @@ bool IRInterpreter::Interpret(llvm::Module &module, llvm::Function &function, frame.AssignValue(inst, result, module); if (log) { - log->Printf("Interpreted a %s", inst->getOpcodeName()); - log->Printf(" Incoming value : %s", - frame.SummarizeValue(value).c_str()); + LLDB_LOGF(log, "Interpreted a %s", inst->getOpcodeName()); + LLDB_LOGF(log, " Incoming value : %s", + frame.SummarizeValue(value).c_str()); } } break; case Instruction::GetElementPtr: { const GetElementPtrInst *gep_inst = dyn_cast<GetElementPtrInst>(inst); if (!gep_inst) { - if (log) - log->Printf("getOpcode() returns GetElementPtr, but instruction is " - "not a GetElementPtrInst"); + LLDB_LOGF(log, "getOpcode() returns GetElementPtr, but instruction is " + "not a GetElementPtrInst"); error.SetErrorToGenericError(); error.SetErrorString(interpreter_internal_error); return false; @@ -1043,9 +1022,8 @@ bool IRInterpreter::Interpret(llvm::Module &module, llvm::Function &function, lldb_private::Scalar P; if (!frame.EvaluateValue(P, pointer_operand, module)) { - if (log) - log->Printf("Couldn't evaluate %s", - PrintValue(pointer_operand).c_str()); + LLDB_LOGF(log, "Couldn't evaluate %s", + PrintValue(pointer_operand).c_str()); error.SetErrorToGenericError(); error.SetErrorString(bad_value_error); return false; @@ -1067,17 +1045,14 @@ bool IRInterpreter::Interpret(llvm::Module &module, llvm::Function &function, lldb_private::Scalar I; if (!frame.EvaluateValue(I, *ii, module)) { - if (log) - log->Printf("Couldn't evaluate %s", PrintValue(*ii).c_str()); + LLDB_LOGF(log, "Couldn't evaluate %s", PrintValue(*ii).c_str()); error.SetErrorToGenericError(); error.SetErrorString(bad_value_error); return false; } - if (log) - log->Printf("Evaluated constant index %s as %llu", - PrintValue(*ii).c_str(), - I.ULongLong(LLDB_INVALID_ADDRESS)); + LLDB_LOGF(log, "Evaluated constant index %s as %llu", + PrintValue(*ii).c_str(), I.ULongLong(LLDB_INVALID_ADDRESS)); constant_index = cast<ConstantInt>(ConstantInt::get( (*ii)->getType(), I.ULongLong(LLDB_INVALID_ADDRESS))); @@ -1094,19 +1069,19 @@ bool IRInterpreter::Interpret(llvm::Module &module, llvm::Function &function, frame.AssignValue(inst, Poffset, module); if (log) { - log->Printf("Interpreted a GetElementPtrInst"); - log->Printf(" P : %s", - frame.SummarizeValue(pointer_operand).c_str()); - log->Printf(" Poffset : %s", frame.SummarizeValue(inst).c_str()); + LLDB_LOGF(log, "Interpreted a GetElementPtrInst"); + LLDB_LOGF(log, " P : %s", + frame.SummarizeValue(pointer_operand).c_str()); + LLDB_LOGF(log, " Poffset : %s", frame.SummarizeValue(inst).c_str()); } } break; case Instruction::ICmp: { const ICmpInst *icmp_inst = dyn_cast<ICmpInst>(inst); if (!icmp_inst) { - if (log) - log->Printf( - "getOpcode() returns ICmp, but instruction is not an ICmpInst"); + LLDB_LOGF( + log, + "getOpcode() returns ICmp, but instruction is not an ICmpInst"); error.SetErrorToGenericError(); error.SetErrorString(interpreter_internal_error); return false; @@ -1121,16 +1096,14 @@ bool IRInterpreter::Interpret(llvm::Module &module, llvm::Function &function, lldb_private::Scalar R; if (!frame.EvaluateValue(L, lhs, module)) { - if (log) - log->Printf("Couldn't evaluate %s", PrintValue(lhs).c_str()); + LLDB_LOGF(log, "Couldn't evaluate %s", PrintValue(lhs).c_str()); error.SetErrorToGenericError(); error.SetErrorString(bad_value_error); return false; } if (!frame.EvaluateValue(R, rhs, module)) { - if (log) - log->Printf("Couldn't evaluate %s", PrintValue(rhs).c_str()); + LLDB_LOGF(log, "Couldn't evaluate %s", PrintValue(rhs).c_str()); error.SetErrorToGenericError(); error.SetErrorString(bad_value_error); return false; @@ -1192,19 +1165,19 @@ bool IRInterpreter::Interpret(llvm::Module &module, llvm::Function &function, frame.AssignValue(inst, result, module); if (log) { - log->Printf("Interpreted an ICmpInst"); - log->Printf(" L : %s", frame.SummarizeValue(lhs).c_str()); - log->Printf(" R : %s", frame.SummarizeValue(rhs).c_str()); - log->Printf(" = : %s", frame.SummarizeValue(inst).c_str()); + LLDB_LOGF(log, "Interpreted an ICmpInst"); + LLDB_LOGF(log, " L : %s", frame.SummarizeValue(lhs).c_str()); + LLDB_LOGF(log, " R : %s", frame.SummarizeValue(rhs).c_str()); + LLDB_LOGF(log, " = : %s", frame.SummarizeValue(inst).c_str()); } } break; case Instruction::IntToPtr: { const IntToPtrInst *int_to_ptr_inst = dyn_cast<IntToPtrInst>(inst); if (!int_to_ptr_inst) { - if (log) - log->Printf("getOpcode() returns IntToPtr, but instruction is not an " - "IntToPtrInst"); + LLDB_LOGF(log, + "getOpcode() returns IntToPtr, but instruction is not an " + "IntToPtrInst"); error.SetErrorToGenericError(); error.SetErrorString(interpreter_internal_error); return false; @@ -1215,8 +1188,7 @@ bool IRInterpreter::Interpret(llvm::Module &module, llvm::Function &function, lldb_private::Scalar I; if (!frame.EvaluateValue(I, src_operand, module)) { - if (log) - log->Printf("Couldn't evaluate %s", PrintValue(src_operand).c_str()); + LLDB_LOGF(log, "Couldn't evaluate %s", PrintValue(src_operand).c_str()); error.SetErrorToGenericError(); error.SetErrorString(bad_value_error); return false; @@ -1225,18 +1197,18 @@ bool IRInterpreter::Interpret(llvm::Module &module, llvm::Function &function, frame.AssignValue(inst, I, module); if (log) { - log->Printf("Interpreted an IntToPtr"); - log->Printf(" Src : %s", frame.SummarizeValue(src_operand).c_str()); - log->Printf(" = : %s", frame.SummarizeValue(inst).c_str()); + LLDB_LOGF(log, "Interpreted an IntToPtr"); + LLDB_LOGF(log, " Src : %s", frame.SummarizeValue(src_operand).c_str()); + LLDB_LOGF(log, " = : %s", frame.SummarizeValue(inst).c_str()); } } break; case Instruction::PtrToInt: { const PtrToIntInst *ptr_to_int_inst = dyn_cast<PtrToIntInst>(inst); if (!ptr_to_int_inst) { - if (log) - log->Printf("getOpcode() returns PtrToInt, but instruction is not an " - "PtrToIntInst"); + LLDB_LOGF(log, + "getOpcode() returns PtrToInt, but instruction is not an " + "PtrToIntInst"); error.SetErrorToGenericError(); error.SetErrorString(interpreter_internal_error); return false; @@ -1247,8 +1219,7 @@ bool IRInterpreter::Interpret(llvm::Module &module, llvm::Function &function, lldb_private::Scalar I; if (!frame.EvaluateValue(I, src_operand, module)) { - if (log) - log->Printf("Couldn't evaluate %s", PrintValue(src_operand).c_str()); + LLDB_LOGF(log, "Couldn't evaluate %s", PrintValue(src_operand).c_str()); error.SetErrorToGenericError(); error.SetErrorString(bad_value_error); return false; @@ -1257,18 +1228,18 @@ bool IRInterpreter::Interpret(llvm::Module &module, llvm::Function &function, frame.AssignValue(inst, I, module); if (log) { - log->Printf("Interpreted a PtrToInt"); - log->Printf(" Src : %s", frame.SummarizeValue(src_operand).c_str()); - log->Printf(" = : %s", frame.SummarizeValue(inst).c_str()); + LLDB_LOGF(log, "Interpreted a PtrToInt"); + LLDB_LOGF(log, " Src : %s", frame.SummarizeValue(src_operand).c_str()); + LLDB_LOGF(log, " = : %s", frame.SummarizeValue(inst).c_str()); } } break; case Instruction::Trunc: { const TruncInst *trunc_inst = dyn_cast<TruncInst>(inst); if (!trunc_inst) { - if (log) - log->Printf( - "getOpcode() returns Trunc, but instruction is not a TruncInst"); + LLDB_LOGF( + log, + "getOpcode() returns Trunc, but instruction is not a TruncInst"); error.SetErrorToGenericError(); error.SetErrorString(interpreter_internal_error); return false; @@ -1279,8 +1250,7 @@ bool IRInterpreter::Interpret(llvm::Module &module, llvm::Function &function, lldb_private::Scalar I; if (!frame.EvaluateValue(I, src_operand, module)) { - if (log) - log->Printf("Couldn't evaluate %s", PrintValue(src_operand).c_str()); + LLDB_LOGF(log, "Couldn't evaluate %s", PrintValue(src_operand).c_str()); error.SetErrorToGenericError(); error.SetErrorString(bad_value_error); return false; @@ -1289,18 +1259,17 @@ bool IRInterpreter::Interpret(llvm::Module &module, llvm::Function &function, frame.AssignValue(inst, I, module); if (log) { - log->Printf("Interpreted a Trunc"); - log->Printf(" Src : %s", frame.SummarizeValue(src_operand).c_str()); - log->Printf(" = : %s", frame.SummarizeValue(inst).c_str()); + LLDB_LOGF(log, "Interpreted a Trunc"); + LLDB_LOGF(log, " Src : %s", frame.SummarizeValue(src_operand).c_str()); + LLDB_LOGF(log, " = : %s", frame.SummarizeValue(inst).c_str()); } } break; case Instruction::Load: { const LoadInst *load_inst = dyn_cast<LoadInst>(inst); if (!load_inst) { - if (log) - log->Printf( - "getOpcode() returns Load, but instruction is not a LoadInst"); + LLDB_LOGF( + log, "getOpcode() returns Load, but instruction is not a LoadInst"); error.SetErrorToGenericError(); error.SetErrorString(interpreter_internal_error); return false; @@ -1317,8 +1286,7 @@ bool IRInterpreter::Interpret(llvm::Module &module, llvm::Function &function, Type *pointer_ty = pointer_operand->getType(); PointerType *pointer_ptr_ty = dyn_cast<PointerType>(pointer_ty); if (!pointer_ptr_ty) { - if (log) - log->Printf("getPointerOperand()->getType() is not a PointerType"); + LLDB_LOGF(log, "getPointerOperand()->getType() is not a PointerType"); error.SetErrorToGenericError(); error.SetErrorString(interpreter_internal_error); return false; @@ -1329,16 +1297,14 @@ bool IRInterpreter::Interpret(llvm::Module &module, llvm::Function &function, lldb::addr_t P = frame.ResolveValue(pointer_operand, module); if (D == LLDB_INVALID_ADDRESS) { - if (log) - log->Printf("LoadInst's value doesn't resolve to anything"); + LLDB_LOGF(log, "LoadInst's value doesn't resolve to anything"); error.SetErrorToGenericError(); error.SetErrorString(bad_value_error); return false; } if (P == LLDB_INVALID_ADDRESS) { - if (log) - log->Printf("LoadInst's pointer doesn't resolve to anything"); + LLDB_LOGF(log, "LoadInst's pointer doesn't resolve to anything"); error.SetErrorToGenericError(); error.SetErrorString(bad_value_error); return false; @@ -1349,8 +1315,7 @@ bool IRInterpreter::Interpret(llvm::Module &module, llvm::Function &function, execution_unit.ReadPointerFromMemory(&R, P, read_error); if (!read_error.Success()) { - if (log) - log->Printf("Couldn't read the address to be loaded for a LoadInst"); + LLDB_LOGF(log, "Couldn't read the address to be loaded for a LoadInst"); error.SetErrorToGenericError(); error.SetErrorString(memory_read_error); return false; @@ -1363,8 +1328,7 @@ bool IRInterpreter::Interpret(llvm::Module &module, llvm::Function &function, execution_unit.ReadMemory(buffer.GetBytes(), R, buffer.GetByteSize(), read_error); if (!read_error.Success()) { - if (log) - log->Printf("Couldn't read from a region on behalf of a LoadInst"); + LLDB_LOGF(log, "Couldn't read from a region on behalf of a LoadInst"); error.SetErrorToGenericError(); error.SetErrorString(memory_read_error); return false; @@ -1374,18 +1338,17 @@ bool IRInterpreter::Interpret(llvm::Module &module, llvm::Function &function, execution_unit.WriteMemory(D, buffer.GetBytes(), buffer.GetByteSize(), write_error); if (!write_error.Success()) { - if (log) - log->Printf("Couldn't write to a region on behalf of a LoadInst"); + LLDB_LOGF(log, "Couldn't write to a region on behalf of a LoadInst"); error.SetErrorToGenericError(); error.SetErrorString(memory_read_error); return false; } if (log) { - log->Printf("Interpreted a LoadInst"); - log->Printf(" P : 0x%" PRIx64, P); - log->Printf(" R : 0x%" PRIx64, R); - log->Printf(" D : 0x%" PRIx64, D); + LLDB_LOGF(log, "Interpreted a LoadInst"); + LLDB_LOGF(log, " P : 0x%" PRIx64, P); + LLDB_LOGF(log, " R : 0x%" PRIx64, R); + LLDB_LOGF(log, " D : 0x%" PRIx64, D); } } break; case Instruction::Ret: { @@ -1395,9 +1358,9 @@ bool IRInterpreter::Interpret(llvm::Module &module, llvm::Function &function, const StoreInst *store_inst = dyn_cast<StoreInst>(inst); if (!store_inst) { - if (log) - log->Printf( - "getOpcode() returns Store, but instruction is not a StoreInst"); + LLDB_LOGF( + log, + "getOpcode() returns Store, but instruction is not a StoreInst"); error.SetErrorToGenericError(); error.SetErrorString(interpreter_internal_error); return false; @@ -1422,16 +1385,14 @@ bool IRInterpreter::Interpret(llvm::Module &module, llvm::Function &function, lldb::addr_t P = frame.ResolveValue(pointer_operand, module); if (D == LLDB_INVALID_ADDRESS) { - if (log) - log->Printf("StoreInst's value doesn't resolve to anything"); + LLDB_LOGF(log, "StoreInst's value doesn't resolve to anything"); error.SetErrorToGenericError(); error.SetErrorString(bad_value_error); return false; } if (P == LLDB_INVALID_ADDRESS) { - if (log) - log->Printf("StoreInst's pointer doesn't resolve to anything"); + LLDB_LOGF(log, "StoreInst's pointer doesn't resolve to anything"); error.SetErrorToGenericError(); error.SetErrorString(bad_value_error); return false; @@ -1442,8 +1403,7 @@ bool IRInterpreter::Interpret(llvm::Module &module, llvm::Function &function, execution_unit.ReadPointerFromMemory(&R, P, read_error); if (!read_error.Success()) { - if (log) - log->Printf("Couldn't read the address to be loaded for a LoadInst"); + LLDB_LOGF(log, "Couldn't read the address to be loaded for a LoadInst"); error.SetErrorToGenericError(); error.SetErrorString(memory_read_error); return false; @@ -1456,8 +1416,7 @@ bool IRInterpreter::Interpret(llvm::Module &module, llvm::Function &function, execution_unit.ReadMemory(buffer.GetBytes(), D, buffer.GetByteSize(), read_error); if (!read_error.Success()) { - if (log) - log->Printf("Couldn't read from a region on behalf of a StoreInst"); + LLDB_LOGF(log, "Couldn't read from a region on behalf of a StoreInst"); error.SetErrorToGenericError(); error.SetErrorString(memory_read_error); return false; @@ -1467,28 +1426,26 @@ bool IRInterpreter::Interpret(llvm::Module &module, llvm::Function &function, execution_unit.WriteMemory(R, buffer.GetBytes(), buffer.GetByteSize(), write_error); if (!write_error.Success()) { - if (log) - log->Printf("Couldn't write to a region on behalf of a StoreInst"); + LLDB_LOGF(log, "Couldn't write to a region on behalf of a StoreInst"); error.SetErrorToGenericError(); error.SetErrorString(memory_write_error); return false; } if (log) { - log->Printf("Interpreted a StoreInst"); - log->Printf(" D : 0x%" PRIx64, D); - log->Printf(" P : 0x%" PRIx64, P); - log->Printf(" R : 0x%" PRIx64, R); + LLDB_LOGF(log, "Interpreted a StoreInst"); + LLDB_LOGF(log, " D : 0x%" PRIx64, D); + LLDB_LOGF(log, " P : 0x%" PRIx64, P); + LLDB_LOGF(log, " R : 0x%" PRIx64, R); } } break; case Instruction::Call: { const CallInst *call_inst = dyn_cast<CallInst>(inst); if (!call_inst) { - if (log) - log->Printf( - "getOpcode() returns %s, but instruction is not a CallInst", - inst->getOpcodeName()); + LLDB_LOGF(log, + "getOpcode() returns %s, but instruction is not a CallInst", + inst->getOpcodeName()); error.SetErrorToGenericError(); error.SetErrorString(interpreter_internal_error); return false; diff --git a/source/Expression/IRMemoryMap.cpp b/source/Expression/IRMemoryMap.cpp index 70e62ac12b0e..5fdf452bf94e 100644 --- a/source/Expression/IRMemoryMap.cpp +++ b/source/Expression/IRMemoryMap.cpp @@ -327,12 +327,12 @@ lldb::addr_t IRMemoryMap::Malloc(size_t size, uint8_t alignment, break; case eAllocationPolicyMirror: process_sp = m_process_wp.lock(); - if (log) - log->Printf("IRMemoryMap::%s process_sp=0x%" PRIx64 - ", process_sp->CanJIT()=%s, process_sp->IsAlive()=%s", - __FUNCTION__, (lldb::addr_t)process_sp.get(), - process_sp && process_sp->CanJIT() ? "true" : "false", - process_sp && process_sp->IsAlive() ? "true" : "false"); + LLDB_LOGF(log, + "IRMemoryMap::%s process_sp=0x%" PRIx64 + ", process_sp->CanJIT()=%s, process_sp->IsAlive()=%s", + __FUNCTION__, (lldb::addr_t)process_sp.get(), + process_sp && process_sp->CanJIT() ? "true" : "false", + process_sp && process_sp->IsAlive() ? "true" : "false"); if (process_sp && process_sp->CanJIT() && process_sp->IsAlive()) { if (!zero_memory) allocation_address = @@ -344,10 +344,10 @@ lldb::addr_t IRMemoryMap::Malloc(size_t size, uint8_t alignment, if (!error.Success()) return LLDB_INVALID_ADDRESS; } else { - if (log) - log->Printf("IRMemoryMap::%s switching to eAllocationPolicyHostOnly " - "due to failed condition (see previous expr log message)", - __FUNCTION__); + LLDB_LOGF(log, + "IRMemoryMap::%s switching to eAllocationPolicyHostOnly " + "due to failed condition (see previous expr log message)", + __FUNCTION__); policy = eAllocationPolicyHostOnly; allocation_address = FindSpace(allocation_size); if (allocation_address == LLDB_INVALID_ADDRESS) { @@ -417,10 +417,11 @@ lldb::addr_t IRMemoryMap::Malloc(size_t size, uint8_t alignment, break; } - log->Printf("IRMemoryMap::Malloc (%" PRIu64 ", 0x%" PRIx64 ", 0x%" PRIx64 - ", %s) -> 0x%" PRIx64, - (uint64_t)allocation_size, (uint64_t)alignment, - (uint64_t)permissions, policy_string, aligned_address); + LLDB_LOGF(log, + "IRMemoryMap::Malloc (%" PRIu64 ", 0x%" PRIx64 ", 0x%" PRIx64 + ", %s) -> 0x%" PRIx64, + (uint64_t)allocation_size, (uint64_t)alignment, + (uint64_t)permissions, policy_string, aligned_address); } return aligned_address; @@ -477,10 +478,11 @@ void IRMemoryMap::Free(lldb::addr_t process_address, Status &error) { if (lldb_private::Log *log = lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_EXPRESSIONS)) { - log->Printf("IRMemoryMap::Free (0x%" PRIx64 ") freed [0x%" PRIx64 - "..0x%" PRIx64 ")", - (uint64_t)process_address, iter->second.m_process_start, - iter->second.m_process_start + iter->second.m_size); + LLDB_LOGF(log, + "IRMemoryMap::Free (0x%" PRIx64 ") freed [0x%" PRIx64 + "..0x%" PRIx64 ")", + (uint64_t)process_address, iter->second.m_process_start, + iter->second.m_process_start + iter->second.m_size); } m_allocations.erase(iter); @@ -574,12 +576,13 @@ void IRMemoryMap::WriteMemory(lldb::addr_t process_address, if (lldb_private::Log *log = lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_EXPRESSIONS)) { - log->Printf("IRMemoryMap::WriteMemory (0x%" PRIx64 ", 0x%" PRIx64 - ", 0x%" PRId64 ") went to [0x%" PRIx64 "..0x%" PRIx64 ")", - (uint64_t)process_address, (uint64_t)bytes, (uint64_t)size, - (uint64_t)allocation.m_process_start, - (uint64_t)allocation.m_process_start + - (uint64_t)allocation.m_size); + LLDB_LOGF(log, + "IRMemoryMap::WriteMemory (0x%" PRIx64 ", 0x%" PRIx64 + ", 0x%" PRId64 ") went to [0x%" PRIx64 "..0x%" PRIx64 ")", + (uint64_t)process_address, (uint64_t)bytes, (uint64_t)size, + (uint64_t)allocation.m_process_start, + (uint64_t)allocation.m_process_start + + (uint64_t)allocation.m_size); } } @@ -704,12 +707,13 @@ void IRMemoryMap::ReadMemory(uint8_t *bytes, lldb::addr_t process_address, if (lldb_private::Log *log = lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_EXPRESSIONS)) { - log->Printf("IRMemoryMap::ReadMemory (0x%" PRIx64 ", 0x%" PRIx64 - ", 0x%" PRId64 ") came from [0x%" PRIx64 "..0x%" PRIx64 ")", - (uint64_t)process_address, (uint64_t)bytes, (uint64_t)size, - (uint64_t)allocation.m_process_start, - (uint64_t)allocation.m_process_start + - (uint64_t)allocation.m_size); + LLDB_LOGF(log, + "IRMemoryMap::ReadMemory (0x%" PRIx64 ", 0x%" PRIx64 + ", 0x%" PRId64 ") came from [0x%" PRIx64 "..0x%" PRIx64 ")", + (uint64_t)process_address, (uint64_t)bytes, (uint64_t)size, + (uint64_t)allocation.m_process_start, + (uint64_t)allocation.m_process_start + + (uint64_t)allocation.m_size); } } diff --git a/source/Expression/LLVMUserExpression.cpp b/source/Expression/LLVMUserExpression.cpp index 5a1b750318c9..99e0c11df420 100644 --- a/source/Expression/LLVMUserExpression.cpp +++ b/source/Expression/LLVMUserExpression.cpp @@ -12,13 +12,12 @@ #include "lldb/Core/StreamFile.h" #include "lldb/Core/ValueObjectConstResult.h" #include "lldb/Expression/DiagnosticManager.h" +#include "lldb/Expression/ExpressionVariable.h" #include "lldb/Expression/IRExecutionUnit.h" #include "lldb/Expression/IRInterpreter.h" #include "lldb/Expression/Materializer.h" #include "lldb/Host/HostInfo.h" #include "lldb/Symbol/Block.h" -#include "lldb/Symbol/ClangASTContext.h" -#include "lldb/Symbol/ClangExternalASTSourceCommon.h" #include "lldb/Symbol/Function.h" #include "lldb/Symbol/ObjectFile.h" #include "lldb/Symbol/SymbolVendor.h" @@ -48,9 +47,7 @@ LLVMUserExpression::LLVMUserExpression(ExecutionContextScope &exe_scope, m_stack_frame_bottom(LLDB_INVALID_ADDRESS), m_stack_frame_top(LLDB_INVALID_ADDRESS), m_allow_cxx(false), m_allow_objc(false), m_transformed_text(), m_execution_unit_sp(), - m_materializer_up(), m_jit_module_wp(), m_enforce_valid_object(true), - m_in_cplusplus_method(false), m_in_objectivec_method(false), - m_in_static_method(false), m_needs_object_ptr(false), m_target(nullptr), + m_materializer_up(), m_jit_module_wp(), m_can_interpret(false), m_materialized_address(LLDB_INVALID_ADDRESS) {} LLVMUserExpression::~LLVMUserExpression() { @@ -161,9 +158,9 @@ LLVMUserExpression::DoExecute(DiagnosticManager &diagnostic_manager, function_stack_bottom = function_stack_pointer - HostInfo::GetPageSize(); function_stack_top = function_stack_pointer; - if (log) - log->Printf( - "-- [UserExpression::Execute] Execution of expression begins --"); + LLDB_LOGF( + log, + "-- [UserExpression::Execute] Execution of expression begins --"); if (exe_ctx.GetProcessPtr()) exe_ctx.GetProcessPtr()->SetRunningUserExpression(true); @@ -175,9 +172,8 @@ LLVMUserExpression::DoExecute(DiagnosticManager &diagnostic_manager, if (exe_ctx.GetProcessPtr()) exe_ctx.GetProcessPtr()->SetRunningUserExpression(false); - if (log) - log->Printf("-- [UserExpression::Execute] Execution of expression " - "completed --"); + LLDB_LOGF(log, "-- [UserExpression::Execute] Execution of expression " + "completed --"); if (execution_result == lldb::eExpressionInterrupted || execution_result == lldb::eExpressionHitBreakpoint) { @@ -251,9 +247,8 @@ bool LLVMUserExpression::FinalizeJITExecution( lldb::addr_t function_stack_top) { Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_EXPRESSIONS)); - if (log) - log->Printf("-- [UserExpression::FinalizeJITExecution] Dematerializing " - "after execution --"); + LLDB_LOGF(log, "-- [UserExpression::FinalizeJITExecution] Dematerializing " + "after execution --"); if (!m_dematerializer_sp) { diagnostic_manager.Printf(eDiagnosticSeverityError, diff --git a/source/Expression/Materializer.cpp b/source/Expression/Materializer.cpp index 0f871fcbefbc..cd332484debb 100644 --- a/source/Expression/Materializer.cpp +++ b/source/Expression/Materializer.cpp @@ -11,7 +11,6 @@ #include "lldb/Core/ValueObjectConstResult.h" #include "lldb/Core/ValueObjectVariable.h" #include "lldb/Expression/ExpressionVariable.h" -#include "lldb/Symbol/ClangASTContext.h" #include "lldb/Symbol/Symbol.h" #include "lldb/Symbol/Type.h" #include "lldb/Symbol/Variable.h" @@ -46,20 +45,6 @@ uint32_t Materializer::AddStructMember(Entity &entity) { return ret; } -void Materializer::Entity::SetSizeAndAlignmentFromType(CompilerType &type) { - if (llvm::Optional<uint64_t> size = type.GetByteSize(nullptr)) - m_size = *size; - - uint32_t bit_alignment = type.GetTypeBitAlign(); - - if (bit_alignment % 8) { - bit_alignment += 8; - bit_alignment &= ~((uint32_t)0x111u); - } - - m_alignment = bit_alignment / 8; -} - class EntityPersistentVariable : public Materializer::Entity { public: EntityPersistentVariable(lldb::ExpressionVariableSP &persistent_variable_sp, @@ -94,9 +79,8 @@ public: return; } - if (log) - log->Printf("Allocated %s (0x%" PRIx64 ") successfully", - m_persistent_variable_sp->GetName().GetCString(), mem); + LLDB_LOGF(log, "Allocated %s (0x%" PRIx64 ") successfully", + m_persistent_variable_sp->GetName().GetCString(), mem); // Put the location of the spare memory into the live data of the // ValueObject. @@ -158,11 +142,12 @@ public: const lldb::addr_t load_addr = process_address + m_offset; if (log) { - log->Printf("EntityPersistentVariable::Materialize [address = 0x%" PRIx64 - ", m_name = %s, m_flags = 0x%hx]", - (uint64_t)load_addr, - m_persistent_variable_sp->GetName().AsCString(), - m_persistent_variable_sp->m_flags); + LLDB_LOGF(log, + "EntityPersistentVariable::Materialize [address = 0x%" PRIx64 + ", m_name = %s, m_flags = 0x%hx]", + (uint64_t)load_addr, + m_persistent_variable_sp->GetName().AsCString(), + m_persistent_variable_sp->m_flags); } if (m_persistent_variable_sp->m_flags & @@ -209,12 +194,12 @@ public: const lldb::addr_t load_addr = process_address + m_offset; if (log) { - log->Printf( - "EntityPersistentVariable::Dematerialize [address = 0x%" PRIx64 - ", m_name = %s, m_flags = 0x%hx]", - (uint64_t)process_address + m_offset, - m_persistent_variable_sp->GetName().AsCString(), - m_persistent_variable_sp->m_flags); + LLDB_LOGF(log, + "EntityPersistentVariable::Dematerialize [address = 0x%" PRIx64 + ", m_name = %s, m_flags = 0x%hx]", + (uint64_t)process_address + m_offset, + m_persistent_variable_sp->GetName().AsCString(), + m_persistent_variable_sp->m_flags); } if (m_delegate) { @@ -291,11 +276,10 @@ public: ExpressionVariable::EVNeedsFreezeDry || m_persistent_variable_sp->m_flags & ExpressionVariable::EVKeepInTarget) { - if (log) - log->Printf( - "Dematerializing %s from 0x%" PRIx64 " (size = %llu)", - m_persistent_variable_sp->GetName().GetCString(), (uint64_t)mem, - (unsigned long long)m_persistent_variable_sp->GetByteSize()); + LLDB_LOGF(log, "Dematerializing %s from 0x%" PRIx64 " (size = %llu)", + m_persistent_variable_sp->GetName().GetCString(), + (uint64_t)mem, + (unsigned long long)m_persistent_variable_sp->GetByteSize()); // Read the contents of the spare memory area @@ -441,9 +425,10 @@ public: const lldb::addr_t load_addr = process_address + m_offset; if (log) { - log->Printf("EntityVariable::Materialize [address = 0x%" PRIx64 - ", m_variable_sp = %s]", - (uint64_t)load_addr, m_variable_sp->GetName().AsCString()); + LLDB_LOGF(log, + "EntityVariable::Materialize [address = 0x%" PRIx64 + ", m_variable_sp = %s]", + (uint64_t)load_addr, m_variable_sp->GetName().AsCString()); } ExecutionContextScope *scope = frame_sp.get(); @@ -545,12 +530,15 @@ public: return; } - size_t bit_align = - m_variable_sp->GetType()->GetLayoutCompilerType().GetTypeBitAlign(); - size_t byte_align = (bit_align + 7) / 8; + llvm::Optional<size_t> opt_bit_align = + m_variable_sp->GetType()->GetLayoutCompilerType().GetTypeBitAlign(scope); + if (!opt_bit_align) { + err.SetErrorStringWithFormat("can't get the type alignment for %s", + m_variable_sp->GetName().AsCString()); + return; + } - if (!byte_align) - byte_align = 1; + size_t byte_align = (*opt_bit_align + 7) / 8; Status alloc_error; const bool zero_memory = false; @@ -606,9 +594,10 @@ public: const lldb::addr_t load_addr = process_address + m_offset; if (log) { - log->Printf("EntityVariable::Dematerialize [address = 0x%" PRIx64 - ", m_variable_sp = %s]", - (uint64_t)load_addr, m_variable_sp->GetName().AsCString()); + LLDB_LOGF(log, + "EntityVariable::Dematerialize [address = 0x%" PRIx64 + ", m_variable_sp = %s]", + (uint64_t)load_addr, m_variable_sp->GetName().AsCString()); } if (m_temporary_allocation != LLDB_INVALID_ADDRESS) { @@ -802,11 +791,14 @@ public: err.SetErrorString("can't get size of type"); return; } - size_t bit_align = m_type.GetTypeBitAlign(); - size_t byte_align = (bit_align + 7) / 8; - if (!byte_align) - byte_align = 1; + llvm::Optional<size_t> opt_bit_align = m_type.GetTypeBitAlign(exe_scope); + if (!opt_bit_align) { + err.SetErrorStringWithFormat("can't get the type alignment"); + return; + } + + size_t byte_align = (*opt_bit_align + 7) / 8; Status alloc_error; const bool zero_memory = true; @@ -869,20 +861,18 @@ public: return; } - Status type_system_error; - TypeSystem *type_system = target_sp->GetScratchTypeSystemForLanguage( - &type_system_error, m_type.GetMinimumLanguage()); + auto type_system_or_err = + target_sp->GetScratchTypeSystemForLanguage(m_type.GetMinimumLanguage()); - if (!type_system) { + if (auto error = type_system_or_err.takeError()) { err.SetErrorStringWithFormat("Couldn't dematerialize a result variable: " "couldn't get the corresponding type " "system: %s", - type_system_error.AsCString()); + llvm::toString(std::move(error)).c_str()); return; } - PersistentExpressionState *persistent_state = - type_system->GetPersistentExpressionState(); + type_system_or_err->GetPersistentExpressionState(); if (!persistent_state) { err.SetErrorString("Couldn't dematerialize a result variable: " @@ -1064,9 +1054,10 @@ public: const lldb::addr_t load_addr = process_address + m_offset; if (log) { - log->Printf("EntitySymbol::Materialize [address = 0x%" PRIx64 - ", m_symbol = %s]", - (uint64_t)load_addr, m_symbol.GetName().AsCString()); + LLDB_LOGF(log, + "EntitySymbol::Materialize [address = 0x%" PRIx64 + ", m_symbol = %s]", + (uint64_t)load_addr, m_symbol.GetName().AsCString()); } const Address sym_address = m_symbol.GetAddress(); @@ -1110,9 +1101,10 @@ public: const lldb::addr_t load_addr = process_address + m_offset; if (log) { - log->Printf("EntitySymbol::Dematerialize [address = 0x%" PRIx64 - ", m_symbol = %s]", - (uint64_t)load_addr, m_symbol.GetName().AsCString()); + LLDB_LOGF(log, + "EntitySymbol::Dematerialize [address = 0x%" PRIx64 + ", m_symbol = %s]", + (uint64_t)load_addr, m_symbol.GetName().AsCString()); } // no work needs to be done @@ -1179,9 +1171,10 @@ public: const lldb::addr_t load_addr = process_address + m_offset; if (log) { - log->Printf("EntityRegister::Materialize [address = 0x%" PRIx64 - ", m_register_info = %s]", - (uint64_t)load_addr, m_register_info.name); + LLDB_LOGF(log, + "EntityRegister::Materialize [address = 0x%" PRIx64 + ", m_register_info = %s]", + (uint64_t)load_addr, m_register_info.name); } RegisterValue reg_value; @@ -1241,9 +1234,10 @@ public: const lldb::addr_t load_addr = process_address + m_offset; if (log) { - log->Printf("EntityRegister::Dematerialize [address = 0x%" PRIx64 - ", m_register_info = %s]", - (uint64_t)load_addr, m_register_info.name); + LLDB_LOGF(log, + "EntityRegister::Dematerialize [address = 0x%" PRIx64 + ", m_register_info = %s]", + (uint64_t)load_addr, m_register_info.name); } Status extract_error; @@ -1380,7 +1374,8 @@ Materializer::Materialize(lldb::StackFrameSP &frame_sp, IRMemoryMap &map, if (Log *log = lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_EXPRESSIONS)) { - log->Printf( + LLDB_LOGF( + log, "Materializer::Materialize (frame_sp = %p, process_address = 0x%" PRIx64 ") materialized:", static_cast<void *>(frame_sp.get()), process_address); @@ -1415,9 +1410,10 @@ void Materializer::Dematerializer::Dematerialize(Status &error, } else { if (Log *log = lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_EXPRESSIONS)) { - log->Printf("Materializer::Dematerialize (frame_sp = %p, process_address " - "= 0x%" PRIx64 ") about to dematerialize:", - static_cast<void *>(frame_sp.get()), m_process_address); + LLDB_LOGF(log, + "Materializer::Dematerialize (frame_sp = %p, process_address " + "= 0x%" PRIx64 ") about to dematerialize:", + static_cast<void *>(frame_sp.get()), m_process_address); for (EntityUP &entity_up : m_materializer->m_entities) entity_up->DumpToLog(*m_map, m_process_address, log); } diff --git a/source/Expression/REPL.cpp b/source/Expression/REPL.cpp index f4ed887729d8..4f81ee3e56dd 100644 --- a/source/Expression/REPL.cpp +++ b/source/Expression/REPL.cpp @@ -96,7 +96,7 @@ void REPL::IOHandlerActivated(IOHandler &io_handler, bool interactive) { lldb::ProcessSP process_sp = m_target.GetProcessSP(); if (process_sp && process_sp->IsAlive()) return; - lldb::StreamFileSP error_sp(io_handler.GetErrorStreamFile()); + lldb::StreamFileSP error_sp(io_handler.GetErrorStreamFileSP()); error_sp->Printf("REPL requires a running target process.\n"); io_handler.SetIsDone(true); } @@ -180,8 +180,8 @@ int REPL::IOHandlerFixIndentation(IOHandler &io_handler, } void REPL::IOHandlerInputComplete(IOHandler &io_handler, std::string &code) { - lldb::StreamFileSP output_sp(io_handler.GetOutputStreamFile()); - lldb::StreamFileSP error_sp(io_handler.GetErrorStreamFile()); + lldb::StreamFileSP output_sp(io_handler.GetOutputStreamFileSP()); + lldb::StreamFileSP error_sp(io_handler.GetErrorStreamFileSP()); bool extra_line = false; bool did_quit = false; @@ -206,7 +206,7 @@ void REPL::IOHandlerInputComplete(IOHandler &io_handler, std::string &code) { // Meta command // Strip the ':' code.erase(0, 1); - if (Args::StripSpaces(code)) { + if (!llvm::StringRef(code).trim().empty()) { // "lldb" was followed by arguments, so just execute the command dump // the results @@ -398,17 +398,22 @@ void REPL::IOHandlerInputComplete(IOHandler &io_handler, std::string &code) { // Update our code on disk if (!m_repl_source_path.empty()) { - lldb_private::File file; - FileSystem::Instance().Open(file, FileSpec(m_repl_source_path), - File::eOpenOptionWrite | - File::eOpenOptionTruncate | - File::eOpenOptionCanCreate, - lldb::eFilePermissionsFileDefault); - std::string code(m_code.CopyList()); - code.append(1, '\n'); - size_t bytes_written = code.size(); - file.Write(code.c_str(), bytes_written); - file.Close(); + auto file = FileSystem::Instance().Open( + FileSpec(m_repl_source_path), + File::eOpenOptionWrite | File::eOpenOptionTruncate | + File::eOpenOptionCanCreate, + lldb::eFilePermissionsFileDefault); + if (file) { + std::string code(m_code.CopyList()); + code.append(1, '\n'); + size_t bytes_written = code.size(); + file.get()->Write(code.c_str(), bytes_written); + file.get()->Close(); + } else { + std::string message = llvm::toString(file.takeError()); + error_sp->Printf("error: couldn't open %s: %s\n", + m_repl_source_path.c_str(), message.c_str()); + } // Now set the default file and line to the REPL source file m_target.GetSourceManager().SetDefaultFileAndLine( @@ -418,7 +423,7 @@ void REPL::IOHandlerInputComplete(IOHandler &io_handler, std::string &code) { .SetBaseLineNumber(m_code.GetSize() + 1); } if (extra_line) { - fprintf(output_sp->GetFile().GetStream(), "\n"); + output_sp->Printf("\n"); } } } @@ -433,31 +438,30 @@ void REPL::IOHandlerInputComplete(IOHandler &io_handler, std::string &code) { } } -int REPL::IOHandlerComplete(IOHandler &io_handler, const char *current_line, - const char *cursor, const char *last_char, - int skip_first_n_matches, int max_matches, - StringList &matches, StringList &descriptions) { - matches.Clear(); - - llvm::StringRef line(current_line, cursor - current_line); - +void REPL::IOHandlerComplete(IOHandler &io_handler, + CompletionRequest &request) { // Complete an LLDB command if the first character is a colon... - if (!line.empty() && line[0] == ':') { + if (request.GetRawLine().startswith(":")) { Debugger &debugger = m_target.GetDebugger(); // auto complete LLDB commands - const char *lldb_current_line = line.substr(1).data(); - return debugger.GetCommandInterpreter().HandleCompletion( - lldb_current_line, cursor, last_char, skip_first_n_matches, max_matches, - matches, descriptions); + llvm::StringRef new_line = request.GetRawLine().drop_front(); + CompletionResult sub_result; + CompletionRequest sub_request(new_line, request.GetRawCursorPos() - 1, + sub_result); + debugger.GetCommandInterpreter().HandleCompletion(sub_request); + StringList matches, descriptions; + sub_result.GetMatches(matches); + sub_result.GetDescriptions(descriptions); + request.AddCompletions(matches, descriptions); + return; } // Strip spaces from the line and see if we had only spaces - line = line.ltrim(); - if (line.empty()) { + if (request.GetRawLine().trim().empty()) { // Only spaces on this line, so just indent - matches.AppendString(m_indent_str); - return 1; + request.AddCompletion(m_indent_str); + return; } std::string current_code; @@ -479,12 +483,17 @@ int REPL::IOHandlerComplete(IOHandler &io_handler, const char *current_line, } } - if (cursor > current_line) { - current_code.append("\n"); - current_code.append(current_line, cursor - current_line); - } - - return CompleteCode(current_code, matches); + current_code.append("\n"); + current_code += request.GetRawLine(); + + StringList matches; + int result = CompleteCode(current_code, matches); + if (result == -2) { + assert(matches.GetSize() == 1); + request.AddCompletion(matches.GetStringAtIndex(0), "", + CompletionMode::RewriteLine); + } else + request.AddCompletions(matches); } bool QuitCommandOverrideCallback(void *baton, const char **argv) { diff --git a/source/Expression/UserExpression.cpp b/source/Expression/UserExpression.cpp index a72e2a07599e..e2d1d2f2b3d2 100644 --- a/source/Expression/UserExpression.cpp +++ b/source/Expression/UserExpression.cpp @@ -6,6 +6,8 @@ // //===----------------------------------------------------------------------===// +#include "lldb/Host/Config.h" + #include <stdio.h> #if HAVE_SYS_TYPES_H #include <sys/types.h> @@ -165,9 +167,8 @@ lldb::ExpressionResults UserExpression::Evaluate( Target *target = exe_ctx.GetTargetPtr(); if (!target) { - if (log) - log->Printf("== [UserExpression::Evaluate] Passed a NULL target, can't " - "run expressions."); + LLDB_LOGF(log, "== [UserExpression::Evaluate] Passed a NULL target, can't " + "run expressions."); error.SetErrorString("expression passed a null target"); return lldb::eExpressionSetupError; } @@ -176,9 +177,9 @@ lldb::ExpressionResults UserExpression::Evaluate( if (process == nullptr || process->GetState() != lldb::eStateStopped) { if (execution_policy == eExecutionPolicyAlways) { - if (log) - log->Printf("== [UserExpression::Evaluate] Expression may not run, but " - "is not constant =="); + LLDB_LOGF(log, + "== [UserExpression::Evaluate] Expression may not run, but " + "is not constant =="); error.SetErrorString("expression needed to run but couldn't"); @@ -224,14 +225,14 @@ lldb::ExpressionResults UserExpression::Evaluate( error)); if (error.Fail()) { if (log) - log->Printf("== [UserExpression::Evaluate] Getting expression: %s ==", - error.AsCString()); + LLDB_LOGF(log, "== [UserExpression::Evaluate] Getting expression: %s ==", + error.AsCString()); return lldb::eExpressionSetupError; } if (log) - log->Printf("== [UserExpression::Evaluate] Parsing expression %s ==", - expr.str().c_str()); + LLDB_LOGF(log, "== [UserExpression::Evaluate] Parsing expression %s ==", + expr.str().c_str()); const bool keep_expression_in_memory = true; const bool generate_debug_info = options.GetGenerateDebugInfo(); @@ -310,8 +311,9 @@ lldb::ExpressionResults UserExpression::Evaluate( if (execution_policy == eExecutionPolicyNever && !user_expression_sp->CanInterpret()) { if (log) - log->Printf("== [UserExpression::Evaluate] Expression may not run, but " - "is not constant =="); + LLDB_LOGF(log, + "== [UserExpression::Evaluate] Expression may not run, but " + "is not constant =="); if (!diagnostic_manager.Diagnostics().size()) error.SetExpressionError(lldb::eExpressionSetupError, @@ -332,7 +334,7 @@ lldb::ExpressionResults UserExpression::Evaluate( diagnostic_manager.Clear(); if (log) - log->Printf("== [UserExpression::Evaluate] Executing expression =="); + LLDB_LOGF(log, "== [UserExpression::Evaluate] Executing expression =="); execution_results = user_expression_sp->Execute(diagnostic_manager, exe_ctx, options, @@ -340,8 +342,8 @@ lldb::ExpressionResults UserExpression::Evaluate( if (execution_results != lldb::eExpressionCompleted) { if (log) - log->Printf("== [UserExpression::Evaluate] Execution completed " - "abnormally =="); + LLDB_LOGF(log, "== [UserExpression::Evaluate] Execution completed " + "abnormally =="); if (!diagnostic_manager.Diagnostics().size()) error.SetExpressionError( @@ -354,13 +356,14 @@ lldb::ExpressionResults UserExpression::Evaluate( result_valobj_sp = expr_result->GetValueObject(); if (log) - log->Printf("== [UserExpression::Evaluate] Execution completed " - "normally with result %s ==", - result_valobj_sp->GetValueAsCString()); + LLDB_LOGF(log, + "== [UserExpression::Evaluate] Execution completed " + "normally with result %s ==", + result_valobj_sp->GetValueAsCString()); } else { if (log) - log->Printf("== [UserExpression::Evaluate] Execution completed " - "normally with no result =="); + LLDB_LOGF(log, "== [UserExpression::Evaluate] Execution completed " + "normally with no result =="); error.SetError(UserExpression::kNoResult, lldb::eErrorTypeGeneric); } diff --git a/source/Expression/UtilityFunction.cpp b/source/Expression/UtilityFunction.cpp index eeaeca18da86..aac8b33a6bfa 100644 --- a/source/Expression/UtilityFunction.cpp +++ b/source/Expression/UtilityFunction.cpp @@ -6,6 +6,8 @@ // //===----------------------------------------------------------------------===// +#include "lldb/Host/Config.h" + #include <stdio.h> #if HAVE_SYS_TYPES_H #include <sys/types.h> diff --git a/source/Host/common/Editline.cpp b/source/Host/common/Editline.cpp index d3a70aeaa326..3e655244b107 100644 --- a/source/Host/common/Editline.cpp +++ b/source/Host/common/Editline.cpp @@ -14,6 +14,7 @@ #include "lldb/Host/Editline.h" #include "lldb/Host/FileSystem.h" #include "lldb/Host/Host.h" +#include "lldb/Utility/CompletionRequest.h" #include "lldb/Utility/FileSpec.h" #include "lldb/Utility/LLDBAssert.h" #include "lldb/Utility/SelectHelper.h" @@ -863,26 +864,59 @@ unsigned char Editline::BufferEndCommand(int ch) { /// Prints completions and their descriptions to the given file. Only the /// completions in the interval [start, end) are printed. -static void PrintCompletion(FILE *output_file, size_t start, size_t end, - StringList &completions, StringList &descriptions) { - // This is an 'int' because of printf. - int max_len = 0; - - for (size_t i = start; i < end; i++) { - const char *completion_str = completions.GetStringAtIndex(i); - max_len = std::max((int)strlen(completion_str), max_len); +static void +PrintCompletion(FILE *output_file, + llvm::ArrayRef<CompletionResult::Completion> results, + size_t max_len) { + for (const CompletionResult::Completion &c : results) { + fprintf(output_file, "\t%-*s", (int)max_len, c.GetCompletion().c_str()); + if (!c.GetDescription().empty()) + fprintf(output_file, " -- %s", c.GetDescription().c_str()); + fprintf(output_file, "\n"); } +} + +static void +DisplayCompletions(::EditLine *editline, FILE *output_file, + llvm::ArrayRef<CompletionResult::Completion> results) { + assert(!results.empty()); - for (size_t i = start; i < end; i++) { - const char *completion_str = completions.GetStringAtIndex(i); - const char *description_str = descriptions.GetStringAtIndex(i); + fprintf(output_file, "\n" ANSI_CLEAR_BELOW "Available completions:\n"); + const size_t page_size = 40; + bool all = false; - if (completion_str) - fprintf(output_file, "\n\t%-*s", max_len, completion_str); + auto longest = + std::max_element(results.begin(), results.end(), [](auto &c1, auto &c2) { + return c1.GetCompletion().size() < c2.GetCompletion().size(); + }); - // Print the description if we got one. - if (description_str && strlen(description_str)) - fprintf(output_file, " -- %s", description_str); + const size_t max_len = longest->GetCompletion().size(); + + if (results.size() < page_size) { + PrintCompletion(output_file, results, max_len); + return; + } + + size_t cur_pos = 0; + while (cur_pos < results.size()) { + size_t remaining = results.size() - cur_pos; + size_t next_size = all ? remaining : std::min(page_size, remaining); + + PrintCompletion(output_file, results.slice(cur_pos, next_size), max_len); + + cur_pos += next_size; + + if (cur_pos >= results.size()) + break; + + fprintf(output_file, "More (Y/n/a): "); + char reply = 'n'; + int got_char = el_getc(editline, &reply); + fprintf(output_file, "\n"); + if (got_char == -1 || reply == 'n') + break; + if (reply == 'a') + all = true; } } @@ -891,74 +925,64 @@ unsigned char Editline::TabCommand(int ch) { return CC_ERROR; const LineInfo *line_info = el_line(m_editline); - StringList completions, descriptions; - int page_size = 40; - const int num_completions = m_completion_callback( - line_info->buffer, line_info->cursor, line_info->lastchar, - 0, // Don't skip any matches (start at match zero) - -1, // Get all the matches - completions, descriptions, m_completion_callback_baton); + llvm::StringRef line(line_info->buffer, + line_info->lastchar - line_info->buffer); + unsigned cursor_index = line_info->cursor - line_info->buffer; + CompletionResult result; + CompletionRequest request(line, cursor_index, result); - if (num_completions == 0) + m_completion_callback(request, m_completion_callback_baton); + + llvm::ArrayRef<CompletionResult::Completion> results = result.GetResults(); + + StringList completions; + result.GetMatches(completions); + + if (results.size() == 0) return CC_ERROR; - // if (num_completions == -1) - // { - // el_insertstr (m_editline, m_completion_key); - // return CC_REDISPLAY; - // } - // else - if (num_completions == -2) { - // Replace the entire line with the first string... - el_deletestr(m_editline, line_info->cursor - line_info->buffer); - el_insertstr(m_editline, completions.GetStringAtIndex(0)); + + if (results.size() == 1) { + CompletionResult::Completion completion = results.front(); + switch (completion.GetMode()) { + case CompletionMode::Normal: { + std::string to_add = completion.GetCompletion(); + to_add = to_add.substr(request.GetCursorArgumentPrefix().size()); + if (request.GetParsedArg().IsQuoted()) + to_add.push_back(request.GetParsedArg().GetQuoteChar()); + to_add.push_back(' '); + el_insertstr(m_editline, to_add.c_str()); + break; + } + case CompletionMode::Partial: { + std::string to_add = completion.GetCompletion(); + to_add = to_add.substr(request.GetCursorArgumentPrefix().size()); + el_insertstr(m_editline, to_add.c_str()); + break; + } + case CompletionMode::RewriteLine: { + el_deletestr(m_editline, line_info->cursor - line_info->buffer); + el_insertstr(m_editline, completion.GetCompletion().c_str()); + break; + } + } return CC_REDISPLAY; } // If we get a longer match display that first. - const char *completion_str = completions.GetStringAtIndex(0); - if (completion_str != nullptr && *completion_str != '\0') { - el_insertstr(m_editline, completion_str); + std::string longest_prefix = completions.LongestCommonPrefix(); + if (!longest_prefix.empty()) + longest_prefix = + longest_prefix.substr(request.GetCursorArgumentPrefix().size()); + if (!longest_prefix.empty()) { + el_insertstr(m_editline, longest_prefix.c_str()); return CC_REDISPLAY; } - if (num_completions > 1) { - int num_elements = num_completions + 1; - fprintf(m_output_file, "\n" ANSI_CLEAR_BELOW "Available completions:"); - if (num_completions < page_size) { - PrintCompletion(m_output_file, 1, num_elements, completions, - descriptions); - fprintf(m_output_file, "\n"); - } else { - int cur_pos = 1; - char reply; - int got_char; - while (cur_pos < num_elements) { - int endpoint = cur_pos + page_size; - if (endpoint > num_elements) - endpoint = num_elements; - - PrintCompletion(m_output_file, cur_pos, endpoint, completions, - descriptions); - cur_pos = endpoint; - - if (cur_pos >= num_elements) { - fprintf(m_output_file, "\n"); - break; - } - - fprintf(m_output_file, "\nMore (Y/n/a): "); - reply = 'n'; - got_char = el_getc(m_editline, &reply); - if (got_char == -1 || reply == 'n') - break; - if (reply == 'a') - page_size = num_elements - cur_pos; - } - } - DisplayInput(); - MoveCursor(CursorLocation::BlockEnd, CursorLocation::EditingCursor); - } + DisplayCompletions(m_editline, m_output_file, results); + + DisplayInput(); + MoveCursor(CursorLocation::BlockEnd, CursorLocation::EditingCursor); return CC_REDISPLAY; } diff --git a/source/Host/common/File.cpp b/source/Host/common/File.cpp index c8c8d7a0d496..9dae24d766f6 100644 --- a/source/Host/common/File.cpp +++ b/source/Host/common/File.cpp @@ -37,8 +37,10 @@ using namespace lldb; using namespace lldb_private; +using llvm::Expected; -static const char *GetStreamOpenModeFromOptions(uint32_t options) { +Expected<const char *> +File::GetStreamOpenModeFromOptions(File::OpenOptions options) { if (options & File::eOpenOptionAppend) { if (options & File::eOpenOptionRead) { if (options & File::eOpenOptionCanCreateNewOnly) @@ -65,15 +67,188 @@ static const char *GetStreamOpenModeFromOptions(uint32_t options) { } else if (options & File::eOpenOptionWrite) { return "w"; } - return nullptr; + return llvm::createStringError( + llvm::inconvertibleErrorCode(), + "invalid options, cannot convert to mode string"); +} + +Expected<File::OpenOptions> File::GetOptionsFromMode(llvm::StringRef mode) { + OpenOptions opts = + llvm::StringSwitch<OpenOptions>(mode) + .Cases("r", "rb", eOpenOptionRead) + .Cases("w", "wb", eOpenOptionWrite) + .Cases("a", "ab", + eOpenOptionWrite | eOpenOptionAppend | eOpenOptionCanCreate) + .Cases("r+", "rb+", "r+b", eOpenOptionRead | eOpenOptionWrite) + .Cases("w+", "wb+", "w+b", + eOpenOptionRead | eOpenOptionWrite | eOpenOptionCanCreate | + eOpenOptionTruncate) + .Cases("a+", "ab+", "a+b", + eOpenOptionRead | eOpenOptionWrite | eOpenOptionAppend | + eOpenOptionCanCreate) + .Default(OpenOptions()); + if (opts) + return opts; + return llvm::createStringError( + llvm::inconvertibleErrorCode(), + "invalid mode, cannot convert to File::OpenOptions"); } int File::kInvalidDescriptor = -1; FILE *File::kInvalidStream = nullptr; -File::~File() { Close(); } +Status File::Read(void *buf, size_t &num_bytes) { + return std::error_code(ENOTSUP, std::system_category()); +} +Status File::Write(const void *buf, size_t &num_bytes) { + return std::error_code(ENOTSUP, std::system_category()); +} + +bool File::IsValid() const { return false; } + +Status File::Close() { return Flush(); } + +IOObject::WaitableHandle File::GetWaitableHandle() { + return IOObject::kInvalidHandleValue; +} -int File::GetDescriptor() const { +Status File::GetFileSpec(FileSpec &file_spec) const { + file_spec.Clear(); + return std::error_code(ENOTSUP, std::system_category()); +} + +int File::GetDescriptor() const { return kInvalidDescriptor; } + +FILE *File::GetStream() { return nullptr; } + +off_t File::SeekFromStart(off_t offset, Status *error_ptr) { + if (error_ptr) + *error_ptr = std::error_code(ENOTSUP, std::system_category()); + return -1; +} + +off_t File::SeekFromCurrent(off_t offset, Status *error_ptr) { + if (error_ptr) + *error_ptr = std::error_code(ENOTSUP, std::system_category()); + return -1; +} + +off_t File::SeekFromEnd(off_t offset, Status *error_ptr) { + if (error_ptr) + *error_ptr = std::error_code(ENOTSUP, std::system_category()); + return -1; +} + +Status File::Read(void *dst, size_t &num_bytes, off_t &offset) { + return std::error_code(ENOTSUP, std::system_category()); +} + +Status File::Write(const void *src, size_t &num_bytes, off_t &offset) { + return std::error_code(ENOTSUP, std::system_category()); +} + +Status File::Flush() { return Status(); } + +Status File::Sync() { return Flush(); } + +void File::CalculateInteractiveAndTerminal() { + const int fd = GetDescriptor(); + if (!DescriptorIsValid(fd)) { + m_is_interactive = eLazyBoolNo; + m_is_real_terminal = eLazyBoolNo; + m_supports_colors = eLazyBoolNo; + return; + } + m_is_interactive = eLazyBoolNo; + m_is_real_terminal = eLazyBoolNo; +#if defined(_WIN32) + if (_isatty(fd)) { + m_is_interactive = eLazyBoolYes; + m_is_real_terminal = eLazyBoolYes; +#if defined(ENABLE_VIRTUAL_TERMINAL_PROCESSING) + m_supports_colors = eLazyBoolYes; +#endif + } +#else + if (isatty(fd)) { + m_is_interactive = eLazyBoolYes; + struct winsize window_size; + if (::ioctl(fd, TIOCGWINSZ, &window_size) == 0) { + if (window_size.ws_col > 0) { + m_is_real_terminal = eLazyBoolYes; + if (llvm::sys::Process::FileDescriptorHasColors(fd)) + m_supports_colors = eLazyBoolYes; + } + } + } +#endif +} + +bool File::GetIsInteractive() { + if (m_is_interactive == eLazyBoolCalculate) + CalculateInteractiveAndTerminal(); + return m_is_interactive == eLazyBoolYes; +} + +bool File::GetIsRealTerminal() { + if (m_is_real_terminal == eLazyBoolCalculate) + CalculateInteractiveAndTerminal(); + return m_is_real_terminal == eLazyBoolYes; +} + +bool File::GetIsTerminalWithColors() { + if (m_supports_colors == eLazyBoolCalculate) + CalculateInteractiveAndTerminal(); + return m_supports_colors == eLazyBoolYes; +} + +size_t File::Printf(const char *format, ...) { + va_list args; + va_start(args, format); + size_t result = PrintfVarArg(format, args); + va_end(args); + return result; +} + +size_t File::PrintfVarArg(const char *format, va_list args) { + size_t result = 0; + char *s = nullptr; + result = vasprintf(&s, format, args); + if (s != nullptr) { + if (result > 0) { + size_t s_len = result; + Write(s, s_len); + result = s_len; + } + free(s); + } + return result; +} + +Expected<File::OpenOptions> File::GetOptions() const { + return llvm::createStringError( + llvm::inconvertibleErrorCode(), + "GetOptions() not implemented for this File class"); +} + +uint32_t File::GetPermissions(Status &error) const { + int fd = GetDescriptor(); + if (!DescriptorIsValid(fd)) { + error = std::error_code(ENOTSUP, std::system_category()); + return 0; + } + struct stat file_stats; + if (::fstat(fd, &file_stats) == -1) { + error.SetErrorToErrno(); + return 0; + } + error.Clear(); + return file_stats.st_mode & (S_IRWXU | S_IRWXG | S_IRWXO); +} + +Expected<File::OpenOptions> NativeFile::GetOptions() const { return m_options; } + +int NativeFile::GetDescriptor() const { if (DescriptorIsValid()) return m_descriptor; @@ -91,21 +266,18 @@ int File::GetDescriptor() const { return kInvalidDescriptor; } -IOObject::WaitableHandle File::GetWaitableHandle() { return m_descriptor; } - -void File::SetDescriptor(int fd, bool transfer_ownership) { - if (IsValid()) - Close(); - m_descriptor = fd; - m_should_close_fd = transfer_ownership; +IOObject::WaitableHandle NativeFile::GetWaitableHandle() { + return GetDescriptor(); } -FILE *File::GetStream() { +FILE *NativeFile::GetStream() { if (!StreamIsValid()) { if (DescriptorIsValid()) { - const char *mode = GetStreamOpenModeFromOptions(m_options); - if (mode) { - if (!m_should_close_fd) { + auto mode = GetStreamOpenModeFromOptions(m_options); + if (!mode) + llvm::consumeError(mode.takeError()); + else { + if (!m_own_descriptor) { // We must duplicate the file descriptor if we don't own it because when you // call fdopen, the stream will own the fd #ifdef _WIN32 @@ -113,18 +285,18 @@ FILE *File::GetStream() { #else m_descriptor = dup(GetDescriptor()); #endif - m_should_close_fd = true; + m_own_descriptor = true; } - m_stream = - llvm::sys::RetryAfterSignal(nullptr, ::fdopen, m_descriptor, mode); + m_stream = llvm::sys::RetryAfterSignal(nullptr, ::fdopen, m_descriptor, + mode.get()); // If we got a stream, then we own the stream and should no longer own // the descriptor because fclose() will close it for us if (m_stream) { m_own_stream = true; - m_should_close_fd = false; + m_own_descriptor = false; } } } @@ -132,60 +304,32 @@ FILE *File::GetStream() { return m_stream; } -void File::SetStream(FILE *fh, bool transfer_ownership) { - if (IsValid()) - Close(); - m_stream = fh; - m_own_stream = transfer_ownership; -} - -uint32_t File::GetPermissions(Status &error) const { - int fd = GetDescriptor(); - if (fd != kInvalidDescriptor) { - struct stat file_stats; - if (::fstat(fd, &file_stats) == -1) - error.SetErrorToErrno(); - else { - error.Clear(); - return file_stats.st_mode & (S_IRWXU | S_IRWXG | S_IRWXO); - } - } else { - error.SetErrorString("invalid file descriptor"); - } - return 0; -} - -Status File::Close() { +Status NativeFile::Close() { Status error; - if (StreamIsValid() && m_own_stream) { - if (::fclose(m_stream) == EOF) - error.SetErrorToErrno(); + if (StreamIsValid()) { + if (m_own_stream) { + if (::fclose(m_stream) == EOF) + error.SetErrorToErrno(); + } else { + if (::fflush(m_stream) == EOF) + error.SetErrorToErrno(); + } } - - if (DescriptorIsValid() && m_should_close_fd) { + if (DescriptorIsValid() && m_own_descriptor) { if (::close(m_descriptor) != 0) error.SetErrorToErrno(); } m_descriptor = kInvalidDescriptor; m_stream = kInvalidStream; - m_options = 0; + m_options = OpenOptions(0); m_own_stream = false; - m_should_close_fd = false; + m_own_descriptor = false; m_is_interactive = eLazyBoolCalculate; m_is_real_terminal = eLazyBoolCalculate; return error; } -void File::Clear() { - m_stream = nullptr; - m_descriptor = kInvalidDescriptor; - m_options = 0; - m_own_stream = false; - m_is_interactive = m_supports_colors = m_is_real_terminal = - eLazyBoolCalculate; -} - -Status File::GetFileSpec(FileSpec &file_spec) const { +Status NativeFile::GetFileSpec(FileSpec &file_spec) const { Status error; #ifdef F_GETPATH if (IsValid()) { @@ -212,7 +356,8 @@ Status File::GetFileSpec(FileSpec &file_spec) const { } } #else - error.SetErrorString("File::GetFileSpec is not supported on this platform"); + error.SetErrorString( + "NativeFile::GetFileSpec is not supported on this platform"); #endif if (error.Fail()) @@ -220,7 +365,7 @@ Status File::GetFileSpec(FileSpec &file_spec) const { return error; } -off_t File::SeekFromStart(off_t offset, Status *error_ptr) { +off_t NativeFile::SeekFromStart(off_t offset, Status *error_ptr) { off_t result = 0; if (DescriptorIsValid()) { result = ::lseek(m_descriptor, offset, SEEK_SET); @@ -246,7 +391,7 @@ off_t File::SeekFromStart(off_t offset, Status *error_ptr) { return result; } -off_t File::SeekFromCurrent(off_t offset, Status *error_ptr) { +off_t NativeFile::SeekFromCurrent(off_t offset, Status *error_ptr) { off_t result = -1; if (DescriptorIsValid()) { result = ::lseek(m_descriptor, offset, SEEK_CUR); @@ -272,7 +417,7 @@ off_t File::SeekFromCurrent(off_t offset, Status *error_ptr) { return result; } -off_t File::SeekFromEnd(off_t offset, Status *error_ptr) { +off_t NativeFile::SeekFromEnd(off_t offset, Status *error_ptr) { off_t result = -1; if (DescriptorIsValid()) { result = ::lseek(m_descriptor, offset, SEEK_END); @@ -298,7 +443,7 @@ off_t File::SeekFromEnd(off_t offset, Status *error_ptr) { return result; } -Status File::Flush() { +Status NativeFile::Flush() { Status error; if (StreamIsValid()) { if (llvm::sys::RetryAfterSignal(EOF, ::fflush, m_stream) == EOF) @@ -309,7 +454,7 @@ Status File::Flush() { return error; } -Status File::Sync() { +Status NativeFile::Sync() { Status error; if (DescriptorIsValid()) { #ifdef _WIN32 @@ -332,7 +477,7 @@ Status File::Sync() { #define MAX_WRITE_SIZE INT_MAX #endif -Status File::Read(void *buf, size_t &num_bytes) { +Status NativeFile::Read(void *buf, size_t &num_bytes) { Status error; #if defined(MAX_READ_SIZE) @@ -391,7 +536,7 @@ Status File::Read(void *buf, size_t &num_bytes) { return error; } -Status File::Write(const void *buf, size_t &num_bytes) { +Status NativeFile::Write(const void *buf, size_t &num_bytes) { Status error; #if defined(MAX_WRITE_SIZE) @@ -453,7 +598,7 @@ Status File::Write(const void *buf, size_t &num_bytes) { return error; } -Status File::Read(void *buf, size_t &num_bytes, off_t &offset) { +Status NativeFile::Read(void *buf, size_t &num_bytes, off_t &offset) { Status error; #if defined(MAX_READ_SIZE) @@ -513,51 +658,7 @@ Status File::Read(void *buf, size_t &num_bytes, off_t &offset) { return error; } -Status File::Read(size_t &num_bytes, off_t &offset, bool null_terminate, - DataBufferSP &data_buffer_sp) { - Status error; - - if (num_bytes > 0) { - int fd = GetDescriptor(); - if (fd != kInvalidDescriptor) { - struct stat file_stats; - if (::fstat(fd, &file_stats) == 0) { - if (file_stats.st_size > offset) { - const size_t bytes_left = file_stats.st_size - offset; - if (num_bytes > bytes_left) - num_bytes = bytes_left; - - size_t num_bytes_plus_nul_char = num_bytes + (null_terminate ? 1 : 0); - std::unique_ptr<DataBufferHeap> data_heap_up; - data_heap_up.reset(new DataBufferHeap()); - data_heap_up->SetByteSize(num_bytes_plus_nul_char); - - if (data_heap_up) { - error = Read(data_heap_up->GetBytes(), num_bytes, offset); - if (error.Success()) { - // Make sure we read exactly what we asked for and if we got - // less, adjust the array - if (num_bytes_plus_nul_char < data_heap_up->GetByteSize()) - data_heap_up->SetByteSize(num_bytes_plus_nul_char); - data_buffer_sp.reset(data_heap_up.release()); - return error; - } - } - } else - error.SetErrorString("file is empty"); - } else - error.SetErrorToErrno(); - } else - error.SetErrorString("invalid file handle"); - } else - error.SetErrorString("invalid file handle"); - - num_bytes = 0; - data_buffer_sp.reset(); - return error; -} - -Status File::Write(const void *buf, size_t &num_bytes, off_t &offset) { +Status NativeFile::Write(const void *buf, size_t &num_bytes, off_t &offset) { Status error; #if defined(MAX_WRITE_SIZE) @@ -621,36 +722,15 @@ Status File::Write(const void *buf, size_t &num_bytes, off_t &offset) { return error; } -// Print some formatted output to the stream. -size_t File::Printf(const char *format, ...) { - va_list args; - va_start(args, format); - size_t result = PrintfVarArg(format, args); - va_end(args); - return result; -} - -// Print some formatted output to the stream. -size_t File::PrintfVarArg(const char *format, va_list args) { - size_t result = 0; - if (DescriptorIsValid()) { - char *s = nullptr; - result = vasprintf(&s, format, args); - if (s != nullptr) { - if (result > 0) { - size_t s_len = result; - Write(s, s_len); - result = s_len; - } - free(s); - } - } else if (StreamIsValid()) { - result = ::vfprintf(m_stream, format, args); +size_t NativeFile::PrintfVarArg(const char *format, va_list args) { + if (StreamIsValid()) { + return ::vfprintf(m_stream, format, args); + } else { + return File::PrintfVarArg(format, args); } - return result; } -mode_t File::ConvertOpenOptionsForPOSIXOpen(uint32_t open_options) { +mode_t File::ConvertOpenOptionsForPOSIXOpen(OpenOptions open_options) { mode_t mode = 0; if (open_options & eOpenOptionRead && open_options & eOpenOptionWrite) mode |= O_RDWR; @@ -674,49 +754,5 @@ mode_t File::ConvertOpenOptionsForPOSIXOpen(uint32_t open_options) { return mode; } -void File::CalculateInteractiveAndTerminal() { - const int fd = GetDescriptor(); - if (fd >= 0) { - m_is_interactive = eLazyBoolNo; - m_is_real_terminal = eLazyBoolNo; -#if defined(_WIN32) - if (_isatty(fd)) { - m_is_interactive = eLazyBoolYes; - m_is_real_terminal = eLazyBoolYes; -#if defined(ENABLE_VIRTUAL_TERMINAL_PROCESSING) - m_supports_colors = eLazyBoolYes; -#endif - } -#else - if (isatty(fd)) { - m_is_interactive = eLazyBoolYes; - struct winsize window_size; - if (::ioctl(fd, TIOCGWINSZ, &window_size) == 0) { - if (window_size.ws_col > 0) { - m_is_real_terminal = eLazyBoolYes; - if (llvm::sys::Process::FileDescriptorHasColors(fd)) - m_supports_colors = eLazyBoolYes; - } - } - } -#endif - } -} - -bool File::GetIsInteractive() { - if (m_is_interactive == eLazyBoolCalculate) - CalculateInteractiveAndTerminal(); - return m_is_interactive == eLazyBoolYes; -} - -bool File::GetIsRealTerminal() { - if (m_is_real_terminal == eLazyBoolCalculate) - CalculateInteractiveAndTerminal(); - return m_is_real_terminal == eLazyBoolYes; -} - -bool File::GetIsTerminalWithColors() { - if (m_supports_colors == eLazyBoolCalculate) - CalculateInteractiveAndTerminal(); - return m_supports_colors == eLazyBoolYes; -} +char File::ID = 0; +char NativeFile::ID = 0; diff --git a/source/Host/common/FileCache.cpp b/source/Host/common/FileCache.cpp index 4bd3efda7fb0..d9dcad992c33 100644 --- a/source/Host/common/FileCache.cpp +++ b/source/Host/common/FileCache.cpp @@ -23,18 +23,20 @@ FileCache &FileCache::GetInstance() { return *m_instance; } -lldb::user_id_t FileCache::OpenFile(const FileSpec &file_spec, uint32_t flags, - uint32_t mode, Status &error) { +lldb::user_id_t FileCache::OpenFile(const FileSpec &file_spec, + File::OpenOptions flags, uint32_t mode, + Status &error) { if (!file_spec) { error.SetErrorString("empty path"); return UINT64_MAX; } - FileSP file_sp(new File()); - error = FileSystem::Instance().Open(*file_sp, file_spec, flags, mode); - if (!file_sp->IsValid()) + auto file = FileSystem::Instance().Open(file_spec, flags, mode); + if (!file) { + error = file.takeError(); return UINT64_MAX; - lldb::user_id_t fd = file_sp->GetDescriptor(); - m_cache[fd] = file_sp; + } + lldb::user_id_t fd = file.get()->GetDescriptor(); + m_cache[fd] = std::move(file.get()); return fd; } @@ -48,12 +50,12 @@ bool FileCache::CloseFile(lldb::user_id_t fd, Status &error) { error.SetErrorStringWithFormat("invalid host file descriptor %" PRIu64, fd); return false; } - FileSP file_sp = pos->second; - if (!file_sp) { + FileUP &file_up = pos->second; + if (!file_up) { error.SetErrorString("invalid host backing file"); return false; } - error = file_sp->Close(); + error = file_up->Close(); m_cache.erase(pos); return error.Success(); } @@ -70,16 +72,16 @@ uint64_t FileCache::WriteFile(lldb::user_id_t fd, uint64_t offset, error.SetErrorStringWithFormat("invalid host file descriptor %" PRIu64, fd); return false; } - FileSP file_sp = pos->second; - if (!file_sp) { + FileUP &file_up = pos->second; + if (!file_up) { error.SetErrorString("invalid host backing file"); return UINT64_MAX; } - if (static_cast<uint64_t>(file_sp->SeekFromStart(offset, &error)) != offset || + if (static_cast<uint64_t>(file_up->SeekFromStart(offset, &error)) != offset || error.Fail()) return UINT64_MAX; size_t bytes_written = src_len; - error = file_sp->Write(src, bytes_written); + error = file_up->Write(src, bytes_written); if (error.Fail()) return UINT64_MAX; return bytes_written; @@ -96,16 +98,16 @@ uint64_t FileCache::ReadFile(lldb::user_id_t fd, uint64_t offset, void *dst, error.SetErrorStringWithFormat("invalid host file descriptor %" PRIu64, fd); return false; } - FileSP file_sp = pos->second; - if (!file_sp) { + FileUP &file_up = pos->second; + if (!file_up) { error.SetErrorString("invalid host backing file"); return UINT64_MAX; } - if (static_cast<uint64_t>(file_sp->SeekFromStart(offset, &error)) != offset || + if (static_cast<uint64_t>(file_up->SeekFromStart(offset, &error)) != offset || error.Fail()) return UINT64_MAX; size_t bytes_read = dst_len; - error = file_sp->Read(dst, bytes_read); + error = file_up->Read(dst, bytes_read); if (error.Fail()) return UINT64_MAX; return bytes_read; diff --git a/source/Host/common/FileSystem.cpp b/source/Host/common/FileSystem.cpp index d5ac05bd447c..2db5bff3207f 100644 --- a/source/Host/common/FileSystem.cpp +++ b/source/Host/common/FileSystem.cpp @@ -49,7 +49,7 @@ void FileSystem::Initialize() { InstanceImpl().emplace(); } -void FileSystem::Initialize(FileCollector &collector) { +void FileSystem::Initialize(std::shared_ptr<FileCollector> collector) { lldbassert(!InstanceImpl() && "Already initialized."); InstanceImpl().emplace(collector); } @@ -280,7 +280,7 @@ std::shared_ptr<DataBufferLLVM> FileSystem::CreateDataBuffer(const llvm::Twine &path, uint64_t size, uint64_t offset) { if (m_collector) - m_collector->AddFile(path); + m_collector->addFile(path); const bool is_volatile = !IsLocal(path); const ErrorOr<std::string> external_path = GetExternalPath(path); @@ -415,13 +415,11 @@ static mode_t GetOpenMode(uint32_t permissions) { return mode; } -Status FileSystem::Open(File &File, const FileSpec &file_spec, uint32_t options, - uint32_t permissions, bool should_close_fd) { +Expected<FileUP> FileSystem::Open(const FileSpec &file_spec, + File::OpenOptions options, + uint32_t permissions, bool should_close_fd) { if (m_collector) - m_collector->AddFile(file_spec); - - if (File.IsValid()) - File.Close(); + m_collector->addFile(file_spec.GetPath()); const int open_flags = GetOpenFlags(options); const mode_t open_mode = @@ -429,20 +427,19 @@ Status FileSystem::Open(File &File, const FileSpec &file_spec, uint32_t options, auto path = GetExternalPath(file_spec); if (!path) - return Status(path.getError()); + return errorCodeToError(path.getError()); int descriptor = llvm::sys::RetryAfterSignal( -1, OpenWithFS, *this, path->c_str(), open_flags, open_mode); - Status error; - if (!File::DescriptorIsValid(descriptor)) { - File.SetDescriptor(descriptor, false); - error.SetErrorToErrno(); - } else { - File.SetDescriptor(descriptor, should_close_fd); - File.SetOptions(options); - } - return error; + if (!File::DescriptorIsValid(descriptor)) + return llvm::errorCodeToError( + std::error_code(errno, std::system_category())); + + auto file = std::unique_ptr<File>( + new NativeFile(descriptor, options, should_close_fd)); + assert(file->IsValid()); + return std::move(file); } ErrorOr<std::string> FileSystem::GetExternalPath(const llvm::Twine &path) { diff --git a/source/Host/common/Host.cpp b/source/Host/common/Host.cpp index 3ba9ab7f21f3..8e210c7e5fa5 100644 --- a/source/Host/common/Host.cpp +++ b/source/Host/common/Host.cpp @@ -164,8 +164,7 @@ static bool CheckForMonitorCancellation() { static thread_result_t MonitorChildProcessThreadFunction(void *arg) { Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_PROCESS)); const char *function = __FUNCTION__; - if (log) - log->Printf("%s (arg = %p) thread starting...", function, arg); + LLDB_LOGF(log, "%s (arg = %p) thread starting...", function, arg); MonitorInfo *info = (MonitorInfo *)arg; @@ -193,9 +192,8 @@ static thread_result_t MonitorChildProcessThreadFunction(void *arg) { while (1) { log = lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_PROCESS); - if (log) - log->Printf("%s ::waitpid (pid = %" PRIi32 ", &status, options = %i)...", - function, pid, options); + LLDB_LOGF(log, "%s ::waitpid (pid = %" PRIi32 ", &status, options = %i)...", + function, pid, options); if (CheckForMonitorCancellation()) break; @@ -245,12 +243,12 @@ static thread_result_t MonitorChildProcessThreadFunction(void *arg) { #endif log = lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_PROCESS); - if (log) - log->Printf("%s ::waitpid (pid = %" PRIi32 - ", &status, options = %i) => pid = %" PRIi32 - ", status = 0x%8.8x (%s), signal = %i, exit_state = %i", - function, pid, options, wait_pid, status, status_cstr, - signal, exit_status); + LLDB_LOGF(log, + "%s ::waitpid (pid = %" PRIi32 + ", &status, options = %i) => pid = %" PRIi32 + ", status = 0x%8.8x (%s), signal = %i, exit_state = %i", + function, pid, options, wait_pid, status, status_cstr, signal, + exit_status); if (exited || (signal != 0 && monitor_signals)) { bool callback_return = false; @@ -259,18 +257,18 @@ static thread_result_t MonitorChildProcessThreadFunction(void *arg) { // If our process exited, then this thread should exit if (exited && wait_pid == abs(pid)) { - if (log) - log->Printf("%s (arg = %p) thread exiting because pid received " - "exit signal...", - __FUNCTION__, arg); + LLDB_LOGF(log, + "%s (arg = %p) thread exiting because pid received " + "exit signal...", + __FUNCTION__, arg); break; } // If the callback returns true, it means this process should exit if (callback_return) { - if (log) - log->Printf("%s (arg = %p) thread exiting because callback " - "returned true...", - __FUNCTION__, arg); + LLDB_LOGF(log, + "%s (arg = %p) thread exiting because callback " + "returned true...", + __FUNCTION__, arg); break; } } @@ -279,8 +277,7 @@ static thread_result_t MonitorChildProcessThreadFunction(void *arg) { } log = lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_PROCESS); - if (log) - log->Printf("%s (arg = %p) thread exiting...", __FUNCTION__, arg); + LLDB_LOGF(log, "%s (arg = %p) thread exiting...", __FUNCTION__, arg); return nullptr; } diff --git a/source/Host/common/HostInfoBase.cpp b/source/Host/common/HostInfoBase.cpp index 130f0eb8ac8d..3765f36fc79a 100644 --- a/source/Host/common/HostInfoBase.cpp +++ b/source/Host/common/HostInfoBase.cpp @@ -221,25 +221,24 @@ bool HostInfoBase::ComputePathRelativeToLibrary(FileSpec &file_spec, return false; std::string raw_path = lldb_file_spec.GetPath(); - if (log) - log->Printf("HostInfo::%s() attempting to " - "derive the path %s relative to liblldb install path: %s", - __FUNCTION__, dir.data(), raw_path.c_str()); + LLDB_LOGF(log, + "HostInfo::%s() attempting to " + "derive the path %s relative to liblldb install path: %s", + __FUNCTION__, dir.data(), raw_path.c_str()); // Drop bin (windows) or lib llvm::StringRef parent_path = llvm::sys::path::parent_path(raw_path); if (parent_path.empty()) { - if (log) - log->Printf("HostInfo::%s() failed to find liblldb within the shared " - "lib path", - __FUNCTION__); + LLDB_LOGF(log, + "HostInfo::%s() failed to find liblldb within the shared " + "lib path", + __FUNCTION__); return false; } raw_path = (parent_path + dir).str(); - if (log) - log->Printf("HostInfo::%s() derived the path as: %s", __FUNCTION__, - raw_path.c_str()); + LLDB_LOGF(log, "HostInfo::%s() derived the path as: %s", __FUNCTION__, + raw_path.c_str()); file_spec.GetDirectory().SetString(raw_path); return (bool)file_spec.GetDirectory(); } diff --git a/source/Host/common/HostNativeThreadBase.cpp b/source/Host/common/HostNativeThreadBase.cpp index a5f876a7232a..fe7d85acaf11 100644 --- a/source/Host/common/HostNativeThreadBase.cpp +++ b/source/Host/common/HostNativeThreadBase.cpp @@ -62,8 +62,7 @@ HostNativeThreadBase::ThreadCreateTrampoline(lldb::thread_arg_t arg) { thread_arg_t thread_arg = info->thread_arg; Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_THREAD)); - if (log) - log->Printf("thread created"); + LLDB_LOGF(log, "thread created"); delete info; return thread_fptr(thread_arg); diff --git a/source/Host/common/LZMA.cpp b/source/Host/common/LZMA.cpp new file mode 100644 index 000000000000..02be8a09df66 --- /dev/null +++ b/source/Host/common/LZMA.cpp @@ -0,0 +1,146 @@ +//===-- LZMA.cpp ------------------------------------------------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#include "lldb/Host/Config.h" +#include "llvm/ADT/StringRef.h" +#include "llvm/Support/Error.h" + +#if LLDB_ENABLE_LZMA +#include <lzma.h> +#endif // LLDB_ENABLE_LZMA + +namespace lldb_private { + +namespace lzma { + +#if !LLDB_ENABLE_LZMA +bool isAvailable() { return false; } +llvm::Expected<uint64_t> +getUncompressedSize(llvm::ArrayRef<uint8_t> InputBuffer) { + llvm_unreachable("lzma::getUncompressedSize is unavailable"); +} + +llvm::Error uncompress(llvm::ArrayRef<uint8_t> InputBuffer, + llvm::SmallVectorImpl<uint8_t> &Uncompressed) { + llvm_unreachable("lzma::uncompress is unavailable"); +} + +#else // LLDB_ENABLE_LZMA + +bool isAvailable() { return true; } + +static const char *convertLZMACodeToString(lzma_ret Code) { + switch (Code) { + case LZMA_STREAM_END: + return "lzma error: LZMA_STREAM_END"; + case LZMA_NO_CHECK: + return "lzma error: LZMA_NO_CHECK"; + case LZMA_UNSUPPORTED_CHECK: + return "lzma error: LZMA_UNSUPPORTED_CHECK"; + case LZMA_GET_CHECK: + return "lzma error: LZMA_GET_CHECK"; + case LZMA_MEM_ERROR: + return "lzma error: LZMA_MEM_ERROR"; + case LZMA_MEMLIMIT_ERROR: + return "lzma error: LZMA_MEMLIMIT_ERROR"; + case LZMA_FORMAT_ERROR: + return "lzma error: LZMA_FORMAT_ERROR"; + case LZMA_OPTIONS_ERROR: + return "lzma error: LZMA_OPTIONS_ERROR"; + case LZMA_DATA_ERROR: + return "lzma error: LZMA_DATA_ERROR"; + case LZMA_BUF_ERROR: + return "lzma error: LZMA_BUF_ERROR"; + case LZMA_PROG_ERROR: + return "lzma error: LZMA_PROG_ERROR"; + default: + llvm_unreachable("unknown or unexpected lzma status code"); + } +} + +llvm::Expected<uint64_t> +getUncompressedSize(llvm::ArrayRef<uint8_t> InputBuffer) { + lzma_stream_flags opts{}; + if (InputBuffer.size() < LZMA_STREAM_HEADER_SIZE) { + return llvm::createStringError( + llvm::inconvertibleErrorCode(), + "size of xz-compressed blob (%lu bytes) is smaller than the " + "LZMA_STREAM_HEADER_SIZE (%lu bytes)", + InputBuffer.size(), LZMA_STREAM_HEADER_SIZE); + } + + // Decode xz footer. + lzma_ret xzerr = lzma_stream_footer_decode( + &opts, InputBuffer.take_back(LZMA_STREAM_HEADER_SIZE).data()); + if (xzerr != LZMA_OK) { + return llvm::createStringError(llvm::inconvertibleErrorCode(), + "lzma_stream_footer_decode()=%s", + convertLZMACodeToString(xzerr)); + } + if (InputBuffer.size() < (opts.backward_size + LZMA_STREAM_HEADER_SIZE)) { + return llvm::createStringError( + llvm::inconvertibleErrorCode(), + "xz-compressed buffer size (%lu bytes) too small (required at " + "least %lu bytes) ", + InputBuffer.size(), (opts.backward_size + LZMA_STREAM_HEADER_SIZE)); + } + + // Decode xz index. + lzma_index *xzindex; + uint64_t memlimit(UINT64_MAX); + size_t inpos = 0; + xzerr = lzma_index_buffer_decode( + &xzindex, &memlimit, nullptr, + InputBuffer.take_back(LZMA_STREAM_HEADER_SIZE + opts.backward_size) + .data(), + &inpos, InputBuffer.size()); + if (xzerr != LZMA_OK) { + return llvm::createStringError(llvm::inconvertibleErrorCode(), + "lzma_index_buffer_decode()=%s", + convertLZMACodeToString(xzerr)); + } + + // Get size of uncompressed file to construct an in-memory buffer of the + // same size on the calling end (if needed). + uint64_t uncompressedSize = lzma_index_uncompressed_size(xzindex); + + // Deallocate xz index as it is no longer needed. + lzma_index_end(xzindex, nullptr); + + return uncompressedSize; +} + +llvm::Error uncompress(llvm::ArrayRef<uint8_t> InputBuffer, + llvm::SmallVectorImpl<uint8_t> &Uncompressed) { + llvm::Expected<uint64_t> uncompressedSize = getUncompressedSize(InputBuffer); + + if (auto err = uncompressedSize.takeError()) + return err; + + Uncompressed.resize(*uncompressedSize); + + // Decompress xz buffer to buffer. + uint64_t memlimit = UINT64_MAX; + size_t inpos = 0; + size_t outpos = 0; + lzma_ret ret = lzma_stream_buffer_decode( + &memlimit, 0, nullptr, InputBuffer.data(), &inpos, InputBuffer.size(), + Uncompressed.data(), &outpos, Uncompressed.size()); + if (ret != LZMA_OK) { + return llvm::createStringError(llvm::inconvertibleErrorCode(), + "lzma_stream_buffer_decode()=%s", + convertLZMACodeToString(ret)); + } + + return llvm::Error::success(); +} + +#endif // LLDB_ENABLE_LZMA + +} // end of namespace lzma +} // namespace lldb_private diff --git a/source/Host/common/MainLoop.cpp b/source/Host/common/MainLoop.cpp index 1ce09a84671c..6f774451c8a4 100644 --- a/source/Host/common/MainLoop.cpp +++ b/source/Host/common/MainLoop.cpp @@ -320,6 +320,7 @@ MainLoop::RegisterSignal(int signo, const Callback &callback, Status &error) { // Even if using kqueue, the signal handler will still be invoked, so it's // important to replace it with our "benign" handler. int ret = sigaction(signo, &new_action, &info.old_action); + (void)ret; assert(ret == 0 && "sigaction failed"); #if HAVE_SYS_EVENT_H diff --git a/source/Host/common/NativeProcessProtocol.cpp b/source/Host/common/NativeProcessProtocol.cpp index 90272cb8d0bc..fd349cc2915b 100644 --- a/source/Host/common/NativeProcessProtocol.cpp +++ b/source/Host/common/NativeProcessProtocol.cpp @@ -16,6 +16,8 @@ #include "lldb/Utility/State.h" #include "lldb/lldb-enumerations.h" +#include "llvm/Support/Process.h" + using namespace lldb; using namespace lldb_private; @@ -329,22 +331,23 @@ void NativeProcessProtocol::SynchronouslyNotifyProcessStateChanged( if (log) { if (!m_delegates.empty()) { - log->Printf("NativeProcessProtocol::%s: sent state notification [%s] " - "from process %" PRIu64, - __FUNCTION__, lldb_private::StateAsCString(state), GetID()); + LLDB_LOGF(log, + "NativeProcessProtocol::%s: sent state notification [%s] " + "from process %" PRIu64, + __FUNCTION__, lldb_private::StateAsCString(state), GetID()); } else { - log->Printf("NativeProcessProtocol::%s: would send state notification " - "[%s] from process %" PRIu64 ", but no delegates", - __FUNCTION__, lldb_private::StateAsCString(state), GetID()); + LLDB_LOGF(log, + "NativeProcessProtocol::%s: would send state notification " + "[%s] from process %" PRIu64 ", but no delegates", + __FUNCTION__, lldb_private::StateAsCString(state), GetID()); } } } void NativeProcessProtocol::NotifyDidExec() { Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_PROCESS)); - if (log) - log->Printf("NativeProcessProtocol::%s - preparing to call delegates", - __FUNCTION__); + LLDB_LOGF(log, "NativeProcessProtocol::%s - preparing to call delegates", + __FUNCTION__); { std::lock_guard<std::recursive_mutex> guard(m_delegates_mutex); @@ -524,6 +527,7 @@ NativeProcessProtocol::GetSoftwareBreakpointTrapOpcode(size_t size_hint) { switch (GetArchitecture().GetMachine()) { case llvm::Triple::aarch64: + case llvm::Triple::aarch64_32: return llvm::makeArrayRef(g_aarch64_opcode); case llvm::Triple::x86: @@ -560,6 +564,7 @@ size_t NativeProcessProtocol::GetSoftwareBreakpointPCOffset() { case llvm::Triple::arm: case llvm::Triple::aarch64: + case llvm::Triple::aarch64_32: case llvm::Triple::mips64: case llvm::Triple::mips64el: case llvm::Triple::mips: @@ -659,6 +664,58 @@ Status NativeProcessProtocol::ReadMemoryWithoutTrap(lldb::addr_t addr, return Status(); } +llvm::Expected<llvm::StringRef> +NativeProcessProtocol::ReadCStringFromMemory(lldb::addr_t addr, char *buffer, + size_t max_size, + size_t &total_bytes_read) { + static const size_t cache_line_size = + llvm::sys::Process::getPageSizeEstimate(); + size_t bytes_read = 0; + size_t bytes_left = max_size; + addr_t curr_addr = addr; + size_t string_size; + char *curr_buffer = buffer; + total_bytes_read = 0; + Status status; + + while (bytes_left > 0 && status.Success()) { + addr_t cache_line_bytes_left = + cache_line_size - (curr_addr % cache_line_size); + addr_t bytes_to_read = std::min<addr_t>(bytes_left, cache_line_bytes_left); + status = ReadMemory(curr_addr, reinterpret_cast<void *>(curr_buffer), + bytes_to_read, bytes_read); + + if (bytes_read == 0) + break; + + void *str_end = std::memchr(curr_buffer, '\0', bytes_read); + if (str_end != nullptr) { + total_bytes_read = + (size_t)(reinterpret_cast<char *>(str_end) - buffer + 1); + status.Clear(); + break; + } + + total_bytes_read += bytes_read; + curr_buffer += bytes_read; + curr_addr += bytes_read; + bytes_left -= bytes_read; + } + + string_size = total_bytes_read - 1; + + // Make sure we return a null terminated string. + if (bytes_left == 0 && max_size > 0 && buffer[max_size - 1] != '\0') { + buffer[max_size - 1] = '\0'; + total_bytes_read--; + } + + if (!status.Success()) + return status.ToError(); + + return llvm::StringRef(buffer, string_size); +} + lldb::StateType NativeProcessProtocol::GetState() const { std::lock_guard<std::recursive_mutex> guard(m_state_mutex); return m_state; diff --git a/source/Host/common/NativeRegisterContext.cpp b/source/Host/common/NativeRegisterContext.cpp index 2f30d52aea63..fe40073eb59d 100644 --- a/source/Host/common/NativeRegisterContext.cpp +++ b/source/Host/common/NativeRegisterContext.cpp @@ -114,16 +114,15 @@ lldb::addr_t NativeRegisterContext::GetPC(lldb::addr_t fail_value) { uint32_t reg = ConvertRegisterKindToRegisterNumber(eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC); - if (log) - log->Printf("NativeRegisterContext::%s using reg index %" PRIu32 - " (default %" PRIu64 ")", - __FUNCTION__, reg, fail_value); + LLDB_LOGF(log, + "NativeRegisterContext::%s using reg index %" PRIu32 + " (default %" PRIu64 ")", + __FUNCTION__, reg, fail_value); const uint64_t retval = ReadRegisterAsUnsigned(reg, fail_value); - if (log) - log->Printf("NativeRegisterContext::%s " PRIu32 " retval %" PRIu64, - __FUNCTION__, retval); + LLDB_LOGF(log, "NativeRegisterContext::%s " PRIu32 " retval %" PRIu64, + __FUNCTION__, retval); return retval; } @@ -192,20 +191,19 @@ NativeRegisterContext::ReadRegisterAsUnsigned(const RegisterInfo *reg_info, RegisterValue value; Status error = ReadRegister(reg_info, value); if (error.Success()) { - if (log) - log->Printf("NativeRegisterContext::%s ReadRegister() succeeded, value " - "%" PRIu64, - __FUNCTION__, value.GetAsUInt64()); + LLDB_LOGF(log, + "NativeRegisterContext::%s ReadRegister() succeeded, value " + "%" PRIu64, + __FUNCTION__, value.GetAsUInt64()); return value.GetAsUInt64(); } else { - if (log) - log->Printf("NativeRegisterContext::%s ReadRegister() failed, error %s", - __FUNCTION__, error.AsCString()); + LLDB_LOGF(log, + "NativeRegisterContext::%s ReadRegister() failed, error %s", + __FUNCTION__, error.AsCString()); } } else { - if (log) - log->Printf("NativeRegisterContext::%s ReadRegister() null reg_info", - __FUNCTION__); + LLDB_LOGF(log, "NativeRegisterContext::%s ReadRegister() null reg_info", + __FUNCTION__); } return fail_value; } diff --git a/source/Host/common/Socket.cpp b/source/Host/common/Socket.cpp index a89f1178e96c..6358ab8a8e77 100644 --- a/source/Host/common/Socket.cpp +++ b/source/Host/common/Socket.cpp @@ -74,9 +74,10 @@ bool IsInterrupted() { Socket::Socket(SocketProtocol protocol, bool should_close, bool child_processes_inherit) - : IOObject(eFDTypeSocket, should_close), m_protocol(protocol), + : IOObject(eFDTypeSocket), m_protocol(protocol), m_socket(kInvalidSocketValue), - m_child_processes_inherit(child_processes_inherit) {} + m_child_processes_inherit(child_processes_inherit), + m_should_close_fd(should_close) {} Socket::~Socket() { Close(); } @@ -114,16 +115,16 @@ std::unique_ptr<Socket> Socket::Create(const SocketProtocol protocol, switch (protocol) { case ProtocolTcp: socket_up = - llvm::make_unique<TCPSocket>(true, child_processes_inherit); + std::make_unique<TCPSocket>(true, child_processes_inherit); break; case ProtocolUdp: socket_up = - llvm::make_unique<UDPSocket>(true, child_processes_inherit); + std::make_unique<UDPSocket>(true, child_processes_inherit); break; case ProtocolUnixDomain: #ifndef LLDB_DISABLE_POSIX socket_up = - llvm::make_unique<DomainSocket>(true, child_processes_inherit); + std::make_unique<DomainSocket>(true, child_processes_inherit); #else error.SetErrorString( "Unix domain sockets are not supported on this platform."); @@ -132,7 +133,7 @@ std::unique_ptr<Socket> Socket::Create(const SocketProtocol protocol, case ProtocolUnixAbstract: #ifdef __linux__ socket_up = - llvm::make_unique<AbstractSocket>(child_processes_inherit); + std::make_unique<AbstractSocket>(child_processes_inherit); #else error.SetErrorString( "Abstract domain sockets are not supported on this platform."); @@ -149,9 +150,8 @@ std::unique_ptr<Socket> Socket::Create(const SocketProtocol protocol, Status Socket::TcpConnect(llvm::StringRef host_and_port, bool child_processes_inherit, Socket *&socket) { Log *log(lldb_private::GetLogIfAnyCategoriesSet(LIBLLDB_LOG_COMMUNICATION)); - if (log) - log->Printf("Socket::%s (host/port = %s)", __FUNCTION__, - host_and_port.str().c_str()); + LLDB_LOGF(log, "Socket::%s (host/port = %s)", __FUNCTION__, + host_and_port.str().c_str()); Status error; std::unique_ptr<Socket> connect_socket( @@ -170,8 +170,7 @@ Status Socket::TcpListen(llvm::StringRef host_and_port, bool child_processes_inherit, Socket *&socket, Predicate<uint16_t> *predicate, int backlog) { Log *log(lldb_private::GetLogIfAnyCategoriesSet(LIBLLDB_LOG_CONNECTION)); - if (log) - log->Printf("Socket::%s (%s)", __FUNCTION__, host_and_port.str().c_str()); + LLDB_LOGF(log, "Socket::%s (%s)", __FUNCTION__, host_and_port.str().c_str()); Status error; std::string host_str; @@ -209,9 +208,8 @@ Status Socket::TcpListen(llvm::StringRef host_and_port, Status Socket::UdpConnect(llvm::StringRef host_and_port, bool child_processes_inherit, Socket *&socket) { Log *log(lldb_private::GetLogIfAnyCategoriesSet(LIBLLDB_LOG_CONNECTION)); - if (log) - log->Printf("Socket::%s (host/port = %s)", __FUNCTION__, - host_and_port.str().c_str()); + LLDB_LOGF(log, "Socket::%s (host/port = %s)", __FUNCTION__, + host_and_port.str().c_str()); return UDPSocket::Connect(host_and_port, child_processes_inherit, socket); } @@ -285,27 +283,25 @@ bool Socket::DecodeHostAndPort(llvm::StringRef host_and_port, int32_t &port, Status *error_ptr) { static RegularExpression g_regex( llvm::StringRef("([^:]+|\\[[0-9a-fA-F:]+.*\\]):([0-9]+)")); - RegularExpression::Match regex_match(2); - if (g_regex.Execute(host_and_port, ®ex_match)) { - if (regex_match.GetMatchAtIndex(host_and_port, 1, host_str) && - regex_match.GetMatchAtIndex(host_and_port, 2, port_str)) { - // IPv6 addresses are wrapped in [] when specified with ports - if (host_str.front() == '[' && host_str.back() == ']') - host_str = host_str.substr(1, host_str.size() - 2); - bool ok = false; - port = StringConvert::ToUInt32(port_str.c_str(), UINT32_MAX, 10, &ok); - if (ok && port <= UINT16_MAX) { - if (error_ptr) - error_ptr->Clear(); - return true; - } - // port is too large + llvm::SmallVector<llvm::StringRef, 3> matches; + if (g_regex.Execute(host_and_port, &matches)) { + host_str = matches[1].str(); + port_str = matches[2].str(); + // IPv6 addresses are wrapped in [] when specified with ports + if (host_str.front() == '[' && host_str.back() == ']') + host_str = host_str.substr(1, host_str.size() - 2); + bool ok = false; + port = StringConvert::ToUInt32(port_str.c_str(), UINT32_MAX, 10, &ok); + if (ok && port <= UINT16_MAX) { if (error_ptr) - error_ptr->SetErrorStringWithFormat( - "invalid host:port specification: '%s'", - host_and_port.str().c_str()); - return false; + error_ptr->Clear(); + return true; } + // port is too large + if (error_ptr) + error_ptr->SetErrorStringWithFormat( + "invalid host:port specification: '%s'", host_and_port.str().c_str()); + return false; } // If this was unsuccessful, then check if it's simply a signed 32-bit @@ -345,18 +341,20 @@ Status Socket::Read(void *buf, size_t &num_bytes) { Log *log(lldb_private::GetLogIfAnyCategoriesSet(LIBLLDB_LOG_COMMUNICATION)); if (log) { - log->Printf("%p Socket::Read() (socket = %" PRIu64 - ", src = %p, src_len = %" PRIu64 ", flags = 0) => %" PRIi64 - " (error = %s)", - static_cast<void *>(this), static_cast<uint64_t>(m_socket), buf, - static_cast<uint64_t>(num_bytes), - static_cast<int64_t>(bytes_received), error.AsCString()); + LLDB_LOGF(log, + "%p Socket::Read() (socket = %" PRIu64 + ", src = %p, src_len = %" PRIu64 ", flags = 0) => %" PRIi64 + " (error = %s)", + static_cast<void *>(this), static_cast<uint64_t>(m_socket), buf, + static_cast<uint64_t>(num_bytes), + static_cast<int64_t>(bytes_received), error.AsCString()); } return error; } Status Socket::Write(const void *buf, size_t &num_bytes) { + const size_t src_len = num_bytes; Status error; int bytes_sent = 0; do { @@ -371,12 +369,13 @@ Status Socket::Write(const void *buf, size_t &num_bytes) { Log *log(lldb_private::GetLogIfAnyCategoriesSet(LIBLLDB_LOG_COMMUNICATION)); if (log) { - log->Printf("%p Socket::Write() (socket = %" PRIu64 - ", src = %p, src_len = %" PRIu64 ", flags = 0) => %" PRIi64 - " (error = %s)", - static_cast<void *>(this), static_cast<uint64_t>(m_socket), buf, - static_cast<uint64_t>(num_bytes), - static_cast<int64_t>(bytes_sent), error.AsCString()); + LLDB_LOGF(log, + "%p Socket::Write() (socket = %" PRIu64 + ", src = %p, src_len = %" PRIu64 ", flags = 0) => %" PRIi64 + " (error = %s)", + static_cast<void *>(this), static_cast<uint64_t>(m_socket), buf, + static_cast<uint64_t>(src_len), + static_cast<int64_t>(bytes_sent), error.AsCString()); } return error; @@ -393,9 +392,8 @@ Status Socket::Close() { return error; Log *log(lldb_private::GetLogIfAnyCategoriesSet(LIBLLDB_LOG_CONNECTION)); - if (log) - log->Printf("%p Socket::Close (fd = %" PRIu64 ")", - static_cast<void *>(this), static_cast<uint64_t>(m_socket)); + LLDB_LOGF(log, "%p Socket::Close (fd = %" PRIu64 ")", + static_cast<void *>(this), static_cast<uint64_t>(m_socket)); #if defined(_WIN32) bool success = !!closesocket(m_socket); @@ -479,11 +477,11 @@ NativeSocket Socket::AcceptSocket(NativeSocket sockfd, struct sockaddr *addr, if (!child_processes_inherit) { flags |= SOCK_CLOEXEC; } - NativeSocket fd = llvm::sys::RetryAfterSignal(-1, ::accept4, - sockfd, addr, addrlen, flags); + NativeSocket fd = llvm::sys::RetryAfterSignal( + static_cast<NativeSocket>(-1), ::accept4, sockfd, addr, addrlen, flags); #else - NativeSocket fd = llvm::sys::RetryAfterSignal(-1, ::accept, - sockfd, addr, addrlen); + NativeSocket fd = llvm::sys::RetryAfterSignal( + static_cast<NativeSocket>(-1), ::accept, sockfd, addr, addrlen); #endif if (fd == kInvalidSocketValue) SetLastError(error); diff --git a/source/Host/common/TCPSocket.cpp b/source/Host/common/TCPSocket.cpp index 58f99f7832fe..e84054f3f581 100644 --- a/source/Host/common/TCPSocket.cpp +++ b/source/Host/common/TCPSocket.cpp @@ -140,8 +140,7 @@ Status TCPSocket::CreateSocket(int domain) { Status TCPSocket::Connect(llvm::StringRef name) { Log *log(lldb_private::GetLogIfAnyCategoriesSet(LIBLLDB_LOG_COMMUNICATION)); - if (log) - log->Printf("TCPSocket::%s (host/port = %s)", __FUNCTION__, name.data()); + LLDB_LOGF(log, "TCPSocket::%s (host/port = %s)", __FUNCTION__, name.data()); Status error; std::string host_str; @@ -177,8 +176,7 @@ Status TCPSocket::Connect(llvm::StringRef name) { Status TCPSocket::Listen(llvm::StringRef name, int backlog) { Log *log(lldb_private::GetLogIfAnyCategoriesSet(LIBLLDB_LOG_CONNECTION)); - if (log) - log->Printf("TCPSocket::%s (%s)", __FUNCTION__, name.data()); + LLDB_LOGF(log, "TCPSocket::%s (%s)", __FUNCTION__, name.data()); Status error; std::string host_str; diff --git a/source/Host/common/UDPSocket.cpp b/source/Host/common/UDPSocket.cpp index 8dbf57d6fe4e..7accbb651ba9 100644 --- a/source/Host/common/UDPSocket.cpp +++ b/source/Host/common/UDPSocket.cpp @@ -58,8 +58,7 @@ Status UDPSocket::Connect(llvm::StringRef name, bool child_processes_inherit, std::unique_ptr<UDPSocket> final_socket; Log *log(lldb_private::GetLogIfAnyCategoriesSet(LIBLLDB_LOG_CONNECTION)); - if (log) - log->Printf("UDPSocket::%s (host/port = %s)", __FUNCTION__, name.data()); + LLDB_LOGF(log, "UDPSocket::%s (host/port = %s)", __FUNCTION__, name.data()); Status error; std::string host_str; @@ -81,7 +80,7 @@ Status UDPSocket::Connect(llvm::StringRef name, bool child_processes_inherit, &service_info_list); if (err != 0) { error.SetErrorStringWithFormat( -#if defined(_MSC_VER) && defined(UNICODE) +#if defined(_WIN32) && defined(UNICODE) "getaddrinfo(%s, %s, &hints, &info) returned error %i (%S)", #else "getaddrinfo(%s, %s, &hints, &info) returned error %i (%s)", diff --git a/source/Host/freebsd/HostInfoFreeBSD.cpp b/source/Host/freebsd/HostInfoFreeBSD.cpp index e28cf4aa420f..7fc6f43d4676 100644 --- a/source/Host/freebsd/HostInfoFreeBSD.cpp +++ b/source/Host/freebsd/HostInfoFreeBSD.cpp @@ -64,13 +64,10 @@ FileSpec HostInfoFreeBSD::GetProgramFileSpec() { static FileSpec g_program_filespec; if (!g_program_filespec) { int exe_path_mib[4] = {CTL_KERN, KERN_PROC, KERN_PROC_PATHNAME, getpid()}; - size_t exe_path_size; - if (sysctl(exe_path_mib, 4, NULL, &exe_path_size, NULL, 0) == 0) { - char *exe_path = new char[exe_path_size]; - if (sysctl(exe_path_mib, 4, exe_path, &exe_path_size, NULL, 0) == 0) - g_program_filespec.SetFile(exe_path, FileSpec::Style::native); - delete[] exe_path; - } + char exe_path[PATH_MAX]; + size_t exe_path_size = sizeof(exe_path); + if (sysctl(exe_path_mib, 4, exe_path, &exe_path_size, NULL, 0) == 0) + g_program_filespec.SetFile(exe_path, FileSpec::Style::native); } return g_program_filespec; } diff --git a/source/Host/posix/ConnectionFileDescriptorPosix.cpp b/source/Host/posix/ConnectionFileDescriptorPosix.cpp index 067e85972eca..325d854921e3 100644 --- a/source/Host/posix/ConnectionFileDescriptorPosix.cpp +++ b/source/Host/posix/ConnectionFileDescriptorPosix.cpp @@ -79,23 +79,22 @@ ConnectionFileDescriptor::ConnectionFileDescriptor(bool child_processes_inherit) m_child_processes_inherit(child_processes_inherit) { Log *log(lldb_private::GetLogIfAnyCategoriesSet(LIBLLDB_LOG_CONNECTION | LIBLLDB_LOG_OBJECT)); - if (log) - log->Printf("%p ConnectionFileDescriptor::ConnectionFileDescriptor ()", - static_cast<void *>(this)); + LLDB_LOGF(log, "%p ConnectionFileDescriptor::ConnectionFileDescriptor ()", + static_cast<void *>(this)); } ConnectionFileDescriptor::ConnectionFileDescriptor(int fd, bool owns_fd) : Connection(), m_pipe(), m_mutex(), m_shutting_down(false), m_waiting_for_accept(false), m_child_processes_inherit(false) { - m_write_sp = std::make_shared<File>(fd, owns_fd); - m_read_sp = std::make_shared<File>(fd, false); + m_write_sp = std::make_shared<NativeFile>(fd, File::eOpenOptionWrite, owns_fd); + m_read_sp = std::make_shared<NativeFile>(fd, File::eOpenOptionRead, false); Log *log(lldb_private::GetLogIfAnyCategoriesSet(LIBLLDB_LOG_CONNECTION | LIBLLDB_LOG_OBJECT)); - if (log) - log->Printf("%p ConnectionFileDescriptor::ConnectionFileDescriptor (fd = " - "%i, owns_fd = %i)", - static_cast<void *>(this), fd, owns_fd); + LLDB_LOGF(log, + "%p ConnectionFileDescriptor::ConnectionFileDescriptor (fd = " + "%i, owns_fd = %i)", + static_cast<void *>(this), fd, owns_fd); OpenCommandPipe(); } @@ -108,9 +107,8 @@ ConnectionFileDescriptor::ConnectionFileDescriptor(Socket *socket) ConnectionFileDescriptor::~ConnectionFileDescriptor() { Log *log(lldb_private::GetLogIfAnyCategoriesSet(LIBLLDB_LOG_CONNECTION | LIBLLDB_LOG_OBJECT)); - if (log) - log->Printf("%p ConnectionFileDescriptor::~ConnectionFileDescriptor ()", - static_cast<void *>(this)); + LLDB_LOGF(log, "%p ConnectionFileDescriptor::~ConnectionFileDescriptor ()", + static_cast<void *>(this)); Disconnect(nullptr); CloseCommandPipe(); } @@ -122,24 +120,23 @@ void ConnectionFileDescriptor::OpenCommandPipe() { // Make the command file descriptor here: Status result = m_pipe.CreateNew(m_child_processes_inherit); if (!result.Success()) { - if (log) - log->Printf("%p ConnectionFileDescriptor::OpenCommandPipe () - could not " - "make pipe: %s", - static_cast<void *>(this), result.AsCString()); + LLDB_LOGF(log, + "%p ConnectionFileDescriptor::OpenCommandPipe () - could not " + "make pipe: %s", + static_cast<void *>(this), result.AsCString()); } else { - if (log) - log->Printf("%p ConnectionFileDescriptor::OpenCommandPipe() - success " - "readfd=%d writefd=%d", - static_cast<void *>(this), m_pipe.GetReadFileDescriptor(), - m_pipe.GetWriteFileDescriptor()); + LLDB_LOGF(log, + "%p ConnectionFileDescriptor::OpenCommandPipe() - success " + "readfd=%d writefd=%d", + static_cast<void *>(this), m_pipe.GetReadFileDescriptor(), + m_pipe.GetWriteFileDescriptor()); } } void ConnectionFileDescriptor::CloseCommandPipe() { Log *log(lldb_private::GetLogIfAnyCategoriesSet(LIBLLDB_LOG_CONNECTION)); - if (log) - log->Printf("%p ConnectionFileDescriptor::CloseCommandPipe()", - static_cast<void *>(this)); + LLDB_LOGF(log, "%p ConnectionFileDescriptor::CloseCommandPipe()", + static_cast<void *>(this)); m_pipe.Close(); } @@ -153,9 +150,8 @@ ConnectionStatus ConnectionFileDescriptor::Connect(llvm::StringRef path, Status *error_ptr) { std::lock_guard<std::recursive_mutex> guard(m_mutex); Log *log(lldb_private::GetLogIfAnyCategoriesSet(LIBLLDB_LOG_CONNECTION)); - if (log) - log->Printf("%p ConnectionFileDescriptor::Connect (url = '%s')", - static_cast<void *>(this), path.str().c_str()); + LLDB_LOGF(log, "%p ConnectionFileDescriptor::Connect (url = '%s')", + static_cast<void *>(this), path.str().c_str()); OpenCommandPipe(); @@ -222,8 +218,10 @@ ConnectionStatus ConnectionFileDescriptor::Connect(llvm::StringRef path, m_read_sp = std::move(tcp_socket); m_write_sp = m_read_sp; } else { - m_read_sp = std::make_shared<File>(fd, false); - m_write_sp = std::make_shared<File>(fd, false); + m_read_sp = + std::make_shared<NativeFile>(fd, File::eOpenOptionRead, false); + m_write_sp = + std::make_shared<NativeFile>(fd, File::eOpenOptionWrite, false); } m_uri = *addr; return eConnectionStatusSuccess; @@ -272,8 +270,8 @@ ConnectionStatus ConnectionFileDescriptor::Connect(llvm::StringRef path, ::fcntl(fd, F_SETFL, flags); } } - m_read_sp = std::make_shared<File>(fd, true); - m_write_sp = std::make_shared<File>(fd, false); + m_read_sp = std::make_shared<NativeFile>(fd, File::eOpenOptionRead, true); + m_write_sp = std::make_shared<NativeFile>(fd, File::eOpenOptionWrite, false); return eConnectionStatusSuccess; } #endif @@ -295,17 +293,15 @@ bool ConnectionFileDescriptor::InterruptRead() { ConnectionStatus ConnectionFileDescriptor::Disconnect(Status *error_ptr) { Log *log(lldb_private::GetLogIfAnyCategoriesSet(LIBLLDB_LOG_CONNECTION)); - if (log) - log->Printf("%p ConnectionFileDescriptor::Disconnect ()", - static_cast<void *>(this)); + LLDB_LOGF(log, "%p ConnectionFileDescriptor::Disconnect ()", + static_cast<void *>(this)); ConnectionStatus status = eConnectionStatusSuccess; if (!IsConnected()) { - if (log) - log->Printf( - "%p ConnectionFileDescriptor::Disconnect(): Nothing to disconnect", - static_cast<void *>(this)); + LLDB_LOGF( + log, "%p ConnectionFileDescriptor::Disconnect(): Nothing to disconnect", + static_cast<void *>(this)); return eConnectionStatusSuccess; } @@ -318,27 +314,28 @@ ConnectionStatus ConnectionFileDescriptor::Disconnect(Status *error_ptr) { // descriptor. If that's the case, then send the "q" char to the command // file channel so the read will wake up and the connection will then know to // shut down. - - m_shutting_down = true; - std::unique_lock<std::recursive_mutex> locker(m_mutex, std::defer_lock); if (!locker.try_lock()) { if (m_pipe.CanWrite()) { size_t bytes_written = 0; Status result = m_pipe.Write("q", 1, bytes_written); - if (log) - log->Printf("%p ConnectionFileDescriptor::Disconnect(): Couldn't get " - "the lock, sent 'q' to %d, error = '%s'.", - static_cast<void *>(this), m_pipe.GetWriteFileDescriptor(), - result.AsCString()); + LLDB_LOGF(log, + "%p ConnectionFileDescriptor::Disconnect(): Couldn't get " + "the lock, sent 'q' to %d, error = '%s'.", + static_cast<void *>(this), m_pipe.GetWriteFileDescriptor(), + result.AsCString()); } else if (log) { - log->Printf("%p ConnectionFileDescriptor::Disconnect(): Couldn't get the " - "lock, but no command pipe is available.", - static_cast<void *>(this)); + LLDB_LOGF(log, + "%p ConnectionFileDescriptor::Disconnect(): Couldn't get the " + "lock, but no command pipe is available.", + static_cast<void *>(this)); } locker.lock(); } + // Prevents reads and writes during shutdown. + m_shutting_down = true; + Status error = m_read_sp->Close(); Status error2 = m_write_sp->Close(); if (error.Fail() || error2.Fail()) @@ -362,10 +359,10 @@ size_t ConnectionFileDescriptor::Read(void *dst, size_t dst_len, std::unique_lock<std::recursive_mutex> locker(m_mutex, std::defer_lock); if (!locker.try_lock()) { - if (log) - log->Printf("%p ConnectionFileDescriptor::Read () failed to get the " - "connection lock.", - static_cast<void *>(this)); + LLDB_LOGF(log, + "%p ConnectionFileDescriptor::Read () failed to get the " + "connection lock.", + static_cast<void *>(this)); if (error_ptr) error_ptr->SetErrorString("failed to get the connection lock for read."); @@ -374,6 +371,8 @@ size_t ConnectionFileDescriptor::Read(void *dst, size_t dst_len, } if (m_shutting_down) { + if (error_ptr) + error_ptr->SetErrorString("shutting down"); status = eConnectionStatusError; return 0; } @@ -387,12 +386,13 @@ size_t ConnectionFileDescriptor::Read(void *dst, size_t dst_len, error = m_read_sp->Read(dst, bytes_read); if (log) { - log->Printf("%p ConnectionFileDescriptor::Read() fd = %" PRIu64 - ", dst = %p, dst_len = %" PRIu64 ") => %" PRIu64 ", error = %s", - static_cast<void *>(this), - static_cast<uint64_t>(m_read_sp->GetWaitableHandle()), - static_cast<void *>(dst), static_cast<uint64_t>(dst_len), - static_cast<uint64_t>(bytes_read), error.AsCString()); + LLDB_LOGF(log, + "%p ConnectionFileDescriptor::Read() fd = %" PRIu64 + ", dst = %p, dst_len = %" PRIu64 ") => %" PRIu64 ", error = %s", + static_cast<void *>(this), + static_cast<uint64_t>(m_read_sp->GetWaitableHandle()), + static_cast<void *>(dst), static_cast<uint64_t>(dst_len), + static_cast<uint64_t>(bytes_read), error.AsCString()); } if (bytes_read == 0) { @@ -464,11 +464,11 @@ size_t ConnectionFileDescriptor::Write(const void *src, size_t src_len, ConnectionStatus &status, Status *error_ptr) { Log *log(lldb_private::GetLogIfAnyCategoriesSet(LIBLLDB_LOG_CONNECTION)); - if (log) - log->Printf( - "%p ConnectionFileDescriptor::Write (src = %p, src_len = %" PRIu64 ")", - static_cast<void *>(this), static_cast<const void *>(src), - static_cast<uint64_t>(src_len)); + LLDB_LOGF(log, + "%p ConnectionFileDescriptor::Write (src = %p, src_len = %" PRIu64 + ")", + static_cast<void *>(this), static_cast<const void *>(src), + static_cast<uint64_t>(src_len)); if (!IsConnected()) { if (error_ptr) @@ -477,19 +477,26 @@ size_t ConnectionFileDescriptor::Write(const void *src, size_t src_len, return 0; } + if (m_shutting_down) { + if (error_ptr) + error_ptr->SetErrorString("shutting down"); + status = eConnectionStatusError; + return 0; + } + Status error; size_t bytes_sent = src_len; error = m_write_sp->Write(src, bytes_sent); if (log) { - log->Printf("%p ConnectionFileDescriptor::Write(fd = %" PRIu64 - ", src = %p, src_len = %" PRIu64 ") => %" PRIu64 - " (error = %s)", - static_cast<void *>(this), - static_cast<uint64_t>(m_write_sp->GetWaitableHandle()), - static_cast<const void *>(src), static_cast<uint64_t>(src_len), - static_cast<uint64_t>(bytes_sent), error.AsCString()); + LLDB_LOGF(log, + "%p ConnectionFileDescriptor::Write(fd = %" PRIu64 + ", src = %p, src_len = %" PRIu64 ") => %" PRIu64 " (error = %s)", + static_cast<void *>(this), + static_cast<uint64_t>(m_write_sp->GetWaitableHandle()), + static_cast<const void *>(src), static_cast<uint64_t>(src_len), + static_cast<uint64_t>(bytes_sent), error.AsCString()); } if (error_ptr) @@ -559,7 +566,7 @@ ConnectionFileDescriptor::BytesAvailable(const Timeout<std::micro> &timeout, select_helper.SetTimeout(*timeout); select_helper.FDSetRead(handle); -#if defined(_MSC_VER) +#if defined(_WIN32) // select() won't accept pipes on Windows. The entire Windows codepath // needs to be converted over to using WaitForMultipleObjects and event // HANDLEs, but for now at least this will allow ::select() to not return @@ -613,10 +620,10 @@ ConnectionFileDescriptor::BytesAvailable(const Timeout<std::micro> &timeout, (void)bytes_read; switch (c) { case 'q': - if (log) - log->Printf("%p ConnectionFileDescriptor::BytesAvailable() " - "got data: %c from the command channel.", - static_cast<void *>(this), c); + LLDB_LOGF(log, + "%p ConnectionFileDescriptor::BytesAvailable() " + "got data: %c from the command channel.", + static_cast<void *>(this), c); return eConnectionStatusEndOfFile; case 'i': // Interrupt the current read diff --git a/source/Host/posix/HostInfoPosix.cpp b/source/Host/posix/HostInfoPosix.cpp index f300e22e9e5c..63cc5dc65e00 100644 --- a/source/Host/posix/HostInfoPosix.cpp +++ b/source/Host/posix/HostInfoPosix.cpp @@ -7,8 +7,8 @@ //===----------------------------------------------------------------------===// #include "lldb/Host/posix/HostInfoPosix.h" -#include "lldb/Utility/UserIDResolver.h" #include "lldb/Utility/Log.h" +#include "lldb/Utility/UserIDResolver.h" #include "llvm/ADT/SmallString.h" #include "llvm/ADT/Twine.h" @@ -18,7 +18,6 @@ #include <grp.h> #include <limits.h> #include <mutex> -#include <netdb.h> #include <pwd.h> #include <stdlib.h> #include <sys/types.h> @@ -32,11 +31,7 @@ bool HostInfoPosix::GetHostname(std::string &s) { char hostname[PATH_MAX]; hostname[sizeof(hostname) - 1] = '\0'; if (::gethostname(hostname, sizeof(hostname) - 1) == 0) { - struct hostent *h = ::gethostbyname(hostname); - if (h) - s.assign(h->h_name); - else - s.assign(hostname); + s.assign(hostname); return true; } return false; @@ -57,15 +52,19 @@ protected: }; } // namespace -llvm::Optional<std::string> PosixUserIDResolver::DoGetUserName(id_t uid) { +struct PasswdEntry { + std::string username; + std::string shell; +}; + +static llvm::Optional<PasswdEntry> GetPassword(id_t uid) { #ifdef USE_GETPWUID // getpwuid_r is missing from android-9 - // UserIDResolver provides some thread safety by making sure noone calls this - // function concurrently, but using getpwuid is ultimately not thread-safe as - // we don't know who else might be calling it. - struct passwd *user_info_ptr = ::getpwuid(uid); - if (user_info_ptr) - return std::string(user_info_ptr->pw_name); + // The caller should provide some thread safety by making sure no one calls + // this function concurrently, because using getpwuid is ultimately not + // thread-safe as we don't know who else might be calling it. + if (auto *user_info_ptr = ::getpwuid(uid)) + return PasswdEntry{user_info_ptr->pw_name, user_info_ptr->pw_shell}; #else struct passwd user_info; struct passwd *user_info_ptr = &user_info; @@ -74,12 +73,18 @@ llvm::Optional<std::string> PosixUserIDResolver::DoGetUserName(id_t uid) { if (::getpwuid_r(uid, &user_info, user_buffer, user_buffer_size, &user_info_ptr) == 0 && user_info_ptr) { - return std::string(user_info_ptr->pw_name); + return PasswdEntry{user_info_ptr->pw_name, user_info_ptr->pw_shell}; } #endif return llvm::None; } +llvm::Optional<std::string> PosixUserIDResolver::DoGetUserName(id_t uid) { + if (llvm::Optional<PasswdEntry> password = GetPassword(uid)) + return password->username; + return llvm::None; +} + llvm::Optional<std::string> PosixUserIDResolver::DoGetGroupName(id_t gid) { #ifndef __ANDROID__ char group_buffer[PATH_MAX]; @@ -98,8 +103,6 @@ llvm::Optional<std::string> PosixUserIDResolver::DoGetGroupName(id_t gid) { if (group_info_ptr) return std::string(group_info_ptr->gr_name); } -#else - assert(false && "getgrgid_r() not supported on Android"); #endif return llvm::None; } @@ -118,7 +121,13 @@ uint32_t HostInfoPosix::GetEffectiveUserID() { return geteuid(); } uint32_t HostInfoPosix::GetEffectiveGroupID() { return getegid(); } -FileSpec HostInfoPosix::GetDefaultShell() { return FileSpec("/bin/sh"); } +FileSpec HostInfoPosix::GetDefaultShell() { + if (const char *v = ::getenv("SHELL")) + return FileSpec(v); + if (llvm::Optional<PasswdEntry> password = GetPassword(::geteuid())) + return FileSpec(password->shell); + return FileSpec("/bin/sh"); +} bool HostInfoPosix::ComputeSupportExeDirectory(FileSpec &file_spec) { return ComputePathRelativeToLibrary(file_spec, "/bin"); diff --git a/source/Initialization/SystemInitializerCommon.cpp b/source/Initialization/SystemInitializerCommon.cpp index 8558911c2f4c..7ae8ef5d4d66 100644 --- a/source/Initialization/SystemInitializerCommon.cpp +++ b/source/Initialization/SystemInitializerCommon.cpp @@ -25,6 +25,7 @@ #if defined(_WIN32) #include "Plugins/Process/Windows/Common/ProcessWindowsLog.h" #include "lldb/Host/windows/windows.h" +#include <crtdbg.h> #endif #include "llvm/Support/TargetSelect.h" @@ -77,6 +78,17 @@ llvm::Error SystemInitializerCommon::Initialize() { } else { FileSystem::Initialize(); } + if (llvm::Expected<std::string> cwd = + loader->LoadBuffer<WorkingDirectoryProvider>()) { + llvm::StringRef working_dir = llvm::StringRef(*cwd).rtrim(); + if (std::error_code ec = FileSystem::Instance() + .GetVirtualFileSystem() + ->setCurrentWorkingDirectory(working_dir)) { + return llvm::errorCodeToError(ec); + } + } else { + return cwd.takeError(); + } } else if (repro::Generator *g = r.GetGenerator()) { repro::VersionProvider &vp = g->GetOrCreate<repro::VersionProvider>(); vp.SetVersion(lldb_private::GetVersion()); diff --git a/source/Interpreter/CommandAlias.cpp b/source/Interpreter/CommandAlias.cpp index 8c40574ee50e..5139c53a47b3 100644 --- a/source/Interpreter/CommandAlias.cpp +++ b/source/Interpreter/CommandAlias.cpp @@ -64,8 +64,8 @@ static bool ProcessAliasOptionsArgs(lldb::CommandObjectSP &cmd_obj_sp, option_arg_vector->emplace_back("<argument>", -1, options_string); else { for (auto &entry : args.entries()) { - if (!entry.ref.empty()) - option_arg_vector->emplace_back("<argument>", -1, entry.ref); + if (!entry.ref().empty()) + option_arg_vector->emplace_back("<argument>", -1, entry.ref()); } } } @@ -115,18 +115,16 @@ bool CommandAlias::WantsCompletion() { return false; } -int CommandAlias::HandleCompletion(CompletionRequest &request) { +void CommandAlias::HandleCompletion(CompletionRequest &request) { if (IsValid()) - return m_underlying_command_sp->HandleCompletion(request); - return -1; + m_underlying_command_sp->HandleCompletion(request); } -int CommandAlias::HandleArgumentCompletion( +void CommandAlias::HandleArgumentCompletion( CompletionRequest &request, OptionElementVector &opt_element_vector) { if (IsValid()) - return m_underlying_command_sp->HandleArgumentCompletion( - request, opt_element_vector); - return -1; + m_underlying_command_sp->HandleArgumentCompletion(request, + opt_element_vector); } Options *CommandAlias::GetOptions() { diff --git a/source/Interpreter/CommandInterpreter.cpp b/source/Interpreter/CommandInterpreter.cpp index 8948037a6307..0c059096c6cd 100644 --- a/source/Interpreter/CommandInterpreter.cpp +++ b/source/Interpreter/CommandInterpreter.cpp @@ -16,7 +16,6 @@ #include "Commands/CommandObjectApropos.h" #include "Commands/CommandObjectBreakpoint.h" -#include "Commands/CommandObjectBugreport.h" #include "Commands/CommandObjectCommands.h" #include "Commands/CommandObjectDisassemble.h" #include "Commands/CommandObjectExpression.h" @@ -64,11 +63,14 @@ #include "lldb/Utility/Args.h" #include "lldb/Target/Process.h" +#include "lldb/Target/StopInfo.h" #include "lldb/Target/TargetList.h" #include "lldb/Target/Thread.h" +#include "lldb/Target/UnixSignals.h" #include "llvm/ADT/STLExtras.h" #include "llvm/ADT/SmallString.h" +#include "llvm/Support/FormatAdapters.h" #include "llvm/Support/Path.h" #include "llvm/Support/PrettyStackTrace.h" @@ -77,10 +79,6 @@ using namespace lldb_private; static const char *k_white_space = " \t\v"; -static constexpr bool NoGlobalSetting = true; -static constexpr uintptr_t DefaultValueTrue = true; -static constexpr uintptr_t DefaultValueFalse = false; -static constexpr const char *NoCStrDefault = nullptr; static constexpr const char *InitFileWarning = "There is a .lldbinit file in the current directory which is not being " "read.\n" @@ -93,38 +91,12 @@ static constexpr const char *InitFileWarning = "and\n" "accept the security risk."; -static constexpr PropertyDefinition g_properties[] = { - {"expand-regex-aliases", OptionValue::eTypeBoolean, NoGlobalSetting, - DefaultValueFalse, NoCStrDefault, {}, - "If true, regular expression alias commands will show the " - "expanded command that will be executed. This can be used to " - "debug new regular expression alias commands."}, - {"prompt-on-quit", OptionValue::eTypeBoolean, NoGlobalSetting, - DefaultValueTrue, NoCStrDefault, {}, - "If true, LLDB will prompt you before quitting if there are any live " - "processes being debugged. If false, LLDB will quit without asking in any " - "case."}, - {"stop-command-source-on-error", OptionValue::eTypeBoolean, NoGlobalSetting, - DefaultValueTrue, NoCStrDefault, {}, - "If true, LLDB will stop running a 'command source' " - "script upon encountering an error."}, - {"space-repl-prompts", OptionValue::eTypeBoolean, NoGlobalSetting, - DefaultValueFalse, NoCStrDefault, {}, - "If true, blank lines will be printed between between REPL submissions."}, - {"echo-commands", OptionValue::eTypeBoolean, NoGlobalSetting, - DefaultValueTrue, NoCStrDefault, {}, - "If true, commands will be echoed before they are evaluated."}, - {"echo-comment-commands", OptionValue::eTypeBoolean, NoGlobalSetting, - DefaultValueTrue, NoCStrDefault, {}, - "If true, commands will be echoed even if they are pure comment lines."}}; +#define LLDB_PROPERTIES_interpreter +#include "InterpreterProperties.inc" enum { - ePropertyExpandRegexAliases = 0, - ePropertyPromptOnQuit = 1, - ePropertyStopCmdSourceOnError = 2, - eSpaceReplPrompts = 3, - eEchoCommands = 4, - eEchoCommentCommands = 5 +#define LLDB_PROPERTIES_interpreter +#include "InterpreterPropertiesEnum.inc" }; ConstString &CommandInterpreter::GetStaticBroadcasterClass() { @@ -139,7 +111,7 @@ CommandInterpreter::CommandInterpreter(Debugger &debugger, Properties(OptionValuePropertiesSP( new OptionValueProperties(ConstString("interpreter")))), IOHandlerDelegate(IOHandlerDelegate::Completion::LLDBCommand), - m_debugger(debugger), m_synchronous_execution(synchronous_execution), + m_debugger(debugger), m_synchronous_execution(true), m_skip_lldbinit_files(false), m_skip_app_init_files(false), m_command_io_handler_sp(), m_comment_char('#'), m_batch_command_mode(false), m_truncation_warning(eNoTruncation), @@ -148,20 +120,21 @@ CommandInterpreter::CommandInterpreter(Debugger &debugger, SetEventName(eBroadcastBitThreadShouldExit, "thread-should-exit"); SetEventName(eBroadcastBitResetPrompt, "reset-prompt"); SetEventName(eBroadcastBitQuitCommandReceived, "quit"); + SetSynchronous(synchronous_execution); CheckInWithManager(); - m_collection_sp->Initialize(g_properties); + m_collection_sp->Initialize(g_interpreter_properties); } bool CommandInterpreter::GetExpandRegexAliases() const { const uint32_t idx = ePropertyExpandRegexAliases; return m_collection_sp->GetPropertyAtIndexAsBoolean( - nullptr, idx, g_properties[idx].default_uint_value != 0); + nullptr, idx, g_interpreter_properties[idx].default_uint_value != 0); } bool CommandInterpreter::GetPromptOnQuit() const { const uint32_t idx = ePropertyPromptOnQuit; return m_collection_sp->GetPropertyAtIndexAsBoolean( - nullptr, idx, g_properties[idx].default_uint_value != 0); + nullptr, idx, g_interpreter_properties[idx].default_uint_value != 0); } void CommandInterpreter::SetPromptOnQuit(bool b) { @@ -170,24 +143,24 @@ void CommandInterpreter::SetPromptOnQuit(bool b) { } bool CommandInterpreter::GetEchoCommands() const { - const uint32_t idx = eEchoCommands; + const uint32_t idx = ePropertyEchoCommands; return m_collection_sp->GetPropertyAtIndexAsBoolean( - nullptr, idx, g_properties[idx].default_uint_value != 0); + nullptr, idx, g_interpreter_properties[idx].default_uint_value != 0); } void CommandInterpreter::SetEchoCommands(bool b) { - const uint32_t idx = eEchoCommands; + const uint32_t idx = ePropertyEchoCommands; m_collection_sp->SetPropertyAtIndexAsBoolean(nullptr, idx, b); } bool CommandInterpreter::GetEchoCommentCommands() const { - const uint32_t idx = eEchoCommentCommands; + const uint32_t idx = ePropertyEchoCommentCommands; return m_collection_sp->GetPropertyAtIndexAsBoolean( - nullptr, idx, g_properties[idx].default_uint_value != 0); + nullptr, idx, g_interpreter_properties[idx].default_uint_value != 0); } void CommandInterpreter::SetEchoCommentCommands(bool b) { - const uint32_t idx = eEchoCommentCommands; + const uint32_t idx = ePropertyEchoCommentCommands; m_collection_sp->SetPropertyAtIndexAsBoolean(nullptr, idx, b); } @@ -223,13 +196,13 @@ void CommandInterpreter::ResolveCommand(const char *command_line, bool CommandInterpreter::GetStopCmdSourceOnError() const { const uint32_t idx = ePropertyStopCmdSourceOnError; return m_collection_sp->GetPropertyAtIndexAsBoolean( - nullptr, idx, g_properties[idx].default_uint_value != 0); + nullptr, idx, g_interpreter_properties[idx].default_uint_value != 0); } bool CommandInterpreter::GetSpaceReplPrompts() const { - const uint32_t idx = eSpaceReplPrompts; + const uint32_t idx = ePropertySpaceReplPrompts; return m_collection_sp->GetPropertyAtIndexAsBoolean( - nullptr, idx, g_properties[idx].default_uint_value != 0); + nullptr, idx, g_interpreter_properties[idx].default_uint_value != 0); } void CommandInterpreter::Initialize() { @@ -473,8 +446,6 @@ void CommandInterpreter::LoadCommandDictionary() { m_command_dict["apropos"] = CommandObjectSP(new CommandObjectApropos(*this)); m_command_dict["breakpoint"] = CommandObjectSP(new CommandObjectMultiwordBreakpoint(*this)); - m_command_dict["bugreport"] = - CommandObjectSP(new CommandObjectMultiwordBugreport(*this)); m_command_dict["command"] = CommandObjectSP(new CommandObjectMultiwordCommands(*this)); m_command_dict["disassemble"] = @@ -1628,8 +1599,7 @@ bool CommandInterpreter::HandleCommand(const char *command_line, llvm::PrettyStackTraceFormat stack_trace("HandleCommand(command = \"%s\")", command_line); - if (log) - log->Printf("Processing command: %s", command_line); + LLDB_LOGF(log, "Processing command: %s", command_line); static Timer::Category func_cat(LLVM_PRETTY_FUNCTION); Timer scoped_timer(func_cat, "Handling command: %s.", command_line); @@ -1735,13 +1705,13 @@ bool CommandInterpreter::HandleCommand(const char *command_line, // "br s -n main", command_string is now "breakpoint set -n main". if (log) { llvm::StringRef command_name = cmd_obj ? cmd_obj->GetCommandName() : "<not found>"; - log->Printf("HandleCommand, cmd_obj : '%s'", command_name.str().c_str()); - log->Printf("HandleCommand, (revised) command_string: '%s'", - command_string.c_str()); + LLDB_LOGF(log, "HandleCommand, cmd_obj : '%s'", command_name.str().c_str()); + LLDB_LOGF(log, "HandleCommand, (revised) command_string: '%s'", + command_string.c_str()); const bool wants_raw_input = (cmd_obj != nullptr) ? cmd_obj->WantsRawCommandString() : false; - log->Printf("HandleCommand, wants_raw_input:'%s'", - wants_raw_input ? "True" : "False"); + LLDB_LOGF(log, "HandleCommand, wants_raw_input:'%s'", + wants_raw_input ? "True" : "False"); } // Phase 2. @@ -1771,34 +1741,30 @@ bool CommandInterpreter::HandleCommand(const char *command_line, if (pos != 0 && pos != std::string::npos) remainder.erase(0, pos); - if (log) - log->Printf( - "HandleCommand, command line after removing command name(s): '%s'", - remainder.c_str()); + LLDB_LOGF( + log, "HandleCommand, command line after removing command name(s): '%s'", + remainder.c_str()); cmd_obj->Execute(remainder.c_str(), result); } - if (log) - log->Printf("HandleCommand, command %s", - (result.Succeeded() ? "succeeded" : "did not succeed")); + LLDB_LOGF(log, "HandleCommand, command %s", + (result.Succeeded() ? "succeeded" : "did not succeed")); return result.Succeeded(); } -int CommandInterpreter::HandleCompletionMatches(CompletionRequest &request) { - int num_command_matches = 0; +void CommandInterpreter::HandleCompletionMatches(CompletionRequest &request) { bool look_for_subcommand = false; // For any of the command completions a unique match will be a complete word. - request.SetWordComplete(true); - if (request.GetCursorIndex() == -1) { + if (request.GetParsedLine().GetArgumentCount() == 0) { // We got nothing on the command line, so return the list of commands bool include_aliases = true; StringList new_matches, descriptions; - num_command_matches = GetCommandNamesMatchingPartialString( - "", include_aliases, new_matches, descriptions); + GetCommandNamesMatchingPartialString("", include_aliases, new_matches, + descriptions); request.AddCompletions(new_matches, descriptions); } else if (request.GetCursorIndex() == 0) { // The cursor is in the first argument, so just do a lookup in the @@ -1808,24 +1774,18 @@ int CommandInterpreter::HandleCompletionMatches(CompletionRequest &request) { GetCommandObject(request.GetParsedLine().GetArgumentAtIndex(0), &new_matches, &new_descriptions); - if (num_command_matches == 1 && cmd_obj && cmd_obj->IsMultiwordObject() && + if (new_matches.GetSize() && cmd_obj && cmd_obj->IsMultiwordObject() && new_matches.GetStringAtIndex(0) != nullptr && strcmp(request.GetParsedLine().GetArgumentAtIndex(0), new_matches.GetStringAtIndex(0)) == 0) { - if (request.GetParsedLine().GetArgumentCount() == 1) { - request.SetWordComplete(true); - } else { + if (request.GetParsedLine().GetArgumentCount() != 1) { look_for_subcommand = true; - num_command_matches = 0; new_matches.DeleteStringAtIndex(0); new_descriptions.DeleteStringAtIndex(0); - request.GetParsedLine().AppendArgument(llvm::StringRef()); - request.SetCursorIndex(request.GetCursorIndex() + 1); - request.SetCursorCharPosition(0); + request.AppendEmptyArgument(); } } request.AddCompletions(new_matches, new_descriptions); - num_command_matches = request.GetNumberOfMatches(); } if (request.GetCursorIndex() > 0 || look_for_subcommand) { @@ -1834,81 +1794,31 @@ int CommandInterpreter::HandleCompletionMatches(CompletionRequest &request) { // matching initial command: CommandObject *command_object = GetCommandObject(request.GetParsedLine().GetArgumentAtIndex(0)); - if (command_object == nullptr) { - return 0; - } else { - request.GetParsedLine().Shift(); - request.SetCursorIndex(request.GetCursorIndex() - 1); - num_command_matches = command_object->HandleCompletion(request); + if (command_object) { + request.ShiftArguments(); + command_object->HandleCompletion(request); } } - - return num_command_matches; } -int CommandInterpreter::HandleCompletion( - const char *current_line, const char *cursor, const char *last_char, - int match_start_point, int max_return_elements, StringList &matches, - StringList &descriptions) { +void CommandInterpreter::HandleCompletion(CompletionRequest &request) { - llvm::StringRef command_line(current_line, last_char - current_line); - CompletionResult result; - CompletionRequest request(command_line, cursor - current_line, - match_start_point, max_return_elements, result); // Don't complete comments, and if the line we are completing is just the // history repeat character, substitute the appropriate history line. - const char *first_arg = request.GetParsedLine().GetArgumentAtIndex(0); - if (first_arg) { - if (first_arg[0] == m_comment_char) - return 0; - else if (first_arg[0] == CommandHistory::g_repeat_char) { - if (auto hist_str = m_command_history.FindString(first_arg)) { - matches.InsertStringAtIndex(0, *hist_str); - descriptions.InsertStringAtIndex(0, "Previous command history event"); - return -2; - } else - return 0; - } - } - - // Only max_return_elements == -1 is supported at present: - lldbassert(max_return_elements == -1); - - int num_command_matches = HandleCompletionMatches(request); - result.GetMatches(matches); - result.GetDescriptions(descriptions); + llvm::StringRef first_arg = request.GetParsedLine().GetArgumentAtIndex(0); - if (num_command_matches <= 0) - return num_command_matches; - - if (request.GetParsedLine().GetArgumentCount() == 0) { - // If we got an empty string, insert nothing. - matches.InsertStringAtIndex(0, ""); - descriptions.InsertStringAtIndex(0, ""); - } else { - // Now figure out if there is a common substring, and if so put that in - // element 0, otherwise put an empty string in element 0. - std::string command_partial_str = request.GetCursorArgumentPrefix().str(); - - std::string common_prefix; - matches.LongestCommonPrefix(common_prefix); - const size_t partial_name_len = command_partial_str.size(); - common_prefix.erase(0, partial_name_len); - - // If we matched a unique single command, add a space... Only do this if - // the completer told us this was a complete word, however... - if (num_command_matches == 1 && request.GetWordComplete()) { - char quote_char = request.GetParsedLine()[request.GetCursorIndex()].quote; - common_prefix = - Args::EscapeLLDBCommandArgument(common_prefix, quote_char); - if (quote_char != '\0') - common_prefix.push_back(quote_char); - common_prefix.push_back(' '); + if (!first_arg.empty()) { + if (first_arg.front() == m_comment_char) + return; + if (first_arg.front() == CommandHistory::g_repeat_char) { + if (auto hist_str = m_command_history.FindString(first_arg)) + request.AddCompletion(*hist_str, "Previous command history event", + CompletionMode::RewriteLine); + return; } - matches.InsertStringAtIndex(0, common_prefix.c_str()); - descriptions.InsertStringAtIndex(0, ""); } - return num_command_matches; + + HandleCompletionMatches(request); } CommandInterpreter::~CommandInterpreter() {} @@ -2051,7 +1961,7 @@ void CommandInterpreter::BuildAliasCommandArgs(CommandObject *alias_cmd_obj, for (auto entry : llvm::enumerate(cmd_args.entries())) { if (!used[entry.index()] && !wants_raw_input) - new_args.AppendArgument(entry.value().ref); + new_args.AppendArgument(entry.value().ref()); } cmd_args.Clear(); @@ -2231,6 +2141,45 @@ PlatformSP CommandInterpreter::GetPlatform(bool prefer_target_platform) { return platform_sp; } +bool CommandInterpreter::DidProcessStopAbnormally() const { + TargetSP target_sp = m_debugger.GetTargetList().GetSelectedTarget(); + if (!target_sp) + return false; + + ProcessSP process_sp(target_sp->GetProcessSP()); + if (!process_sp) + return false; + + if (eStateStopped != process_sp->GetState()) + return false; + + for (const auto &thread_sp : process_sp->GetThreadList().Threads()) { + StopInfoSP stop_info = thread_sp->GetStopInfo(); + if (!stop_info) + return false; + + const StopReason reason = stop_info->GetStopReason(); + if (reason == eStopReasonException || reason == eStopReasonInstrumentation) + return true; + + if (reason == eStopReasonSignal) { + const auto stop_signal = static_cast<int32_t>(stop_info->GetValue()); + UnixSignalsSP signals_sp = process_sp->GetUnixSignals(); + if (!signals_sp || !signals_sp->SignalIsValid(stop_signal)) + // The signal is unknown, treat it as abnormal. + return true; + + const auto sigint_num = signals_sp->GetSignalNumberFromName("SIGINT"); + const auto sigstop_num = signals_sp->GetSignalNumberFromName("SIGSTOP"); + if ((stop_signal != sigint_num) && (stop_signal != sigstop_num)) + // The signal very likely implies a crash. + return true; + } + } + + return false; +} + void CommandInterpreter::HandleCommands(const StringList &commands, ExecutionContext *override_context, CommandInterpreterRunOptions &options, @@ -2341,38 +2290,22 @@ void CommandInterpreter::HandleCommands(const StringList &commands, } // Also check for "stop on crash here: - bool should_stop = false; - if (tmp_result.GetDidChangeProcessState() && options.GetStopOnCrash()) { - TargetSP target_sp(m_debugger.GetTargetList().GetSelectedTarget()); - if (target_sp) { - ProcessSP process_sp(target_sp->GetProcessSP()); - if (process_sp) { - for (ThreadSP thread_sp : process_sp->GetThreadList().Threads()) { - StopReason reason = thread_sp->GetStopReason(); - if (reason == eStopReasonSignal || reason == eStopReasonException || - reason == eStopReasonInstrumentation) { - should_stop = true; - break; - } - } - } - } - if (should_stop) { - if (idx != num_lines - 1) - result.AppendErrorWithFormat( - "Aborting reading of commands after command #%" PRIu64 - ": '%s' stopped with a signal or exception.\n", - (uint64_t)idx + 1, cmd); - else - result.AppendMessageWithFormat( - "Command #%" PRIu64 " '%s' stopped with a signal or exception.\n", - (uint64_t)idx + 1, cmd); + if (tmp_result.GetDidChangeProcessState() && options.GetStopOnCrash() && + DidProcessStopAbnormally()) { + if (idx != num_lines - 1) + result.AppendErrorWithFormat( + "Aborting reading of commands after command #%" PRIu64 + ": '%s' stopped with a signal or exception.\n", + (uint64_t)idx + 1, cmd); + else + result.AppendMessageWithFormat( + "Command #%" PRIu64 " '%s' stopped with a signal or exception.\n", + (uint64_t)idx + 1, cmd); - result.SetStatus(tmp_result.GetStatus()); - m_debugger.SetAsyncExecution(old_async_execution); + result.SetStatus(tmp_result.GetStatus()); + m_debugger.SetAsyncExecution(old_async_execution); - return; - } + return; } } @@ -2405,18 +2338,18 @@ void CommandInterpreter::HandleCommandsFromFile( return; } - StreamFileSP input_file_sp(new StreamFile()); std::string cmd_file_path = cmd_file.GetPath(); - Status error = FileSystem::Instance().Open(input_file_sp->GetFile(), cmd_file, - File::eOpenOptionRead); - - if (error.Fail()) { - result.AppendErrorWithFormat( - "error: an error occurred read file '%s': %s\n", cmd_file_path.c_str(), - error.AsCString()); + auto input_file_up = + FileSystem::Instance().Open(cmd_file, File::eOpenOptionRead); + if (!input_file_up) { + std::string error = llvm::toString(input_file_up.takeError()); + result.AppendErrorWithFormatv( + "error: an error occurred read file '{0}': {1}\n", cmd_file_path, + llvm::fmt_consume(input_file_up.takeError())); result.SetStatus(eReturnStatusFailed); return; } + FileSP input_file_sp = FileSP(std::move(input_file_up.get())); Debugger &debugger = GetDebugger(); @@ -2502,8 +2435,8 @@ void CommandInterpreter::HandleCommandsFromFile( } if (flags & eHandleCommandFlagPrintResult) { - debugger.GetOutputFile()->Printf("Executing commands in '%s'.\n", - cmd_file_path.c_str()); + debugger.GetOutputFile().Printf("Executing commands in '%s'.\n", + cmd_file_path.c_str()); } // Used for inheriting the right settings when "command source" might @@ -2541,6 +2474,9 @@ void CommandInterpreter::HandleCommandsFromFile( bool CommandInterpreter::GetSynchronous() { return m_synchronous_execution; } void CommandInterpreter::SetSynchronous(bool value) { + // Asynchronous mode is not supported during reproducer replay. + if (repro::Reproducer::Instance().GetLoader()) + return; m_synchronous_execution = value; } @@ -2701,32 +2637,14 @@ void CommandInterpreter::UpdateExecutionContext( } } -size_t CommandInterpreter::GetProcessOutput() { - // The process has stuff waiting for stderr; get it and write it out to the - // appropriate place. - char stdio_buffer[1024]; - size_t len; - size_t total_bytes = 0; - Status error; +void CommandInterpreter::GetProcessOutput() { TargetSP target_sp(m_debugger.GetTargetList().GetSelectedTarget()); - if (target_sp) { - ProcessSP process_sp(target_sp->GetProcessSP()); - if (process_sp) { - while ((len = process_sp->GetSTDOUT(stdio_buffer, sizeof(stdio_buffer), - error)) > 0) { - size_t bytes_written = len; - m_debugger.GetOutputFile()->Write(stdio_buffer, bytes_written); - total_bytes += len; - } - while ((len = process_sp->GetSTDERR(stdio_buffer, sizeof(stdio_buffer), - error)) > 0) { - size_t bytes_written = len; - m_debugger.GetErrorFile()->Write(stdio_buffer, bytes_written); - total_bytes += len; - } - } - } - return total_bytes; + if (!target_sp) + return; + + if (ProcessSP process_sp = target_sp->GetProcessSP()) + m_debugger.FlushProcessOutput(*process_sp, /*flush_stdout*/ true, + /*flush_stderr*/ true); } void CommandInterpreter::StartHandlingCommand() { @@ -2818,8 +2736,8 @@ void CommandInterpreter::IOHandlerInputComplete(IOHandler &io_handler, // from a file) we need to echo the command out so we don't just see the // command output and no command... if (EchoCommandNonInteractive(line, io_handler.GetFlags())) - io_handler.GetOutputStreamFile()->Printf("%s%s\n", io_handler.GetPrompt(), - line.c_str()); + io_handler.GetOutputStreamFileSP()->Printf( + "%s%s\n", io_handler.GetPrompt(), line.c_str()); } StartHandlingCommand(); @@ -2836,13 +2754,13 @@ void CommandInterpreter::IOHandlerInputComplete(IOHandler &io_handler, if (!result.GetImmediateOutputStream()) { llvm::StringRef output = result.GetOutputData(); - PrintCommandOutput(*io_handler.GetOutputStreamFile(), output); + PrintCommandOutput(*io_handler.GetOutputStreamFileSP(), output); } // Now emit the command error text from the command we just executed if (!result.GetImmediateErrorStream()) { llvm::StringRef error = result.GetErrorData(); - PrintCommandOutput(*io_handler.GetErrorStreamFile(), error); + PrintCommandOutput(*io_handler.GetErrorStreamFileSP(), error); } } @@ -2875,27 +2793,10 @@ void CommandInterpreter::IOHandlerInputComplete(IOHandler &io_handler, // Finally, if we're going to stop on crash, check that here: if (!m_quit_requested && result.GetDidChangeProcessState() && - io_handler.GetFlags().Test(eHandleCommandFlagStopOnCrash)) { - bool should_stop = false; - TargetSP target_sp(m_debugger.GetTargetList().GetSelectedTarget()); - if (target_sp) { - ProcessSP process_sp(target_sp->GetProcessSP()); - if (process_sp) { - for (ThreadSP thread_sp : process_sp->GetThreadList().Threads()) { - StopReason reason = thread_sp->GetStopReason(); - if ((reason == eStopReasonSignal || reason == eStopReasonException || - reason == eStopReasonInstrumentation) && - !result.GetAbnormalStopWasExpected()) { - should_stop = true; - break; - } - } - } - } - if (should_stop) { - io_handler.SetIsDone(true); - m_stopped_for_crash = true; - } + io_handler.GetFlags().Test(eHandleCommandFlagStopOnCrash) && + DidProcessStopAbnormally()) { + io_handler.SetIsDone(true); + m_stopped_for_crash = true; } } @@ -3009,8 +2910,8 @@ CommandInterpreter::GetIOHandler(bool force_create, m_command_io_handler_sp = std::make_shared<IOHandlerEditline>( m_debugger, IOHandler::Type::CommandInterpreter, - m_debugger.GetInputFile(), m_debugger.GetOutputFile(), - m_debugger.GetErrorFile(), flags, "lldb", m_debugger.GetPrompt(), + m_debugger.GetInputFileSP(), m_debugger.GetOutputStreamSP(), + m_debugger.GetErrorStreamSP(), flags, "lldb", m_debugger.GetPrompt(), llvm::StringRef(), // Continuation prompt false, // Don't enable multiple line input, just single line commands m_debugger.GetUseColor(), diff --git a/source/Interpreter/CommandObject.cpp b/source/Interpreter/CommandObject.cpp index 8e493c7a326f..d666852ee68c 100644 --- a/source/Interpreter/CommandObject.cpp +++ b/source/Interpreter/CommandObject.cpp @@ -257,14 +257,14 @@ void CommandObject::Cleanup() { m_api_locker.unlock(); } -int CommandObject::HandleCompletion(CompletionRequest &request) { +void CommandObject::HandleCompletion(CompletionRequest &request) { // Default implementation of WantsCompletion() is !WantsRawCommandString(). // Subclasses who want raw command string but desire, for example, argument // completion should override WantsCompletion() to return true, instead. if (WantsRawCommandString() && !WantsCompletion()) { // FIXME: Abstract telling the completion to insert the completion // character. - return -1; + return; } else { // Can we do anything generic with the options? Options *cur_options = GetOptions(); @@ -278,11 +278,11 @@ int CommandObject::HandleCompletion(CompletionRequest &request) { bool handled_by_options = cur_options->HandleOptionCompletion( request, opt_element_vector, GetCommandInterpreter()); if (handled_by_options) - return request.GetNumberOfMatches(); + return; } // If we got here, the last word is not an option or an option argument. - return HandleArgumentCompletion(request, opt_element_vector); + HandleArgumentCompletion(request, opt_element_vector); } } @@ -917,12 +917,21 @@ const char *CommandObject::GetArgumentDescriptionAsCString( return g_arguments_data[arg_type].help_text; } -Target *CommandObject::GetDummyTarget() { - return m_interpreter.GetDebugger().GetDummyTarget(); +Target &CommandObject::GetDummyTarget() { + return *m_interpreter.GetDebugger().GetDummyTarget(); +} + +Target &CommandObject::GetSelectedOrDummyTarget(bool prefer_dummy) { + return *m_interpreter.GetDebugger().GetSelectedOrDummyTarget(prefer_dummy); } -Target *CommandObject::GetSelectedOrDummyTarget(bool prefer_dummy) { - return m_interpreter.GetDebugger().GetSelectedOrDummyTarget(prefer_dummy); +Target &CommandObject::GetSelectedTarget() { + assert(m_flags.AnySet(eCommandRequiresTarget | eCommandProcessMustBePaused | + eCommandProcessMustBeLaunched | eCommandRequiresFrame | + eCommandRequiresThread | eCommandRequiresProcess | + eCommandRequiresRegContext) && + "GetSelectedTarget called from object that may have no target"); + return *m_interpreter.GetDebugger().GetSelectedTarget(); } Thread *CommandObject::GetDefaultThread() { @@ -958,7 +967,7 @@ bool CommandObjectParsed::Execute(const char *args_string, } if (!handled) { for (auto entry : llvm::enumerate(cmd_args.entries())) { - if (!entry.value().ref.empty() && entry.value().ref.front() == '`') { + if (!entry.value().ref().empty() && entry.value().ref().front() == '`') { cmd_args.ReplaceArgumentAtIndex( entry.index(), m_interpreter.ProcessEmbeddedScriptCommands(entry.value().c_str())); @@ -1064,7 +1073,7 @@ CommandObject::ArgumentTableEntry CommandObject::g_arguments_data[] = { { eArgTypePythonScript, "python-script", CommandCompletions::eNoCompletion, { nullptr, false }, "Source code written in Python." }, { eArgTypeQueueName, "queue-name", CommandCompletions::eNoCompletion, { nullptr, false }, "The name of the thread queue." }, { eArgTypeRegisterName, "register-name", CommandCompletions::eNoCompletion, { RegisterNameHelpTextCallback, true }, nullptr }, - { eArgTypeRegularExpression, "regular-expression", CommandCompletions::eNoCompletion, { nullptr, false }, "A regular expression." }, + { eArgTypeRegularExpression, "regular-expression", CommandCompletions::eNoCompletion, { nullptr, false }, "A POSIX-compliant extended regular expression." }, { eArgTypeRunArgs, "run-args", CommandCompletions::eNoCompletion, { nullptr, false }, "Arguments to be passed to the target program when it starts executing." }, { eArgTypeRunMode, "run-mode", CommandCompletions::eNoCompletion, { nullptr, false }, "Help text goes here." }, { eArgTypeScriptedCommandSynchronicity, "script-cmd-synchronicity", CommandCompletions::eNoCompletion, { nullptr, false }, "The synchronicity to use to run scripted commands with regard to LLDB event system." }, diff --git a/source/Interpreter/CommandObjectRegexCommand.cpp b/source/Interpreter/CommandObjectRegexCommand.cpp index 19335b95ca3a..693d18ce7bdf 100644 --- a/source/Interpreter/CommandObjectRegexCommand.cpp +++ b/source/Interpreter/CommandObjectRegexCommand.cpp @@ -30,15 +30,14 @@ bool CommandObjectRegexCommand::DoExecute(llvm::StringRef command, CommandReturnObject &result) { EntryCollection::const_iterator pos, end = m_entries.end(); for (pos = m_entries.begin(); pos != end; ++pos) { - RegularExpression::Match regex_match(m_max_matches); - - if (pos->regex.Execute(command, ®ex_match)) { + llvm::SmallVector<llvm::StringRef, 4> matches; + if (pos->regex.Execute(command, &matches)) { std::string new_command(pos->command); - std::string match_str; char percent_var[8]; size_t idx, percent_var_idx; for (uint32_t match_idx = 1; match_idx <= m_max_matches; ++match_idx) { - if (regex_match.GetMatchAtIndex(command, match_idx, match_str)) { + if (match_idx < matches.size()) { + const std::string match_str = matches[match_idx].str(); const int percent_var_len = ::snprintf(percent_var, sizeof(percent_var), "%%%u", match_idx); for (idx = 0; (percent_var_idx = new_command.find( @@ -74,8 +73,9 @@ bool CommandObjectRegexCommand::AddRegexCommand(const char *re_cstr, const char *command_cstr) { m_entries.resize(m_entries.size() + 1); // Only add the regular expression if it compiles - if (m_entries.back().regex.Compile( - llvm::StringRef::withNullAsEmpty(re_cstr))) { + m_entries.back().regex = + RegularExpression(llvm::StringRef::withNullAsEmpty(re_cstr)); + if (m_entries.back().regex.IsValid()) { m_entries.back().command.assign(command_cstr); return true; } @@ -84,13 +84,9 @@ bool CommandObjectRegexCommand::AddRegexCommand(const char *re_cstr, return false; } -int CommandObjectRegexCommand::HandleCompletion(CompletionRequest &request) { +void CommandObjectRegexCommand::HandleCompletion(CompletionRequest &request) { if (m_completion_type_mask) { CommandCompletions::InvokeCommonCompletionCallbacks( GetCommandInterpreter(), m_completion_type_mask, request, nullptr); - return request.GetNumberOfMatches(); - } else { - request.SetWordComplete(false); } - return 0; } diff --git a/source/Interpreter/CommandReturnObject.cpp b/source/Interpreter/CommandReturnObject.cpp index 3a7a8755d975..c17390be7311 100644 --- a/source/Interpreter/CommandReturnObject.cpp +++ b/source/Interpreter/CommandReturnObject.cpp @@ -33,8 +33,7 @@ static void DumpStringToStreamWithNewline(Stream &strm, const std::string &s, CommandReturnObject::CommandReturnObject() : m_out_stream(), m_err_stream(), m_status(eReturnStatusStarted), - m_did_change_process_state(false), m_interactive(true), - m_abnormal_stop_was_expected(false) {} + m_did_change_process_state(false), m_interactive(true) {} CommandReturnObject::~CommandReturnObject() {} diff --git a/source/Interpreter/InterpreterProperties.td b/source/Interpreter/InterpreterProperties.td new file mode 100644 index 000000000000..600c1e3edb9b --- /dev/null +++ b/source/Interpreter/InterpreterProperties.td @@ -0,0 +1,28 @@ +include "../../include/lldb/Core/PropertiesBase.td" + +let Definition = "interpreter" in { + def ExpandRegexAliases: Property<"expand-regex-aliases", "Boolean">, + Global, + DefaultFalse, + Desc<"If true, regular expression alias commands will show the expanded command that will be executed. This can be used to debug new regular expression alias commands.">; + def PromptOnQuit: Property<"prompt-on-quit", "Boolean">, + Global, + DefaultTrue, + Desc<"If true, LLDB will prompt you before quitting if there are any live processes being debugged. If false, LLDB will quit without asking in any case.">; + def StopCmdSourceOnError: Property<"stop-command-source-on-error", "Boolean">, + Global, + DefaultTrue, + Desc<"If true, LLDB will stop running a 'command source' script upon encountering an error.">; + def SpaceReplPrompts: Property<"space-repl-prompts", "Boolean">, + Global, + DefaultFalse, + Desc<"If true, blank lines will be printed between between REPL submissions.">; + def EchoCommands: Property<"echo-commands", "Boolean">, + Global, + DefaultTrue, + Desc<"If true, commands will be echoed before they are evaluated.">; + def EchoCommentCommands: Property<"echo-comment-commands", "Boolean">, + Global, + DefaultTrue, + Desc<"If true, commands will be echoed even if they are pure comment lines.">; +} diff --git a/source/Interpreter/OptionArgParser.cpp b/source/Interpreter/OptionArgParser.cpp index efaac0720fd0..14b81cd7b3d2 100644 --- a/source/Interpreter/OptionArgParser.cpp +++ b/source/Interpreter/OptionArgParser.cpp @@ -211,29 +211,21 @@ lldb::addr_t OptionArgParser::ToAddress(const ExecutionContext *exe_ctx, // pointer types. static RegularExpression g_symbol_plus_offset_regex( "^(.*)([-\\+])[[:space:]]*(0x[0-9A-Fa-f]+|[0-9]+)[[:space:]]*$"); - RegularExpression::Match regex_match(3); - if (g_symbol_plus_offset_regex.Execute(sref, ®ex_match)) { + + llvm::SmallVector<llvm::StringRef, 4> matches; + if (g_symbol_plus_offset_regex.Execute(sref, &matches)) { uint64_t offset = 0; - bool add = true; - std::string name; - std::string str; - if (regex_match.GetMatchAtIndex(s, 1, name)) { - if (regex_match.GetMatchAtIndex(s, 2, str)) { - add = str[0] == '+'; - - if (regex_match.GetMatchAtIndex(s, 3, str)) { - if (!llvm::StringRef(str).getAsInteger(0, offset)) { - Status error; - addr = ToAddress(exe_ctx, name.c_str(), LLDB_INVALID_ADDRESS, - &error); - if (addr != LLDB_INVALID_ADDRESS) { - if (add) - return addr + offset; - else - return addr - offset; - } - } - } + std::string name = matches[1].str(); + std::string sign = matches[2].str(); + std::string str_offset = matches[3].str(); + if (!llvm::StringRef(str_offset).getAsInteger(0, offset)) { + Status error; + addr = ToAddress(exe_ctx, name.c_str(), LLDB_INVALID_ADDRESS, &error); + if (addr != LLDB_INVALID_ADDRESS) { + if (sign[0] == '+') + return addr + offset; + else + return addr - offset; } } } diff --git a/source/Interpreter/OptionGroupArchitecture.cpp b/source/Interpreter/OptionGroupArchitecture.cpp index 2ee1a9c7cf84..11f786c52c09 100644 --- a/source/Interpreter/OptionGroupArchitecture.cpp +++ b/source/Interpreter/OptionGroupArchitecture.cpp @@ -46,8 +46,7 @@ OptionGroupArchitecture::SetOptionValue(uint32_t option_idx, break; default: - error.SetErrorStringWithFormat("unrecognized option '%c'", short_option); - break; + llvm_unreachable("Unimplemented option"); } return error; diff --git a/source/Interpreter/OptionGroupFormat.cpp b/source/Interpreter/OptionGroupFormat.cpp index d9acfd663dd1..c25e35f84517 100644 --- a/source/Interpreter/OptionGroupFormat.cpp +++ b/source/Interpreter/OptionGroupFormat.cpp @@ -160,8 +160,7 @@ Status OptionGroupFormat::SetOptionValue(uint32_t option_idx, } break; default: - error.SetErrorStringWithFormat("unrecognized option '%c'", short_option); - break; + llvm_unreachable("Unimplemented option"); } return error; diff --git a/source/Interpreter/OptionGroupOutputFile.cpp b/source/Interpreter/OptionGroupOutputFile.cpp index ccb99a8fce4a..3df75cf86b85 100644 --- a/source/Interpreter/OptionGroupOutputFile.cpp +++ b/source/Interpreter/OptionGroupOutputFile.cpp @@ -50,8 +50,7 @@ OptionGroupOutputFile::SetOptionValue(uint32_t option_idx, break; default: - error.SetErrorStringWithFormat("unrecognized option '%c'", short_option); - break; + llvm_unreachable("Unimplemented option"); } return error; diff --git a/source/Interpreter/OptionGroupPlatform.cpp b/source/Interpreter/OptionGroupPlatform.cpp index 6dc2996bb78a..6ddbbf0e3abb 100644 --- a/source/Interpreter/OptionGroupPlatform.cpp +++ b/source/Interpreter/OptionGroupPlatform.cpp @@ -113,8 +113,7 @@ OptionGroupPlatform::SetOptionValue(uint32_t option_idx, break; default: - error.SetErrorStringWithFormat("unrecognized option '%c'", short_option); - break; + llvm_unreachable("Unimplemented option"); } return error; } diff --git a/source/Interpreter/OptionGroupPythonClassWithDict.cpp b/source/Interpreter/OptionGroupPythonClassWithDict.cpp new file mode 100644 index 000000000000..9a893ec53625 --- /dev/null +++ b/source/Interpreter/OptionGroupPythonClassWithDict.cpp @@ -0,0 +1,123 @@ +//===-- OptionGroupPythonClassWithDict.cpp ----------------------------------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#include "lldb/Interpreter/OptionGroupPythonClassWithDict.h" + +#include "lldb/Host/OptionParser.h" + +using namespace lldb; +using namespace lldb_private; + +OptionGroupPythonClassWithDict::OptionGroupPythonClassWithDict + (const char *class_use, + int class_option, + int key_option, + int value_option, + const char *class_long_option, + const char *key_long_option, + const char *value_long_option, + bool required) { + m_key_usage_text.assign("The key for a key/value pair passed to the class" + " that implements a "); + m_key_usage_text.append(class_use); + m_key_usage_text.append(". Pairs can be specified more than once."); + + m_value_usage_text.assign("The value for a previous key in the pair passed to" + " the class that implements a "); + m_value_usage_text.append(class_use); + m_value_usage_text.append(". Pairs can be specified more than once."); + + m_class_usage_text.assign("The name of the class that will manage a "); + m_class_usage_text.append(class_use); + m_class_usage_text.append("."); + + m_option_definition[0].usage_mask = LLDB_OPT_SET_1; + m_option_definition[0].required = required; + m_option_definition[0].long_option = class_long_option; + m_option_definition[0].short_option = class_option; + m_option_definition[0].validator = nullptr; + m_option_definition[0].option_has_arg = OptionParser::eRequiredArgument; + m_option_definition[0].enum_values = {}; + m_option_definition[0].completion_type = 0; + m_option_definition[0].argument_type = eArgTypePythonClass; + m_option_definition[0].usage_text = m_class_usage_text.data(); + + m_option_definition[1].usage_mask = LLDB_OPT_SET_1; + m_option_definition[1].required = required; + m_option_definition[1].long_option = key_long_option; + m_option_definition[1].short_option = key_option; + m_option_definition[1].validator = nullptr; + m_option_definition[1].option_has_arg = OptionParser::eRequiredArgument; + m_option_definition[1].enum_values = {}; + m_option_definition[1].completion_type = 0; + m_option_definition[1].argument_type = eArgTypeNone; + m_option_definition[1].usage_text = m_key_usage_text.data(); + + m_option_definition[2].usage_mask = LLDB_OPT_SET_1; + m_option_definition[2].required = required; + m_option_definition[2].long_option = value_long_option; + m_option_definition[2].short_option = value_option; + m_option_definition[2].validator = nullptr; + m_option_definition[2].option_has_arg = OptionParser::eRequiredArgument; + m_option_definition[2].enum_values = {}; + m_option_definition[2].completion_type = 0; + m_option_definition[2].argument_type = eArgTypeNone; + m_option_definition[2].usage_text = m_value_usage_text.data(); +} + +OptionGroupPythonClassWithDict::~OptionGroupPythonClassWithDict() {} + +Status OptionGroupPythonClassWithDict::SetOptionValue( + uint32_t option_idx, + llvm::StringRef option_arg, + ExecutionContext *execution_context) { + Status error; + switch (option_idx) { + case 0: { + m_class_name.assign(option_arg); + } break; + case 1: { + if (m_current_key.empty()) + m_current_key.assign(option_arg); + else + error.SetErrorStringWithFormat("Key: \"%s\" missing value.", + m_current_key.c_str()); + + } break; + case 2: { + if (!m_current_key.empty()) { + m_dict_sp->AddStringItem(m_current_key, option_arg); + m_current_key.clear(); + } + else + error.SetErrorStringWithFormat("Value: \"%s\" missing matching key.", + option_arg.str().c_str()); + } break; + default: + llvm_unreachable("Unimplemented option"); + } + return error; +} + +void OptionGroupPythonClassWithDict::OptionParsingStarting( + ExecutionContext *execution_context) { + m_current_key.erase(); + m_dict_sp = std::make_shared<StructuredData::Dictionary>(); +} + +Status OptionGroupPythonClassWithDict::OptionParsingFinished( + ExecutionContext *execution_context) { + Status error; + // If we get here and there's contents in the m_current_key, somebody must + // have provided a key but no value. + if (!m_current_key.empty()) + error.SetErrorStringWithFormat("Key: \"%s\" missing value.", + m_current_key.c_str()); + return error; +} + diff --git a/source/Interpreter/OptionGroupUUID.cpp b/source/Interpreter/OptionGroupUUID.cpp index e32673bc52af..8fc330a89391 100644 --- a/source/Interpreter/OptionGroupUUID.cpp +++ b/source/Interpreter/OptionGroupUUID.cpp @@ -40,8 +40,7 @@ Status OptionGroupUUID::SetOptionValue(uint32_t option_idx, break; default: - error.SetErrorStringWithFormat("unrecognized option '%c'", short_option); - break; + llvm_unreachable("Unimplemented option"); } return error; diff --git a/source/Interpreter/OptionGroupValueObjectDisplay.cpp b/source/Interpreter/OptionGroupValueObjectDisplay.cpp index 4e5463a4de00..81c10a6c762e 100644 --- a/source/Interpreter/OptionGroupValueObjectDisplay.cpp +++ b/source/Interpreter/OptionGroupValueObjectDisplay.cpp @@ -152,8 +152,7 @@ Status OptionGroupValueObjectDisplay::SetOptionValue( break; default: - error.SetErrorStringWithFormat("unrecognized option '%c'", short_option); - break; + llvm_unreachable("Unimplemented option"); } return error; diff --git a/source/Interpreter/OptionGroupVariable.cpp b/source/Interpreter/OptionGroupVariable.cpp index d703c3dedcd9..a9004bf03cd2 100644 --- a/source/Interpreter/OptionGroupVariable.cpp +++ b/source/Interpreter/OptionGroupVariable.cpp @@ -109,9 +109,7 @@ OptionGroupVariable::SetOptionValue(uint32_t option_idx, error = summary_string.SetCurrentValue(option_arg); break; default: - error.SetErrorStringWithFormat("unrecognized short option '%c'", - short_option); - break; + llvm_unreachable("Unimplemented option"); } return error; diff --git a/source/Interpreter/OptionGroupWatchpoint.cpp b/source/Interpreter/OptionGroupWatchpoint.cpp index 28e6b817fcc5..682f99b8c5cc 100644 --- a/source/Interpreter/OptionGroupWatchpoint.cpp +++ b/source/Interpreter/OptionGroupWatchpoint.cpp @@ -16,16 +16,45 @@ using namespace lldb; using namespace lldb_private; static constexpr OptionEnumValueElement g_watch_type[] = { - {OptionGroupWatchpoint::eWatchRead, "read", "Watch for read"}, - {OptionGroupWatchpoint::eWatchWrite, "write", "Watch for write"}, - {OptionGroupWatchpoint::eWatchReadWrite, "read_write", - "Watch for read/write"} }; + { + OptionGroupWatchpoint::eWatchRead, + "read", + "Watch for read", + }, + { + OptionGroupWatchpoint::eWatchWrite, + "write", + "Watch for write", + }, + { + OptionGroupWatchpoint::eWatchReadWrite, + "read_write", + "Watch for read/write", + }, +}; static constexpr OptionEnumValueElement g_watch_size[] = { - {1, "1", "Watch for byte size of 1"}, - {2, "2", "Watch for byte size of 2"}, - {4, "4", "Watch for byte size of 4"}, - {8, "8", "Watch for byte size of 8"} }; + { + 1, + "1", + "Watch for byte size of 1", + }, + { + 2, + "2", + "Watch for byte size of 2", + }, + { + 4, + "4", + "Watch for byte size of 4", + }, + { + 8, + "8", + "Watch for byte size of 8", + }, +}; static constexpr OptionDefinition g_option_table[] = { {LLDB_OPT_SET_1, false, "watch", 'w', OptionParser::eRequiredArgument, @@ -72,9 +101,7 @@ OptionGroupWatchpoint::SetOptionValue(uint32_t option_idx, break; default: - error.SetErrorStringWithFormat("unrecognized short option '%c'", - short_option); - break; + llvm_unreachable("Unimplemented option"); } return error; diff --git a/source/Interpreter/OptionValue.cpp b/source/Interpreter/OptionValue.cpp index 00c8642595b7..bc929aa9dabf 100644 --- a/source/Interpreter/OptionValue.cpp +++ b/source/Interpreter/OptionValue.cpp @@ -565,11 +565,8 @@ bool OptionValue::DumpQualifiedName(Stream &strm) const { return dumped_something; } -size_t OptionValue::AutoComplete(CommandInterpreter &interpreter, - CompletionRequest &request) { - request.SetWordComplete(false); - return request.GetNumberOfMatches(); -} +void OptionValue::AutoComplete(CommandInterpreter &interpreter, + CompletionRequest &request) {} Status OptionValue::SetValueFromString(llvm::StringRef value, VarSetOperationType op) { diff --git a/source/Interpreter/OptionValueArch.cpp b/source/Interpreter/OptionValueArch.cpp index 92dc45d092be..7271c1471f90 100644 --- a/source/Interpreter/OptionValueArch.cpp +++ b/source/Interpreter/OptionValueArch.cpp @@ -68,11 +68,9 @@ lldb::OptionValueSP OptionValueArch::DeepCopy() const { return OptionValueSP(new OptionValueArch(*this)); } -size_t OptionValueArch::AutoComplete(CommandInterpreter &interpreter, - CompletionRequest &request) { - request.SetWordComplete(false); +void OptionValueArch::AutoComplete(CommandInterpreter &interpreter, + CompletionRequest &request) { CommandCompletions::InvokeCommonCompletionCallbacks( interpreter, CommandCompletions::eArchitectureCompletion, request, nullptr); - return request.GetNumberOfMatches(); } diff --git a/source/Interpreter/OptionValueBoolean.cpp b/source/Interpreter/OptionValueBoolean.cpp index 8be8220fb306..6f893a94e863 100644 --- a/source/Interpreter/OptionValueBoolean.cpp +++ b/source/Interpreter/OptionValueBoolean.cpp @@ -71,21 +71,17 @@ lldb::OptionValueSP OptionValueBoolean::DeepCopy() const { return OptionValueSP(new OptionValueBoolean(*this)); } -size_t OptionValueBoolean::AutoComplete(CommandInterpreter &interpreter, - CompletionRequest &request) { - request.SetWordComplete(false); - static const llvm::StringRef g_autocomplete_entries[] = { - "true", "false", "on", "off", "yes", "no", "1", "0"}; +void OptionValueBoolean::AutoComplete(CommandInterpreter &interpreter, + CompletionRequest &request) { + llvm::StringRef autocomplete_entries[] = {"true", "false", "on", "off", + "yes", "no", "1", "0"}; - auto entries = llvm::makeArrayRef(g_autocomplete_entries); + auto entries = llvm::makeArrayRef(autocomplete_entries); // only suggest "true" or "false" by default if (request.GetCursorArgumentPrefix().empty()) entries = entries.take_front(2); - for (auto entry : entries) { - if (entry.startswith_lower(request.GetCursorArgumentPrefix())) - request.AddCompletion(entry); - } - return request.GetNumberOfMatches(); + for (auto entry : entries) + request.TryCompleteCurrentArg(entry); } diff --git a/source/Interpreter/OptionValueDictionary.cpp b/source/Interpreter/OptionValueDictionary.cpp index eb66c485bfd1..a4022288fccb 100644 --- a/source/Interpreter/OptionValueDictionary.cpp +++ b/source/Interpreter/OptionValueDictionary.cpp @@ -111,18 +111,18 @@ Status OptionValueDictionary::SetArgs(const Args &args, return error; } for (const auto &entry : args) { - if (entry.ref.empty()) { + if (entry.ref().empty()) { error.SetErrorString("empty argument"); return error; } - if (!entry.ref.contains('=')) { + if (!entry.ref().contains('=')) { error.SetErrorString( "assign operation takes one or more key=value arguments"); return error; } llvm::StringRef key, value; - std::tie(key, value) = entry.ref.split('='); + std::tie(key, value) = entry.ref().split('='); bool key_valid = false; if (key.empty()) { error.SetErrorString("empty dictionary key"); diff --git a/source/Interpreter/OptionValueEnumeration.cpp b/source/Interpreter/OptionValueEnumeration.cpp index 0b76bd0601aa..26933aa78240 100644 --- a/source/Interpreter/OptionValueEnumeration.cpp +++ b/source/Interpreter/OptionValueEnumeration.cpp @@ -102,21 +102,16 @@ lldb::OptionValueSP OptionValueEnumeration::DeepCopy() const { return OptionValueSP(new OptionValueEnumeration(*this)); } -size_t OptionValueEnumeration::AutoComplete(CommandInterpreter &interpreter, - CompletionRequest &request) { - request.SetWordComplete(false); - +void OptionValueEnumeration::AutoComplete(CommandInterpreter &interpreter, + CompletionRequest &request) { const uint32_t num_enumerators = m_enumerations.GetSize(); if (!request.GetCursorArgumentPrefix().empty()) { for (size_t i = 0; i < num_enumerators; ++i) { llvm::StringRef name = m_enumerations.GetCStringAtIndex(i).GetStringRef(); - if (name.startswith(request.GetCursorArgumentPrefix())) - request.AddCompletion(name); + request.TryCompleteCurrentArg(name); } - } else { - // only suggest "true" or "false" by default + return; + } for (size_t i = 0; i < num_enumerators; ++i) request.AddCompletion(m_enumerations.GetCStringAtIndex(i).GetStringRef()); - } - return request.GetNumberOfMatches(); } diff --git a/source/Interpreter/OptionValueFileSpec.cpp b/source/Interpreter/OptionValueFileSpec.cpp index 062d7ccdf2aa..20d3d4e68e33 100644 --- a/source/Interpreter/OptionValueFileSpec.cpp +++ b/source/Interpreter/OptionValueFileSpec.cpp @@ -99,12 +99,10 @@ lldb::OptionValueSP OptionValueFileSpec::DeepCopy() const { return OptionValueSP(new OptionValueFileSpec(*this)); } -size_t OptionValueFileSpec::AutoComplete(CommandInterpreter &interpreter, - CompletionRequest &request) { - request.SetWordComplete(false); +void OptionValueFileSpec::AutoComplete(CommandInterpreter &interpreter, + CompletionRequest &request) { CommandCompletions::InvokeCommonCompletionCallbacks( interpreter, m_completion_mask, request, nullptr); - return request.GetNumberOfMatches(); } const lldb::DataBufferSP &OptionValueFileSpec::GetFileContents() { diff --git a/source/Interpreter/OptionValueFileSpecLIst.cpp b/source/Interpreter/OptionValueFileSpecList.cpp index a95188870f0b..1a9d3c9ecb87 100644 --- a/source/Interpreter/OptionValueFileSpecLIst.cpp +++ b/source/Interpreter/OptionValueFileSpecList.cpp @@ -1,4 +1,4 @@ -//===-- OptionValueFileSpecLIst.cpp -----------------------------*- C++ -*-===// +//===-- OptionValueFileSpecList.cpp ---------------------------------------===// // // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. // See https://llvm.org/LICENSE.txt for license information. diff --git a/source/Interpreter/OptionValueFormatEntity.cpp b/source/Interpreter/OptionValueFormatEntity.cpp index 1bb8c9f6955a..8dc52650a331 100644 --- a/source/Interpreter/OptionValueFormatEntity.cpp +++ b/source/Interpreter/OptionValueFormatEntity.cpp @@ -116,7 +116,7 @@ lldb::OptionValueSP OptionValueFormatEntity::DeepCopy() const { return OptionValueSP(new OptionValueFormatEntity(*this)); } -size_t OptionValueFormatEntity::AutoComplete(CommandInterpreter &interpreter, - CompletionRequest &request) { - return FormatEntity::AutoComplete(request); +void OptionValueFormatEntity::AutoComplete(CommandInterpreter &interpreter, + CompletionRequest &request) { + FormatEntity::AutoComplete(request); } diff --git a/source/Interpreter/OptionValueLanguage.cpp b/source/Interpreter/OptionValueLanguage.cpp index d935d5e23496..1d7e18868b6f 100644 --- a/source/Interpreter/OptionValueLanguage.cpp +++ b/source/Interpreter/OptionValueLanguage.cpp @@ -10,6 +10,7 @@ #include "lldb/DataFormatters/FormatManager.h" #include "lldb/Target/Language.h" +#include "lldb/Symbol/TypeSystem.h" #include "lldb/Utility/Args.h" #include "lldb/Utility/Stream.h" @@ -39,23 +40,20 @@ Status OptionValueLanguage::SetValueFromString(llvm::StringRef value, case eVarSetOperationReplace: case eVarSetOperationAssign: { ConstString lang_name(value.trim()); - std::set<lldb::LanguageType> languages_for_types; - std::set<lldb::LanguageType> languages_for_expressions; - Language::GetLanguagesSupportingTypeSystems(languages_for_types, - languages_for_expressions); - + LanguageSet languages_for_types = Language::GetLanguagesSupportingTypeSystems(); LanguageType new_type = Language::GetLanguageTypeFromString(lang_name.GetStringRef()); - if (new_type && languages_for_types.count(new_type)) { + if (new_type && languages_for_types[new_type]) { m_value_was_set = true; m_current_value = new_type; } else { StreamString error_strm; error_strm.Printf("invalid language type '%s', ", value.str().c_str()); error_strm.Printf("valid values are:\n"); - for (lldb::LanguageType language : languages_for_types) { - error_strm.Printf("%s%s%s", " ", - Language::GetNameForLanguageType(language), "\n"); + for (int bit : languages_for_types.bitvector.set_bits()) { + auto language = (LanguageType)bit; + error_strm.Printf(" %s\n", + Language::GetNameForLanguageType(language)); } error.SetErrorString(error_strm.GetString()); } diff --git a/source/Interpreter/OptionValueRegex.cpp b/source/Interpreter/OptionValueRegex.cpp index bbe3fa715019..cf806fb550f9 100644 --- a/source/Interpreter/OptionValueRegex.cpp +++ b/source/Interpreter/OptionValueRegex.cpp @@ -46,16 +46,14 @@ Status OptionValueRegex::SetValueFromString(llvm::StringRef value, case eVarSetOperationReplace: case eVarSetOperationAssign: - if (m_regex.Compile(value)) { + m_regex = RegularExpression(value); + if (m_regex.IsValid()) { m_value_was_set = true; NotifyValueChanged(); + } else if (llvm::Error err = m_regex.GetError()) { + error.SetErrorString(llvm::toString(std::move(err))); } else { - char regex_error[1024]; - if (m_regex.GetErrorAsCString(regex_error, sizeof(regex_error))) - error.SetErrorString(regex_error); - else - error.SetErrorStringWithFormat("regex error %u", - m_regex.GetErrorCode()); + error.SetErrorString("regex error"); } break; } diff --git a/source/Interpreter/OptionValueUUID.cpp b/source/Interpreter/OptionValueUUID.cpp index f39b66b77bb0..7a6bc65b25a4 100644 --- a/source/Interpreter/OptionValueUUID.cpp +++ b/source/Interpreter/OptionValueUUID.cpp @@ -62,30 +62,24 @@ lldb::OptionValueSP OptionValueUUID::DeepCopy() const { return OptionValueSP(new OptionValueUUID(*this)); } -size_t OptionValueUUID::AutoComplete(CommandInterpreter &interpreter, - CompletionRequest &request) { - request.SetWordComplete(false); +void OptionValueUUID::AutoComplete(CommandInterpreter &interpreter, + CompletionRequest &request) { ExecutionContext exe_ctx(interpreter.GetExecutionContext()); Target *target = exe_ctx.GetTargetPtr(); - if (target) { - auto prefix = request.GetCursorArgumentPrefix(); - llvm::SmallVector<uint8_t, 20> uuid_bytes; - if (UUID::DecodeUUIDBytesFromString(prefix, uuid_bytes).empty()) { - const size_t num_modules = target->GetImages().GetSize(); - for (size_t i = 0; i < num_modules; ++i) { - ModuleSP module_sp(target->GetImages().GetModuleAtIndex(i)); - if (module_sp) { - const UUID &module_uuid = module_sp->GetUUID(); - if (module_uuid.IsValid()) { - llvm::ArrayRef<uint8_t> module_bytes = module_uuid.GetBytes(); - if (module_bytes.size() >= uuid_bytes.size() && - module_bytes.take_front(uuid_bytes.size()).equals(uuid_bytes)) { - request.AddCompletion(module_uuid.GetAsString()); - } - } - } - } - } + if (!target) + return; + auto prefix = request.GetCursorArgumentPrefix(); + llvm::SmallVector<uint8_t, 20> uuid_bytes; + if (!UUID::DecodeUUIDBytesFromString(prefix, uuid_bytes).empty()) + return; + const size_t num_modules = target->GetImages().GetSize(); + for (size_t i = 0; i < num_modules; ++i) { + ModuleSP module_sp(target->GetImages().GetModuleAtIndex(i)); + if (!module_sp) + continue; + const UUID &module_uuid = module_sp->GetUUID(); + if (!module_uuid.IsValid()) + continue; + request.TryCompleteCurrentArg(module_uuid.GetAsString()); } - return request.GetNumberOfMatches(); } diff --git a/source/Interpreter/Options.cpp b/source/Interpreter/Options.cpp index ba15c020f2da..0bceea14269d 100644 --- a/source/Interpreter/Options.cpp +++ b/source/Interpreter/Options.cpp @@ -645,8 +645,6 @@ bool Options::VerifyPartialOptions(CommandReturnObject &result) { bool Options::HandleOptionCompletion(CompletionRequest &request, OptionElementVector &opt_element_vector, CommandInterpreter &interpreter) { - request.SetWordComplete(true); - // For now we just scan the completions to see if the cursor position is in // an option or its argument. Otherwise we'll call HandleArgumentCompletion. // In the future we can use completion to validate options as well if we @@ -654,12 +652,11 @@ bool Options::HandleOptionCompletion(CompletionRequest &request, auto opt_defs = GetDefinitions(); - std::string cur_opt_std_str = request.GetCursorArgumentPrefix().str(); - const char *cur_opt_str = cur_opt_std_str.c_str(); + llvm::StringRef cur_opt_str = request.GetCursorArgumentPrefix(); for (size_t i = 0; i < opt_element_vector.size(); i++) { - int opt_pos = opt_element_vector[i].opt_pos; - int opt_arg_pos = opt_element_vector[i].opt_arg_pos; + size_t opt_pos = static_cast<size_t>(opt_element_vector[i].opt_pos); + size_t opt_arg_pos = static_cast<size_t>(opt_element_vector[i].opt_arg_pos); int opt_defs_index = opt_element_vector[i].opt_defs_index; if (opt_pos == request.GetCursorIndex()) { // We're completing the option itself. @@ -669,13 +666,13 @@ bool Options::HandleOptionCompletion(CompletionRequest &request, // FIXME: We should scan the other options provided and only complete // options // within the option group they belong to. - char opt_str[3] = {'-', 'a', '\0'}; + std::string opt_str = "-a"; for (auto &def : opt_defs) { if (!def.short_option) continue; opt_str[1] = def.short_option; - request.AddCompletion(opt_str); + request.AddCompletion(opt_str, def.usage_text); } return true; @@ -687,7 +684,7 @@ bool Options::HandleOptionCompletion(CompletionRequest &request, full_name.erase(full_name.begin() + 2, full_name.end()); full_name.append(def.long_option); - request.AddCompletion(full_name.c_str()); + request.AddCompletion(full_name, def.usage_text); } return true; } else if (opt_defs_index != OptionArgElement::eUnrecognizedArg) { @@ -695,17 +692,14 @@ bool Options::HandleOptionCompletion(CompletionRequest &request, // anyway (getopt_long_only is happy with shortest unique string, but // it's still a nice thing to do.) Otherwise return The string so the // upper level code will know this is a full match and add the " ". - if (cur_opt_str && strlen(cur_opt_str) > 2 && cur_opt_str[0] == '-' && - cur_opt_str[1] == '-' && - strcmp(opt_defs[opt_defs_index].long_option, cur_opt_str) != 0) { - std::string full_name("--"); - full_name.append(opt_defs[opt_defs_index].long_option); - request.AddCompletion(full_name.c_str()); - return true; - } else { - request.AddCompletion(request.GetCursorArgument()); + const OptionDefinition &opt = opt_defs[opt_defs_index]; + llvm::StringRef long_option = opt.long_option; + if (cur_opt_str.startswith("--") && cur_opt_str != long_option) { + request.AddCompletion("--" + long_option.str(), opt.usage_text); return true; - } + } else + request.AddCompletion(request.GetCursorArgumentPrefix()); + return true; } else { // FIXME - not handling wrong options yet: // Check to see if they are writing a long option & complete it. @@ -713,18 +707,11 @@ bool Options::HandleOptionCompletion(CompletionRequest &request, // elements // that are not unique up to this point. getopt_long_only does // shortest unique match for long options already. - - if (cur_opt_str && strlen(cur_opt_str) > 2 && cur_opt_str[0] == '-' && - cur_opt_str[1] == '-') { + if (cur_opt_str.consume_front("--")) { for (auto &def : opt_defs) { - if (!def.long_option) - continue; - - if (strstr(def.long_option, cur_opt_str + 2) == def.long_option) { - std::string full_name("--"); - full_name.append(def.long_option); - request.AddCompletion(full_name.c_str()); - } + llvm::StringRef long_option(def.long_option); + if (long_option.startswith(cur_opt_str)) + request.AddCompletion("--" + long_option.str(), def.usage_text); } } return true; @@ -733,13 +720,9 @@ bool Options::HandleOptionCompletion(CompletionRequest &request, } else if (opt_arg_pos == request.GetCursorIndex()) { // Okay the cursor is on the completion of an argument. See if it has a // completion, otherwise return no matches. - - CompletionRequest subrequest = request; - subrequest.SetCursorCharPosition(subrequest.GetCursorArgument().size()); if (opt_defs_index != -1) { - HandleOptionArgumentCompletion(subrequest, opt_element_vector, i, + HandleOptionArgumentCompletion(request, opt_element_vector, i, interpreter); - request.SetWordComplete(subrequest.GetWordComplete()); return true; } else { // No completion callback means no completions... @@ -754,34 +737,20 @@ bool Options::HandleOptionCompletion(CompletionRequest &request, return false; } -bool Options::HandleOptionArgumentCompletion( +void Options::HandleOptionArgumentCompletion( CompletionRequest &request, OptionElementVector &opt_element_vector, int opt_element_index, CommandInterpreter &interpreter) { auto opt_defs = GetDefinitions(); std::unique_ptr<SearchFilter> filter_up; - int opt_arg_pos = opt_element_vector[opt_element_index].opt_arg_pos; int opt_defs_index = opt_element_vector[opt_element_index].opt_defs_index; // See if this is an enumeration type option, and if so complete it here: const auto &enum_values = opt_defs[opt_defs_index].enum_values; - if (!enum_values.empty()) { - bool return_value = false; - std::string match_string( - request.GetParsedLine().GetArgumentAtIndex(opt_arg_pos), - request.GetParsedLine().GetArgumentAtIndex(opt_arg_pos) + - request.GetCursorCharPosition()); - - for (const auto &enum_value : enum_values) { - if (strstr(enum_value.string_value, match_string.c_str()) == - enum_value.string_value) { - request.AddCompletion(enum_value.string_value); - return_value = true; - } - } - return return_value; - } + if (!enum_values.empty()) + for (const auto &enum_value : enum_values) + request.TryCompleteCurrentArg(enum_value.string_value); // If this is a source file or symbol type completion, and there is a -shlib // option somewhere in the supplied arguments, then make a search filter for @@ -836,7 +805,7 @@ bool Options::HandleOptionArgumentCompletion( } } - return CommandCompletions::InvokeCommonCompletionCallbacks( + CommandCompletions::InvokeCommonCompletionCallbacks( interpreter, completion_mask, request, filter_up.get()); } @@ -954,7 +923,7 @@ static Args ReconstituteArgsAfterParsing(llvm::ArrayRef<char *> parsed, for (const char *arg : parsed) { auto pos = FindOriginalIter(arg, original); assert(pos != original.end()); - result.AppendArgument(pos->ref, pos->quote); + result.AppendArgument(pos->ref(), pos->GetQuoteChar()); } return result; } @@ -965,8 +934,8 @@ static size_t FindArgumentIndexForOption(const Args &args, std::string long_opt = llvm::formatv("--{0}", long_option.definition->long_option); for (const auto &entry : llvm::enumerate(args)) { - if (entry.value().ref.startswith(short_opt) || - entry.value().ref.startswith(long_opt)) + if (entry.value().ref().startswith(short_opt) || + entry.value().ref().startswith(long_opt)) return entry.index(); } @@ -1105,7 +1074,7 @@ llvm::Expected<Args> Options::ParseAlias(const Args &args, continue; if (!input_line.empty()) { - auto tmp_arg = args_copy[idx].ref; + auto tmp_arg = args_copy[idx].ref(); size_t pos = input_line.find(tmp_arg); if (pos != std::string::npos) input_line.erase(pos, tmp_arg.size()); @@ -1115,9 +1084,9 @@ llvm::Expected<Args> Options::ParseAlias(const Args &args, OptionParser::eNoArgument) && (OptionParser::GetOptionArgument() != nullptr) && (idx < args_copy.GetArgumentCount()) && - (args_copy[idx].ref == OptionParser::GetOptionArgument())) { + (args_copy[idx].ref() == OptionParser::GetOptionArgument())) { if (input_line.size() > 0) { - auto tmp_arg = args_copy[idx].ref; + auto tmp_arg = args_copy[idx].ref(); size_t pos = input_line.find(tmp_arg); if (pos != std::string::npos) input_line.erase(pos, tmp_arg.size()); @@ -1308,7 +1277,7 @@ OptionElementVector Options::ParseForCompletion(const Args &args, const Args::ArgEntry &cursor = args[cursor_index]; if ((static_cast<int32_t>(dash_dash_pos) == -1 || cursor_index < dash_dash_pos) && - !cursor.IsQuoted() && cursor.ref == "-") { + !cursor.IsQuoted() && cursor.ref() == "-") { option_element_vector.push_back( OptionArgElement(OptionArgElement::eBareDash, cursor_index, OptionArgElement::eBareDash)); @@ -1411,6 +1380,10 @@ llvm::Expected<Args> Options::Parse(const Args &args, ? nullptr : OptionParser::GetOptionArgument(), execution_context); + // If the Option setting returned an error, we should stop parsing + // and return the error. + if (error.Fail()) + break; } else { error.SetErrorStringWithFormat("invalid option with value '%i'", val); } diff --git a/source/Plugins/ABI/MacOSX-arm/ABIMacOSX_arm.cpp b/source/Plugins/ABI/MacOSX-arm/ABIMacOSX_arm.cpp index 362a80be4b0d..9dff12bcc748 100644 --- a/source/Plugins/ABI/MacOSX-arm/ABIMacOSX_arm.cpp +++ b/source/Plugins/ABI/MacOSX-arm/ABIMacOSX_arm.cpp @@ -1326,7 +1326,8 @@ ABIMacOSX_arm::CreateInstance(ProcessSP process_sp, const ArchSpec &arch) { if (vendor_type == llvm::Triple::Apple) { if ((arch_type == llvm::Triple::arm) || (arch_type == llvm::Triple::thumb)) { - return ABISP(new ABIMacOSX_arm(process_sp)); + return ABISP( + new ABIMacOSX_arm(std::move(process_sp), MakeMCRegisterInfo(arch))); } } @@ -1846,6 +1847,7 @@ bool ABIMacOSX_arm::CreateDefaultUnwindPlan(UnwindPlan &unwind_plan) { unwind_plan.SetSourceName("arm-apple-ios default unwind plan"); unwind_plan.SetSourcedFromCompiler(eLazyBoolNo); unwind_plan.SetUnwindPlanValidAtAllInstructions(eLazyBoolNo); + unwind_plan.SetUnwindPlanForSignalTrap(eLazyBoolNo); return true; } diff --git a/source/Plugins/ABI/MacOSX-arm/ABIMacOSX_arm.h b/source/Plugins/ABI/MacOSX-arm/ABIMacOSX_arm.h index ac9ba00b9d91..e512651f86e5 100644 --- a/source/Plugins/ABI/MacOSX-arm/ABIMacOSX_arm.h +++ b/source/Plugins/ABI/MacOSX-arm/ABIMacOSX_arm.h @@ -85,7 +85,9 @@ protected: lldb_private::CompilerType &ast_type) const override; private: - ABIMacOSX_arm(lldb::ProcessSP process_sp) : lldb_private::ABI(process_sp) { + ABIMacOSX_arm(lldb::ProcessSP process_sp, + std::unique_ptr<llvm::MCRegisterInfo> info_up) + : lldb_private::ABI(std::move(process_sp), std::move(info_up)) { // Call CreateInstance instead. } }; diff --git a/source/Plugins/ABI/MacOSX-arm64/ABIMacOSX_arm64.cpp b/source/Plugins/ABI/MacOSX-arm64/ABIMacOSX_arm64.cpp index 368e37213249..6473ccf9a19a 100644 --- a/source/Plugins/ABI/MacOSX-arm64/ABIMacOSX_arm64.cpp +++ b/source/Plugins/ABI/MacOSX-arm64/ABIMacOSX_arm64.cpp @@ -1665,8 +1665,10 @@ ABIMacOSX_arm64::CreateInstance(ProcessSP process_sp, const ArchSpec &arch) { const llvm::Triple::VendorType vendor_type = arch.GetTriple().getVendor(); if (vendor_type == llvm::Triple::Apple) { - if (arch_type == llvm::Triple::aarch64) { - return ABISP(new ABIMacOSX_arm64(process_sp)); + if (arch_type == llvm::Triple::aarch64 || + arch_type == llvm::Triple::aarch64_32) { + return ABISP( + new ABIMacOSX_arm64(std::move(process_sp), MakeMCRegisterInfo(arch))); } } @@ -1710,9 +1712,8 @@ bool ABIMacOSX_arm64::PrepareTrivialCall( for (size_t i = 0; i < args.size(); ++i) { const RegisterInfo *reg_info = reg_ctx->GetRegisterInfo( eRegisterKindGeneric, LLDB_REGNUM_GENERIC_ARG1 + i); - if (log) - log->Printf("About to write arg%d (0x%" PRIx64 ") into %s", - static_cast<int>(i + 1), args[i], reg_info->name); + LLDB_LOGF(log, "About to write arg%d (0x%" PRIx64 ") into %s", + static_cast<int>(i + 1), args[i], reg_info->name); if (!reg_ctx->WriteRegisterFromUnsigned(reg_info, args[i])) return false; } @@ -2011,6 +2012,7 @@ bool ABIMacOSX_arm64::CreateDefaultUnwindPlan(UnwindPlan &unwind_plan) { unwind_plan.SetSourceName("arm64-apple-darwin default unwind plan"); unwind_plan.SetSourcedFromCompiler(eLazyBoolNo); unwind_plan.SetUnwindPlanValidAtAllInstructions(eLazyBoolNo); + unwind_plan.SetUnwindPlanForSignalTrap(eLazyBoolNo); return true; } diff --git a/source/Plugins/ABI/MacOSX-arm64/ABIMacOSX_arm64.h b/source/Plugins/ABI/MacOSX-arm64/ABIMacOSX_arm64.h index bfacbcd54a94..c7a91ba9c468 100644 --- a/source/Plugins/ABI/MacOSX-arm64/ABIMacOSX_arm64.h +++ b/source/Plugins/ABI/MacOSX-arm64/ABIMacOSX_arm64.h @@ -93,7 +93,9 @@ protected: lldb_private::CompilerType &ast_type) const override; private: - ABIMacOSX_arm64(lldb::ProcessSP process_sp) : lldb_private::ABI(process_sp) { + ABIMacOSX_arm64(lldb::ProcessSP process_sp, + std::unique_ptr<llvm::MCRegisterInfo> info_up) + : lldb_private::ABI(std::move(process_sp), std::move(info_up)) { // Call CreateInstance instead. } }; diff --git a/source/Plugins/ABI/MacOSX-i386/ABIMacOSX_i386.cpp b/source/Plugins/ABI/MacOSX-i386/ABIMacOSX_i386.cpp index 67371b432ff8..76ebd6476ffd 100644 --- a/source/Plugins/ABI/MacOSX-i386/ABIMacOSX_i386.cpp +++ b/source/Plugins/ABI/MacOSX-i386/ABIMacOSX_i386.cpp @@ -710,7 +710,8 @@ ABIMacOSX_i386::CreateInstance(lldb::ProcessSP process_sp, const ArchSpec &arch) if ((arch.GetTriple().getArch() == llvm::Triple::x86) && (arch.GetTriple().isMacOSX() || arch.GetTriple().isiOS() || arch.GetTriple().isWatchOS())) { - return ABISP(new ABIMacOSX_i386(process_sp)); + return ABISP( + new ABIMacOSX_i386(std::move(process_sp), MakeMCRegisterInfo(arch))); } return ABISP(); } @@ -1055,6 +1056,7 @@ bool ABIMacOSX_i386::CreateDefaultUnwindPlan(UnwindPlan &unwind_plan) { unwind_plan.SetSourceName("i386 default unwind plan"); unwind_plan.SetSourcedFromCompiler(eLazyBoolNo); unwind_plan.SetUnwindPlanValidAtAllInstructions(eLazyBoolNo); + unwind_plan.SetUnwindPlanForSignalTrap(eLazyBoolNo); return true; } diff --git a/source/Plugins/ABI/MacOSX-i386/ABIMacOSX_i386.h b/source/Plugins/ABI/MacOSX-i386/ABIMacOSX_i386.h index 57def683283f..50062b84d878 100644 --- a/source/Plugins/ABI/MacOSX-i386/ABIMacOSX_i386.h +++ b/source/Plugins/ABI/MacOSX-i386/ABIMacOSX_i386.h @@ -92,7 +92,9 @@ protected: bool RegisterIsCalleeSaved(const lldb_private::RegisterInfo *reg_info); private: - ABIMacOSX_i386(lldb::ProcessSP process_sp) : lldb_private::ABI(process_sp) { + ABIMacOSX_i386(lldb::ProcessSP process_sp, + std::unique_ptr<llvm::MCRegisterInfo> info_up) + : lldb_private::ABI(std::move(process_sp), std::move(info_up)) { // Call CreateInstance instead. } }; diff --git a/source/Plugins/ABI/SysV-arc/ABISysV_arc.cpp b/source/Plugins/ABI/SysV-arc/ABISysV_arc.cpp new file mode 100644 index 000000000000..715b5e5d2b95 --- /dev/null +++ b/source/Plugins/ABI/SysV-arc/ABISysV_arc.cpp @@ -0,0 +1,614 @@ +//===-- ABISysV_arc.cpp ---------------------------------------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#include "ABISysV_arc.h" + +// C Includes +// C++ Includes +#include <array> +#include <limits> +#include <type_traits> + +// Other libraries and framework includes +#include "llvm/ADT/Triple.h" +#include "llvm/IR/DerivedTypes.h" +#include "llvm/Support/MathExtras.h" + +#include "lldb/Core/Module.h" +#include "lldb/Core/PluginManager.h" +#include "lldb/Core/Value.h" +#include "lldb/Core/ValueObjectConstResult.h" +#include "lldb/Core/ValueObjectMemory.h" +#include "lldb/Core/ValueObjectRegister.h" +#include "lldb/Symbol/UnwindPlan.h" +#include "lldb/Target/Process.h" +#include "lldb/Target/RegisterContext.h" +#include "lldb/Target/StackFrame.h" +#include "lldb/Target/Target.h" +#include "lldb/Target/Thread.h" +#include "lldb/Utility/ConstString.h" +#include "lldb/Utility/RegisterValue.h" +#include "lldb/Utility/Status.h" + +#define DEFINE_REG_NAME(reg_num) ConstString(#reg_num).GetCString() +#define DEFINE_REG_NAME_STR(reg_name) ConstString(reg_name).GetCString() + +// The ABI is not a source of such information as size, offset, encoding, etc. +// of a register. Just provides correct dwarf and eh_frame numbers. + +#define DEFINE_GENERIC_REGISTER_STUB(dwarf_num, str_name, generic_num) \ + { \ + DEFINE_REG_NAME(dwarf_num), DEFINE_REG_NAME_STR(str_name), \ + 0, 0, eEncodingInvalid, eFormatDefault, \ + { dwarf_num, dwarf_num, generic_num, LLDB_INVALID_REGNUM, dwarf_num }, \ + nullptr, nullptr, nullptr, 0 \ + } + +#define DEFINE_REGISTER_STUB(dwarf_num, str_name) \ + DEFINE_GENERIC_REGISTER_STUB(dwarf_num, str_name, LLDB_INVALID_REGNUM) + +using namespace lldb; +using namespace lldb_private; + +namespace { +namespace dwarf { +enum regnums { + r0, r1, r2, r3, r4, r5, r6, r7, r8, r9, r10, r11, r12, r13, r14, r15, r16, + r17, r18, r19, r20, r21, r22, r23, r24, r25, r26, + r27, fp = r27, r28, sp = r28, r29, r30, r31, blink = r31, + r32, r33, r34, r35, r36, r37, r38, r39, r40, r41, r42, r43, r44, r45, r46, + r47, r48, r49, r50, r51, r52, r53, r54, r55, r56, r57, r58, r59, r60, + /*reserved,*/ /*limm indicator,*/ r63 = 63, pc = 70, status32 = 74 +}; + +static const std::array<RegisterInfo, 64> g_register_infos = { { + DEFINE_GENERIC_REGISTER_STUB(r0, nullptr, LLDB_REGNUM_GENERIC_ARG1), + DEFINE_GENERIC_REGISTER_STUB(r1, nullptr, LLDB_REGNUM_GENERIC_ARG2), + DEFINE_GENERIC_REGISTER_STUB(r2, nullptr, LLDB_REGNUM_GENERIC_ARG3), + DEFINE_GENERIC_REGISTER_STUB(r3, nullptr, LLDB_REGNUM_GENERIC_ARG4), + DEFINE_GENERIC_REGISTER_STUB(r4, nullptr, LLDB_REGNUM_GENERIC_ARG5), + DEFINE_GENERIC_REGISTER_STUB(r5, nullptr, LLDB_REGNUM_GENERIC_ARG6), + DEFINE_GENERIC_REGISTER_STUB(r6, nullptr, LLDB_REGNUM_GENERIC_ARG7), + DEFINE_GENERIC_REGISTER_STUB(r7, nullptr, LLDB_REGNUM_GENERIC_ARG8), + DEFINE_REGISTER_STUB(r8, nullptr), + DEFINE_REGISTER_STUB(r9, nullptr), + DEFINE_REGISTER_STUB(r10, nullptr), + DEFINE_REGISTER_STUB(r11, nullptr), + DEFINE_REGISTER_STUB(r12, nullptr), + DEFINE_REGISTER_STUB(r13, nullptr), + DEFINE_REGISTER_STUB(r14, nullptr), + DEFINE_REGISTER_STUB(r15, nullptr), + DEFINE_REGISTER_STUB(r16, nullptr), + DEFINE_REGISTER_STUB(r17, nullptr), + DEFINE_REGISTER_STUB(r18, nullptr), + DEFINE_REGISTER_STUB(r19, nullptr), + DEFINE_REGISTER_STUB(r20, nullptr), + DEFINE_REGISTER_STUB(r21, nullptr), + DEFINE_REGISTER_STUB(r22, nullptr), + DEFINE_REGISTER_STUB(r23, nullptr), + DEFINE_REGISTER_STUB(r24, nullptr), + DEFINE_REGISTER_STUB(r25, nullptr), + DEFINE_REGISTER_STUB(r26, "gp"), + DEFINE_GENERIC_REGISTER_STUB(r27, "fp", LLDB_REGNUM_GENERIC_FP), + DEFINE_GENERIC_REGISTER_STUB(r28, "sp", LLDB_REGNUM_GENERIC_SP), + DEFINE_REGISTER_STUB(r29, "ilink"), + DEFINE_REGISTER_STUB(r30, nullptr), + DEFINE_GENERIC_REGISTER_STUB(r31, "blink", LLDB_REGNUM_GENERIC_RA), + DEFINE_REGISTER_STUB(r32, nullptr), + DEFINE_REGISTER_STUB(r33, nullptr), + DEFINE_REGISTER_STUB(r34, nullptr), + DEFINE_REGISTER_STUB(r35, nullptr), + DEFINE_REGISTER_STUB(r36, nullptr), + DEFINE_REGISTER_STUB(r37, nullptr), + DEFINE_REGISTER_STUB(r38, nullptr), + DEFINE_REGISTER_STUB(r39, nullptr), + DEFINE_REGISTER_STUB(r40, nullptr), + DEFINE_REGISTER_STUB(r41, nullptr), + DEFINE_REGISTER_STUB(r42, nullptr), + DEFINE_REGISTER_STUB(r43, nullptr), + DEFINE_REGISTER_STUB(r44, nullptr), + DEFINE_REGISTER_STUB(r45, nullptr), + DEFINE_REGISTER_STUB(r46, nullptr), + DEFINE_REGISTER_STUB(r47, nullptr), + DEFINE_REGISTER_STUB(r48, nullptr), + DEFINE_REGISTER_STUB(r49, nullptr), + DEFINE_REGISTER_STUB(r50, nullptr), + DEFINE_REGISTER_STUB(r51, nullptr), + DEFINE_REGISTER_STUB(r52, nullptr), + DEFINE_REGISTER_STUB(r53, nullptr), + DEFINE_REGISTER_STUB(r54, nullptr), + DEFINE_REGISTER_STUB(r55, nullptr), + DEFINE_REGISTER_STUB(r56, nullptr), + DEFINE_REGISTER_STUB(r57, nullptr), + DEFINE_REGISTER_STUB(r58, "accl"), + DEFINE_REGISTER_STUB(r59, "acch"), + DEFINE_REGISTER_STUB(r60, "lp_count"), + DEFINE_REGISTER_STUB(r63, "pcl"), + DEFINE_GENERIC_REGISTER_STUB(pc, nullptr, LLDB_REGNUM_GENERIC_PC), + DEFINE_GENERIC_REGISTER_STUB(status32, nullptr, LLDB_REGNUM_GENERIC_FLAGS)} }; +} // namespace dwarf +} // namespace + +const RegisterInfo *ABISysV_arc::GetRegisterInfoArray(uint32_t &count) { + count = dwarf::g_register_infos.size(); + return dwarf::g_register_infos.data(); +} + +size_t ABISysV_arc::GetRedZoneSize() const { return 0; } + +bool ABISysV_arc::IsRegisterFileReduced(RegisterContext ®_ctx) const { + if (!m_is_reg_file_reduced) { + const auto *const rf_build_reg = reg_ctx.GetRegisterInfoByName("rf_build"); + + const auto reg_value = reg_ctx.ReadRegisterAsUnsigned(rf_build_reg, + /*fail_value*/ 0); + // RF_BUILD "Number of Entries" bit. + const uint32_t rf_entries_bit = 1U << 9U; + m_is_reg_file_reduced = (reg_value | rf_entries_bit) != 0; + } + + return m_is_reg_file_reduced.getValueOr(false); +} + +//------------------------------------------------------------------ +// Static Functions +//------------------------------------------------------------------ + +ABISP ABISysV_arc::CreateInstance(ProcessSP process_sp, const ArchSpec &arch) { + return llvm::Triple::arc == arch.GetTriple().getArch() ? + ABISP(new ABISysV_arc(std::move(process_sp), MakeMCRegisterInfo(arch))) : + ABISP(); +} + +namespace { +const size_t word_size = 4U; +const size_t reg_size = word_size; + +inline size_t AugmentArgSize(size_t size_in_bytes) { + return llvm::alignTo(size_in_bytes, word_size); +} + +size_t TotalArgsSizeInWords(const llvm::ArrayRef<ABI::CallArgument> &args) { + size_t total_size = 0; + for (const auto &arg : args) + total_size += + (ABI::CallArgument::TargetValue == arg.type ? AugmentArgSize(arg.size) + : reg_size) / + word_size; + + return total_size; +} +} // namespace + +bool ABISysV_arc::PrepareTrivialCall(Thread &thread, addr_t sp, + addr_t func_addr, addr_t return_addr, + llvm::ArrayRef<addr_t> args) const { + // We don't use the traditional trivial call specialized for jit. + return false; +} + +bool ABISysV_arc::PrepareTrivialCall(Thread &thread, addr_t sp, addr_t pc, + addr_t ra, llvm::Type &prototype, + llvm::ArrayRef<ABI::CallArgument> args) const { + auto reg_ctx = thread.GetRegisterContext(); + if (!reg_ctx) + return false; + + uint32_t pc_reg = reg_ctx->ConvertRegisterKindToRegisterNumber( + eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC); + if (pc_reg == LLDB_INVALID_REGNUM) + return false; + + uint32_t ra_reg = reg_ctx->ConvertRegisterKindToRegisterNumber( + eRegisterKindGeneric, LLDB_REGNUM_GENERIC_RA); + if (ra_reg == LLDB_INVALID_REGNUM) + return false; + + uint32_t sp_reg = reg_ctx->ConvertRegisterKindToRegisterNumber( + eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP); + if (sp_reg == LLDB_INVALID_REGNUM) + return false; + + Status error; + ProcessSP process = thread.GetProcess(); + if (!process) + return false; + + // Push host data onto target. + for (const auto &arg : args) { + // Skip over target values. + if (arg.type == ABI::CallArgument::TargetValue) + continue; + + // Create space on the stack for this data 4-byte aligned. + sp -= AugmentArgSize(arg.size); + + if (process->WriteMemory(sp, arg.data_up.get(), arg.size, error) < arg.size + || error.Fail()) + return false; + + // Update the argument with the target pointer. + *const_cast<addr_t *>(&arg.value) = sp; + } + + // Make sure number of parameters matches prototype. + assert(!prototype.isFunctionVarArg()); + assert(prototype.getFunctionNumParams() == args.size()); + + const size_t regs_for_args_count = IsRegisterFileReduced(*reg_ctx) ? 4U : 8U; + + // Number of arguments passed on stack. + auto args_size = TotalArgsSizeInWords(args); + auto on_stack = + args_size <= regs_for_args_count ? 0 : args_size - regs_for_args_count; + auto offset = on_stack * word_size; + + uint8_t reg_value[reg_size]; + size_t reg_index = LLDB_REGNUM_GENERIC_ARG1; + + for (const auto &arg : args) { + auto value = reinterpret_cast<const uint8_t *>(&arg.value); + auto size = + ABI::CallArgument::TargetValue == arg.type ? arg.size : reg_size; + + // Pass arguments via registers. + while (size > 0 && reg_index < regs_for_args_count) { + size_t byte_index = 0; + auto end = size < reg_size ? size : reg_size; + + while (byte_index < end) { + reg_value[byte_index++] = *(value++); + --size; + } + + while (byte_index < reg_size) { + reg_value[byte_index++] = 0; + } + + RegisterValue reg_val_obj(reg_value, reg_size, eByteOrderLittle); + if (!reg_ctx->WriteRegister( + reg_ctx->GetRegisterInfo(eRegisterKindGeneric, reg_index), + reg_val_obj)) + return false; + + // NOTE: It's unsafe to iterate through LLDB_REGNUM_GENERICs. + ++reg_index; + } + + if (reg_index < regs_for_args_count || size == 0) + continue; + + // Remaining arguments are passed on the stack. + if (process->WriteMemory(sp - offset, value, size, error) < size || + !error.Success()) + return false; + + offset -= AugmentArgSize(size); + } + + // Set stack pointer immediately below arguments. + sp -= on_stack * word_size; + + // Update registers with current function call state. + reg_ctx->WriteRegisterFromUnsigned(pc_reg, pc); + reg_ctx->WriteRegisterFromUnsigned(ra_reg, ra); + reg_ctx->WriteRegisterFromUnsigned(sp_reg, sp); + + return true; +} + +bool ABISysV_arc::GetArgumentValues(Thread &thread, ValueList &values) const { + return false; +} + +Status ABISysV_arc::SetReturnValueObject(StackFrameSP &frame_sp, + ValueObjectSP &new_value_sp) { + Status result; + if (!new_value_sp) { + result.SetErrorString("Empty value object for return value."); + return result; + } + + CompilerType compiler_type = new_value_sp->GetCompilerType(); + if (!compiler_type) { + result.SetErrorString("Null clang type for return value."); + return result; + } + + auto ®_ctx = *frame_sp->GetThread()->GetRegisterContext(); + + bool is_signed = false; + if (!compiler_type.IsIntegerOrEnumerationType(is_signed) && + !compiler_type.IsPointerType()) { + result.SetErrorString("We don't support returning other types at present"); + return result; + } + + DataExtractor data; + size_t num_bytes = new_value_sp->GetData(data, result); + + if (result.Fail()) { + result.SetErrorStringWithFormat( + "Couldn't convert return value to raw data: %s", result.AsCString()); + return result; + } + + if (num_bytes <= 2 * reg_size) { + offset_t offset = 0; + uint64_t raw_value = data.GetMaxU64(&offset, num_bytes); + + auto reg_info = + reg_ctx.GetRegisterInfo(eRegisterKindGeneric, LLDB_REGNUM_GENERIC_ARG1); + if (!reg_ctx.WriteRegisterFromUnsigned(reg_info, raw_value)) { + result.SetErrorStringWithFormat("Couldn't write value to register %s", + reg_info->name); + return result; + } + + if (num_bytes <= reg_size) + return result; // Successfully written. + + raw_value >>= 32; + reg_info = + reg_ctx.GetRegisterInfo(eRegisterKindGeneric, LLDB_REGNUM_GENERIC_ARG2); + if (!reg_ctx.WriteRegisterFromUnsigned(reg_info, raw_value)) { + result.SetErrorStringWithFormat("Couldn't write value to register %s", + reg_info->name); + } + + return result; + } + + result.SetErrorString( + "We don't support returning large integer values at present."); + return result; +} + +namespace { +template <typename T> +void SetInteger(Scalar &scalar, uint64_t raw_value, bool is_signed) { + raw_value &= std::numeric_limits<T>::max(); + if (is_signed) + scalar = static_cast<typename std::make_signed<T>::type>(raw_value); + else + scalar = static_cast<T>(raw_value); +} + +bool SetSizedInteger(Scalar &scalar, uint64_t raw_value, uint8_t size_in_bytes, + bool is_signed) { + switch (size_in_bytes) { + default: + return false; + + case sizeof(uint64_t): + SetInteger<uint64_t>(scalar, raw_value, is_signed); + break; + + case sizeof(uint32_t): + SetInteger<uint32_t>(scalar, raw_value, is_signed); + break; + + case sizeof(uint16_t): + SetInteger<uint16_t>(scalar, raw_value, is_signed); + break; + + case sizeof(uint8_t): + SetInteger<uint8_t>(scalar, raw_value, is_signed); + break; + } + + return true; +} + +bool SetSizedFloat(Scalar &scalar, uint64_t raw_value, uint8_t size_in_bytes) { + switch (size_in_bytes) { + default: + return false; + + case sizeof(uint64_t): + scalar = *reinterpret_cast<double *>(&raw_value); + break; + + case sizeof(uint32_t): + scalar = *reinterpret_cast<float *>(&raw_value); + break; + } + + return true; +} + +uint64_t ReadRawValue(const RegisterContextSP ®_ctx, uint8_t size_in_bytes) { + auto reg_info_r0 = + reg_ctx->GetRegisterInfo(eRegisterKindGeneric, LLDB_REGNUM_GENERIC_ARG1); + + // Extract the register context so we can read arguments from registers. + uint64_t raw_value = + reg_ctx->ReadRegisterAsUnsigned(reg_info_r0, 0) & UINT32_MAX; + + if (sizeof(uint64_t) == size_in_bytes) + raw_value |= (reg_ctx->ReadRegisterAsUnsigned( + reg_ctx->GetRegisterInfo(eRegisterKindGeneric, + LLDB_REGNUM_GENERIC_ARG2), 0) & + UINT64_MAX) << 32U; + + return raw_value; +} +} // namespace + +ValueObjectSP +ABISysV_arc::GetReturnValueObjectSimple(Thread &thread, + CompilerType &compiler_type) const { + if (!compiler_type) + return ValueObjectSP(); + + auto reg_ctx = thread.GetRegisterContext(); + if (!reg_ctx) + return ValueObjectSP(); + + Value value; + value.SetCompilerType(compiler_type); + + const uint32_t type_flags = compiler_type.GetTypeInfo(); + // Integer return type. + if (type_flags & eTypeIsInteger) { + const size_t byte_size = compiler_type.GetByteSize(nullptr).getValueOr(0); + auto raw_value = ReadRawValue(reg_ctx, byte_size); + + const bool is_signed = (type_flags & eTypeIsSigned) != 0; + if (!SetSizedInteger(value.GetScalar(), raw_value, byte_size, is_signed)) + return ValueObjectSP(); + + value.SetValueType(Value::eValueTypeScalar); + } + // Pointer return type. + else if (type_flags & eTypeIsPointer) { + auto reg_info_r0 = reg_ctx->GetRegisterInfo(eRegisterKindGeneric, + LLDB_REGNUM_GENERIC_ARG1); + value.GetScalar() = reg_ctx->ReadRegisterAsUnsigned(reg_info_r0, 0); + + value.SetValueType(Value::eValueTypeScalar); + } + // Floating point return type. + else if (type_flags & eTypeIsFloat) { + uint32_t float_count = 0; + bool is_complex = false; + + if (compiler_type.IsFloatingPointType(float_count, is_complex) && + 1 == float_count && !is_complex) { + const size_t byte_size = compiler_type.GetByteSize(nullptr).getValueOr(0); + auto raw_value = ReadRawValue(reg_ctx, byte_size); + + if (!SetSizedFloat(value.GetScalar(), raw_value, byte_size)) + return ValueObjectSP(); + } + } + // Unsupported return type. + else + return ValueObjectSP(); + + return ValueObjectConstResult::Create(thread.GetStackFrameAtIndex(0).get(), + value, ConstString("")); +} + +ValueObjectSP ABISysV_arc::GetReturnValueObjectImpl( + Thread &thread, CompilerType &return_compiler_type) const { + ValueObjectSP return_valobj_sp; + + if (!return_compiler_type) + return return_valobj_sp; + + ExecutionContext exe_ctx(thread.shared_from_this()); + return GetReturnValueObjectSimple(thread, return_compiler_type); +} + +ValueObjectSP ABISysV_arc::GetReturnValueObjectImpl(Thread &thread, + llvm::Type &retType) const { + auto reg_ctx = thread.GetRegisterContext(); + if (!reg_ctx) + return ValueObjectSP(); + + Value value; + // Void return type. + if (retType.isVoidTy()) { + value.GetScalar() = 0; + } + // Integer return type. + else if (retType.isIntegerTy()) { + size_t byte_size = retType.getPrimitiveSizeInBits(); + if (1 != byte_size) // For boolian type. + byte_size /= CHAR_BIT; + + auto raw_value = ReadRawValue(reg_ctx, byte_size); + + const bool is_signed = false; // IR Type doesn't provide this info. + if (!SetSizedInteger(value.GetScalar(), raw_value, byte_size, is_signed)) + return ValueObjectSP(); + } + // Pointer return type. + else if (retType.isPointerTy()) { + auto reg_info_r0 = reg_ctx->GetRegisterInfo(eRegisterKindGeneric, + LLDB_REGNUM_GENERIC_ARG1); + value.GetScalar() = reg_ctx->ReadRegisterAsUnsigned(reg_info_r0, 0); + value.SetValueType(Value::eValueTypeScalar); + } + // Floating point return type. + else if (retType.isFloatingPointTy()) { + const size_t byte_size = retType.getPrimitiveSizeInBits() / CHAR_BIT; + auto raw_value = ReadRawValue(reg_ctx, byte_size); + + if (!SetSizedFloat(value.GetScalar(), raw_value, byte_size)) + return ValueObjectSP(); + } + // Unsupported return type. + else + return ValueObjectSP(); + + return ValueObjectConstResult::Create(thread.GetStackFrameAtIndex(0).get(), + value, ConstString("")); +} + +bool ABISysV_arc::CreateFunctionEntryUnwindPlan(UnwindPlan &unwind_plan) { + unwind_plan.Clear(); + unwind_plan.SetRegisterKind(eRegisterKindDWARF); + + UnwindPlan::RowSP row(new UnwindPlan::Row); + + // Our Call Frame Address is the stack pointer value. + row->GetCFAValue().SetIsRegisterPlusOffset(dwarf::sp, 0); + + // The previous PC is in the BLINK. + row->SetRegisterLocationToRegister(dwarf::pc, dwarf::blink, true); + unwind_plan.AppendRow(row); + + // All other registers are the same. + unwind_plan.SetSourceName("arc at-func-entry default"); + unwind_plan.SetSourcedFromCompiler(eLazyBoolNo); + + return true; +} + +bool ABISysV_arc::CreateDefaultUnwindPlan(UnwindPlan &unwind_plan) { + return false; +} + +bool ABISysV_arc::RegisterIsVolatile(const RegisterInfo *reg_info) { + if (nullptr == reg_info) + return false; + + // Volatile registers are: r0..r12. + uint32_t regnum = reg_info->kinds[eRegisterKindDWARF]; + if (regnum <= 12) + return true; + + static const std::string ra_reg_name = "blink"; + return ra_reg_name == reg_info->name; +} + +void ABISysV_arc::Initialize() { + PluginManager::RegisterPlugin(GetPluginNameStatic(), + "System V ABI for ARC targets", CreateInstance); +} + +void ABISysV_arc::Terminate() { + PluginManager::UnregisterPlugin(CreateInstance); +} + +ConstString ABISysV_arc::GetPluginNameStatic() { + static ConstString g_name("sysv-arc"); + return g_name; +} + +//------------------------------------------------------------------ +// PluginInterface protocol +//------------------------------------------------------------------ + +ConstString ABISysV_arc::GetPluginName() { + return GetPluginNameStatic(); +} + +uint32_t ABISysV_arc::GetPluginVersion() { return 1; } diff --git a/source/Plugins/ABI/SysV-arc/ABISysV_arc.h b/source/Plugins/ABI/SysV-arc/ABISysV_arc.h new file mode 100644 index 000000000000..c4b26a54158c --- /dev/null +++ b/source/Plugins/ABI/SysV-arc/ABISysV_arc.h @@ -0,0 +1,106 @@ +//===-- ArchitectureArc.h ---------------------------------------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef liblldb_ABISysV_arc_h_ +#define liblldb_ABISysV_arc_h_ + +// Other libraries and framework includes +#include <llvm/ADT/Optional.h> + +// Project includes +#include "lldb/Target/ABI.h" +#include "lldb/lldb-private.h" + +class ABISysV_arc : public lldb_private::ABI { +public: + ~ABISysV_arc() override = default; + + size_t GetRedZoneSize() const override; + + bool PrepareTrivialCall(lldb_private::Thread &thread, lldb::addr_t sp, + lldb::addr_t functionAddress, + lldb::addr_t returnAddress, + llvm::ArrayRef<lldb::addr_t> args) const override; + + // Special thread plan for GDB style non-jit function calls. + bool + PrepareTrivialCall(lldb_private::Thread &thread, lldb::addr_t sp, + lldb::addr_t functionAddress, lldb::addr_t returnAddress, + llvm::Type &prototype, + llvm::ArrayRef<ABI::CallArgument> args) const override; + + bool GetArgumentValues(lldb_private::Thread &thread, + lldb_private::ValueList &values) const override; + + lldb_private::Status + SetReturnValueObject(lldb::StackFrameSP &frame_sp, + lldb::ValueObjectSP &new_value) override; + + lldb::ValueObjectSP + GetReturnValueObjectImpl(lldb_private::Thread &thread, + lldb_private::CompilerType &type) const override; + + // Specialized to work with llvm IR types. + lldb::ValueObjectSP GetReturnValueObjectImpl(lldb_private::Thread &thread, + llvm::Type &type) const override; + + bool + CreateFunctionEntryUnwindPlan(lldb_private::UnwindPlan &unwind_plan) override; + + bool CreateDefaultUnwindPlan(lldb_private::UnwindPlan &unwind_plan) override; + + bool RegisterIsVolatile(const lldb_private::RegisterInfo *reg_info) override; + + bool CallFrameAddressIsValid(lldb::addr_t cfa) override { + // Stack call frame address must be 4 byte aligned. + return (cfa & 0x3ull) == 0; + } + + bool CodeAddressIsValid(lldb::addr_t pc) override { + // Code addresse must be 2 byte aligned. + return (pc & 1ull) == 0; + } + + const lldb_private::RegisterInfo * + GetRegisterInfoArray(uint32_t &count) override; + + //------------------------------------------------------------------ + // Static Functions + //------------------------------------------------------------------ + + static void Initialize(); + + static void Terminate(); + + static lldb::ABISP CreateInstance(lldb::ProcessSP process_sp, + const lldb_private::ArchSpec &arch); + + static lldb_private::ConstString GetPluginNameStatic(); + + //------------------------------------------------------------------ + // PluginInterface protocol + //------------------------------------------------------------------ + + lldb_private::ConstString GetPluginName() override; + + uint32_t GetPluginVersion() override; + +private: + lldb::ValueObjectSP + GetReturnValueObjectSimple(lldb_private::Thread &thread, + lldb_private::CompilerType &ast_type) const; + + bool IsRegisterFileReduced(lldb_private::RegisterContext ®_ctx) const; + + using lldb_private::ABI::ABI; // Call CreateInstance instead. + + using RegisterFileFlag = llvm::Optional<bool>; + mutable RegisterFileFlag m_is_reg_file_reduced; +}; + +#endif // liblldb_ABISysV_arc_h_ diff --git a/source/Plugins/ABI/SysV-arc/CMakeLists.txt b/source/Plugins/ABI/SysV-arc/CMakeLists.txt new file mode 100644 index 000000000000..3dc0d1c65b46 --- /dev/null +++ b/source/Plugins/ABI/SysV-arc/CMakeLists.txt @@ -0,0 +1,11 @@ +add_lldb_library(lldbPluginABISysV_arc PLUGIN + ABISysV_arc.cpp + + LINK_LIBS + lldbCore + lldbSymbol + lldbTarget + lldbPluginProcessUtility + LINK_COMPONENTS + Support + ) diff --git a/source/Plugins/ABI/SysV-arm/ABISysV_arm.cpp b/source/Plugins/ABI/SysV-arm/ABISysV_arm.cpp index dd47ac7cbe3c..b6e8f8806829 100644 --- a/source/Plugins/ABI/SysV-arm/ABISysV_arm.cpp +++ b/source/Plugins/ABI/SysV-arm/ABISysV_arm.cpp @@ -1327,7 +1327,8 @@ ABISysV_arm::CreateInstance(lldb::ProcessSP process_sp, const ArchSpec &arch) { if (vendor_type != llvm::Triple::Apple) { if ((arch_type == llvm::Triple::arm) || (arch_type == llvm::Triple::thumb)) { - return ABISP(new ABISysV_arm(process_sp)); + return ABISP( + new ABISysV_arm(std::move(process_sp), MakeMCRegisterInfo(arch))); } } @@ -1960,6 +1961,7 @@ bool ABISysV_arm::CreateDefaultUnwindPlan(UnwindPlan &unwind_plan) { unwind_plan.SetSourceName("arm default unwind plan"); unwind_plan.SetSourcedFromCompiler(eLazyBoolNo); unwind_plan.SetUnwindPlanValidAtAllInstructions(eLazyBoolNo); + unwind_plan.SetUnwindPlanForSignalTrap(eLazyBoolNo); return true; } diff --git a/source/Plugins/ABI/SysV-arm/ABISysV_arm.h b/source/Plugins/ABI/SysV-arm/ABISysV_arm.h index a0f00c8f227d..60fb14be5f7b 100644 --- a/source/Plugins/ABI/SysV-arm/ABISysV_arm.h +++ b/source/Plugins/ABI/SysV-arm/ABISysV_arm.h @@ -85,7 +85,9 @@ protected: lldb_private::CompilerType &ast_type) const override; private: - ABISysV_arm(lldb::ProcessSP process_sp) : lldb_private::ABI(process_sp) { + ABISysV_arm(lldb::ProcessSP process_sp, + std::unique_ptr<llvm::MCRegisterInfo> info_up) + : lldb_private::ABI(std::move(process_sp), std::move(info_up)) { // Call CreateInstance instead. } }; diff --git a/source/Plugins/ABI/SysV-arm64/ABISysV_arm64.cpp b/source/Plugins/ABI/SysV-arm64/ABISysV_arm64.cpp index 1d547121e231..89a1f2b3cf04 100644 --- a/source/Plugins/ABI/SysV-arm64/ABISysV_arm64.cpp +++ b/source/Plugins/ABI/SysV-arm64/ABISysV_arm64.cpp @@ -1668,8 +1668,10 @@ ABISysV_arm64::CreateInstance(lldb::ProcessSP process_sp, const ArchSpec &arch) const llvm::Triple::VendorType vendor_type = arch.GetTriple().getVendor(); if (vendor_type != llvm::Triple::Apple) { - if (arch_type == llvm::Triple::aarch64) { - return ABISP(new ABISysV_arm64(process_sp)); + if (arch_type == llvm::Triple::aarch64 || + arch_type == llvm::Triple::aarch64_32) { + return ABISP( + new ABISysV_arm64(std::move(process_sp), MakeMCRegisterInfo(arch))); } } @@ -1706,9 +1708,8 @@ bool ABISysV_arm64::PrepareTrivialCall(Thread &thread, addr_t sp, for (size_t i = 0; i < args.size(); ++i) { const RegisterInfo *reg_info = reg_ctx->GetRegisterInfo( eRegisterKindGeneric, LLDB_REGNUM_GENERIC_ARG1 + i); - if (log) - log->Printf("About to write arg%d (0x%" PRIx64 ") into %s", - static_cast<int>(i + 1), args[i], reg_info->name); + LLDB_LOGF(log, "About to write arg%d (0x%" PRIx64 ") into %s", + static_cast<int>(i + 1), args[i], reg_info->name); if (!reg_ctx->WriteRegisterFromUnsigned(reg_info, args[i])) return false; } @@ -1958,6 +1959,7 @@ bool ABISysV_arm64::CreateFunctionEntryUnwindPlan(UnwindPlan &unwind_plan) { unwind_plan.SetSourceName("arm64 at-func-entry default"); unwind_plan.SetSourcedFromCompiler(eLazyBoolNo); unwind_plan.SetUnwindPlanValidAtAllInstructions(eLazyBoolNo); + unwind_plan.SetUnwindPlanForSignalTrap(eLazyBoolNo); return true; } @@ -1982,6 +1984,7 @@ bool ABISysV_arm64::CreateDefaultUnwindPlan(UnwindPlan &unwind_plan) { unwind_plan.SetSourceName("arm64 default unwind plan"); unwind_plan.SetSourcedFromCompiler(eLazyBoolNo); unwind_plan.SetUnwindPlanValidAtAllInstructions(eLazyBoolNo); + unwind_plan.SetUnwindPlanForSignalTrap(eLazyBoolNo); return true; } diff --git a/source/Plugins/ABI/SysV-arm64/ABISysV_arm64.h b/source/Plugins/ABI/SysV-arm64/ABISysV_arm64.h index 1fbdc793ed6e..1bf5773e2db3 100644 --- a/source/Plugins/ABI/SysV-arm64/ABISysV_arm64.h +++ b/source/Plugins/ABI/SysV-arm64/ABISysV_arm64.h @@ -92,7 +92,9 @@ protected: lldb_private::CompilerType &ast_type) const override; private: - ABISysV_arm64(lldb::ProcessSP process_sp) : lldb_private::ABI(process_sp) { + ABISysV_arm64(lldb::ProcessSP process_sp, + std::unique_ptr<llvm::MCRegisterInfo> info_up) + : lldb_private::ABI(std::move(process_sp), std::move(info_up)) { // Call CreateInstance instead. } }; diff --git a/source/Plugins/ABI/SysV-hexagon/ABISysV_hexagon.cpp b/source/Plugins/ABI/SysV-hexagon/ABISysV_hexagon.cpp index 93647564fe25..34d9258ccb92 100644 --- a/source/Plugins/ABI/SysV-hexagon/ABISysV_hexagon.cpp +++ b/source/Plugins/ABI/SysV-hexagon/ABISysV_hexagon.cpp @@ -1014,7 +1014,8 @@ size_t ABISysV_hexagon::GetRedZoneSize() const { return 0; } ABISP ABISysV_hexagon::CreateInstance(lldb::ProcessSP process_sp, const ArchSpec &arch) { if (arch.GetTriple().getArch() == llvm::Triple::hexagon) { - return ABISP(new ABISysV_hexagon(process_sp)); + return ABISP( + new ABISysV_hexagon(std::move(process_sp), MakeMCRegisterInfo(arch))); } return ABISP(); } @@ -1247,6 +1248,7 @@ bool ABISysV_hexagon::CreateDefaultUnwindPlan(UnwindPlan &unwind_plan) { unwind_plan.SetSourceName("hexagon default unwind plan"); unwind_plan.SetSourcedFromCompiler(eLazyBoolNo); unwind_plan.SetUnwindPlanValidAtAllInstructions(eLazyBoolNo); + unwind_plan.SetUnwindPlanForSignalTrap(eLazyBoolNo); return true; } diff --git a/source/Plugins/ABI/SysV-hexagon/ABISysV_hexagon.h b/source/Plugins/ABI/SysV-hexagon/ABISysV_hexagon.h index 459b6315dba2..bef64a22d95f 100644 --- a/source/Plugins/ABI/SysV-hexagon/ABISysV_hexagon.h +++ b/source/Plugins/ABI/SysV-hexagon/ABISysV_hexagon.h @@ -97,7 +97,9 @@ protected: bool RegisterIsCalleeSaved(const lldb_private::RegisterInfo *reg_info); private: - ABISysV_hexagon(lldb::ProcessSP process_sp) : lldb_private::ABI(process_sp) { + ABISysV_hexagon(lldb::ProcessSP process_sp, + std::unique_ptr<llvm::MCRegisterInfo> info_up) + : lldb_private::ABI(std::move(process_sp), std::move(info_up)) { // Call CreateInstance instead. } }; diff --git a/source/Plugins/ABI/SysV-i386/ABISysV_i386.cpp b/source/Plugins/ABI/SysV-i386/ABISysV_i386.cpp index 05f5dba90687..69e4cff90ebf 100644 --- a/source/Plugins/ABI/SysV-i386/ABISysV_i386.cpp +++ b/source/Plugins/ABI/SysV-i386/ABISysV_i386.cpp @@ -198,7 +198,8 @@ ABISP ABISysV_i386::CreateInstance(lldb::ProcessSP process_sp, const ArchSpec &arch) { if (arch.GetTriple().getVendor() != llvm::Triple::Apple) { if (arch.GetTriple().getArch() == llvm::Triple::x86) { - return ABISP(new ABISysV_i386(process_sp)); + return ABISP( + new ABISysV_i386(std::move(process_sp), MakeMCRegisterInfo(arch))); } } return ABISP(); @@ -785,6 +786,7 @@ bool ABISysV_i386::CreateDefaultUnwindPlan(UnwindPlan &unwind_plan) { unwind_plan.SetSourceName("i386 default unwind plan"); unwind_plan.SetSourcedFromCompiler(eLazyBoolNo); unwind_plan.SetUnwindPlanValidAtAllInstructions(eLazyBoolNo); + unwind_plan.SetUnwindPlanForSignalTrap(eLazyBoolNo); return true; } diff --git a/source/Plugins/ABI/SysV-i386/ABISysV_i386.h b/source/Plugins/ABI/SysV-i386/ABISysV_i386.h index 982bdd676b74..2362e9adda98 100644 --- a/source/Plugins/ABI/SysV-i386/ABISysV_i386.h +++ b/source/Plugins/ABI/SysV-i386/ABISysV_i386.h @@ -100,7 +100,9 @@ protected: bool RegisterIsCalleeSaved(const lldb_private::RegisterInfo *reg_info); private: - ABISysV_i386(lldb::ProcessSP process_sp) : lldb_private::ABI(process_sp) { + ABISysV_i386(lldb::ProcessSP process_sp, + std::unique_ptr<llvm::MCRegisterInfo> info_up) + : lldb_private::ABI(std::move(process_sp), std::move(info_up)) { // Call CreateInstance instead. } }; diff --git a/source/Plugins/ABI/SysV-mips/ABISysV_mips.cpp b/source/Plugins/ABI/SysV-mips/ABISysV_mips.cpp index 121c7300b968..416db9f5ae87 100644 --- a/source/Plugins/ABI/SysV-mips/ABISysV_mips.cpp +++ b/source/Plugins/ABI/SysV-mips/ABISysV_mips.cpp @@ -556,7 +556,8 @@ ABISysV_mips::CreateInstance(lldb::ProcessSP process_sp, const ArchSpec &arch) { const llvm::Triple::ArchType arch_type = arch.GetTriple().getArch(); if ((arch_type == llvm::Triple::mips) || (arch_type == llvm::Triple::mipsel)) { - return ABISP(new ABISysV_mips(process_sp)); + return ABISP( + new ABISysV_mips(std::move(process_sp), MakeMCRegisterInfo(arch))); } return ABISP(); } @@ -600,9 +601,8 @@ bool ABISysV_mips::PrepareTrivialCall(Thread &thread, addr_t sp, reg_info = reg_ctx->GetRegisterInfo(eRegisterKindGeneric, LLDB_REGNUM_GENERIC_ARG1 + i); - if (log) - log->Printf("About to write arg%zd (0x%" PRIx64 ") into %s", i + 1, - args[i], reg_info->name); + LLDB_LOGF(log, "About to write arg%zd (0x%" PRIx64 ") into %s", i + 1, + args[i], reg_info->name); if (!reg_ctx->WriteRegisterFromUnsigned(reg_info, args[i])) return false; @@ -630,9 +630,8 @@ bool ABISysV_mips::PrepareTrivialCall(Thread &thread, addr_t sp, size_t i = 4; for (; ai != ae; ++ai) { reg_value.SetUInt32(*ai); - if (log) - log->Printf("About to write arg%zd (0x%" PRIx64 ") at 0x%" PRIx64 "", - i + 1, args[i], arg_pos); + LLDB_LOGF(log, "About to write arg%zd (0x%" PRIx64 ") at 0x%" PRIx64 "", + i + 1, args[i], arg_pos); if (reg_ctx ->WriteRegisterValueToMemory(reg_info, arg_pos, @@ -654,8 +653,7 @@ bool ABISysV_mips::PrepareTrivialCall(Thread &thread, addr_t sp, const RegisterInfo *r25_info = reg_ctx->GetRegisterInfoByName("r25", 0); const RegisterInfo *r0_info = reg_ctx->GetRegisterInfoByName("zero", 0); - if (log) - log->Printf("Writing R0: 0x%" PRIx64, (uint64_t)0); + LLDB_LOGF(log, "Writing R0: 0x%" PRIx64, (uint64_t)0); /* Write r0 with 0, in case we are stopped in syscall, * such setting prevents automatic decrement of the PC. @@ -664,29 +662,25 @@ bool ABISysV_mips::PrepareTrivialCall(Thread &thread, addr_t sp, if (!reg_ctx->WriteRegisterFromUnsigned(r0_info, (uint64_t)0)) return false; - if (log) - log->Printf("Writing SP: 0x%" PRIx64, (uint64_t)sp); + LLDB_LOGF(log, "Writing SP: 0x%" PRIx64, (uint64_t)sp); // Set "sp" to the requested value if (!reg_ctx->WriteRegisterFromUnsigned(sp_reg_info, sp)) return false; - if (log) - log->Printf("Writing RA: 0x%" PRIx64, (uint64_t)return_addr); + LLDB_LOGF(log, "Writing RA: 0x%" PRIx64, (uint64_t)return_addr); // Set "ra" to the return address if (!reg_ctx->WriteRegisterFromUnsigned(ra_reg_info, return_addr)) return false; - if (log) - log->Printf("Writing PC: 0x%" PRIx64, (uint64_t)func_addr); + LLDB_LOGF(log, "Writing PC: 0x%" PRIx64, (uint64_t)func_addr); // Set pc to the address of the called function. if (!reg_ctx->WriteRegisterFromUnsigned(pc_reg_info, func_addr)) return false; - if (log) - log->Printf("Writing r25: 0x%" PRIx64, (uint64_t)func_addr); + LLDB_LOGF(log, "Writing r25: 0x%" PRIx64, (uint64_t)func_addr); // All callers of position independent functions must place the address of // the called function in t9 (r25) @@ -997,6 +991,7 @@ bool ABISysV_mips::CreateDefaultUnwindPlan(UnwindPlan &unwind_plan) { unwind_plan.SetSourceName("mips default unwind plan"); unwind_plan.SetSourcedFromCompiler(eLazyBoolNo); unwind_plan.SetUnwindPlanValidAtAllInstructions(eLazyBoolNo); + unwind_plan.SetUnwindPlanForSignalTrap(eLazyBoolNo); return true; } diff --git a/source/Plugins/ABI/SysV-mips/ABISysV_mips.h b/source/Plugins/ABI/SysV-mips/ABISysV_mips.h index 6cd9c19c22ac..8143f552fc4d 100644 --- a/source/Plugins/ABI/SysV-mips/ABISysV_mips.h +++ b/source/Plugins/ABI/SysV-mips/ABISysV_mips.h @@ -87,7 +87,9 @@ protected: bool RegisterIsCalleeSaved(const lldb_private::RegisterInfo *reg_info); private: - ABISysV_mips(lldb::ProcessSP process_sp) : lldb_private::ABI(process_sp) { + ABISysV_mips(lldb::ProcessSP process_sp, + std::unique_ptr<llvm::MCRegisterInfo> info_up) + : lldb_private::ABI(std::move(process_sp), std::move(info_up)) { // Call CreateInstance instead. } }; diff --git a/source/Plugins/ABI/SysV-mips64/ABISysV_mips64.cpp b/source/Plugins/ABI/SysV-mips64/ABISysV_mips64.cpp index 18011cfb6b9e..72ec0715b6cd 100644 --- a/source/Plugins/ABI/SysV-mips64/ABISysV_mips64.cpp +++ b/source/Plugins/ABI/SysV-mips64/ABISysV_mips64.cpp @@ -554,7 +554,8 @@ size_t ABISysV_mips64::GetRedZoneSize() const { return 0; } ABISP ABISysV_mips64::CreateInstance(lldb::ProcessSP process_sp, const ArchSpec &arch) { if (arch.GetTriple().isMIPS64()) - return ABISP(new ABISysV_mips64(process_sp)); + return ABISP( + new ABISysV_mips64(std::move(process_sp), MakeMCRegisterInfo(arch))); return ABISP(); } @@ -589,18 +590,16 @@ bool ABISysV_mips64::PrepareTrivialCall(Thread &thread, addr_t sp, for (size_t i = 0; i < args.size(); ++i) { reg_info = reg_ctx->GetRegisterInfo(eRegisterKindGeneric, LLDB_REGNUM_GENERIC_ARG1 + i); - if (log) - log->Printf("About to write arg%zd (0x%" PRIx64 ") into %s", i + 1, - args[i], reg_info->name); + LLDB_LOGF(log, "About to write arg%zd (0x%" PRIx64 ") into %s", i + 1, + args[i], reg_info->name); if (!reg_ctx->WriteRegisterFromUnsigned(reg_info, args[i])) return false; } // First, align the SP - if (log) - log->Printf("16-byte aligning SP: 0x%" PRIx64 " to 0x%" PRIx64, - (uint64_t)sp, (uint64_t)(sp & ~0xfull)); + LLDB_LOGF(log, "16-byte aligning SP: 0x%" PRIx64 " to 0x%" PRIx64, + (uint64_t)sp, (uint64_t)(sp & ~0xfull)); sp &= ~(0xfull); // 16-byte alignment @@ -614,8 +613,7 @@ bool ABISysV_mips64::PrepareTrivialCall(Thread &thread, addr_t sp, const RegisterInfo *r25_info = reg_ctx->GetRegisterInfoByName("r25", 0); const RegisterInfo *r0_info = reg_ctx->GetRegisterInfoByName("zero", 0); - if (log) - log->Printf("Writing R0: 0x%" PRIx64, (uint64_t)0); + LLDB_LOGF(log, "Writing R0: 0x%" PRIx64, (uint64_t)0); /* Write r0 with 0, in case we are stopped in syscall, * such setting prevents automatic decrement of the PC. @@ -624,29 +622,25 @@ bool ABISysV_mips64::PrepareTrivialCall(Thread &thread, addr_t sp, if (!reg_ctx->WriteRegisterFromUnsigned(r0_info, (uint64_t)0)) return false; - if (log) - log->Printf("Writing SP: 0x%" PRIx64, (uint64_t)sp); + LLDB_LOGF(log, "Writing SP: 0x%" PRIx64, (uint64_t)sp); // Set "sp" to the requested value if (!reg_ctx->WriteRegisterFromUnsigned(sp_reg_info, sp)) return false; - if (log) - log->Printf("Writing RA: 0x%" PRIx64, (uint64_t)return_addr); + LLDB_LOGF(log, "Writing RA: 0x%" PRIx64, (uint64_t)return_addr); // Set "ra" to the return address if (!reg_ctx->WriteRegisterFromUnsigned(ra_reg_info, return_addr)) return false; - if (log) - log->Printf("Writing PC: 0x%" PRIx64, (uint64_t)func_addr); + LLDB_LOGF(log, "Writing PC: 0x%" PRIx64, (uint64_t)func_addr); // Set pc to the address of the called function. if (!reg_ctx->WriteRegisterFromUnsigned(pc_reg_info, func_addr)) return false; - if (log) - log->Printf("Writing r25: 0x%" PRIx64, (uint64_t)func_addr); + LLDB_LOGF(log, "Writing r25: 0x%" PRIx64, (uint64_t)func_addr); // All callers of position independent functions must place the address of // the called function in t9 (r25) @@ -1168,6 +1162,7 @@ bool ABISysV_mips64::CreateDefaultUnwindPlan(UnwindPlan &unwind_plan) { unwind_plan.SetSourceName("mips64 default unwind plan"); unwind_plan.SetSourcedFromCompiler(eLazyBoolNo); unwind_plan.SetUnwindPlanValidAtAllInstructions(eLazyBoolNo); + unwind_plan.SetUnwindPlanForSignalTrap(eLazyBoolNo); return true; } diff --git a/source/Plugins/ABI/SysV-mips64/ABISysV_mips64.h b/source/Plugins/ABI/SysV-mips64/ABISysV_mips64.h index 7da71b36b4b7..76c3c5413b92 100644 --- a/source/Plugins/ABI/SysV-mips64/ABISysV_mips64.h +++ b/source/Plugins/ABI/SysV-mips64/ABISysV_mips64.h @@ -100,7 +100,9 @@ protected: bool RegisterIsCalleeSaved(const lldb_private::RegisterInfo *reg_info); private: - ABISysV_mips64(lldb::ProcessSP process_sp) : lldb_private::ABI(process_sp) { + ABISysV_mips64(lldb::ProcessSP process_sp, + std::unique_ptr<llvm::MCRegisterInfo> info_up) + : lldb_private::ABI(std::move(process_sp), std::move(info_up)) { // Call CreateInstance instead. } }; diff --git a/source/Plugins/ABI/SysV-ppc/ABISysV_ppc.cpp b/source/Plugins/ABI/SysV-ppc/ABISysV_ppc.cpp index faa995033ac2..857b7fee10e3 100644 --- a/source/Plugins/ABI/SysV-ppc/ABISysV_ppc.cpp +++ b/source/Plugins/ABI/SysV-ppc/ABISysV_ppc.cpp @@ -218,7 +218,8 @@ size_t ABISysV_ppc::GetRedZoneSize() const { return 224; } ABISP ABISysV_ppc::CreateInstance(lldb::ProcessSP process_sp, const ArchSpec &arch) { if (arch.GetTriple().getArch() == llvm::Triple::ppc) { - return ABISP(new ABISysV_ppc(process_sp)); + return ABISP( + new ABISysV_ppc(std::move(process_sp), MakeMCRegisterInfo(arch))); } return ABISP(); } @@ -255,18 +256,16 @@ bool ABISysV_ppc::PrepareTrivialCall(Thread &thread, addr_t sp, for (size_t i = 0; i < args.size(); ++i) { reg_info = reg_ctx->GetRegisterInfo(eRegisterKindGeneric, LLDB_REGNUM_GENERIC_ARG1 + i); - if (log) - log->Printf("About to write arg%" PRIu64 " (0x%" PRIx64 ") into %s", - static_cast<uint64_t>(i + 1), args[i], reg_info->name); + LLDB_LOGF(log, "About to write arg%" PRIu64 " (0x%" PRIx64 ") into %s", + static_cast<uint64_t>(i + 1), args[i], reg_info->name); if (!reg_ctx->WriteRegisterFromUnsigned(reg_info, args[i])) return false; } // First, align the SP - if (log) - log->Printf("16-byte aligning SP: 0x%" PRIx64 " to 0x%" PRIx64, - (uint64_t)sp, (uint64_t)(sp & ~0xfull)); + LLDB_LOGF(log, "16-byte aligning SP: 0x%" PRIx64 " to 0x%" PRIx64, + (uint64_t)sp, (uint64_t)(sp & ~0xfull)); sp &= ~(0xfull); // 16-byte alignment @@ -281,10 +280,10 @@ bool ABISysV_ppc::PrepareTrivialCall(Thread &thread, addr_t sp, RegisterValue reg_value; - if (log) - log->Printf("Pushing the return address onto the stack: 0x%" PRIx64 - ": 0x%" PRIx64, - (uint64_t)sp, (uint64_t)return_addr); + LLDB_LOGF(log, + "Pushing the return address onto the stack: 0x%" PRIx64 + ": 0x%" PRIx64, + (uint64_t)sp, (uint64_t)return_addr); // Save return address onto the stack if (!process_sp->WritePointerToMemory(sp, return_addr, error)) @@ -292,16 +291,14 @@ bool ABISysV_ppc::PrepareTrivialCall(Thread &thread, addr_t sp, // %r1 is set to the actual stack value. - if (log) - log->Printf("Writing SP: 0x%" PRIx64, (uint64_t)sp); + LLDB_LOGF(log, "Writing SP: 0x%" PRIx64, (uint64_t)sp); if (!reg_ctx->WriteRegisterFromUnsigned(sp_reg_info, sp)) return false; // %pc is set to the address of the called function. - if (log) - log->Printf("Writing IP: 0x%" PRIx64, (uint64_t)func_addr); + LLDB_LOGF(log, "Writing IP: 0x%" PRIx64, (uint64_t)func_addr); if (!reg_ctx->WriteRegisterFromUnsigned(pc_reg_info, func_addr)) return false; @@ -910,6 +907,7 @@ bool ABISysV_ppc::CreateDefaultUnwindPlan(UnwindPlan &unwind_plan) { unwind_plan.SetSourceName("ppc default unwind plan"); unwind_plan.SetSourcedFromCompiler(eLazyBoolNo); unwind_plan.SetUnwindPlanValidAtAllInstructions(eLazyBoolNo); + unwind_plan.SetUnwindPlanForSignalTrap(eLazyBoolNo); unwind_plan.SetReturnAddressRegister(dwarf_lr); return true; } diff --git a/source/Plugins/ABI/SysV-ppc/ABISysV_ppc.h b/source/Plugins/ABI/SysV-ppc/ABISysV_ppc.h index 3b199852c30d..59907c4648ba 100644 --- a/source/Plugins/ABI/SysV-ppc/ABISysV_ppc.h +++ b/source/Plugins/ABI/SysV-ppc/ABISysV_ppc.h @@ -96,7 +96,9 @@ protected: bool RegisterIsCalleeSaved(const lldb_private::RegisterInfo *reg_info); private: - ABISysV_ppc(lldb::ProcessSP process_sp) : lldb_private::ABI(process_sp) { + ABISysV_ppc(lldb::ProcessSP process_sp, + std::unique_ptr<llvm::MCRegisterInfo> info_up) + : lldb_private::ABI(std::move(process_sp), std::move(info_up)) { // Call CreateInstance instead. } }; diff --git a/source/Plugins/ABI/SysV-ppc64/ABISysV_ppc64.cpp b/source/Plugins/ABI/SysV-ppc64/ABISysV_ppc64.cpp index aa7907550f29..935353c38ca4 100644 --- a/source/Plugins/ABI/SysV-ppc64/ABISysV_ppc64.cpp +++ b/source/Plugins/ABI/SysV-ppc64/ABISysV_ppc64.cpp @@ -70,7 +70,8 @@ ABISP ABISysV_ppc64::CreateInstance(lldb::ProcessSP process_sp, const ArchSpec &arch) { if (arch.GetTriple().isPPC64()) - return ABISP(new ABISysV_ppc64(process_sp)); + return ABISP( + new ABISysV_ppc64(std::move(process_sp), MakeMCRegisterInfo(arch))); return ABISP(); } @@ -106,18 +107,16 @@ bool ABISysV_ppc64::PrepareTrivialCall(Thread &thread, addr_t sp, for (size_t i = 0; i < args.size(); ++i) { reg_info = reg_ctx->GetRegisterInfo(eRegisterKindGeneric, LLDB_REGNUM_GENERIC_ARG1 + i); - if (log) - log->Printf("About to write arg%" PRIu64 " (0x%" PRIx64 ") into %s", - static_cast<uint64_t>(i + 1), args[i], reg_info->name); + LLDB_LOGF(log, "About to write arg%" PRIu64 " (0x%" PRIx64 ") into %s", + static_cast<uint64_t>(i + 1), args[i], reg_info->name); if (!reg_ctx->WriteRegisterFromUnsigned(reg_info, args[i])) return false; } // First, align the SP - if (log) - log->Printf("16-byte aligning SP: 0x%" PRIx64 " to 0x%" PRIx64, - (uint64_t)sp, (uint64_t)(sp & ~0xfull)); + LLDB_LOGF(log, "16-byte aligning SP: 0x%" PRIx64 " to 0x%" PRIx64, + (uint64_t)sp, (uint64_t)(sp & ~0xfull)); sp &= ~(0xfull); // 16-byte alignment @@ -136,22 +135,20 @@ bool ABISysV_ppc64::PrepareTrivialCall(Thread &thread, addr_t sp, const RegisterInfo *r12_reg_info = reg_ctx->GetRegisterInfoAtIndex(12); // Save return address onto the stack. - if (log) - log->Printf("Pushing the return address onto the stack: 0x%" PRIx64 - "(+16): 0x%" PRIx64, - (uint64_t)sp, (uint64_t)return_addr); + LLDB_LOGF(log, + "Pushing the return address onto the stack: 0x%" PRIx64 + "(+16): 0x%" PRIx64, + (uint64_t)sp, (uint64_t)return_addr); if (!process_sp->WritePointerToMemory(sp + 16, return_addr, error)) return false; // Write the return address to link register. - if (log) - log->Printf("Writing LR: 0x%" PRIx64, (uint64_t)return_addr); + LLDB_LOGF(log, "Writing LR: 0x%" PRIx64, (uint64_t)return_addr); if (!reg_ctx->WriteRegisterFromUnsigned(lr_reg_info, return_addr)) return false; // Write target address to %r12 register. - if (log) - log->Printf("Writing R12: 0x%" PRIx64, (uint64_t)func_addr); + LLDB_LOGF(log, "Writing R12: 0x%" PRIx64, (uint64_t)func_addr); if (!reg_ctx->WriteRegisterFromUnsigned(r12_reg_info, func_addr)) return false; @@ -165,10 +162,9 @@ bool ABISysV_ppc64::PrepareTrivialCall(Thread &thread, addr_t sp, else stack_offset = 40; - if (log) - log->Printf("Writing R2 (TOC) at SP(0x%" PRIx64 ")+%d: 0x%" PRIx64, - (uint64_t)(sp + stack_offset), (int)stack_offset, - (uint64_t)reg_value); + LLDB_LOGF(log, "Writing R2 (TOC) at SP(0x%" PRIx64 ")+%d: 0x%" PRIx64, + (uint64_t)(sp + stack_offset), (int)stack_offset, + (uint64_t)reg_value); if (!process_sp->WritePointerToMemory(sp + stack_offset, reg_value, error)) return false; @@ -176,23 +172,20 @@ bool ABISysV_ppc64::PrepareTrivialCall(Thread &thread, addr_t sp, reg_value = reg_ctx->ReadRegisterAsUnsigned(sp_reg_info, 0); // Save current SP onto the stack. - if (log) - log->Printf("Writing SP at SP(0x%" PRIx64 ")+0: 0x%" PRIx64, (uint64_t)sp, - (uint64_t)reg_value); + LLDB_LOGF(log, "Writing SP at SP(0x%" PRIx64 ")+0: 0x%" PRIx64, (uint64_t)sp, + (uint64_t)reg_value); if (!process_sp->WritePointerToMemory(sp, reg_value, error)) return false; // %r1 is set to the actual stack value. - if (log) - log->Printf("Writing SP: 0x%" PRIx64, (uint64_t)sp); + LLDB_LOGF(log, "Writing SP: 0x%" PRIx64, (uint64_t)sp); if (!reg_ctx->WriteRegisterFromUnsigned(sp_reg_info, sp)) return false; // %pc is set to the address of the called function. - if (log) - log->Printf("Writing IP: 0x%" PRIx64, (uint64_t)func_addr); + LLDB_LOGF(log, "Writing IP: 0x%" PRIx64, (uint64_t)func_addr); if (!reg_ctx->WriteRegisterFromUnsigned(pc_reg_info, func_addr)) return false; @@ -1017,6 +1010,7 @@ bool ABISysV_ppc64::CreateDefaultUnwindPlan(UnwindPlan &unwind_plan) { unwind_plan.SetSourceName("ppc64 default unwind plan"); unwind_plan.SetSourcedFromCompiler(eLazyBoolNo); unwind_plan.SetUnwindPlanValidAtAllInstructions(eLazyBoolNo); + unwind_plan.SetUnwindPlanForSignalTrap(eLazyBoolNo); unwind_plan.SetReturnAddressRegister(pc_reg_num); return true; } diff --git a/source/Plugins/ABI/SysV-ppc64/ABISysV_ppc64.h b/source/Plugins/ABI/SysV-ppc64/ABISysV_ppc64.h index d5fb09eec0d0..1b58975dd9d9 100644 --- a/source/Plugins/ABI/SysV-ppc64/ABISysV_ppc64.h +++ b/source/Plugins/ABI/SysV-ppc64/ABISysV_ppc64.h @@ -96,7 +96,9 @@ protected: bool RegisterIsCalleeSaved(const lldb_private::RegisterInfo *reg_info); private: - ABISysV_ppc64(lldb::ProcessSP process_sp) : lldb_private::ABI(process_sp) { + ABISysV_ppc64(lldb::ProcessSP process_sp, + std::unique_ptr<llvm::MCRegisterInfo> info_up) + : lldb_private::ABI(std::move(process_sp), std::move(info_up)) { // Call CreateInstance instead. } diff --git a/source/Plugins/ABI/SysV-s390x/ABISysV_s390x.cpp b/source/Plugins/ABI/SysV-s390x/ABISysV_s390x.cpp index abe847b386a8..f4f803a8277d 100644 --- a/source/Plugins/ABI/SysV-s390x/ABISysV_s390x.cpp +++ b/source/Plugins/ABI/SysV-s390x/ABISysV_s390x.cpp @@ -200,7 +200,7 @@ size_t ABISysV_s390x::GetRedZoneSize() const { return 0; } ABISP ABISysV_s390x::CreateInstance(lldb::ProcessSP process_sp, const ArchSpec &arch) { if (arch.GetTriple().getArch() == llvm::Triple::systemz) { - return ABISP(new ABISysV_s390x(process_sp)); + return ABISP(new ABISysV_s390x(std::move(process_sp), MakeMCRegisterInfo(arch))); } return ABISP(); } @@ -252,16 +252,14 @@ bool ABISysV_s390x::PrepareTrivialCall(Thread &thread, addr_t sp, if (i < 5) { const RegisterInfo *reg_info = reg_ctx->GetRegisterInfo( eRegisterKindGeneric, LLDB_REGNUM_GENERIC_ARG1 + i); - if (log) - log->Printf("About to write arg%" PRIu64 " (0x%" PRIx64 ") into %s", - static_cast<uint64_t>(i + 1), args[i], reg_info->name); + LLDB_LOGF(log, "About to write arg%" PRIu64 " (0x%" PRIx64 ") into %s", + static_cast<uint64_t>(i + 1), args[i], reg_info->name); if (!reg_ctx->WriteRegisterFromUnsigned(reg_info, args[i])) return false; } else { Status error; - if (log) - log->Printf("About to write arg%" PRIu64 " (0x%" PRIx64 ") onto stack", - static_cast<uint64_t>(i + 1), args[i]); + LLDB_LOGF(log, "About to write arg%" PRIu64 " (0x%" PRIx64 ") onto stack", + static_cast<uint64_t>(i + 1), args[i]); if (!process_sp->WritePointerToMemory(arg_pos, args[i], error)) return false; arg_pos += 8; @@ -270,24 +268,21 @@ bool ABISysV_s390x::PrepareTrivialCall(Thread &thread, addr_t sp, // %r14 is set to the return address - if (log) - log->Printf("Writing RA: 0x%" PRIx64, (uint64_t)return_addr); + LLDB_LOGF(log, "Writing RA: 0x%" PRIx64, (uint64_t)return_addr); if (!reg_ctx->WriteRegisterFromUnsigned(ra_reg_info, return_addr)) return false; // %r15 is set to the actual stack value. - if (log) - log->Printf("Writing SP: 0x%" PRIx64, (uint64_t)sp); + LLDB_LOGF(log, "Writing SP: 0x%" PRIx64, (uint64_t)sp); if (!reg_ctx->WriteRegisterFromUnsigned(sp_reg_info, sp)) return false; // %pc is set to the address of the called function. - if (log) - log->Printf("Writing PC: 0x%" PRIx64, (uint64_t)func_addr); + LLDB_LOGF(log, "Writing PC: 0x%" PRIx64, (uint64_t)func_addr); if (!reg_ctx->WriteRegisterFromUnsigned(pc_reg_info, func_addr)) return false; diff --git a/source/Plugins/ABI/SysV-s390x/ABISysV_s390x.h b/source/Plugins/ABI/SysV-s390x/ABISysV_s390x.h index 13df477e84bc..671d6a18260e 100644 --- a/source/Plugins/ABI/SysV-s390x/ABISysV_s390x.h +++ b/source/Plugins/ABI/SysV-s390x/ABISysV_s390x.h @@ -88,7 +88,9 @@ protected: bool RegisterIsCalleeSaved(const lldb_private::RegisterInfo *reg_info); private: - ABISysV_s390x(lldb::ProcessSP process_sp) : lldb_private::ABI(process_sp) { + ABISysV_s390x(lldb::ProcessSP process_sp, + std::unique_ptr<llvm::MCRegisterInfo> info_up) + : lldb_private::ABI(std::move(process_sp), std::move(info_up)) { // Call CreateInstance instead. } }; diff --git a/source/Plugins/ABI/SysV-x86_64/ABISysV_x86_64.cpp b/source/Plugins/ABI/SysV-x86_64/ABISysV_x86_64.cpp index 6c7b45f63399..bf1c48f778e1 100644 --- a/source/Plugins/ABI/SysV-x86_64/ABISysV_x86_64.cpp +++ b/source/Plugins/ABI/SysV-x86_64/ABISysV_x86_64.cpp @@ -222,17 +222,35 @@ ABISP ABISysV_x86_64::CreateInstance(lldb::ProcessSP process_sp, const ArchSpec &arch) { const llvm::Triple::ArchType arch_type = arch.GetTriple().getArch(); const llvm::Triple::OSType os_type = arch.GetTriple().getOS(); + const llvm::Triple::EnvironmentType os_env = + arch.GetTriple().getEnvironment(); if (arch_type == llvm::Triple::x86_64) { switch(os_type) { - case llvm::Triple::OSType::MacOSX: - case llvm::Triple::OSType::Linux: - case llvm::Triple::OSType::FreeBSD: - case llvm::Triple::OSType::NetBSD: - case llvm::Triple::OSType::Solaris: - case llvm::Triple::OSType::UnknownOS: - return ABISP(new ABISysV_x86_64(process_sp)); - default: + case llvm::Triple::OSType::IOS: + case llvm::Triple::OSType::TvOS: + case llvm::Triple::OSType::WatchOS: + switch (os_env) { + case llvm::Triple::EnvironmentType::MacABI: + case llvm::Triple::EnvironmentType::Simulator: + case llvm::Triple::EnvironmentType::UnknownEnvironment: + // UnknownEnvironment is needed for older compilers that don't + // support the simulator environment. + return ABISP(new ABISysV_x86_64(std::move(process_sp), + MakeMCRegisterInfo(arch))); + default: return ABISP(); + } + case llvm::Triple::OSType::Darwin: + case llvm::Triple::OSType::FreeBSD: + case llvm::Triple::OSType::Linux: + case llvm::Triple::OSType::MacOSX: + case llvm::Triple::OSType::NetBSD: + case llvm::Triple::OSType::Solaris: + case llvm::Triple::OSType::UnknownOS: + return ABISP( + new ABISysV_x86_64(std::move(process_sp), MakeMCRegisterInfo(arch))); + default: + return ABISP(); } } return ABISP(); @@ -270,18 +288,16 @@ bool ABISysV_x86_64::PrepareTrivialCall(Thread &thread, addr_t sp, for (size_t i = 0; i < args.size(); ++i) { reg_info = reg_ctx->GetRegisterInfo(eRegisterKindGeneric, LLDB_REGNUM_GENERIC_ARG1 + i); - if (log) - log->Printf("About to write arg%" PRIu64 " (0x%" PRIx64 ") into %s", - static_cast<uint64_t>(i + 1), args[i], reg_info->name); + LLDB_LOGF(log, "About to write arg%" PRIu64 " (0x%" PRIx64 ") into %s", + static_cast<uint64_t>(i + 1), args[i], reg_info->name); if (!reg_ctx->WriteRegisterFromUnsigned(reg_info, args[i])) return false; } // First, align the SP - if (log) - log->Printf("16-byte aligning SP: 0x%" PRIx64 " to 0x%" PRIx64, - (uint64_t)sp, (uint64_t)(sp & ~0xfull)); + LLDB_LOGF(log, "16-byte aligning SP: 0x%" PRIx64 " to 0x%" PRIx64, + (uint64_t)sp, (uint64_t)(sp & ~0xfull)); sp &= ~(0xfull); // 16-byte alignment @@ -295,10 +311,10 @@ bool ABISysV_x86_64::PrepareTrivialCall(Thread &thread, addr_t sp, ProcessSP process_sp(thread.GetProcess()); RegisterValue reg_value; - if (log) - log->Printf("Pushing the return address onto the stack: 0x%" PRIx64 - ": 0x%" PRIx64, - (uint64_t)sp, (uint64_t)return_addr); + LLDB_LOGF(log, + "Pushing the return address onto the stack: 0x%" PRIx64 + ": 0x%" PRIx64, + (uint64_t)sp, (uint64_t)return_addr); // Save return address onto the stack if (!process_sp->WritePointerToMemory(sp, return_addr, error)) @@ -306,16 +322,14 @@ bool ABISysV_x86_64::PrepareTrivialCall(Thread &thread, addr_t sp, // %rsp is set to the actual stack value. - if (log) - log->Printf("Writing SP: 0x%" PRIx64, (uint64_t)sp); + LLDB_LOGF(log, "Writing SP: 0x%" PRIx64, (uint64_t)sp); if (!reg_ctx->WriteRegisterFromUnsigned(sp_reg_info, sp)) return false; // %rip is set to the address of the called function. - if (log) - log->Printf("Writing IP: 0x%" PRIx64, (uint64_t)func_addr); + LLDB_LOGF(log, "Writing IP: 0x%" PRIx64, (uint64_t)func_addr); if (!reg_ctx->WriteRegisterFromUnsigned(pc_reg_info, func_addr)) return false; @@ -1034,6 +1048,7 @@ bool ABISysV_x86_64::CreateDefaultUnwindPlan(UnwindPlan &unwind_plan) { unwind_plan.SetSourceName("x86_64 default unwind plan"); unwind_plan.SetSourcedFromCompiler(eLazyBoolNo); unwind_plan.SetUnwindPlanValidAtAllInstructions(eLazyBoolNo); + unwind_plan.SetUnwindPlanForSignalTrap(eLazyBoolNo); return true; } diff --git a/source/Plugins/ABI/SysV-x86_64/ABISysV_x86_64.h b/source/Plugins/ABI/SysV-x86_64/ABISysV_x86_64.h index f6704aff348c..d445d8f4142a 100644 --- a/source/Plugins/ABI/SysV-x86_64/ABISysV_x86_64.h +++ b/source/Plugins/ABI/SysV-x86_64/ABISysV_x86_64.h @@ -98,7 +98,9 @@ protected: bool RegisterIsCalleeSaved(const lldb_private::RegisterInfo *reg_info); private: - ABISysV_x86_64(lldb::ProcessSP process_sp) : lldb_private::ABI(process_sp) { + ABISysV_x86_64(lldb::ProcessSP process_sp, + std::unique_ptr<llvm::MCRegisterInfo> info_up) + : lldb_private::ABI(std::move(process_sp), std::move(info_up)) { // Call CreateInstance instead. } }; diff --git a/source/Plugins/ABI/Windows-x86_64/ABIWindows_x86_64.cpp b/source/Plugins/ABI/Windows-x86_64/ABIWindows_x86_64.cpp index 5dc7717d865d..ac24426914e1 100644 --- a/source/Plugins/ABI/Windows-x86_64/ABIWindows_x86_64.cpp +++ b/source/Plugins/ABI/Windows-x86_64/ABIWindows_x86_64.cpp @@ -1092,7 +1092,8 @@ ABISP ABIWindows_x86_64::CreateInstance(lldb::ProcessSP process_sp, const ArchSpec &arch) { if (arch.GetTriple().getArch() == llvm::Triple::x86_64 && arch.GetTriple().isOSWindows()) { - return ABISP(new ABIWindows_x86_64(process_sp)); + return ABISP( + new ABIWindows_x86_64(std::move(process_sp), MakeMCRegisterInfo(arch))); } return ABISP(); } @@ -1129,18 +1130,16 @@ bool ABIWindows_x86_64::PrepareTrivialCall(Thread &thread, addr_t sp, for (size_t i = 0; i < args.size(); ++i) { reg_info = reg_ctx->GetRegisterInfo(eRegisterKindGeneric, LLDB_REGNUM_GENERIC_ARG1 + i); - if (log) - log->Printf("About to write arg%" PRIu64 " (0x%" PRIx64 ") into %s", - static_cast<uint64_t>(i + 1), args[i], reg_info->name); + LLDB_LOGF(log, "About to write arg%" PRIu64 " (0x%" PRIx64 ") into %s", + static_cast<uint64_t>(i + 1), args[i], reg_info->name); if (!reg_ctx->WriteRegisterFromUnsigned(reg_info, args[i])) return false; } // First, align the SP - if (log) - log->Printf("16-byte aligning SP: 0x%" PRIx64 " to 0x%" PRIx64, - (uint64_t)sp, (uint64_t)(sp & ~0xfull)); + LLDB_LOGF(log, "16-byte aligning SP: 0x%" PRIx64 " to 0x%" PRIx64, + (uint64_t)sp, (uint64_t)(sp & ~0xfull)); sp &= ~(0xfull); // 16-byte alignment @@ -1154,10 +1153,10 @@ bool ABIWindows_x86_64::PrepareTrivialCall(Thread &thread, addr_t sp, ProcessSP process_sp(thread.GetProcess()); RegisterValue reg_value; - if (log) - log->Printf("Pushing the return address onto the stack: 0x%" PRIx64 - ": 0x%" PRIx64, - (uint64_t)sp, (uint64_t)return_addr); + LLDB_LOGF(log, + "Pushing the return address onto the stack: 0x%" PRIx64 + ": 0x%" PRIx64, + (uint64_t)sp, (uint64_t)return_addr); // Save return address onto the stack if (!process_sp->WritePointerToMemory(sp, return_addr, error)) @@ -1165,16 +1164,14 @@ bool ABIWindows_x86_64::PrepareTrivialCall(Thread &thread, addr_t sp, // %rsp is set to the actual stack value. - if (log) - log->Printf("Writing SP: 0x%" PRIx64, (uint64_t)sp); + LLDB_LOGF(log, "Writing SP: 0x%" PRIx64, (uint64_t)sp); if (!reg_ctx->WriteRegisterFromUnsigned(sp_reg_info, sp)) return false; // %rip is set to the address of the called function. - if (log) - log->Printf("Writing IP: 0x%" PRIx64, (uint64_t)func_addr); + LLDB_LOGF(log, "Writing IP: 0x%" PRIx64, (uint64_t)func_addr); if (!reg_ctx->WriteRegisterFromUnsigned(pc_reg_info, func_addr)) return false; diff --git a/source/Plugins/ABI/Windows-x86_64/ABIWindows_x86_64.h b/source/Plugins/ABI/Windows-x86_64/ABIWindows_x86_64.h index 9f6b2ceef299..2366566d7809 100644 --- a/source/Plugins/ABI/Windows-x86_64/ABIWindows_x86_64.h +++ b/source/Plugins/ABI/Windows-x86_64/ABIWindows_x86_64.h @@ -91,7 +91,9 @@ protected: bool RegisterIsCalleeSaved(const lldb_private::RegisterInfo *reg_info); private: - ABIWindows_x86_64(lldb::ProcessSP process_sp) : lldb_private::ABI(process_sp) { + ABIWindows_x86_64(lldb::ProcessSP process_sp, + std::unique_ptr<llvm::MCRegisterInfo> info_up) + : lldb_private::ABI(std::move(process_sp), std::move(info_up)) { // Call CreateInstance instead. } }; diff --git a/source/Plugins/Architecture/Mips/ArchitectureMips.cpp b/source/Plugins/Architecture/Mips/ArchitectureMips.cpp index 60f1a2eb7572..5f2f6eeb8261 100644 --- a/source/Plugins/Architecture/Mips/ArchitectureMips.cpp +++ b/source/Plugins/Architecture/Mips/ArchitectureMips.cpp @@ -127,10 +127,10 @@ lldb::addr_t ArchitectureMips::GetBreakableLoadAddress(lldb::addr_t addr, // Adjust the breakable address uint64_t breakable_addr = addr - insn->GetOpcode().GetByteSize(); - if (log) - log->Printf("Target::%s Breakpoint at 0x%8.8" PRIx64 - " is adjusted to 0x%8.8" PRIx64 " due to delay slot\n", - __FUNCTION__, addr, breakable_addr); + LLDB_LOGF(log, + "Target::%s Breakpoint at 0x%8.8" PRIx64 + " is adjusted to 0x%8.8" PRIx64 " due to delay slot\n", + __FUNCTION__, addr, breakable_addr); return breakable_addr; } diff --git a/source/Plugins/Disassembler/llvm/DisassemblerLLVMC.cpp b/source/Plugins/Disassembler/llvm/DisassemblerLLVMC.cpp index 44c75fc953c8..28c9de2c1e96 100644 --- a/source/Plugins/Disassembler/llvm/DisassemblerLLVMC.cpp +++ b/source/Plugins/Disassembler/llvm/DisassemblerLLVMC.cpp @@ -381,11 +381,10 @@ public: static RegularExpression s_regex( llvm::StringRef("[ \t]*([^ ^\t]+)[ \t]*([^ ^\t].*)?")); - RegularExpression::Match matches(3); - + llvm::SmallVector<llvm::StringRef, 4> matches; if (s_regex.Execute(out_string, &matches)) { - matches.GetMatchAtIndex(out_string.c_str(), 1, m_opcode_name); - matches.GetMatchAtIndex(out_string.c_str(), 2, m_mnemonics); + m_opcode_name = matches[1].str(); + m_mnemonics = matches[2].str(); } } } @@ -1190,10 +1189,12 @@ DisassemblerLLVMC::DisassemblerLLVMC(const ArchSpec &arch, // If any AArch64 variant, enable the ARMv8.5 ISA with SVE extensions so we // can disassemble newer instructions. - if (triple.getArch() == llvm::Triple::aarch64) + if (triple.getArch() == llvm::Triple::aarch64 || + triple.getArch() == llvm::Triple::aarch64_32) features_str += "+v8.5a,+sve2"; - if (triple.getArch() == llvm::Triple::aarch64 + if ((triple.getArch() == llvm::Triple::aarch64 || + triple.getArch() == llvm::Triple::aarch64_32) && triple.getVendor() == llvm::Triple::Apple) { cpu = "apple-latest"; } diff --git a/source/Plugins/DynamicLoader/Hexagon-DYLD/DynamicLoaderHexagonDYLD.cpp b/source/Plugins/DynamicLoader/Hexagon-DYLD/DynamicLoaderHexagonDYLD.cpp index 23c8416f4986..5b19647a27ba 100644 --- a/source/Plugins/DynamicLoader/Hexagon-DYLD/DynamicLoaderHexagonDYLD.cpp +++ b/source/Plugins/DynamicLoader/Hexagon-DYLD/DynamicLoaderHexagonDYLD.cpp @@ -277,8 +277,7 @@ bool DynamicLoaderHexagonDYLD::SetRendezvousBreakpoint() { // Do not try to set the breakpoint if we don't know where to put it if (break_addr == LLDB_INVALID_ADDRESS) { - if (log) - log->Printf("Unable to locate _rtld_debug_state breakpoint address"); + LLDB_LOGF(log, "Unable to locate _rtld_debug_state breakpoint address"); return false; } @@ -301,7 +300,7 @@ bool DynamicLoaderHexagonDYLD::SetRendezvousBreakpoint() { .GetID() == m_dyld_bid); if (log && dyld_break == nullptr) - log->Printf("Failed to create _rtld_debug_state breakpoint"); + LLDB_LOGF(log, "Failed to create _rtld_debug_state breakpoint"); // check we have successfully set bp return (dyld_break != nullptr); @@ -316,8 +315,7 @@ bool DynamicLoaderHexagonDYLD::RendezvousBreakpointHit( user_id_t break_loc_id) { Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_DYNAMIC_LOADER)); - if (log) - log->Printf("Rendezvous breakpoint hit!"); + LLDB_LOGF(log, "Rendezvous breakpoint hit!"); DynamicLoaderHexagonDYLD *dyld_instance = nullptr; dyld_instance = static_cast<DynamicLoaderHexagonDYLD *>(baton); @@ -333,11 +331,9 @@ bool DynamicLoaderHexagonDYLD::RendezvousBreakpointHit( if (structAddr != LLDB_INVALID_ADDRESS) { dyld_instance->m_rendezvous.SetRendezvousAddress(structAddr); - if (log) - log->Printf("Found _rtld_debug structure @ 0x%08" PRIx64, structAddr); + LLDB_LOGF(log, "Found _rtld_debug structure @ 0x%08" PRIx64, structAddr); } else { - if (log) - log->Printf("Unable to resolve the _rtld_debug structure"); + LLDB_LOGF(log, "Unable to resolve the _rtld_debug structure"); } } @@ -375,11 +371,11 @@ void DynamicLoaderHexagonDYLD::RefreshModules() { } if (log) { - log->Printf("Target is loading '%s'", I->path.c_str()); + LLDB_LOGF(log, "Target is loading '%s'", I->path.c_str()); if (!module_sp.get()) - log->Printf("LLDB failed to load '%s'", I->path.c_str()); + LLDB_LOGF(log, "LLDB failed to load '%s'", I->path.c_str()); else - log->Printf("LLDB successfully loaded '%s'", I->path.c_str()); + LLDB_LOGF(log, "LLDB successfully loaded '%s'", I->path.c_str()); } } m_process->GetTarget().ModulesDidLoad(new_modules); @@ -400,8 +396,7 @@ void DynamicLoaderHexagonDYLD::RefreshModules() { UnloadSections(module_sp); } - if (log) - log->Printf("Target is unloading '%s'", I->path.c_str()); + LLDB_LOGF(log, "Target is unloading '%s'", I->path.c_str()); } loaded_modules.Remove(old_modules); m_process->GetTarget().ModulesDidUnload(old_modules, false); @@ -472,10 +467,10 @@ void DynamicLoaderHexagonDYLD::LoadAllCurrentModules() { if (!m_rendezvous.Resolve()) { Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_DYNAMIC_LOADER)); - if (log) - log->Printf( - "DynamicLoaderHexagonDYLD::%s unable to resolve rendezvous address", - __FUNCTION__); + LLDB_LOGF( + log, + "DynamicLoaderHexagonDYLD::%s unable to resolve rendezvous address", + __FUNCTION__); return; } @@ -493,10 +488,10 @@ void DynamicLoaderHexagonDYLD::LoadAllCurrentModules() { module_list.Append(module_sp); } else { Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_DYNAMIC_LOADER)); - if (log) - log->Printf("DynamicLoaderHexagonDYLD::%s failed loading module %s at " - "0x%" PRIx64, - __FUNCTION__, module_path, I->base_addr); + LLDB_LOGF(log, + "DynamicLoaderHexagonDYLD::%s failed loading module %s at " + "0x%" PRIx64, + __FUNCTION__, module_path, I->base_addr); } } @@ -604,12 +599,11 @@ DynamicLoaderHexagonDYLD::GetThreadLocalData(const lldb::ModuleSP module, Module *mod = module.get(); Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_DYNAMIC_LOADER)); - if (log) - log->Printf("DynamicLoaderHexagonDYLD::Performed TLS lookup: " - "module=%s, link_map=0x%" PRIx64 ", tp=0x%" PRIx64 - ", modid=%i, tls_block=0x%" PRIx64, - mod->GetObjectName().AsCString(""), link_map, tp, modid, - tls_block); + LLDB_LOGF(log, + "DynamicLoaderHexagonDYLD::Performed TLS lookup: " + "module=%s, link_map=0x%" PRIx64 ", tp=0x%" PRIx64 + ", modid=%i, tls_block=0x%" PRIx64, + mod->GetObjectName().AsCString(""), link_map, tp, modid, tls_block); if (tls_block == LLDB_INVALID_ADDRESS) return LLDB_INVALID_ADDRESS; diff --git a/source/Plugins/DynamicLoader/Hexagon-DYLD/HexagonDYLDRendezvous.cpp b/source/Plugins/DynamicLoader/Hexagon-DYLD/HexagonDYLDRendezvous.cpp index 844a06c2b37d..f4788816d4ea 100644 --- a/source/Plugins/DynamicLoader/Hexagon-DYLD/HexagonDYLDRendezvous.cpp +++ b/source/Plugins/DynamicLoader/Hexagon-DYLD/HexagonDYLDRendezvous.cpp @@ -290,8 +290,9 @@ bool HexagonDYLDRendezvous::FindMetadata(const char *name, PThreadField field, Target &target = m_process->GetTarget(); SymbolContextList list; - if (!target.GetImages().FindSymbolsWithNameAndType(ConstString(name), - eSymbolTypeAny, list)) + target.GetImages().FindSymbolsWithNameAndType(ConstString(name), + eSymbolTypeAny, list); + if (list.IsEmpty()) return false; Address address = list[0].symbol->GetAddress(); @@ -339,16 +340,16 @@ void HexagonDYLDRendezvous::DumpToLog(Log *log) const { return; log->PutCString("HexagonDYLDRendezvous:"); - log->Printf(" Address: %" PRIx64, GetRendezvousAddress()); - log->Printf(" Version: %" PRIu64, GetVersion()); - log->Printf(" Link : %" PRIx64, GetLinkMapAddress()); - log->Printf(" Break : %" PRIx64, GetBreakAddress()); - log->Printf(" LDBase : %" PRIx64, GetLDBase()); - log->Printf(" State : %s", - (state == eConsistent) - ? "consistent" - : (state == eAdd) ? "add" : (state == eDelete) ? "delete" - : "unknown"); + LLDB_LOGF(log, " Address: %" PRIx64, GetRendezvousAddress()); + LLDB_LOGF(log, " Version: %" PRIu64, GetVersion()); + LLDB_LOGF(log, " Link : %" PRIx64, GetLinkMapAddress()); + LLDB_LOGF(log, " Break : %" PRIx64, GetBreakAddress()); + LLDB_LOGF(log, " LDBase : %" PRIx64, GetLDBase()); + LLDB_LOGF(log, " State : %s", + (state == eConsistent) + ? "consistent" + : (state == eAdd) ? "add" + : (state == eDelete) ? "delete" : "unknown"); iterator I = begin(); iterator E = end(); @@ -357,11 +358,11 @@ void HexagonDYLDRendezvous::DumpToLog(Log *log) const { log->PutCString("HexagonDYLDRendezvous SOEntries:"); for (int i = 1; I != E; ++I, ++i) { - log->Printf("\n SOEntry [%d] %s", i, I->path.c_str()); - log->Printf(" Base : %" PRIx64, I->base_addr); - log->Printf(" Path : %" PRIx64, I->path_addr); - log->Printf(" Dyn : %" PRIx64, I->dyn_addr); - log->Printf(" Next : %" PRIx64, I->next); - log->Printf(" Prev : %" PRIx64, I->prev); + LLDB_LOGF(log, "\n SOEntry [%d] %s", i, I->path.c_str()); + LLDB_LOGF(log, " Base : %" PRIx64, I->base_addr); + LLDB_LOGF(log, " Path : %" PRIx64, I->path_addr); + LLDB_LOGF(log, " Dyn : %" PRIx64, I->dyn_addr); + LLDB_LOGF(log, " Next : %" PRIx64, I->next); + LLDB_LOGF(log, " Prev : %" PRIx64, I->prev); } } diff --git a/source/Plugins/DynamicLoader/POSIX-DYLD/DYLDRendezvous.cpp b/source/Plugins/DynamicLoader/POSIX-DYLD/DYLDRendezvous.cpp index 0d736738ebb5..737599303a60 100644 --- a/source/Plugins/DynamicLoader/POSIX-DYLD/DYLDRendezvous.cpp +++ b/source/Plugins/DynamicLoader/POSIX-DYLD/DYLDRendezvous.cpp @@ -33,16 +33,14 @@ static addr_t ResolveRendezvousAddress(Process *process) { Status error; if (!process) { - if (log) - log->Printf("%s null process provided", __FUNCTION__); + LLDB_LOGF(log, "%s null process provided", __FUNCTION__); return LLDB_INVALID_ADDRESS; } // Try to get it from our process. This might be a remote process and might // grab it via some remote-specific mechanism. info_location = process->GetImageInfoAddress(); - if (log) - log->Printf("%s info_location = 0x%" PRIx64, __FUNCTION__, info_location); + LLDB_LOGF(log, "%s info_location = 0x%" PRIx64, __FUNCTION__, info_location); // If the process fails to return an address, fall back to seeing if the // local object file can help us find it. @@ -54,42 +52,38 @@ static addr_t ResolveRendezvousAddress(Process *process) { if (addr.IsValid()) { info_location = addr.GetLoadAddress(target); - if (log) - log->Printf( - "%s resolved via direct object file approach to 0x%" PRIx64, - __FUNCTION__, info_location); + LLDB_LOGF(log, + "%s resolved via direct object file approach to 0x%" PRIx64, + __FUNCTION__, info_location); } else { - if (log) - log->Printf("%s FAILED - direct object file approach did not yield a " - "valid address", - __FUNCTION__); + LLDB_LOGF(log, + "%s FAILED - direct object file approach did not yield a " + "valid address", + __FUNCTION__); } } } if (info_location == LLDB_INVALID_ADDRESS) { - if (log) - log->Printf("%s FAILED - invalid info address", __FUNCTION__); + LLDB_LOGF(log, "%s FAILED - invalid info address", __FUNCTION__); return LLDB_INVALID_ADDRESS; } - if (log) - log->Printf("%s reading pointer (%" PRIu32 " bytes) from 0x%" PRIx64, - __FUNCTION__, process->GetAddressByteSize(), info_location); + LLDB_LOGF(log, "%s reading pointer (%" PRIu32 " bytes) from 0x%" PRIx64, + __FUNCTION__, process->GetAddressByteSize(), info_location); info_addr = process->ReadPointerFromMemory(info_location, error); if (error.Fail()) { - if (log) - log->Printf("%s FAILED - could not read from the info location: %s", - __FUNCTION__, error.AsCString()); + LLDB_LOGF(log, "%s FAILED - could not read from the info location: %s", + __FUNCTION__, error.AsCString()); return LLDB_INVALID_ADDRESS; } if (info_addr == 0) { - if (log) - log->Printf("%s FAILED - the rendezvous address contained at 0x%" PRIx64 - " returned a null value", - __FUNCTION__, info_location); + LLDB_LOGF(log, + "%s FAILED - the rendezvous address contained at 0x%" PRIx64 + " returned a null value", + __FUNCTION__, info_location); return LLDB_INVALID_ADDRESS; } @@ -109,14 +103,13 @@ DYLDRendezvous::DYLDRendezvous(Process *process) Module *exe_mod = m_process->GetTarget().GetExecutableModulePointer(); if (exe_mod) { m_exe_file_spec = exe_mod->GetPlatformFileSpec(); - if (log) - log->Printf("DYLDRendezvous::%s exe module executable path set: '%s'", - __FUNCTION__, m_exe_file_spec.GetCString()); + LLDB_LOGF(log, "DYLDRendezvous::%s exe module executable path set: '%s'", + __FUNCTION__, m_exe_file_spec.GetCString()); } else { - if (log) - log->Printf("DYLDRendezvous::%s cannot cache exe module path: null " - "executable module pointer", - __FUNCTION__); + LLDB_LOGF(log, + "DYLDRendezvous::%s cannot cache exe module path: null " + "executable module pointer", + __FUNCTION__); } } } @@ -133,17 +126,16 @@ bool DYLDRendezvous::Resolve() { address_size = m_process->GetAddressByteSize(); padding = address_size - word_size; - if (log) - log->Printf("DYLDRendezvous::%s address size: %" PRIu64 - ", padding %" PRIu64, - __FUNCTION__, uint64_t(address_size), uint64_t(padding)); + LLDB_LOGF(log, + "DYLDRendezvous::%s address size: %" PRIu64 ", padding %" PRIu64, + __FUNCTION__, uint64_t(address_size), uint64_t(padding)); if (m_rendezvous_addr == LLDB_INVALID_ADDRESS) cursor = info_addr = ResolveRendezvousAddress(m_process); else cursor = info_addr = m_rendezvous_addr; - if (log) - log->Printf("DYLDRendezvous::%s cursor = 0x%" PRIx64, __FUNCTION__, cursor); + LLDB_LOGF(log, "DYLDRendezvous::%s cursor = 0x%" PRIx64, __FUNCTION__, + cursor); if (cursor == LLDB_INVALID_ADDRESS) return false; @@ -168,7 +160,10 @@ bool DYLDRendezvous::Resolve() { m_previous = m_current; m_current = info; - if (UpdateSOEntries(true)) + if (m_current.map_addr == 0) + return false; + + if (UpdateSOEntriesFromRemote()) return true; return UpdateSOEntries(); @@ -178,53 +173,91 @@ bool DYLDRendezvous::IsValid() { return m_rendezvous_addr != LLDB_INVALID_ADDRESS; } -bool DYLDRendezvous::UpdateSOEntries(bool fromRemote) { - SOEntry entry; - LoadedModuleInfoList module_list; +DYLDRendezvous::RendezvousAction DYLDRendezvous::GetAction() const { + switch (m_current.state) { + + case eConsistent: + switch (m_previous.state) { + // When the previous and current states are consistent this is the first + // time we have been asked to update. Just take a snapshot of the + // currently loaded modules. + case eConsistent: + return eTakeSnapshot; + // If we are about to add or remove a shared object clear out the current + // state and take a snapshot of the currently loaded images. + case eAdd: + return eAddModules; + case eDelete: + return eRemoveModules; + } + break; - // If we can't get the SO info from the remote, return failure. - if (fromRemote && m_process->LoadModules(module_list) == 0) - return false; + case eAdd: + case eDelete: + // Some versions of the android dynamic linker might send two + // notifications with state == eAdd back to back. Ignore them until we + // get an eConsistent notification. + if (!(m_previous.state == eConsistent || + (m_previous.state == eAdd && m_current.state == eDelete))) + return eNoAction; + + return eTakeSnapshot; + } + + return eNoAction; +} + +bool DYLDRendezvous::UpdateSOEntriesFromRemote() { + auto action = GetAction(); - if (!fromRemote && m_current.map_addr == 0) + if (action == eNoAction) return false; - // When the previous and current states are consistent this is the first time - // we have been asked to update. Just take a snapshot of the currently - // loaded modules. - if (m_previous.state == eConsistent && m_current.state == eConsistent) - return fromRemote ? SaveSOEntriesFromRemote(module_list) - : TakeSnapshot(m_soentries); - - // If we are about to add or remove a shared object clear out the current - // state and take a snapshot of the currently loaded images. - if (m_current.state == eAdd || m_current.state == eDelete) { - // Some versions of the android dynamic linker might send two notifications - // with state == eAdd back to back. Ignore them until we get an eConsistent - // notification. - if (!(m_previous.state == eConsistent || - (m_previous.state == eAdd && m_current.state == eDelete))) - return false; + if (action == eTakeSnapshot) { + m_added_soentries.clear(); + m_removed_soentries.clear(); + // We already have the loaded list from the previous update so no need to + // find all the modules again. + if (!m_loaded_modules.m_list.empty()) + return true; + } + + llvm::Expected<LoadedModuleInfoList> module_list = + m_process->GetLoadedModuleList(); + if (!module_list) { + llvm::consumeError(module_list.takeError()); + return false; + } + switch (action) { + case eTakeSnapshot: m_soentries.clear(); - if (fromRemote) - return SaveSOEntriesFromRemote(module_list); + return SaveSOEntriesFromRemote(*module_list); + case eAddModules: + return AddSOEntriesFromRemote(*module_list); + case eRemoveModules: + return RemoveSOEntriesFromRemote(*module_list); + case eNoAction: + return false; + } + llvm_unreachable("Fully covered switch above!"); +} +bool DYLDRendezvous::UpdateSOEntries() { + switch (GetAction()) { + case eTakeSnapshot: + m_soentries.clear(); m_added_soentries.clear(); m_removed_soentries.clear(); return TakeSnapshot(m_soentries); + case eAddModules: + return AddSOEntries(); + case eRemoveModules: + return RemoveSOEntries(); + case eNoAction: + return false; } - assert(m_current.state == eConsistent); - - // Otherwise check the previous state to determine what to expect and update - // accordingly. - if (m_previous.state == eAdd) - return fromRemote ? AddSOEntriesFromRemote(module_list) : AddSOEntries(); - else if (m_previous.state == eDelete) - return fromRemote ? RemoveSOEntriesFromRemote(module_list) - : RemoveSOEntries(); - - return false; + llvm_unreachable("Fully covered switch above!"); } bool DYLDRendezvous::FillSOEntryFromModuleInfo( @@ -255,7 +288,7 @@ bool DYLDRendezvous::FillSOEntryFromModuleInfo( } bool DYLDRendezvous::SaveSOEntriesFromRemote( - LoadedModuleInfoList &module_list) { + const LoadedModuleInfoList &module_list) { for (auto const &modInfo : module_list.m_list) { SOEntry entry; if (!FillSOEntryFromModuleInfo(modInfo, entry)) @@ -270,7 +303,8 @@ bool DYLDRendezvous::SaveSOEntriesFromRemote( return true; } -bool DYLDRendezvous::AddSOEntriesFromRemote(LoadedModuleInfoList &module_list) { +bool DYLDRendezvous::AddSOEntriesFromRemote( + const LoadedModuleInfoList &module_list) { for (auto const &modInfo : module_list.m_list) { bool found = false; for (auto const &existing : m_loaded_modules.m_list) { @@ -288,8 +322,10 @@ bool DYLDRendezvous::AddSOEntriesFromRemote(LoadedModuleInfoList &module_list) { return false; // Only add shared libraries and not the executable. - if (!SOEntryIsMainExecutable(entry)) + if (!SOEntryIsMainExecutable(entry)) { m_soentries.push_back(entry); + m_added_soentries.push_back(entry); + } } m_loaded_modules = module_list; @@ -297,7 +333,7 @@ bool DYLDRendezvous::AddSOEntriesFromRemote(LoadedModuleInfoList &module_list) { } bool DYLDRendezvous::RemoveSOEntriesFromRemote( - LoadedModuleInfoList &module_list) { + const LoadedModuleInfoList &module_list) { for (auto const &existing : m_loaded_modules.m_list) { bool found = false; for (auto const &modInfo : module_list.m_list) { @@ -321,6 +357,7 @@ bool DYLDRendezvous::RemoveSOEntriesFromRemote( return false; m_soentries.erase(pos); + m_removed_soentries.push_back(entry); } } @@ -521,9 +558,10 @@ bool DYLDRendezvous::FindMetadata(const char *name, PThreadField field, Target &target = m_process->GetTarget(); SymbolContextList list; - if (!target.GetImages().FindSymbolsWithNameAndType(ConstString(name), - eSymbolTypeAny, list)) - return false; + target.GetImages().FindSymbolsWithNameAndType(ConstString(name), + eSymbolTypeAny, list); + if (list.IsEmpty()) + return false; Address address = list[0].symbol->GetAddress(); addr_t addr = address.GetLoadAddress(&target); @@ -569,16 +607,16 @@ void DYLDRendezvous::DumpToLog(Log *log) const { return; log->PutCString("DYLDRendezvous:"); - log->Printf(" Address: %" PRIx64, GetRendezvousAddress()); - log->Printf(" Version: %" PRIu64, GetVersion()); - log->Printf(" Link : %" PRIx64, GetLinkMapAddress()); - log->Printf(" Break : %" PRIx64, GetBreakAddress()); - log->Printf(" LDBase : %" PRIx64, GetLDBase()); - log->Printf(" State : %s", - (state == eConsistent) - ? "consistent" - : (state == eAdd) ? "add" : (state == eDelete) ? "delete" - : "unknown"); + LLDB_LOGF(log, " Address: %" PRIx64, GetRendezvousAddress()); + LLDB_LOGF(log, " Version: %" PRIu64, GetVersion()); + LLDB_LOGF(log, " Link : %" PRIx64, GetLinkMapAddress()); + LLDB_LOGF(log, " Break : %" PRIx64, GetBreakAddress()); + LLDB_LOGF(log, " LDBase : %" PRIx64, GetLDBase()); + LLDB_LOGF(log, " State : %s", + (state == eConsistent) + ? "consistent" + : (state == eAdd) ? "add" + : (state == eDelete) ? "delete" : "unknown"); iterator I = begin(); iterator E = end(); @@ -587,11 +625,11 @@ void DYLDRendezvous::DumpToLog(Log *log) const { log->PutCString("DYLDRendezvous SOEntries:"); for (int i = 1; I != E; ++I, ++i) { - log->Printf("\n SOEntry [%d] %s", i, I->file_spec.GetCString()); - log->Printf(" Base : %" PRIx64, I->base_addr); - log->Printf(" Path : %" PRIx64, I->path_addr); - log->Printf(" Dyn : %" PRIx64, I->dyn_addr); - log->Printf(" Next : %" PRIx64, I->next); - log->Printf(" Prev : %" PRIx64, I->prev); + LLDB_LOGF(log, "\n SOEntry [%d] %s", i, I->file_spec.GetCString()); + LLDB_LOGF(log, " Base : %" PRIx64, I->base_addr); + LLDB_LOGF(log, " Path : %" PRIx64, I->path_addr); + LLDB_LOGF(log, " Dyn : %" PRIx64, I->dyn_addr); + LLDB_LOGF(log, " Next : %" PRIx64, I->next); + LLDB_LOGF(log, " Prev : %" PRIx64, I->prev); } } diff --git a/source/Plugins/DynamicLoader/POSIX-DYLD/DYLDRendezvous.h b/source/Plugins/DynamicLoader/POSIX-DYLD/DYLDRendezvous.h index 993e62f5e9f9..536eeeaaf334 100644 --- a/source/Plugins/DynamicLoader/POSIX-DYLD/DYLDRendezvous.h +++ b/source/Plugins/DynamicLoader/POSIX-DYLD/DYLDRendezvous.h @@ -222,16 +222,20 @@ protected: /// Updates the current set of SOEntries, the set of added entries, and the /// set of removed entries. - bool UpdateSOEntries(bool fromRemote = false); + bool UpdateSOEntries(); + + /// Same as UpdateSOEntries but it gets the list of loaded modules from the + /// remote debug server (faster when supported). + bool UpdateSOEntriesFromRemote(); bool FillSOEntryFromModuleInfo( LoadedModuleInfoList::LoadedModuleInfo const &modInfo, SOEntry &entry); - bool SaveSOEntriesFromRemote(LoadedModuleInfoList &module_list); + bool SaveSOEntriesFromRemote(const LoadedModuleInfoList &module_list); - bool AddSOEntriesFromRemote(LoadedModuleInfoList &module_list); + bool AddSOEntriesFromRemote(const LoadedModuleInfoList &module_list); - bool RemoveSOEntriesFromRemote(LoadedModuleInfoList &module_list); + bool RemoveSOEntriesFromRemote(const LoadedModuleInfoList &module_list); bool AddSOEntries(); @@ -248,6 +252,17 @@ protected: enum PThreadField { eSize, eNElem, eOffset }; bool FindMetadata(const char *name, PThreadField field, uint32_t &value); + + enum RendezvousAction { + eNoAction, + eTakeSnapshot, + eAddModules, + eRemoveModules + }; + + /// Returns the current action to be taken given the current and previous + /// state + RendezvousAction GetAction() const; }; #endif diff --git a/source/Plugins/DynamicLoader/POSIX-DYLD/DynamicLoaderPOSIXDYLD.cpp b/source/Plugins/DynamicLoader/POSIX-DYLD/DynamicLoaderPOSIXDYLD.cpp index b55660899d0d..9d61c8feb923 100644 --- a/source/Plugins/DynamicLoader/POSIX-DYLD/DynamicLoaderPOSIXDYLD.cpp +++ b/source/Plugins/DynamicLoader/POSIX-DYLD/DynamicLoaderPOSIXDYLD.cpp @@ -85,32 +85,31 @@ DynamicLoaderPOSIXDYLD::~DynamicLoaderPOSIXDYLD() { void DynamicLoaderPOSIXDYLD::DidAttach() { Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_DYNAMIC_LOADER)); - if (log) - log->Printf("DynamicLoaderPOSIXDYLD::%s() pid %" PRIu64, __FUNCTION__, - m_process ? m_process->GetID() : LLDB_INVALID_PROCESS_ID); - m_auxv = llvm::make_unique<AuxVector>(m_process->GetAuxvData()); + LLDB_LOGF(log, "DynamicLoaderPOSIXDYLD::%s() pid %" PRIu64, __FUNCTION__, + m_process ? m_process->GetID() : LLDB_INVALID_PROCESS_ID); + m_auxv = std::make_unique<AuxVector>(m_process->GetAuxvData()); - if (log) - log->Printf("DynamicLoaderPOSIXDYLD::%s pid %" PRIu64 " reloaded auxv data", - __FUNCTION__, - m_process ? m_process->GetID() : LLDB_INVALID_PROCESS_ID); + LLDB_LOGF( + log, "DynamicLoaderPOSIXDYLD::%s pid %" PRIu64 " reloaded auxv data", + __FUNCTION__, m_process ? m_process->GetID() : LLDB_INVALID_PROCESS_ID); // ask the process if it can load any of its own modules - m_process->LoadModules(); + auto error = m_process->LoadModules(); + LLDB_LOG_ERROR(log, std::move(error), "Couldn't load modules: {0}"); ModuleSP executable_sp = GetTargetExecutable(); ResolveExecutableModule(executable_sp); // find the main process load offset addr_t load_offset = ComputeLoadOffset(); - if (log) - log->Printf("DynamicLoaderPOSIXDYLD::%s pid %" PRIu64 - " executable '%s', load_offset 0x%" PRIx64, - __FUNCTION__, - m_process ? m_process->GetID() : LLDB_INVALID_PROCESS_ID, - executable_sp ? executable_sp->GetFileSpec().GetPath().c_str() - : "<null executable>", - load_offset); + LLDB_LOGF(log, + "DynamicLoaderPOSIXDYLD::%s pid %" PRIu64 + " executable '%s', load_offset 0x%" PRIx64, + __FUNCTION__, + m_process ? m_process->GetID() : LLDB_INVALID_PROCESS_ID, + executable_sp ? executable_sp->GetFileSpec().GetPath().c_str() + : "<null executable>", + load_offset); EvalSpecialModulesStatus(); @@ -137,12 +136,12 @@ void DynamicLoaderPOSIXDYLD::DidAttach() { ModuleList module_list; module_list.Append(executable_sp); - if (log) - log->Printf("DynamicLoaderPOSIXDYLD::%s pid %" PRIu64 - " added executable '%s' to module load list", - __FUNCTION__, - m_process ? m_process->GetID() : LLDB_INVALID_PROCESS_ID, - executable_sp->GetFileSpec().GetPath().c_str()); + LLDB_LOGF(log, + "DynamicLoaderPOSIXDYLD::%s pid %" PRIu64 + " added executable '%s' to module load list", + __FUNCTION__, + m_process ? m_process->GetID() : LLDB_INVALID_PROCESS_ID, + executable_sp->GetFileSpec().GetPath().c_str()); UpdateLoadedSections(executable_sp, LLDB_INVALID_ADDRESS, load_offset, true); @@ -151,14 +150,15 @@ void DynamicLoaderPOSIXDYLD::DidAttach() { m_process->GetTarget().ModulesDidLoad(module_list); if (log) { - log->Printf("DynamicLoaderPOSIXDYLD::%s told the target about the " - "modules that loaded:", - __FUNCTION__); + LLDB_LOGF(log, + "DynamicLoaderPOSIXDYLD::%s told the target about the " + "modules that loaded:", + __FUNCTION__); for (auto module_sp : module_list.Modules()) { - log->Printf("-- [module] %s (pid %" PRIu64 ")", - module_sp ? module_sp->GetFileSpec().GetPath().c_str() - : "<null>", - m_process ? m_process->GetID() : LLDB_INVALID_PROCESS_ID); + LLDB_LOGF(log, "-- [module] %s (pid %" PRIu64 ")", + module_sp ? module_sp->GetFileSpec().GetPath().c_str() + : "<null>", + m_process ? m_process->GetID() : LLDB_INVALID_PROCESS_ID); } } } @@ -174,13 +174,12 @@ void DynamicLoaderPOSIXDYLD::DidAttach() { void DynamicLoaderPOSIXDYLD::DidLaunch() { Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_DYNAMIC_LOADER)); - if (log) - log->Printf("DynamicLoaderPOSIXDYLD::%s()", __FUNCTION__); + LLDB_LOGF(log, "DynamicLoaderPOSIXDYLD::%s()", __FUNCTION__); ModuleSP executable; addr_t load_offset; - m_auxv = llvm::make_unique<AuxVector>(m_process->GetAuxvData()); + m_auxv = std::make_unique<AuxVector>(m_process->GetAuxvData()); executable = GetTargetExecutable(); load_offset = ComputeLoadOffset(); @@ -191,9 +190,8 @@ void DynamicLoaderPOSIXDYLD::DidLaunch() { module_list.Append(executable); UpdateLoadedSections(executable, LLDB_INVALID_ADDRESS, load_offset, true); - if (log) - log->Printf("DynamicLoaderPOSIXDYLD::%s about to call ProbeEntry()", - __FUNCTION__); + LLDB_LOGF(log, "DynamicLoaderPOSIXDYLD::%s about to call ProbeEntry()", + __FUNCTION__); if (!SetRendezvousBreakpoint()) { // If we cannot establish rendezvous breakpoint right now we'll try again @@ -227,22 +225,20 @@ void DynamicLoaderPOSIXDYLD::ProbeEntry() { const addr_t entry = GetEntryPoint(); if (entry == LLDB_INVALID_ADDRESS) { - if (log) - log->Printf( - "DynamicLoaderPOSIXDYLD::%s pid %" PRIu64 - " GetEntryPoint() returned no address, not setting entry breakpoint", - __FUNCTION__, - m_process ? m_process->GetID() : LLDB_INVALID_PROCESS_ID); + LLDB_LOGF( + log, + "DynamicLoaderPOSIXDYLD::%s pid %" PRIu64 + " GetEntryPoint() returned no address, not setting entry breakpoint", + __FUNCTION__, m_process ? m_process->GetID() : LLDB_INVALID_PROCESS_ID); return; } - if (log) - log->Printf("DynamicLoaderPOSIXDYLD::%s pid %" PRIu64 - " GetEntryPoint() returned address 0x%" PRIx64 - ", setting entry breakpoint", - __FUNCTION__, - m_process ? m_process->GetID() : LLDB_INVALID_PROCESS_ID, - entry); + LLDB_LOGF(log, + "DynamicLoaderPOSIXDYLD::%s pid %" PRIu64 + " GetEntryPoint() returned address 0x%" PRIx64 + ", setting entry breakpoint", + __FUNCTION__, + m_process ? m_process->GetID() : LLDB_INVALID_PROCESS_ID, entry); if (m_process) { Breakpoint *const entry_break = @@ -271,11 +267,10 @@ bool DynamicLoaderPOSIXDYLD::EntryBreakpointHit( Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_DYNAMIC_LOADER)); DynamicLoaderPOSIXDYLD *const dyld_instance = static_cast<DynamicLoaderPOSIXDYLD *>(baton); - if (log) - log->Printf("DynamicLoaderPOSIXDYLD::%s called for pid %" PRIu64, - __FUNCTION__, - dyld_instance->m_process ? dyld_instance->m_process->GetID() - : LLDB_INVALID_PROCESS_ID); + LLDB_LOGF(log, "DynamicLoaderPOSIXDYLD::%s called for pid %" PRIu64, + __FUNCTION__, + dyld_instance->m_process ? dyld_instance->m_process->GetID() + : LLDB_INVALID_PROCESS_ID); // Disable the breakpoint --- if a stop happens right after this, which we've // seen on occasion, we don't want the breakpoint stepping thread-plan logic @@ -287,22 +282,22 @@ bool DynamicLoaderPOSIXDYLD::EntryBreakpointHit( BreakpointSP breakpoint_sp = dyld_instance->m_process->GetTarget().GetBreakpointByID(break_id); if (breakpoint_sp) { - if (log) - log->Printf("DynamicLoaderPOSIXDYLD::%s pid %" PRIu64 - " disabling breakpoint id %" PRIu64, - __FUNCTION__, dyld_instance->m_process->GetID(), break_id); + LLDB_LOGF(log, + "DynamicLoaderPOSIXDYLD::%s pid %" PRIu64 + " disabling breakpoint id %" PRIu64, + __FUNCTION__, dyld_instance->m_process->GetID(), break_id); breakpoint_sp->SetEnabled(false); } else { - if (log) - log->Printf("DynamicLoaderPOSIXDYLD::%s pid %" PRIu64 - " failed to find breakpoint for breakpoint id %" PRIu64, - __FUNCTION__, dyld_instance->m_process->GetID(), break_id); + LLDB_LOGF(log, + "DynamicLoaderPOSIXDYLD::%s pid %" PRIu64 + " failed to find breakpoint for breakpoint id %" PRIu64, + __FUNCTION__, dyld_instance->m_process->GetID(), break_id); } } else { - if (log) - log->Printf("DynamicLoaderPOSIXDYLD::%s breakpoint id %" PRIu64 - " no Process instance! Cannot disable breakpoint", - __FUNCTION__, break_id); + LLDB_LOGF(log, + "DynamicLoaderPOSIXDYLD::%s breakpoint id %" PRIu64 + " no Process instance! Cannot disable breakpoint", + __FUNCTION__, break_id); } dyld_instance->LoadAllCurrentModules(); @@ -393,23 +388,22 @@ bool DynamicLoaderPOSIXDYLD::RendezvousBreakpointHit( Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_DYNAMIC_LOADER)); DynamicLoaderPOSIXDYLD *const dyld_instance = static_cast<DynamicLoaderPOSIXDYLD *>(baton); - if (log) - log->Printf("DynamicLoaderPOSIXDYLD::%s called for pid %" PRIu64, - __FUNCTION__, - dyld_instance->m_process ? dyld_instance->m_process->GetID() - : LLDB_INVALID_PROCESS_ID); + LLDB_LOGF(log, "DynamicLoaderPOSIXDYLD::%s called for pid %" PRIu64, + __FUNCTION__, + dyld_instance->m_process ? dyld_instance->m_process->GetID() + : LLDB_INVALID_PROCESS_ID); dyld_instance->RefreshModules(); // Return true to stop the target, false to just let the target run. const bool stop_when_images_change = dyld_instance->GetStopWhenImagesChange(); - if (log) - log->Printf("DynamicLoaderPOSIXDYLD::%s pid %" PRIu64 - " stop_when_images_change=%s", - __FUNCTION__, - dyld_instance->m_process ? dyld_instance->m_process->GetID() - : LLDB_INVALID_PROCESS_ID, - stop_when_images_change ? "true" : "false"); + LLDB_LOGF(log, + "DynamicLoaderPOSIXDYLD::%s pid %" PRIu64 + " stop_when_images_change=%s", + __FUNCTION__, + dyld_instance->m_process ? dyld_instance->m_process->GetID() + : LLDB_INVALID_PROCESS_ID, + stop_when_images_change ? "true" : "false"); return stop_when_images_change; } @@ -562,10 +556,10 @@ void DynamicLoaderPOSIXDYLD::LoadAllCurrentModules() { LoadVDSO(); if (!m_rendezvous.Resolve()) { - if (log) - log->Printf("DynamicLoaderPOSIXDYLD::%s unable to resolve POSIX DYLD " - "rendezvous address", - __FUNCTION__); + LLDB_LOGF(log, + "DynamicLoaderPOSIXDYLD::%s unable to resolve POSIX DYLD " + "rendezvous address", + __FUNCTION__); return; } @@ -589,10 +583,10 @@ void DynamicLoaderPOSIXDYLD::LoadAllCurrentModules() { module_list.Append(module_sp); } else { Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_DYNAMIC_LOADER)); - if (log) - log->Printf( - "DynamicLoaderPOSIXDYLD::%s failed loading module %s at 0x%" PRIx64, - __FUNCTION__, I->file_spec.GetCString(), I->base_addr); + LLDB_LOGF( + log, + "DynamicLoaderPOSIXDYLD::%s failed loading module %s at 0x%" PRIx64, + __FUNCTION__, I->file_spec.GetCString(), I->base_addr); } } @@ -697,12 +691,12 @@ DynamicLoaderPOSIXDYLD::GetThreadLocalData(const lldb::ModuleSP module_sp, addr_t tls_block = ReadPointer(dtv_slot + metadata.tls_offset); Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_DYNAMIC_LOADER)); - if (log) - log->Printf("DynamicLoaderPOSIXDYLD::Performed TLS lookup: " - "module=%s, link_map=0x%" PRIx64 ", tp=0x%" PRIx64 - ", modid=%" PRId64 ", tls_block=0x%" PRIx64 "\n", - module_sp->GetObjectName().AsCString(""), link_map, tp, - (int64_t)modid, tls_block); + LLDB_LOGF(log, + "DynamicLoaderPOSIXDYLD::Performed TLS lookup: " + "module=%s, link_map=0x%" PRIx64 ", tp=0x%" PRIx64 + ", modid=%" PRId64 ", tls_block=0x%" PRIx64 "\n", + module_sp->GetObjectName().AsCString(""), link_map, tp, + (int64_t)modid, tls_block); if (tls_block == LLDB_INVALID_ADDRESS) return LLDB_INVALID_ADDRESS; @@ -722,18 +716,17 @@ void DynamicLoaderPOSIXDYLD::ResolveExecutableModule( ProcessInstanceInfo process_info; if (!m_process->GetProcessInfo(process_info)) { - if (log) - log->Printf("DynamicLoaderPOSIXDYLD::%s - failed to get process info for " - "pid %" PRIu64, - __FUNCTION__, m_process->GetID()); + LLDB_LOGF(log, + "DynamicLoaderPOSIXDYLD::%s - failed to get process info for " + "pid %" PRIu64, + __FUNCTION__, m_process->GetID()); return; } - if (log) - log->Printf("DynamicLoaderPOSIXDYLD::%s - got executable by pid %" PRIu64 - ": %s", - __FUNCTION__, m_process->GetID(), - process_info.GetExecutableFile().GetPath().c_str()); + LLDB_LOGF( + log, "DynamicLoaderPOSIXDYLD::%s - got executable by pid %" PRIu64 ": %s", + __FUNCTION__, m_process->GetID(), + process_info.GetExecutableFile().GetPath().c_str()); ModuleSpec module_spec(process_info.GetExecutableFile(), process_info.GetArchitecture()); @@ -748,10 +741,10 @@ void DynamicLoaderPOSIXDYLD::ResolveExecutableModule( StreamString stream; module_spec.Dump(stream); - if (log) - log->Printf("DynamicLoaderPOSIXDYLD::%s - failed to resolve executable " - "with module spec \"%s\": %s", - __FUNCTION__, stream.GetData(), error.AsCString()); + LLDB_LOGF(log, + "DynamicLoaderPOSIXDYLD::%s - failed to resolve executable " + "with module spec \"%s\": %s", + __FUNCTION__, stream.GetData(), error.AsCString()); return; } diff --git a/source/Plugins/DynamicLoader/Windows-DYLD/DynamicLoaderWindowsDYLD.cpp b/source/Plugins/DynamicLoader/Windows-DYLD/DynamicLoaderWindowsDYLD.cpp index fa3fbe0d9fa6..25ab30e9db9c 100644 --- a/source/Plugins/DynamicLoader/Windows-DYLD/DynamicLoaderWindowsDYLD.cpp +++ b/source/Plugins/DynamicLoader/Windows-DYLD/DynamicLoaderWindowsDYLD.cpp @@ -122,38 +122,37 @@ lldb::addr_t DynamicLoaderWindowsDYLD::GetLoadAddress(ModuleSP executable) { void DynamicLoaderWindowsDYLD::DidAttach() { Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_DYNAMIC_LOADER)); - if (log) - log->Printf("DynamicLoaderWindowsDYLD::%s()", __FUNCTION__); + LLDB_LOGF(log, "DynamicLoaderWindowsDYLD::%s()", __FUNCTION__); - ModuleSP executable = GetTargetExecutable(); + ModuleSP executable = GetTargetExecutable(); - if (!executable.get()) - return; + if (!executable.get()) + return; - // Try to fetch the load address of the file from the process, since there - // could be randomization of the load address. - lldb::addr_t load_addr = GetLoadAddress(executable); - if (load_addr == LLDB_INVALID_ADDRESS) - return; + // Try to fetch the load address of the file from the process, since there + // could be randomization of the load address. + lldb::addr_t load_addr = GetLoadAddress(executable); + if (load_addr == LLDB_INVALID_ADDRESS) + return; - // Request the process base address. - lldb::addr_t image_base = m_process->GetImageInfoAddress(); - if (image_base == load_addr) - return; + // Request the process base address. + lldb::addr_t image_base = m_process->GetImageInfoAddress(); + if (image_base == load_addr) + return; - // Rebase the process's modules if there is a mismatch. - UpdateLoadedSections(executable, LLDB_INVALID_ADDRESS, load_addr, false); + // Rebase the process's modules if there is a mismatch. + UpdateLoadedSections(executable, LLDB_INVALID_ADDRESS, load_addr, false); - ModuleList module_list; - module_list.Append(executable); - m_process->GetTarget().ModulesDidLoad(module_list); - m_process->LoadModules(); + ModuleList module_list; + module_list.Append(executable); + m_process->GetTarget().ModulesDidLoad(module_list); + auto error = m_process->LoadModules(); + LLDB_LOG_ERROR(log, std::move(error), "failed to load modules: {0}"); } void DynamicLoaderWindowsDYLD::DidLaunch() { Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_DYNAMIC_LOADER)); - if (log) - log->Printf("DynamicLoaderWindowsDYLD::%s()", __FUNCTION__); + LLDB_LOGF(log, "DynamicLoaderWindowsDYLD::%s()", __FUNCTION__); ModuleSP executable = GetTargetExecutable(); if (!executable.get()) @@ -167,7 +166,8 @@ void DynamicLoaderWindowsDYLD::DidLaunch() { ModuleList module_list; module_list.Append(executable); m_process->GetTarget().ModulesDidLoad(module_list); - m_process->LoadModules(); + auto error = m_process->LoadModules(); + LLDB_LOG_ERROR(log, std::move(error), "failed to load modules: {0}"); } } diff --git a/source/Plugins/ExpressionParser/Clang/ASTDumper.cpp b/source/Plugins/ExpressionParser/Clang/ASTDumper.cpp index 369f88327dd9..f33a713cc0b2 100644 --- a/source/Plugins/ExpressionParser/Clang/ASTDumper.cpp +++ b/source/Plugins/ExpressionParser/Clang/ASTDumper.cpp @@ -75,8 +75,6 @@ ASTDumper::ASTDumper(const CompilerType &compiler_type) { const char *ASTDumper::GetCString() { return m_dump.c_str(); } -void ASTDumper::ToSTDERR() { fprintf(stderr, "%s\n", m_dump.c_str()); } - void ASTDumper::ToLog(Log *log, const char *prefix) { size_t len = m_dump.length() + 1; @@ -92,7 +90,7 @@ void ASTDumper::ToLog(Log *log, const char *prefix) { while (end) { *end = '\0'; - log->Printf("%s%s", prefix, str); + LLDB_LOGF(log, "%s%s", prefix, str); *end = '\n'; @@ -100,9 +98,7 @@ void ASTDumper::ToLog(Log *log, const char *prefix) { end = strchr(str, '\n'); } - log->Printf("%s%s", prefix, str); + LLDB_LOGF(log, "%s%s", prefix, str); free(alloc); } - -void ASTDumper::ToStream(lldb::StreamSP &stream) { stream->PutCString(m_dump); } diff --git a/source/Plugins/ExpressionParser/Clang/ASTResultSynthesizer.cpp b/source/Plugins/ExpressionParser/Clang/ASTResultSynthesizer.cpp index 526ef90782ef..68eaad33f51c 100644 --- a/source/Plugins/ExpressionParser/Clang/ASTResultSynthesizer.cpp +++ b/source/Plugins/ExpressionParser/Clang/ASTResultSynthesizer.cpp @@ -58,13 +58,13 @@ void ASTResultSynthesizer::TransformTopLevelDecl(Decl *D) { if (NamedDecl *named_decl = dyn_cast<NamedDecl>(D)) { if (log && log->GetVerbose()) { if (named_decl->getIdentifier()) - log->Printf("TransformTopLevelDecl(%s)", - named_decl->getIdentifier()->getNameStart()); + LLDB_LOGF(log, "TransformTopLevelDecl(%s)", + named_decl->getIdentifier()->getNameStart()); else if (ObjCMethodDecl *method_decl = dyn_cast<ObjCMethodDecl>(D)) - log->Printf("TransformTopLevelDecl(%s)", - method_decl->getSelector().getAsString().c_str()); + LLDB_LOGF(log, "TransformTopLevelDecl(%s)", + method_decl->getSelector().getAsString().c_str()); else - log->Printf("TransformTopLevelDecl(<complex>)"); + LLDB_LOGF(log, "TransformTopLevelDecl(<complex>)"); } if (m_top_level) { @@ -130,7 +130,7 @@ bool ASTResultSynthesizer::SynthesizeFunctionResult(FunctionDecl *FunDecl) { os.flush(); - log->Printf("Untransformed function AST:\n%s", s.c_str()); + LLDB_LOGF(log, "Untransformed function AST:\n%s", s.c_str()); } Stmt *function_body = function_decl->getBody(); @@ -146,7 +146,7 @@ bool ASTResultSynthesizer::SynthesizeFunctionResult(FunctionDecl *FunDecl) { os.flush(); - log->Printf("Transformed function AST:\n%s", s.c_str()); + LLDB_LOGF(log, "Transformed function AST:\n%s", s.c_str()); } return ret; @@ -170,7 +170,7 @@ bool ASTResultSynthesizer::SynthesizeObjCMethodResult( os.flush(); - log->Printf("Untransformed method AST:\n%s", s.c_str()); + LLDB_LOGF(log, "Untransformed method AST:\n%s", s.c_str()); } Stmt *method_body = MethodDecl->getBody(); @@ -190,7 +190,7 @@ bool ASTResultSynthesizer::SynthesizeObjCMethodResult( os.flush(); - log->Printf("Transformed method AST:\n%s", s.c_str()); + LLDB_LOGF(log, "Transformed method AST:\n%s", s.c_str()); } return ret; @@ -308,8 +308,8 @@ bool ASTResultSynthesizer::SynthesizeBodyResult(CompoundStmt *Body, if (log) { std::string s = expr_qual_type.getAsString(); - log->Printf("Last statement is an %s with type: %s", - (is_lvalue ? "lvalue" : "rvalue"), s.c_str()); + LLDB_LOGF(log, "Last statement is an %s with type: %s", + (is_lvalue ? "lvalue" : "rvalue"), s.c_str()); } clang::VarDecl *result_decl = nullptr; @@ -422,8 +422,7 @@ void ASTResultSynthesizer::MaybeRecordPersistentType(TypeDecl *D) { ConstString name_cs(name.str().c_str()); - if (log) - log->Printf("Recording persistent type %s\n", name_cs.GetCString()); + LLDB_LOGF(log, "Recording persistent type %s\n", name_cs.GetCString()); m_decls.push_back(D); } @@ -443,8 +442,7 @@ void ASTResultSynthesizer::RecordPersistentDecl(NamedDecl *D) { ConstString name_cs(name.str().c_str()); - if (log) - log->Printf("Recording persistent decl %s\n", name_cs.GetCString()); + LLDB_LOGF(log, "Recording persistent decl %s\n", name_cs.GetCString()); m_decls.push_back(D); } @@ -467,7 +465,7 @@ void ASTResultSynthesizer::CommitPersistentDecls() { decl->dump(ss); ss.flush(); - log->Printf("Couldn't commit persistent decl: %s\n", s.c_str()); + LLDB_LOGF(log, "Couldn't commit persistent decl: %s\n", s.c_str()); } continue; diff --git a/source/Plugins/ExpressionParser/Clang/ClangASTSource.cpp b/source/Plugins/ExpressionParser/Clang/ClangASTSource.cpp index c5778f86bb62..372c2439ebf0 100644 --- a/source/Plugins/ExpressionParser/Clang/ClangASTSource.cpp +++ b/source/Plugins/ExpressionParser/Clang/ClangASTSource.cpp @@ -9,6 +9,7 @@ #include "ClangASTSource.h" #include "ASTDumper.h" +#include "ClangDeclVendor.h" #include "ClangModulesDeclVendor.h" #include "lldb/Core/Module.h" @@ -18,7 +19,6 @@ #include "lldb/Symbol/CompilerDeclContext.h" #include "lldb/Symbol/Function.h" #include "lldb/Symbol/SymbolFile.h" -#include "lldb/Symbol/SymbolVendor.h" #include "lldb/Symbol/TaggedASTType.h" #include "lldb/Target/Target.h" #include "lldb/Utility/Log.h" @@ -74,14 +74,19 @@ void ClangASTSource::InstallASTContext(clang::ASTContext &ast_context, file_manager}; std::vector<clang::ExternalASTMerger::ImporterSource> sources; for (lldb::ModuleSP module_sp : m_target->GetImages().Modules()) { - if (auto *module_ast_ctx = llvm::cast_or_null<ClangASTContext>( - module_sp->GetTypeSystemForLanguage(lldb::eLanguageTypeC))) { + auto type_system_or_err = + module_sp->GetTypeSystemForLanguage(lldb::eLanguageTypeC); + if (auto err = type_system_or_err.takeError()) { + LLDB_LOG_ERROR( + lldb_private::GetLogIfAnyCategoriesSet(LIBLLDB_LOG_EXPRESSIONS), + std::move(err), "Failed to get ClangASTContext"); + } else if (auto *module_ast_ctx = llvm::cast_or_null<ClangASTContext>( + &type_system_or_err.get())) { lldbassert(module_ast_ctx->getASTContext()); lldbassert(module_ast_ctx->getFileManager()); - sources.push_back({*module_ast_ctx->getASTContext(), - *module_ast_ctx->getFileManager(), - module_ast_ctx->GetOriginMap() - }); + sources.emplace_back(*module_ast_ctx->getASTContext(), + *module_ast_ctx->getFileManager(), + module_ast_ctx->GetOriginMap()); } } @@ -96,17 +101,14 @@ void ClangASTSource::InstallASTContext(clang::ASTContext &ast_context, if (!language_runtime) break; - DeclVendor *runtime_decl_vendor = language_runtime->GetDeclVendor(); - - if (!runtime_decl_vendor) - break; - - sources.push_back(runtime_decl_vendor->GetImporterSource()); + if (auto *runtime_decl_vendor = llvm::dyn_cast_or_null<ClangDeclVendor>( + language_runtime->GetDeclVendor())) { + sources.push_back(runtime_decl_vendor->GetImporterSource()); + } } while (false); do { - DeclVendor *modules_decl_vendor = - m_target->GetClangModulesDeclVendor(); + auto *modules_decl_vendor = m_target->GetClangModulesDeclVendor(); if (!modules_decl_vendor) break; @@ -127,11 +129,9 @@ void ClangASTSource::InstallASTContext(clang::ASTContext &ast_context, *scratch_ast_context->getFileManager(), scratch_ast_context->GetOriginMap()}); } - while (false) - ; m_merger_up = - llvm::make_unique<clang::ExternalASTMerger>(target, sources); + std::make_unique<clang::ExternalASTMerger>(target, sources); } else { m_ast_importer_sp->InstallMapCompleter(&ast_context, *this); } @@ -273,13 +273,13 @@ void ClangASTSource::CompleteType(TagDecl *tag_decl) { unsigned int current_id = invocation_id++; if (log) { - log->Printf(" CompleteTagDecl[%u] on (ASTContext*)%p Completing " - "(TagDecl*)%p named %s", - current_id, static_cast<void *>(m_ast_context), - static_cast<void *>(tag_decl), - tag_decl->getName().str().c_str()); + LLDB_LOGF(log, + " CompleteTagDecl[%u] on (ASTContext*)%p Completing " + "(TagDecl*)%p named %s", + current_id, static_cast<void *>(m_ast_context), + static_cast<void *>(tag_decl), tag_decl->getName().str().c_str()); - log->Printf(" CTD[%u] Before:", current_id); + LLDB_LOGF(log, " CTD[%u] Before:", current_id); ASTDumper dumper((Decl *)tag_decl); dumper.ToLog(log, " [CTD] "); } @@ -301,10 +301,10 @@ void ClangASTSource::CompleteType(TagDecl *tag_decl) { // We couldn't complete the type. Maybe there's a definition somewhere // else that can be completed. - if (log) - log->Printf(" CTD[%u] Type could not be completed in the module in " - "which it was first found.", - current_id); + LLDB_LOGF(log, + " CTD[%u] Type could not be completed in the module in " + "which it was first found.", + current_id); bool found = false; @@ -316,9 +316,9 @@ void ClangASTSource::CompleteType(TagDecl *tag_decl) { m_ast_importer_sp->GetNamespaceMap(namespace_context); if (log && log->GetVerbose()) - log->Printf(" CTD[%u] Inspecting namespace map %p (%d entries)", - current_id, static_cast<void *>(namespace_map.get()), - static_cast<int>(namespace_map->size())); + LLDB_LOGF(log, " CTD[%u] Inspecting namespace map %p (%d entries)", + current_id, static_cast<void *>(namespace_map.get()), + static_cast<int>(namespace_map->size())); if (!namespace_map) return; @@ -326,10 +326,9 @@ void ClangASTSource::CompleteType(TagDecl *tag_decl) { for (ClangASTImporter::NamespaceMap::iterator i = namespace_map->begin(), e = namespace_map->end(); i != e && !found; ++i) { - if (log) - log->Printf(" CTD[%u] Searching namespace %s in module %s", - current_id, i->second.GetName().AsCString(), - i->first->GetFileSpec().GetFilename().GetCString()); + LLDB_LOGF(log, " CTD[%u] Searching namespace %s in module %s", + current_id, i->second.GetName().AsCString(), + i->first->GetFileSpec().GetFilename().GetCString()); TypeList types; @@ -409,7 +408,7 @@ void ClangASTSource::CompleteType(TagDecl *tag_decl) { } if (log) { - log->Printf(" [CTD] After:"); + LLDB_LOGF(log, " [CTD] After:"); ASTDumper dumper((Decl *)tag_decl); dumper.ToLog(log, " [CTD] "); } @@ -419,11 +418,12 @@ void ClangASTSource::CompleteType(clang::ObjCInterfaceDecl *interface_decl) { Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_EXPRESSIONS)); if (log) { - log->Printf(" [CompleteObjCInterfaceDecl] on (ASTContext*)%p Completing " - "an ObjCInterfaceDecl named %s", - static_cast<void *>(m_ast_context), - interface_decl->getName().str().c_str()); - log->Printf(" [COID] Before:"); + LLDB_LOGF(log, + " [CompleteObjCInterfaceDecl] on (ASTContext*)%p Completing " + "an ObjCInterfaceDecl named %s", + static_cast<void *>(m_ast_context), + interface_decl->getName().str().c_str()); + LLDB_LOGF(log, " [COID] Before:"); ASTDumper dumper((Decl *)interface_decl); dumper.ToLog(log, " [COID] "); } @@ -467,7 +467,7 @@ void ClangASTSource::CompleteType(clang::ObjCInterfaceDecl *interface_decl) { CompleteType(interface_decl->getSuperClass()); if (log) { - log->Printf(" [COID] After:"); + LLDB_LOGF(log, " [COID] After:"); ASTDumper dumper((Decl *)interface_decl); dumper.ToLog(log, " [COID] "); } @@ -554,20 +554,22 @@ void ClangASTSource::FindExternalLexicalDecls( if (log) { if (const NamedDecl *context_named_decl = dyn_cast<NamedDecl>(context_decl)) - log->Printf( + LLDB_LOGF( + log, "FindExternalLexicalDecls[%u] on (ASTContext*)%p in '%s' (%sDecl*)%p", current_id, static_cast<void *>(m_ast_context), context_named_decl->getNameAsString().c_str(), context_decl->getDeclKindName(), static_cast<const void *>(context_decl)); else if (context_decl) - log->Printf( - "FindExternalLexicalDecls[%u] on (ASTContext*)%p in (%sDecl*)%p", + LLDB_LOGF( + log, "FindExternalLexicalDecls[%u] on (ASTContext*)%p in (%sDecl*)%p", current_id, static_cast<void *>(m_ast_context), context_decl->getDeclKindName(), static_cast<const void *>(context_decl)); else - log->Printf( + LLDB_LOGF( + log, "FindExternalLexicalDecls[%u] on (ASTContext*)%p in a NULL context", current_id, static_cast<const void *>(m_ast_context)); } @@ -580,9 +582,9 @@ void ClangASTSource::FindExternalLexicalDecls( return; if (log) { - log->Printf(" FELD[%u] Original decl (ASTContext*)%p (Decl*)%p:", - current_id, static_cast<void *>(original_ctx), - static_cast<void *>(original_decl)); + LLDB_LOGF( + log, " FELD[%u] Original decl (ASTContext*)%p (Decl*)%p:", current_id, + static_cast<void *>(original_ctx), static_cast<void *>(original_decl)); ASTDumper(original_decl).ToLog(log, " "); } @@ -626,13 +628,13 @@ void ClangASTSource::FindExternalLexicalDecls( ASTDumper ast_dumper(decl); if (const NamedDecl *context_named_decl = dyn_cast<NamedDecl>(context_decl)) - log->Printf(" FELD[%d] Adding [to %sDecl %s] lexical %sDecl %s", - current_id, context_named_decl->getDeclKindName(), - context_named_decl->getNameAsString().c_str(), - decl->getDeclKindName(), ast_dumper.GetCString()); + LLDB_LOGF(log, " FELD[%d] Adding [to %sDecl %s] lexical %sDecl %s", + current_id, context_named_decl->getDeclKindName(), + context_named_decl->getNameAsString().c_str(), + decl->getDeclKindName(), ast_dumper.GetCString()); else - log->Printf(" FELD[%d] Adding lexical %sDecl %s", current_id, - decl->getDeclKindName(), ast_dumper.GetCString()); + LLDB_LOGF(log, " FELD[%d] Adding lexical %sDecl %s", current_id, + decl->getDeclKindName(), ast_dumper.GetCString()); } Decl *copied_decl = CopyDecl(decl); @@ -645,6 +647,20 @@ void ClangASTSource::FindExternalLexicalDecls( m_ast_importer_sp->RequireCompleteType(copied_field_type); } + auto decl_context_non_const = const_cast<DeclContext *>(decl_context); + + // The decl ended up in the wrong DeclContext. Let's fix that so + // the decl we copied will actually be found. + // FIXME: This is a horrible hack that shouldn't be necessary. However + // it seems our current setup sometimes fails to copy decls to the right + // place. See rdar://55129537. + if (copied_decl->getDeclContext() != decl_context) { + assert(copied_decl->getDeclContext()->containsDecl(copied_decl)); + copied_decl->getDeclContext()->removeDecl(copied_decl); + copied_decl->setDeclContext(decl_context_non_const); + assert(!decl_context_non_const->containsDecl(copied_decl)); + decl_context_non_const->addDeclInternal(copied_decl); + } } else { SkippedDecls = true; } @@ -678,22 +694,25 @@ void ClangASTSource::FindExternalVisibleDecls(NameSearchContext &context) { if (log) { if (!context.m_decl_context) - log->Printf("ClangASTSource::FindExternalVisibleDecls[%u] on " - "(ASTContext*)%p for '%s' in a NULL DeclContext", - current_id, static_cast<void *>(m_ast_context), - name.GetCString()); + LLDB_LOGF(log, + "ClangASTSource::FindExternalVisibleDecls[%u] on " + "(ASTContext*)%p for '%s' in a NULL DeclContext", + current_id, static_cast<void *>(m_ast_context), + name.GetCString()); else if (const NamedDecl *context_named_decl = dyn_cast<NamedDecl>(context.m_decl_context)) - log->Printf("ClangASTSource::FindExternalVisibleDecls[%u] on " - "(ASTContext*)%p for '%s' in '%s'", - current_id, static_cast<void *>(m_ast_context), - name.GetCString(), - context_named_decl->getNameAsString().c_str()); + LLDB_LOGF(log, + "ClangASTSource::FindExternalVisibleDecls[%u] on " + "(ASTContext*)%p for '%s' in '%s'", + current_id, static_cast<void *>(m_ast_context), + name.GetCString(), + context_named_decl->getNameAsString().c_str()); else - log->Printf("ClangASTSource::FindExternalVisibleDecls[%u] on " - "(ASTContext*)%p for '%s' in a '%s'", - current_id, static_cast<void *>(m_ast_context), - name.GetCString(), context.m_decl_context->getDeclKindName()); + LLDB_LOGF(log, + "ClangASTSource::FindExternalVisibleDecls[%u] on " + "(ASTContext*)%p for '%s' in a '%s'", + current_id, static_cast<void *>(m_ast_context), + name.GetCString(), context.m_decl_context->getDeclKindName()); } if (HasMerger() && !isa<TranslationUnitDecl>(context.m_decl_context) @@ -723,9 +742,9 @@ void ClangASTSource::FindExternalVisibleDecls(NameSearchContext &context) { m_ast_importer_sp->GetNamespaceMap(namespace_context) : nullptr; if (log && log->GetVerbose()) - log->Printf(" CAS::FEVD[%u] Inspecting namespace map %p (%d entries)", - current_id, static_cast<void *>(namespace_map.get()), - static_cast<int>(namespace_map->size())); + LLDB_LOGF(log, " CAS::FEVD[%u] Inspecting namespace map %p (%d entries)", + current_id, static_cast<void *>(namespace_map.get()), + static_cast<int>(namespace_map->size())); if (!namespace_map) return; @@ -733,10 +752,9 @@ void ClangASTSource::FindExternalVisibleDecls(NameSearchContext &context) { for (ClangASTImporter::NamespaceMap::iterator i = namespace_map->begin(), e = namespace_map->end(); i != e; ++i) { - if (log) - log->Printf(" CAS::FEVD[%u] Searching namespace %s in module %s", - current_id, i->second.GetName().AsCString(), - i->first->GetFileSpec().GetFilename().GetCString()); + LLDB_LOGF(log, " CAS::FEVD[%u] Searching namespace %s in module %s", + current_id, i->second.GetName().AsCString(), + i->first->GetFileSpec().GetFilename().GetCString()); FindExternalVisibleDecls(context, i->first, i->second, current_id); } @@ -748,8 +766,7 @@ void ClangASTSource::FindExternalVisibleDecls(NameSearchContext &context) { } else { CompilerDeclContext namespace_decl; - if (log) - log->Printf(" CAS::FEVD[%u] Searching the root namespace", current_id); + LLDB_LOGF(log, " CAS::FEVD[%u] Searching the root namespace", current_id); FindExternalVisibleDecls(context, lldb::ModuleSP(), namespace_decl, current_id); @@ -757,10 +774,10 @@ void ClangASTSource::FindExternalVisibleDecls(NameSearchContext &context) { if (!context.m_namespace_map->empty()) { if (log && log->GetVerbose()) - log->Printf(" CAS::FEVD[%u] Registering namespace map %p (%d entries)", - current_id, - static_cast<void *>(context.m_namespace_map.get()), - static_cast<int>(context.m_namespace_map->size())); + LLDB_LOGF(log, + " CAS::FEVD[%u] Registering namespace map %p (%d entries)", + current_id, static_cast<void *>(context.m_namespace_map.get()), + static_cast<int>(context.m_namespace_map->size())); NamespaceDecl *clang_namespace_decl = AddNamespace(context, context.m_namespace_map); @@ -807,21 +824,17 @@ void ClangASTSource::FindExternalVisibleDecls( if (module_sp && namespace_decl) { CompilerDeclContext found_namespace_decl; - SymbolVendor *symbol_vendor = module_sp->GetSymbolVendor(); - - if (symbol_vendor) { - found_namespace_decl = - symbol_vendor->FindNamespace(name, &namespace_decl); + if (SymbolFile *symbol_file = module_sp->GetSymbolFile()) { + found_namespace_decl = symbol_file->FindNamespace(name, &namespace_decl); if (found_namespace_decl) { context.m_namespace_map->push_back( std::pair<lldb::ModuleSP, CompilerDeclContext>( module_sp, found_namespace_decl)); - if (log) - log->Printf(" CAS::FEVD[%u] Found namespace %s in module %s", - current_id, name.GetCString(), - module_sp->GetFileSpec().GetFilename().GetCString()); + LLDB_LOGF(log, " CAS::FEVD[%u] Found namespace %s in module %s", + current_id, name.GetCString(), + module_sp->GetFileSpec().GetFilename().GetCString()); } } } else if (!HasMerger()) { @@ -836,23 +849,21 @@ void ClangASTSource::FindExternalVisibleDecls( CompilerDeclContext found_namespace_decl; - SymbolVendor *symbol_vendor = image->GetSymbolVendor(); + SymbolFile *symbol_file = image->GetSymbolFile(); - if (!symbol_vendor) + if (!symbol_file) continue; - found_namespace_decl = - symbol_vendor->FindNamespace(name, &namespace_decl); + found_namespace_decl = symbol_file->FindNamespace(name, &namespace_decl); if (found_namespace_decl) { context.m_namespace_map->push_back( std::pair<lldb::ModuleSP, CompilerDeclContext>( image, found_namespace_decl)); - if (log) - log->Printf(" CAS::FEVD[%u] Found namespace %s in module %s", - current_id, name.GetCString(), - image->GetFileSpec().GetFilename().GetCString()); + LLDB_LOGF(log, " CAS::FEVD[%u] Found namespace %s in module %s", + current_id, name.GetCString(), + image->GetFileSpec().GetFilename().GetCString()); } } } @@ -878,9 +889,9 @@ void ClangASTSource::FindExternalVisibleDecls( if (log) { const char *name_string = type_sp->GetName().GetCString(); - log->Printf(" CAS::FEVD[%u] Matching type found for \"%s\": %s", - current_id, name.GetCString(), - (name_string ? name_string : "<anonymous>")); + LLDB_LOGF(log, " CAS::FEVD[%u] Matching type found for \"%s\": %s", + current_id, name.GetCString(), + (name_string ? name_string : "<anonymous>")); } CompilerType full_type = type_sp->GetFullCompilerType(); @@ -888,8 +899,8 @@ void ClangASTSource::FindExternalVisibleDecls( CompilerType copied_clang_type(GuardedCopyType(full_type)); if (!copied_clang_type) { - if (log) - log->Printf(" CAS::FEVD[%u] - Couldn't export a type", current_id); + LLDB_LOGF(log, " CAS::FEVD[%u] - Couldn't export a type", + current_id); continue; } @@ -915,9 +926,10 @@ void ClangASTSource::FindExternalVisibleDecls( break; if (log) { - log->Printf(" CAS::FEVD[%u] Matching entity found for \"%s\" in " - "the modules", - current_id, name.GetCString()); + LLDB_LOGF(log, + " CAS::FEVD[%u] Matching entity found for \"%s\" in " + "the modules", + current_id, name.GetCString()); } clang::NamedDecl *const decl_from_modules = decls[0]; @@ -930,10 +942,10 @@ void ClangASTSource::FindExternalVisibleDecls( copied_decl ? dyn_cast<clang::NamedDecl>(copied_decl) : nullptr; if (!copied_named_decl) { - if (log) - log->Printf( - " CAS::FEVD[%u] - Couldn't export a type from the modules", - current_id); + LLDB_LOGF( + log, + " CAS::FEVD[%u] - Couldn't export a type from the modules", + current_id); break; } @@ -971,11 +983,13 @@ void ClangASTSource::FindExternalVisibleDecls( uint32_t max_matches = 1; std::vector<clang::NamedDecl *> decls; - if (!decl_vendor->FindDecls(name, append, max_matches, decls)) + auto *clang_decl_vendor = llvm::cast<ClangDeclVendor>(decl_vendor); + if (!clang_decl_vendor->FindDecls(name, append, max_matches, decls)) break; if (log) { - log->Printf( + LLDB_LOGF( + log, " CAS::FEVD[%u] Matching type found for \"%s\" in the runtime", current_id, name.GetCString()); } @@ -985,10 +999,9 @@ void ClangASTSource::FindExternalVisibleDecls( copied_decl ? dyn_cast<clang::NamedDecl>(copied_decl) : nullptr; if (!copied_named_decl) { - if (log) - log->Printf( - " CAS::FEVD[%u] - Couldn't export a type from the runtime", - current_id); + LLDB_LOGF(log, + " CAS::FEVD[%u] - Couldn't export a type from the runtime", + current_id); break; } @@ -1126,8 +1139,8 @@ bool ClangASTSource::FindObjCMethodDeclsWithOrigin( if (log) { ASTDumper dumper((Decl *)copied_method_decl); - log->Printf(" CAS::FOMD[%d] found (%s) %s", current_id, log_info, - dumper.GetCString()); + LLDB_LOGF(log, " CAS::FOMD[%d] found (%s) %s", current_id, log_info, + dumper.GetCString()); } context.AddNamedDecl(copied_method_decl); @@ -1205,17 +1218,16 @@ void ClangASTSource::FindObjCMethodDecls(NameSearchContext &context) { ConstString selector_name(ss.GetString()); - if (log) - log->Printf("ClangASTSource::FindObjCMethodDecls[%d] on (ASTContext*)%p " - "for selector [%s %s]", - current_id, static_cast<void *>(m_ast_context), - interface_decl->getNameAsString().c_str(), - selector_name.AsCString()); + LLDB_LOGF(log, + "ClangASTSource::FindObjCMethodDecls[%d] on (ASTContext*)%p " + "for selector [%s %s]", + current_id, static_cast<void *>(m_ast_context), + interface_decl->getNameAsString().c_str(), + selector_name.AsCString()); SymbolContextList sc_list; const bool include_symbols = false; const bool include_inlines = false; - const bool append = false; std::string interface_name = interface_decl->getNameAsString(); @@ -1225,9 +1237,10 @@ void ClangASTSource::FindObjCMethodDecls(NameSearchContext &context) { ms.Flush(); ConstString instance_method_name(ms.GetString()); + sc_list.Clear(); m_target->GetImages().FindFunctions( instance_method_name, lldb::eFunctionNameTypeFull, include_symbols, - include_inlines, append, sc_list); + include_inlines, sc_list); if (sc_list.GetSize()) break; @@ -1237,9 +1250,10 @@ void ClangASTSource::FindObjCMethodDecls(NameSearchContext &context) { ms.Flush(); ConstString class_method_name(ms.GetString()); + sc_list.Clear(); m_target->GetImages().FindFunctions( class_method_name, lldb::eFunctionNameTypeFull, include_symbols, - include_inlines, append, sc_list); + include_inlines, sc_list); if (sc_list.GetSize()) break; @@ -1252,7 +1266,7 @@ void ClangASTSource::FindObjCMethodDecls(NameSearchContext &context) { m_target->GetImages().FindFunctions( selector_name, lldb::eFunctionNameTypeSelector, include_symbols, - include_inlines, append, candidate_sc_list); + include_inlines, candidate_sc_list); for (uint32_t ci = 0, ce = candidate_sc_list.GetSize(); ci != ce; ++ci) { SymbolContext candidate_sc; @@ -1331,8 +1345,8 @@ void ClangASTSource::FindObjCMethodDecls(NameSearchContext &context) { if (log) { ASTDumper dumper((Decl *)copied_method_decl); - log->Printf(" CAS::FOMD[%d] found (in symbols) %s", current_id, - dumper.GetCString()); + LLDB_LOGF(log, " CAS::FOMD[%d] found (in symbols) %s", current_id, + dumper.GetCString()); } context.AddNamedDecl(copied_method_decl); @@ -1360,11 +1374,11 @@ void ClangASTSource::FindObjCMethodDecls(NameSearchContext &context) { if (complete_interface_decl == interface_decl) break; // already checked this one - if (log) - log->Printf("CAS::FOPD[%d] trying origin " - "(ObjCInterfaceDecl*)%p/(ASTContext*)%p...", - current_id, static_cast<void *>(complete_interface_decl), - static_cast<void *>(&complete_iface_decl->getASTContext())); + LLDB_LOGF(log, + "CAS::FOPD[%d] trying origin " + "(ObjCInterfaceDecl*)%p/(ASTContext*)%p...", + current_id, static_cast<void *>(complete_interface_decl), + static_cast<void *>(&complete_iface_decl->getASTContext())); FindObjCMethodDeclsWithOrigin(current_id, context, complete_interface_decl, "in debug info"); @@ -1423,7 +1437,9 @@ void ClangASTSource::FindObjCMethodDecls(NameSearchContext &context) { uint32_t max_matches = 1; std::vector<clang::NamedDecl *> decls; - if (!decl_vendor->FindDecls(interface_name, append, max_matches, decls)) + auto *clang_decl_vendor = llvm::cast<ClangDeclVendor>(decl_vendor); + if (!clang_decl_vendor->FindDecls(interface_name, append, max_matches, + decls)) break; ObjCInterfaceDecl *runtime_interface_decl = @@ -1462,8 +1478,8 @@ static bool FindObjCPropertyAndIvarDeclsWithOrigin( if (parser_property_decl.IsValid()) { if (log) { ASTDumper dumper((Decl *)parser_property_decl.decl); - log->Printf(" CAS::FOPD[%d] found %s", current_id, - dumper.GetCString()); + LLDB_LOGF(log, " CAS::FOPD[%d] found %s", current_id, + dumper.GetCString()); } context.AddNamedDecl(parser_property_decl.decl); @@ -1480,8 +1496,8 @@ static bool FindObjCPropertyAndIvarDeclsWithOrigin( if (parser_ivar_decl.IsValid()) { if (log) { ASTDumper dumper((Decl *)parser_ivar_decl.decl); - log->Printf(" CAS::FOPD[%d] found %s", current_id, - dumper.GetCString()); + LLDB_LOGF(log, " CAS::FOPD[%d] found %s", current_id, + dumper.GetCString()); } context.AddNamedDecl(parser_ivar_decl.decl); @@ -1505,23 +1521,23 @@ void ClangASTSource::FindObjCPropertyAndIvarDecls(NameSearchContext &context) { ConstString class_name(parser_iface_decl->getNameAsString().c_str()); - if (log) - log->Printf("ClangASTSource::FindObjCPropertyAndIvarDecls[%d] on " - "(ASTContext*)%p for '%s.%s'", - current_id, static_cast<void *>(m_ast_context), - parser_iface_decl->getNameAsString().c_str(), - context.m_decl_name.getAsString().c_str()); + LLDB_LOGF(log, + "ClangASTSource::FindObjCPropertyAndIvarDecls[%d] on " + "(ASTContext*)%p for '%s.%s'", + current_id, static_cast<void *>(m_ast_context), + parser_iface_decl->getNameAsString().c_str(), + context.m_decl_name.getAsString().c_str()); if (FindObjCPropertyAndIvarDeclsWithOrigin( current_id, context, *this, origin_iface_decl)) return; - if (log) - log->Printf("CAS::FOPD[%d] couldn't find the property on origin " - "(ObjCInterfaceDecl*)%p/(ASTContext*)%p, searching " - "elsewhere...", - current_id, static_cast<const void *>(origin_iface_decl.decl), - static_cast<void *>(&origin_iface_decl->getASTContext())); + LLDB_LOGF(log, + "CAS::FOPD[%d] couldn't find the property on origin " + "(ObjCInterfaceDecl*)%p/(ASTContext*)%p, searching " + "elsewhere...", + current_id, static_cast<const void *>(origin_iface_decl.decl), + static_cast<void *>(&origin_iface_decl->getASTContext())); SymbolContext null_sc; TypeList type_list; @@ -1542,12 +1558,11 @@ void ClangASTSource::FindObjCPropertyAndIvarDecls(NameSearchContext &context) { if (complete_iface_decl.decl == origin_iface_decl.decl) break; // already checked this one - if (log) - log->Printf("CAS::FOPD[%d] trying origin " - "(ObjCInterfaceDecl*)%p/(ASTContext*)%p...", - current_id, - static_cast<const void *>(complete_iface_decl.decl), - static_cast<void *>(&complete_iface_decl->getASTContext())); + LLDB_LOGF(log, + "CAS::FOPD[%d] trying origin " + "(ObjCInterfaceDecl*)%p/(ASTContext*)%p...", + current_id, static_cast<const void *>(complete_iface_decl.decl), + static_cast<void *>(&complete_iface_decl->getASTContext())); FindObjCPropertyAndIvarDeclsWithOrigin(current_id, context, *this, complete_iface_decl); @@ -1578,13 +1593,12 @@ void ClangASTSource::FindObjCPropertyAndIvarDecls(NameSearchContext &context) { if (!interface_decl_from_modules.IsValid()) break; - if (log) - log->Printf( - "CAS::FOPD[%d] trying module " - "(ObjCInterfaceDecl*)%p/(ASTContext*)%p...", - current_id, - static_cast<const void *>(interface_decl_from_modules.decl), - static_cast<void *>(&interface_decl_from_modules->getASTContext())); + LLDB_LOGF( + log, + "CAS::FOPD[%d] trying module " + "(ObjCInterfaceDecl*)%p/(ASTContext*)%p...", + current_id, static_cast<const void *>(interface_decl_from_modules.decl), + static_cast<void *>(&interface_decl_from_modules->getASTContext())); if (FindObjCPropertyAndIvarDeclsWithOrigin(current_id, context, *this, interface_decl_from_modules)) @@ -1614,7 +1628,8 @@ void ClangASTSource::FindObjCPropertyAndIvarDecls(NameSearchContext &context) { uint32_t max_matches = 1; std::vector<clang::NamedDecl *> decls; - if (!decl_vendor->FindDecls(class_name, append, max_matches, decls)) + auto *clang_decl_vendor = llvm::cast<ClangDeclVendor>(decl_vendor); + if (!clang_decl_vendor->FindDecls(class_name, append, max_matches, decls)) break; DeclFromUser<const ObjCInterfaceDecl> interface_decl_from_runtime( @@ -1623,13 +1638,12 @@ void ClangASTSource::FindObjCPropertyAndIvarDecls(NameSearchContext &context) { if (!interface_decl_from_runtime.IsValid()) break; - if (log) - log->Printf( - "CAS::FOPD[%d] trying runtime " - "(ObjCInterfaceDecl*)%p/(ASTContext*)%p...", - current_id, - static_cast<const void *>(interface_decl_from_runtime.decl), - static_cast<void *>(&interface_decl_from_runtime->getASTContext())); + LLDB_LOGF( + log, + "CAS::FOPD[%d] trying runtime " + "(ObjCInterfaceDecl*)%p/(ASTContext*)%p...", + current_id, static_cast<const void *>(interface_decl_from_runtime.decl), + static_cast<void *>(&interface_decl_from_runtime->getASTContext())); if (FindObjCPropertyAndIvarDeclsWithOrigin( current_id, context, *this, interface_decl_from_runtime)) @@ -1729,12 +1743,12 @@ bool ClangASTSource::layoutRecordType(const RecordDecl *record, uint64_t &size, Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_EXPRESSIONS)); - if (log) - log->Printf("LayoutRecordType[%u] on (ASTContext*)%p for (RecordDecl*)%p " - "[name = '%s']", - current_id, static_cast<void *>(m_ast_context), - static_cast<const void *>(record), - record->getNameAsString().c_str()); + LLDB_LOGF(log, + "LayoutRecordType[%u] on (ASTContext*)%p for (RecordDecl*)%p " + "[name = '%s']", + current_id, static_cast<void *>(m_ast_context), + static_cast<const void *>(record), + record->getNameAsString().c_str()); DeclFromParser<const RecordDecl> parser_record(record); DeclFromUser<const RecordDecl> origin_record( @@ -1798,24 +1812,25 @@ bool ClangASTSource::layoutRecordType(const RecordDecl *record, uint64_t &size, m_ast_context->getCharWidth(); if (log) { - log->Printf("LRT[%u] returned:", current_id); - log->Printf("LRT[%u] Original = (RecordDecl*)%p", current_id, - static_cast<const void *>(origin_record.decl)); - log->Printf("LRT[%u] Size = %" PRId64, current_id, size); - log->Printf("LRT[%u] Alignment = %" PRId64, current_id, alignment); - log->Printf("LRT[%u] Fields:", current_id); + LLDB_LOGF(log, "LRT[%u] returned:", current_id); + LLDB_LOGF(log, "LRT[%u] Original = (RecordDecl*)%p", current_id, + static_cast<const void *>(origin_record.decl)); + LLDB_LOGF(log, "LRT[%u] Size = %" PRId64, current_id, size); + LLDB_LOGF(log, "LRT[%u] Alignment = %" PRId64, current_id, alignment); + LLDB_LOGF(log, "LRT[%u] Fields:", current_id); for (RecordDecl::field_iterator fi = record->field_begin(), fe = record->field_end(); fi != fe; ++fi) { - log->Printf("LRT[%u] (FieldDecl*)%p, Name = '%s', Offset = %" PRId64 - " bits", - current_id, static_cast<void *>(*fi), - fi->getNameAsString().c_str(), field_offsets[*fi]); + LLDB_LOGF(log, + "LRT[%u] (FieldDecl*)%p, Name = '%s', Offset = %" PRId64 + " bits", + current_id, static_cast<void *>(*fi), + fi->getNameAsString().c_str(), field_offsets[*fi]); } DeclFromParser<const CXXRecordDecl> parser_cxx_record = DynCast<const CXXRecordDecl>(parser_record); if (parser_cxx_record.IsValid()) { - log->Printf("LRT[%u] Bases:", current_id); + LLDB_LOGF(log, "LRT[%u] Bases:", current_id); for (CXXRecordDecl::base_class_const_iterator bi = parser_cxx_record->bases_begin(), be = parser_cxx_record->bases_end(); @@ -1828,7 +1843,8 @@ bool ClangASTSource::layoutRecordType(const RecordDecl *record, uint64_t &size, DeclFromParser<CXXRecordDecl> base_cxx_record = DynCast<CXXRecordDecl>(base_record); - log->Printf( + LLDB_LOGF( + log, "LRT[%u] %s(CXXRecordDecl*)%p, Name = '%s', Offset = %" PRId64 " chars", current_id, (is_virtual ? "Virtual " : ""), @@ -1839,7 +1855,7 @@ bool ClangASTSource::layoutRecordType(const RecordDecl *record, uint64_t &size, : base_offsets[base_cxx_record.decl].getQuantity())); } } else { - log->Printf("LRD[%u] Not a CXXRecord, so no bases", current_id); + LLDB_LOGF(log, "LRD[%u] Not a CXXRecord, so no bases", current_id); } } @@ -1856,16 +1872,18 @@ void ClangASTSource::CompleteNamespaceMap( if (log) { if (parent_map && parent_map->size()) - log->Printf("CompleteNamespaceMap[%u] on (ASTContext*)%p Searching for " - "namespace %s in namespace %s", - current_id, static_cast<void *>(m_ast_context), - name.GetCString(), - parent_map->begin()->second.GetName().AsCString()); + LLDB_LOGF(log, + "CompleteNamespaceMap[%u] on (ASTContext*)%p Searching for " + "namespace %s in namespace %s", + current_id, static_cast<void *>(m_ast_context), + name.GetCString(), + parent_map->begin()->second.GetName().AsCString()); else - log->Printf("CompleteNamespaceMap[%u] on (ASTContext*)%p Searching for " - "namespace %s", - current_id, static_cast<void *>(m_ast_context), - name.GetCString()); + LLDB_LOGF(log, + "CompleteNamespaceMap[%u] on (ASTContext*)%p Searching for " + "namespace %s", + current_id, static_cast<void *>(m_ast_context), + name.GetCString()); } if (parent_map) { @@ -1877,13 +1895,13 @@ void ClangASTSource::CompleteNamespaceMap( lldb::ModuleSP module_sp = i->first; CompilerDeclContext module_parent_namespace_decl = i->second; - SymbolVendor *symbol_vendor = module_sp->GetSymbolVendor(); + SymbolFile *symbol_file = module_sp->GetSymbolFile(); - if (!symbol_vendor) + if (!symbol_file) continue; found_namespace_decl = - symbol_vendor->FindNamespace(name, &module_parent_namespace_decl); + symbol_file->FindNamespace(name, &module_parent_namespace_decl); if (!found_namespace_decl) continue; @@ -1891,10 +1909,9 @@ void ClangASTSource::CompleteNamespaceMap( namespace_map->push_back(std::pair<lldb::ModuleSP, CompilerDeclContext>( module_sp, found_namespace_decl)); - if (log) - log->Printf(" CMN[%u] Found namespace %s in module %s", current_id, - name.GetCString(), - module_sp->GetFileSpec().GetFilename().GetCString()); + LLDB_LOGF(log, " CMN[%u] Found namespace %s in module %s", current_id, + name.GetCString(), + module_sp->GetFileSpec().GetFilename().GetCString()); } } else { const ModuleList &target_images = m_target->GetImages(); @@ -1910,13 +1927,13 @@ void ClangASTSource::CompleteNamespaceMap( CompilerDeclContext found_namespace_decl; - SymbolVendor *symbol_vendor = image->GetSymbolVendor(); + SymbolFile *symbol_file = image->GetSymbolFile(); - if (!symbol_vendor) + if (!symbol_file) continue; found_namespace_decl = - symbol_vendor->FindNamespace(name, &null_namespace_decl); + symbol_file->FindNamespace(name, &null_namespace_decl); if (!found_namespace_decl) continue; @@ -1924,10 +1941,9 @@ void ClangASTSource::CompleteNamespaceMap( namespace_map->push_back(std::pair<lldb::ModuleSP, CompilerDeclContext>( image, found_namespace_decl)); - if (log) - log->Printf(" CMN[%u] Found namespace %s in module %s", current_id, - name.GetCString(), - image->GetFileSpec().GetFilename().GetCString()); + LLDB_LOGF(log, " CMN[%u] Found namespace %s in module %s", current_id, + name.GetCString(), + image->GetFileSpec().GetFilename().GetCString()); } } } @@ -2065,7 +2081,8 @@ CompilerType ClangASTSource::GuardedCopyType(const CompilerType &src_type) { // seems to be generating bad types on occasion. return CompilerType(); - return CompilerType(m_ast_context, copied_qual_type); + return CompilerType(ClangASTContext::GetASTContext(m_ast_context), + copied_qual_type.getAsOpaquePtr()); } clang::NamedDecl *NameSearchContext::AddVarDecl(const CompilerType &type) { @@ -2162,8 +2179,7 @@ clang::NamedDecl *NameSearchContext::AddFunDecl(const CompilerType &type, } else { Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_EXPRESSIONS)); - if (log) - log->Printf("Function type wasn't a FunctionProtoType"); + LLDB_LOGF(log, "Function type wasn't a FunctionProtoType"); } // If this is an operator (e.g. operator new or operator==), only insert the @@ -2194,7 +2210,9 @@ clang::NamedDecl *NameSearchContext::AddGenericFunDecl() { proto_info)); return AddFunDecl( - CompilerType(m_ast_source.m_ast_context, generic_function_type), true); + CompilerType(ClangASTContext::GetASTContext(m_ast_source.m_ast_context), + generic_function_type.getAsOpaquePtr()), + true); } clang::NamedDecl * diff --git a/source/Plugins/ExpressionParser/Clang/ClangDeclVendor.cpp b/source/Plugins/ExpressionParser/Clang/ClangDeclVendor.cpp new file mode 100644 index 000000000000..c59722b7b4f8 --- /dev/null +++ b/source/Plugins/ExpressionParser/Clang/ClangDeclVendor.cpp @@ -0,0 +1,30 @@ +//===-- ClangDeclVendor.cpp -------------------------------------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#include "Plugins/ExpressionParser/Clang/ClangDeclVendor.h" + +#include "lldb/Symbol/ClangASTContext.h" +#include "lldb/Utility/ConstString.h" + +using namespace lldb_private; + +uint32_t ClangDeclVendor::FindDecls(ConstString name, bool append, + uint32_t max_matches, + std::vector<CompilerDecl> &decls) { + if (!append) + decls.clear(); + + std::vector<clang::NamedDecl *> named_decls; + uint32_t ret = FindDecls(name, /*append*/ false, max_matches, named_decls); + for (auto *named_decl : named_decls) { + decls.push_back(CompilerDecl( + ClangASTContext::GetASTContext(&named_decl->getASTContext()), + named_decl)); + } + return ret; +} diff --git a/source/Plugins/ExpressionParser/Clang/ClangDeclVendor.h b/source/Plugins/ExpressionParser/Clang/ClangDeclVendor.h new file mode 100644 index 000000000000..90b715f37cba --- /dev/null +++ b/source/Plugins/ExpressionParser/Clang/ClangDeclVendor.h @@ -0,0 +1,50 @@ +//===-- ClangDeclVendor.h ---------------------------------------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef liblldb_ClangDeclVendor_h_ +#define liblldb_ClangDeclVendor_h_ + +#include "lldb/Core/ClangForward.h" +#include "lldb/Symbol/DeclVendor.h" + +#include "clang/AST/ExternalASTMerger.h" + +namespace lldb_private { + +// A clang specialized extension to DeclVendor. +class ClangDeclVendor : public DeclVendor { +public: + ClangDeclVendor(DeclVendorKind kind) : DeclVendor(kind) {} + + virtual ~ClangDeclVendor() {} + + /// Interface for ExternalASTMerger. Returns an ImporterSource allowing type + /// completion. + /// + /// \return + /// An ImporterSource for this ClangDeclVendor. + virtual clang::ExternalASTMerger::ImporterSource GetImporterSource() = 0; + + uint32_t FindDecls(ConstString name, bool append, uint32_t max_matches, + std::vector<CompilerDecl> &decls) override; + + virtual uint32_t FindDecls(ConstString name, bool append, + uint32_t max_matches, + std::vector<clang::NamedDecl *> &decls) = 0; + + static bool classof(const DeclVendor *vendor) { + return vendor->GetKind() >= eClangDeclVendor && + vendor->GetKind() < eLastClangDeclVendor; + } + +private: + DISALLOW_COPY_AND_ASSIGN(ClangDeclVendor); +}; +} // namespace lldb_private + +#endif diff --git a/source/Plugins/ExpressionParser/Clang/ClangDiagnostic.h b/source/Plugins/ExpressionParser/Clang/ClangDiagnostic.h index db50c2aa3e90..48cd1c4b99fa 100644 --- a/source/Plugins/ExpressionParser/Clang/ClangDiagnostic.h +++ b/source/Plugins/ExpressionParser/Clang/ClangDiagnostic.h @@ -29,7 +29,7 @@ public: return diag->getKind() == eDiagnosticOriginClang; } - ClangDiagnostic(const char *message, DiagnosticSeverity severity, + ClangDiagnostic(llvm::StringRef message, DiagnosticSeverity severity, uint32_t compiler_id) : Diagnostic(message, severity, eDiagnosticOriginClang, compiler_id) {} @@ -42,6 +42,7 @@ public: } const FixItList &FixIts() const { return m_fixit_vec; } +private: FixItList m_fixit_vec; }; diff --git a/source/Plugins/ExpressionParser/Clang/ClangExpressionDeclMap.cpp b/source/Plugins/ExpressionParser/Clang/ClangExpressionDeclMap.cpp index a49a7029e0d2..f4457fc1b740 100644 --- a/source/Plugins/ExpressionParser/Clang/ClangExpressionDeclMap.cpp +++ b/source/Plugins/ExpressionParser/Clang/ClangExpressionDeclMap.cpp @@ -180,98 +180,20 @@ ClangExpressionDeclMap::TargetInfo ClangExpressionDeclMap::GetTargetInfo() { return ret; } -namespace { -/// This class walks an AST and ensures that all DeclContexts defined inside the -/// current source file are properly complete. -/// -/// This is used to ensure that persistent types defined in the current source -/// file migrate completely to the persistent AST context before they are -/// reused. If that didn't happen, it would be impoossible to complete them -/// because their origin would be gone. -/// -/// The stragtegy used by this class is to check the SourceLocation (to be -/// specific, the FileID) and see if it's the FileID for the current expression. -/// Alternate strategies could include checking whether an ExternalASTMerger, -/// set up to not have the current context as a source, can find an original for -/// the type. -class Completer : public clang::RecursiveASTVisitor<Completer> { -private: - clang::ASTImporter &m_exporter; /// Used to import Decl contents - clang::FileID m_file; /// The file that's going away - llvm::DenseSet<clang::Decl *> m_completed; /// Visited Decls, to avoid cycles - - bool ImportAndCheckCompletable(clang::Decl *decl) { - (void)m_exporter.Import(decl); - if (m_completed.count(decl)) - return false; - if (!llvm::isa<DeclContext>(decl)) - return false; - const clang::SourceLocation loc = decl->getLocation(); - if (!loc.isValid()) - return false; - const clang::FileID file = - m_exporter.getFromContext().getSourceManager().getFileID(loc); - if (file != m_file) - return false; - // We are assuming the Decl was parsed in this very expression, so it - // should not have external storage. - lldbassert(!llvm::cast<DeclContext>(decl)->hasExternalLexicalStorage()); - return true; - } - - void Complete(clang::Decl *decl) { - m_completed.insert(decl); - auto *decl_context = llvm::cast<DeclContext>(decl); - (void)m_exporter.Import(decl); - m_exporter.CompleteDecl(decl); - for (Decl *child : decl_context->decls()) - if (ImportAndCheckCompletable(child)) - Complete(child); - } - - void MaybeComplete(clang::Decl *decl) { - if (ImportAndCheckCompletable(decl)) - Complete(decl); - } - -public: - Completer(clang::ASTImporter &exporter, clang::FileID file) - : m_exporter(exporter), m_file(file) {} - - // Implements the RecursiveASTVisitor's core API. It is called on each Decl - // that the RecursiveASTVisitor encounters, and returns true if the traversal - // should continue. - bool VisitDecl(clang::Decl *decl) { - MaybeComplete(decl); - return true; - } -}; -} - -static void CompleteAllDeclContexts(clang::ASTImporter &exporter, - clang::FileID file, - clang::QualType root) { - clang::QualType canonical_type = root.getCanonicalType(); - if (clang::TagDecl *tag_decl = canonical_type->getAsTagDecl()) { - Completer(exporter, file).TraverseDecl(tag_decl); - } else if (auto interface_type = llvm::dyn_cast<ObjCInterfaceType>( - canonical_type.getTypePtr())) { - Completer(exporter, file).TraverseDecl(interface_type->getDecl()); - } else { - Completer(exporter, file).TraverseType(canonical_type); - } -} - static clang::QualType ExportAllDeclaredTypes( - clang::ExternalASTMerger &merger, + clang::ExternalASTMerger &parent_merger, clang::ExternalASTMerger &merger, clang::ASTContext &source, clang::FileManager &source_file_manager, const clang::ExternalASTMerger::OriginMap &source_origin_map, clang::FileID file, clang::QualType root) { - clang::ExternalASTMerger::ImporterSource importer_source = - { source, source_file_manager, source_origin_map }; + // Mark the source as temporary to make sure all declarations from the + // AST are exported. Also add the parent_merger as the merger into the + // source AST so that the merger can track back any declarations from + // the persistent ASTs we used as sources. + clang::ExternalASTMerger::ImporterSource importer_source( + source, source_file_manager, source_origin_map, /*Temporary*/ true, + &parent_merger); merger.AddSources(importer_source); clang::ASTImporter &exporter = merger.ImporterForOrigin(source); - CompleteAllDeclContexts(exporter, file, root); llvm::Expected<clang::QualType> ret_or_error = exporter.Import(root); merger.RemoveSources(importer_source); if (ret_or_error) { @@ -286,10 +208,10 @@ static clang::QualType ExportAllDeclaredTypes( TypeFromUser ClangExpressionDeclMap::DeportType(ClangASTContext &target, ClangASTContext &source, TypeFromParser parser_type) { - assert (&target == m_target->GetScratchClangASTContext()); - assert ((TypeSystem*)&source == parser_type.GetTypeSystem()); - assert (source.getASTContext() == m_ast_context); - + assert(&target == m_target->GetScratchClangASTContext()); + assert((TypeSystem *)&source == parser_type.GetTypeSystem()); + assert(source.getASTContext() == m_ast_context); + if (m_ast_importer_sp) { return TypeFromUser(m_ast_importer_sp->DeportType( target.getASTContext(), source.getASTContext(), @@ -299,13 +221,12 @@ TypeFromUser ClangExpressionDeclMap::DeportType(ClangASTContext &target, clang::FileID source_file = source.getASTContext()->getSourceManager().getFileID( source.getASTContext()->getTranslationUnitDecl()->getLocation()); - auto scratch_ast_context = static_cast<ClangASTContextForExpressions*>( + auto scratch_ast_context = static_cast<ClangASTContextForExpressions *>( m_target->GetScratchClangASTContext()); clang::QualType exported_type = ExportAllDeclaredTypes( - scratch_ast_context->GetMergerUnchecked(), + *m_merger_up.get(), scratch_ast_context->GetMergerUnchecked(), *source.getASTContext(), *source.getFileManager(), - m_merger_up->GetOrigins(), - source_file, + m_merger_up->GetOrigins(), source_file, clang::QualType::getFromOpaquePtr(parser_type.GetOpaqueQualType())); return TypeFromUser(exported_type.getAsOpaquePtr(), &target); } else { @@ -375,8 +296,7 @@ bool ClangExpressionDeclMap::AddPersistentVariable(const NamedDecl *decl, TypeFromUser user_type = DeportType(*context, *ast, parser_type); if (!user_type.GetOpaqueQualType()) { - if (log) - log->Printf("Persistent variable's type wasn't copied successfully"); + LLDB_LOGF(log, "Persistent variable's type wasn't copied successfully"); return false; } @@ -415,8 +335,7 @@ bool ClangExpressionDeclMap::AddPersistentVariable(const NamedDecl *decl, var->m_flags |= ClangExpressionVariable::EVKeepInTarget; } - if (log) - log->Printf("Created persistent variable with flags 0x%hx", var->m_flags); + LLDB_LOGF(log, "Created persistent variable with flags 0x%hx", var->m_flags); var->EnableParserVars(GetParserID()); @@ -458,10 +377,9 @@ bool ClangExpressionDeclMap::AddValueToStruct(const NamedDecl *decl, if (!var) return false; - if (log) - log->Printf("Adding value for (NamedDecl*)%p [%s - %s] to the structure", - static_cast<const void *>(decl), name.GetCString(), - var->GetName().GetCString()); + LLDB_LOGF(log, "Adding value for (NamedDecl*)%p [%s - %s] to the structure", + static_cast<const void *>(decl), name.GetCString(), + var->GetName().GetCString()); // We know entity->m_parser_vars is valid because we used a parser variable // to find it @@ -475,9 +393,8 @@ bool ClangExpressionDeclMap::AddValueToStruct(const NamedDecl *decl, llvm::cast<ClangExpressionVariable>(var)->GetJITVars(GetParserID())) { // We already laid this out; do not touch - if (log) - log->Printf("Already placed at 0x%llx", - (unsigned long long)jit_vars->m_offset); + LLDB_LOGF(log, "Already placed at 0x%llx", + (unsigned long long)jit_vars->m_offset); } llvm::cast<ClangExpressionVariable>(var)->EnableJITVars(GetParserID()); @@ -512,8 +429,7 @@ bool ClangExpressionDeclMap::AddValueToStruct(const NamedDecl *decl, if (!err.Success()) return false; - if (log) - log->Printf("Placed at 0x%llx", (unsigned long long)offset); + LLDB_LOGF(log, "Placed at 0x%llx", (unsigned long long)offset); jit_vars->m_offset = offset; // TODO DoStructLayout() should not change this. @@ -779,7 +695,7 @@ void ClangExpressionDeclMap::FindExternalVisibleDecls( if (GetImportInProgress()) { if (log && log->GetVerbose()) - log->Printf("Ignoring a query during an import"); + LLDB_LOGF(log, "Ignoring a query during an import"); return; } @@ -788,20 +704,23 @@ void ClangExpressionDeclMap::FindExternalVisibleDecls( if (log) { if (!context.m_decl_context) - log->Printf("ClangExpressionDeclMap::FindExternalVisibleDecls[%u] for " - "'%s' in a NULL DeclContext", - current_id, name.GetCString()); + LLDB_LOGF(log, + "ClangExpressionDeclMap::FindExternalVisibleDecls[%u] for " + "'%s' in a NULL DeclContext", + current_id, name.GetCString()); else if (const NamedDecl *context_named_decl = dyn_cast<NamedDecl>(context.m_decl_context)) - log->Printf("ClangExpressionDeclMap::FindExternalVisibleDecls[%u] for " - "'%s' in '%s'", - current_id, name.GetCString(), - context_named_decl->getNameAsString().c_str()); + LLDB_LOGF(log, + "ClangExpressionDeclMap::FindExternalVisibleDecls[%u] for " + "'%s' in '%s'", + current_id, name.GetCString(), + context_named_decl->getNameAsString().c_str()); else - log->Printf("ClangExpressionDeclMap::FindExternalVisibleDecls[%u] for " - "'%s' in a '%s'", - current_id, name.GetCString(), - context.m_decl_context->getDeclKindName()); + LLDB_LOGF(log, + "ClangExpressionDeclMap::FindExternalVisibleDecls[%u] for " + "'%s' in a '%s'", + current_id, name.GetCString(), + context.m_decl_context->getDeclKindName()); } if (const NamespaceDecl *namespace_context = @@ -828,7 +747,7 @@ void ClangExpressionDeclMap::FindExternalVisibleDecls( log->Printf(" CEDM::FEVD[%u] Inspecting (NamespaceMap*)%p (%d entries)", current_id, static_cast<void *>(namespace_map.get()), (int)namespace_map->size()); - + for (ClangASTImporter::NamespaceMap::iterator i = namespace_map->begin(), e = namespace_map->end(); i != e; ++i) { @@ -848,7 +767,7 @@ void ClangExpressionDeclMap::FindExternalVisibleDecls( FindExternalVisibleDecls(context, lldb::ModuleSP(), namespace_decl, current_id); } - + ClangASTSource::FindExternalVisibleDecls(context); } @@ -922,9 +841,8 @@ void ClangExpressionDeclMap::FindExternalVisibleDecls( MaybeRegisterFunctionBody(parser_function_decl); } - if (log) - log->Printf(" CEDM::FEVD[%u] Found persistent decl %s", current_id, - name.GetCString()); + LLDB_LOGF(log, " CEDM::FEVD[%u] Found persistent decl %s", current_id, + name.GetCString()); context.AddNamedDecl(parser_named_decl); } while (false); @@ -979,8 +897,8 @@ void ClangExpressionDeclMap::FindExternalVisibleDecls( if (log) { ASTDumper ast_dumper(class_qual_type); - log->Printf(" CEDM::FEVD[%u] Adding type for $__lldb_class: %s", - current_id, ast_dumper.GetCString()); + LLDB_LOGF(log, " CEDM::FEVD[%u] Adding type for $__lldb_class: %s", + current_id, ast_dumper.GetCString()); } AddThisType(context, class_user_type, current_id); @@ -1024,8 +942,8 @@ void ClangExpressionDeclMap::FindExternalVisibleDecls( if (pointee_type.IsValid()) { if (log) { ASTDumper ast_dumper(pointee_type); - log->Printf(" FEVD[%u] Adding type for $__lldb_class: %s", - current_id, ast_dumper.GetCString()); + LLDB_LOGF(log, " FEVD[%u] Adding type for $__lldb_class: %s", + current_id, ast_dumper.GetCString()); } AddThisType(context, pointee_type, current_id); @@ -1048,7 +966,7 @@ void ClangExpressionDeclMap::FindExternalVisibleDecls( return; AddOneType(context, TypeFromUser(m_ctx_obj->GetCompilerType()), - current_id); + current_id); m_struct_vars->m_object_pointer_type = TypeFromUser(ctx_obj_ptr->GetCompilerType()); @@ -1096,8 +1014,8 @@ void ClangExpressionDeclMap::FindExternalVisibleDecls( if (log) { ASTDumper ast_dumper(interface_type); - log->Printf(" FEVD[%u] Adding type for $__lldb_objc_class: %s", - current_id, ast_dumper.GetCString()); + LLDB_LOGF(log, " FEVD[%u] Adding type for $__lldb_objc_class: %s", + current_id, ast_dumper.GetCString()); } AddOneType(context, class_user_type, current_id); @@ -1157,8 +1075,9 @@ void ClangExpressionDeclMap::FindExternalVisibleDecls( if (log) { ASTDumper ast_dumper(self_type->GetFullCompilerType()); - log->Printf(" FEVD[%u] Adding type for $__lldb_objc_class: %s", - current_id, ast_dumper.GetCString()); + LLDB_LOGF(log, + " FEVD[%u] Adding type for $__lldb_objc_class: %s", + current_id, ast_dumper.GetCString()); } TypeFromUser class_user_type(self_clang_type); @@ -1222,9 +1141,8 @@ void ClangExpressionDeclMap::FindExternalVisibleDecls( reg_name)); if (reg_info) { - if (log) - log->Printf(" CEDM::FEVD[%u] Found register %s", current_id, - reg_info->name); + LLDB_LOGF(log, " CEDM::FEVD[%u] Found register %s", current_id, + reg_info->name); AddOneRegister(context, reg_info, current_id); } @@ -1298,14 +1216,12 @@ void ClangExpressionDeclMap::FindExternalVisibleDecls( } const bool include_inlines = false; - const bool append = false; - + sc_list.Clear(); if (namespace_decl && module_sp) { const bool include_symbols = false; module_sp->FindFunctions(name, &namespace_decl, eFunctionNameTypeBase, - include_symbols, include_inlines, append, - sc_list); + include_symbols, include_inlines, sc_list); } else if (target && !namespace_decl) { const bool include_symbols = true; @@ -1314,7 +1230,7 @@ void ClangExpressionDeclMap::FindExternalVisibleDecls( target->GetImages().FindFunctions(name, eFunctionNameTypeFull, include_symbols, include_inlines, - append, sc_list); + sc_list); } // If we found more than one function, see if we can use the frame's decl @@ -1511,9 +1427,10 @@ void ClangExpressionDeclMap::FindExternalVisibleDecls( if (llvm::isa<clang::FunctionDecl>(decl_from_modules)) { if (log) { - log->Printf(" CAS::FEVD[%u] Matching function found for " - "\"%s\" in the modules", - current_id, name.GetCString()); + LLDB_LOGF(log, + " CAS::FEVD[%u] Matching function found for " + "\"%s\" in the modules", + current_id, name.GetCString()); } clang::Decl *copied_decl = CopyDecl(decl_from_modules); @@ -1522,10 +1439,10 @@ void ClangExpressionDeclMap::FindExternalVisibleDecls( : nullptr; if (!copied_function_decl) { - if (log) - log->Printf(" CAS::FEVD[%u] - Couldn't export a function " - "declaration from the modules", - current_id); + LLDB_LOGF(log, + " CAS::FEVD[%u] - Couldn't export a function " + "declaration from the modules", + current_id); break; } @@ -1538,9 +1455,10 @@ void ClangExpressionDeclMap::FindExternalVisibleDecls( context.m_found.function = true; } else if (llvm::isa<clang::VarDecl>(decl_from_modules)) { if (log) { - log->Printf(" CAS::FEVD[%u] Matching variable found for " - "\"%s\" in the modules", - current_id, name.GetCString()); + LLDB_LOGF(log, + " CAS::FEVD[%u] Matching variable found for " + "\"%s\" in the modules", + current_id, name.GetCString()); } clang::Decl *copied_decl = CopyDecl(decl_from_modules); @@ -1549,10 +1467,10 @@ void ClangExpressionDeclMap::FindExternalVisibleDecls( : nullptr; if (!copied_var_decl) { - if (log) - log->Printf(" CAS::FEVD[%u] - Couldn't export a variable " - "declaration from the modules", - current_id); + LLDB_LOGF(log, + " CAS::FEVD[%u] - Couldn't export a variable " + "declaration from the modules", + current_id); break; } @@ -1647,8 +1565,7 @@ bool ClangExpressionDeclMap::GetVariableValue(VariableSP &var, const_value_extractor.GetByteSize()); var_location.SetValueType(Value::eValueTypeHostAddress); } else { - if (log) - log->Printf("Error evaluating constant variable: %s", err.AsCString()); + LLDB_LOGF(log, "Error evaluating constant variable: %s", err.AsCString()); return false; } } @@ -1656,9 +1573,8 @@ bool ClangExpressionDeclMap::GetVariableValue(VariableSP &var, CompilerType type_to_use = GuardedCopyType(var_clang_type); if (!type_to_use) { - if (log) - log->Printf( - "Couldn't copy a variable's type into the parser's AST context"); + LLDB_LOGF(log, + "Couldn't copy a variable's type into the parser's AST context"); return false; } @@ -1751,9 +1667,10 @@ void ClangExpressionDeclMap::AddOneVariable(NameSearchContext &context, if (log) { ASTDumper orig_dumper(ut.GetOpaqueQualType()); ASTDumper ast_dumper(var_decl); - log->Printf(" CEDM::FEVD[%u] Found variable %s, returned %s (original %s)", - current_id, decl_name.c_str(), ast_dumper.GetCString(), - orig_dumper.GetCString()); + LLDB_LOGF(log, + " CEDM::FEVD[%u] Found variable %s, returned %s (original %s)", + current_id, decl_name.c_str(), ast_dumper.GetCString(), + orig_dumper.GetCString()); } } @@ -1768,9 +1685,8 @@ void ClangExpressionDeclMap::AddOneVariable(NameSearchContext &context, TypeFromParser parser_type(GuardedCopyType(user_type)); if (!parser_type.GetOpaqueQualType()) { - if (log) - log->Printf(" CEDM::FEVD[%u] Couldn't import type for pvar %s", - current_id, pvar_sp->GetName().GetCString()); + LLDB_LOGF(log, " CEDM::FEVD[%u] Couldn't import type for pvar %s", + current_id, pvar_sp->GetName().GetCString()); return; } @@ -1789,8 +1705,8 @@ void ClangExpressionDeclMap::AddOneVariable(NameSearchContext &context, if (log) { ASTDumper ast_dumper(var_decl); - log->Printf(" CEDM::FEVD[%u] Added pvar %s, returned %s", current_id, - pvar_sp->GetName().GetCString(), ast_dumper.GetCString()); + LLDB_LOGF(log, " CEDM::FEVD[%u] Added pvar %s, returned %s", current_id, + pvar_sp->GetName().GetCString(), ast_dumper.GetCString()); } } @@ -1848,8 +1764,8 @@ void ClangExpressionDeclMap::AddOneGenericVariable(NameSearchContext &context, if (log) { ASTDumper ast_dumper(var_decl); - log->Printf(" CEDM::FEVD[%u] Found variable %s, returned %s", current_id, - decl_name.c_str(), ast_dumper.GetCString()); + LLDB_LOGF(log, " CEDM::FEVD[%u] Found variable %s, returned %s", + current_id, decl_name.c_str(), ast_dumper.GetCString()); } } @@ -1858,7 +1774,7 @@ bool ClangExpressionDeclMap::ResolveUnknownTypes() { Target *target = m_parser_vars->m_exe_ctx.GetTargetPtr(); ClangASTContextForExpressions *scratch_ast_context = - static_cast<ClangASTContextForExpressions*>( + static_cast<ClangASTContextForExpressions *>( target->GetScratchClangASTContext()); for (size_t index = 0, num_entities = m_found_entities.GetSize(); @@ -1874,15 +1790,14 @@ bool ClangExpressionDeclMap::ResolveUnknownTypes() { const VarDecl *var_decl = dyn_cast<VarDecl>(named_decl); if (!var_decl) { - if (log) - log->Printf("Entity of unknown type does not have a VarDecl"); + LLDB_LOGF(log, "Entity of unknown type does not have a VarDecl"); return false; } if (log) { ASTDumper ast_dumper(const_cast<VarDecl *>(var_decl)); - log->Printf("Variable of unknown type now has Decl %s", - ast_dumper.GetCString()); + LLDB_LOGF(log, "Variable of unknown type now has Decl %s", + ast_dumper.GetCString()); } QualType var_type = var_decl->getType(); @@ -1897,18 +1812,17 @@ bool ClangExpressionDeclMap::ResolveUnknownTypes() { var_type.getAsOpaquePtr()); } else if (HasMerger()) { copied_type = CopyTypeWithMerger( - var_decl->getASTContext(), - scratch_ast_context->GetMergerUnchecked(), - var_type).getAsOpaquePtr(); + var_decl->getASTContext(), + scratch_ast_context->GetMergerUnchecked(), var_type) + .getAsOpaquePtr(); } else { lldbassert(0 && "No mechanism to copy a resolved unknown type!"); return false; } if (!copied_type) { - if (log) - log->Printf("ClangExpressionDeclMap::ResolveUnknownType - Couldn't " - "import the type for a variable"); + LLDB_LOGF(log, "ClangExpressionDeclMap::ResolveUnknownType - Couldn't " + "import the type for a variable"); return (bool)lldb::ExpressionVariableSP(); } @@ -1939,9 +1853,8 @@ void ClangExpressionDeclMap::AddOneRegister(NameSearchContext &context, m_ast_context, reg_info->encoding, reg_info->byte_size * 8); if (!clang_type) { - if (log) - log->Printf(" Tried to add a type for %s, but couldn't get one", - context.m_decl_name.getAsString().c_str()); + LLDB_LOGF(log, " Tried to add a type for %s, but couldn't get one", + context.m_decl_name.getAsString().c_str()); return; } @@ -1969,9 +1882,9 @@ void ClangExpressionDeclMap::AddOneRegister(NameSearchContext &context, if (log) { ASTDumper ast_dumper(var_decl); - log->Printf(" CEDM::FEVD[%d] Added register %s, returned %s", current_id, - context.m_decl_name.getAsString().c_str(), - ast_dumper.GetCString()); + LLDB_LOGF(log, " CEDM::FEVD[%d] Added register %s, returned %s", + current_id, context.m_decl_name.getAsString().c_str(), + ast_dumper.GetCString()); } } @@ -2016,24 +1929,24 @@ void ClangExpressionDeclMap::AddOneFunction(NameSearchContext &context, if (copied_function_template) { if (log) { ASTDumper ast_dumper((clang::Decl *)copied_function_template); - + StreamString ss; - + function->DumpSymbolContext(&ss); - + log->Printf(" CEDM::FEVD[%u] Imported decl for function template" " %s (description %s), returned %s", current_id, copied_function_template->getNameAsString().c_str(), ss.GetData(), ast_dumper.GetCString()); } - + context.AddNamedDecl(copied_function_template); } } else if (src_function_decl) { if (clang::FunctionDecl *copied_function_decl = llvm::dyn_cast_or_null<clang::FunctionDecl>( - CopyDecl(src_function_decl))) { + CopyDecl(src_function_decl))) { if (log) { ASTDumper ast_dumper((clang::Decl *)copied_function_decl); @@ -2041,19 +1954,20 @@ void ClangExpressionDeclMap::AddOneFunction(NameSearchContext &context, function->DumpSymbolContext(&ss); - log->Printf(" CEDM::FEVD[%u] Imported decl for function %s " - "(description %s), returned %s", - current_id, - copied_function_decl->getNameAsString().c_str(), - ss.GetData(), ast_dumper.GetCString()); + LLDB_LOGF(log, + " CEDM::FEVD[%u] Imported decl for function %s " + "(description %s), returned %s", + current_id, + copied_function_decl->getNameAsString().c_str(), + ss.GetData(), ast_dumper.GetCString()); } context.AddNamedDecl(copied_function_decl); return; } else { if (log) { - log->Printf(" Failed to import the function decl for '%s'", - src_function_decl->getName().str().c_str()); + LLDB_LOGF(log, " Failed to import the function decl for '%s'", + src_function_decl->getName().str().c_str()); } } } @@ -2082,7 +1996,8 @@ void ClangExpressionDeclMap::AddOneFunction(NameSearchContext &context, if (!function_decl) { if (log) { - log->Printf( + LLDB_LOGF( + log, " Failed to create a function decl for '%s' {0x%8.8" PRIx64 "}", function_type->GetName().GetCString(), function_type->GetID()); } @@ -2092,10 +2007,11 @@ void ClangExpressionDeclMap::AddOneFunction(NameSearchContext &context, } else { // We failed to copy the type we found if (log) { - log->Printf(" Failed to import the function type '%s' {0x%8.8" PRIx64 - "} into the expression parser AST contenxt", - function_type->GetName().GetCString(), - function_type->GetID()); + LLDB_LOGF(log, + " Failed to import the function type '%s' {0x%8.8" PRIx64 + "} into the expression parser AST contenxt", + function_type->GetName().GetCString(), + function_type->GetID()); } return; @@ -2154,7 +2070,8 @@ void ClangExpressionDeclMap::AddOneFunction(NameSearchContext &context, m_parser_vars->m_exe_ctx.GetBestExecutionContextScope(), Address::DumpStyleResolvedDescription); - log->Printf( + LLDB_LOGF( + log, " CEDM::FEVD[%u] Found %s function %s (description %s), returned %s", current_id, (function ? "specific" : "generic"), decl_name.c_str(), ss.GetData(), function_str.c_str()); @@ -2170,7 +2087,8 @@ void ClangExpressionDeclMap::AddThisType(NameSearchContext &context, if (!copied_clang_type) { if (log) - log->Printf( + LLDB_LOGF( + log, "ClangExpressionDeclMap::AddThisType - Couldn't import the type"); return; @@ -2203,9 +2121,10 @@ void ClangExpressionDeclMap::AddThisType(NameSearchContext &context, ASTDumper method_ast_dumper((clang::Decl *)method_decl); ASTDumper type_ast_dumper(copied_clang_type); - log->Printf(" CEDM::AddThisType Added function $__lldb_expr " - "(description %s) for this type %s", - method_ast_dumper.GetCString(), type_ast_dumper.GetCString()); + LLDB_LOGF(log, + " CEDM::AddThisType Added function $__lldb_expr " + "(description %s) for this type %s", + method_ast_dumper.GetCString(), type_ast_dumper.GetCString()); } } @@ -2244,8 +2163,8 @@ void ClangExpressionDeclMap::AddOneType(NameSearchContext &context, Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_EXPRESSIONS)); if (log) - log->Printf( - "ClangExpressionDeclMap::AddOneType - Couldn't import the type"); + LLDB_LOGF( + log, "ClangExpressionDeclMap::AddOneType - Couldn't import the type"); return; } diff --git a/source/Plugins/ExpressionParser/Clang/ClangExpressionDeclMap.h b/source/Plugins/ExpressionParser/Clang/ClangExpressionDeclMap.h index 03b73e6be391..2711e90726e7 100644 --- a/source/Plugins/ExpressionParser/Clang/ClangExpressionDeclMap.h +++ b/source/Plugins/ExpressionParser/Clang/ClangExpressionDeclMap.h @@ -356,7 +356,7 @@ private: /// Activate parser-specific variables void EnableParserVars() { if (!m_parser_vars.get()) - m_parser_vars = llvm::make_unique<ParserVars>(); + m_parser_vars = std::make_unique<ParserVars>(); } /// Deallocate parser-specific variables diff --git a/source/Plugins/ExpressionParser/Clang/ClangExpressionParser.cpp b/source/Plugins/ExpressionParser/Clang/ClangExpressionParser.cpp index 7d13891ded8d..1422911d6546 100644 --- a/source/Plugins/ExpressionParser/Clang/ClangExpressionParser.cpp +++ b/source/Plugins/ExpressionParser/Clang/ClangExpressionParser.cpp @@ -105,16 +105,26 @@ using namespace lldb_private; class ClangExpressionParser::LLDBPreprocessorCallbacks : public PPCallbacks { ClangModulesDeclVendor &m_decl_vendor; ClangPersistentVariables &m_persistent_vars; + clang::SourceManager &m_source_mgr; StreamString m_error_stream; bool m_has_errors = false; public: LLDBPreprocessorCallbacks(ClangModulesDeclVendor &decl_vendor, - ClangPersistentVariables &persistent_vars) - : m_decl_vendor(decl_vendor), m_persistent_vars(persistent_vars) {} + ClangPersistentVariables &persistent_vars, + clang::SourceManager &source_mgr) + : m_decl_vendor(decl_vendor), m_persistent_vars(persistent_vars), + m_source_mgr(source_mgr) {} void moduleImport(SourceLocation import_location, clang::ModuleIdPath path, const clang::Module * /*null*/) override { + // Ignore modules that are imported in the wrapper code as these are not + // loaded by the user. + llvm::StringRef filename = + m_source_mgr.getPresumedLoc(import_location).getFilename(); + if (filename == ClangExpressionSourceCode::g_prefix_file_name) + return; + SourceModule module; for (const std::pair<IdentifierInfo *, SourceLocation> &component : path) @@ -137,12 +147,14 @@ public: class ClangDiagnosticManagerAdapter : public clang::DiagnosticConsumer { public: - ClangDiagnosticManagerAdapter() - : m_passthrough(new clang::TextDiagnosticBuffer) {} - - ClangDiagnosticManagerAdapter( - const std::shared_ptr<clang::TextDiagnosticBuffer> &passthrough) - : m_passthrough(passthrough) {} + ClangDiagnosticManagerAdapter(DiagnosticOptions &opts) { + DiagnosticOptions *m_options = new DiagnosticOptions(opts); + m_options->ShowPresumedLoc = true; + m_options->ShowLevel = false; + m_os.reset(new llvm::raw_string_ostream(m_output)); + m_passthrough.reset( + new clang::TextDiagnosticPrinter(*m_os, m_options, false)); + } void ResetManager(DiagnosticManager *manager = nullptr) { m_manager = manager; @@ -150,79 +162,92 @@ public: void HandleDiagnostic(DiagnosticsEngine::Level DiagLevel, const clang::Diagnostic &Info) override { - if (m_manager) { - llvm::SmallVector<char, 32> diag_str; - Info.FormatDiagnostic(diag_str); - diag_str.push_back('\0'); - const char *data = diag_str.data(); - - lldb_private::DiagnosticSeverity severity; - bool make_new_diagnostic = true; - - switch (DiagLevel) { - case DiagnosticsEngine::Level::Fatal: - case DiagnosticsEngine::Level::Error: - severity = eDiagnosticSeverityError; - break; - case DiagnosticsEngine::Level::Warning: - severity = eDiagnosticSeverityWarning; - break; - case DiagnosticsEngine::Level::Remark: - case DiagnosticsEngine::Level::Ignored: - severity = eDiagnosticSeverityRemark; - break; - case DiagnosticsEngine::Level::Note: - m_manager->AppendMessageToDiagnostic(data); - make_new_diagnostic = false; - } - if (make_new_diagnostic) { - ClangDiagnostic *new_diagnostic = - new ClangDiagnostic(data, severity, Info.getID()); - m_manager->AddDiagnostic(new_diagnostic); - - // Don't store away warning fixits, since the compiler doesn't have - // enough context in an expression for the warning to be useful. - // FIXME: Should we try to filter out FixIts that apply to our generated - // code, and not the user's expression? - if (severity == eDiagnosticSeverityError) { - size_t num_fixit_hints = Info.getNumFixItHints(); - for (size_t i = 0; i < num_fixit_hints; i++) { - const clang::FixItHint &fixit = Info.getFixItHint(i); - if (!fixit.isNull()) - new_diagnostic->AddFixitHint(fixit); - } - } + if (!m_manager) { + // We have no DiagnosticManager before/after parsing but we still could + // receive diagnostics (e.g., by the ASTImporter failing to copy decls + // when we move the expression result ot the ScratchASTContext). Let's at + // least log these diagnostics until we find a way to properly render + // them and display them to the user. + Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_EXPRESSIONS)); + if (log) { + llvm::SmallVector<char, 32> diag_str; + Info.FormatDiagnostic(diag_str); + diag_str.push_back('\0'); + const char *plain_diag = diag_str.data(); + LLDB_LOG(log, "Received diagnostic outside parsing: {0}", plain_diag); } + return; } + // Render diagnostic message to m_output. + m_output.clear(); m_passthrough->HandleDiagnostic(DiagLevel, Info); - } + m_os->flush(); - void FlushDiagnostics(DiagnosticsEngine &Diags) { - m_passthrough->FlushDiagnostics(Diags); - } + lldb_private::DiagnosticSeverity severity; + bool make_new_diagnostic = true; + + switch (DiagLevel) { + case DiagnosticsEngine::Level::Fatal: + case DiagnosticsEngine::Level::Error: + severity = eDiagnosticSeverityError; + break; + case DiagnosticsEngine::Level::Warning: + severity = eDiagnosticSeverityWarning; + break; + case DiagnosticsEngine::Level::Remark: + case DiagnosticsEngine::Level::Ignored: + severity = eDiagnosticSeverityRemark; + break; + case DiagnosticsEngine::Level::Note: + m_manager->AppendMessageToDiagnostic(m_output); + make_new_diagnostic = false; + } + if (make_new_diagnostic) { + // ClangDiagnostic messages are expected to have no whitespace/newlines + // around them. + std::string stripped_output = llvm::StringRef(m_output).trim(); + + auto new_diagnostic = std::make_unique<ClangDiagnostic>( + stripped_output, severity, Info.getID()); + + // Don't store away warning fixits, since the compiler doesn't have + // enough context in an expression for the warning to be useful. + // FIXME: Should we try to filter out FixIts that apply to our generated + // code, and not the user's expression? + if (severity == eDiagnosticSeverityError) { + size_t num_fixit_hints = Info.getNumFixItHints(); + for (size_t i = 0; i < num_fixit_hints; i++) { + const clang::FixItHint &fixit = Info.getFixItHint(i); + if (!fixit.isNull()) + new_diagnostic->AddFixitHint(fixit); + } + } - DiagnosticConsumer *clone(DiagnosticsEngine &Diags) const { - return new ClangDiagnosticManagerAdapter(m_passthrough); + m_manager->AddDiagnostic(std::move(new_diagnostic)); + } } - clang::TextDiagnosticBuffer *GetPassthrough() { return m_passthrough.get(); } + clang::TextDiagnosticPrinter *GetPassthrough() { return m_passthrough.get(); } private: DiagnosticManager *m_manager = nullptr; - std::shared_ptr<clang::TextDiagnosticBuffer> m_passthrough; + std::shared_ptr<clang::TextDiagnosticPrinter> m_passthrough; + /// Output stream of m_passthrough. + std::shared_ptr<llvm::raw_string_ostream> m_os; + /// Output string filled by m_os. + std::string m_output; }; -static void -SetupModuleHeaderPaths(CompilerInstance *compiler, - std::vector<ConstString> include_directories, - lldb::TargetSP target_sp) { +static void SetupModuleHeaderPaths(CompilerInstance *compiler, + std::vector<std::string> include_directories, + lldb::TargetSP target_sp) { Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_EXPRESSIONS)); HeaderSearchOptions &search_opts = compiler->getHeaderSearchOpts(); - for (ConstString dir : include_directories) { - search_opts.AddPath(dir.AsCString(), frontend::System, false, true); + for (const std::string &dir : include_directories) { + search_opts.AddPath(dir, frontend::System, false, true); LLDB_LOG(log, "Added user include dir: {0}", dir); } @@ -232,27 +257,9 @@ SetupModuleHeaderPaths(CompilerInstance *compiler, search_opts.ModuleCachePath = module_cache.str(); LLDB_LOG(log, "Using module cache path: {0}", module_cache.c_str()); - FileSpec clang_resource_dir = GetClangResourceDir(); - std::string resource_dir = clang_resource_dir.GetPath(); - if (FileSystem::Instance().IsDirectory(resource_dir)) { - search_opts.ResourceDir = resource_dir; - std::string resource_include = resource_dir + "/include"; - search_opts.AddPath(resource_include, frontend::System, false, true); - - LLDB_LOG(log, "Added resource include dir: {0}", resource_include); - } + search_opts.ResourceDir = GetClangResourceDir().GetPath(); search_opts.ImplicitModuleMaps = true; - - std::vector<std::string> system_include_directories = - target_sp->GetPlatform()->GetSystemIncludeDirectories( - lldb::eLanguageTypeC_plus_plus); - - for (const std::string &include_dir : system_include_directories) { - search_opts.AddPath(include_dir, frontend::System, false, true); - - LLDB_LOG(log, "Added system include dir: {0}", include_dir); - } } //===----------------------------------------------------------------------===// @@ -261,10 +268,12 @@ SetupModuleHeaderPaths(CompilerInstance *compiler, ClangExpressionParser::ClangExpressionParser( ExecutionContextScope *exe_scope, Expression &expr, - bool generate_debug_info, std::vector<ConstString> include_directories) + bool generate_debug_info, std::vector<std::string> include_directories, + std::string filename) : ExpressionParser(exe_scope, expr, generate_debug_info), m_compiler(), m_pp_callbacks(nullptr), - m_include_directories(std::move(include_directories)) { + m_include_directories(std::move(include_directories)), + m_filename(std::move(filename)) { Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_EXPRESSIONS)); // We can't compile expressions without a target. So if the exe_scope is @@ -331,9 +340,8 @@ ClangExpressionParser::ClangExpressionParser( if (process_sp && frame_lang != lldb::eLanguageTypeUnknown) { lang_rt = process_sp->GetLanguageRuntime(frame_lang); - if (log) - log->Printf("Frame has language of type %s", - Language::GetNameForLanguageType(frame_lang)); + LLDB_LOGF(log, "Frame has language of type %s", + Language::GetNameForLanguageType(frame_lang)); } // 2. Configure the compiler with a set of default options that are @@ -341,9 +349,8 @@ ClangExpressionParser::ClangExpressionParser( if (target_arch.IsValid()) { std::string triple = target_arch.GetTriple().str(); m_compiler->getTargetOpts().Triple = triple; - if (log) - log->Printf("Using %s as the target triple", - m_compiler->getTargetOpts().Triple.c_str()); + LLDB_LOGF(log, "Using %s as the target triple", + m_compiler->getTargetOpts().Triple.c_str()); } else { // If we get here we don't have a valid target and just have to guess. // Sometimes this will be ok to just use the host target triple (when we @@ -352,9 +359,8 @@ ClangExpressionParser::ClangExpressionParser( // the host triple. In such a case the language runtime should expose an // overridden options set (3), below. m_compiler->getTargetOpts().Triple = llvm::sys::getDefaultTargetTriple(); - if (log) - log->Printf("Using default target triple of %s", - m_compiler->getTargetOpts().Triple.c_str()); + LLDB_LOGF(log, "Using default target triple of %s", + m_compiler->getTargetOpts().Triple.c_str()); } // Now add some special fixes for known architectures: Any arm32 iOS // environment, but not on arm64 @@ -408,12 +414,13 @@ ClangExpressionParser::ClangExpressionParser( auto target_info = TargetInfo::CreateTargetInfo( m_compiler->getDiagnostics(), m_compiler->getInvocation().TargetOpts); if (log) { - log->Printf("Using SIMD alignment: %d", target_info->getSimdDefaultAlign()); - log->Printf("Target datalayout string: '%s'", - target_info->getDataLayout().getStringRepresentation().c_str()); - log->Printf("Target ABI: '%s'", target_info->getABI().str().c_str()); - log->Printf("Target vector alignment: %d", - target_info->getMaxVectorAlign()); + LLDB_LOGF(log, "Using SIMD alignment: %d", + target_info->getSimdDefaultAlign()); + LLDB_LOGF(log, "Target datalayout string: '%s'", + target_info->getDataLayout().getStringRepresentation().c_str()); + LLDB_LOGF(log, "Target ABI: '%s'", target_info->getABI().str().c_str()); + LLDB_LOGF(log, "Target vector alignment: %d", + target_info->getMaxVectorAlign()); } m_compiler->setTarget(target_info); @@ -508,6 +515,9 @@ ClangExpressionParser::ClangExpressionParser( lang_opts.DoubleSquareBracketAttributes = true; lang_opts.CPlusPlus11 = true; + // The Darwin libc expects this macro to be set. + lang_opts.GNUCVersion = 40201; + SetupModuleHeaderPaths(m_compiler.get(), m_include_directories, target_sp); } @@ -537,8 +547,8 @@ ClangExpressionParser::ClangExpressionParser( // Set CodeGen options m_compiler->getCodeGenOpts().EmitDeclMetadata = true; m_compiler->getCodeGenOpts().InstrumentFunctions = false; - m_compiler->getCodeGenOpts().DisableFPElim = true; - m_compiler->getCodeGenOpts().OmitLeafFramePointer = false; + m_compiler->getCodeGenOpts().setFramePointer( + CodeGenOptions::FramePointerKind::All); if (generate_debug_info) m_compiler->getCodeGenOpts().setDebugInfo(codegenoptions::FullDebugInfo); else @@ -560,7 +570,9 @@ ClangExpressionParser::ClangExpressionParser( // 6. Set up the diagnostic buffer for reporting errors - m_compiler->getDiagnostics().setClient(new ClangDiagnosticManagerAdapter); + auto diag_mgr = new ClangDiagnosticManagerAdapter( + m_compiler->getDiagnostics().getDiagnosticOptions()); + m_compiler->getDiagnostics().setClient(diag_mgr); // 7. Set up the source management objects inside the compiler m_compiler->createFileManager(); @@ -574,8 +586,8 @@ ClangExpressionParser::ClangExpressionParser( llvm::cast<ClangPersistentVariables>( target_sp->GetPersistentExpressionStateForLanguage( lldb::eLanguageTypeC)); - std::unique_ptr<PPCallbacks> pp_callbacks( - new LLDBPreprocessorCallbacks(*decl_vendor, *clang_persistent_vars)); + std::unique_ptr<PPCallbacks> pp_callbacks(new LLDBPreprocessorCallbacks( + *decl_vendor, *clang_persistent_vars, m_compiler->getSourceManager())); m_pp_callbacks = static_cast<LLDBPreprocessorCallbacks *>(pp_callbacks.get()); m_compiler->getPreprocessor().addPPCallbacks(std::move(pp_callbacks)); @@ -592,9 +604,7 @@ ClangExpressionParser::ClangExpressionParser( m_compiler->createASTContext(); clang::ASTContext &ast_context = m_compiler->getASTContext(); - m_ast_context.reset( - new ClangASTContext(m_compiler->getTargetOpts().Triple.c_str())); - m_ast_context->setASTContext(&ast_context); + m_ast_context.reset(new ClangASTContext(ast_context)); std::string module_name("$__lldb_module"); @@ -872,8 +882,7 @@ ClangExpressionParser::ParseInternal(DiagnosticManager &diagnostic_manager, ClangDiagnosticManagerAdapter *adapter = static_cast<ClangDiagnosticManagerAdapter *>( m_compiler->getDiagnostics().getClient()); - clang::TextDiagnosticBuffer *diag_buf = adapter->GetPassthrough(); - diag_buf->FlushDiagnostics(m_compiler->getDiagnostics()); + auto diag_buf = adapter->GetPassthrough(); adapter->ResetManager(&diagnostic_manager); @@ -904,16 +913,19 @@ ClangExpressionParser::ParseInternal(DiagnosticManager &diagnostic_manager, } if (temp_fd != -1) { - lldb_private::File file(temp_fd, true); + lldb_private::NativeFile file(temp_fd, File::eOpenOptionWrite, true); const size_t expr_text_len = strlen(expr_text); size_t bytes_written = expr_text_len; if (file.Write(expr_text, bytes_written).Success()) { if (bytes_written == expr_text_len) { file.Close(); - source_mgr.setMainFileID(source_mgr.createFileID( - m_compiler->getFileManager().getFile(result_path), - SourceLocation(), SrcMgr::C_User)); - created_main_file = true; + if (auto fileEntry = + m_compiler->getFileManager().getFile(result_path)) { + source_mgr.setMainFileID(source_mgr.createFileID( + *fileEntry, + SourceLocation(), SrcMgr::C_User)); + created_main_file = true; + } } } } @@ -921,7 +933,7 @@ ClangExpressionParser::ParseInternal(DiagnosticManager &diagnostic_manager, if (!created_main_file) { std::unique_ptr<MemoryBuffer> memory_buffer = - MemoryBuffer::getMemBufferCopy(expr_text, "<lldb-expr>"); + MemoryBuffer::getMemBufferCopy(expr_text, m_filename); source_mgr.setMainFileID(source_mgr.createFileID(std::move(memory_buffer))); } @@ -1092,8 +1104,8 @@ bool ClangExpressionParser::RewriteExpression( if (num_diags == 0) return false; - for (const Diagnostic *diag : diagnostic_manager.Diagnostics()) { - const ClangDiagnostic *diagnostic = llvm::dyn_cast<ClangDiagnostic>(diag); + for (const auto &diag : diagnostic_manager.Diagnostics()) { + const auto *diagnostic = llvm::dyn_cast<ClangDiagnostic>(diag.get()); if (diagnostic && diagnostic->HasFixIts()) { for (const FixItHint &fixit : diagnostic->FixIts()) { // This is cobbed from clang::Rewrite::FixItRewriter. @@ -1181,9 +1193,8 @@ lldb_private::Status ClangExpressionParser::PrepareForExecution( m_expr.FunctionName()); return err; } else { - if (log) - log->Printf("Found function %s for %s", function_name.AsCString(), - m_expr.FunctionName()); + LLDB_LOGF(log, "Found function %s for %s", function_name.AsCString(), + m_expr.FunctionName()); } } @@ -1198,9 +1209,8 @@ lldb_private::Status ClangExpressionParser::PrepareForExecution( LLVMUserExpression::IRPasses custom_passes; { auto lang = m_expr.Language(); - if (log) - log->Printf("%s - Current expression language is %s\n", __FUNCTION__, - Language::GetNameForLanguageType(lang)); + LLDB_LOGF(log, "%s - Current expression language is %s\n", __FUNCTION__, + Language::GetNameForLanguageType(lang)); lldb::ProcessSP process_sp = exe_ctx.GetProcessSP(); if (process_sp && lang != lldb::eLanguageTypeUnknown) { auto runtime = process_sp->GetLanguageRuntime(lang); @@ -1210,10 +1220,10 @@ lldb_private::Status ClangExpressionParser::PrepareForExecution( } if (custom_passes.EarlyPasses) { - if (log) - log->Printf("%s - Running Early IR Passes from LanguageRuntime on " - "expression module '%s'", - __FUNCTION__, m_expr.FunctionName()); + LLDB_LOGF(log, + "%s - Running Early IR Passes from LanguageRuntime on " + "expression module '%s'", + __FUNCTION__, m_expr.FunctionName()); custom_passes.EarlyPasses->run(*llvm_module_up); } @@ -1230,12 +1240,10 @@ lldb_private::Status ClangExpressionParser::PrepareForExecution( type_system_helper->DeclMap(); // result can be NULL if (decl_map) { - Stream *error_stream = nullptr; Target *target = exe_ctx.GetTargetPtr(); - error_stream = target->GetDebugger().GetErrorFile().get(); - + auto &error_stream = target->GetDebugger().GetErrorStream(); IRForTarget ir_for_target(decl_map, m_expr.NeedsVariableResolution(), - *execution_unit_sp, *error_stream, + *execution_unit_sp, error_stream, function_name.AsCString()); bool ir_can_run = @@ -1298,9 +1306,8 @@ lldb_private::Status ClangExpressionParser::PrepareForExecution( process->SetDynamicCheckers(dynamic_checkers); - if (log) - log->Printf("== [ClangExpressionParser::PrepareForExecution] " - "Finished installing dynamic checkers =="); + LLDB_LOGF(log, "== [ClangExpressionParser::PrepareForExecution] " + "Finished installing dynamic checkers =="); } if (auto *checker_funcs = llvm::dyn_cast<ClangDynamicCheckerFunctions>( @@ -1316,10 +1323,10 @@ lldb_private::Status ClangExpressionParser::PrepareForExecution( } if (custom_passes.LatePasses) { - if (log) - log->Printf("%s - Running Late IR Passes from LanguageRuntime on " - "expression module '%s'", - __FUNCTION__, m_expr.FunctionName()); + LLDB_LOGF(log, + "%s - Running Late IR Passes from LanguageRuntime on " + "expression module '%s'", + __FUNCTION__, m_expr.FunctionName()); custom_passes.LatePasses->run(*module); } diff --git a/source/Plugins/ExpressionParser/Clang/ClangExpressionParser.h b/source/Plugins/ExpressionParser/Clang/ClangExpressionParser.h index a42c2190ffb8..79ad5728bf74 100644 --- a/source/Plugins/ExpressionParser/Clang/ClangExpressionParser.h +++ b/source/Plugins/ExpressionParser/Clang/ClangExpressionParser.h @@ -53,9 +53,14 @@ public: /// @param[in] include_directories /// List of include directories that should be used when parsing the /// expression. + /// + /// @param[in] filename + /// Name of the source file that should be used when rendering + /// diagnostics (i.e. errors, warnings or notes from Clang). ClangExpressionParser(ExecutionContextScope *exe_scope, Expression &expr, bool generate_debug_info, - std::vector<ConstString> include_directories = {}); + std::vector<std::string> include_directories = {}, + std::string filename = "<clang expression>"); /// Destructor ~ClangExpressionParser() override; @@ -177,7 +182,9 @@ private: ///encounters module imports std::unique_ptr<ClangASTContext> m_ast_context; - std::vector<ConstString> m_include_directories; + std::vector<std::string> m_include_directories; + /// File name used for the user expression. + std::string m_filename; }; } diff --git a/source/Plugins/ExpressionParser/Clang/ClangExpressionSourceCode.cpp b/source/Plugins/ExpressionParser/Clang/ClangExpressionSourceCode.cpp index f513b1eea360..21cb33402e7f 100644 --- a/source/Plugins/ExpressionParser/Clang/ClangExpressionSourceCode.cpp +++ b/source/Plugins/ExpressionParser/Clang/ClangExpressionSourceCode.cpp @@ -29,7 +29,15 @@ using namespace lldb_private; -const char *ClangExpressionSourceCode::g_expression_prefix = R"( +#define PREFIX_NAME "<lldb wrapper prefix>" + +const llvm::StringRef ClangExpressionSourceCode::g_prefix_file_name = PREFIX_NAME; + +const char *ClangExpressionSourceCode::g_expression_prefix = +"#line 1 \"" PREFIX_NAME R"(" +#ifndef offsetof +#define offsetof(t, d) __builtin_offsetof(t, d) +#endif #ifndef NULL #define NULL (__null) #endif @@ -64,9 +72,6 @@ extern "C" } )"; -static const char *c_start_marker = " /*LLDB_BODY_START*/\n "; -static const char *c_end_marker = ";\n /*LLDB_BODY_END*/\n"; - namespace { class AddMacroState { @@ -166,6 +171,17 @@ static void AddMacros(const DebugMacros *dm, CompileUnit *comp_unit, } } +lldb_private::ClangExpressionSourceCode::ClangExpressionSourceCode( + llvm::StringRef filename, llvm::StringRef name, llvm::StringRef prefix, + llvm::StringRef body, Wrapping wrap) + : ExpressionSourceCode(name, prefix, body, wrap) { + // Use #line markers to pretend that we have a single-line source file + // containing only the user expression. This will hide our wrapper code + // from the user when we render diagnostics with Clang. + m_start_marker = "#line 1 \"" + filename.str() + "\"\n"; + m_end_marker = "\n;\n#line 1 \"<lldb wrapper suffix>\"\n"; +} + namespace { /// Allows checking if a token is contained in a given expression. class TokenVerifier { @@ -286,7 +302,8 @@ bool ClangExpressionSourceCode::GetText( Target *target = exe_ctx.GetTargetPtr(); if (target) { - if (target->GetArchitecture().GetMachine() == llvm::Triple::aarch64) { + if (target->GetArchitecture().GetMachine() == llvm::Triple::aarch64 || + target->GetArchitecture().GetMachine() == llvm::Triple::aarch64_32) { target_specific_defines = "typedef bool BOOL;\n"; } if (target->GetArchitecture().GetMachine() == llvm::Triple::x86_64) { @@ -398,9 +415,9 @@ bool ClangExpressionSourceCode::GetText( case lldb::eLanguageTypeC: case lldb::eLanguageTypeC_plus_plus: case lldb::eLanguageTypeObjC: - tagged_body.append(c_start_marker); + tagged_body.append(m_start_marker); tagged_body.append(m_body); - tagged_body.append(c_end_marker); + tagged_body.append(m_end_marker); break; } switch (wrapping_language) { @@ -474,24 +491,19 @@ bool ClangExpressionSourceCode::GetText( bool ClangExpressionSourceCode::GetOriginalBodyBounds( std::string transformed_text, lldb::LanguageType wrapping_language, size_t &start_loc, size_t &end_loc) { - const char *start_marker; - const char *end_marker; - switch (wrapping_language) { default: return false; case lldb::eLanguageTypeC: case lldb::eLanguageTypeC_plus_plus: case lldb::eLanguageTypeObjC: - start_marker = c_start_marker; - end_marker = c_end_marker; break; } - start_loc = transformed_text.find(start_marker); + start_loc = transformed_text.find(m_start_marker); if (start_loc == std::string::npos) return false; - start_loc += strlen(start_marker); - end_loc = transformed_text.find(end_marker); + start_loc += m_start_marker.size(); + end_loc = transformed_text.find(m_end_marker); return end_loc != std::string::npos; } diff --git a/source/Plugins/ExpressionParser/Clang/ClangExpressionSourceCode.h b/source/Plugins/ExpressionParser/Clang/ClangExpressionSourceCode.h index 894290295837..1d159670b962 100644 --- a/source/Plugins/ExpressionParser/Clang/ClangExpressionSourceCode.h +++ b/source/Plugins/ExpressionParser/Clang/ClangExpressionSourceCode.h @@ -23,15 +23,18 @@ class ExecutionContext; class ClangExpressionSourceCode : public ExpressionSourceCode { public: + /// The file name we use for the wrapper code that we inject before + /// the user expression. + static const llvm::StringRef g_prefix_file_name; static const char *g_expression_prefix; - static ClangExpressionSourceCode *CreateWrapped(const char *prefix, - const char *body) { - return new ClangExpressionSourceCode("$__lldb_expr", prefix, body, true); + static ClangExpressionSourceCode *CreateWrapped(llvm::StringRef filename, + llvm::StringRef prefix, + llvm::StringRef body) { + return new ClangExpressionSourceCode(filename, "$__lldb_expr", prefix, body, + Wrap); } - uint32_t GetNumBodyLines(); - /// Generates the source code that will evaluate the expression. /// /// \param text output parameter containing the source code string. @@ -56,14 +59,20 @@ public: // Given a string returned by GetText, find the beginning and end of the body // passed to CreateWrapped. Return true if the bounds could be found. This // will also work on text with FixItHints applied. - static bool GetOriginalBodyBounds(std::string transformed_text, - lldb::LanguageType wrapping_language, - size_t &start_loc, size_t &end_loc); + bool GetOriginalBodyBounds(std::string transformed_text, + lldb::LanguageType wrapping_language, + size_t &start_loc, size_t &end_loc); protected: - ClangExpressionSourceCode(const char *name, const char *prefix, const char *body, - bool wrap) : - ExpressionSourceCode(name, prefix, body, wrap) {} + ClangExpressionSourceCode(llvm::StringRef filename, llvm::StringRef name, + llvm::StringRef prefix, llvm::StringRef body, + Wrapping wrap); + +private: + /// String marking the start of the user expression. + std::string m_start_marker; + /// String marking the end of the user expression. + std::string m_end_marker; }; } // namespace lldb_private diff --git a/source/Plugins/ExpressionParser/Clang/ClangFunctionCaller.cpp b/source/Plugins/ExpressionParser/Clang/ClangFunctionCaller.cpp index eabc96aa8e51..8fbfa6e47578 100644 --- a/source/Plugins/ExpressionParser/Clang/ClangFunctionCaller.cpp +++ b/source/Plugins/ExpressionParser/Clang/ClangFunctionCaller.cpp @@ -179,8 +179,7 @@ ClangFunctionCaller::CompileFunction(lldb::ThreadSP thread_to_use_sp, m_wrapper_function_text.append(");\n}\n"); Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_EXPRESSIONS)); - if (log) - log->Printf("Expression: \n\n%s\n\n", m_wrapper_function_text.c_str()); + LLDB_LOGF(log, "Expression: \n\n%s\n\n", m_wrapper_function_text.c_str()); // Okay, now compile this expression diff --git a/source/Plugins/ExpressionParser/Clang/ClangHost.cpp b/source/Plugins/ExpressionParser/Clang/ClangHost.cpp index 65c547391831..42d3f22014dd 100644 --- a/source/Plugins/ExpressionParser/Clang/ClangHost.cpp +++ b/source/Plugins/ExpressionParser/Clang/ClangHost.cpp @@ -30,10 +30,10 @@ static bool VerifyClangPath(const llvm::Twine &clang_path) { if (FileSystem::Instance().IsDirectory(clang_path)) return true; Log *log = lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_HOST); - if (log) - log->Printf("VerifyClangPath(): " - "failed to stat clang resource directory at \"%s\"", - clang_path.str().c_str()); + LLDB_LOGF(log, + "VerifyClangPath(): " + "failed to stat clang resource directory at \"%s\"", + clang_path.str().c_str()); return false; } @@ -67,10 +67,10 @@ static bool DefaultComputeClangResourceDirectory(FileSpec &lldb_shlib_spec, llvm::sys::path::native(relative_path); llvm::sys::path::append(clang_dir, relative_path); if (!verify || VerifyClangPath(clang_dir)) { - if (log) - log->Printf("DefaultComputeClangResourceDir: Setting ClangResourceDir " - "to \"%s\", verify = %s", - clang_dir.str().str().c_str(), verify ? "true" : "false"); + LLDB_LOGF(log, + "DefaultComputeClangResourceDir: Setting ClangResourceDir " + "to \"%s\", verify = %s", + clang_dir.str().str().c_str(), verify ? "true" : "false"); file_spec.GetDirectory().SetString(clang_dir); FileSystem::Instance().Resolve(file_spec); return true; @@ -160,9 +160,8 @@ FileSpec lldb_private::GetClangResourceDir() { ComputeClangResourceDirectory(lldb_file_spec, g_cached_resource_dir, true); Log *log = lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_HOST); - if (log) - log->Printf("GetClangResourceDir() => '%s'", - g_cached_resource_dir.GetPath().c_str()); + LLDB_LOGF(log, "GetClangResourceDir() => '%s'", + g_cached_resource_dir.GetPath().c_str()); }); return g_cached_resource_dir; } diff --git a/source/Plugins/ExpressionParser/Clang/ClangModulesDeclVendor.cpp b/source/Plugins/ExpressionParser/Clang/ClangModulesDeclVendor.cpp index 4a220790e50d..f3df589d7311 100644 --- a/source/Plugins/ExpressionParser/Clang/ClangModulesDeclVendor.cpp +++ b/source/Plugins/ExpressionParser/Clang/ClangModulesDeclVendor.cpp @@ -27,6 +27,7 @@ #include "lldb/Core/ModuleList.h" #include "lldb/Host/Host.h" #include "lldb/Host/HostInfo.h" +#include "lldb/Symbol/ClangASTContext.h" #include "lldb/Symbol/CompileUnit.h" #include "lldb/Symbol/SourceModule.h" #include "lldb/Target/Target.h" @@ -110,6 +111,9 @@ private: ImportedModuleMap m_imported_modules; ImportedModuleSet m_user_imported_modules; const clang::ExternalASTMerger::OriginMap m_origin_map; + // We assume that every ASTContext has an ClangASTContext, so we also store + // a custom ClangASTContext for our internal ASTContext. + std::unique_ptr<ClangASTContext> m_ast_context; }; } // anonymous namespace @@ -143,7 +147,8 @@ void StoringDiagnosticConsumer::DumpDiagnostics(Stream &error_stream) { } } -ClangModulesDeclVendor::ClangModulesDeclVendor() {} +ClangModulesDeclVendor::ClangModulesDeclVendor() + : ClangDeclVendor(eClangModuleDeclVendor) {} ClangModulesDeclVendor::~ClangModulesDeclVendor() {} @@ -155,7 +160,11 @@ ClangModulesDeclVendorImpl::ClangModulesDeclVendorImpl( : m_diagnostics_engine(std::move(diagnostics_engine)), m_compiler_invocation(std::move(compiler_invocation)), m_compiler_instance(std::move(compiler_instance)), - m_parser(std::move(parser)), m_origin_map() {} + m_parser(std::move(parser)), m_origin_map() { + + // Initialize our ClangASTContext. + m_ast_context.reset(new ClangASTContext(m_compiler_instance->getASTContext())); +} void ClangModulesDeclVendorImpl::ReportModuleExportsHelper( std::set<ClangModulesDeclVendor::ModuleID> &exports, @@ -237,11 +246,11 @@ bool ClangModulesDeclVendorImpl::AddModule(const SourceModule &module, bool is_system = true; bool is_framework = false; - auto *dir = + auto dir = HS.getFileMgr().getDirectory(module.search_path.GetStringRef()); if (!dir) return error(); - auto *file = HS.lookupModuleMapFile(dir, is_framework); + auto *file = HS.lookupModuleMapFile(*dir, is_framework); if (!file) return error(); if (!HS.loadModuleMapFile(file, is_system)) @@ -562,8 +571,9 @@ ClangModulesDeclVendorImpl::DoGetModule(clang::ModuleIdPath path, clang::ExternalASTMerger::ImporterSource ClangModulesDeclVendorImpl::GetImporterSource() { - return {m_compiler_instance->getASTContext(), - m_compiler_instance->getFileManager(), m_origin_map}; + return clang::ExternalASTMerger::ImporterSource( + m_compiler_instance->getASTContext(), + m_compiler_instance->getFileManager(), m_origin_map); } static const char *ModuleImportBufferName = "LLDBModulesMemoryBuffer"; diff --git a/source/Plugins/ExpressionParser/Clang/ClangModulesDeclVendor.h b/source/Plugins/ExpressionParser/Clang/ClangModulesDeclVendor.h index d5c8757bdcd0..e099b59041d8 100644 --- a/source/Plugins/ExpressionParser/Clang/ClangModulesDeclVendor.h +++ b/source/Plugins/ExpressionParser/Clang/ClangModulesDeclVendor.h @@ -10,22 +10,27 @@ #define liblldb_ClangModulesDeclVendor_h #include "lldb/Core/ClangForward.h" -#include "lldb/Symbol/DeclVendor.h" #include "lldb/Symbol/SourceModule.h" #include "lldb/Target/Platform.h" +#include "Plugins/ExpressionParser/Clang/ClangDeclVendor.h" + #include <set> #include <vector> namespace lldb_private { -class ClangModulesDeclVendor : public DeclVendor { +class ClangModulesDeclVendor : public ClangDeclVendor { public: // Constructors and Destructors ClangModulesDeclVendor(); ~ClangModulesDeclVendor() override; + static bool classof(const DeclVendor *vendor) { + return vendor->GetKind() == eClangModuleDeclVendor; + } + static ClangModulesDeclVendor *Create(Target &target); typedef std::vector<ConstString> ModulePath; diff --git a/source/Plugins/ExpressionParser/Clang/ClangPersistentVariables.cpp b/source/Plugins/ExpressionParser/Clang/ClangPersistentVariables.cpp index 742a14992dc9..24dd705e37b1 100644 --- a/source/Plugins/ExpressionParser/Clang/ClangPersistentVariables.cpp +++ b/source/Plugins/ExpressionParser/Clang/ClangPersistentVariables.cpp @@ -23,8 +23,7 @@ using namespace lldb; using namespace lldb_private; ClangPersistentVariables::ClangPersistentVariables() - : lldb_private::PersistentExpressionState(LLVMCastKind::eKindClang), - m_next_persistent_variable_id(0) {} + : lldb_private::PersistentExpressionState(LLVMCastKind::eKindClang) {} ExpressionVariableSP ClangPersistentVariables::CreatePersistentVariable( const lldb::ValueObjectSP &valobj_sp) { @@ -43,13 +42,25 @@ void ClangPersistentVariables::RemovePersistentVariable( lldb::ExpressionVariableSP variable) { RemoveVariable(variable); - const char *name = variable->GetName().AsCString(); + // Check if the removed variable was the last one that was created. If yes, + // reuse the variable id for the next variable. - if (*name != '$') + // Nothing to do if we have not assigned a variable id so far. + if (m_next_persistent_variable_id == 0) return; - name++; - if (strtoul(name, nullptr, 0) == m_next_persistent_variable_id - 1) + llvm::StringRef name = variable->GetName().GetStringRef(); + // Remove the prefix from the variable that only the indes is left. + if (!name.consume_front(GetPersistentVariablePrefix(false))) + return; + + // Check if the variable contained a variable id. + uint32_t variable_id; + if (name.getAsInteger(10, variable_id)) + return; + // If it's the most recent variable id that was assigned, make sure that this + // variable id will be used for the next persistent variable. + if (variable_id == m_next_persistent_variable_id - 1) m_next_persistent_variable_id--; } diff --git a/source/Plugins/ExpressionParser/Clang/ClangPersistentVariables.h b/source/Plugins/ExpressionParser/Clang/ClangPersistentVariables.h index b39f89ad7eef..95e6c3ac963d 100644 --- a/source/Plugins/ExpressionParser/Clang/ClangPersistentVariables.h +++ b/source/Plugins/ExpressionParser/Clang/ClangPersistentVariables.h @@ -45,11 +45,20 @@ public: uint32_t addr_byte_size) override; void RemovePersistentVariable(lldb::ExpressionVariableSP variable) override; - llvm::StringRef - GetPersistentVariablePrefix(bool is_error) const override { + + llvm::StringRef GetPersistentVariablePrefix(bool is_error) const override { return "$"; } + /// Returns the next file name that should be used for user expressions. + std::string GetNextExprFileName() { + std::string name; + name.append("<user expression "); + name.append(std::to_string(m_next_user_file_id++)); + name.append(">"); + return name; + } + llvm::Optional<CompilerType> GetCompilerTypeFromPersistentDecl(ConstString type_name) override; @@ -66,8 +75,10 @@ public: } private: - uint32_t m_next_persistent_variable_id; ///< The counter used by - ///GetNextResultName(). + /// The counter used by GetNextExprFileName. + uint32_t m_next_user_file_id = 0; + // The counter used by GetNextPersistentVariableName + uint32_t m_next_persistent_variable_id = 0; typedef llvm::DenseMap<const char *, clang::NamedDecl *> PersistentDeclMap; PersistentDeclMap diff --git a/source/Plugins/ExpressionParser/Clang/ClangUserExpression.cpp b/source/Plugins/ExpressionParser/Clang/ClangUserExpression.cpp index 2dae5b7022f3..da1ca785635c 100644 --- a/source/Plugins/ExpressionParser/Clang/ClangUserExpression.cpp +++ b/source/Plugins/ExpressionParser/Clang/ClangUserExpression.cpp @@ -6,6 +6,8 @@ // //===----------------------------------------------------------------------===// +#include "lldb/Host/Config.h" + #include <stdio.h> #if HAVE_SYS_TYPES_H #include <sys/types.h> @@ -21,9 +23,9 @@ #include "ClangDiagnostic.h" #include "ClangExpressionDeclMap.h" #include "ClangExpressionParser.h" -#include "ClangExpressionSourceCode.h" #include "ClangModulesDeclVendor.h" #include "ClangPersistentVariables.h" +#include "CppModuleConfiguration.h" #include "lldb/Core/Debugger.h" #include "lldb/Core/Module.h" @@ -90,21 +92,18 @@ ClangUserExpression::~ClangUserExpression() {} void ClangUserExpression::ScanContext(ExecutionContext &exe_ctx, Status &err) { Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_EXPRESSIONS)); - if (log) - log->Printf("ClangUserExpression::ScanContext()"); + LLDB_LOGF(log, "ClangUserExpression::ScanContext()"); m_target = exe_ctx.GetTargetPtr(); if (!(m_allow_cxx || m_allow_objc)) { - if (log) - log->Printf(" [CUE::SC] Settings inhibit C++ and Objective-C"); + LLDB_LOGF(log, " [CUE::SC] Settings inhibit C++ and Objective-C"); return; } StackFrame *frame = exe_ctx.GetFramePtr(); if (frame == nullptr) { - if (log) - log->Printf(" [CUE::SC] Null stack frame"); + LLDB_LOGF(log, " [CUE::SC] Null stack frame"); return; } @@ -112,8 +111,7 @@ void ClangUserExpression::ScanContext(ExecutionContext &exe_ctx, Status &err) { lldb::eSymbolContextBlock); if (!sym_ctx.function) { - if (log) - log->Printf(" [CUE::SC] Null function"); + LLDB_LOGF(log, " [CUE::SC] Null function"); return; } @@ -121,16 +119,14 @@ void ClangUserExpression::ScanContext(ExecutionContext &exe_ctx, Status &err) { Block *function_block = sym_ctx.GetFunctionBlock(); if (!function_block) { - if (log) - log->Printf(" [CUE::SC] Null function block"); + LLDB_LOGF(log, " [CUE::SC] Null function block"); return; } CompilerDeclContext decl_context = function_block->GetDeclContext(); if (!decl_context) { - if (log) - log->Printf(" [CUE::SC] Null decl context"); + LLDB_LOGF(log, " [CUE::SC] Null decl context"); return; } @@ -317,17 +313,13 @@ void ClangUserExpression::ScanContext(ExecutionContext &exe_ctx, Status &err) { // count is not available, [myArray count] returns id, which can't be directly // cast to int without causing a clang error. static void ApplyObjcCastHack(std::string &expr) { -#define OBJC_CAST_HACK_FROM "(int)[" -#define OBJC_CAST_HACK_TO "(int)(long long)[" - - size_t from_offset; + const std::string from = "(int)["; + const std::string to = "(int)(long long)["; - while ((from_offset = expr.find(OBJC_CAST_HACK_FROM)) != expr.npos) - expr.replace(from_offset, sizeof(OBJC_CAST_HACK_FROM) - 1, - OBJC_CAST_HACK_TO); + size_t offset; -#undef OBJC_CAST_HACK_TO -#undef OBJC_CAST_HACK_FROM + while ((offset = expr.find(from)) != expr.npos) + expr.replace(offset, from.size(), to); } bool ClangUserExpression::SetupPersistentState(DiagnosticManager &diagnostic_manager, @@ -336,6 +328,7 @@ bool ClangUserExpression::SetupPersistentState(DiagnosticManager &diagnostic_man if (PersistentExpressionState *persistent_state = target->GetPersistentExpressionStateForLanguage( lldb::eLanguageTypeC)) { + m_clang_state = llvm::cast<ClangPersistentVariables>(persistent_state); m_result_delegate.RegisterPersistentState(persistent_state); } else { diagnostic_manager.PutString( @@ -384,30 +377,34 @@ static void SetupDeclVendor(ExecutionContext &exe_ctx, Target *target) { } } -void ClangUserExpression::UpdateLanguageForExpr( +void ClangUserExpression::UpdateLanguageForExpr() { + m_expr_lang = lldb::LanguageType::eLanguageTypeUnknown; + if (m_options.GetExecutionPolicy() == eExecutionPolicyTopLevel) + return; + if (m_in_cplusplus_method) + m_expr_lang = lldb::eLanguageTypeC_plus_plus; + else if (m_in_objectivec_method) + m_expr_lang = lldb::eLanguageTypeObjC; + else + m_expr_lang = lldb::eLanguageTypeC; +} + +void ClangUserExpression::CreateSourceCode( DiagnosticManager &diagnostic_manager, ExecutionContext &exe_ctx, std::vector<std::string> modules_to_import, bool for_completion) { - m_expr_lang = lldb::LanguageType::eLanguageTypeUnknown; + m_filename = m_clang_state->GetNextExprFileName(); std::string prefix = m_expr_prefix; if (m_options.GetExecutionPolicy() == eExecutionPolicyTopLevel) { m_transformed_text = m_expr_text; } else { - std::unique_ptr<ClangExpressionSourceCode> source_code( - ClangExpressionSourceCode::CreateWrapped(prefix.c_str(), - m_expr_text.c_str())); - - if (m_in_cplusplus_method) - m_expr_lang = lldb::eLanguageTypeC_plus_plus; - else if (m_in_objectivec_method) - m_expr_lang = lldb::eLanguageTypeObjC; - else - m_expr_lang = lldb::eLanguageTypeC; - - if (!source_code->GetText(m_transformed_text, m_expr_lang, - m_in_static_method, exe_ctx, !m_ctx_obj, - for_completion, modules_to_import)) { + m_source_code.reset(ClangExpressionSourceCode::CreateWrapped( + m_filename, prefix.c_str(), m_expr_text.c_str())); + + if (!m_source_code->GetText(m_transformed_text, m_expr_lang, + m_in_static_method, exe_ctx, !m_ctx_obj, + for_completion, modules_to_import)) { diagnostic_manager.PutString(eDiagnosticSeverityError, "couldn't construct expression body"); return; @@ -417,7 +414,7 @@ void ClangUserExpression::UpdateLanguageForExpr( // transformed code. We need this later for the code completion. std::size_t original_start; std::size_t original_end; - bool found_bounds = source_code->GetOriginalBodyBounds( + bool found_bounds = m_source_code->GetOriginalBodyBounds( m_transformed_text, m_expr_lang, original_start, original_end); if (found_bounds) m_user_expression_start_pos = original_start; @@ -437,48 +434,70 @@ static bool SupportsCxxModuleImport(lldb::LanguageType language) { } } -std::vector<std::string> -ClangUserExpression::GetModulesToImport(ExecutionContext &exe_ctx) { +/// Utility method that puts a message into the expression log and +/// returns an invalid module configuration. +static CppModuleConfiguration LogConfigError(const std::string &msg) { Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_EXPRESSIONS)); + LLDB_LOG(log, "[C++ module config] {0}", msg); + return CppModuleConfiguration(); +} - if (!SupportsCxxModuleImport(Language())) - return {}; +CppModuleConfiguration GetModuleConfig(lldb::LanguageType language, + ExecutionContext &exe_ctx) { + Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_EXPRESSIONS)); + + // Don't do anything if this is not a C++ module configuration. + if (!SupportsCxxModuleImport(language)) + return LogConfigError("Language doesn't support C++ modules"); Target *target = exe_ctx.GetTargetPtr(); - if (!target || !target->GetEnableImportStdModule()) - return {}; + if (!target) + return LogConfigError("No target"); + + if (!target->GetEnableImportStdModule()) + return LogConfigError("Importing std module not enabled in settings"); StackFrame *frame = exe_ctx.GetFramePtr(); if (!frame) - return {}; + return LogConfigError("No frame"); Block *block = frame->GetFrameBlock(); if (!block) - return {}; + return LogConfigError("No block"); SymbolContext sc; block->CalculateSymbolContext(&sc); if (!sc.comp_unit) - return {}; - - if (log) { - for (const SourceModule &m : sc.comp_unit->GetImportedModules()) { - LLDB_LOG(log, "Found module in compile unit: {0:$[.]} - include dir: {1}", - llvm::make_range(m.path.begin(), m.path.end()), m.search_path); + return LogConfigError("Couldn't calculate symbol context"); + + // Build a list of files we need to analyze to build the configuration. + FileSpecList files; + for (const FileSpec &f : sc.comp_unit->GetSupportFiles()) + files.AppendIfUnique(f); + // We also need to look at external modules in the case of -gmodules as they + // contain the support files for libc++ and the C library. + sc.comp_unit->ForEachExternalModule([&files](lldb::ModuleSP module) { + for (std::size_t i = 0; i < module->GetNumCompileUnits(); ++i) { + const FileSpecList &support_files = + module->GetCompileUnitAtIndex(i)->GetSupportFiles(); + for (const FileSpec &f : support_files) { + files.AppendIfUnique(f); + } } + }); + + LLDB_LOG(log, "[C++ module config] Found {0} support files to analyze", + files.GetSize()); + if (log && log->GetVerbose()) { + for (const FileSpec &f : files) + LLDB_LOGV(log, "[C++ module config] Analyzing support file: {0}", + f.GetPath()); } - for (const SourceModule &m : sc.comp_unit->GetImportedModules()) - m_include_directories.push_back(m.search_path); - - // Check if we imported 'std' or any of its submodules. - // We currently don't support importing any other modules in the expression - // parser. - for (const SourceModule &m : sc.comp_unit->GetImportedModules()) - if (!m.path.empty() && m.path.front() == "std") - return {"std"}; - - return {}; + // Try to create a configuration from the files. If there is no valid + // configuration possible with the files, this just returns an invalid + // configuration. + return CppModuleConfiguration(files); } bool ClangUserExpression::PrepareForParsing( @@ -506,14 +525,21 @@ bool ClangUserExpression::PrepareForParsing( SetupDeclVendor(exe_ctx, m_target); - std::vector<std::string> used_modules = GetModulesToImport(exe_ctx); - m_imported_cpp_modules = !used_modules.empty(); + CppModuleConfiguration module_config = GetModuleConfig(m_language, exe_ctx); + llvm::ArrayRef<std::string> imported_modules = + module_config.GetImportedModules(); + m_imported_cpp_modules = !imported_modules.empty(); + m_include_directories = module_config.GetIncludeDirs(); LLDB_LOG(log, "List of imported modules in expression: {0}", - llvm::make_range(used_modules.begin(), used_modules.end())); - - UpdateLanguageForExpr(diagnostic_manager, exe_ctx, used_modules, - for_completion); + llvm::make_range(imported_modules.begin(), imported_modules.end())); + LLDB_LOG(log, "List of include directories gathered for modules: {0}", + llvm::make_range(m_include_directories.begin(), + m_include_directories.end())); + + UpdateLanguageForExpr(); + CreateSourceCode(diagnostic_manager, exe_ctx, imported_modules, + for_completion); return true; } @@ -527,8 +553,7 @@ bool ClangUserExpression::Parse(DiagnosticManager &diagnostic_manager, if (!PrepareForParsing(diagnostic_manager, exe_ctx, /*for_completion*/ false)) return false; - if (log) - log->Printf("Parsing the following code:\n%s", m_transformed_text.c_str()); + LLDB_LOGF(log, "Parsing the following code:\n%s", m_transformed_text.c_str()); //////////////////////////////////// // Set up the target and compiler @@ -573,7 +598,7 @@ bool ClangUserExpression::Parse(DiagnosticManager &diagnostic_manager, // parser_sp will never be empty. ClangExpressionParser parser(exe_scope, *this, generate_debug_info, - m_include_directories); + m_include_directories, m_filename); unsigned num_errors = parser.Parse(diagnostic_manager); @@ -586,8 +611,11 @@ bool ClangUserExpression::Parse(DiagnosticManager &diagnostic_manager, size_t fixed_end; const std::string &fixed_expression = diagnostic_manager.GetFixedExpression(); - if (ClangExpressionSourceCode::GetOriginalBodyBounds( - fixed_expression, m_expr_lang, fixed_start, fixed_end)) + // Retrieve the original expression in case we don't have a top level + // expression (which has no surrounding source code). + if (m_source_code && + m_source_code->GetOriginalBodyBounds(fixed_expression, m_expr_lang, + fixed_start, fixed_end)) m_fixed_text = fixed_expression.substr(fixed_start, fixed_end - fixed_start); } @@ -648,12 +676,10 @@ bool ClangUserExpression::Parse(DiagnosticManager &diagnostic_manager, register_execution_unit = true; } - if (register_execution_unit) { - llvm::cast<PersistentExpressionState>( - exe_ctx.GetTargetPtr()->GetPersistentExpressionStateForLanguage( - m_language)) + if (register_execution_unit) + exe_ctx.GetTargetPtr() + ->GetPersistentExpressionStateForLanguage(m_language) ->RegisterExecutionUnit(m_execution_unit_sp); - } } if (generate_debug_info) { @@ -726,8 +752,7 @@ bool ClangUserExpression::Complete(ExecutionContext &exe_ctx, if (!PrepareForParsing(diagnostic_manager, exe_ctx, /*for_completion*/ true)) return false; - if (log) - log->Printf("Parsing the following code:\n%s", m_transformed_text.c_str()); + LLDB_LOGF(log, "Parsing the following code:\n%s", m_transformed_text.c_str()); ////////////////////////// // Parse the expression diff --git a/source/Plugins/ExpressionParser/Clang/ClangUserExpression.h b/source/Plugins/ExpressionParser/Clang/ClangUserExpression.h index 24c152bdb45d..d94f9cc5e066 100644 --- a/source/Plugins/ExpressionParser/Clang/ClangUserExpression.h +++ b/source/Plugins/ExpressionParser/Clang/ClangUserExpression.h @@ -15,6 +15,7 @@ #include "ASTStructExtractor.h" #include "ClangExpressionDeclMap.h" #include "ClangExpressionHelper.h" +#include "ClangExpressionSourceCode.h" #include "ClangExpressionVariable.h" #include "IRForTarget.h" @@ -105,6 +106,9 @@ public: /// If not eResultTypeAny, the type to use for the expression /// result. /// + /// \param[in] options + /// Additional options for the expression. + /// /// \param[in] ctx_obj /// The object (if any) in which context the expression /// must be evaluated. For details see the comment to @@ -175,11 +179,11 @@ private: lldb::addr_t struct_address, DiagnosticManager &diagnostic_manager) override; - std::vector<std::string> GetModulesToImport(ExecutionContext &exe_ctx); - void UpdateLanguageForExpr(DiagnosticManager &diagnostic_manager, - ExecutionContext &exe_ctx, - std::vector<std::string> modules_to_import, - bool for_completion); + void CreateSourceCode(DiagnosticManager &diagnostic_manager, + ExecutionContext &exe_ctx, + std::vector<std::string> modules_to_import, + bool for_completion); + void UpdateLanguageForExpr(); bool SetupPersistentState(DiagnosticManager &diagnostic_manager, ExecutionContext &exe_ctx); bool PrepareForParsing(DiagnosticManager &diagnostic_manager, @@ -205,13 +209,17 @@ private: /// The language type of the current expression. lldb::LanguageType m_expr_lang = lldb::eLanguageTypeUnknown; /// The include directories that should be used when parsing the expression. - std::vector<ConstString> m_include_directories; + std::vector<std::string> m_include_directories; /// The absolute character position in the transformed source code where the /// user code (as typed by the user) starts. If the variable is empty, then we /// were not able to calculate this position. llvm::Optional<size_t> m_user_expression_start_pos; ResultDelegate m_result_delegate; + ClangPersistentVariables *m_clang_state; + std::unique_ptr<ClangExpressionSourceCode> m_source_code; + /// File name used for the expression. + std::string m_filename; /// The object (if any) in which context the expression is evaluated. /// See the comment to `UserExpression::Evaluate` for details. @@ -219,6 +227,23 @@ private: /// True iff this expression explicitly imported C++ modules. bool m_imported_cpp_modules = false; + + /// True if the expression parser should enforce the presence of a valid class + /// pointer in order to generate the expression as a method. + bool m_enforce_valid_object = true; + /// True if the expression is compiled as a C++ member function (true if it + /// was parsed when exe_ctx was in a C++ method). + bool m_in_cplusplus_method = false; + /// True if the expression is compiled as an Objective-C method (true if it + /// was parsed when exe_ctx was in an Objective-C method). + bool m_in_objectivec_method = false; + /// True if the expression is compiled as a static (or class) method + /// (currently true if it was parsed when exe_ctx was in an Objective-C class + /// method). + bool m_in_static_method = false; + /// True if "this" or "self" must be looked up and passed in. False if the + /// expression doesn't really use them and they can be NULL. + bool m_needs_object_ptr = false; }; } // namespace lldb_private diff --git a/source/Plugins/ExpressionParser/Clang/ClangUtilityFunction.cpp b/source/Plugins/ExpressionParser/Clang/ClangUtilityFunction.cpp index 5eec224477fc..564c62c6a2c6 100644 --- a/source/Plugins/ExpressionParser/Clang/ClangUtilityFunction.cpp +++ b/source/Plugins/ExpressionParser/Clang/ClangUtilityFunction.cpp @@ -6,6 +6,8 @@ // //===----------------------------------------------------------------------===// +#include "lldb/Host/Config.h" + #include "ClangUtilityFunction.h" #include "ClangExpressionDeclMap.h" #include "ClangExpressionParser.h" diff --git a/source/Plugins/ExpressionParser/Clang/CppModuleConfiguration.cpp b/source/Plugins/ExpressionParser/Clang/CppModuleConfiguration.cpp new file mode 100644 index 000000000000..51ae73285b53 --- /dev/null +++ b/source/Plugins/ExpressionParser/Clang/CppModuleConfiguration.cpp @@ -0,0 +1,82 @@ +//===-- CppModuleConfiguration.cpp ----------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#include "CppModuleConfiguration.h" + +#include "ClangHost.h" +#include "lldb/Host/FileSystem.h" + +using namespace lldb_private; + +bool CppModuleConfiguration::SetOncePath::TrySet(llvm::StringRef path) { + // Setting for the first time always works. + if (m_first) { + m_path = path.str(); + m_valid = true; + m_first = false; + return true; + } + // Changing the path to the same value is fine. + if (m_path == path) + return true; + + // Changing the path after it was already set is not allowed. + m_valid = false; + return false; +} + +bool CppModuleConfiguration::analyzeFile(const FileSpec &f) { + using namespace llvm::sys::path; + // Convert to slashes to make following operations simpler. + std::string dir_buffer = convert_to_slash(f.GetDirectory().GetStringRef()); + llvm::StringRef posix_dir(dir_buffer); + + // Check for /c++/vX/ that is used by libc++. + static llvm::Regex libcpp_regex(R"regex(/c[+][+]/v[0-9]/)regex"); + if (libcpp_regex.match(f.GetPath())) { + // Strip away libc++'s /experimental directory if there is one. + posix_dir.consume_back("/experimental"); + return m_std_inc.TrySet(posix_dir); + } + + // Check for /usr/include. On Linux this might be /usr/include/bits, so + // we should remove that '/bits' suffix to get the actual include directory. + if (posix_dir.endswith("/usr/include/bits")) + posix_dir.consume_back("/bits"); + if (posix_dir.endswith("/usr/include")) + return m_c_inc.TrySet(posix_dir); + + // File wasn't interesting, continue analyzing. + return true; +} + +bool CppModuleConfiguration::hasValidConfig() { + // We all these include directories to have a valid usable configuration. + return m_c_inc.Valid() && m_std_inc.Valid(); +} + +CppModuleConfiguration::CppModuleConfiguration( + const FileSpecList &support_files) { + // Analyze all files we were given to build the configuration. + bool error = !llvm::all_of(support_files, + std::bind(&CppModuleConfiguration::analyzeFile, + this, std::placeholders::_1)); + // If we have a valid configuration at this point, set the + // include directories and module list that should be used. + if (!error && hasValidConfig()) { + // Calculate the resource directory for LLDB. + llvm::SmallString<256> resource_dir; + llvm::sys::path::append(resource_dir, GetClangResourceDir().GetPath(), + "include"); + m_resource_inc = resource_dir.str(); + + // This order matches the way Clang orders these directories. + m_include_dirs = {m_std_inc.Get(), m_resource_inc, m_c_inc.Get()}; + m_imported_modules = {"std"}; + } +} diff --git a/source/Plugins/ExpressionParser/Clang/CppModuleConfiguration.h b/source/Plugins/ExpressionParser/Clang/CppModuleConfiguration.h new file mode 100644 index 000000000000..8e892e37d0de --- /dev/null +++ b/source/Plugins/ExpressionParser/Clang/CppModuleConfiguration.h @@ -0,0 +1,84 @@ +//===-- CppModuleConfiguration.h --------------------------------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef liblldb_CppModuleConfiguration_h_ +#define liblldb_CppModuleConfiguration_h_ + +#include <lldb/Core/FileSpecList.h> +#include <llvm/Support/Regex.h> + +namespace lldb_private { + +/// A Clang configuration when importing C++ modules. +/// +/// Includes a list of include paths that should be used when importing +/// and a list of modules that can be imported. Currently only used when +/// importing the 'std' module and its dependencies. +class CppModuleConfiguration { + /// Utility class for a path that can only be set once. + class SetOncePath { + std::string m_path; + bool m_valid = false; + /// True iff this path hasn't been set yet. + bool m_first = true; + + public: + /// Try setting the path. Returns true if the path was set and false if + /// the path was already set. + LLVM_NODISCARD bool TrySet(llvm::StringRef path); + /// Return the path if there is one. + std::string Get() const { + assert(m_valid && "Called Get() on an invalid SetOncePath?"); + return m_path; + } + /// Returns true iff this path was set exactly once so far. + bool Valid() const { return m_valid; } + }; + + /// If valid, the include path used for the std module. + SetOncePath m_std_inc; + /// If valid, the include path to the C library (e.g. /usr/include). + SetOncePath m_c_inc; + /// The Clang resource include path for this configuration. + std::string m_resource_inc; + + std::vector<std::string> m_include_dirs; + std::vector<std::string> m_imported_modules; + + /// Analyze a given source file to build the current configuration. + /// Returns false iff there was a fatal error that makes analyzing any + /// further files pointless as the configuration is now invalid. + bool analyzeFile(const FileSpec &f); + +public: + /// Creates a configuraiton by analyzing the given list of used source files. + /// + /// Currently only looks at the used paths and doesn't actually access the + /// files on the disk. + explicit CppModuleConfiguration(const FileSpecList &support_files); + /// Creates an empty and invalid configuration. + CppModuleConfiguration() {} + + /// Returns true iff this is a valid configuration that can be used to + /// load and compile modules. + bool hasValidConfig(); + + /// Returns a list of include directories that should be used when using this + /// configuration (e.g. {"/usr/include", "/usr/include/c++/v1"}). + llvm::ArrayRef<std::string> GetIncludeDirs() const { return m_include_dirs; } + + /// Returns a list of (top level) modules that should be imported when using + /// this configuration (e.g. {"std"}). + llvm::ArrayRef<std::string> GetImportedModules() const { + return m_imported_modules; + } +}; + +} // namespace lldb_private + +#endif diff --git a/source/Plugins/ExpressionParser/Clang/IRDynamicChecks.cpp b/source/Plugins/ExpressionParser/Clang/IRDynamicChecks.cpp index f8e004fe7d4a..d5ffb9529f36 100644 --- a/source/Plugins/ExpressionParser/Clang/IRDynamicChecks.cpp +++ b/source/Plugins/ExpressionParser/Clang/IRDynamicChecks.cpp @@ -320,9 +320,8 @@ protected: bool InstrumentInstruction(llvm::Instruction *inst) override { Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_EXPRESSIONS)); - if (log) - log->Printf("Instrumenting load/store instruction: %s\n", - PrintValue(inst).c_str()); + LLDB_LOGF(log, "Instrumenting load/store instruction: %s\n", + PrintValue(inst).c_str()); if (!m_valid_pointer_check_func) m_valid_pointer_check_func = @@ -483,9 +482,8 @@ protected: std::string name_str = called_function->getName().str(); const char *name_cstr = name_str.c_str(); - if (log) - log->Printf("Found call to %s: %s\n", name_cstr, - PrintValue(call_inst).c_str()); + LLDB_LOGF(log, "Found call to %s: %s\n", name_cstr, + PrintValue(call_inst).c_str()); if (name_str.find("objc_msgSend") == std::string::npos) return true; @@ -520,10 +518,9 @@ protected: return true; } - if (log) - log->Printf( - "Function name '%s' contains 'objc_msgSend' but is not handled", - name_str.c_str()); + LLDB_LOGF(log, + "Function name '%s' contains 'objc_msgSend' but is not handled", + name_str.c_str()); return true; } @@ -548,8 +545,7 @@ bool IRDynamicChecks::runOnModule(llvm::Module &M) { llvm::Function *function = M.getFunction(StringRef(m_func_name)); if (!function) { - if (log) - log->Printf("Couldn't find %s() in the module", m_func_name.c_str()); + LLDB_LOGF(log, "Couldn't find %s() in the module", m_func_name.c_str()); return false; } @@ -582,7 +578,7 @@ bool IRDynamicChecks::runOnModule(llvm::Module &M) { oss.flush(); - log->Printf("Module after dynamic checks: \n%s", s.c_str()); + LLDB_LOGF(log, "Module after dynamic checks: \n%s", s.c_str()); } return true; diff --git a/source/Plugins/ExpressionParser/Clang/IRForTarget.cpp b/source/Plugins/ExpressionParser/Clang/IRForTarget.cpp index 07acb2e1030f..4e871f7d6a44 100644 --- a/source/Plugins/ExpressionParser/Clang/IRForTarget.cpp +++ b/source/Plugins/ExpressionParser/Clang/IRForTarget.cpp @@ -43,6 +43,8 @@ using namespace llvm; static char ID; +typedef SmallVector<Instruction *, 2> InstrList; + IRForTarget::FunctionValueCache::FunctionValueCache(Maker const &maker) : m_maker(maker), m_values() {} @@ -153,6 +155,15 @@ clang::NamedDecl *IRForTarget::DeclForGlobal(GlobalValue *global_val) { return DeclForGlobal(global_val, m_module); } +/// Returns true iff the mangled symbol is for a static guard variable. +static bool isGuardVariableSymbol(llvm::StringRef mangled_symbol, + bool check_ms_abi = true) { + bool result = mangled_symbol.startswith("_ZGV"); // Itanium ABI guard variable + if (check_ms_abi) + result |= mangled_symbol.endswith("@4IA"); // Microsoft ABI + return result; +} + bool IRForTarget::CreateResultVariable(llvm::Function &llvm_function) { lldb_private::Log *log( lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_EXPRESSIONS)); @@ -164,64 +175,58 @@ bool IRForTarget::CreateResultVariable(llvm::Function &llvm_function) { ValueSymbolTable &value_symbol_table = m_module->getValueSymbolTable(); - std::string result_name_str; - const char *result_name = nullptr; + llvm::StringRef result_name; + bool found_result = false; - for (ValueSymbolTable::iterator vi = value_symbol_table.begin(), - ve = value_symbol_table.end(); - vi != ve; ++vi) { - result_name_str = vi->first().str(); - const char *value_name = result_name_str.c_str(); + for (StringMapEntry<llvm::Value *> &value_symbol : value_symbol_table) { + result_name = value_symbol.first(); - if (strstr(value_name, "$__lldb_expr_result_ptr") && - strncmp(value_name, "_ZGV", 4)) { - result_name = value_name; + // Check if this is a guard variable. It seems this causes some hiccups + // on Windows, so let's only check for Itanium guard variables. + bool is_guard_var = isGuardVariableSymbol(result_name, /*MS ABI*/ false); + + if (result_name.contains("$__lldb_expr_result_ptr") && !is_guard_var) { + found_result = true; m_result_is_pointer = true; break; } - if (strstr(value_name, "$__lldb_expr_result") && - strncmp(value_name, "_ZGV", 4)) { - result_name = value_name; + if (result_name.contains("$__lldb_expr_result") && !is_guard_var) { + found_result = true; m_result_is_pointer = false; break; } } - if (!result_name) { - if (log) - log->PutCString("Couldn't find result variable"); + if (!found_result) { + LLDB_LOG(log, "Couldn't find result variable"); return true; } - if (log) - log->Printf("Result name: \"%s\"", result_name); + LLDB_LOG(log, "Result name: \"{0}\"", result_name); Value *result_value = m_module->getNamedValue(result_name); if (!result_value) { - if (log) - log->PutCString("Result variable had no data"); + LLDB_LOG(log, "Result variable had no data"); - m_error_stream.Printf("Internal error [IRForTarget]: Result variable's " - "name (%s) exists, but not its definition\n", + m_error_stream.Format("Internal error [IRForTarget]: Result variable's " + "name ({0}) exists, but not its definition\n", result_name); return false; } - if (log) - log->Printf("Found result in the IR: \"%s\"", - PrintValue(result_value, false).c_str()); + LLDB_LOG(log, "Found result in the IR: \"{0}\"", + PrintValue(result_value, false)); GlobalVariable *result_global = dyn_cast<GlobalVariable>(result_value); if (!result_global) { - if (log) - log->PutCString("Result variable isn't a GlobalVariable"); + LLDB_LOG(log, "Result variable isn't a GlobalVariable"); - m_error_stream.Printf("Internal error [IRForTarget]: Result variable (%s) " + m_error_stream.Format("Internal error [IRForTarget]: Result variable ({0}) " "is defined, but is not a global variable\n", result_name); @@ -230,10 +235,9 @@ bool IRForTarget::CreateResultVariable(llvm::Function &llvm_function) { clang::NamedDecl *result_decl = DeclForGlobal(result_global); if (!result_decl) { - if (log) - log->PutCString("Result variable doesn't have a corresponding Decl"); + LLDB_LOG(log, "Result variable doesn't have a corresponding Decl"); - m_error_stream.Printf("Internal error [IRForTarget]: Result variable (%s) " + m_error_stream.Format("Internal error [IRForTarget]: Result variable ({0}) " "does not have a corresponding Clang entity\n", result_name); @@ -246,16 +250,15 @@ bool IRForTarget::CreateResultVariable(llvm::Function &llvm_function) { result_decl->print(decl_desc_stream); decl_desc_stream.flush(); - log->Printf("Found result decl: \"%s\"", decl_desc_str.c_str()); + LLDB_LOG(log, "Found result decl: \"{0}\"", decl_desc_str); } clang::VarDecl *result_var = dyn_cast<clang::VarDecl>(result_decl); if (!result_var) { - if (log) - log->PutCString("Result variable Decl isn't a VarDecl"); + LLDB_LOG(log, "Result variable Decl isn't a VarDecl"); - m_error_stream.Printf("Internal error [IRForTarget]: Result variable " - "(%s)'s corresponding Clang entity isn't a " + m_error_stream.Format("Internal error [IRForTarget]: Result variable " + "({0})'s corresponding Clang entity isn't a " "variable\n", result_name); @@ -292,10 +295,9 @@ bool IRForTarget::CreateResultVariable(llvm::Function &llvm_function) { lldb_private::ClangASTContext::GetASTContext( &result_decl->getASTContext())); } else { - if (log) - log->PutCString("Expected result to have pointer type, but it did not"); + LLDB_LOG(log, "Expected result to have pointer type, but it did not"); - m_error_stream.Printf("Internal error [IRForTarget]: Lvalue result (%s) " + m_error_stream.Format("Internal error [IRForTarget]: Lvalue result ({0}) " "is not a pointer variable\n", result_name); @@ -316,8 +318,7 @@ bool IRForTarget::CreateResultVariable(llvm::Function &llvm_function) { lldb_private::StreamString type_desc_stream; m_result_type.DumpTypeDescription(&type_desc_stream); - if (log) - log->Printf("Result type has unknown size"); + LLDB_LOG(log, "Result type has unknown size"); m_error_stream.Printf("Error [IRForTarget]: Size of result type '%s' " "couldn't be determined\n", @@ -329,15 +330,13 @@ bool IRForTarget::CreateResultVariable(llvm::Function &llvm_function) { lldb_private::StreamString type_desc_stream; m_result_type.DumpTypeDescription(&type_desc_stream); - log->Printf("Result decl type: \"%s\"", type_desc_stream.GetData()); + LLDB_LOG(log, "Result decl type: \"{0}\"", type_desc_stream.GetData()); } m_result_name = lldb_private::ConstString("$RESULT_NAME"); - if (log) - log->Printf("Creating a new result global: \"%s\" with size 0x%" PRIx64, - m_result_name.GetCString(), - m_result_type.GetByteSize(nullptr).getValueOr(0)); + LLDB_LOG(log, "Creating a new result global: \"{0}\" with size {1}", + m_result_name, m_result_type.GetByteSize(nullptr).getValueOr(0)); // Construct a new result global and set up its metadata @@ -369,10 +368,8 @@ bool IRForTarget::CreateResultVariable(llvm::Function &llvm_function) { m_module->getNamedMetadata("clang.global.decl.ptrs"); named_metadata->addOperand(persistent_global_md); - if (log) - log->Printf("Replacing \"%s\" with \"%s\"", - PrintValue(result_global).c_str(), - PrintValue(new_result_global).c_str()); + LLDB_LOG(log, "Replacing \"{0}\" with \"{1}\"", PrintValue(result_global), + PrintValue(new_result_global)); if (result_global->use_empty()) { // We need to synthesize a store for this variable, because otherwise @@ -385,11 +382,10 @@ bool IRForTarget::CreateResultVariable(llvm::Function &llvm_function) { return false; if (!result_global->hasInitializer()) { - if (log) - log->Printf("Couldn't find initializer for unused variable"); + LLDB_LOG(log, "Couldn't find initializer for unused variable"); - m_error_stream.Printf("Internal error [IRForTarget]: Result variable " - "(%s) has no writes and no initializer\n", + m_error_stream.Format("Internal error [IRForTarget]: Result variable " + "({0}) has no writes and no initializer\n", result_name); return false; @@ -400,9 +396,8 @@ bool IRForTarget::CreateResultVariable(llvm::Function &llvm_function) { StoreInst *synthesized_store = new StoreInst(initializer, new_result_global, first_entry_instruction); - if (log) - log->Printf("Synthesized result store \"%s\"\n", - PrintValue(synthesized_store).c_str()); + LLDB_LOG(log, "Synthesized result store \"{0}\"\n", + PrintValue(synthesized_store)); } else { result_global->replaceAllUsesWith(new_result_global); } @@ -438,7 +433,6 @@ bool IRForTarget::RewriteObjCConstString(llvm::GlobalVariable *ns_str, m_execution_unit.FindSymbol(g_CFStringCreateWithBytes_str, missing_weak); if (CFStringCreateWithBytes_addr == LLDB_INVALID_ADDRESS || missing_weak) { - if (log) log->PutCString("Couldn't find CFStringCreateWithBytes in the target"); m_error_stream.Printf("Error [IRForTarget]: Rewriting an Objective-C " @@ -448,9 +442,8 @@ bool IRForTarget::RewriteObjCConstString(llvm::GlobalVariable *ns_str, return false; } - if (log) - log->Printf("Found CFStringCreateWithBytes at 0x%" PRIx64, - CFStringCreateWithBytes_addr); + LLDB_LOG(log, "Found CFStringCreateWithBytes at {0}", + CFStringCreateWithBytes_addr); // Build the function type: // @@ -543,9 +536,7 @@ bool IRForTarget::RewriteObjCConstString(llvm::GlobalVariable *ns_str, if (!UnfoldConstant(ns_str, nullptr, CFSCWB_Caller, m_entry_instruction_finder, m_error_stream)) { - if (log) - log->PutCString( - "Couldn't replace the NSString with the result of the call"); + LLDB_LOG(log, "Couldn't replace the NSString with the result of the call"); m_error_stream.Printf("error [IRForTarget internal]: Couldn't replace an " "Objective-C constant string with a dynamic " @@ -565,21 +556,17 @@ bool IRForTarget::RewriteObjCConstStrings() { ValueSymbolTable &value_symbol_table = m_module->getValueSymbolTable(); - for (ValueSymbolTable::iterator vi = value_symbol_table.begin(), - ve = value_symbol_table.end(); - vi != ve; ++vi) { - std::string value_name = vi->first().str(); - const char *value_name_cstr = value_name.c_str(); + for (StringMapEntry<llvm::Value *> &value_symbol : value_symbol_table) { + llvm::StringRef value_name = value_symbol.first(); - if (strstr(value_name_cstr, "_unnamed_cfstring_")) { - Value *nsstring_value = vi->second; + if (value_name.contains("_unnamed_cfstring_")) { + Value *nsstring_value = value_symbol.second; GlobalVariable *nsstring_global = dyn_cast<GlobalVariable>(nsstring_value); if (!nsstring_global) { - if (log) - log->PutCString("NSString variable is not a GlobalVariable"); + LLDB_LOG(log, "NSString variable is not a GlobalVariable"); m_error_stream.Printf("Internal error [IRForTarget]: An Objective-C " "constant string is not a global variable\n"); @@ -588,8 +575,7 @@ bool IRForTarget::RewriteObjCConstStrings() { } if (!nsstring_global->hasInitializer()) { - if (log) - log->PutCString("NSString variable does not have an initializer"); + LLDB_LOG(log, "NSString variable does not have an initializer"); m_error_stream.Printf("Internal error [IRForTarget]: An Objective-C " "constant string does not have an initializer\n"); @@ -601,9 +587,8 @@ bool IRForTarget::RewriteObjCConstStrings() { dyn_cast<ConstantStruct>(nsstring_global->getInitializer()); if (!nsstring_struct) { - if (log) - log->PutCString( - "NSString variable's initializer is not a ConstantStruct"); + LLDB_LOG(log, + "NSString variable's initializer is not a ConstantStruct"); m_error_stream.Printf("Internal error [IRForTarget]: An Objective-C " "constant string is not a structure constant\n"); @@ -621,10 +606,11 @@ bool IRForTarget::RewriteObjCConstStrings() { // }; if (nsstring_struct->getNumOperands() != 4) { - if (log) - log->Printf("NSString variable's initializer structure has an " - "unexpected number of members. Should be 4, is %d", - nsstring_struct->getNumOperands()); + + LLDB_LOG(log, + "NSString variable's initializer structure has an " + "unexpected number of members. Should be 4, is {0}", + nsstring_struct->getNumOperands()); m_error_stream.Printf("Internal error [IRForTarget]: The struct for an " "Objective-C constant string is not as " @@ -636,8 +622,7 @@ bool IRForTarget::RewriteObjCConstStrings() { Constant *nsstring_member = nsstring_struct->getOperand(2); if (!nsstring_member) { - if (log) - log->PutCString("NSString initializer's str element was empty"); + LLDB_LOG(log, "NSString initializer's str element was empty"); m_error_stream.Printf("Internal error [IRForTarget]: An Objective-C " "constant string does not have a string " @@ -649,9 +634,8 @@ bool IRForTarget::RewriteObjCConstStrings() { ConstantExpr *nsstring_expr = dyn_cast<ConstantExpr>(nsstring_member); if (!nsstring_expr) { - if (log) - log->PutCString( - "NSString initializer's str element is not a ConstantExpr"); + LLDB_LOG(log, + "NSString initializer's str element is not a ConstantExpr"); m_error_stream.Printf("Internal error [IRForTarget]: An Objective-C " "constant string's string initializer is not " @@ -671,9 +655,8 @@ bool IRForTarget::RewriteObjCConstStrings() { } if (!cstr_global) { - if (log) - log->PutCString( - "NSString initializer's str element is not a GlobalVariable"); + LLDB_LOG(log, + "NSString initializer's str element is not a GlobalVariable"); m_error_stream.Printf("Internal error [IRForTarget]: Unhandled" "constant string initializer\n"); @@ -682,9 +665,8 @@ bool IRForTarget::RewriteObjCConstStrings() { } if (!cstr_global->hasInitializer()) { - if (log) - log->PutCString("NSString initializer's str element does not have an " - "initializer"); + LLDB_LOG(log, "NSString initializer's str element does not have an " + "initializer"); m_error_stream.Printf("Internal error [IRForTarget]: An Objective-C " "constant string's string initializer doesn't " @@ -726,21 +708,18 @@ bool IRForTarget::RewriteObjCConstStrings() { ConstantDataArray *cstr_array = dyn_cast<ConstantDataArray>(cstr_global->getInitializer()); - if (log) { - if (cstr_array) - log->Printf("Found NSString constant %s, which contains \"%s\"", - value_name_cstr, cstr_array->getAsString().str().c_str()); - else - log->Printf("Found NSString constant %s, which contains \"\"", - value_name_cstr); - } + if (cstr_array) + LLDB_LOG(log, "Found NSString constant {0}, which contains \"{1}\"", + value_name, cstr_array->getAsString()); + else + LLDB_LOG(log, "Found NSString constant {0}, which contains \"\"", + value_name); if (!cstr_array) cstr_global = nullptr; if (!RewriteObjCConstString(nsstring_global, cstr_global)) { - if (log) - log->PutCString("Error rewriting the constant string"); + LLDB_LOG(log, "Error rewriting the constant string"); // We don't print an error message here because RewriteObjCConstString // has done so for us. @@ -750,19 +729,15 @@ bool IRForTarget::RewriteObjCConstStrings() { } } - for (ValueSymbolTable::iterator vi = value_symbol_table.begin(), - ve = value_symbol_table.end(); - vi != ve; ++vi) { - std::string value_name = vi->first().str(); - const char *value_name_cstr = value_name.c_str(); + for (StringMapEntry<llvm::Value *> &value_symbol : value_symbol_table) { + llvm::StringRef value_name = value_symbol.first(); - if (!strcmp(value_name_cstr, "__CFConstantStringClassReference")) { - GlobalVariable *gv = dyn_cast<GlobalVariable>(vi->second); + if (value_name == "__CFConstantStringClassReference") { + GlobalVariable *gv = dyn_cast<GlobalVariable>(value_symbol.second); if (!gv) { - if (log) - log->PutCString( - "__CFConstantStringClassReference is not a global variable"); + LLDB_LOG(log, + "__CFConstantStringClassReference is not a global variable"); m_error_stream.Printf("Internal error [IRForTarget]: Found a " "CFConstantStringClassReference, but it is not a " @@ -850,9 +825,8 @@ bool IRForTarget::RewriteObjCSelector(Instruction *selector_load) { std::string omvn_initializer_string = omvn_initializer_array->getAsString(); - if (log) - log->Printf("Found Objective-C selector reference \"%s\"", - omvn_initializer_string.c_str()); + LLDB_LOG(log, "Found Objective-C selector reference \"{0}\"", + omvn_initializer_string); // Construct a call to sel_registerName @@ -866,9 +840,7 @@ bool IRForTarget::RewriteObjCSelector(Instruction *selector_load) { if (sel_registerName_addr == LLDB_INVALID_ADDRESS || missing_weak) return false; - if (log) - log->Printf("Found sel_registerName at 0x%" PRIx64, - sel_registerName_addr); + LLDB_LOG(log, "Found sel_registerName at {0}", sel_registerName_addr); // Build the function type: struct objc_selector // *sel_registerName(uint8_t*) @@ -921,32 +893,21 @@ bool IRForTarget::RewriteObjCSelectors(BasicBlock &basic_block) { lldb_private::Log *log( lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_EXPRESSIONS)); - BasicBlock::iterator ii; - - typedef SmallVector<Instruction *, 2> InstrList; - typedef InstrList::iterator InstrIterator; - InstrList selector_loads; - for (ii = basic_block.begin(); ii != basic_block.end(); ++ii) { - Instruction &inst = *ii; - + for (Instruction &inst : basic_block) { if (LoadInst *load = dyn_cast<LoadInst>(&inst)) if (IsObjCSelectorRef(load->getPointerOperand())) selector_loads.push_back(&inst); } - InstrIterator iter; - - for (iter = selector_loads.begin(); iter != selector_loads.end(); ++iter) { - if (!RewriteObjCSelector(*iter)) { + for (Instruction *inst : selector_loads) { + if (!RewriteObjCSelector(inst)) { m_error_stream.Printf("Internal error [IRForTarget]: Couldn't change a " "static reference to an Objective-C selector to a " "dynamic reference\n"); - if (log) - log->PutCString( - "Couldn't rewrite a reference to an Objective-C selector"); + LLDB_LOG(log, "Couldn't rewrite a reference to an Objective-C selector"); return false; } @@ -1022,9 +983,8 @@ bool IRForTarget::RewriteObjCClassReference(Instruction *class_load) { std::string ocn_initializer_string = ocn_initializer_array->getAsString(); - if (log) - log->Printf("Found Objective-C class reference \"%s\"", - ocn_initializer_string.c_str()); + LLDB_LOG(log, "Found Objective-C class reference \"{0}\"", + ocn_initializer_string); // Construct a call to objc_getClass @@ -1038,9 +998,7 @@ bool IRForTarget::RewriteObjCClassReference(Instruction *class_load) { if (objc_getClass_addr == LLDB_INVALID_ADDRESS || missing_weak) return false; - if (log) - log->Printf("Found objc_getClass at 0x%" PRIx64, - objc_getClass_addr); + LLDB_LOG(log, "Found objc_getClass at {0}", objc_getClass_addr); // Build the function type: %struct._objc_class *objc_getClass(i8*) @@ -1086,32 +1044,21 @@ bool IRForTarget::RewriteObjCClassReferences(BasicBlock &basic_block) { lldb_private::Log *log( lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_EXPRESSIONS)); - BasicBlock::iterator ii; - - typedef SmallVector<Instruction *, 2> InstrList; - typedef InstrList::iterator InstrIterator; - InstrList class_loads; - for (ii = basic_block.begin(); ii != basic_block.end(); ++ii) { - Instruction &inst = *ii; - + for (Instruction &inst : basic_block) { if (LoadInst *load = dyn_cast<LoadInst>(&inst)) if (IsObjCClassReference(load->getPointerOperand())) class_loads.push_back(&inst); } - InstrIterator iter; - - for (iter = class_loads.begin(); iter != class_loads.end(); ++iter) { - if (!RewriteObjCClassReference(*iter)) { + for (Instruction *inst : class_loads) { + if (!RewriteObjCClassReference(inst)) { m_error_stream.Printf("Internal error [IRForTarget]: Couldn't change a " "static reference to an Objective-C class to a " "dynamic reference\n"); - if (log) - log->PutCString( - "Couldn't rewrite a reference to an Objective-C class"); + LLDB_LOG(log, "Couldn't rewrite a reference to an Objective-C class"); return false; } @@ -1180,9 +1127,8 @@ bool IRForTarget::RewritePersistentAlloc(llvm::Instruction *persistent_alloc) { LoadInst *persistent_load = new LoadInst(persistent_global, "", alloc); - if (log) - log->Printf("Replacing \"%s\" with \"%s\"", PrintValue(alloc).c_str(), - PrintValue(persistent_load).c_str()); + LLDB_LOG(log, "Replacing \"{0}\" with \"{1}\"", PrintValue(alloc), + PrintValue(persistent_load)); alloc->replaceAllUsesWith(persistent_load); alloc->eraseFromParent(); @@ -1197,23 +1143,16 @@ bool IRForTarget::RewritePersistentAllocs(llvm::BasicBlock &basic_block) { lldb_private::Log *log( lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_EXPRESSIONS)); - BasicBlock::iterator ii; - - typedef SmallVector<Instruction *, 2> InstrList; - typedef InstrList::iterator InstrIterator; - InstrList pvar_allocs; - for (ii = basic_block.begin(); ii != basic_block.end(); ++ii) { - Instruction &inst = *ii; + for (Instruction &inst : basic_block) { if (AllocaInst *alloc = dyn_cast<AllocaInst>(&inst)) { llvm::StringRef alloc_name = alloc->getName(); if (alloc_name.startswith("$") && !alloc_name.startswith("$__lldb")) { if (alloc_name.find_first_of("0123456789") == 1) { - if (log) - log->Printf("Rejecting a numeric persistent variable."); + LLDB_LOG(log, "Rejecting a numeric persistent variable."); m_error_stream.Printf("Error [IRForTarget]: Names starting with $0, " "$1, ... are reserved for use as result " @@ -1227,16 +1166,12 @@ bool IRForTarget::RewritePersistentAllocs(llvm::BasicBlock &basic_block) { } } - InstrIterator iter; - - for (iter = pvar_allocs.begin(); iter != pvar_allocs.end(); ++iter) { - if (!RewritePersistentAlloc(*iter)) { + for (Instruction *inst : pvar_allocs) { + if (!RewritePersistentAlloc(inst)) { m_error_stream.Printf("Internal error [IRForTarget]: Couldn't rewrite " "the creation of a persistent variable\n"); - if (log) - log->PutCString( - "Couldn't rewrite the creation of a persistent variable"); + LLDB_LOG(log, "Couldn't rewrite the creation of a persistent variable"); return false; } @@ -1245,79 +1180,12 @@ bool IRForTarget::RewritePersistentAllocs(llvm::BasicBlock &basic_block) { return true; } -bool IRForTarget::MaterializeInitializer(uint8_t *data, Constant *initializer) { - if (!initializer) - return true; - - lldb_private::Log *log( - lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_EXPRESSIONS)); - - if (log && log->GetVerbose()) - log->Printf(" MaterializeInitializer(%p, %s)", (void *)data, - PrintValue(initializer).c_str()); - - Type *initializer_type = initializer->getType(); - - if (ConstantInt *int_initializer = dyn_cast<ConstantInt>(initializer)) { - size_t constant_size = m_target_data->getTypeStoreSize(initializer_type); - lldb_private::Scalar scalar = int_initializer->getValue().zextOrTrunc( - llvm::NextPowerOf2(constant_size) * 8); - - lldb_private::Status get_data_error; - return scalar.GetAsMemoryData(data, constant_size, - lldb_private::endian::InlHostByteOrder(), - get_data_error) != 0; - } else if (ConstantDataArray *array_initializer = - dyn_cast<ConstantDataArray>(initializer)) { - if (array_initializer->isString()) { - std::string array_initializer_string = array_initializer->getAsString(); - memcpy(data, array_initializer_string.c_str(), - m_target_data->getTypeStoreSize(initializer_type)); - } else { - ArrayType *array_initializer_type = array_initializer->getType(); - Type *array_element_type = array_initializer_type->getElementType(); - - size_t element_size = m_target_data->getTypeAllocSize(array_element_type); - - for (unsigned i = 0; i < array_initializer->getNumOperands(); ++i) { - Value *operand_value = array_initializer->getOperand(i); - Constant *operand_constant = dyn_cast<Constant>(operand_value); - - if (!operand_constant) - return false; - - if (!MaterializeInitializer(data + (i * element_size), - operand_constant)) - return false; - } - } - return true; - } else if (ConstantStruct *struct_initializer = - dyn_cast<ConstantStruct>(initializer)) { - StructType *struct_initializer_type = struct_initializer->getType(); - const StructLayout *struct_layout = - m_target_data->getStructLayout(struct_initializer_type); - - for (unsigned i = 0; i < struct_initializer->getNumOperands(); ++i) { - if (!MaterializeInitializer(data + struct_layout->getElementOffset(i), - struct_initializer->getOperand(i))) - return false; - } - return true; - } else if (isa<ConstantAggregateZero>(initializer)) { - memset(data, 0, m_target_data->getTypeStoreSize(initializer_type)); - return true; - } - return false; -} - // This function does not report errors; its callers are responsible. bool IRForTarget::MaybeHandleVariable(Value *llvm_value_ptr) { lldb_private::Log *log( lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_EXPRESSIONS)); - if (log) - log->Printf("MaybeHandleVariable (%s)", PrintValue(llvm_value_ptr).c_str()); + LLDB_LOG(log, "MaybeHandleVariable ({0})", PrintValue(llvm_value_ptr)); if (ConstantExpr *constant_expr = dyn_cast<ConstantExpr>(llvm_value_ptr)) { switch (constant_expr->getOpcode()) { @@ -1343,25 +1211,26 @@ bool IRForTarget::MaybeHandleVariable(Value *llvm_value_ptr) { if (!global_variable->hasExternalLinkage()) return true; - if (log) - log->Printf("Found global variable \"%s\" without metadata", - global_variable->getName().str().c_str()); + LLDB_LOG(log, "Found global variable \"{0}\" without metadata", + global_variable->getName()); return false; } - std::string name(named_decl->getName().str()); + llvm::StringRef name(named_decl->getName()); clang::ValueDecl *value_decl = dyn_cast<clang::ValueDecl>(named_decl); if (value_decl == nullptr) return false; - lldb_private::CompilerType compiler_type(&value_decl->getASTContext(), - value_decl->getType()); + lldb_private::CompilerType compiler_type( + lldb_private::ClangASTContext::GetASTContext( + &value_decl->getASTContext()), + value_decl->getType().getAsOpaquePtr()); const Type *value_type = nullptr; - if (name[0] == '$') { + if (name.startswith("$")) { // The $__lldb_expr_result name indicates the return value has allocated // as a static variable. Per the comment at // ASTResultSynthesizer::SynthesizeBodyResult, accesses to this static @@ -1381,31 +1250,24 @@ bool IRForTarget::MaybeHandleVariable(Value *llvm_value_ptr) { llvm::Optional<uint64_t> value_size = compiler_type.GetByteSize(nullptr); if (!value_size) return false; - lldb::offset_t value_alignment = - (compiler_type.GetTypeBitAlign() + 7ull) / 8ull; - - if (log) { - log->Printf("Type of \"%s\" is [clang \"%s\", llvm \"%s\"] [size %" PRIu64 - ", align %" PRIu64 "]", - name.c_str(), - lldb_private::ClangUtil::GetQualType(compiler_type) - .getAsString() - .c_str(), - PrintType(value_type).c_str(), *value_size, value_alignment); - } - - if (named_decl && - !m_decl_map->AddValueToStruct( - named_decl, lldb_private::ConstString(name.c_str()), llvm_value_ptr, - *value_size, value_alignment)) { - if (!global_variable->hasExternalLinkage()) - return true; - else - return true; - } + llvm::Optional<size_t> opt_alignment = compiler_type.GetTypeBitAlign(nullptr); + if (!opt_alignment) + return false; + lldb::offset_t value_alignment = (*opt_alignment + 7ull) / 8ull; + + LLDB_LOG(log, + "Type of \"{0}\" is [clang \"{1}\", llvm \"{2}\"] [size {3}, " + "align {4}]", + name, + lldb_private::ClangUtil::GetQualType(compiler_type).getAsString(), + PrintType(value_type), *value_size, value_alignment); + + if (named_decl) + m_decl_map->AddValueToStruct(named_decl, lldb_private::ConstString(name), + llvm_value_ptr, *value_size, + value_alignment); } else if (dyn_cast<llvm::Function>(llvm_value_ptr)) { - if (log) - log->Printf("Function pointers aren't handled right now"); + LLDB_LOG(log, "Function pointers aren't handled right now"); return false; } @@ -1424,14 +1286,12 @@ bool IRForTarget::HandleSymbol(Value *symbol) { m_decl_map->GetSymbolAddress(name, lldb::eSymbolTypeAny); if (symbol_addr == LLDB_INVALID_ADDRESS) { - if (log) - log->Printf("Symbol \"%s\" had no address", name.GetCString()); + LLDB_LOG(log, "Symbol \"{0}\" had no address", name); return false; } - if (log) - log->Printf("Found \"%s\" at 0x%" PRIx64, name.GetCString(), symbol_addr); + LLDB_LOG(log, "Found \"{0}\" at {1}", name, symbol_addr); Type *symbol_type = symbol->getType(); @@ -1440,9 +1300,8 @@ bool IRForTarget::HandleSymbol(Value *symbol) { Value *symbol_addr_ptr = ConstantExpr::getIntToPtr(symbol_addr_int, symbol_type); - if (log) - log->Printf("Replacing %s with %s", PrintValue(symbol).c_str(), - PrintValue(symbol_addr_ptr).c_str()); + LLDB_LOG(log, "Replacing {0} with {1}", PrintValue(symbol), + PrintValue(symbol_addr_ptr)); symbol->replaceAllUsesWith(symbol_addr_ptr); @@ -1453,14 +1312,12 @@ bool IRForTarget::MaybeHandleCallArguments(CallInst *Old) { lldb_private::Log *log( lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_EXPRESSIONS)); - if (log) - log->Printf("MaybeHandleCallArguments(%s)", PrintValue(Old).c_str()); + LLDB_LOG(log, "MaybeHandleCallArguments({0})", PrintValue(Old)); for (unsigned op_index = 0, num_ops = Old->getNumArgOperands(); op_index < num_ops; ++op_index) - if (!MaybeHandleVariable(Old->getArgOperand( - op_index))) // conservatively believe that this is a store - { + // conservatively believe that this is a store + if (!MaybeHandleVariable(Old->getArgOperand(op_index))) { m_error_stream.Printf("Internal error [IRForTarget]: Couldn't rewrite " "one of the arguments of a function call.\n"); @@ -1493,9 +1350,8 @@ bool IRForTarget::HandleObjCClass(Value *classlist_reference) { lldb::addr_t class_ptr = m_decl_map->GetSymbolAddress(name_cstr, lldb::eSymbolTypeObjCClass); - if (log) - log->Printf("Found reference to Objective-C class %s (0x%llx)", - name_cstr.AsCString(), (unsigned long long)class_ptr); + LLDB_LOG(log, "Found reference to Objective-C class {0} ({1})", name, + (unsigned long long)class_ptr); if (class_ptr == LLDB_INVALID_ADDRESS) return false; @@ -1528,13 +1384,9 @@ bool IRForTarget::HandleObjCClass(Value *classlist_reference) { } bool IRForTarget::RemoveCXAAtExit(BasicBlock &basic_block) { - BasicBlock::iterator ii; - std::vector<CallInst *> calls_to_remove; - for (ii = basic_block.begin(); ii != basic_block.end(); ++ii) { - Instruction &inst = *ii; - + for (Instruction &inst : basic_block) { CallInst *call = dyn_cast<CallInst>(&inst); // MaybeHandleCallArguments handles error reporting; we are silent here @@ -1557,25 +1409,16 @@ bool IRForTarget::RemoveCXAAtExit(BasicBlock &basic_block) { calls_to_remove.push_back(call); } - for (std::vector<CallInst *>::iterator ci = calls_to_remove.begin(), - ce = calls_to_remove.end(); - ci != ce; ++ci) { - (*ci)->eraseFromParent(); - } + for (CallInst *ci : calls_to_remove) + ci->eraseFromParent(); return true; } bool IRForTarget::ResolveCalls(BasicBlock &basic_block) { - ///////////////////////////////////////////////////////////////////////// // Prepare the current basic block for execution in the remote process - // - - BasicBlock::iterator ii; - - for (ii = basic_block.begin(); ii != basic_block.end(); ++ii) { - Instruction &inst = *ii; + for (Instruction &inst : basic_block) { CallInst *call = dyn_cast<CallInst>(&inst); // MaybeHandleCallArguments handles error reporting; we are silent here @@ -1591,31 +1434,27 @@ bool IRForTarget::ResolveExternals(Function &llvm_function) { lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_EXPRESSIONS)); for (GlobalVariable &global_var : m_module->globals()) { - std::string global_name = global_var.getName().str(); + llvm::StringRef global_name = global_var.getName(); - if (log) - log->Printf("Examining %s, DeclForGlobalValue returns %p", - global_name.c_str(), - static_cast<void *>(DeclForGlobal(&global_var))); + LLDB_LOG(log, "Examining {0}, DeclForGlobalValue returns {1}", global_name, + static_cast<void *>(DeclForGlobal(&global_var))); - if (global_name.find("OBJC_IVAR") == 0) { + if (global_name.startswith("OBJC_IVAR")) { if (!HandleSymbol(&global_var)) { - m_error_stream.Printf("Error [IRForTarget]: Couldn't find Objective-C " - "indirect ivar symbol %s\n", - global_name.c_str()); + m_error_stream.Format("Error [IRForTarget]: Couldn't find Objective-C " + "indirect ivar symbol {0}\n", + global_name); return false; } - } else if (global_name.find("OBJC_CLASSLIST_REFERENCES_$") != - global_name.npos) { + } else if (global_name.contains("OBJC_CLASSLIST_REFERENCES_$")) { if (!HandleObjCClass(&global_var)) { m_error_stream.Printf("Error [IRForTarget]: Couldn't resolve the class " "for an Objective-C static method call\n"); return false; } - } else if (global_name.find("OBJC_CLASSLIST_SUP_REFS_$") != - global_name.npos) { + } else if (global_name.contains("OBJC_CLASSLIST_SUP_REFS_$")) { if (!HandleObjCClass(&global_var)) { m_error_stream.Printf("Error [IRForTarget]: Couldn't resolve the class " "for an Objective-C static method call\n"); @@ -1624,9 +1463,9 @@ bool IRForTarget::ResolveExternals(Function &llvm_function) { } } else if (DeclForGlobal(&global_var)) { if (!MaybeHandleVariable(&global_var)) { - m_error_stream.Printf("Internal error [IRForTarget]: Couldn't rewrite " - "external variable %s\n", - global_name.c_str()); + m_error_stream.Format("Internal error [IRForTarget]: Couldn't rewrite " + "external variable {0}\n", + global_name); return false; } @@ -1637,14 +1476,12 @@ bool IRForTarget::ResolveExternals(Function &llvm_function) { } static bool isGuardVariableRef(Value *V) { - Constant *Old = nullptr; + Constant *Old = dyn_cast<Constant>(V); - if (!(Old = dyn_cast<Constant>(V))) + if (!Old) return false; - ConstantExpr *CE = nullptr; - - if ((CE = dyn_cast<ConstantExpr>(V))) { + if (auto CE = dyn_cast<ConstantExpr>(V)) { if (CE->getOpcode() != Instruction::BitCast) return false; @@ -1653,12 +1490,8 @@ static bool isGuardVariableRef(Value *V) { GlobalVariable *GV = dyn_cast<GlobalVariable>(Old); - if (!GV || !GV->hasName() || - (!GV->getName().startswith("_ZGV") && // Itanium ABI guard variable - !GV->getName().endswith("@4IA"))) // Microsoft ABI guard variable - { + if (!GV || !GV->hasName() || !isGuardVariableSymbol(GV->getName())) return false; - } return true; } @@ -1674,20 +1507,12 @@ static void ExciseGuardStore(Instruction *guard_store) { } bool IRForTarget::RemoveGuards(BasicBlock &basic_block) { - /////////////////////////////////////////////////////// // Eliminate any reference to guard variables found. - // - - BasicBlock::iterator ii; - - typedef SmallVector<Instruction *, 2> InstrList; - typedef InstrList::iterator InstrIterator; InstrList guard_loads; InstrList guard_stores; - for (ii = basic_block.begin(); ii != basic_block.end(); ++ii) { - Instruction &inst = *ii; + for (Instruction &inst : basic_block) { if (LoadInst *load = dyn_cast<LoadInst>(&inst)) if (isGuardVariableRef(load->getPointerOperand())) @@ -1698,13 +1523,11 @@ bool IRForTarget::RemoveGuards(BasicBlock &basic_block) { guard_stores.push_back(&inst); } - InstrIterator iter; + for (Instruction *inst : guard_loads) + TurnGuardLoadIntoZero(inst); - for (iter = guard_loads.begin(); iter != guard_loads.end(); ++iter) - TurnGuardLoadIntoZero(*iter); - - for (iter = guard_stores.begin(); iter != guard_stores.end(); ++iter) - ExciseGuardStore(*iter); + for (Instruction *inst : guard_stores) + ExciseGuardStore(inst); return true; } @@ -1837,8 +1660,7 @@ bool IRForTarget::ReplaceVariables(Function &llvm_function) { m_decl_map->DoStructLayout(); - if (log) - log->Printf("Element arrangement:"); + LLDB_LOG(log, "Element arrangement:"); uint32_t num_elements; uint32_t element_index; @@ -1884,9 +1706,9 @@ bool IRForTarget::ReplaceVariables(Function &llvm_function) { } if (!iter->getName().equals("_cmd")) { - m_error_stream.Printf("Internal error [IRForTarget]: Wrapper takes '%s' " + m_error_stream.Format("Internal error [IRForTarget]: Wrapper takes '{0}' " "after 'self' argument (should take '_cmd')", - iter->getName().str().c_str()); + iter->getName()); return false; } @@ -1905,15 +1727,14 @@ bool IRForTarget::ReplaceVariables(Function &llvm_function) { } if (!argument->getName().equals("$__lldb_arg")) { - m_error_stream.Printf("Internal error [IRForTarget]: Wrapper takes an " - "argument named '%s' instead of the struct pointer", - argument->getName().str().c_str()); + m_error_stream.Format("Internal error [IRForTarget]: Wrapper takes an " + "argument named '{0}' instead of the struct pointer", + argument->getName()); return false; } - if (log) - log->Printf("Arg: \"%s\"", PrintValue(argument).c_str()); + LLDB_LOG(log, "Arg: \"{0}\"", PrintValue(argument)); BasicBlock &entry_block(llvm_function.getEntryBlock()); Instruction *FirstEntryInstruction(entry_block.getFirstNonPHIOrDbg()); @@ -1950,13 +1771,11 @@ bool IRForTarget::ReplaceVariables(Function &llvm_function) { return false; } - if (log) - log->Printf(" \"%s\" (\"%s\") placed at %" PRIu64, name.GetCString(), - decl->getNameAsString().c_str(), offset); + LLDB_LOG(log, " \"{0}\" (\"{1}\") placed at {2}", name, + decl->getNameAsString(), offset); if (value) { - if (log) - log->Printf(" Replacing [%s]", PrintValue(value).c_str()); + LLDB_LOG(log, " Replacing [{0}]", PrintValue(value)); FunctionValueCache body_result_maker( [this, name, offset_type, offset, argument, @@ -2005,9 +1824,8 @@ bool IRForTarget::ReplaceVariables(Function &llvm_function) { value->replaceAllUsesWith( body_result_maker.GetValue(instruction->getParent()->getParent())); } else { - if (log) - log->Printf("Unhandled non-constant type: \"%s\"", - PrintValue(value).c_str()); + LLDB_LOG(log, "Unhandled non-constant type: \"{0}\"", + PrintValue(value)); return false; } @@ -2016,35 +1834,12 @@ bool IRForTarget::ReplaceVariables(Function &llvm_function) { } } - if (log) - log->Printf("Total structure [align %" PRId64 ", size %" PRIu64 "]", - (int64_t)alignment, (uint64_t)size); + LLDB_LOG(log, "Total structure [align {0}, size {1}]", (int64_t)alignment, + (uint64_t)size); return true; } -llvm::Constant *IRForTarget::BuildRelocation(llvm::Type *type, - uint64_t offset) { - llvm::Constant *offset_int = ConstantInt::get(m_intptr_ty, offset); - - llvm::Constant *offset_array[1]; - - offset_array[0] = offset_int; - - llvm::ArrayRef<llvm::Constant *> offsets(offset_array, 1); - llvm::Type *char_type = llvm::Type::getInt8Ty(m_module->getContext()); - llvm::Type *char_pointer_type = char_type->getPointerTo(); - - llvm::Constant *reloc_placeholder_bitcast = - ConstantExpr::getBitCast(m_reloc_placeholder, char_pointer_type); - llvm::Constant *reloc_getelementptr = ConstantExpr::getGetElementPtr( - char_type, reloc_placeholder_bitcast, offsets); - llvm::Constant *reloc_bitcast = - ConstantExpr::getBitCast(reloc_getelementptr, type); - - return reloc_bitcast; -} - bool IRForTarget::runOnModule(Module &llvm_module) { lldb_private::Log *log( lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_EXPRESSIONS)); @@ -2062,7 +1857,7 @@ bool IRForTarget::runOnModule(Module &llvm_module) { oss.flush(); - log->Printf("Module as passed in to IRForTarget: \n\"%s\"", s.c_str()); + LLDB_LOG(log, "Module as passed in to IRForTarget: \n\"{0}\"", s); } Function *const main_function = @@ -2070,21 +1865,18 @@ bool IRForTarget::runOnModule(Module &llvm_module) { : m_module->getFunction(m_func_name.GetStringRef()); if (!m_func_name.IsEmpty() && !main_function) { - if (log) - log->Printf("Couldn't find \"%s()\" in the module", - m_func_name.AsCString()); + LLDB_LOG(log, "Couldn't find \"{0}()\" in the module", m_func_name); - m_error_stream.Printf("Internal error [IRForTarget]: Couldn't find wrapper " - "'%s' in the module", - m_func_name.AsCString()); + m_error_stream.Format("Internal error [IRForTarget]: Couldn't find wrapper " + "'{0}' in the module", + m_func_name); return false; } if (main_function) { if (!FixFunctionLinkage(*main_function)) { - if (log) - log->Printf("Couldn't fix the linkage for the function"); + LLDB_LOG(log, "Couldn't fix the linkage for the function"); return false; } @@ -2104,8 +1896,7 @@ bool IRForTarget::runOnModule(Module &llvm_module) { if (main_function) { if (!CreateResultVariable(*main_function)) { - if (log) - log->Printf("CreateResultVariable() failed"); + LLDB_LOG(log, "CreateResultVariable() failed"); // CreateResultVariable() reports its own errors, so we don't do so here @@ -2121,32 +1912,21 @@ bool IRForTarget::runOnModule(Module &llvm_module) { oss.flush(); - log->Printf("Module after creating the result variable: \n\"%s\"", - s.c_str()); + LLDB_LOG(log, "Module after creating the result variable: \n\"{0}\"", s); } - for (Module::iterator fi = m_module->begin(), fe = m_module->end(); fi != fe; - ++fi) { - llvm::Function *function = &*fi; - - if (function->begin() == function->end()) - continue; - - Function::iterator bbi; - - for (bbi = function->begin(); bbi != function->end(); ++bbi) { - if (!RemoveGuards(*bbi)) { - if (log) - log->Printf("RemoveGuards() failed"); + for (llvm::Function &function : *m_module) { + for (BasicBlock &bb : function) { + if (!RemoveGuards(bb)) { + LLDB_LOG(log, "RemoveGuards() failed"); // RemoveGuards() reports its own errors, so we don't do so here return false; } - if (!RewritePersistentAllocs(*bbi)) { - if (log) - log->Printf("RewritePersistentAllocs() failed"); + if (!RewritePersistentAllocs(bb)) { + LLDB_LOG(log, "RewritePersistentAllocs() failed"); // RewritePersistentAllocs() reports its own errors, so we don't do so // here @@ -2154,9 +1934,8 @@ bool IRForTarget::runOnModule(Module &llvm_module) { return false; } - if (!RemoveCXAAtExit(*bbi)) { - if (log) - log->Printf("RemoveCXAAtExit() failed"); + if (!RemoveCXAAtExit(bb)) { + LLDB_LOG(log, "RemoveCXAAtExit() failed"); // RemoveCXAAtExit() reports its own errors, so we don't do so here @@ -2170,24 +1949,17 @@ bool IRForTarget::runOnModule(Module &llvm_module) { // if (!RewriteObjCConstStrings()) { - if (log) - log->Printf("RewriteObjCConstStrings() failed"); + LLDB_LOG(log, "RewriteObjCConstStrings() failed"); // RewriteObjCConstStrings() reports its own errors, so we don't do so here return false; } - for (Module::iterator fi = m_module->begin(), fe = m_module->end(); fi != fe; - ++fi) { - llvm::Function *function = &*fi; - - for (llvm::Function::iterator bbi = function->begin(), - bbe = function->end(); - bbi != bbe; ++bbi) { - if (!RewriteObjCSelectors(*bbi)) { - if (log) - log->Printf("RewriteObjCSelectors() failed"); + for (llvm::Function &function : *m_module) { + for (llvm::BasicBlock &bb : function) { + if (!RewriteObjCSelectors(bb)) { + LLDB_LOG(log, "RewriteObjCSelectors() failed"); // RewriteObjCSelectors() reports its own errors, so we don't do so // here @@ -2195,9 +1967,8 @@ bool IRForTarget::runOnModule(Module &llvm_module) { return false; } - if (!RewriteObjCClassReferences(*bbi)) { - if (log) - log->Printf("RewriteObjCClassReferences() failed"); + if (!RewriteObjCClassReferences(bb)) { + LLDB_LOG(log, "RewriteObjCClassReferences() failed"); // RewriteObjCClasses() reports its own errors, so we don't do so here @@ -2206,16 +1977,10 @@ bool IRForTarget::runOnModule(Module &llvm_module) { } } - for (Module::iterator fi = m_module->begin(), fe = m_module->end(); fi != fe; - ++fi) { - llvm::Function *function = &*fi; - - for (llvm::Function::iterator bbi = function->begin(), - bbe = function->end(); - bbi != bbe; ++bbi) { - if (!ResolveCalls(*bbi)) { - if (log) - log->Printf("ResolveCalls() failed"); + for (llvm::Function &function : *m_module) { + for (BasicBlock &bb : function) { + if (!ResolveCalls(bb)) { + LLDB_LOG(log, "ResolveCalls() failed"); // ResolveCalls() reports its own errors, so we don't do so here @@ -2230,8 +1995,7 @@ bool IRForTarget::runOnModule(Module &llvm_module) { if (main_function) { if (!ResolveExternals(*main_function)) { - if (log) - log->Printf("ResolveExternals() failed"); + LLDB_LOG(log, "ResolveExternals() failed"); // ResolveExternals() reports its own errors, so we don't do so here @@ -2239,8 +2003,7 @@ bool IRForTarget::runOnModule(Module &llvm_module) { } if (!ReplaceVariables(*main_function)) { - if (log) - log->Printf("ReplaceVariables() failed"); + LLDB_LOG(log, "ReplaceVariables() failed"); // ReplaceVariables() reports its own errors, so we don't do so here @@ -2256,7 +2019,7 @@ bool IRForTarget::runOnModule(Module &llvm_module) { oss.flush(); - log->Printf("Module after preparing for execution: \n\"%s\"", s.c_str()); + LLDB_LOG(log, "Module after preparing for execution: \n\"{0}\"", s); } return true; diff --git a/source/Plugins/ExpressionParser/Clang/IRForTarget.h b/source/Plugins/ExpressionParser/Clang/IRForTarget.h index f87fd8ac32cb..893620f7f8e0 100644 --- a/source/Plugins/ExpressionParser/Clang/IRForTarget.h +++ b/source/Plugins/ExpressionParser/Clang/IRForTarget.h @@ -10,6 +10,7 @@ #ifndef liblldb_IRForTarget_h_ #define liblldb_IRForTarget_h_ +#include "lldb/Core/ClangForward.h" #include "lldb/Symbol/TaggedASTType.h" #include "lldb/Utility/ConstString.h" #include "lldb/Utility/Status.h" @@ -331,27 +332,6 @@ private: /// a call to a function pointer whose value is the address of the function /// in the target process. - /// Write an initializer to a memory array of assumed sufficient size. - /// - /// \param[in] data - /// A pointer to the data to write to. - /// - /// \param[in] initializer - /// The initializer itself. - /// - /// \return - /// True on success; false otherwise - bool MaterializeInitializer(uint8_t *data, llvm::Constant *initializer); - - /// Move an internal variable into the static allocation section. - /// - /// \param[in] global_variable - /// The variable. - /// - /// \return - /// True on success; false otherwise - bool MaterializeInternalVariable(llvm::GlobalVariable *global_variable); - /// Handle a single externally-defined variable /// /// \param[in] value @@ -539,20 +519,6 @@ private: FunctionValueCache &entry_instruction_finder, lldb_private::Stream &error_stream); - /// Construct a reference to m_reloc_placeholder with a given type and - /// offset. This typically happens after inserting data into - /// m_data_allocator. - /// - /// \param[in] type - /// The type of the value being loaded. - /// - /// \param[in] offset - /// The offset of the value from the base of m_data_allocator. - /// - /// \return - /// The Constant for the reference, usually a ConstantExpr. - llvm::Constant *BuildRelocation(llvm::Type *type, uint64_t offset); - /// Commit the allocation in m_data_allocator and use its final location to /// replace m_reloc_placeholder. /// diff --git a/source/Plugins/ExpressionParser/Clang/ModuleDependencyCollector.h b/source/Plugins/ExpressionParser/Clang/ModuleDependencyCollector.h index 0e959f86fd2a..7553860f2492 100644 --- a/source/Plugins/ExpressionParser/Clang/ModuleDependencyCollector.h +++ b/source/Plugins/ExpressionParser/Clang/ModuleDependencyCollector.h @@ -9,21 +9,23 @@ #ifndef liblldb_ModuleDependencyCollector_h_ #define liblldb_ModuleDependencyCollector_h_ -#include "lldb/Utility/FileCollector.h" #include "clang/Frontend/Utils.h" #include "llvm/ADT/StringRef.h" +#include "llvm/Support/FileCollector.h" namespace lldb_private { class ModuleDependencyCollectorAdaptor : public clang::ModuleDependencyCollector { public: - ModuleDependencyCollectorAdaptor(FileCollector &file_collector) + ModuleDependencyCollectorAdaptor( + std::shared_ptr<llvm::FileCollector> file_collector) : clang::ModuleDependencyCollector(""), m_file_collector(file_collector) { } void addFile(llvm::StringRef Filename, llvm::StringRef FileDst = {}) override { - m_file_collector.AddFile(Filename); + if (m_file_collector) + m_file_collector->addFile(Filename); } bool insertSeen(llvm::StringRef Filename) override { return false; } @@ -31,7 +33,7 @@ public: void writeFileMap() override {} private: - FileCollector &m_file_collector; + std::shared_ptr<llvm::FileCollector> m_file_collector; }; } // namespace lldb_private diff --git a/source/Plugins/Instruction/ARM/EmulateInstructionARM.cpp b/source/Plugins/Instruction/ARM/EmulateInstructionARM.cpp index 6323889c2e09..19a987b0f004 100644 --- a/source/Plugins/Instruction/ARM/EmulateInstructionARM.cpp +++ b/source/Plugins/Instruction/ARM/EmulateInstructionARM.cpp @@ -14507,6 +14507,7 @@ bool EmulateInstructionARM::CreateFunctionEntryUnwind(UnwindPlan &unwind_plan) { unwind_plan.SetSourceName("EmulateInstructionARM"); unwind_plan.SetSourcedFromCompiler(eLazyBoolNo); unwind_plan.SetUnwindPlanValidAtAllInstructions(eLazyBoolYes); + unwind_plan.SetUnwindPlanForSignalTrap(eLazyBoolNo); unwind_plan.SetReturnAddressRegister(dwarf_lr); return true; } diff --git a/source/Plugins/Instruction/ARM64/EmulateInstructionARM64.cpp b/source/Plugins/Instruction/ARM64/EmulateInstructionARM64.cpp index d7e8e0491342..3e06fca2504c 100644 --- a/source/Plugins/Instruction/ARM64/EmulateInstructionARM64.cpp +++ b/source/Plugins/Instruction/ARM64/EmulateInstructionARM64.cpp @@ -149,7 +149,8 @@ EmulateInstructionARM64::CreateInstance(const ArchSpec &arch, InstructionType inst_type) { if (EmulateInstructionARM64::SupportsEmulatingInstructionsOfTypeStatic( inst_type)) { - if (arch.GetTriple().getArch() == llvm::Triple::aarch64) { + if (arch.GetTriple().getArch() == llvm::Triple::aarch64 || + arch.GetTriple().getArch() == llvm::Triple::aarch64_32) { return new EmulateInstructionARM64(arch); } } @@ -479,6 +480,7 @@ bool EmulateInstructionARM64::CreateFunctionEntryUnwind( unwind_plan.SetSourceName("EmulateInstructionARM64"); unwind_plan.SetSourcedFromCompiler(eLazyBoolNo); unwind_plan.SetUnwindPlanValidAtAllInstructions(eLazyBoolYes); + unwind_plan.SetUnwindPlanForSignalTrap(eLazyBoolNo); unwind_plan.SetReturnAddressRegister(gpr_lr_arm64); return true; } diff --git a/source/Plugins/Instruction/MIPS/EmulateInstructionMIPS.cpp b/source/Plugins/Instruction/MIPS/EmulateInstructionMIPS.cpp index cbf3dda7896e..21b6296745bd 100644 --- a/source/Plugins/Instruction/MIPS/EmulateInstructionMIPS.cpp +++ b/source/Plugins/Instruction/MIPS/EmulateInstructionMIPS.cpp @@ -1150,6 +1150,7 @@ bool EmulateInstructionMIPS::CreateFunctionEntryUnwind( unwind_plan.SetSourceName("EmulateInstructionMIPS"); unwind_plan.SetSourcedFromCompiler(eLazyBoolNo); unwind_plan.SetUnwindPlanValidAtAllInstructions(eLazyBoolYes); + unwind_plan.SetUnwindPlanForSignalTrap(eLazyBoolNo); unwind_plan.SetReturnAddressRegister(dwarf_ra_mips); return true; diff --git a/source/Plugins/Instruction/MIPS64/EmulateInstructionMIPS64.cpp b/source/Plugins/Instruction/MIPS64/EmulateInstructionMIPS64.cpp index 69f0278d1437..5fabbeb756cc 100644 --- a/source/Plugins/Instruction/MIPS64/EmulateInstructionMIPS64.cpp +++ b/source/Plugins/Instruction/MIPS64/EmulateInstructionMIPS64.cpp @@ -1042,6 +1042,7 @@ bool EmulateInstructionMIPS64::CreateFunctionEntryUnwind( unwind_plan.SetSourceName("EmulateInstructionMIPS64"); unwind_plan.SetSourcedFromCompiler(eLazyBoolNo); unwind_plan.SetUnwindPlanValidAtAllInstructions(eLazyBoolYes); + unwind_plan.SetUnwindPlanForSignalTrap(eLazyBoolNo); unwind_plan.SetReturnAddressRegister(dwarf_ra_mips64); return true; diff --git a/source/Plugins/Instruction/PPC64/EmulateInstructionPPC64.cpp b/source/Plugins/Instruction/PPC64/EmulateInstructionPPC64.cpp index c77fa04fc7d7..4b8d8dd2228c 100644 --- a/source/Plugins/Instruction/PPC64/EmulateInstructionPPC64.cpp +++ b/source/Plugins/Instruction/PPC64/EmulateInstructionPPC64.cpp @@ -135,6 +135,7 @@ bool EmulateInstructionPPC64::CreateFunctionEntryUnwind( unwind_plan.SetSourceName("EmulateInstructionPPC64"); unwind_plan.SetSourcedFromCompiler(eLazyBoolNo); unwind_plan.SetUnwindPlanValidAtAllInstructions(eLazyBoolYes); + unwind_plan.SetUnwindPlanForSignalTrap(eLazyBoolNo); unwind_plan.SetReturnAddressRegister(gpr_lr_ppc64le); return true; } diff --git a/source/Plugins/InstrumentationRuntime/ASan/ASanRuntime.cpp b/source/Plugins/InstrumentationRuntime/ASan/ASanRuntime.cpp index c8ac04641e68..2e5dd5989e77 100644 --- a/source/Plugins/InstrumentationRuntime/ASan/ASanRuntime.cpp +++ b/source/Plugins/InstrumentationRuntime/ASan/ASanRuntime.cpp @@ -264,7 +264,7 @@ bool AddressSanitizerRuntime::NotifyBreakpointHit( *thread_sp, description, report)); StreamFileSP stream_sp( - process_sp->GetTarget().GetDebugger().GetOutputFile()); + process_sp->GetTarget().GetDebugger().GetOutputStreamSP()); if (stream_sp) { stream_sp->Printf("AddressSanitizer report breakpoint hit. Use 'thread " "info -s' to get extended information about the " diff --git a/source/Plugins/InstrumentationRuntime/TSan/TSanRuntime.cpp b/source/Plugins/InstrumentationRuntime/TSan/TSanRuntime.cpp index 89f2139db71b..45a3aeeb204e 100644 --- a/source/Plugins/InstrumentationRuntime/TSan/TSanRuntime.cpp +++ b/source/Plugins/InstrumentationRuntime/TSan/TSanRuntime.cpp @@ -863,13 +863,11 @@ bool ThreadSanitizerRuntime::NotifyBreakpointHit( CreateStopReasonWithInstrumentationData( *thread_sp, stop_reason_description, report)); - StreamFileSP stream_sp( - process_sp->GetTarget().GetDebugger().GetOutputFile()); - if (stream_sp) { - stream_sp->Printf("ThreadSanitizer report breakpoint hit. Use 'thread " - "info -s' to get extended information about the " - "report.\n"); - } + StreamFile &s = process_sp->GetTarget().GetDebugger().GetOutputStream(); + s.Printf("ThreadSanitizer report breakpoint hit. Use 'thread " + "info -s' to get extended information about the " + "report.\n"); + return true; // Return true to stop the target } else return false; // Let target run diff --git a/source/Plugins/InstrumentationRuntime/UBSan/UBSanRuntime.cpp b/source/Plugins/InstrumentationRuntime/UBSan/UBSanRuntime.cpp index 367098bb448e..50f1d48d03e0 100644 --- a/source/Plugins/InstrumentationRuntime/UBSan/UBSanRuntime.cpp +++ b/source/Plugins/InstrumentationRuntime/UBSan/UBSanRuntime.cpp @@ -124,7 +124,7 @@ StructuredData::ObjectSP UndefinedBehaviorSanitizerRuntime::RetrieveReportData( if (!frame_sp) return StructuredData::ObjectSP(); - StreamFileSP Stream(target.GetDebugger().GetOutputFile()); + StreamFileSP Stream = target.GetDebugger().GetOutputStreamSP(); EvaluateExpressionOptions options; options.SetUnwindOnError(true); diff --git a/source/Plugins/JITLoader/GDB/JITLoaderGDB.cpp b/source/Plugins/JITLoader/GDB/JITLoaderGDB.cpp index 140d09ed43cf..fff44123539f 100644 --- a/source/Plugins/JITLoader/GDB/JITLoaderGDB.cpp +++ b/source/Plugins/JITLoader/GDB/JITLoaderGDB.cpp @@ -6,9 +6,8 @@ // //===----------------------------------------------------------------------===// - -#include "llvm/Support/MathExtras.h" - +#include "JITLoaderGDB.h" +#include "Plugins/ObjectFile/Mach-O/ObjectFileMachO.h" #include "lldb/Breakpoint/Breakpoint.h" #include "lldb/Core/Module.h" #include "lldb/Core/ModuleSpec.h" @@ -26,8 +25,7 @@ #include "lldb/Utility/LLDBAssert.h" #include "lldb/Utility/Log.h" #include "lldb/Utility/StreamString.h" - -#include "JITLoaderGDB.h" +#include "llvm/Support/MathExtras.h" #include <memory> @@ -59,21 +57,33 @@ enum EnableJITLoaderGDB { eEnableJITLoaderGDBOff, }; -static constexpr OptionEnumValueElement g_enable_jit_loader_gdb_enumerators[] = { - {eEnableJITLoaderGDBDefault, "default", "Enable JIT compilation interface " - "for all platforms except macOS"}, - {eEnableJITLoaderGDBOn, "on", "Enable JIT compilation interface"}, - {eEnableJITLoaderGDBOff, "off", "Disable JIT compilation interface"} - }; +static constexpr OptionEnumValueElement g_enable_jit_loader_gdb_enumerators[] = + { + { + eEnableJITLoaderGDBDefault, + "default", + "Enable JIT compilation interface for all platforms except macOS", + }, + { + eEnableJITLoaderGDBOn, + "on", + "Enable JIT compilation interface", + }, + { + eEnableJITLoaderGDBOff, + "off", + "Disable JIT compilation interface", + }, +}; -static constexpr PropertyDefinition g_properties[] = { - {"enable", OptionValue::eTypeEnum, true, - eEnableJITLoaderGDBDefault, nullptr, - OptionEnumValues(g_enable_jit_loader_gdb_enumerators), - "Enable GDB's JIT compilation interface (default: enabled on " - "all platforms except macOS)"}}; +#define LLDB_PROPERTIES_jitloadergdb +#include "JITLoaderGDBProperties.inc" -enum { ePropertyEnable, ePropertyEnableJITBreakpoint }; +enum { +#define LLDB_PROPERTIES_jitloadergdb +#include "JITLoaderGDBPropertiesEnum.inc" + ePropertyEnableJITBreakpoint +}; class PluginProperties : public Properties { public: @@ -83,13 +93,13 @@ public: PluginProperties() { m_collection_sp = std::make_shared<OptionValueProperties>(GetSettingName()); - m_collection_sp->Initialize(g_properties); + m_collection_sp->Initialize(g_jitloadergdb_properties); } EnableJITLoaderGDB GetEnable() const { return (EnableJITLoaderGDB)m_collection_sp->GetPropertyAtIndexAsEnumeration( nullptr, ePropertyEnable, - g_properties[ePropertyEnable].default_uint_value); + g_jitloadergdb_properties[ePropertyEnable].default_uint_value); } }; @@ -177,8 +187,8 @@ void JITLoaderGDB::SetJITBreakpoint(lldb_private::ModuleList &module_list) { return; Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_JIT_LOADER)); - if (log) - log->Printf("JITLoaderGDB::%s looking for JIT register hook", __FUNCTION__); + LLDB_LOGF(log, "JITLoaderGDB::%s looking for JIT register hook", + __FUNCTION__); addr_t jit_addr = GetSymbolAddress( module_list, ConstString("__jit_debug_register_code"), eSymbolTypeAny); @@ -188,14 +198,12 @@ void JITLoaderGDB::SetJITBreakpoint(lldb_private::ModuleList &module_list) { m_jit_descriptor_addr = GetSymbolAddress( module_list, ConstString("__jit_debug_descriptor"), eSymbolTypeData); if (m_jit_descriptor_addr == LLDB_INVALID_ADDRESS) { - if (log) - log->Printf("JITLoaderGDB::%s failed to find JIT descriptor address", - __FUNCTION__); + LLDB_LOGF(log, "JITLoaderGDB::%s failed to find JIT descriptor address", + __FUNCTION__); return; } - if (log) - log->Printf("JITLoaderGDB::%s setting JIT breakpoint", __FUNCTION__); + LLDB_LOGF(log, "JITLoaderGDB::%s setting JIT breakpoint", __FUNCTION__); Breakpoint *bp = m_process->GetTarget().CreateBreakpoint(jit_addr, true, false).get(); @@ -211,8 +219,7 @@ bool JITLoaderGDB::JITDebugBreakpointHit(void *baton, user_id_t break_id, user_id_t break_loc_id) { Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_JIT_LOADER)); - if (log) - log->Printf("JITLoaderGDB::%s hit JIT breakpoint", __FUNCTION__); + LLDB_LOGF(log, "JITLoaderGDB::%s hit JIT breakpoint", __FUNCTION__); JITLoaderGDB *instance = static_cast<JITLoaderGDB *>(baton); return instance->ReadJITDescriptor(false); } @@ -285,9 +292,8 @@ bool JITLoaderGDB::ReadJITDescriptorImpl(bool all_entries) { size_t bytes_read = m_process->DoReadMemory(m_jit_descriptor_addr, &jit_desc, jit_desc_size, error); if (bytes_read != jit_desc_size || !error.Success()) { - if (log) - log->Printf("JITLoaderGDB::%s failed to read JIT descriptor", - __FUNCTION__); + LLDB_LOGF(log, "JITLoaderGDB::%s failed to read JIT descriptor", + __FUNCTION__); return false; } @@ -301,9 +307,8 @@ bool JITLoaderGDB::ReadJITDescriptorImpl(bool all_entries) { while (jit_relevant_entry != 0) { jit_code_entry<ptr_t> jit_entry; if (!ReadJITEntry(jit_relevant_entry, m_process, &jit_entry)) { - if (log) - log->Printf("JITLoaderGDB::%s failed to read JIT entry at 0x%" PRIx64, - __FUNCTION__, jit_relevant_entry); + LLDB_LOGF(log, "JITLoaderGDB::%s failed to read JIT entry at 0x%" PRIx64, + __FUNCTION__, jit_relevant_entry); return false; } @@ -312,10 +317,10 @@ bool JITLoaderGDB::ReadJITDescriptorImpl(bool all_entries) { ModuleSP module_sp; if (jit_action == JIT_REGISTER_FN) { - if (log) - log->Printf("JITLoaderGDB::%s registering JIT entry at 0x%" PRIx64 - " (%" PRIu64 " bytes)", - __FUNCTION__, symbolfile_addr, (uint64_t)symbolfile_size); + LLDB_LOGF(log, + "JITLoaderGDB::%s registering JIT entry at 0x%" PRIx64 + " (%" PRIu64 " bytes)", + __FUNCTION__, symbolfile_addr, (uint64_t)symbolfile_size); char jit_name[64]; snprintf(jit_name, 64, "JIT(0x%" PRIx64 ")", symbolfile_addr); @@ -331,20 +336,16 @@ bool JITLoaderGDB::ReadJITDescriptorImpl(bool all_entries) { module_sp->GetObjectFile()->GetSymtab(); m_jit_objects.insert(std::make_pair(symbolfile_addr, module_sp)); - if (module_sp->GetObjectFile()->GetPluginName() == - ConstString("mach-o")) { - ObjectFile *image_object_file = module_sp->GetObjectFile(); - if (image_object_file) { - const SectionList *section_list = - image_object_file->GetSectionList(); - if (section_list) { - uint64_t vmaddrheuristic = 0; - uint64_t lower = (uint64_t)-1; - uint64_t upper = 0; - updateSectionLoadAddress(*section_list, target, symbolfile_addr, - symbolfile_size, vmaddrheuristic, lower, - upper); - } + if (auto image_object_file = + llvm::dyn_cast<ObjectFileMachO>(module_sp->GetObjectFile())) { + const SectionList *section_list = image_object_file->GetSectionList(); + if (section_list) { + uint64_t vmaddrheuristic = 0; + uint64_t lower = (uint64_t)-1; + uint64_t upper = 0; + updateSectionLoadAddress(*section_list, target, symbolfile_addr, + symbolfile_size, vmaddrheuristic, lower, + upper); } } else { bool changed = false; @@ -357,15 +358,14 @@ bool JITLoaderGDB::ReadJITDescriptorImpl(bool all_entries) { module_list.Append(module_sp); target.ModulesDidLoad(module_list); } else { - if (log) - log->Printf("JITLoaderGDB::%s failed to load module for " - "JIT entry at 0x%" PRIx64, - __FUNCTION__, symbolfile_addr); + LLDB_LOGF(log, + "JITLoaderGDB::%s failed to load module for " + "JIT entry at 0x%" PRIx64, + __FUNCTION__, symbolfile_addr); } } else if (jit_action == JIT_UNREGISTER_FN) { - if (log) - log->Printf("JITLoaderGDB::%s unregistering JIT entry at 0x%" PRIx64, - __FUNCTION__, symbolfile_addr); + LLDB_LOGF(log, "JITLoaderGDB::%s unregistering JIT entry at 0x%" PRIx64, + __FUNCTION__, symbolfile_addr); JITObjectMap::iterator it = m_jit_objects.find(symbolfile_addr); if (it != m_jit_objects.end()) { @@ -458,8 +458,8 @@ addr_t JITLoaderGDB::GetSymbolAddress(ModuleList &module_list, SymbolContextList target_symbols; Target &target = m_process->GetTarget(); - if (!module_list.FindSymbolsWithNameAndType(name, symbol_type, - target_symbols)) + module_list.FindSymbolsWithNameAndType(name, symbol_type, target_symbols); + if (target_symbols.IsEmpty()) return LLDB_INVALID_ADDRESS; SymbolContext sym_ctx; diff --git a/source/Plugins/JITLoader/GDB/JITLoaderGDBProperties.td b/source/Plugins/JITLoader/GDB/JITLoaderGDBProperties.td new file mode 100644 index 000000000000..0493838bc85d --- /dev/null +++ b/source/Plugins/JITLoader/GDB/JITLoaderGDBProperties.td @@ -0,0 +1,9 @@ +include "../../../../include/lldb/Core/PropertiesBase.td" + +let Definition = "jitloadergdb" in { + def Enable: Property<"enable", "Enum">, + Global, + DefaultEnumValue<"eEnableJITLoaderGDBDefault">, + EnumValues<"OptionEnumValues(g_enable_jit_loader_gdb_enumerators)">, + Desc<"Enable GDB's JIT compilation interface (default: enabled on all platforms except macOS)">; +} diff --git a/source/Plugins/Language/CPlusPlus/BlockPointer.cpp b/source/Plugins/Language/CPlusPlus/BlockPointer.cpp index 87b5b5947f35..5cfd978774fd 100644 --- a/source/Plugins/Language/CPlusPlus/BlockPointer.cpp +++ b/source/Plugins/Language/CPlusPlus/BlockPointer.cpp @@ -17,6 +17,7 @@ #include "lldb/Target/Target.h" #include "lldb/Utility/LLDBAssert.h" +#include "lldb/Utility/Log.h" using namespace lldb; using namespace lldb_private; @@ -39,16 +40,17 @@ public: return; } - Status err; - TypeSystem *type_system = target_sp->GetScratchTypeSystemForLanguage( - &err, lldb::eLanguageTypeC_plus_plus); - - if (!err.Success() || !type_system) { + auto type_system_or_err = target_sp->GetScratchTypeSystemForLanguage( + lldb::eLanguageTypeC_plus_plus); + if (auto err = type_system_or_err.takeError()) { + LLDB_LOG_ERROR( + lldb_private::GetLogIfAnyCategoriesSet(LIBLLDB_LOG_DATAFORMATTERS), + std::move(err), "Failed to get scratch ClangASTContext"); return; } ClangASTContext *clang_ast_context = - llvm::dyn_cast<ClangASTContext>(type_system); + llvm::dyn_cast<ClangASTContext>(&type_system_or_err.get()); if (!clang_ast_context) { return; diff --git a/source/Plugins/Language/CPlusPlus/CPlusPlusLanguage.cpp b/source/Plugins/Language/CPlusPlus/CPlusPlusLanguage.cpp index 44b9e5e24ccd..489fa7d0ad91 100644 --- a/source/Plugins/Language/CPlusPlus/CPlusPlusLanguage.cpp +++ b/source/Plugins/Language/CPlusPlus/CPlusPlusLanguage.cpp @@ -486,8 +486,11 @@ static void LoadLibCxxFormatters(lldb::TypeCategoryImplSP cpp_category_sp) { cpp_category_sp, lldb_private::formatters::LibcxxStdListSyntheticFrontEndCreator, "libc++ std::list synthetic children", - ConstString("^std::__[[:alnum:]]+::list<.+>(( )?&)?$"), stl_deref_flags, - true); + // A POSIX variant of: "^std::__(?!cxx11:)[[:alnum:]]+::list<.+>(( )?&)?$" + // so that it does not clash with: "^std::(__cxx11::)?list<.+>(( )?&)?$" + ConstString("^std::__([A-Zabd-z0-9]|cx?[A-Za-wyz0-9]|cxx1?[A-Za-z02-9]|" + "cxx11[[:alnum:]])[[:alnum:]]*::list<.+>(( )?&)?$"), + stl_deref_flags, true); AddCXXSynthetic( cpp_category_sp, lldb_private::formatters::LibcxxStdMapSyntheticFrontEndCreator, @@ -547,8 +550,8 @@ static void LoadLibCxxFormatters(lldb::TypeCategoryImplSP cpp_category_sp) { ConstString("^std::__[[:alnum:]]+::atomic<.+>$"), stl_synth_flags, true); cpp_category_sp->GetRegexTypeSyntheticsContainer()->Add( - RegularExpressionSP(new RegularExpression( - llvm::StringRef("^(std::__[[:alnum:]]+::)deque<.+>(( )?&)?$"))), + RegularExpression( + llvm::StringRef("^(std::__[[:alnum:]]+::)deque<.+>(( )?&)?$")), SyntheticChildrenSP(new ScriptedSyntheticChildren( stl_synth_flags, "lldb.formatters.cpp.libcxx.stddeque_SynthProvider"))); @@ -566,12 +569,6 @@ static void LoadLibCxxFormatters(lldb::TypeCategoryImplSP cpp_category_sp) { ConstString("^(std::__[[:alnum:]]+::)weak_ptr<.+>(( )?&)?$"), stl_synth_flags, true); - AddCXXSummary( - cpp_category_sp, lldb_private::formatters::LibcxxFunctionSummaryProvider, - "libc++ std::function summary provider", - ConstString("^std::__[[:alnum:]]+::function<.+>$"), stl_summary_flags, - true); - stl_summary_flags.SetDontShowChildren(false); stl_summary_flags.SetSkipPointers(false); AddCXXSummary(cpp_category_sp, @@ -589,11 +586,14 @@ static void LoadLibCxxFormatters(lldb::TypeCategoryImplSP cpp_category_sp) { "libc++ std::list summary provider", ConstString("^std::__[[:alnum:]]+::forward_list<.+>(( )?&)?$"), stl_summary_flags, true); - AddCXXSummary(cpp_category_sp, - lldb_private::formatters::LibcxxContainerSummaryProvider, - "libc++ std::list summary provider", - ConstString("^std::__[[:alnum:]]+::list<.+>(( )?&)?$"), - stl_summary_flags, true); + AddCXXSummary( + cpp_category_sp, lldb_private::formatters::LibcxxContainerSummaryProvider, + "libc++ std::list summary provider", + // A POSIX variant of: "^std::__(?!cxx11:)[[:alnum:]]+::list<.+>(( )?&)?$" + // so that it does not clash with: "^std::(__cxx11::)?list<.+>(( )?&)?$" + ConstString("^std::__([A-Zabd-z0-9]|cx?[A-Za-wyz0-9]|cxx1?[A-Za-z02-9]|" + "cxx11[[:alnum:]])[[:alnum:]]*::list<.+>(( )?&)?$"), + stl_summary_flags, true); AddCXXSummary(cpp_category_sp, lldb_private::formatters::LibcxxContainerSummaryProvider, "libc++ std::map summary provider", @@ -750,38 +750,32 @@ static void LoadLibStdcppFormatters(lldb::TypeCategoryImplSP cpp_category_sp) { false); cpp_category_sp->GetRegexTypeSyntheticsContainer()->Add( - RegularExpressionSP( - new RegularExpression(llvm::StringRef("^std::vector<.+>(( )?&)?$"))), + RegularExpression(llvm::StringRef("^std::vector<.+>(( )?&)?$")), SyntheticChildrenSP(new ScriptedSyntheticChildren( stl_synth_flags, "lldb.formatters.cpp.gnu_libstdcpp.StdVectorSynthProvider"))); cpp_category_sp->GetRegexTypeSyntheticsContainer()->Add( - RegularExpressionSP( - new RegularExpression(llvm::StringRef("^std::map<.+> >(( )?&)?$"))), + RegularExpression(llvm::StringRef("^std::map<.+> >(( )?&)?$")), SyntheticChildrenSP(new ScriptedSyntheticChildren( stl_synth_flags, "lldb.formatters.cpp.gnu_libstdcpp.StdMapSynthProvider"))); cpp_category_sp->GetRegexTypeSyntheticsContainer()->Add( - RegularExpressionSP(new RegularExpression( - llvm::StringRef("^std::(__cxx11::)?list<.+>(( )?&)?$"))), + RegularExpression(llvm::StringRef("^std::(__cxx11::)?list<.+>(( )?&)?$")), SyntheticChildrenSP(new ScriptedSyntheticChildren( stl_synth_flags, "lldb.formatters.cpp.gnu_libstdcpp.StdListSynthProvider"))); stl_summary_flags.SetDontShowChildren(false); stl_summary_flags.SetSkipPointers(true); cpp_category_sp->GetRegexTypeSummariesContainer()->Add( - RegularExpressionSP( - new RegularExpression(llvm::StringRef("^std::vector<.+>(( )?&)?$"))), + RegularExpression(llvm::StringRef("^std::vector<.+>(( )?&)?$")), TypeSummaryImplSP( new StringSummaryFormat(stl_summary_flags, "size=${svar%#}"))); cpp_category_sp->GetRegexTypeSummariesContainer()->Add( - RegularExpressionSP( - new RegularExpression(llvm::StringRef("^std::map<.+> >(( )?&)?$"))), + RegularExpression(llvm::StringRef("^std::map<.+> >(( )?&)?$")), TypeSummaryImplSP( new StringSummaryFormat(stl_summary_flags, "size=${svar%#}"))); cpp_category_sp->GetRegexTypeSummariesContainer()->Add( - RegularExpressionSP(new RegularExpression( - llvm::StringRef("^std::(__cxx11::)?list<.+>(( )?&)?$"))), + RegularExpression(llvm::StringRef("^std::(__cxx11::)?list<.+>(( )?&)?$")), TypeSummaryImplSP( new StringSummaryFormat(stl_summary_flags, "size=${svar%#}"))); @@ -860,6 +854,14 @@ static void LoadSystemFormatters(lldb::TypeCategoryImplSP cpp_category_sp) { // FIXME because of a bug in the FormattersContainer we need to add a summary // for both X* and const X* (<rdar://problem/12717717>) AddCXXSummary( + cpp_category_sp, lldb_private::formatters::Char8StringSummaryProvider, + "char8_t * summary provider", ConstString("char8_t *"), string_flags); + AddCXXSummary(cpp_category_sp, + lldb_private::formatters::Char8StringSummaryProvider, + "char8_t [] summary provider", + ConstString("char8_t \\[[0-9]+\\]"), string_array_flags, true); + + AddCXXSummary( cpp_category_sp, lldb_private::formatters::Char16StringSummaryProvider, "char16_t * summary provider", ConstString("char16_t *"), string_flags); AddCXXSummary(cpp_category_sp, @@ -896,6 +898,9 @@ static void LoadSystemFormatters(lldb::TypeCategoryImplSP cpp_category_sp) { .SetHideItemNames(true) .SetShowMembersOneLiner(false); + AddCXXSummary(cpp_category_sp, lldb_private::formatters::Char8SummaryProvider, + "char8_t summary provider", ConstString("char8_t"), + widechar_flags); AddCXXSummary( cpp_category_sp, lldb_private::formatters::Char16SummaryProvider, "char16_t summary provider", ConstString("char16_t"), widechar_flags); diff --git a/source/Plugins/Language/CPlusPlus/CxxStringTypes.cpp b/source/Plugins/Language/CPlusPlus/CxxStringTypes.cpp index 959079070acc..3ea7589d8e4a 100644 --- a/source/Plugins/Language/CPlusPlus/CxxStringTypes.cpp +++ b/source/Plugins/Language/CPlusPlus/CxxStringTypes.cpp @@ -32,6 +32,31 @@ using namespace lldb; using namespace lldb_private; using namespace lldb_private::formatters; +bool lldb_private::formatters::Char8StringSummaryProvider( + ValueObject &valobj, Stream &stream, const TypeSummaryOptions &) { + ProcessSP process_sp = valobj.GetProcessSP(); + if (!process_sp) + return false; + + lldb::addr_t valobj_addr = GetArrayAddressOrPointerValue(valobj); + if (valobj_addr == 0 || valobj_addr == LLDB_INVALID_ADDRESS) + return false; + + StringPrinter::ReadStringAndDumpToStreamOptions options(valobj); + options.SetLocation(valobj_addr); + options.SetProcessSP(process_sp); + options.SetStream(&stream); + options.SetPrefixToken("u8"); + + if (!StringPrinter::ReadStringAndDumpToStream< + StringPrinter::StringElementType::UTF8>(options)) { + stream.Printf("Summary Unavailable"); + return true; + } + + return true; +} + bool lldb_private::formatters::Char16StringSummaryProvider( ValueObject &valobj, Stream &stream, const TypeSummaryOptions &) { ProcessSP process_sp = valobj.GetProcessSP(); @@ -128,6 +153,32 @@ bool lldb_private::formatters::WCharStringSummaryProvider( return true; } +bool lldb_private::formatters::Char8SummaryProvider( + ValueObject &valobj, Stream &stream, const TypeSummaryOptions &) { + DataExtractor data; + Status error; + valobj.GetData(data, error); + + if (error.Fail()) + return false; + + std::string value; + valobj.GetValueAsCString(lldb::eFormatUnicode8, value); + if (!value.empty()) + stream.Printf("%s ", value.c_str()); + + StringPrinter::ReadBufferAndDumpToStreamOptions options(valobj); + options.SetData(data); + options.SetStream(&stream); + options.SetPrefixToken("u8"); + options.SetQuote('\''); + options.SetSourceSize(1); + options.SetBinaryZeroIsTerminator(false); + + return StringPrinter::ReadBufferAndDumpToStream< + StringPrinter::StringElementType::UTF8>(options); +} + bool lldb_private::formatters::Char16SummaryProvider( ValueObject &valobj, Stream &stream, const TypeSummaryOptions &) { DataExtractor data; diff --git a/source/Plugins/Language/CPlusPlus/CxxStringTypes.h b/source/Plugins/Language/CPlusPlus/CxxStringTypes.h index 92bef2382eac..35498b3b568f 100644 --- a/source/Plugins/Language/CPlusPlus/CxxStringTypes.h +++ b/source/Plugins/Language/CPlusPlus/CxxStringTypes.h @@ -16,6 +16,9 @@ namespace lldb_private { namespace formatters { +bool Char8StringSummaryProvider(ValueObject &valobj, Stream &stream, + const TypeSummaryOptions &options); // char8_t* + bool Char16StringSummaryProvider( ValueObject &valobj, Stream &stream, const TypeSummaryOptions &options); // char16_t* and unichar* @@ -27,6 +30,9 @@ bool Char32StringSummaryProvider( bool WCharStringSummaryProvider(ValueObject &valobj, Stream &stream, const TypeSummaryOptions &options); // wchar_t* +bool Char8SummaryProvider(ValueObject &valobj, Stream &stream, + const TypeSummaryOptions &options); // char8_t + bool Char16SummaryProvider( ValueObject &valobj, Stream &stream, const TypeSummaryOptions &options); // char16_t and unichar diff --git a/source/Plugins/Language/CPlusPlus/LibCxxBitset.cpp b/source/Plugins/Language/CPlusPlus/LibCxxBitset.cpp index 815dafb6c724..78c453cd1b3c 100644 --- a/source/Plugins/Language/CPlusPlus/LibCxxBitset.cpp +++ b/source/Plugins/Language/CPlusPlus/LibCxxBitset.cpp @@ -30,8 +30,15 @@ public: ValueObjectSP GetChildAtIndex(size_t idx) override; private: + // The lifetime of a ValueObject and all its derivative ValueObjects + // (children, clones, etc.) is managed by a ClusterManager. These + // objects are only destroyed when every shared pointer to any of them + // is destroyed, so we must not store a shared pointer to any ValueObject + // derived from our backend ValueObject (since we're in the same cluster). + // Value objects created from raw data (i.e. in a different cluster) must + // be referenced via shared pointer to keep them alive, however. std::vector<ValueObjectSP> m_elements; - ValueObjectSP m_first; + ValueObject* m_first = nullptr; CompilerType m_bool_type; ByteOrder m_byte_order = eByteOrderInvalid; uint8_t m_byte_size = 0; @@ -50,7 +57,7 @@ BitsetFrontEnd::BitsetFrontEnd(ValueObject &valobj) bool BitsetFrontEnd::Update() { m_elements.clear(); - m_first.reset(); + m_first = nullptr; TargetSP target_sp = m_backend.GetTargetSP(); if (!target_sp) @@ -63,7 +70,7 @@ bool BitsetFrontEnd::Update() { m_elements.assign(size, ValueObjectSP()); - m_first = m_backend.GetChildMemberWithName(ConstString("__first_"), true); + m_first = m_backend.GetChildMemberWithName(ConstString("__first_"), true).get(); return false; } @@ -86,7 +93,7 @@ ValueObjectSP BitsetFrontEnd::GetChildAtIndex(size_t idx) { chunk = m_first->GetChildAtIndex(idx / *bit_size, true); } else { type = m_first->GetCompilerType(); - chunk = m_first; + chunk = m_first->GetSP(); } if (!type || !chunk) return {}; diff --git a/source/Plugins/Language/CPlusPlus/LibCxxOptional.cpp b/source/Plugins/Language/CPlusPlus/LibCxxOptional.cpp index 116021588848..b1ad171d0b0c 100644 --- a/source/Plugins/Language/CPlusPlus/LibCxxOptional.cpp +++ b/source/Plugins/Language/CPlusPlus/LibCxxOptional.cpp @@ -31,7 +31,6 @@ public: private: size_t m_size = 0; - ValueObjectSP m_base_sp; }; } // namespace diff --git a/source/Plugins/Language/CPlusPlus/LibCxxQueue.cpp b/source/Plugins/Language/CPlusPlus/LibCxxQueue.cpp index 4b72089c6ba2..2f06d684f953 100644 --- a/source/Plugins/Language/CPlusPlus/LibCxxQueue.cpp +++ b/source/Plugins/Language/CPlusPlus/LibCxxQueue.cpp @@ -38,16 +38,21 @@ public: } private: - ValueObjectSP m_container_sp; + // The lifetime of a ValueObject and all its derivative ValueObjects + // (children, clones, etc.) is managed by a ClusterManager. These + // objects are only destroyed when every shared pointer to any of them + // is destroyed, so we must not store a shared pointer to any ValueObject + // derived from our backend ValueObject (since we're in the same cluster). + ValueObject* m_container_sp = nullptr; }; } // namespace bool QueueFrontEnd::Update() { - m_container_sp.reset(); + m_container_sp = nullptr; ValueObjectSP c_sp = m_backend.GetChildMemberWithName(ConstString("c"), true); if (!c_sp) return false; - m_container_sp = c_sp->GetSyntheticValue(); + m_container_sp = c_sp->GetSyntheticValue().get(); return false; } diff --git a/source/Plugins/Language/CPlusPlus/LibCxxTuple.cpp b/source/Plugins/Language/CPlusPlus/LibCxxTuple.cpp index 8da7460f2275..45294e25f0f5 100644 --- a/source/Plugins/Language/CPlusPlus/LibCxxTuple.cpp +++ b/source/Plugins/Language/CPlusPlus/LibCxxTuple.cpp @@ -30,47 +30,58 @@ public: ValueObjectSP GetChildAtIndex(size_t idx) override; private: - std::vector<ValueObjectSP> m_elements; - ValueObjectSP m_base_sp; + // The lifetime of a ValueObject and all its derivative ValueObjects + // (children, clones, etc.) is managed by a ClusterManager. These + // objects are only destroyed when every shared pointer to any of them + // is destroyed, so we must not store a shared pointer to any ValueObject + // derived from our backend ValueObject (since we're in the same cluster). + std::vector<ValueObject*> m_elements; + ValueObject* m_base = nullptr; }; } bool TupleFrontEnd::Update() { m_elements.clear(); - m_base_sp = m_backend.GetChildMemberWithName(ConstString("__base_"), true); - if (! m_base_sp) { + m_base = nullptr; + + ValueObjectSP base_sp; + base_sp = m_backend.GetChildMemberWithName(ConstString("__base_"), true); + if (!base_sp) { // Pre r304382 name of the base element. - m_base_sp = m_backend.GetChildMemberWithName(ConstString("base_"), true); + base_sp = m_backend.GetChildMemberWithName(ConstString("base_"), true); } - if (! m_base_sp) + if (!base_sp) return false; - m_elements.assign(m_base_sp->GetCompilerType().GetNumDirectBaseClasses(), - ValueObjectSP()); + m_base = base_sp.get(); + m_elements.assign(base_sp->GetCompilerType().GetNumDirectBaseClasses(), + nullptr); return false; } ValueObjectSP TupleFrontEnd::GetChildAtIndex(size_t idx) { if (idx >= m_elements.size()) return ValueObjectSP(); - if (!m_base_sp) + if (!m_base) return ValueObjectSP(); if (m_elements[idx]) - return m_elements[idx]; + return m_elements[idx]->GetSP(); CompilerType holder_type = - m_base_sp->GetCompilerType().GetDirectBaseClassAtIndex(idx, nullptr); + m_base->GetCompilerType().GetDirectBaseClassAtIndex(idx, nullptr); if (!holder_type) return ValueObjectSP(); - ValueObjectSP holder_sp = m_base_sp->GetChildAtIndex(idx, true); + ValueObjectSP holder_sp = m_base->GetChildAtIndex(idx, true); if (!holder_sp) return ValueObjectSP(); ValueObjectSP elem_sp = holder_sp->GetChildAtIndex(0, true); if (elem_sp) m_elements[idx] = - elem_sp->Clone(ConstString(llvm::formatv("[{0}]", idx).str())); + elem_sp->Clone(ConstString(llvm::formatv("[{0}]", idx).str())).get(); - return m_elements[idx]; + if (m_elements[idx]) + return m_elements[idx]->GetSP(); + return ValueObjectSP(); } SyntheticChildrenFrontEnd * diff --git a/source/Plugins/Language/CPlusPlus/LibCxxVariant.cpp b/source/Plugins/Language/CPlusPlus/LibCxxVariant.cpp index 491cf048e459..62945bd3ce80 100644 --- a/source/Plugins/Language/CPlusPlus/LibCxxVariant.cpp +++ b/source/Plugins/Language/CPlusPlus/LibCxxVariant.cpp @@ -184,7 +184,6 @@ public: private: size_t m_size = 0; - ValueObjectSP m_base_sp; }; } // namespace diff --git a/source/Plugins/Language/CPlusPlus/LibStdcppTuple.cpp b/source/Plugins/Language/CPlusPlus/LibStdcppTuple.cpp index 66624e5beb6d..0ac7b8f8e02b 100644 --- a/source/Plugins/Language/CPlusPlus/LibStdcppTuple.cpp +++ b/source/Plugins/Language/CPlusPlus/LibStdcppTuple.cpp @@ -37,7 +37,12 @@ public: size_t GetIndexOfChildWithName(ConstString name) override; private: - std::vector<ValueObjectSP> m_members; + // The lifetime of a ValueObject and all its derivative ValueObjects + // (children, clones, etc.) is managed by a ClusterManager. These + // objects are only destroyed when every shared pointer to any of them + // is destroyed, so we must not store a shared pointer to any ValueObject + // derived from our backend ValueObject (since we're in the same cluster). + std::vector<ValueObject*> m_members; }; } // end of anonymous namespace @@ -72,7 +77,7 @@ bool LibStdcppTupleSyntheticFrontEnd::Update() { if (value_sp) { StreamString name; name.Printf("[%zd]", m_members.size()); - m_members.push_back(value_sp->Clone(ConstString(name.GetString()))); + m_members.push_back(value_sp->Clone(ConstString(name.GetString())).get()); } } } @@ -85,8 +90,8 @@ bool LibStdcppTupleSyntheticFrontEnd::MightHaveChildren() { return true; } lldb::ValueObjectSP LibStdcppTupleSyntheticFrontEnd::GetChildAtIndex(size_t idx) { - if (idx < m_members.size()) - return m_members[idx]; + if (idx < m_members.size() && m_members[idx]) + return m_members[idx]->GetSP(); return lldb::ValueObjectSP(); } diff --git a/source/Plugins/Language/CPlusPlus/LibStdcppUniquePointer.cpp b/source/Plugins/Language/CPlusPlus/LibStdcppUniquePointer.cpp index 3860f960cb3d..cceb511cdc46 100644 --- a/source/Plugins/Language/CPlusPlus/LibStdcppUniquePointer.cpp +++ b/source/Plugins/Language/CPlusPlus/LibStdcppUniquePointer.cpp @@ -39,9 +39,14 @@ public: bool GetSummary(Stream &stream, const TypeSummaryOptions &options); private: - ValueObjectSP m_ptr_obj; - ValueObjectSP m_obj_obj; - ValueObjectSP m_del_obj; + // The lifetime of a ValueObject and all its derivative ValueObjects + // (children, clones, etc.) is managed by a ClusterManager. These + // objects are only destroyed when every shared pointer to any of them + // is destroyed, so we must not store a shared pointer to any ValueObject + // derived from our backend ValueObject (since we're in the same cluster). + ValueObject* m_ptr_obj = nullptr; + ValueObject* m_obj_obj = nullptr; + ValueObject* m_del_obj = nullptr; ValueObjectSP GetTuple(); }; @@ -92,17 +97,17 @@ bool LibStdcppUniquePtrSyntheticFrontEnd::Update() { ValueObjectSP ptr_obj = tuple_frontend->GetChildAtIndex(0); if (ptr_obj) - m_ptr_obj = ptr_obj->Clone(ConstString("pointer")); + m_ptr_obj = ptr_obj->Clone(ConstString("pointer")).get(); ValueObjectSP del_obj = tuple_frontend->GetChildAtIndex(1); if (del_obj) - m_del_obj = del_obj->Clone(ConstString("deleter")); + m_del_obj = del_obj->Clone(ConstString("deleter")).get(); if (m_ptr_obj) { Status error; ValueObjectSP obj_obj = m_ptr_obj->Dereference(error); if (error.Success()) { - m_obj_obj = obj_obj->Clone(ConstString("object")); + m_obj_obj = obj_obj->Clone(ConstString("object")).get(); } } @@ -113,12 +118,12 @@ bool LibStdcppUniquePtrSyntheticFrontEnd::MightHaveChildren() { return true; } lldb::ValueObjectSP LibStdcppUniquePtrSyntheticFrontEnd::GetChildAtIndex(size_t idx) { - if (idx == 0) - return m_ptr_obj; - if (idx == 1) - return m_del_obj; - if (idx == 2) - return m_obj_obj; + if (idx == 0 && m_ptr_obj) + return m_ptr_obj->GetSP(); + if (idx == 1 && m_del_obj) + return m_del_obj->GetSP(); + if (idx == 2 && m_obj_obj) + return m_obj_obj->GetSP(); return lldb::ValueObjectSP(); } diff --git a/source/Plugins/Language/ObjC/CoreMedia.cpp b/source/Plugins/Language/ObjC/CoreMedia.cpp index d19290ec56fb..247429da1b06 100644 --- a/source/Plugins/Language/ObjC/CoreMedia.cpp +++ b/source/Plugins/Language/ObjC/CoreMedia.cpp @@ -10,6 +10,7 @@ #include "CoreMedia.h" #include "lldb/Utility/Flags.h" +#include "lldb/Utility/Log.h" #include "lldb/Symbol/TypeSystem.h" #include "lldb/Target/Target.h" @@ -25,18 +26,21 @@ bool lldb_private::formatters::CMTimeSummaryProvider( if (!type.IsValid()) return false; - TypeSystem *type_system = + auto type_system_or_err = valobj.GetExecutionContextRef() .GetTargetSP() - ->GetScratchTypeSystemForLanguage(nullptr, lldb::eLanguageTypeC); - if (!type_system) + ->GetScratchTypeSystemForLanguage(lldb::eLanguageTypeC); + if (auto err = type_system_or_err.takeError()) { + LLDB_LOG_ERROR( + lldb_private::GetLogIfAnyCategoriesSet(LIBLLDB_LOG_DATAFORMATTERS), + std::move(err), "Failed to get scratch type system"); return false; - + } // fetch children by offset to compensate for potential lack of debug info - auto int64_ty = - type_system->GetBuiltinTypeForEncodingAndBitSize(eEncodingSint, 64); - auto int32_ty = - type_system->GetBuiltinTypeForEncodingAndBitSize(eEncodingSint, 32); + auto int64_ty = type_system_or_err->GetBuiltinTypeForEncodingAndBitSize( + eEncodingSint, 64); + auto int32_ty = type_system_or_err->GetBuiltinTypeForEncodingAndBitSize( + eEncodingSint, 32); auto value_sp(valobj.GetSyntheticChildAtOffset(0, int64_ty, true)); auto timescale_sp(valobj.GetSyntheticChildAtOffset(8, int32_ty, true)); diff --git a/source/Plugins/Language/ObjC/NSArray.cpp b/source/Plugins/Language/ObjC/NSArray.cpp index 404dabf2870c..7219c016dfd1 100644 --- a/source/Plugins/Language/ObjC/NSArray.cpp +++ b/source/Plugins/Language/ObjC/NSArray.cpp @@ -461,12 +461,13 @@ lldb_private::formatters::NSArrayMSyntheticFrontEndBase::NSArrayMSyntheticFrontE : SyntheticChildrenFrontEnd(*valobj_sp), m_exe_ctx_ref(), m_ptr_size(8), m_id_type() { if (valobj_sp) { - clang::ASTContext *ast = valobj_sp->GetExecutionContextRef() - .GetTargetSP() - ->GetScratchClangASTContext() - ->getASTContext(); - if (ast) - m_id_type = CompilerType(ast, ast->ObjCBuiltinIdTy); + auto *clang_ast_context = valobj_sp->GetExecutionContextRef() + .GetTargetSP() + ->GetScratchClangASTContext(); + if (clang_ast_context) + m_id_type = CompilerType( + clang_ast_context, + clang_ast_context->getASTContext()->ObjCBuiltinIdTy.getAsOpaquePtr()); if (valobj_sp->GetProcessSP()) m_ptr_size = valobj_sp->GetProcessSP()->GetAddressByteSize(); } @@ -609,12 +610,13 @@ lldb_private::formatters::GenericNSArrayISyntheticFrontEnd<D32, D64, Inline>:: if (valobj_sp) { CompilerType type = valobj_sp->GetCompilerType(); if (type) { - ClangASTContext *ast = valobj_sp->GetExecutionContextRef() - .GetTargetSP() - ->GetScratchClangASTContext(); - if (ast) - m_id_type = CompilerType(ast->getASTContext(), - ast->getASTContext()->ObjCBuiltinIdTy); + auto *clang_ast_context = valobj_sp->GetExecutionContextRef() + .GetTargetSP() + ->GetScratchClangASTContext(); + if (clang_ast_context) + m_id_type = CompilerType(clang_ast_context, + clang_ast_context->getASTContext() + ->ObjCBuiltinIdTy.getAsOpaquePtr()); } } } diff --git a/source/Plugins/Language/ObjC/NSDictionary.h b/source/Plugins/Language/ObjC/NSDictionary.h index ecb3fccdf877..44d56f9c2c68 100644 --- a/source/Plugins/Language/ObjC/NSDictionary.h +++ b/source/Plugins/Language/ObjC/NSDictionary.h @@ -68,10 +68,10 @@ public: }; typedef Matcher::UP MatcherUP; - MatcherUP GetFullMatch(ConstString n) { return llvm::make_unique<Full>(n); } + MatcherUP GetFullMatch(ConstString n) { return std::make_unique<Full>(n); } MatcherUP GetPrefixMatch(ConstString p) { - return llvm::make_unique<Prefix>(p); + return std::make_unique<Prefix>(p); } }; diff --git a/source/Plugins/Language/ObjC/NSString.cpp b/source/Plugins/Language/ObjC/NSString.cpp index 4800c955e5f5..55e129b098dc 100644 --- a/source/Plugins/Language/ObjC/NSString.cpp +++ b/source/Plugins/Language/ObjC/NSString.cpp @@ -78,12 +78,12 @@ bool lldb_private::formatters::NSStringSummaryProvider( return false; ConstString class_name_cs = descriptor->GetClassName(); - const char *class_name = class_name_cs.GetCString(); + llvm::StringRef class_name = class_name_cs.GetStringRef(); - if (!class_name || !*class_name) + if (class_name.empty()) return false; - bool is_tagged_ptr = (0 == strcmp(class_name, "NSTaggedPointerString")) && + bool is_tagged_ptr = class_name == "NSTaggedPointerString" && descriptor->GetTaggedPointerInfo(); // for a tagged pointer, the descriptor has everything we need if (is_tagged_ptr) @@ -111,7 +111,7 @@ bool lldb_private::formatters::NSStringSummaryProvider( bool is_inline = (info_bits & 0x60) == 0; bool has_explicit_length = (info_bits & (1 | 4)) != 4; bool is_unicode = (info_bits & 0x10) == 0x10; - bool is_path_store = strcmp(class_name, "NSPathStore2") == 0; + bool is_path_store = class_name == "NSPathStore2"; bool has_null = (info_bits & 8) == 8; size_t explicit_length = 0; @@ -135,14 +135,14 @@ bool lldb_private::formatters::NSStringSummaryProvider( } } - if (strcmp(class_name, "NSString") && strcmp(class_name, "CFStringRef") && - strcmp(class_name, "CFMutableStringRef") && - strcmp(class_name, "__NSCFConstantString") && - strcmp(class_name, "__NSCFString") && - strcmp(class_name, "NSCFConstantString") && - strcmp(class_name, "NSCFString") && strcmp(class_name, "NSPathStore2")) { + const llvm::StringSet<> supported_string_classes = { + "NSString", "CFMutableStringRef", + "CFStringRef", "__NSCFConstantString", + "__NSCFString", "NSCFConstantString", + "NSCFString", "NSPathStore2"}; + if (supported_string_classes.count(class_name) == 0) { // not one of us - but tell me class name - stream.Printf("class name = %s", class_name); + stream.Printf("class name = %s", class_name_cs.GetCString()); return true; } diff --git a/source/Plugins/Language/ObjC/ObjCLanguage.cpp b/source/Plugins/Language/ObjC/ObjCLanguage.cpp index f9ab18688de7..c5bfb5747c13 100644 --- a/source/Plugins/Language/ObjC/ObjCLanguage.cpp +++ b/source/Plugins/Language/ObjC/ObjCLanguage.cpp @@ -22,6 +22,7 @@ #include "llvm/Support/Threading.h" +#include "Plugins/ExpressionParser/Clang/ClangModulesDeclVendor.h" #include "Plugins/LanguageRuntime/ObjC/ObjCLanguageRuntime.h" #include "CF.h" diff --git a/source/Plugins/LanguageRuntime/CPlusPlus/CPPLanguageRuntime.cpp b/source/Plugins/LanguageRuntime/CPlusPlus/CPPLanguageRuntime.cpp index b392282c3eb1..f38014505a8b 100644 --- a/source/Plugins/LanguageRuntime/CPlusPlus/CPPLanguageRuntime.cpp +++ b/source/Plugins/LanguageRuntime/CPlusPlus/CPPLanguageRuntime.cpp @@ -231,7 +231,7 @@ CPPLanguageRuntime::FindLibCppStdFunctionCallableInfo( SymbolContextList scl; target.GetImages().FindSymbolsMatchingRegExAndType( - RegularExpression{R"(^)" + func_to_match}, eSymbolTypeAny, scl, true); + RegularExpression{R"(^)" + func_to_match}, eSymbolTypeAny, scl); // Case 1,2 or 3 if (scl.GetSize() >= 1) { diff --git a/source/Plugins/LanguageRuntime/CPlusPlus/ItaniumABI/ItaniumABILanguageRuntime.cpp b/source/Plugins/LanguageRuntime/CPlusPlus/ItaniumABI/ItaniumABILanguageRuntime.cpp index 41f38a4e3dcd..02e62a263286 100644 --- a/source/Plugins/LanguageRuntime/CPlusPlus/ItaniumABI/ItaniumABILanguageRuntime.cpp +++ b/source/Plugins/LanguageRuntime/CPlusPlus/ItaniumABI/ItaniumABILanguageRuntime.cpp @@ -79,11 +79,10 @@ TypeAndOrName ItaniumABILanguageRuntime::GetTypeInfoFromVTableAddress( if (name && strstr(name, vtable_demangled_prefix) == name) { Log *log( lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_OBJECT)); - if (log) - log->Printf("0x%16.16" PRIx64 - ": static-type = '%s' has vtable symbol '%s'\n", - original_ptr, in_value.GetTypeName().GetCString(), - name); + LLDB_LOGF(log, + "0x%16.16" PRIx64 + ": static-type = '%s' has vtable symbol '%s'\n", + original_ptr, in_value.GetTypeName().GetCString(), name); // We are a C++ class, that's good. Get the class name and look it // up: const char *class_name = name + strlen(vtable_demangled_prefix); @@ -96,87 +95,81 @@ TypeAndOrName ItaniumABILanguageRuntime::GetTypeInfoFromVTableAddress( const bool exact_match = true; TypeList class_types; - uint32_t num_matches = 0; // First look in the module that the vtable symbol came from and // look for a single exact match. llvm::DenseSet<SymbolFile *> searched_symbol_files; - if (sc.module_sp) { - num_matches = sc.module_sp->FindTypes( - ConstString(lookup_name), exact_match, 1, - searched_symbol_files, class_types); - } + if (sc.module_sp) + sc.module_sp->FindTypes(ConstString(lookup_name), exact_match, 1, + searched_symbol_files, class_types); // If we didn't find a symbol, then move on to the entire module // list in the target and get as many unique matches as possible - if (num_matches == 0) { - num_matches = target.GetImages().FindTypes( - nullptr, ConstString(lookup_name), exact_match, UINT32_MAX, - searched_symbol_files, class_types); - } + if (class_types.Empty()) + target.GetImages().FindTypes(nullptr, ConstString(lookup_name), + exact_match, UINT32_MAX, + searched_symbol_files, class_types); lldb::TypeSP type_sp; - if (num_matches == 0) { - if (log) - log->Printf("0x%16.16" PRIx64 ": is not dynamic\n", - original_ptr); + if (class_types.Empty()) { + LLDB_LOGF(log, "0x%16.16" PRIx64 ": is not dynamic\n", + original_ptr); return TypeAndOrName(); } - if (num_matches == 1) { + if (class_types.GetSize() == 1) { type_sp = class_types.GetTypeAtIndex(0); if (type_sp) { if (ClangASTContext::IsCXXClassType( type_sp->GetForwardCompilerType())) { - if (log) - log->Printf( - "0x%16.16" PRIx64 - ": static-type = '%s' has dynamic type: uid={0x%" PRIx64 - "}, type-name='%s'\n", - original_ptr, in_value.GetTypeName().AsCString(), - type_sp->GetID(), type_sp->GetName().GetCString()); + LLDB_LOGF( + log, + "0x%16.16" PRIx64 + ": static-type = '%s' has dynamic type: uid={0x%" PRIx64 + "}, type-name='%s'\n", + original_ptr, in_value.GetTypeName().AsCString(), + type_sp->GetID(), type_sp->GetName().GetCString()); type_info.SetTypeSP(type_sp); } } - } else if (num_matches > 1) { + } else { size_t i; if (log) { - for (i = 0; i < num_matches; i++) { + for (i = 0; i < class_types.GetSize(); i++) { type_sp = class_types.GetTypeAtIndex(i); if (type_sp) { - if (log) - log->Printf( - "0x%16.16" PRIx64 - ": static-type = '%s' has multiple matching dynamic " - "types: uid={0x%" PRIx64 "}, type-name='%s'\n", - original_ptr, in_value.GetTypeName().AsCString(), - type_sp->GetID(), type_sp->GetName().GetCString()); + LLDB_LOGF( + log, + "0x%16.16" PRIx64 + ": static-type = '%s' has multiple matching dynamic " + "types: uid={0x%" PRIx64 "}, type-name='%s'\n", + original_ptr, in_value.GetTypeName().AsCString(), + type_sp->GetID(), type_sp->GetName().GetCString()); } } } - for (i = 0; i < num_matches; i++) { + for (i = 0; i < class_types.GetSize(); i++) { type_sp = class_types.GetTypeAtIndex(i); if (type_sp) { if (ClangASTContext::IsCXXClassType( type_sp->GetForwardCompilerType())) { - if (log) - log->Printf( - "0x%16.16" PRIx64 ": static-type = '%s' has multiple " - "matching dynamic types, picking " - "this one: uid={0x%" PRIx64 - "}, type-name='%s'\n", - original_ptr, in_value.GetTypeName().AsCString(), - type_sp->GetID(), type_sp->GetName().GetCString()); + LLDB_LOGF( + log, + "0x%16.16" PRIx64 ": static-type = '%s' has multiple " + "matching dynamic types, picking " + "this one: uid={0x%" PRIx64 "}, type-name='%s'\n", + original_ptr, in_value.GetTypeName().AsCString(), + type_sp->GetID(), type_sp->GetName().GetCString()); type_info.SetTypeSP(type_sp); } } } - if (log && i == num_matches) { - log->Printf( - "0x%16.16" PRIx64 - ": static-type = '%s' has multiple matching dynamic " - "types, didn't find a C++ match\n", - original_ptr, in_value.GetTypeName().AsCString()); + if (log) { + LLDB_LOGF(log, + "0x%16.16" PRIx64 + ": static-type = '%s' has multiple matching dynamic " + "types, didn't find a C++ match\n", + original_ptr, in_value.GetTypeName().AsCString()); } } if (type_info) @@ -351,7 +344,7 @@ protected: bool demangled_any = false; bool error_any = false; for (auto &entry : command.entries()) { - if (entry.ref.empty()) + if (entry.ref().empty()) continue; // the actual Mangled class should be strict about this, but on the @@ -359,21 +352,21 @@ protected: // they will come out with an extra underscore - be willing to strip this // on behalf of the user. This is the moral equivalent of the -_/-n // options to c++filt - auto name = entry.ref; + auto name = entry.ref(); if (name.startswith("__Z")) name = name.drop_front(); - Mangled mangled(name, true); + Mangled mangled(name); if (mangled.GuessLanguage() == lldb::eLanguageTypeC_plus_plus) { ConstString demangled( mangled.GetDisplayDemangledName(lldb::eLanguageTypeC_plus_plus)); demangled_any = true; - result.AppendMessageWithFormat("%s ---> %s\n", entry.ref.str().c_str(), + result.AppendMessageWithFormat("%s ---> %s\n", entry.c_str(), demangled.GetCString()); } else { error_any = true; result.AppendErrorWithFormat("%s is not a valid C++ mangled name\n", - entry.ref.str().c_str()); + entry.ref().str().c_str()); } } @@ -471,8 +464,8 @@ lldb::SearchFilterSP ItaniumABILanguageRuntime::CreateExceptionSearchFilter() { if (target.GetArchitecture().GetTriple().getVendor() == llvm::Triple::Apple) { // Limit the number of modules that are searched for these breakpoints for // Apple binaries. - filter_modules.Append(FileSpec("libc++abi.dylib")); - filter_modules.Append(FileSpec("libSystem.B.dylib")); + filter_modules.EmplaceBack("libc++abi.dylib"); + filter_modules.EmplaceBack("libSystem.B.dylib"); } return target.GetSearchFilterForModuleList(&filter_modules); } diff --git a/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCDeclVendor.cpp b/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCDeclVendor.cpp index 18f2a1829a41..1f27a4f0b3ed 100644 --- a/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCDeclVendor.cpp +++ b/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCDeclVendor.cpp @@ -38,12 +38,13 @@ public: LIBLLDB_LOG_EXPRESSIONS)); // FIXME - a more appropriate log channel? if (log) { - log->Printf("AppleObjCExternalASTSource::FindExternalVisibleDeclsByName[%" - "u] on (ASTContext*)%p Looking for %s in (%sDecl*)%p", - current_id, - static_cast<void *>(&decl_ctx->getParentASTContext()), - name.getAsString().c_str(), decl_ctx->getDeclKindName(), - static_cast<const void *>(decl_ctx)); + LLDB_LOGF(log, + "AppleObjCExternalASTSource::FindExternalVisibleDeclsByName[%" + "u] on (ASTContext*)%p Looking for %s in (%sDecl*)%p", + current_id, + static_cast<void *>(&decl_ctx->getParentASTContext()), + name.getAsString().c_str(), decl_ctx->getDeclKindName(), + static_cast<const void *>(decl_ctx)); } do { @@ -77,19 +78,20 @@ public: LIBLLDB_LOG_EXPRESSIONS)); // FIXME - a more appropriate log channel? if (log) { - log->Printf("AppleObjCExternalASTSource::CompleteType[%u] on " - "(ASTContext*)%p Completing (TagDecl*)%p named %s", - current_id, static_cast<void *>(&tag_decl->getASTContext()), - static_cast<void *>(tag_decl), - tag_decl->getName().str().c_str()); - - log->Printf(" AOEAS::CT[%u] Before:", current_id); + LLDB_LOGF(log, + "AppleObjCExternalASTSource::CompleteType[%u] on " + "(ASTContext*)%p Completing (TagDecl*)%p named %s", + current_id, static_cast<void *>(&tag_decl->getASTContext()), + static_cast<void *>(tag_decl), + tag_decl->getName().str().c_str()); + + LLDB_LOGF(log, " AOEAS::CT[%u] Before:", current_id); ASTDumper dumper((clang::Decl *)tag_decl); dumper.ToLog(log, " [CT] "); } if (log) { - log->Printf(" AOEAS::CT[%u] After:", current_id); + LLDB_LOGF(log, " AOEAS::CT[%u] After:", current_id); ASTDumper dumper((clang::Decl *)tag_decl); dumper.ToLog(log, " [CT] "); } @@ -104,14 +106,15 @@ public: LIBLLDB_LOG_EXPRESSIONS)); // FIXME - a more appropriate log channel? if (log) { - log->Printf("AppleObjCExternalASTSource::CompleteType[%u] on " - "(ASTContext*)%p Completing (ObjCInterfaceDecl*)%p named %s", - current_id, - static_cast<void *>(&interface_decl->getASTContext()), - static_cast<void *>(interface_decl), - interface_decl->getName().str().c_str()); - - log->Printf(" AOEAS::CT[%u] Before:", current_id); + LLDB_LOGF(log, + "AppleObjCExternalASTSource::CompleteType[%u] on " + "(ASTContext*)%p Completing (ObjCInterfaceDecl*)%p named %s", + current_id, + static_cast<void *>(&interface_decl->getASTContext()), + static_cast<void *>(interface_decl), + interface_decl->getName().str().c_str()); + + LLDB_LOGF(log, " AOEAS::CT[%u] Before:", current_id); ASTDumper dumper((clang::Decl *)interface_decl); dumper.ToLog(log, " [CT] "); } @@ -119,7 +122,7 @@ public: m_decl_vendor.FinishDecl(interface_decl); if (log) { - log->Printf(" [CT] After:"); + LLDB_LOGF(log, " [CT] After:"); ASTDumper dumper((clang::Decl *)interface_decl); dumper.ToLog(log, " [CT] "); } @@ -148,12 +151,13 @@ private: }; AppleObjCDeclVendor::AppleObjCDeclVendor(ObjCLanguageRuntime &runtime) - : DeclVendor(), m_runtime(runtime), m_ast_ctx(runtime.GetProcess() - ->GetTarget() - .GetArchitecture() - .GetTriple() - .getTriple() - .c_str()), + : ClangDeclVendor(eAppleObjCDeclVendor), m_runtime(runtime), + m_ast_ctx(runtime.GetProcess() + ->GetTarget() + .GetArchitecture() + .GetTriple() + .getTriple() + .c_str()), m_type_realizer_sp(m_runtime.GetEncodingToType()) { m_external_source = new AppleObjCExternalASTSource(*this); llvm::IntrusiveRefCntPtr<clang::ExternalASTSource> external_source_owning_ptr( @@ -462,8 +466,7 @@ bool AppleObjCDeclVendor::FinishDecl(clang::ObjCInterfaceDecl *interface_decl) { clang::ObjCMethodDecl *method_decl = method_type.BuildMethod(interface_decl, name, true, m_type_realizer_sp); - if (log) - log->Printf("[ AOTV::FD] Instance method [%s] [%s]", name, types); + LLDB_LOGF(log, "[ AOTV::FD] Instance method [%s] [%s]", name, types); if (method_decl) interface_decl->addDecl(method_decl); @@ -481,8 +484,7 @@ bool AppleObjCDeclVendor::FinishDecl(clang::ObjCInterfaceDecl *interface_decl) { clang::ObjCMethodDecl *method_decl = method_type.BuildMethod( interface_decl, name, false, m_type_realizer_sp); - if (log) - log->Printf("[ AOTV::FD] Class method [%s] [%s]", name, types); + LLDB_LOGF(log, "[ AOTV::FD] Class method [%s] [%s]", name, types); if (method_decl) interface_decl->addDecl(method_decl); @@ -498,10 +500,9 @@ bool AppleObjCDeclVendor::FinishDecl(clang::ObjCInterfaceDecl *interface_decl) { const bool for_expression = false; - if (log) - log->Printf( - "[ AOTV::FD] Instance variable [%s] [%s], offset at %" PRIx64, name, - type, offset_ptr); + LLDB_LOGF(log, + "[ AOTV::FD] Instance variable [%s] [%s], offset at %" PRIx64, + name, type, offset_ptr); CompilerType ivar_type = m_runtime.GetEncodingToType()->RealizeType( m_ast_ctx, type, for_expression); @@ -527,9 +528,10 @@ bool AppleObjCDeclVendor::FinishDecl(clang::ObjCInterfaceDecl *interface_decl) { if (log) { ASTDumper method_dumper((clang::Decl *)interface_decl); - log->Printf("[AppleObjCDeclVendor::FinishDecl] Finishing Objective-C " - "interface for %s", - descriptor->GetClassName().AsCString()); + LLDB_LOGF(log, + "[AppleObjCDeclVendor::FinishDecl] Finishing Objective-C " + "interface for %s", + descriptor->GetClassName().AsCString()); } if (!descriptor->Describe(superclass_func, instance_method_func, @@ -539,7 +541,8 @@ bool AppleObjCDeclVendor::FinishDecl(clang::ObjCInterfaceDecl *interface_decl) { if (log) { ASTDumper method_dumper((clang::Decl *)interface_decl); - log->Printf( + LLDB_LOGF( + log, "[AppleObjCDeclVendor::FinishDecl] Finished Objective-C interface"); method_dumper.ToLog(log, " [AOTV::FD] "); @@ -558,10 +561,9 @@ AppleObjCDeclVendor::FindDecls(ConstString name, bool append, Log *log(GetLogIfAllCategoriesSet( LIBLLDB_LOG_EXPRESSIONS)); // FIXME - a more appropriate log channel? - if (log) - log->Printf("AppleObjCDeclVendor::FindDecls [%u] ('%s', %s, %u, )", - current_id, (const char *)name.AsCString(), - append ? "true" : "false", max_matches); + LLDB_LOGF(log, "AppleObjCDeclVendor::FindDecls [%u] ('%s', %s, %u, )", + current_id, (const char *)name.AsCString(), + append ? "true" : "false", max_matches); if (!append) decls.clear(); @@ -595,24 +597,25 @@ AppleObjCDeclVendor::FindDecls(ConstString name, bool append, if (metadata) isa_value = metadata->GetISAPtr(); - log->Printf("AOCTV::FT [%u] Found %s (isa 0x%" PRIx64 - ") in the ASTContext", - current_id, dumper.GetCString(), isa_value); + LLDB_LOGF(log, + "AOCTV::FT [%u] Found %s (isa 0x%" PRIx64 + ") in the ASTContext", + current_id, dumper.GetCString(), isa_value); } decls.push_back(result_iface_decl); ret++; break; } else { - if (log) - log->Printf("AOCTV::FT [%u] There's something in the ASTContext, but " - "it's not something we know about", - current_id); + LLDB_LOGF(log, + "AOCTV::FT [%u] There's something in the ASTContext, but " + "it's not something we know about", + current_id); break; } } else if (log) { - log->Printf("AOCTV::FT [%u] Couldn't find %s in the ASTContext", - current_id, name.AsCString()); + LLDB_LOGF(log, "AOCTV::FT [%u] Couldn't find %s in the ASTContext", + current_id, name.AsCString()); } // It's not. If it exists, we have to put it into our ASTContext. @@ -620,8 +623,7 @@ AppleObjCDeclVendor::FindDecls(ConstString name, bool append, ObjCLanguageRuntime::ObjCISA isa = m_runtime.GetISA(name); if (!isa) { - if (log) - log->Printf("AOCTV::FT [%u] Couldn't find the isa", current_id); + LLDB_LOGF(log, "AOCTV::FT [%u] Couldn't find the isa", current_id); break; } @@ -629,10 +631,10 @@ AppleObjCDeclVendor::FindDecls(ConstString name, bool append, clang::ObjCInterfaceDecl *iface_decl = GetDeclForISA(isa); if (!iface_decl) { - if (log) - log->Printf("AOCTV::FT [%u] Couldn't get the Objective-C interface for " - "isa 0x%" PRIx64, - current_id, (uint64_t)isa); + LLDB_LOGF(log, + "AOCTV::FT [%u] Couldn't get the Objective-C interface for " + "isa 0x%" PRIx64, + current_id, (uint64_t)isa); break; } @@ -641,8 +643,8 @@ AppleObjCDeclVendor::FindDecls(ConstString name, bool append, clang::QualType new_iface_type = ast_ctx->getObjCInterfaceType(iface_decl); ASTDumper dumper(new_iface_type); - log->Printf("AOCTV::FT [%u] Created %s (isa 0x%" PRIx64 ")", current_id, - dumper.GetCString(), (uint64_t)isa); + LLDB_LOGF(log, "AOCTV::FT [%u] Created %s (isa 0x%" PRIx64 ")", + current_id, dumper.GetCString(), (uint64_t)isa); } decls.push_back(iface_decl); @@ -655,8 +657,7 @@ AppleObjCDeclVendor::FindDecls(ConstString name, bool append, clang::ExternalASTMerger::ImporterSource AppleObjCDeclVendor::GetImporterSource() { - return {*m_ast_ctx.getASTContext(), - *m_ast_ctx.getFileManager(), - m_ast_ctx.GetOriginMap() - }; + return clang::ExternalASTMerger::ImporterSource(*m_ast_ctx.getASTContext(), + *m_ast_ctx.getFileManager(), + m_ast_ctx.GetOriginMap()); } diff --git a/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCDeclVendor.h b/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCDeclVendor.h index 77b30b7fde79..99ca4b748709 100644 --- a/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCDeclVendor.h +++ b/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCDeclVendor.h @@ -10,19 +10,23 @@ #define liblldb_AppleObjCDeclVendor_h_ #include "lldb/Symbol/ClangASTContext.h" -#include "lldb/Symbol/DeclVendor.h" #include "lldb/lldb-private.h" +#include "Plugins/ExpressionParser/Clang/ClangDeclVendor.h" #include "Plugins/LanguageRuntime/ObjC/ObjCLanguageRuntime.h" namespace lldb_private { class AppleObjCExternalASTSource; -class AppleObjCDeclVendor : public DeclVendor { +class AppleObjCDeclVendor : public ClangDeclVendor { public: AppleObjCDeclVendor(ObjCLanguageRuntime &runtime); + static bool classof(const DeclVendor *vendor) { + return vendor->GetKind() == eAppleObjCDeclVendor; + } + uint32_t FindDecls(ConstString name, bool append, uint32_t max_matches, std::vector<clang::NamedDecl *> &decls) override; diff --git a/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntime.cpp b/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntime.cpp index 52ed3628520f..8ca9ad7b843a 100644 --- a/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntime.cpp +++ b/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntime.cpp @@ -223,11 +223,14 @@ Address *AppleObjCRuntime::GetPrintForDebuggerAddr() { SymbolContextList contexts; SymbolContext context; - if ((!modules.FindSymbolsWithNameAndType(ConstString("_NSPrintForDebugger"), - eSymbolTypeCode, contexts)) && - (!modules.FindSymbolsWithNameAndType(ConstString("_CFPrintForDebugger"), - eSymbolTypeCode, contexts))) - return nullptr; + modules.FindSymbolsWithNameAndType(ConstString("_NSPrintForDebugger"), + eSymbolTypeCode, contexts); + if (contexts.IsEmpty()) { + modules.FindSymbolsWithNameAndType(ConstString("_CFPrintForDebugger"), + eSymbolTypeCode, contexts); + if (contexts.IsEmpty()) + return nullptr; + } contexts.GetContextAtIndex(0, context); @@ -444,10 +447,12 @@ bool AppleObjCRuntime::CalculateHasNewLiteralsAndIndexing() { SymbolContextList sc_list; - return target.GetImages().FindSymbolsWithNameAndType( - s_method_signature, eSymbolTypeCode, sc_list) || - target.GetImages().FindSymbolsWithNameAndType( - s_arclite_method_signature, eSymbolTypeCode, sc_list); + target.GetImages().FindSymbolsWithNameAndType(s_method_signature, + eSymbolTypeCode, sc_list); + if (sc_list.IsEmpty()) + target.GetImages().FindSymbolsWithNameAndType(s_arclite_method_signature, + eSymbolTypeCode, sc_list); + return !sc_list.IsEmpty(); } lldb::SearchFilterSP AppleObjCRuntime::CreateExceptionSearchFilter() { diff --git a/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntimeV1.cpp b/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntimeV1.cpp index c8884fd5c9b9..88bfe2ce0203 100644 --- a/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntimeV1.cpp +++ b/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntimeV1.cpp @@ -395,10 +395,11 @@ void AppleObjCRuntimeV1::UpdateISAToDescriptorMapIfNeeded() { new ClassDescriptorV1(isa, process_sp)); if (log && log->GetVerbose()) - log->Printf("AppleObjCRuntimeV1 added (ObjCISA)0x%" PRIx64 - " from _objc_debug_class_hash to " - "isa->descriptor cache", - isa); + LLDB_LOGF(log, + "AppleObjCRuntimeV1 added (ObjCISA)0x%" PRIx64 + " from _objc_debug_class_hash to " + "isa->descriptor cache", + isa); AddClass(isa, descriptor_sp); } @@ -417,7 +418,8 @@ void AppleObjCRuntimeV1::UpdateISAToDescriptorMapIfNeeded() { new ClassDescriptorV1(isa, process_sp)); if (log && log->GetVerbose()) - log->Printf( + LLDB_LOGF( + log, "AppleObjCRuntimeV1 added (ObjCISA)0x%" PRIx64 " from _objc_debug_class_hash to isa->descriptor " "cache", diff --git a/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntimeV2.cpp b/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntimeV2.cpp index 635eaff637bc..9bdbef393e39 100644 --- a/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntimeV2.cpp +++ b/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntimeV2.cpp @@ -582,9 +582,9 @@ protected: case 0: break; case 1: { - regex_up.reset(new RegularExpression()); - if (!regex_up->Compile(llvm::StringRef::withNullAsEmpty( - command.GetArgumentAtIndex(0)))) { + regex_up.reset(new RegularExpression( + llvm::StringRef::withNullAsEmpty(command.GetArgumentAtIndex(0)))); + if (!regex_up->IsValid()) { result.AppendError( "invalid argument - please provide a valid regular expression"); result.SetStatus(lldb::eReturnStatusFailed); @@ -1209,11 +1209,11 @@ AppleObjCRuntimeV2::GetClassDescriptor(ValueObject &valobj) { objc_class_sp = GetClassDescriptorFromISA(isa); if (isa && !objc_class_sp) { Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_PROCESS)); - if (log) - log->Printf("0x%" PRIx64 - ": AppleObjCRuntimeV2::GetClassDescriptor() ISA was " - "not in class descriptor cache 0x%" PRIx64, - isa_pointer, isa); + LLDB_LOGF(log, + "0x%" PRIx64 + ": AppleObjCRuntimeV2::GetClassDescriptor() ISA was " + "not in class descriptor cache 0x%" PRIx64, + isa_pointer, isa); } } } @@ -1317,8 +1317,7 @@ AppleObjCRuntimeV2::UpdateISAToDescriptorMapDynamic( // Read the total number of classes from the hash table const uint32_t num_classes = hash_table.GetCount(); if (num_classes == 0) { - if (log) - log->Printf("No dynamic classes found in gdb_objc_realized_classes."); + LLDB_LOGF(log, "No dynamic classes found in gdb_objc_realized_classes."); return DescriptorMapUpdateResult::Success(0); } @@ -1337,17 +1336,16 @@ AppleObjCRuntimeV2::UpdateISAToDescriptorMapDynamic( g_get_dynamic_class_info_body, eLanguageTypeObjC, g_get_dynamic_class_info_name, error)); if (error.Fail()) { - if (log) - log->Printf( - "Failed to get Utility Function for implementation lookup: %s", - error.AsCString()); + LLDB_LOGF(log, + "Failed to get Utility Function for implementation lookup: %s", + error.AsCString()); m_get_class_info_code.reset(); } else { diagnostics.Clear(); if (!m_get_class_info_code->Install(diagnostics, exe_ctx)) { if (log) { - log->Printf("Failed to install implementation lookup"); + LLDB_LOGF(log, "Failed to install implementation lookup"); diagnostics.Dump(log); } m_get_class_info_code.reset(); @@ -1372,17 +1370,16 @@ AppleObjCRuntimeV2::UpdateISAToDescriptorMapDynamic( clang_uint32_t_type, arguments, thread_sp, error); if (error.Fail()) { - if (log) - log->Printf( - "Failed to make function caller for implementation lookup: %s.", - error.AsCString()); + LLDB_LOGF(log, + "Failed to make function caller for implementation lookup: %s.", + error.AsCString()); return DescriptorMapUpdateResult::Fail(); } } else { get_class_info_function = m_get_class_info_code->GetFunctionCaller(); if (!get_class_info_function) { if (log) { - log->Printf("Failed to get implementation lookup function caller."); + LLDB_LOGF(log, "Failed to get implementation lookup function caller."); diagnostics.Dump(log); } @@ -1399,10 +1396,10 @@ AppleObjCRuntimeV2::UpdateISAToDescriptorMapDynamic( class_infos_byte_size, ePermissionsReadable | ePermissionsWritable, err); if (class_infos_addr == LLDB_INVALID_ADDRESS) { - if (log) - log->Printf("unable to allocate %" PRIu32 - " bytes in process for shared cache read", - class_infos_byte_size); + LLDB_LOGF(log, + "unable to allocate %" PRIu32 + " bytes in process for shared cache read", + class_infos_byte_size); return DescriptorMapUpdateResult::Fail(); } @@ -1451,8 +1448,7 @@ AppleObjCRuntimeV2::UpdateISAToDescriptorMapDynamic( if (results == eExpressionCompleted) { // The result is the number of ClassInfo structures that were filled in num_class_infos = return_value.GetScalar().ULong(); - if (log) - log->Printf("Discovered %u ObjC classes\n", num_class_infos); + LLDB_LOGF(log, "Discovered %u ObjC classes\n", num_class_infos); if (num_class_infos > 0) { // Read the ClassInfo structures DataBufferHeap buffer(num_class_infos * class_info_byte_size, 0); @@ -1468,13 +1464,13 @@ AppleObjCRuntimeV2::UpdateISAToDescriptorMapDynamic( success = true; } else { if (log) { - log->Printf("Error evaluating our find class name function."); + LLDB_LOGF(log, "Error evaluating our find class name function."); diagnostics.Dump(log); } } } else { if (log) { - log->Printf("Error writing function arguments."); + LLDB_LOGF(log, "Error writing function arguments."); diagnostics.Dump(log); } } @@ -1507,17 +1503,18 @@ uint32_t AppleObjCRuntimeV2::ParseClassInfoArray(const DataExtractor &data, if (isa == 0) { if (should_log) - log->Printf( - "AppleObjCRuntimeV2 found NULL isa, ignoring this class info"); + LLDB_LOGF( + log, "AppleObjCRuntimeV2 found NULL isa, ignoring this class info"); continue; } // Check if we already know about this ISA, if we do, the info will never // change, so we can just skip it. if (ISAIsCached(isa)) { if (should_log) - log->Printf("AppleObjCRuntimeV2 found cached isa=0x%" PRIx64 - ", ignoring this class info", - isa); + LLDB_LOGF(log, + "AppleObjCRuntimeV2 found cached isa=0x%" PRIx64 + ", ignoring this class info", + isa); offset += 4; } else { // Read the 32 bit hash for the class name @@ -1536,15 +1533,16 @@ uint32_t AppleObjCRuntimeV2::ParseClassInfoArray(const DataExtractor &data, AddClass(isa, descriptor_sp, descriptor_sp->GetClassName().AsCString(nullptr)); num_parsed++; if (should_log) - log->Printf("AppleObjCRuntimeV2 added isa=0x%" PRIx64 - ", hash=0x%8.8x, name=%s", - isa, name_hash, - descriptor_sp->GetClassName().AsCString("<unknown>")); + LLDB_LOGF(log, + "AppleObjCRuntimeV2 added isa=0x%" PRIx64 + ", hash=0x%8.8x, name=%s", + isa, name_hash, + descriptor_sp->GetClassName().AsCString("<unknown>")); } } if (should_log) - log->Printf("AppleObjCRuntimeV2 parsed %" PRIu32 " class infos", - num_parsed); + LLDB_LOGF(log, "AppleObjCRuntimeV2 parsed %" PRIu32 " class infos", + num_parsed); return num_parsed; } @@ -1603,7 +1601,7 @@ AppleObjCRuntimeV2::UpdateISAToDescriptorMapSharedCache() { // use that in our jitted expression. Else fall back to the old // class_getName. static ConstString g_class_getName_symbol_name("class_getName"); - static ConstString g_class_getNameRaw_symbol_name("class_getNameRaw"); + static ConstString g_class_getNameRaw_symbol_name("objc_debug_class_getNameRaw"); ConstString class_name_getter_function_name = g_class_getName_symbol_name; ObjCLanguageRuntime *objc_runtime = ObjCLanguageRuntime::Get(*process); @@ -1646,17 +1644,16 @@ AppleObjCRuntimeV2::UpdateISAToDescriptorMapSharedCache() { shared_class_expression.c_str(), eLanguageTypeObjC, g_get_shared_cache_class_info_name, error)); if (error.Fail()) { - if (log) - log->Printf( - "Failed to get Utility function for implementation lookup: %s.", - error.AsCString()); + LLDB_LOGF(log, + "Failed to get Utility function for implementation lookup: %s.", + error.AsCString()); m_get_shared_cache_class_info_code.reset(); } else { diagnostics.Clear(); if (!m_get_shared_cache_class_info_code->Install(diagnostics, exe_ctx)) { if (log) { - log->Printf("Failed to install implementation lookup."); + LLDB_LOGF(log, "Failed to install implementation lookup."); diagnostics.Dump(log); } m_get_shared_cache_class_info_code.reset(); @@ -1703,10 +1700,10 @@ AppleObjCRuntimeV2::UpdateISAToDescriptorMapSharedCache() { class_infos_byte_size, ePermissionsReadable | ePermissionsWritable, err); if (class_infos_addr == LLDB_INVALID_ADDRESS) { - if (log) - log->Printf("unable to allocate %" PRIu32 - " bytes in process for shared cache read", - class_infos_byte_size); + LLDB_LOGF(log, + "unable to allocate %" PRIu32 + " bytes in process for shared cache read", + class_infos_byte_size); return DescriptorMapUpdateResult::Fail(); } @@ -1757,9 +1754,8 @@ AppleObjCRuntimeV2::UpdateISAToDescriptorMapSharedCache() { if (results == eExpressionCompleted) { // The result is the number of ClassInfo structures that were filled in num_class_infos = return_value.GetScalar().ULong(); - if (log) - log->Printf("Discovered %u ObjC classes in shared cache\n", - num_class_infos); + LLDB_LOGF(log, "Discovered %u ObjC classes in shared cache\n", + num_class_infos); assert(num_class_infos <= num_classes); if (num_class_infos > 0) { if (num_class_infos > num_classes) { @@ -1786,13 +1782,13 @@ AppleObjCRuntimeV2::UpdateISAToDescriptorMapSharedCache() { } } else { if (log) { - log->Printf("Error evaluating our find class name function."); + LLDB_LOGF(log, "Error evaluating our find class name function."); diagnostics.Dump(log); } } } else { if (log) { - log->Printf("Error writing function arguments."); + LLDB_LOGF(log, "Error writing function arguments."); diagnostics.Dump(log); } } @@ -1827,9 +1823,10 @@ bool AppleObjCRuntimeV2::UpdateISAToDescriptorMapFromMemory( new ClassDescriptorV2(*this, elt.second, elt.first.AsCString())); if (log && log->GetVerbose()) - log->Printf("AppleObjCRuntimeV2 added (ObjCISA)0x%" PRIx64 - " (%s) from dynamic table to isa->descriptor cache", - elt.second, elt.first.AsCString()); + LLDB_LOGF(log, + "AppleObjCRuntimeV2 added (ObjCISA)0x%" PRIx64 + " (%s) from dynamic table to isa->descriptor cache", + elt.second, elt.first.AsCString()); AddClass(elt.second, descriptor_sp, elt.first.AsCString()); } @@ -1912,14 +1909,14 @@ void AppleObjCRuntimeV2::UpdateISAToDescriptorMapIfNeeded() { DescriptorMapUpdateResult shared_cache_update_result = UpdateISAToDescriptorMapSharedCache(); - if (log) - log->Printf("attempted to read objc class data - results: " - "[dynamic_update]: ran: %s, count: %" PRIu32 - " [shared_cache_update]: ran: %s, count: %" PRIu32, - dynamic_update_result.m_update_ran ? "yes" : "no", - dynamic_update_result.m_num_found, - shared_cache_update_result.m_update_ran ? "yes" : "no", - shared_cache_update_result.m_num_found); + LLDB_LOGF(log, + "attempted to read objc class data - results: " + "[dynamic_update]: ran: %s, count: %" PRIu32 + " [shared_cache_update]: ran: %s, count: %" PRIu32, + dynamic_update_result.m_update_ran ? "yes" : "no", + dynamic_update_result.m_num_found, + shared_cache_update_result.m_update_ran ? "yes" : "no", + shared_cache_update_result.m_num_found); // warn if: // - we could not run either expression @@ -2032,8 +2029,8 @@ lldb::addr_t AppleObjCRuntimeV2::LookupRuntimeSymbol(ConstString name) { if (name_cstr) { llvm::StringRef name_strref(name_cstr); - static const llvm::StringRef ivar_prefix("OBJC_IVAR_$_"); - static const llvm::StringRef class_prefix("OBJC_CLASS_$_"); + llvm::StringRef ivar_prefix("OBJC_IVAR_$_"); + llvm::StringRef class_prefix("OBJC_CLASS_$_"); if (name_strref.startswith(ivar_prefix)) { llvm::StringRef ivar_skipped_prefix = @@ -2516,8 +2513,7 @@ bool AppleObjCRuntimeV2::NonPointerISACache::EvaluateNonPointerISA( ObjCISA isa, ObjCISA &ret_isa) { Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_TYPES)); - if (log) - log->Printf("AOCRT::NPI Evalulate(isa = 0x%" PRIx64 ")", (uint64_t)isa); + LLDB_LOGF(log, "AOCRT::NPI Evalulate(isa = 0x%" PRIx64 ")", (uint64_t)isa); if ((isa & ~m_objc_debug_isa_class_mask) == 0) return false; @@ -2543,10 +2539,10 @@ bool AppleObjCRuntimeV2::NonPointerISACache::EvaluateNonPointerISA( // read the count again, and update the cache if the count has been // updated. if (index > m_indexed_isa_cache.size()) { - if (log) - log->Printf("AOCRT::NPI (index = %" PRIu64 - ") exceeds cache (size = %" PRIu64 ")", - (uint64_t)index, (uint64_t)m_indexed_isa_cache.size()); + LLDB_LOGF(log, + "AOCRT::NPI (index = %" PRIu64 + ") exceeds cache (size = %" PRIu64 ")", + (uint64_t)index, (uint64_t)m_indexed_isa_cache.size()); Process *process(m_runtime.GetProcess()); @@ -2561,9 +2557,8 @@ bool AppleObjCRuntimeV2::NonPointerISACache::EvaluateNonPointerISA( if (error.Fail()) return false; - if (log) - log->Printf("AOCRT::NPI (new class count = %" PRIu64 ")", - (uint64_t)objc_indexed_classes_count); + LLDB_LOGF(log, "AOCRT::NPI (new class count = %" PRIu64 ")", + (uint64_t)objc_indexed_classes_count); if (objc_indexed_classes_count > m_indexed_isa_cache.size()) { // Read the class entries we don't have. We should just read all of @@ -2581,9 +2576,8 @@ bool AppleObjCRuntimeV2::NonPointerISACache::EvaluateNonPointerISA( if (error.Fail() || bytes_read != buffer.GetByteSize()) return false; - if (log) - log->Printf("AOCRT::NPI (read new classes count = %" PRIu64 ")", - (uint64_t)num_new_classes); + LLDB_LOGF(log, "AOCRT::NPI (read new classes count = %" PRIu64 ")", + (uint64_t)num_new_classes); // Append the new entries to the existing cache. DataExtractor data(buffer.GetBytes(), buffer.GetByteSize(), @@ -2600,9 +2594,8 @@ bool AppleObjCRuntimeV2::NonPointerISACache::EvaluateNonPointerISA( if (index > m_indexed_isa_cache.size()) return false; - if (log) - log->Printf("AOCRT::NPI Evalulate(ret_isa = 0x%" PRIx64 ")", - (uint64_t)m_indexed_isa_cache[index]); + LLDB_LOGF(log, "AOCRT::NPI Evalulate(ret_isa = 0x%" PRIx64 ")", + (uint64_t)m_indexed_isa_cache[index]); ret_isa = m_indexed_isa_cache[index]; return (ret_isa != 0); // this is a pointer so 0 is not a valid value @@ -2647,8 +2640,9 @@ bool AppleObjCRuntimeV2::GetCFBooleanValuesIfNeeded() { std::function<lldb::addr_t(ConstString)> get_symbol = [this](ConstString sym) -> lldb::addr_t { SymbolContextList sc_list; - if (GetProcess()->GetTarget().GetImages().FindSymbolsWithNameAndType( - sym, lldb::eSymbolTypeData, sc_list) == 1) { + GetProcess()->GetTarget().GetImages().FindSymbolsWithNameAndType( + sym, lldb::eSymbolTypeData, sc_list); + if (sc_list.GetSize() == 1) { SymbolContext sc; sc_list.GetContextAtIndex(0, sc); if (sc.symbol) diff --git a/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCTrampolineHandler.cpp b/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCTrampolineHandler.cpp index b3eb09caa86d..379ef3dca86c 100644 --- a/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCTrampolineHandler.cpp +++ b/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCTrampolineHandler.cpp @@ -543,7 +543,7 @@ bool AppleObjCTrampolineHandler::AppleObjCVTables::RefreshTrampolines( Status error; DataExtractor data; error = argument_values.GetValueAtIndex(0)->GetValueAsData(&exe_ctx, data, - 0, nullptr); + nullptr); lldb::offset_t offset = 0; lldb::addr_t region_addr = data.GetPointer(&offset); @@ -593,7 +593,7 @@ bool AppleObjCTrampolineHandler::AppleObjCVTables::ReadRegions( if (log) { StreamString s; m_regions.back().Dump(s); - log->Printf("Read vtable region: \n%s", s.GetData()); + LLDB_LOGF(log, "Read vtable region: \n%s", s.GetData()); } next_region = m_regions.back().GetNextRegionAddr(); @@ -704,7 +704,7 @@ AppleObjCTrampolineHandler::AppleObjCTrampolineHandler( // step through any method dispatches. Warn to that effect and get out of // here. if (process_sp->CanJIT()) { - process_sp->GetTarget().GetDebugger().GetErrorFile()->Printf( + process_sp->GetTarget().GetDebugger().GetErrorStream().Printf( "Could not find implementation lookup function \"%s\"" " step in through ObjC method dispatch will not work.\n", get_impl_name.AsCString()); @@ -779,25 +779,24 @@ AppleObjCTrampolineHandler::SetupDispatchFunction(Thread &thread, m_lookup_implementation_function_code, eLanguageTypeObjC, g_lookup_implementation_function_name, error)); if (error.Fail()) { - if (log) - log->Printf( - "Failed to get Utility Function for implementation lookup: %s.", - error.AsCString()); + LLDB_LOGF( + log, + "Failed to get Utility Function for implementation lookup: %s.", + error.AsCString()); m_impl_code.reset(); return args_addr; } if (!m_impl_code->Install(diagnostics, exe_ctx)) { if (log) { - log->Printf("Failed to install implementation lookup."); + LLDB_LOGF(log, "Failed to install implementation lookup."); diagnostics.Dump(log); } m_impl_code.reset(); return args_addr; } } else { - if (log) - log->Printf("No method lookup implementation code."); + LLDB_LOGF(log, "No method lookup implementation code."); return LLDB_INVALID_ADDRESS; } @@ -811,10 +810,9 @@ AppleObjCTrampolineHandler::SetupDispatchFunction(Thread &thread, impl_function_caller = m_impl_code->MakeFunctionCaller( clang_void_ptr_type, dispatch_values, thread_sp, error); if (error.Fail()) { - if (log) - log->Printf( - "Error getting function caller for dispatch lookup: \"%s\".", - error.AsCString()); + LLDB_LOGF(log, + "Error getting function caller for dispatch lookup: \"%s\".", + error.AsCString()); return args_addr; } } else { @@ -833,7 +831,7 @@ AppleObjCTrampolineHandler::SetupDispatchFunction(Thread &thread, if (!impl_function_caller->WriteFunctionArguments( exe_ctx, args_addr, dispatch_values, diagnostics)) { if (log) { - log->Printf("Error writing function arguments."); + LLDB_LOGF(log, "Error writing function arguments."); diagnostics.Dump(log); } return args_addr; @@ -934,9 +932,9 @@ AppleObjCTrampolineHandler::GetStepThroughDispatchPlan(Thread &thread, lldb::addr_t obj_addr = argument_values.GetValueAtIndex(obj_index)->GetScalar().ULongLong(); if (obj_addr == 0x0) { - if (log) - log->Printf( - "Asked to step to dispatch to nil object, returning empty plan."); + LLDB_LOGF( + log, + "Asked to step to dispatch to nil object, returning empty plan."); return ret_plan_sp; } @@ -976,13 +974,11 @@ AppleObjCTrampolineHandler::GetStepThroughDispatchPlan(Thread &thread, if (super_value.GetScalar().IsValid()) isa_addr = super_value.GetScalar().ULongLong(); else { - if (log) - log->Printf("Failed to extract the super class value from the " - "class in objc_super."); + LLDB_LOGF(log, "Failed to extract the super class value from the " + "class in objc_super."); } } else { - if (log) - log->Printf("Failed to extract the class value from objc_super."); + LLDB_LOGF(log, "Failed to extract the class value from objc_super."); } } else { // In the objc_msgSendSuper case, we don't get the object @@ -998,8 +994,7 @@ AppleObjCTrampolineHandler::GetStepThroughDispatchPlan(Thread &thread, if (super_value.GetScalar().IsValid()) { isa_addr = super_value.GetScalar().ULongLong(); } else { - if (log) - log->Printf("Failed to extract the class value from objc_super."); + LLDB_LOGF(log, "Failed to extract the class value from objc_super."); } } } else { @@ -1022,8 +1017,7 @@ AppleObjCTrampolineHandler::GetStepThroughDispatchPlan(Thread &thread, if (isa_value.GetScalar().IsValid()) { isa_addr = isa_value.GetScalar().ULongLong(); } else { - if (log) - log->Printf("Failed to extract the isa value from object."); + LLDB_LOGF(log, "Failed to extract the isa value from object."); } } @@ -1033,9 +1027,10 @@ AppleObjCTrampolineHandler::GetStepThroughDispatchPlan(Thread &thread, if (isa_addr != LLDB_INVALID_ADDRESS) { if (log) { - log->Printf("Resolving call for class - 0x%" PRIx64 - " and selector - 0x%" PRIx64, - isa_addr, sel_addr); + LLDB_LOGF(log, + "Resolving call for class - 0x%" PRIx64 + " and selector - 0x%" PRIx64, + isa_addr, sel_addr); } ObjCLanguageRuntime *objc_runtime = ObjCLanguageRuntime::Get(*thread.GetProcess()); @@ -1047,9 +1042,8 @@ AppleObjCTrampolineHandler::GetStepThroughDispatchPlan(Thread &thread, if (impl_addr != LLDB_INVALID_ADDRESS) { // Yup, it was in the cache, so we can run to that address directly. - if (log) - log->Printf("Found implementation address in cache: 0x%" PRIx64, - impl_addr); + LLDB_LOGF(log, "Found implementation address in cache: 0x%" PRIx64, + impl_addr); ret_plan_sp = std::make_shared<ThreadPlanRunToAddress>(thread, impl_addr, stop_others); @@ -1137,7 +1131,7 @@ AppleObjCTrampolineHandler::GetStepThroughDispatchPlan(Thread &thread, if (log) { StreamString s; ret_plan_sp->GetDescription(&s, eDescriptionLevelFull); - log->Printf("Using ObjC step plan: %s.\n", s.GetData()); + LLDB_LOGF(log, "Using ObjC step plan: %s.\n", s.GetData()); } } } diff --git a/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCTypeEncodingParser.cpp b/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCTypeEncodingParser.cpp index 26654e9212b9..6402e80d6f98 100644 --- a/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCTypeEncodingParser.cpp +++ b/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCTypeEncodingParser.cpp @@ -18,7 +18,6 @@ #include <vector> using namespace lldb_private; -using namespace lldb_utility; AppleObjCTypeEncodingParser::AppleObjCTypeEncodingParser( ObjCLanguageRuntime &runtime) @@ -32,16 +31,14 @@ AppleObjCTypeEncodingParser::AppleObjCTypeEncodingParser( .c_str())); } -std::string -AppleObjCTypeEncodingParser::ReadStructName(lldb_utility::StringLexer &type) { +std::string AppleObjCTypeEncodingParser::ReadStructName(StringLexer &type) { StreamString buffer; while (type.HasAtLeast(1) && type.Peek() != '=') buffer.Printf("%c", type.Next()); return buffer.GetString(); } -std::string -AppleObjCTypeEncodingParser::ReadQuotedString(lldb_utility::StringLexer &type) { +std::string AppleObjCTypeEncodingParser::ReadQuotedString(StringLexer &type) { StreamString buffer; while (type.HasAtLeast(1) && type.Peek() != '"') buffer.Printf("%c", type.Next()); @@ -51,8 +48,7 @@ AppleObjCTypeEncodingParser::ReadQuotedString(lldb_utility::StringLexer &type) { return buffer.GetString(); } -uint32_t -AppleObjCTypeEncodingParser::ReadNumber(lldb_utility::StringLexer &type) { +uint32_t AppleObjCTypeEncodingParser::ReadNumber(StringLexer &type) { uint32_t total = 0; while (type.HasAtLeast(1) && isdigit(type.Peek())) total = 10 * total + (type.Next() - '0'); @@ -68,7 +64,7 @@ AppleObjCTypeEncodingParser::StructElement::StructElement() AppleObjCTypeEncodingParser::StructElement AppleObjCTypeEncodingParser::ReadStructElement(clang::ASTContext &ast_ctx, - lldb_utility::StringLexer &type, + StringLexer &type, bool for_expression) { StructElement retval; if (type.NextIf('"')) @@ -81,25 +77,21 @@ AppleObjCTypeEncodingParser::ReadStructElement(clang::ASTContext &ast_ctx, return retval; } -clang::QualType -AppleObjCTypeEncodingParser::BuildStruct(clang::ASTContext &ast_ctx, - lldb_utility::StringLexer &type, - bool for_expression) { +clang::QualType AppleObjCTypeEncodingParser::BuildStruct( + clang::ASTContext &ast_ctx, StringLexer &type, bool for_expression) { return BuildAggregate(ast_ctx, type, for_expression, '{', '}', clang::TTK_Struct); } -clang::QualType -AppleObjCTypeEncodingParser::BuildUnion(clang::ASTContext &ast_ctx, - lldb_utility::StringLexer &type, - bool for_expression) { +clang::QualType AppleObjCTypeEncodingParser::BuildUnion( + clang::ASTContext &ast_ctx, StringLexer &type, bool for_expression) { return BuildAggregate(ast_ctx, type, for_expression, '(', ')', clang::TTK_Union); } clang::QualType AppleObjCTypeEncodingParser::BuildAggregate( - clang::ASTContext &ast_ctx, lldb_utility::StringLexer &type, - bool for_expression, char opener, char closer, uint32_t kind) { + clang::ASTContext &ast_ctx, StringLexer &type, bool for_expression, + char opener, char closer, uint32_t kind) { if (!type.NextIf(opener)) return clang::QualType(); std::string name(ReadStructName(type)); @@ -149,8 +141,9 @@ clang::QualType AppleObjCTypeEncodingParser::BuildAggregate( } ClangASTContext::AddFieldToRecordType( union_type, element.name.c_str(), - CompilerType(&ast_ctx, element.type), lldb::eAccessPublic, - element.bitfield); + CompilerType(ClangASTContext::GetASTContext(&ast_ctx), + element.type.getAsOpaquePtr()), + lldb::eAccessPublic, element.bitfield); ++count; } ClangASTContext::CompleteTagDeclarationDefinition(union_type); @@ -158,10 +151,8 @@ clang::QualType AppleObjCTypeEncodingParser::BuildAggregate( return ClangUtil::GetQualType(union_type); } -clang::QualType -AppleObjCTypeEncodingParser::BuildArray(clang::ASTContext &ast_ctx, - lldb_utility::StringLexer &type, - bool for_expression) { +clang::QualType AppleObjCTypeEncodingParser::BuildArray( + clang::ASTContext &ast_ctx, StringLexer &type, bool for_expression) { if (!type.NextIf('[')) return clang::QualType(); uint32_t size = ReadNumber(type); @@ -172,7 +163,9 @@ AppleObjCTypeEncodingParser::BuildArray(clang::ASTContext &ast_ctx, if (!lldb_ctx) return clang::QualType(); CompilerType array_type(lldb_ctx->CreateArrayType( - CompilerType(&ast_ctx, element_type), size, false)); + CompilerType(ClangASTContext::GetASTContext(&ast_ctx), + element_type.getAsOpaquePtr()), + size, false)); return ClangUtil::GetQualType(array_type); } @@ -182,8 +175,7 @@ AppleObjCTypeEncodingParser::BuildArray(clang::ASTContext &ast_ctx, // consume but ignore the type info and always return an 'id'; if anything, // dynamic typing will resolve things for us anyway clang::QualType AppleObjCTypeEncodingParser::BuildObjCObjectPointerType( - clang::ASTContext &ast_ctx, lldb_utility::StringLexer &type, - bool for_expression) { + clang::ASTContext &ast_ctx, StringLexer &type, bool for_expression) { if (!type.NextIf('@')) return clang::QualType(); @@ -375,7 +367,8 @@ CompilerType AppleObjCTypeEncodingParser::RealizeType( if (name && name[0]) { StringLexer lexer(name); clang::QualType qual_type = BuildType(ast_ctx, lexer, for_expression); - return CompilerType(&ast_ctx, qual_type); + return CompilerType(ClangASTContext::GetASTContext(&ast_ctx), + qual_type.getAsOpaquePtr()); } return CompilerType(); } diff --git a/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCTypeEncodingParser.h b/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCTypeEncodingParser.h index e576e8f283f2..590bc4ba9eae 100644 --- a/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCTypeEncodingParser.h +++ b/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCTypeEncodingParser.h @@ -15,12 +15,8 @@ #include "Plugins/LanguageRuntime/ObjC/ObjCLanguageRuntime.h" -namespace lldb_utility { -class StringLexer; -} - namespace lldb_private { - +class StringLexer; class AppleObjCTypeEncodingParser : public ObjCLanguageRuntime::EncodingToType { public: AppleObjCTypeEncodingParser(ObjCLanguageRuntime &runtime); @@ -39,41 +35,35 @@ private: ~StructElement() = default; }; - clang::QualType BuildType(clang::ASTContext &ast_ctx, - lldb_utility::StringLexer &type, + clang::QualType BuildType(clang::ASTContext &ast_ctx, StringLexer &type, bool for_expression, uint32_t *bitfield_bit_size = nullptr); - clang::QualType BuildStruct(clang::ASTContext &ast_ctx, - lldb_utility::StringLexer &type, + clang::QualType BuildStruct(clang::ASTContext &ast_ctx, StringLexer &type, bool for_expression); - clang::QualType BuildAggregate(clang::ASTContext &ast_ctx, - lldb_utility::StringLexer &type, + clang::QualType BuildAggregate(clang::ASTContext &ast_ctx, StringLexer &type, bool for_expression, char opener, char closer, uint32_t kind); - clang::QualType BuildUnion(clang::ASTContext &ast_ctx, - lldb_utility::StringLexer &type, + clang::QualType BuildUnion(clang::ASTContext &ast_ctx, StringLexer &type, bool for_expression); - clang::QualType BuildArray(clang::ASTContext &ast_ctx, - lldb_utility::StringLexer &type, + clang::QualType BuildArray(clang::ASTContext &ast_ctx, StringLexer &type, bool for_expression); - std::string ReadStructName(lldb_utility::StringLexer &type); + std::string ReadStructName(StringLexer &type); - StructElement ReadStructElement(clang::ASTContext &ast_ctx, - lldb_utility::StringLexer &type, + StructElement ReadStructElement(clang::ASTContext &ast_ctx, StringLexer &type, bool for_expression); clang::QualType BuildObjCObjectPointerType(clang::ASTContext &ast_ctx, - lldb_utility::StringLexer &type, + StringLexer &type, bool for_expression); - uint32_t ReadNumber(lldb_utility::StringLexer &type); + uint32_t ReadNumber(StringLexer &type); - std::string ReadQuotedString(lldb_utility::StringLexer &type); + std::string ReadQuotedString(StringLexer &type); ObjCLanguageRuntime &m_runtime; }; diff --git a/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleThreadPlanStepThroughObjCTrampoline.cpp b/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleThreadPlanStepThroughObjCTrampoline.cpp index d18435c9c6db..af630eee7265 100644 --- a/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleThreadPlanStepThroughObjCTrampoline.cpp +++ b/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleThreadPlanStepThroughObjCTrampoline.cpp @@ -141,17 +141,15 @@ bool AppleThreadPlanStepThroughObjCTrampoline::ShouldStop(Event *event_ptr) { target_so_addr.SetOpcodeLoadAddress(target_addr, exc_ctx.GetTargetPtr()); Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_STEP)); if (target_addr == 0) { - if (log) - log->Printf("Got target implementation of 0x0, stopping."); + LLDB_LOGF(log, "Got target implementation of 0x0, stopping."); SetPlanComplete(); return true; } if (m_trampoline_handler->AddrIsMsgForward(target_addr)) { - if (log) - log->Printf( - "Implementation lookup returned msgForward function: 0x%" PRIx64 - ", stopping.", - target_addr); + LLDB_LOGF(log, + "Implementation lookup returned msgForward function: 0x%" PRIx64 + ", stopping.", + target_addr); SymbolContext sc = m_thread.GetStackFrameAtIndex(0)->GetSymbolContext( eSymbolContextEverything); @@ -167,18 +165,17 @@ bool AppleThreadPlanStepThroughObjCTrampoline::ShouldStop(Event *event_ptr) { return false; } - if (log) - log->Printf("Running to ObjC method implementation: 0x%" PRIx64, - target_addr); + LLDB_LOGF(log, "Running to ObjC method implementation: 0x%" PRIx64, + target_addr); ObjCLanguageRuntime *objc_runtime = ObjCLanguageRuntime::Get(*GetThread().GetProcess()); assert(objc_runtime != nullptr); objc_runtime->AddToMethodCache(m_isa_addr, m_sel_addr, target_addr); - if (log) - log->Printf("Adding {isa-addr=0x%" PRIx64 ", sel-addr=0x%" PRIx64 - "} = addr=0x%" PRIx64 " to cache.", - m_isa_addr, m_sel_addr, target_addr); + LLDB_LOGF(log, + "Adding {isa-addr=0x%" PRIx64 ", sel-addr=0x%" PRIx64 + "} = addr=0x%" PRIx64 " to cache.", + m_isa_addr, m_sel_addr, target_addr); // Extract the target address from the value: diff --git a/source/Plugins/LanguageRuntime/ObjC/ObjCLanguageRuntime.cpp b/source/Plugins/LanguageRuntime/ObjC/ObjCLanguageRuntime.cpp index 631c15c46ce8..87ae4c2c6c48 100644 --- a/source/Plugins/LanguageRuntime/ObjC/ObjCLanguageRuntime.cpp +++ b/source/Plugins/LanguageRuntime/ObjC/ObjCLanguageRuntime.cpp @@ -64,9 +64,10 @@ void ObjCLanguageRuntime::AddToMethodCache(lldb::addr_t class_addr, lldb::addr_t impl_addr) { Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_STEP)); if (log) { - log->Printf("Caching: class 0x%" PRIx64 " selector 0x%" PRIx64 - " implementation 0x%" PRIx64 ".", - class_addr, selector, impl_addr); + LLDB_LOGF(log, + "Caching: class 0x%" PRIx64 " selector 0x%" PRIx64 + " implementation 0x%" PRIx64 ".", + class_addr, selector, impl_addr); } m_impl_cache.insert(std::pair<ClassAndSel, lldb::addr_t>( ClassAndSel(class_addr, selector), impl_addr)); @@ -102,8 +103,8 @@ ObjCLanguageRuntime::LookupInCompleteClassCache(ConstString &name) { const ModuleList &modules = m_process->GetTarget().GetImages(); SymbolContextList sc_list; - const size_t matching_symbols = - modules.FindSymbolsWithNameAndType(name, eSymbolTypeObjCClass, sc_list); + modules.FindSymbolsWithNameAndType(name, eSymbolTypeObjCClass, sc_list); + const size_t matching_symbols = sc_list.GetSize(); if (matching_symbols) { SymbolContext sc; @@ -120,20 +121,17 @@ ObjCLanguageRuntime::LookupInCompleteClassCache(ConstString &name) { TypeList types; llvm::DenseSet<SymbolFile *> searched_symbol_files; - const uint32_t num_types = module_sp->FindTypes( - name, exact_match, max_matches, searched_symbol_files, types); - - if (num_types) { - uint32_t i; - for (i = 0; i < num_types; ++i) { - TypeSP type_sp(types.GetTypeAtIndex(i)); - - if (ClangASTContext::IsObjCObjectOrInterfaceType( - type_sp->GetForwardCompilerType())) { - if (type_sp->IsCompleteObjCClass()) { - m_complete_class_cache[name] = type_sp; - return type_sp; - } + module_sp->FindTypes(name, exact_match, max_matches, searched_symbol_files, + types); + + for (uint32_t i = 0; i < types.GetSize(); ++i) { + TypeSP type_sp(types.GetTypeAtIndex(i)); + + if (ClangASTContext::IsObjCObjectOrInterfaceType( + type_sp->GetForwardCompilerType())) { + if (type_sp->IsCompleteObjCClass()) { + m_complete_class_cache[name] = type_sp; + return type_sp; } } } diff --git a/source/Plugins/LanguageRuntime/ObjC/ObjCLanguageRuntime.h b/source/Plugins/LanguageRuntime/ObjC/ObjCLanguageRuntime.h index 1925c78ed342..39acd6e9f268 100644 --- a/source/Plugins/LanguageRuntime/ObjC/ObjCLanguageRuntime.h +++ b/source/Plugins/LanguageRuntime/ObjC/ObjCLanguageRuntime.h @@ -17,6 +17,7 @@ #include "llvm/Support/Casting.h" #include "lldb/Breakpoint/BreakpointPrecondition.h" +#include "lldb/Core/ClangForward.h" #include "lldb/Core/PluginInterface.h" #include "lldb/Core/ThreadSafeDenseMap.h" #include "lldb/Symbol/CompilerType.h" diff --git a/source/Plugins/LanguageRuntime/RenderScript/RenderScriptRuntime/RenderScriptExpressionOpts.cpp b/source/Plugins/LanguageRuntime/RenderScript/RenderScriptRuntime/RenderScriptExpressionOpts.cpp index 60549663db66..b396781e6726 100644 --- a/source/Plugins/LanguageRuntime/RenderScript/RenderScriptRuntime/RenderScriptExpressionOpts.cpp +++ b/source/Plugins/LanguageRuntime/RenderScript/RenderScriptRuntime/RenderScriptExpressionOpts.cpp @@ -140,10 +140,10 @@ bool RenderScriptRuntimeModulePass::runOnModule(llvm::Module &module) { // We've been using a triple and datalayout of some ARM variant all along, // so we need to let the backend know that this is no longer the case. if (log) { - log->Printf("%s - Changing RS target triple to '%s'", __FUNCTION__, - real_triple.str().c_str()); - log->Printf( - "%s - Changing RS datalayout to '%s'", __FUNCTION__, + LLDB_LOGF(log, "%s - Changing RS target triple to '%s'", __FUNCTION__, + real_triple.str().c_str()); + LLDB_LOGF( + log, "%s - Changing RS datalayout to '%s'", __FUNCTION__, target_machine->createDataLayout().getStringRepresentation().c_str()); } module.setTargetTriple(real_triple); diff --git a/source/Plugins/LanguageRuntime/RenderScript/RenderScriptRuntime/RenderScriptRuntime.cpp b/source/Plugins/LanguageRuntime/RenderScript/RenderScriptRuntime/RenderScriptRuntime.cpp index c9cd34cf379d..5200749d759f 100644 --- a/source/Plugins/LanguageRuntime/RenderScript/RenderScriptRuntime/RenderScriptRuntime.cpp +++ b/source/Plugins/LanguageRuntime/RenderScript/RenderScriptRuntime/RenderScriptRuntime.cpp @@ -138,9 +138,8 @@ bool GetArgsX86(const GetArgsCtx &ctx, ArgItem *arg_list, size_t num_args) { size_t read = ctx.process->ReadMemory(sp, &arg.value, sizeof(uint32_t), err); if (read != arg_size || !err.Success()) { - if (log) - log->Printf("%s - error reading argument: %" PRIu64 " '%s'", - __FUNCTION__, uint64_t(i), err.AsCString()); + LLDB_LOGF(log, "%s - error reading argument: %" PRIu64 " '%s'", + __FUNCTION__, uint64_t(i), err.AsCString()); return false; } } @@ -173,8 +172,7 @@ bool GetArgsX86_64(GetArgsCtx &ctx, ArgItem *arg_list, size_t num_args) { // check the stack alignment was correct (16 byte aligned) if ((sp & 0xf) != 0x0) { - if (log) - log->Printf("%s - stack misaligned", __FUNCTION__); + LLDB_LOGF(log, "%s - stack misaligned", __FUNCTION__); return false; } @@ -213,9 +211,8 @@ bool GetArgsX86_64(GetArgsCtx &ctx, ArgItem *arg_list, size_t num_args) { } // fail if we couldn't read this argument if (!success) { - if (log) - log->Printf("%s - error reading argument: %" PRIu64 ", reason: %s", - __FUNCTION__, uint64_t(i), err.AsCString("n/a")); + LLDB_LOGF(log, "%s - error reading argument: %" PRIu64 ", reason: %s", + __FUNCTION__, uint64_t(i), err.AsCString("n/a")); return false; } } @@ -258,9 +255,8 @@ bool GetArgsArm(GetArgsCtx &ctx, ArgItem *arg_list, size_t num_args) { } // fail if we couldn't read this argument if (!success) { - if (log) - log->Printf("%s - error reading argument: %" PRIu64 ", reason: %s", - __FUNCTION__, uint64_t(i), err.AsCString("n/a")); + LLDB_LOGF(log, "%s - error reading argument: %" PRIu64 ", reason: %s", + __FUNCTION__, uint64_t(i), err.AsCString("n/a")); return false; } } @@ -285,15 +281,13 @@ bool GetArgsAarch64(GetArgsCtx &ctx, ArgItem *arg_list, size_t num_args) { } // arguments passed on the stack else { - if (log) - log->Printf("%s - reading arguments spilled to stack not implemented", - __FUNCTION__); + LLDB_LOGF(log, "%s - reading arguments spilled to stack not implemented", + __FUNCTION__); } // fail if we couldn't read this argument if (!success) { - if (log) - log->Printf("%s - error reading argument: %" PRIu64, __FUNCTION__, - uint64_t(i)); + LLDB_LOGF(log, "%s - error reading argument: %" PRIu64, __FUNCTION__, + uint64_t(i)); return false; } } @@ -337,9 +331,8 @@ bool GetArgsMipsel(GetArgsCtx &ctx, ArgItem *arg_list, size_t num_args) { } // fail if we couldn't read this argument if (!success) { - if (log) - log->Printf("%s - error reading argument: %" PRIu64 ", reason: %s", - __FUNCTION__, uint64_t(i), err.AsCString("n/a")); + LLDB_LOGF(log, "%s - error reading argument: %" PRIu64 ", reason: %s", + __FUNCTION__, uint64_t(i), err.AsCString("n/a")); return false; } } @@ -385,9 +378,8 @@ bool GetArgsMips64el(GetArgsCtx &ctx, ArgItem *arg_list, size_t num_args) { } // fail if we couldn't read this argument if (!success) { - if (log) - log->Printf("%s - error reading argument: %" PRIu64 ", reason: %s", - __FUNCTION__, uint64_t(i), err.AsCString("n/a")); + LLDB_LOGF(log, "%s - error reading argument: %" PRIu64 ", reason: %s", + __FUNCTION__, uint64_t(i), err.AsCString("n/a")); return false; } } @@ -399,8 +391,7 @@ bool GetArgs(ExecutionContext &exe_ctx, ArgItem *arg_list, size_t num_args) { // verify that we have a target if (!exe_ctx.GetTargetPtr()) { - if (log) - log->Printf("%s - invalid target", __FUNCTION__); + LLDB_LOGF(log, "%s - invalid target", __FUNCTION__); return false; } @@ -430,9 +421,8 @@ bool GetArgs(ExecutionContext &exe_ctx, ArgItem *arg_list, size_t num_args) { default: // unsupported architecture if (log) { - log->Printf( - "%s - architecture not supported: '%s'", __FUNCTION__, - exe_ctx.GetTargetRef().GetArchitecture().GetArchitectureName()); + LLDB_LOGF(log, "%s - architecture not supported: '%s'", __FUNCTION__, + exe_ctx.GetTargetRef().GetArchitecture().GetArchitectureName()); } return false; } @@ -452,28 +442,20 @@ bool ParseCoordinate(llvm::StringRef coord_s, RSCoordinate &coord) { // elements fails the contents of &coord are undefined and `false` is // returned, `true` otherwise - RegularExpression regex; - RegularExpression::Match regex_match(3); - - bool matched = false; - if (regex.Compile(llvm::StringRef("^([0-9]+),([0-9]+),([0-9]+)$")) && - regex.Execute(coord_s, ®ex_match)) - matched = true; - else if (regex.Compile(llvm::StringRef("^([0-9]+),([0-9]+)$")) && - regex.Execute(coord_s, ®ex_match)) - matched = true; - else if (regex.Compile(llvm::StringRef("^([0-9]+)$")) && - regex.Execute(coord_s, ®ex_match)) - matched = true; - - if (!matched) + llvm::SmallVector<llvm::StringRef, 4> matches; + + if (!RegularExpression("^([0-9]+),([0-9]+),([0-9]+)$") + .Execute(coord_s, &matches) && + !RegularExpression("^([0-9]+),([0-9]+)$").Execute(coord_s, &matches) && + !RegularExpression("^([0-9]+)$").Execute(coord_s, &matches)) return false; - auto get_index = [&](int idx, uint32_t &i) -> bool { + auto get_index = [&](size_t idx, uint32_t &i) -> bool { std::string group; errno = 0; - if (regex_match.GetMatchAtIndex(coord_s.str().c_str(), idx + 1, group)) - return !llvm::StringRef(group).getAsInteger<uint32_t>(10, i); + if (idx + 1 < matches.size()) { + return !llvm::StringRef(matches[idx + 1]).getAsInteger<uint32_t>(10, i); + } return true; }; @@ -492,9 +474,8 @@ bool SkipPrologue(lldb::ModuleSP &module, Address &addr) { ConstString name = sc.GetFunctionName(); if (offset) addr.Slide(offset); - if (log) - log->Printf("%s: Prologue offset for %s is %" PRIu32, __FUNCTION__, - name.AsCString(), offset); + LLDB_LOGF(log, "%s: Prologue offset for %s is %" PRIu32, __FUNCTION__, + name.AsCString(), offset); } return true; } else @@ -809,7 +790,7 @@ RenderScriptRuntime::CreateInstance(Process *process, // symbol. Searcher::CallbackReturn RSBreakpointResolver::SearchCallback(SearchFilter &filter, - SymbolContext &context, Address *, bool) { + SymbolContext &context, Address *) { ModuleSP module = context.module_sp; if (!module || !IsRenderScriptScriptModule(module)) @@ -839,7 +820,7 @@ RSBreakpointResolver::SearchCallback(SearchFilter &filter, Searcher::CallbackReturn RSReduceBreakpointResolver::SearchCallback(lldb_private::SearchFilter &filter, lldb_private::SymbolContext &context, - Address *, bool) { + Address *) { // We need to have access to the list of reductions currently parsed, as // reduce names don't actually exist as symbols in a module. They are only // identifiable by parsing the .rs.info packet, or finding the expand symbol. @@ -884,14 +865,13 @@ RSReduceBreakpointResolver::SearchCallback(lldb_private::SearchFilter &filter, if (filter.AddressPasses(address)) { bool new_bp; if (!SkipPrologue(module, address)) { - if (log) - log->Printf("%s: Error trying to skip prologue", __FUNCTION__); + LLDB_LOGF(log, "%s: Error trying to skip prologue", __FUNCTION__); } m_breakpoint->AddLocation(address, &new_bp); - if (log) - log->Printf("%s: %s reduction breakpoint on %s in %s", __FUNCTION__, - new_bp ? "new" : "existing", kernel_name.GetCString(), - address.GetModule()->GetFileSpec().GetCString()); + LLDB_LOGF(log, "%s: %s reduction breakpoint on %s in %s", + __FUNCTION__, new_bp ? "new" : "existing", + kernel_name.GetCString(), + address.GetModule()->GetFileSpec().GetCString()); } } } @@ -900,8 +880,7 @@ RSReduceBreakpointResolver::SearchCallback(lldb_private::SearchFilter &filter, } Searcher::CallbackReturn RSScriptGroupBreakpointResolver::SearchCallback( - SearchFilter &filter, SymbolContext &context, Address *addr, - bool containing) { + SearchFilter &filter, SymbolContext &context, Address *addr) { if (!m_breakpoint) return eCallbackReturnContinue; @@ -920,48 +899,43 @@ Searcher::CallbackReturn RSScriptGroupBreakpointResolver::SearchCallback( for (auto &name : names) { const RSScriptGroupDescriptorSP sg = FindScriptGroup(ConstString(name)); if (!sg) { - if (log) - log->Printf("%s: could not find script group for %s", __FUNCTION__, - name.c_str()); + LLDB_LOGF(log, "%s: could not find script group for %s", __FUNCTION__, + name.c_str()); continue; } - if (log) - log->Printf("%s: Found ScriptGroup for %s", __FUNCTION__, name.c_str()); + LLDB_LOGF(log, "%s: Found ScriptGroup for %s", __FUNCTION__, name.c_str()); for (const RSScriptGroupDescriptor::Kernel &k : sg->m_kernels) { if (log) { - log->Printf("%s: Adding breakpoint for %s", __FUNCTION__, - k.m_name.AsCString()); - log->Printf("%s: Kernel address 0x%" PRIx64, __FUNCTION__, k.m_addr); + LLDB_LOGF(log, "%s: Adding breakpoint for %s", __FUNCTION__, + k.m_name.AsCString()); + LLDB_LOGF(log, "%s: Kernel address 0x%" PRIx64, __FUNCTION__, k.m_addr); } const lldb_private::Symbol *sym = module->FindFirstSymbolWithNameAndType(k.m_name, eSymbolTypeCode); if (!sym) { - if (log) - log->Printf("%s: Unable to find symbol for %s", __FUNCTION__, - k.m_name.AsCString()); + LLDB_LOGF(log, "%s: Unable to find symbol for %s", __FUNCTION__, + k.m_name.AsCString()); continue; } if (log) { - log->Printf("%s: Found symbol name is %s", __FUNCTION__, - sym->GetName().AsCString()); + LLDB_LOGF(log, "%s: Found symbol name is %s", __FUNCTION__, + sym->GetName().AsCString()); } auto address = sym->GetAddress(); if (!SkipPrologue(module, address)) { - if (log) - log->Printf("%s: Error trying to skip prologue", __FUNCTION__); + LLDB_LOGF(log, "%s: Error trying to skip prologue", __FUNCTION__); } bool new_bp; m_breakpoint->AddLocation(address, &new_bp); - if (log) - log->Printf("%s: Placed %sbreakpoint on %s", __FUNCTION__, - new_bp ? "new " : "", k.m_name.AsCString()); + LLDB_LOGF(log, "%s: Placed %sbreakpoint on %s", __FUNCTION__, + new_bp ? "new " : "", k.m_name.AsCString()); // exit after placing the first breakpoint if we do not intend to stop on // all kernels making up this script group @@ -1136,8 +1110,7 @@ void RenderScriptRuntime::HookCallback(RuntimeHook *hook, ExecutionContext &exe_ctx) { Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_LANGUAGE)); - if (log) - log->Printf("%s - '%s'", __FUNCTION__, hook->defn->name); + LLDB_LOGF(log, "%s - '%s'", __FUNCTION__, hook->defn->name); if (hook->defn->grabber) { (this->*(hook->defn->grabber))(hook, exe_ctx); @@ -1163,19 +1136,18 @@ void RenderScriptRuntime::CaptureDebugHintScriptGroup2( }}; if (!GetArgs(context, args.data(), args.size())) { - if (log) - log->Printf("%s - Error while reading the function parameters", - __FUNCTION__); + LLDB_LOGF(log, "%s - Error while reading the function parameters", + __FUNCTION__); return; } else if (log) { - log->Printf("%s - groupName : 0x%" PRIx64, __FUNCTION__, - addr_t(args[eGroupName])); - log->Printf("%s - groupNameSize: %" PRIu64, __FUNCTION__, - uint64_t(args[eGroupNameSize])); - log->Printf("%s - kernel : 0x%" PRIx64, __FUNCTION__, - addr_t(args[eKernel])); - log->Printf("%s - kernelCount : %" PRIu64, __FUNCTION__, - uint64_t(args[eKernelCount])); + LLDB_LOGF(log, "%s - groupName : 0x%" PRIx64, __FUNCTION__, + addr_t(args[eGroupName])); + LLDB_LOGF(log, "%s - groupNameSize: %" PRIu64, __FUNCTION__, + uint64_t(args[eGroupNameSize])); + LLDB_LOGF(log, "%s - kernel : 0x%" PRIx64, __FUNCTION__, + addr_t(args[eKernel])); + LLDB_LOGF(log, "%s - kernelCount : %" PRIu64, __FUNCTION__, + uint64_t(args[eKernelCount])); } // parse script group name @@ -1187,12 +1159,10 @@ void RenderScriptRuntime::CaptureDebugHintScriptGroup2( m_process->ReadMemory(addr_t(args[eGroupName]), buffer.get(), len, err); buffer.get()[len] = '\0'; if (!err.Success()) { - if (log) - log->Printf("Error reading scriptgroup name from target"); + LLDB_LOGF(log, "Error reading scriptgroup name from target"); return; } else { - if (log) - log->Printf("Extracted scriptgroup name %s", buffer.get()); + LLDB_LOGF(log, "Extracted scriptgroup name %s", buffer.get()); } // write back the script group name group_name.SetCString(buffer.get()); @@ -1214,9 +1184,8 @@ void RenderScriptRuntime::CaptureDebugHintScriptGroup2( m_scriptGroups.push_back(group); } else { // already have this script group - if (log) - log->Printf("Attempt to add duplicate script group %s", - group_name.AsCString()); + LLDB_LOGF(log, "Attempt to add duplicate script group %s", + group_name.AsCString()); return; } } @@ -1234,21 +1203,18 @@ void RenderScriptRuntime::CaptureDebugHintScriptGroup2( size_t read = m_process->ReadMemory(ptr_addr, &kernel_addr, target_ptr_size, err); if (!err.Success() || read != target_ptr_size) { - if (log) - log->Printf("Error parsing kernel address %" PRIu64 " in script group", - i); + LLDB_LOGF(log, "Error parsing kernel address %" PRIu64 " in script group", + i); return; } - if (log) - log->Printf("Extracted scriptgroup kernel address - 0x%" PRIx64, - kernel_addr); + LLDB_LOGF(log, "Extracted scriptgroup kernel address - 0x%" PRIx64, + kernel_addr); kernel.m_addr = kernel_addr; // try to resolve the associated kernel name if (!ResolveKernelName(kernel.m_addr, kernel.m_name)) { - if (log) - log->Printf("Parsed scriptgroup kernel %" PRIu64 " - 0x%" PRIx64, i, - kernel_addr); + LLDB_LOGF(log, "Parsed scriptgroup kernel %" PRIu64 " - 0x%" PRIx64, i, + kernel_addr); return; } @@ -1261,9 +1227,8 @@ void RenderScriptRuntime::CaptureDebugHintScriptGroup2( // verify this function is a valid kernel if (IsKnownKernel(base_kernel)) { kernel.m_name = base_kernel; - if (log) - log->Printf("%s - found non expand version '%s'", __FUNCTION__, - base_kernel.GetCString()); + LLDB_LOGF(log, "%s - found non expand version '%s'", __FUNCTION__, + base_kernel.GetCString()); } } } @@ -1276,15 +1241,13 @@ void RenderScriptRuntime::CaptureDebugHintScriptGroup2( Target &target = m_process->GetTarget(); const BreakpointList &list = target.GetBreakpointList(); const size_t num_breakpoints = list.GetSize(); - if (log) - log->Printf("Resolving %zu breakpoints", num_breakpoints); + LLDB_LOGF(log, "Resolving %zu breakpoints", num_breakpoints); for (size_t i = 0; i < num_breakpoints; ++i) { const BreakpointSP bp = list.GetBreakpointAtIndex(i); if (bp) { if (bp->MatchesName(group_name.AsCString())) { - if (log) - log->Printf("Found breakpoint with name %s", - group_name.AsCString()); + LLDB_LOGF(log, "Found breakpoint with name %s", + group_name.AsCString()); bp->ResolveBreakpoint(); } } @@ -1322,9 +1285,8 @@ void RenderScriptRuntime::CaptureScriptInvokeForEachMulti( bool success = GetArgs(exe_ctx, &args[0], args.size()); if (!success) { - if (log) - log->Printf("%s - Error while reading the function parameters", - __FUNCTION__); + LLDB_LOGF(log, "%s - Error while reading the function parameters", + __FUNCTION__); return; } @@ -1342,10 +1304,9 @@ void RenderScriptRuntime::CaptureScriptInvokeForEachMulti( uint64_t result = 0; size_t read = m_process->ReadMemory(addr, &result, target_ptr_size, err); if (read != target_ptr_size || !err.Success()) { - if (log) - log->Printf( - "%s - Error while reading allocation list argument %" PRIu64, - __FUNCTION__, i); + LLDB_LOGF(log, + "%s - Error while reading allocation list argument %" PRIu64, + __FUNCTION__, i); } else { allocs.push_back(result); } @@ -1375,8 +1336,8 @@ void RenderScriptRuntime::CaptureScriptInvokeForEachMulti( if (log) { if (alloc->context.isValid() && *alloc->context.get() != addr_t(args[eRsContext])) - log->Printf("%s - Allocation used by multiple contexts", - __FUNCTION__); + LLDB_LOGF(log, "%s - Allocation used by multiple contexts", + __FUNCTION__); } alloc->context = addr_t(args[eRsContext]); } @@ -1388,7 +1349,7 @@ void RenderScriptRuntime::CaptureScriptInvokeForEachMulti( if (log) { if (script->context.isValid() && *script->context.get() != addr_t(args[eRsContext])) - log->Printf("%s - Script used by multiple contexts", __FUNCTION__); + LLDB_LOGF(log, "%s - Script used by multiple contexts", __FUNCTION__); } script->context = addr_t(args[eRsContext]); } @@ -1416,26 +1377,26 @@ void RenderScriptRuntime::CaptureSetGlobalVar(RuntimeHook *hook, bool success = GetArgs(context, &args[0], args.size()); if (!success) { - if (log) - log->Printf("%s - error reading the function parameters.", __FUNCTION__); + LLDB_LOGF(log, "%s - error reading the function parameters.", __FUNCTION__); return; } if (log) { - log->Printf("%s - 0x%" PRIx64 ",0x%" PRIx64 " slot %" PRIu64 " = 0x%" PRIx64 - ":%" PRIu64 "bytes.", - __FUNCTION__, uint64_t(args[eRsContext]), - uint64_t(args[eRsScript]), uint64_t(args[eRsId]), - uint64_t(args[eRsData]), uint64_t(args[eRsLength])); + LLDB_LOGF(log, + "%s - 0x%" PRIx64 ",0x%" PRIx64 " slot %" PRIu64 " = 0x%" PRIx64 + ":%" PRIu64 "bytes.", + __FUNCTION__, uint64_t(args[eRsContext]), + uint64_t(args[eRsScript]), uint64_t(args[eRsId]), + uint64_t(args[eRsData]), uint64_t(args[eRsLength])); addr_t script_addr = addr_t(args[eRsScript]); if (m_scriptMappings.find(script_addr) != m_scriptMappings.end()) { auto rsm = m_scriptMappings[script_addr]; if (uint64_t(args[eRsId]) < rsm->m_globals.size()) { auto rsg = rsm->m_globals[uint64_t(args[eRsId])]; - log->Printf("%s - Setting of '%s' within '%s' inferred", __FUNCTION__, - rsg.m_name.AsCString(), - rsm->m_module->GetFileSpec().GetFilename().AsCString()); + LLDB_LOGF(log, "%s - Setting of '%s' within '%s' inferred", + __FUNCTION__, rsg.m_name.AsCString(), + rsm->m_module->GetFileSpec().GetFilename().AsCString()); } } } @@ -1455,16 +1416,14 @@ void RenderScriptRuntime::CaptureAllocationInit(RuntimeHook *hook, bool success = GetArgs(exe_ctx, &args[0], args.size()); if (!success) { - if (log) - log->Printf("%s - error while reading the function parameters", - __FUNCTION__); + LLDB_LOGF(log, "%s - error while reading the function parameters", + __FUNCTION__); return; } - if (log) - log->Printf("%s - 0x%" PRIx64 ",0x%" PRIx64 ",0x%" PRIx64 " .", - __FUNCTION__, uint64_t(args[eRsContext]), - uint64_t(args[eRsAlloc]), uint64_t(args[eRsForceZero])); + LLDB_LOGF(log, "%s - 0x%" PRIx64 ",0x%" PRIx64 ",0x%" PRIx64 " .", + __FUNCTION__, uint64_t(args[eRsContext]), uint64_t(args[eRsAlloc]), + uint64_t(args[eRsForceZero])); AllocationDetails *alloc = CreateAllocation(uint64_t(args[eRsAlloc])); if (alloc) @@ -1487,29 +1446,25 @@ void RenderScriptRuntime::CaptureAllocationDestroy(RuntimeHook *hook, bool success = GetArgs(exe_ctx, &args[0], args.size()); if (!success) { - if (log) - log->Printf("%s - error while reading the function parameters.", - __FUNCTION__); + LLDB_LOGF(log, "%s - error while reading the function parameters.", + __FUNCTION__); return; } - if (log) - log->Printf("%s - 0x%" PRIx64 ", 0x%" PRIx64 ".", __FUNCTION__, - uint64_t(args[eRsContext]), uint64_t(args[eRsAlloc])); + LLDB_LOGF(log, "%s - 0x%" PRIx64 ", 0x%" PRIx64 ".", __FUNCTION__, + uint64_t(args[eRsContext]), uint64_t(args[eRsAlloc])); for (auto iter = m_allocations.begin(); iter != m_allocations.end(); ++iter) { auto &allocation_up = *iter; // get the unique pointer if (allocation_up->address.isValid() && *allocation_up->address.get() == addr_t(args[eRsAlloc])) { m_allocations.erase(iter); - if (log) - log->Printf("%s - deleted allocation entry.", __FUNCTION__); + LLDB_LOGF(log, "%s - deleted allocation entry.", __FUNCTION__); return; } } - if (log) - log->Printf("%s - couldn't find destroyed allocation.", __FUNCTION__); + LLDB_LOGF(log, "%s - couldn't find destroyed allocation.", __FUNCTION__); } void RenderScriptRuntime::CaptureScriptInit(RuntimeHook *hook, @@ -1526,32 +1481,28 @@ void RenderScriptRuntime::CaptureScriptInit(RuntimeHook *hook, ArgItem{ArgItem::ePointer, 0}, ArgItem{ArgItem::ePointer, 0}}}; bool success = GetArgs(exe_ctx, &args[0], args.size()); if (!success) { - if (log) - log->Printf("%s - error while reading the function parameters.", - __FUNCTION__); + LLDB_LOGF(log, "%s - error while reading the function parameters.", + __FUNCTION__); return; } std::string res_name; process->ReadCStringFromMemory(addr_t(args[eRsResNamePtr]), res_name, err); if (err.Fail()) { - if (log) - log->Printf("%s - error reading res_name: %s.", __FUNCTION__, - err.AsCString()); + LLDB_LOGF(log, "%s - error reading res_name: %s.", __FUNCTION__, + err.AsCString()); } std::string cache_dir; process->ReadCStringFromMemory(addr_t(args[eRsCachedDirPtr]), cache_dir, err); if (err.Fail()) { - if (log) - log->Printf("%s - error reading cache_dir: %s.", __FUNCTION__, - err.AsCString()); + LLDB_LOGF(log, "%s - error reading cache_dir: %s.", __FUNCTION__, + err.AsCString()); } - if (log) - log->Printf("%s - 0x%" PRIx64 ",0x%" PRIx64 " => '%s' at '%s' .", - __FUNCTION__, uint64_t(args[eRsContext]), - uint64_t(args[eRsScript]), res_name.c_str(), cache_dir.c_str()); + LLDB_LOGF(log, "%s - 0x%" PRIx64 ",0x%" PRIx64 " => '%s' at '%s' .", + __FUNCTION__, uint64_t(args[eRsContext]), uint64_t(args[eRsScript]), + res_name.c_str(), cache_dir.c_str()); if (res_name.size() > 0) { StreamString strm; @@ -1566,13 +1517,14 @@ void RenderScriptRuntime::CaptureScriptInit(RuntimeHook *hook, script->context = addr_t(args[eRsContext]); } - if (log) - log->Printf("%s - '%s' tagged with context 0x%" PRIx64 - " and script 0x%" PRIx64 ".", - __FUNCTION__, strm.GetData(), uint64_t(args[eRsContext]), - uint64_t(args[eRsScript])); + LLDB_LOGF(log, + "%s - '%s' tagged with context 0x%" PRIx64 + " and script 0x%" PRIx64 ".", + __FUNCTION__, strm.GetData(), uint64_t(args[eRsContext]), + uint64_t(args[eRsScript])); } else if (log) { - log->Printf("%s - resource name invalid, Script not tagged.", __FUNCTION__); + LLDB_LOGF(log, "%s - resource name invalid, Script not tagged.", + __FUNCTION__); } } @@ -1593,8 +1545,7 @@ void RenderScriptRuntime::LoadRuntimeHooks(lldb::ModuleSP module, machine != llvm::Triple::ArchType::mipsel && machine != llvm::Triple::ArchType::mips64el && machine != llvm::Triple::ArchType::x86_64) { - if (log) - log->Printf("%s - unable to hook runtime functions.", __FUNCTION__); + LLDB_LOGF(log, "%s - unable to hook runtime functions.", __FUNCTION__); return; } @@ -1618,23 +1569,22 @@ void RenderScriptRuntime::LoadRuntimeHooks(lldb::ModuleSP module, ConstString(symbol_name), eSymbolTypeCode); if (!sym) { if (log) { - log->Printf("%s - symbol '%s' related to the function %s not found", - __FUNCTION__, symbol_name, hook_defn->name); + LLDB_LOGF(log, "%s - symbol '%s' related to the function %s not found", + __FUNCTION__, symbol_name, hook_defn->name); } continue; } addr_t addr = sym->GetLoadAddress(&target); if (addr == LLDB_INVALID_ADDRESS) { - if (log) - log->Printf("%s - unable to resolve the address of hook function '%s' " - "with symbol '%s'.", - __FUNCTION__, hook_defn->name, symbol_name); + LLDB_LOGF(log, + "%s - unable to resolve the address of hook function '%s' " + "with symbol '%s'.", + __FUNCTION__, hook_defn->name, symbol_name); continue; } else { - if (log) - log->Printf("%s - function %s, address resolved at 0x%" PRIx64, - __FUNCTION__, hook_defn->name, addr); + LLDB_LOGF(log, "%s - function %s, address resolved at 0x%" PRIx64, + __FUNCTION__, hook_defn->name, addr); } RuntimeHookSP hook(new RuntimeHook()); @@ -1644,11 +1594,12 @@ void RenderScriptRuntime::LoadRuntimeHooks(lldb::ModuleSP module, hook->bp_sp->SetCallback(HookCallback, hook.get(), true); m_runtimeHooks[addr] = hook; if (log) { - log->Printf("%s - successfully hooked '%s' in '%s' version %" PRIu64 - " at 0x%" PRIx64 ".", - __FUNCTION__, hook_defn->name, - module->GetFileSpec().GetFilename().AsCString(), - (uint64_t)hook_defn->version, (uint64_t)addr); + LLDB_LOGF(log, + "%s - successfully hooked '%s' in '%s' version %" PRIu64 + " at 0x%" PRIx64 ".", + __FUNCTION__, hook_defn->name, + module->GetFileSpec().GetFilename().AsCString(), + (uint64_t)hook_defn->version, (uint64_t)addr); } hook_placed[idx] = true; } @@ -1661,8 +1612,8 @@ void RenderScriptRuntime::LoadRuntimeHooks(lldb::ModuleSP module, const HookDefn &hook_defn = s_runtimeHookDefns[i]; if (hook_defn.kind != kind) continue; - log->Printf("%s - function %s was not hooked", __FUNCTION__, - hook_defn.name); + LLDB_LOGF(log, "%s - function %s was not hooked", __FUNCTION__, + hook_defn.name); } } } @@ -1697,11 +1648,11 @@ void RenderScriptRuntime::FixupScriptDetails(RSModuleDescriptorSP rsmodule_sp) { if (m_scriptMappings.find(script) != m_scriptMappings.end()) { // if the module we have stored is different to the one we just received. if (m_scriptMappings[script] != rsmodule_sp) { - if (log) - log->Printf( - "%s - script %" PRIx64 " wants reassigned to new rsmodule '%s'.", - __FUNCTION__, (uint64_t)script, - rsmodule_sp->m_module->GetFileSpec().GetFilename().AsCString()); + LLDB_LOGF( + log, + "%s - script %" PRIx64 " wants reassigned to new rsmodule '%s'.", + __FUNCTION__, (uint64_t)script, + rsmodule_sp->m_module->GetFileSpec().GetFilename().AsCString()); } } // We don't have a script mapping for the current script. @@ -1713,11 +1664,9 @@ void RenderScriptRuntime::FixupScriptDetails(RSModuleDescriptorSP rsmodule_sp) { rsmodule_sp->m_resname = res_name; // Add Script/Module pair to map. m_scriptMappings[script] = rsmodule_sp; - if (log) - log->Printf( - "%s - script %" PRIx64 " associated with rsmodule '%s'.", - __FUNCTION__, (uint64_t)script, - rsmodule_sp->m_module->GetFileSpec().GetFilename().AsCString()); + LLDB_LOGF(log, "%s - script %" PRIx64 " associated with rsmodule '%s'.", + __FUNCTION__, (uint64_t)script, + rsmodule_sp->m_module->GetFileSpec().GetFilename().AsCString()); } } } @@ -1730,8 +1679,7 @@ bool RenderScriptRuntime::EvalRSExpression(const char *expr, StackFrame *frame_ptr, uint64_t *result) { Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_LANGUAGE)); - if (log) - log->Printf("%s(%s)", __FUNCTION__, expr); + LLDB_LOGF(log, "%s(%s)", __FUNCTION__, expr); ValueObjectSP expr_result; EvaluateExpressionOptions options; @@ -1741,8 +1689,7 @@ bool RenderScriptRuntime::EvalRSExpression(const char *expr, target.EvaluateExpression(expr, frame_ptr, expr_result, options); if (!expr_result) { - if (log) - log->Printf("%s: couldn't evaluate expression.", __FUNCTION__); + LLDB_LOGF(log, "%s: couldn't evaluate expression.", __FUNCTION__); return false; } @@ -1751,16 +1698,14 @@ bool RenderScriptRuntime::EvalRSExpression(const char *expr, Status err = expr_result->GetError(); // Expression returned is void, so this is actually a success if (err.GetError() == UserExpression::kNoResult) { - if (log) - log->Printf("%s - expression returned void.", __FUNCTION__); + LLDB_LOGF(log, "%s - expression returned void.", __FUNCTION__); result = nullptr; return true; } - if (log) - log->Printf("%s - error evaluating expression result: %s", __FUNCTION__, - err.AsCString()); + LLDB_LOGF(log, "%s - error evaluating expression result: %s", __FUNCTION__, + err.AsCString()); return false; } @@ -1769,9 +1714,8 @@ bool RenderScriptRuntime::EvalRSExpression(const char *expr, *result = expr_result->GetValueAsUnsigned(0, &success); if (!success) { - if (log) - log->Printf("%s - couldn't convert expression result to uint32_t", - __FUNCTION__); + LLDB_LOGF(log, "%s - couldn't convert expression result to uint32_t", + __FUNCTION__); return false; } @@ -1884,8 +1828,7 @@ bool RenderScriptRuntime::JITDataPointer(AllocationDetails *alloc, Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_LANGUAGE)); if (!alloc->address.isValid()) { - if (log) - log->Printf("%s - failed to find allocation details.", __FUNCTION__); + LLDB_LOGF(log, "%s - failed to find allocation details.", __FUNCTION__); return false; } @@ -1895,12 +1838,10 @@ bool RenderScriptRuntime::JITDataPointer(AllocationDetails *alloc, int written = snprintf(expr_buf, jit_max_expr_size, fmt_str, *alloc->address.get(), x, y, z); if (written < 0) { - if (log) - log->Printf("%s - encoding error in snprintf().", __FUNCTION__); + LLDB_LOGF(log, "%s - encoding error in snprintf().", __FUNCTION__); return false; } else if (written >= jit_max_expr_size) { - if (log) - log->Printf("%s - expression too long.", __FUNCTION__); + LLDB_LOGF(log, "%s - expression too long.", __FUNCTION__); return false; } @@ -1922,8 +1863,7 @@ bool RenderScriptRuntime::JITTypePointer(AllocationDetails *alloc, Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_LANGUAGE)); if (!alloc->address.isValid() || !alloc->context.isValid()) { - if (log) - log->Printf("%s - failed to find allocation details.", __FUNCTION__); + LLDB_LOGF(log, "%s - failed to find allocation details.", __FUNCTION__); return false; } @@ -1933,12 +1873,10 @@ bool RenderScriptRuntime::JITTypePointer(AllocationDetails *alloc, int written = snprintf(expr_buf, jit_max_expr_size, fmt_str, *alloc->context.get(), *alloc->address.get()); if (written < 0) { - if (log) - log->Printf("%s - encoding error in snprintf().", __FUNCTION__); + LLDB_LOGF(log, "%s - encoding error in snprintf().", __FUNCTION__); return false; } else if (written >= jit_max_expr_size) { - if (log) - log->Printf("%s - expression too long.", __FUNCTION__); + LLDB_LOGF(log, "%s - expression too long.", __FUNCTION__); return false; } @@ -1960,8 +1898,7 @@ bool RenderScriptRuntime::JITTypePacked(AllocationDetails *alloc, Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_LANGUAGE)); if (!alloc->type_ptr.isValid() || !alloc->context.isValid()) { - if (log) - log->Printf("%s - Failed to find allocation details.", __FUNCTION__); + LLDB_LOGF(log, "%s - Failed to find allocation details.", __FUNCTION__); return false; } @@ -1983,12 +1920,10 @@ bool RenderScriptRuntime::JITTypePacked(AllocationDetails *alloc, int written = snprintf(expr_bufs[i], jit_max_expr_size, fmt_str, *alloc->context.get(), bits, *alloc->type_ptr.get()); if (written < 0) { - if (log) - log->Printf("%s - encoding error in snprintf().", __FUNCTION__); + LLDB_LOGF(log, "%s - encoding error in snprintf().", __FUNCTION__); return false; } else if (written >= jit_max_expr_size) { - if (log) - log->Printf("%s - expression too long.", __FUNCTION__); + LLDB_LOGF(log, "%s - expression too long.", __FUNCTION__); return false; } @@ -2007,10 +1942,10 @@ bool RenderScriptRuntime::JITTypePacked(AllocationDetails *alloc, addr_t element_ptr = static_cast<lldb::addr_t>(results[3]); alloc->element.element_ptr = element_ptr; - if (log) - log->Printf("%s - dims (%" PRIu32 ", %" PRIu32 ", %" PRIu32 - ") Element*: 0x%" PRIx64 ".", - __FUNCTION__, dims.dim_1, dims.dim_2, dims.dim_3, element_ptr); + LLDB_LOGF(log, + "%s - dims (%" PRIu32 ", %" PRIu32 ", %" PRIu32 + ") Element*: 0x%" PRIx64 ".", + __FUNCTION__, dims.dim_1, dims.dim_2, dims.dim_3, element_ptr); return true; } @@ -2024,8 +1959,7 @@ bool RenderScriptRuntime::JITElementPacked(Element &elem, Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_LANGUAGE)); if (!elem.element_ptr.isValid()) { - if (log) - log->Printf("%s - failed to find allocation details.", __FUNCTION__); + LLDB_LOGF(log, "%s - failed to find allocation details.", __FUNCTION__); return false; } @@ -2042,12 +1976,10 @@ bool RenderScriptRuntime::JITElementPacked(Element &elem, int written = snprintf(expr_bufs[i], jit_max_expr_size, fmt_str, context, *elem.element_ptr.get()); if (written < 0) { - if (log) - log->Printf("%s - encoding error in snprintf().", __FUNCTION__); + LLDB_LOGF(log, "%s - encoding error in snprintf().", __FUNCTION__); return false; } else if (written >= jit_max_expr_size) { - if (log) - log->Printf("%s - expression too long.", __FUNCTION__); + LLDB_LOGF(log, "%s - expression too long.", __FUNCTION__); return false; } @@ -2063,11 +1995,11 @@ bool RenderScriptRuntime::JITElementPacked(Element &elem, elem.type_vec_size = static_cast<uint32_t>(results[2]); elem.field_count = static_cast<uint32_t>(results[3]); - if (log) - log->Printf("%s - data type %" PRIu32 ", pixel type %" PRIu32 - ", vector size %" PRIu32 ", field count %" PRIu32, - __FUNCTION__, *elem.type.get(), *elem.type_kind.get(), - *elem.type_vec_size.get(), *elem.field_count.get()); + LLDB_LOGF(log, + "%s - data type %" PRIu32 ", pixel type %" PRIu32 + ", vector size %" PRIu32 ", field count %" PRIu32, + __FUNCTION__, *elem.type.get(), *elem.type_kind.get(), + *elem.type_vec_size.get(), *elem.field_count.get()); // If this Element has subelements then JIT rsaElementGetSubElements() for // details about its fields @@ -2084,8 +2016,7 @@ bool RenderScriptRuntime::JITSubelements(Element &elem, Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_LANGUAGE)); if (!elem.element_ptr.isValid() || !elem.field_count.isValid()) { - if (log) - log->Printf("%s - failed to find allocation details.", __FUNCTION__); + LLDB_LOGF(log, "%s - failed to find allocation details.", __FUNCTION__); return false; } @@ -2107,12 +2038,10 @@ bool RenderScriptRuntime::JITSubelements(Element &elem, context, field_count, field_count, field_count, *elem.element_ptr.get(), field_count, field_index); if (written < 0) { - if (log) - log->Printf("%s - encoding error in snprintf().", __FUNCTION__); + LLDB_LOGF(log, "%s - encoding error in snprintf().", __FUNCTION__); return false; } else if (written >= jit_max_expr_size) { - if (log) - log->Printf("%s - expression too long.", __FUNCTION__); + LLDB_LOGF(log, "%s - expression too long.", __FUNCTION__); return false; } @@ -2120,8 +2049,7 @@ bool RenderScriptRuntime::JITSubelements(Element &elem, if (!EvalRSExpression(expr_buffer, frame_ptr, &results)) return false; - if (log) - log->Printf("%s - expr result 0x%" PRIx64 ".", __FUNCTION__, results); + LLDB_LOGF(log, "%s - expr result 0x%" PRIx64 ".", __FUNCTION__, results); switch (expr_index) { case 0: // Element* of child @@ -2136,9 +2064,8 @@ bool RenderScriptRuntime::JITSubelements(Element &elem, if (!err.Fail()) child.type_name = ConstString(name); else { - if (log) - log->Printf("%s - warning: Couldn't read field name.", - __FUNCTION__); + LLDB_LOGF(log, "%s - warning: Couldn't read field name.", + __FUNCTION__); } break; } @@ -2173,8 +2100,7 @@ bool RenderScriptRuntime::JITAllocationSize(AllocationDetails *alloc, if (!alloc->address.isValid() || !alloc->dimension.isValid() || !alloc->data_ptr.isValid() || !alloc->element.datum_size.isValid()) { - if (log) - log->Printf("%s - failed to find allocation details.", __FUNCTION__); + LLDB_LOGF(log, "%s - failed to find allocation details.", __FUNCTION__); return false; } @@ -2196,9 +2122,8 @@ bool RenderScriptRuntime::JITAllocationSize(AllocationDetails *alloc, alloc->size = dim_x * dim_y * dim_z * *alloc->element.datum_size.get(); - if (log) - log->Printf("%s - inferred size of struct allocation %" PRIu32 ".", - __FUNCTION__, *alloc->size.get()); + LLDB_LOGF(log, "%s - inferred size of struct allocation %" PRIu32 ".", + __FUNCTION__, *alloc->size.get()); return true; } @@ -2213,12 +2138,10 @@ bool RenderScriptRuntime::JITAllocationSize(AllocationDetails *alloc, int written = snprintf(expr_buf, jit_max_expr_size, fmt_str, *alloc->address.get(), dim_x, dim_y, dim_z); if (written < 0) { - if (log) - log->Printf("%s - encoding error in snprintf().", __FUNCTION__); + LLDB_LOGF(log, "%s - encoding error in snprintf().", __FUNCTION__); return false; } else if (written >= jit_max_expr_size) { - if (log) - log->Printf("%s - expression too long.", __FUNCTION__); + LLDB_LOGF(log, "%s - expression too long.", __FUNCTION__); return false; } @@ -2242,8 +2165,7 @@ bool RenderScriptRuntime::JITAllocationStride(AllocationDetails *alloc, Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_LANGUAGE)); if (!alloc->address.isValid() || !alloc->data_ptr.isValid()) { - if (log) - log->Printf("%s - failed to find allocation details.", __FUNCTION__); + LLDB_LOGF(log, "%s - failed to find allocation details.", __FUNCTION__); return false; } @@ -2253,12 +2175,10 @@ bool RenderScriptRuntime::JITAllocationStride(AllocationDetails *alloc, int written = snprintf(expr_buf, jit_max_expr_size, fmt_str, *alloc->address.get(), 0, 1, 0); if (written < 0) { - if (log) - log->Printf("%s - encoding error in snprintf().", __FUNCTION__); + LLDB_LOGF(log, "%s - encoding error in snprintf().", __FUNCTION__); return false; } else if (written >= jit_max_expr_size) { - if (log) - log->Printf("%s - expression too long.", __FUNCTION__); + LLDB_LOGF(log, "%s - expression too long.", __FUNCTION__); return false; } @@ -2354,9 +2274,8 @@ void RenderScriptRuntime::FindStructTypeName(Element &elem, // '#rs_padding_[0-9]+' if (found && num_children < elem.children.size()) { const uint32_t size_diff = elem.children.size() - num_children; - if (log) - log->Printf("%s - %" PRIu32 " padding struct entries", __FUNCTION__, - size_diff); + LLDB_LOGF(log, "%s - %" PRIu32 " padding struct entries", __FUNCTION__, + size_diff); for (uint32_t i = 0; i < size_diff; ++i) { ConstString name = elem.children[num_children + i].type_name; @@ -2377,9 +2296,8 @@ void RenderScriptRuntime::FindStructTypeName(Element &elem, // Save name of variable in Element. elem.type_name = valobj_sp->GetTypeName(); - if (log) - log->Printf("%s - element name set to %s", __FUNCTION__, - elem.type_name.AsCString()); + LLDB_LOGF(log, "%s - element name set to %s", __FUNCTION__, + elem.type_name.AsCString()); return; } @@ -2424,9 +2342,8 @@ void RenderScriptRuntime::SetElementSize(Element &elem) { elem.padding = padding; elem.datum_size = data_size + padding; - if (log) - log->Printf("%s - element size set to %" PRIu32, __FUNCTION__, - data_size + padding); + LLDB_LOGF(log, "%s - element size set to %" PRIu32, __FUNCTION__, + data_size + padding); } // Given an allocation, this function copies the allocation contents from @@ -2439,13 +2356,11 @@ RenderScriptRuntime::GetAllocationData(AllocationDetails *alloc, // JIT all the allocation details if (alloc->ShouldRefresh()) { - if (log) - log->Printf("%s - allocation details not calculated yet, jitting info", - __FUNCTION__); + LLDB_LOGF(log, "%s - allocation details not calculated yet, jitting info", + __FUNCTION__); if (!RefreshAllocation(alloc, frame_ptr)) { - if (log) - log->Printf("%s - couldn't JIT allocation details", __FUNCTION__); + LLDB_LOGF(log, "%s - couldn't JIT allocation details", __FUNCTION__); return nullptr; } } @@ -2458,9 +2373,8 @@ RenderScriptRuntime::GetAllocationData(AllocationDetails *alloc, const uint32_t size = *alloc->size.get(); std::shared_ptr<uint8_t> buffer(new uint8_t[size]); if (!buffer) { - if (log) - log->Printf("%s - couldn't allocate a %" PRIu32 " byte buffer", - __FUNCTION__, size); + LLDB_LOGF(log, "%s - couldn't allocate a %" PRIu32 " byte buffer", + __FUNCTION__, size); return nullptr; } @@ -2469,10 +2383,10 @@ RenderScriptRuntime::GetAllocationData(AllocationDetails *alloc, lldb::addr_t data_ptr = *alloc->data_ptr.get(); GetProcess()->ReadMemory(data_ptr, buffer.get(), size, err); if (err.Fail()) { - if (log) - log->Printf("%s - '%s' Couldn't read %" PRIu32 - " bytes of allocation data from 0x%" PRIx64, - __FUNCTION__, err.AsCString(), size, data_ptr); + LLDB_LOGF(log, + "%s - '%s' Couldn't read %" PRIu32 + " bytes of allocation data from 0x%" PRIx64, + __FUNCTION__, err.AsCString(), size, data_ptr); return nullptr; } @@ -2493,19 +2407,16 @@ bool RenderScriptRuntime::LoadAllocation(Stream &strm, const uint32_t alloc_id, if (!alloc) return false; - if (log) - log->Printf("%s - found allocation 0x%" PRIx64, __FUNCTION__, - *alloc->address.get()); + LLDB_LOGF(log, "%s - found allocation 0x%" PRIx64, __FUNCTION__, + *alloc->address.get()); // JIT all the allocation details if (alloc->ShouldRefresh()) { - if (log) - log->Printf("%s - allocation details not calculated yet, jitting info.", - __FUNCTION__); + LLDB_LOGF(log, "%s - allocation details not calculated yet, jitting info.", + __FUNCTION__); if (!RefreshAllocation(alloc, frame_ptr)) { - if (log) - log->Printf("%s - couldn't JIT allocation details", __FUNCTION__); + LLDB_LOGF(log, "%s - couldn't JIT allocation details", __FUNCTION__); return false; } } @@ -2559,9 +2470,8 @@ bool RenderScriptRuntime::LoadAllocation(Stream &strm, const uint32_t alloc_id, sizeof(AllocationDetails::FileHeader), sizeof(AllocationDetails::ElementHeader)); - if (log) - log->Printf("%s - header type %" PRIu32 ", element size %" PRIu32, - __FUNCTION__, root_el_hdr.type, root_el_hdr.element_size); + LLDB_LOGF(log, "%s - header type %" PRIu32 ", element size %" PRIu32, + __FUNCTION__, root_el_hdr.type, root_el_hdr.element_size); // Check if the target allocation and file both have the same number of bytes // for an Element @@ -2717,19 +2627,16 @@ bool RenderScriptRuntime::SaveAllocation(Stream &strm, const uint32_t alloc_id, if (!alloc) return false; - if (log) - log->Printf("%s - found allocation 0x%" PRIx64 ".", __FUNCTION__, - *alloc->address.get()); + LLDB_LOGF(log, "%s - found allocation 0x%" PRIx64 ".", __FUNCTION__, + *alloc->address.get()); // JIT all the allocation details if (alloc->ShouldRefresh()) { - if (log) - log->Printf("%s - allocation details not calculated yet, jitting info.", - __FUNCTION__); + LLDB_LOGF(log, "%s - allocation details not calculated yet, jitting info.", + __FUNCTION__); if (!RefreshAllocation(alloc, frame_ptr)) { - if (log) - log->Printf("%s - couldn't JIT allocation details.", __FUNCTION__); + LLDB_LOGF(log, "%s - couldn't JIT allocation details.", __FUNCTION__); return false; } } @@ -2743,14 +2650,14 @@ bool RenderScriptRuntime::SaveAllocation(Stream &strm, const uint32_t alloc_id, // Check we can create writable file FileSpec file_spec(path); FileSystem::Instance().Resolve(file_spec); - File file; - FileSystem::Instance().Open(file, file_spec, - File::eOpenOptionWrite | - File::eOpenOptionCanCreate | - File::eOpenOptionTruncate); + auto file = FileSystem::Instance().Open( + file_spec, File::eOpenOptionWrite | File::eOpenOptionCanCreate | + File::eOpenOptionTruncate); if (!file) { - strm.Printf("Error: Failed to open '%s' for writing", path); + std::string error = llvm::toString(file.takeError()); + strm.Printf("Error: Failed to open '%s' for writing: %s", path, + error.c_str()); strm.EOL(); return false; } @@ -2779,11 +2686,10 @@ bool RenderScriptRuntime::SaveAllocation(Stream &strm, const uint32_t alloc_id, // Write the file header size_t num_bytes = sizeof(AllocationDetails::FileHeader); - if (log) - log->Printf("%s - writing File Header, 0x%" PRIx64 " bytes", __FUNCTION__, - (uint64_t)num_bytes); + LLDB_LOGF(log, "%s - writing File Header, 0x%" PRIx64 " bytes", __FUNCTION__, + (uint64_t)num_bytes); - Status err = file.Write(&head, num_bytes); + Status err = file.get()->Write(&head, num_bytes); if (!err.Success()) { strm.Printf("Error: '%s' when writing to file '%s'", err.AsCString(), path); strm.EOL(); @@ -2805,11 +2711,10 @@ bool RenderScriptRuntime::SaveAllocation(Stream &strm, const uint32_t alloc_id, // Write headers for allocation element type to file num_bytes = element_header_size; - if (log) - log->Printf("%s - writing element headers, 0x%" PRIx64 " bytes.", - __FUNCTION__, (uint64_t)num_bytes); + LLDB_LOGF(log, "%s - writing element headers, 0x%" PRIx64 " bytes.", + __FUNCTION__, (uint64_t)num_bytes); - err = file.Write(element_header_buffer.get(), num_bytes); + err = file.get()->Write(element_header_buffer.get(), num_bytes); if (!err.Success()) { strm.Printf("Error: '%s' when writing to file '%s'", err.AsCString(), path); strm.EOL(); @@ -2818,11 +2723,10 @@ bool RenderScriptRuntime::SaveAllocation(Stream &strm, const uint32_t alloc_id, // Write allocation data to file num_bytes = static_cast<size_t>(*alloc->size.get()); - if (log) - log->Printf("%s - writing 0x%" PRIx64 " bytes", __FUNCTION__, - (uint64_t)num_bytes); + LLDB_LOGF(log, "%s - writing 0x%" PRIx64 " bytes", __FUNCTION__, + (uint64_t)num_bytes); - err = file.Write(buffer.get(), num_bytes); + err = file.get()->Write(buffer.get(), num_bytes); if (!err.Success()) { strm.Printf("Error: '%s' when writing to file '%s'", err.AsCString(), path); strm.EOL(); @@ -2894,17 +2798,17 @@ bool RenderScriptRuntime::LoadModule(const lldb::ModuleSP &module_sp) { addr_t addr = debug_present->GetLoadAddress(&target); GetProcess()->WriteMemory(addr, &flag, sizeof(flag), err); if (err.Success()) { - if (log) - log->Printf("%s - debugger present flag set on debugee.", - __FUNCTION__); + LLDB_LOGF(log, "%s - debugger present flag set on debugee.", + __FUNCTION__); m_debuggerPresentFlagged = true; } else if (log) { - log->Printf("%s - error writing debugger present flags '%s' ", - __FUNCTION__, err.AsCString()); + LLDB_LOGF(log, "%s - error writing debugger present flags '%s' ", + __FUNCTION__, err.AsCString()); } } else if (log) { - log->Printf( + LLDB_LOGF( + log, "%s - error writing debugger present flags - symbol not found", __FUNCTION__); } @@ -3004,8 +2908,7 @@ bool RSModuleDescriptor::ParseExportReduceCount(llvm::StringRef *lines, return false; } - if (log) - log->Printf("Found RenderScript reduction '%s'", spec[2].str().c_str()); + LLDB_LOGF(log, "Found RenderScript reduction '%s'", spec[2].str().c_str()); m_reductions.push_back(RSReductionDescriptor(this, sig, accum_data_size, spec[2], spec[3], spec[4], @@ -3082,10 +2985,8 @@ bool RSModuleDescriptor::ParseRSInfo() { { const llvm::StringRef raw_rs_info((const char *)buffer->GetBytes()); raw_rs_info.split(info_lines, '\n'); - if (log) - log->Printf("'.rs.info symbol for '%s':\n%s", - m_module->GetFileSpec().GetCString(), - raw_rs_info.str().c_str()); + LLDB_LOGF(log, "'.rs.info symbol for '%s':\n%s", + m_module->GetFileSpec().GetCString(), raw_rs_info.str().c_str()); } enum { @@ -3153,9 +3054,8 @@ bool RSModuleDescriptor::ParseRSInfo() { success = ParseVersionInfo(line, n_lines); break; default: { - if (log) - log->Printf("%s - skipping .rs.info field '%s'", __FUNCTION__, - line->str().c_str()); + LLDB_LOGF(log, "%s - skipping .rs.info field '%s'", __FUNCTION__, + line->str().c_str()); continue; } } @@ -3276,15 +3176,13 @@ bool RenderScriptRuntime::DumpAllocation(Stream &strm, StackFrame *frame_ptr, if (!alloc) return false; // FindAllocByID() will print error message for us here - if (log) - log->Printf("%s - found allocation 0x%" PRIx64, __FUNCTION__, - *alloc->address.get()); + LLDB_LOGF(log, "%s - found allocation 0x%" PRIx64, __FUNCTION__, + *alloc->address.get()); // Check we have information about the allocation, if not calculate it if (alloc->ShouldRefresh()) { - if (log) - log->Printf("%s - allocation details not calculated yet, jitting info.", - __FUNCTION__); + LLDB_LOGF(log, "%s - allocation details not calculated yet, jitting info.", + __FUNCTION__); // JIT all the allocation information if (!RefreshAllocation(alloc, frame_ptr)) { @@ -3313,9 +3211,8 @@ bool RenderScriptRuntime::DumpAllocation(Stream &strm, StackFrame *frame_ptr, const uint32_t data_size = *alloc->element.datum_size.get(); - if (log) - log->Printf("%s - element size %" PRIu32 " bytes, including padding", - __FUNCTION__, data_size); + LLDB_LOGF(log, "%s - element size %" PRIu32 " bytes, including padding", + __FUNCTION__, data_size); // Allocate a buffer to copy data into std::shared_ptr<uint8_t> buffer = GetAllocationData(alloc, frame_ptr); @@ -3340,10 +3237,10 @@ bool RenderScriptRuntime::DumpAllocation(Stream &strm, StackFrame *frame_ptr, const uint32_t size = *alloc->size.get(); // Size of whole allocation const uint32_t padding = alloc->element.padding.isValid() ? *alloc->element.padding.get() : 0; - if (log) - log->Printf("%s - stride %" PRIu32 " bytes, size %" PRIu32 - " bytes, padding %" PRIu32, - __FUNCTION__, stride, size, padding); + LLDB_LOGF(log, + "%s - stride %" PRIu32 " bytes, size %" PRIu32 + " bytes, padding %" PRIu32, + __FUNCTION__, stride, size, padding); // Find dimensions used to index loops, so need to be non-zero uint32_t dim_x = alloc->dimension.get()->dim_1; @@ -3395,8 +3292,7 @@ bool RenderScriptRuntime::DumpAllocation(Stream &strm, StackFrame *frame_ptr, *alloc->data_ptr.get() + offset); if (written < 0 || written >= jit_max_expr_size) { - if (log) - log->Printf("%s - error in snprintf().", __FUNCTION__); + LLDB_LOGF(log, "%s - error in snprintf().", __FUNCTION__); continue; } @@ -3573,17 +3469,16 @@ void RenderScriptRuntime::SetBreakAllKernels(bool do_break, TargetSP target) { for (const auto &module : m_rsmodules) BreakOnModuleKernels(module); - if (log) - log->Printf("%s(True) - breakpoints set on all currently loaded kernels.", - __FUNCTION__); + LLDB_LOGF(log, + "%s(True) - breakpoints set on all currently loaded kernels.", + __FUNCTION__); } else if (!do_break && m_breakAllKernels) // Breakpoints won't be set on any new kernels. { m_breakAllKernels = false; - if (log) - log->Printf("%s(False) - breakpoints no longer automatically set.", - __FUNCTION__); + LLDB_LOGF(log, "%s(False) - breakpoints no longer automatically set.", + __FUNCTION__); } } @@ -3595,8 +3490,8 @@ RenderScriptRuntime::CreateKernelBreakpoint(ConstString name) { GetLogIfAnyCategoriesSet(LIBLLDB_LOG_LANGUAGE | LIBLLDB_LOG_BREAKPOINTS)); if (!m_filtersp) { - if (log) - log->Printf("%s - error, no breakpoint search filter set.", __FUNCTION__); + LLDB_LOGF(log, "%s - error, no breakpoint search filter set.", + __FUNCTION__); return nullptr; } @@ -3610,9 +3505,8 @@ RenderScriptRuntime::CreateKernelBreakpoint(ConstString name) { Status err; target.AddNameToBreakpoint(bp, "RenderScriptKernel", err); if (err.Fail() && log) - if (log) - log->Printf("%s - error setting break name, '%s'.", __FUNCTION__, - err.AsCString()); + LLDB_LOGF(log, "%s - error setting break name, '%s'.", __FUNCTION__, + err.AsCString()); return bp; } @@ -3624,8 +3518,8 @@ RenderScriptRuntime::CreateReductionBreakpoint(ConstString name, GetLogIfAnyCategoriesSet(LIBLLDB_LOG_LANGUAGE | LIBLLDB_LOG_BREAKPOINTS)); if (!m_filtersp) { - if (log) - log->Printf("%s - error, no breakpoint search filter set.", __FUNCTION__); + LLDB_LOGF(log, "%s - error, no breakpoint search filter set.", + __FUNCTION__); return nullptr; } @@ -3640,8 +3534,8 @@ RenderScriptRuntime::CreateReductionBreakpoint(ConstString name, Status err; target.AddNameToBreakpoint(bp, "RenderScriptReduction", err); if (err.Fail() && log) - log->Printf("%s - error setting break name, '%s'.", __FUNCTION__, - err.AsCString()); + LLDB_LOGF(log, "%s - error setting break name, '%s'.", __FUNCTION__, + err.AsCString()); return bp; } @@ -3663,9 +3557,8 @@ bool RenderScriptRuntime::GetFrameVarAsUnsigned(const StackFrameSP frame_sp, StackFrame::eExpressionPathOptionsAllowDirectIVarAccess, var_sp, err)); if (!err.Success()) { - if (log) - log->Printf("%s - error, couldn't find '%s' in frame", __FUNCTION__, - var_name); + LLDB_LOGF(log, "%s - error, couldn't find '%s' in frame", __FUNCTION__, + var_name); return false; } @@ -3673,9 +3566,8 @@ bool RenderScriptRuntime::GetFrameVarAsUnsigned(const StackFrameSP frame_sp, bool success = false; val = value_sp->GetValueAsUnsigned(0, &success); if (!success) { - if (log) - log->Printf("%s - error, couldn't parse '%s' as an uint32_t.", - __FUNCTION__, var_name); + LLDB_LOGF(log, "%s - error, couldn't parse '%s' as an uint32_t.", + __FUNCTION__, var_name); return false; } @@ -3695,8 +3587,7 @@ bool RenderScriptRuntime::GetKernelCoordinate(RSCoordinate &coord, Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_LANGUAGE)); if (!thread_ptr) { - if (log) - log->Printf("%s - Error, No thread pointer", __FUNCTION__); + LLDB_LOGF(log, "%s - Error, No thread pointer", __FUNCTION__); return false; } @@ -3718,17 +3609,15 @@ bool RenderScriptRuntime::GetKernelCoordinate(RSCoordinate &coord, if (!func_name) continue; - if (log) - log->Printf("%s - Inspecting function '%s'", __FUNCTION__, - func_name.GetCString()); + LLDB_LOGF(log, "%s - Inspecting function '%s'", __FUNCTION__, + func_name.GetCString()); // Check if function name has .expand suffix if (!func_name.GetStringRef().endswith(".expand")) continue; - if (log) - log->Printf("%s - Found .expand function '%s'", __FUNCTION__, - func_name.GetCString()); + LLDB_LOGF(log, "%s - Found .expand function '%s'", __FUNCTION__, + func_name.GetCString()); // Get values for variables in .expand frame that tell us the current // kernel invocation @@ -3770,9 +3659,8 @@ bool RenderScriptRuntime::KernelBreakpointHit(void *baton, // Coordinate we want to stop on RSCoordinate target_coord = *static_cast<RSCoordinate *>(baton); - if (log) - log->Printf("%s - Break ID %" PRIu64 ", " FMT_COORD, __FUNCTION__, break_id, - target_coord.x, target_coord.y, target_coord.z); + LLDB_LOGF(log, "%s - Break ID %" PRIu64 ", " FMT_COORD, __FUNCTION__, + break_id, target_coord.x, target_coord.y, target_coord.z); // Select current thread ExecutionContext context(ctx->exe_ctx_ref); @@ -3782,22 +3670,19 @@ bool RenderScriptRuntime::KernelBreakpointHit(void *baton, // Find current kernel invocation from .expand frame variables RSCoordinate current_coord{}; if (!GetKernelCoordinate(current_coord, thread_ptr)) { - if (log) - log->Printf("%s - Error, couldn't select .expand stack frame", - __FUNCTION__); + LLDB_LOGF(log, "%s - Error, couldn't select .expand stack frame", + __FUNCTION__); return false; } - if (log) - log->Printf("%s - " FMT_COORD, __FUNCTION__, current_coord.x, - current_coord.y, current_coord.z); + LLDB_LOGF(log, "%s - " FMT_COORD, __FUNCTION__, current_coord.x, + current_coord.y, current_coord.z); // Check if the current kernel invocation coordinate matches our target // coordinate if (target_coord == current_coord) { - if (log) - log->Printf("%s, BREAKING " FMT_COORD, __FUNCTION__, current_coord.x, - current_coord.y, current_coord.z); + LLDB_LOGF(log, "%s, BREAKING " FMT_COORD, __FUNCTION__, current_coord.x, + current_coord.y, current_coord.z); BreakpointSP breakpoint_sp = context.GetTargetPtr()->GetBreakpointByID(break_id); @@ -3865,8 +3750,8 @@ RenderScriptRuntime::CreateScriptGroupBreakpoint(ConstString name, GetLogIfAnyCategoriesSet(LIBLLDB_LOG_LANGUAGE | LIBLLDB_LOG_BREAKPOINTS)); if (!m_filtersp) { - if (log) - log->Printf("%s - error, no breakpoint search filter set.", __FUNCTION__); + LLDB_LOGF(log, "%s - error, no breakpoint search filter set.", + __FUNCTION__); return nullptr; } @@ -3880,8 +3765,8 @@ RenderScriptRuntime::CreateScriptGroupBreakpoint(ConstString name, Status err; target.AddNameToBreakpoint(bp, name.GetCString(), err); if (err.Fail() && log) - log->Printf("%s - error setting break name, '%s'.", __FUNCTION__, - err.AsCString()); + LLDB_LOGF(log, "%s - error setting break name, '%s'.", __FUNCTION__, + err.AsCString()); // ask the breakpoint to resolve itself bp->ResolveBreakpoint(); return bp; @@ -3964,9 +3849,8 @@ RenderScriptRuntime::CreateAllocation(addr_t address) { auto it = m_allocations.begin(); while (it != m_allocations.end()) { if (*((*it)->address) == address) { - if (log) - log->Printf("%s - Removing allocation id: %d, address: 0x%" PRIx64, - __FUNCTION__, (*it)->id, address); + LLDB_LOGF(log, "%s - Removing allocation id: %d, address: 0x%" PRIx64, + __FUNCTION__, (*it)->id, address); it = m_allocations.erase(it); } else { @@ -3988,9 +3872,8 @@ bool RenderScriptRuntime::ResolveKernelName(lldb::addr_t kernel_addr, Address resolved; // RenderScript module if (!target.GetSectionLoadList().ResolveLoadAddress(kernel_addr, resolved)) { - if (log) - log->Printf("%s: unable to resolve 0x%" PRIx64 " to a loaded symbol", - __FUNCTION__, kernel_addr); + LLDB_LOGF(log, "%s: unable to resolve 0x%" PRIx64 " to a loaded symbol", + __FUNCTION__, kernel_addr); return false; } @@ -4000,9 +3883,8 @@ bool RenderScriptRuntime::ResolveKernelName(lldb::addr_t kernel_addr, name = sym->GetName(); assert(IsRenderScriptModule(resolved.CalculateSymbolContextModule())); - if (log) - log->Printf("%s: 0x%" PRIx64 " resolved to the symbol '%s'", __FUNCTION__, - kernel_addr, name.GetCString()); + LLDB_LOGF(log, "%s: 0x%" PRIx64 " resolved to the symbol '%s'", __FUNCTION__, + kernel_addr, name.GetCString()); return true; } @@ -4256,13 +4138,12 @@ public: // Matching a comma separated list of known words is fairly // straightforward with PCRE, but we're using ERE, so we end up with a // little ugliness... - RegularExpression::Match match(/* max_matches */ 5); RegularExpression match_type_list( llvm::StringRef("^([[:alpha:]]+)(,[[:alpha:]]+){0,4}$")); assert(match_type_list.IsValid()); - if (!match_type_list.Execute(option_val, &match)) { + if (!match_type_list.Execute(option_val)) { err_str.PutCString( "a comma-separated list of kernel types is required"); return false; @@ -4696,32 +4577,36 @@ public: return false; } - Stream *output_strm = nullptr; - StreamFile outfile_stream; + Stream *output_stream_p = nullptr; + std::unique_ptr<Stream> output_stream_storage; + const FileSpec &outfile_spec = m_options.m_outfile; // Dump allocation to file instead if (outfile_spec) { // Open output file std::string path = outfile_spec.GetPath(); - auto error = FileSystem::Instance().Open( - outfile_stream.GetFile(), outfile_spec, - File::eOpenOptionWrite | File::eOpenOptionCanCreate); - if (error.Success()) { - output_strm = &outfile_stream; + auto file = FileSystem::Instance().Open( + outfile_spec, File::eOpenOptionWrite | File::eOpenOptionCanCreate); + if (file) { + output_stream_storage = + std::make_unique<StreamFile>(std::move(file.get())); + output_stream_p = output_stream_storage.get(); result.GetOutputStream().Printf("Results written to '%s'", path.c_str()); result.GetOutputStream().EOL(); } else { - result.AppendErrorWithFormat("Couldn't open file '%s'", path.c_str()); + std::string error = llvm::toString(file.takeError()); + result.AppendErrorWithFormat("Couldn't open file '%s': %s", + path.c_str(), error.c_str()); result.SetStatus(eReturnStatusFailed); return false; } } else - output_strm = &result.GetOutputStream(); + output_stream_p = &result.GetOutputStream(); - assert(output_strm != nullptr); + assert(output_stream_p != nullptr); bool dumped = - runtime->DumpAllocation(*output_strm, m_exe_ctx.GetFramePtr(), id); + runtime->DumpAllocation(*output_stream_p, m_exe_ctx.GetFramePtr(), id); if (dumped) result.SetStatus(eReturnStatusSuccessFinishResult); diff --git a/source/Plugins/LanguageRuntime/RenderScript/RenderScriptRuntime/RenderScriptRuntime.h b/source/Plugins/LanguageRuntime/RenderScript/RenderScriptRuntime/RenderScriptRuntime.h index 3923221d4302..c3740ba55a11 100644 --- a/source/Plugins/LanguageRuntime/RenderScript/RenderScriptRuntime/RenderScriptRuntime.h +++ b/source/Plugins/LanguageRuntime/RenderScript/RenderScriptRuntime/RenderScriptRuntime.h @@ -67,8 +67,8 @@ public: void Dump(Stream *s) const override {} Searcher::CallbackReturn SearchCallback(SearchFilter &filter, - SymbolContext &context, Address *addr, - bool containing) override; + SymbolContext &context, + Address *addr) override; lldb::SearchDepth GetDepth() override { return lldb::eSearchDepthModule; } @@ -117,8 +117,8 @@ public: void Dump(Stream *s) const override {} Searcher::CallbackReturn SearchCallback(SearchFilter &filter, - SymbolContext &context, Address *addr, - bool containing) override; + SymbolContext &context, + Address *addr) override; lldb::SearchDepth GetDepth() override { return lldb::eSearchDepthModule; } @@ -262,8 +262,8 @@ public: void Dump(Stream *s) const override {} Searcher::CallbackReturn SearchCallback(SearchFilter &filter, - SymbolContext &context, Address *addr, - bool containing) override; + SymbolContext &context, + Address *addr) override; lldb::SearchDepth GetDepth() override { return lldb::eSearchDepthModule; } diff --git a/source/Plugins/LanguageRuntime/RenderScript/RenderScriptRuntime/RenderScriptx86ABIFixups.cpp b/source/Plugins/LanguageRuntime/RenderScript/RenderScriptRuntime/RenderScriptx86ABIFixups.cpp index 4725e8c5b0eb..a6d225d2fbd8 100644 --- a/source/Plugins/LanguageRuntime/RenderScript/RenderScriptRuntime/RenderScriptx86ABIFixups.cpp +++ b/source/Plugins/LanguageRuntime/RenderScript/RenderScriptRuntime/RenderScriptx86ABIFixups.cpp @@ -93,9 +93,8 @@ llvm::FunctionType *cloneToStructRetFnTy(llvm::CallInst *call_inst) { assert(orig && "CallInst has no called function"); llvm::FunctionType *orig_type = orig->getFunctionType(); auto name = orig->getName(); - if (log) - log->Printf("%s - cloning to StructRet function for '%s'", __FUNCTION__, - name.str().c_str()); + LLDB_LOGF(log, "%s - cloning to StructRet function for '%s'", __FUNCTION__, + name.str().c_str()); unsigned num_params = orig_type->getNumParams(); std::vector<llvm::Type *> new_params{num_params + 1, nullptr}; @@ -113,9 +112,9 @@ llvm::FunctionType *cloneToStructRetFnTy(llvm::CallInst *call_inst) { if (!return_type_ptr_type) return nullptr; - if (log) - log->Printf("%s - return type pointer type for StructRet clone @ '0x%p':\n", - __FUNCTION__, (void *)return_type_ptr_type); + LLDB_LOGF(log, + "%s - return type pointer type for StructRet clone @ '0x%p':\n", + __FUNCTION__, (void *)return_type_ptr_type); // put the sret pointer argument in place at the beginning of the // argument list. params.emplace(params.begin(), return_type_ptr_type); diff --git a/source/Plugins/ObjectFile/Breakpad/BreakpadRecords.cpp b/source/Plugins/ObjectFile/Breakpad/BreakpadRecords.cpp index d489eaf11115..de17d986a860 100644 --- a/source/Plugins/ObjectFile/Breakpad/BreakpadRecords.cpp +++ b/source/Plugins/ObjectFile/Breakpad/BreakpadRecords.cpp @@ -16,7 +16,19 @@ using namespace lldb_private; using namespace lldb_private::breakpad; namespace { -enum class Token { Unknown, Module, Info, CodeID, File, Func, Public, Stack, CFI, Init }; +enum class Token { + Unknown, + Module, + Info, + CodeID, + File, + Func, + Public, + Stack, + CFI, + Init, + Win, +}; } template<typename T> @@ -33,6 +45,7 @@ template <> Token stringTo<Token>(llvm::StringRef Str) { .Case("STACK", Token::Stack) .Case("CFI", Token::CFI) .Case("INIT", Token::Init) + .Case("WIN", Token::Win) .Default(Token::Unknown); } @@ -127,6 +140,8 @@ llvm::Optional<Record::Kind> Record::classify(llvm::StringRef Line) { switch (Tok) { case Token::CFI: return Record::StackCFI; + case Token::Win: + return Record::StackWin; default: return llvm::None; } @@ -134,13 +149,13 @@ llvm::Optional<Record::Kind> Record::classify(llvm::StringRef Line) { case Token::Unknown: // Optimistically assume that any unrecognised token means this is a line // record, those don't have a special keyword and start directly with a - // hex number. CODE_ID should never be at the start of a line, but if it - // is, it can be treated the same way as a garbled line record. + // hex number. return Record::Line; case Token::CodeID: case Token::CFI: case Token::Init: + case Token::Win: // These should never appear at the start of a valid record. return llvm::None; } @@ -390,6 +405,81 @@ llvm::raw_ostream &breakpad::operator<<(llvm::raw_ostream &OS, return OS << " " << R.UnwindRules; } +llvm::Optional<StackWinRecord> StackWinRecord::parse(llvm::StringRef Line) { + // STACK WIN type rva code_size prologue_size epilogue_size parameter_size + // saved_register_size local_size max_stack_size has_program_string + // program_string_OR_allocates_base_pointer + + if (consume<Token>(Line) != Token::Stack) + return llvm::None; + if (consume<Token>(Line) != Token::Win) + return llvm::None; + + llvm::StringRef Str; + uint8_t Type; + std::tie(Str, Line) = getToken(Line); + // Right now we only support the "FrameData" frame type. + if (!to_integer(Str, Type) || FrameType(Type) != FrameType::FrameData) + return llvm::None; + + lldb::addr_t RVA; + std::tie(Str, Line) = getToken(Line); + if (!to_integer(Str, RVA, 16)) + return llvm::None; + + lldb::addr_t CodeSize; + std::tie(Str, Line) = getToken(Line); + if (!to_integer(Str, CodeSize, 16)) + return llvm::None; + + // Skip fields which we aren't using right now. + std::tie(Str, Line) = getToken(Line); // prologue_size + std::tie(Str, Line) = getToken(Line); // epilogue_size + + lldb::addr_t ParameterSize; + std::tie(Str, Line) = getToken(Line); + if (!to_integer(Str, ParameterSize, 16)) + return llvm::None; + + lldb::addr_t SavedRegisterSize; + std::tie(Str, Line) = getToken(Line); + if (!to_integer(Str, SavedRegisterSize, 16)) + return llvm::None; + + lldb::addr_t LocalSize; + std::tie(Str, Line) = getToken(Line); + if (!to_integer(Str, LocalSize, 16)) + return llvm::None; + + std::tie(Str, Line) = getToken(Line); // max_stack_size + + uint8_t HasProgramString; + std::tie(Str, Line) = getToken(Line); + if (!to_integer(Str, HasProgramString)) + return llvm::None; + // FrameData records should always have a program string. + if (!HasProgramString) + return llvm::None; + + return StackWinRecord(RVA, CodeSize, ParameterSize, SavedRegisterSize, + LocalSize, Line.trim()); +} + +bool breakpad::operator==(const StackWinRecord &L, const StackWinRecord &R) { + return L.RVA == R.RVA && L.CodeSize == R.CodeSize && + L.ParameterSize == R.ParameterSize && + L.SavedRegisterSize == R.SavedRegisterSize && + L.LocalSize == R.LocalSize && L.ProgramString == R.ProgramString; +} + +llvm::raw_ostream &breakpad::operator<<(llvm::raw_ostream &OS, + const StackWinRecord &R) { + return OS << llvm::formatv( + "STACK WIN 4 {0:x-} {1:x-} ? ? {2} {3} {4} ? 1 {5}", R.RVA, + R.CodeSize, R.ParameterSize, R.SavedRegisterSize, R.LocalSize, + R.ProgramString); +} + llvm::StringRef breakpad::toString(Record::Kind K) { switch (K) { case Record::Module: @@ -406,6 +496,8 @@ llvm::StringRef breakpad::toString(Record::Kind K) { return "PUBLIC"; case Record::StackCFI: return "STACK CFI"; + case Record::StackWin: + return "STACK WIN"; } llvm_unreachable("Unknown record kind!"); } diff --git a/source/Plugins/ObjectFile/Breakpad/BreakpadRecords.h b/source/Plugins/ObjectFile/Breakpad/BreakpadRecords.h index 5d5cdb319c10..27bef975125d 100644 --- a/source/Plugins/ObjectFile/Breakpad/BreakpadRecords.h +++ b/source/Plugins/ObjectFile/Breakpad/BreakpadRecords.h @@ -20,7 +20,7 @@ namespace breakpad { class Record { public: - enum Kind { Module, Info, File, Func, Line, Public, StackCFI }; + enum Kind { Module, Info, File, Func, Line, Public, StackCFI, StackWin }; /// Attempt to guess the kind of the record present in the argument without /// doing a full parse. The returned kind will always be correct for valid @@ -157,6 +157,29 @@ public: bool operator==(const StackCFIRecord &L, const StackCFIRecord &R); llvm::raw_ostream &operator<<(llvm::raw_ostream &OS, const StackCFIRecord &R); +class StackWinRecord : public Record { +public: + static llvm::Optional<StackWinRecord> parse(llvm::StringRef Line); + + StackWinRecord(lldb::addr_t RVA, lldb::addr_t CodeSize, + lldb::addr_t ParameterSize, lldb::addr_t SavedRegisterSize, + lldb::addr_t LocalSize, llvm::StringRef ProgramString) + : Record(StackWin), RVA(RVA), CodeSize(CodeSize), + ParameterSize(ParameterSize), SavedRegisterSize(SavedRegisterSize), + LocalSize(LocalSize), ProgramString(ProgramString) {} + + enum class FrameType : uint8_t { FPO = 0, FrameData = 4 }; + lldb::addr_t RVA; + lldb::addr_t CodeSize; + lldb::addr_t ParameterSize; + lldb::addr_t SavedRegisterSize; + lldb::addr_t LocalSize; + llvm::StringRef ProgramString; +}; + +bool operator==(const StackWinRecord &L, const StackWinRecord &R); +llvm::raw_ostream &operator<<(llvm::raw_ostream &OS, const StackWinRecord &R); + } // namespace breakpad } // namespace lldb_private diff --git a/source/Plugins/ObjectFile/Breakpad/ObjectFileBreakpad.cpp b/source/Plugins/ObjectFile/Breakpad/ObjectFileBreakpad.cpp index 60dd9f9cecf0..3b9e0e2092a9 100644 --- a/source/Plugins/ObjectFile/Breakpad/ObjectFileBreakpad.cpp +++ b/source/Plugins/ObjectFile/Breakpad/ObjectFileBreakpad.cpp @@ -42,6 +42,8 @@ llvm::Optional<Header> Header::parse(llvm::StringRef text) { return Header{ArchSpec(triple), std::move(uuid)}; } +char ObjectFileBreakpad::ID; + void ObjectFileBreakpad::Initialize() { PluginManager::RegisterPlugin(GetPluginNameStatic(), GetPluginDescriptionStatic(), CreateInstance, @@ -125,7 +127,7 @@ Symtab *ObjectFileBreakpad::GetSymtab() { void ObjectFileBreakpad::CreateSections(SectionList &unified_section_list) { if (m_sections_up) return; - m_sections_up = llvm::make_unique<SectionList>(); + m_sections_up = std::make_unique<SectionList>(); llvm::Optional<Record::Kind> current_section; offset_t section_start; diff --git a/source/Plugins/ObjectFile/Breakpad/ObjectFileBreakpad.h b/source/Plugins/ObjectFile/Breakpad/ObjectFileBreakpad.h index e8885e0cc898..cb4bba01fb71 100644 --- a/source/Plugins/ObjectFile/Breakpad/ObjectFileBreakpad.h +++ b/source/Plugins/ObjectFile/Breakpad/ObjectFileBreakpad.h @@ -48,6 +48,13 @@ public: uint32_t GetPluginVersion() override { return 1; } + // LLVM RTTI support + static char ID; + bool isA(const void *ClassID) const override { + return ClassID == &ID || ObjectFile::isA(ClassID); + } + static bool classof(const ObjectFile *obj) { return obj->isA(&ID); } + // ObjectFile Protocol. bool ParseHeader() override; @@ -78,8 +85,6 @@ public: UUID GetUUID() override { return m_uuid; } - FileSpecList GetDebugSymbolFilePaths() override { return FileSpecList(); } - uint32_t GetDependentModules(FileSpecList &files) override { return 0; } Type CalculateType() override { return eTypeDebugInfo; } diff --git a/source/Plugins/ObjectFile/ELF/ObjectFileELF.cpp b/source/Plugins/ObjectFile/ELF/ObjectFileELF.cpp index d62afa34bbe8..3f8502548fc2 100644 --- a/source/Plugins/ObjectFile/ELF/ObjectFileELF.cpp +++ b/source/Plugins/ObjectFile/ELF/ObjectFileELF.cpp @@ -18,6 +18,7 @@ #include "lldb/Core/PluginManager.h" #include "lldb/Core/Section.h" #include "lldb/Host/FileSystem.h" +#include "lldb/Host/LZMA.h" #include "lldb/Symbol/DWARFCallFrameInfo.h" #include "lldb/Symbol/SymbolContext.h" #include "lldb/Target/SectionLoadList.h" @@ -29,12 +30,13 @@ #include "lldb/Utility/Status.h" #include "lldb/Utility/Stream.h" #include "lldb/Utility/Timer.h" - #include "llvm/ADT/IntervalMap.h" #include "llvm/ADT/PointerUnion.h" #include "llvm/ADT/StringRef.h" +#include "llvm/BinaryFormat/ELF.h" #include "llvm/Object/Decompressor.h" #include "llvm/Support/ARMBuildAttributes.h" +#include "llvm/Support/CRC.h" #include "llvm/Support/MathExtras.h" #include "llvm/Support/MemoryBuffer.h" #include "llvm/Support/MipsABIFlags.h" @@ -80,41 +82,6 @@ const elf_word LLDB_NT_GNU_ABI_OS_LINUX = 0x00; const elf_word LLDB_NT_GNU_ABI_OS_HURD = 0x01; const elf_word LLDB_NT_GNU_ABI_OS_SOLARIS = 0x02; -// LLDB_NT_OWNER_CORE and LLDB_NT_OWNER_LINUX note contants -#define NT_PRSTATUS 1 -#define NT_PRFPREG 2 -#define NT_PRPSINFO 3 -#define NT_TASKSTRUCT 4 -#define NT_AUXV 6 -#define NT_SIGINFO 0x53494749 -#define NT_FILE 0x46494c45 -#define NT_PRXFPREG 0x46e62b7f -#define NT_PPC_VMX 0x100 -#define NT_PPC_SPE 0x101 -#define NT_PPC_VSX 0x102 -#define NT_386_TLS 0x200 -#define NT_386_IOPERM 0x201 -#define NT_X86_XSTATE 0x202 -#define NT_S390_HIGH_GPRS 0x300 -#define NT_S390_TIMER 0x301 -#define NT_S390_TODCMP 0x302 -#define NT_S390_TODPREG 0x303 -#define NT_S390_CTRS 0x304 -#define NT_S390_PREFIX 0x305 -#define NT_S390_LAST_BREAK 0x306 -#define NT_S390_SYSTEM_CALL 0x307 -#define NT_S390_TDB 0x308 -#define NT_S390_VXRS_LOW 0x309 -#define NT_S390_VXRS_HIGH 0x30a -#define NT_ARM_VFP 0x400 -#define NT_ARM_TLS 0x401 -#define NT_ARM_HW_BREAK 0x402 -#define NT_ARM_HW_WATCH 0x403 -#define NT_ARM_SYSTEM_CALL 0x404 -#define NT_METAG_CBUF 0x500 -#define NT_METAG_RPIPE 0x501 -#define NT_METAG_TLS 0x502 - //===----------------------------------------------------------------------===// /// \class ELFRelocation /// Generic wrapper for ELFRel and ELFRela. @@ -264,8 +231,7 @@ bool ELFNote::Parse(const DataExtractor &data, lldb::offset_t *offset) { const char *cstr = data.GetCStr(offset, llvm::alignTo(n_namesz, 4)); if (cstr == nullptr) { Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_SYMBOLS)); - if (log) - log->Printf("Failed to parse note name lacking nul terminator"); + LLDB_LOGF(log, "Failed to parse note name lacking nul terminator"); return false; } @@ -333,6 +299,8 @@ static uint32_t subTypeFromElfHeader(const elf::ELFHeader &header) { return LLDB_INVALID_CPUTYPE; } +char ObjectFileELF::ID; + // Arbitrary constant used as UUID prefix for core files. const uint32_t ObjectFileELF::g_core_uuid_magic(0xE210C); @@ -429,67 +397,9 @@ bool ObjectFileELF::MagicBytesMatch(DataBufferSP &data_sp, return false; } -/* - * crc function from http://svnweb.freebsd.org/base/head/sys/libkern/crc32.c - * - * COPYRIGHT (C) 1986 Gary S. Brown. You may use this program, or - * code or tables extracted from it, as desired without restriction. - */ -static uint32_t calc_crc32(uint32_t crc, const void *buf, size_t size) { - static const uint32_t g_crc32_tab[] = { - 0x00000000, 0x77073096, 0xee0e612c, 0x990951ba, 0x076dc419, 0x706af48f, - 0xe963a535, 0x9e6495a3, 0x0edb8832, 0x79dcb8a4, 0xe0d5e91e, 0x97d2d988, - 0x09b64c2b, 0x7eb17cbd, 0xe7b82d07, 0x90bf1d91, 0x1db71064, 0x6ab020f2, - 0xf3b97148, 0x84be41de, 0x1adad47d, 0x6ddde4eb, 0xf4d4b551, 0x83d385c7, - 0x136c9856, 0x646ba8c0, 0xfd62f97a, 0x8a65c9ec, 0x14015c4f, 0x63066cd9, - 0xfa0f3d63, 0x8d080df5, 0x3b6e20c8, 0x4c69105e, 0xd56041e4, 0xa2677172, - 0x3c03e4d1, 0x4b04d447, 0xd20d85fd, 0xa50ab56b, 0x35b5a8fa, 0x42b2986c, - 0xdbbbc9d6, 0xacbcf940, 0x32d86ce3, 0x45df5c75, 0xdcd60dcf, 0xabd13d59, - 0x26d930ac, 0x51de003a, 0xc8d75180, 0xbfd06116, 0x21b4f4b5, 0x56b3c423, - 0xcfba9599, 0xb8bda50f, 0x2802b89e, 0x5f058808, 0xc60cd9b2, 0xb10be924, - 0x2f6f7c87, 0x58684c11, 0xc1611dab, 0xb6662d3d, 0x76dc4190, 0x01db7106, - 0x98d220bc, 0xefd5102a, 0x71b18589, 0x06b6b51f, 0x9fbfe4a5, 0xe8b8d433, - 0x7807c9a2, 0x0f00f934, 0x9609a88e, 0xe10e9818, 0x7f6a0dbb, 0x086d3d2d, - 0x91646c97, 0xe6635c01, 0x6b6b51f4, 0x1c6c6162, 0x856530d8, 0xf262004e, - 0x6c0695ed, 0x1b01a57b, 0x8208f4c1, 0xf50fc457, 0x65b0d9c6, 0x12b7e950, - 0x8bbeb8ea, 0xfcb9887c, 0x62dd1ddf, 0x15da2d49, 0x8cd37cf3, 0xfbd44c65, - 0x4db26158, 0x3ab551ce, 0xa3bc0074, 0xd4bb30e2, 0x4adfa541, 0x3dd895d7, - 0xa4d1c46d, 0xd3d6f4fb, 0x4369e96a, 0x346ed9fc, 0xad678846, 0xda60b8d0, - 0x44042d73, 0x33031de5, 0xaa0a4c5f, 0xdd0d7cc9, 0x5005713c, 0x270241aa, - 0xbe0b1010, 0xc90c2086, 0x5768b525, 0x206f85b3, 0xb966d409, 0xce61e49f, - 0x5edef90e, 0x29d9c998, 0xb0d09822, 0xc7d7a8b4, 0x59b33d17, 0x2eb40d81, - 0xb7bd5c3b, 0xc0ba6cad, 0xedb88320, 0x9abfb3b6, 0x03b6e20c, 0x74b1d29a, - 0xead54739, 0x9dd277af, 0x04db2615, 0x73dc1683, 0xe3630b12, 0x94643b84, - 0x0d6d6a3e, 0x7a6a5aa8, 0xe40ecf0b, 0x9309ff9d, 0x0a00ae27, 0x7d079eb1, - 0xf00f9344, 0x8708a3d2, 0x1e01f268, 0x6906c2fe, 0xf762575d, 0x806567cb, - 0x196c3671, 0x6e6b06e7, 0xfed41b76, 0x89d32be0, 0x10da7a5a, 0x67dd4acc, - 0xf9b9df6f, 0x8ebeeff9, 0x17b7be43, 0x60b08ed5, 0xd6d6a3e8, 0xa1d1937e, - 0x38d8c2c4, 0x4fdff252, 0xd1bb67f1, 0xa6bc5767, 0x3fb506dd, 0x48b2364b, - 0xd80d2bda, 0xaf0a1b4c, 0x36034af6, 0x41047a60, 0xdf60efc3, 0xa867df55, - 0x316e8eef, 0x4669be79, 0xcb61b38c, 0xbc66831a, 0x256fd2a0, 0x5268e236, - 0xcc0c7795, 0xbb0b4703, 0x220216b9, 0x5505262f, 0xc5ba3bbe, 0xb2bd0b28, - 0x2bb45a92, 0x5cb36a04, 0xc2d7ffa7, 0xb5d0cf31, 0x2cd99e8b, 0x5bdeae1d, - 0x9b64c2b0, 0xec63f226, 0x756aa39c, 0x026d930a, 0x9c0906a9, 0xeb0e363f, - 0x72076785, 0x05005713, 0x95bf4a82, 0xe2b87a14, 0x7bb12bae, 0x0cb61b38, - 0x92d28e9b, 0xe5d5be0d, 0x7cdcefb7, 0x0bdbdf21, 0x86d3d2d4, 0xf1d4e242, - 0x68ddb3f8, 0x1fda836e, 0x81be16cd, 0xf6b9265b, 0x6fb077e1, 0x18b74777, - 0x88085ae6, 0xff0f6a70, 0x66063bca, 0x11010b5c, 0x8f659eff, 0xf862ae69, - 0x616bffd3, 0x166ccf45, 0xa00ae278, 0xd70dd2ee, 0x4e048354, 0x3903b3c2, - 0xa7672661, 0xd06016f7, 0x4969474d, 0x3e6e77db, 0xaed16a4a, 0xd9d65adc, - 0x40df0b66, 0x37d83bf0, 0xa9bcae53, 0xdebb9ec5, 0x47b2cf7f, 0x30b5ffe9, - 0xbdbdf21c, 0xcabac28a, 0x53b39330, 0x24b4a3a6, 0xbad03605, 0xcdd70693, - 0x54de5729, 0x23d967bf, 0xb3667a2e, 0xc4614ab8, 0x5d681b02, 0x2a6f2b94, - 0xb40bbe37, 0xc30c8ea1, 0x5a05df1b, 0x2d02ef8d}; - const uint8_t *p = (const uint8_t *)buf; - - crc = crc ^ ~0U; - while (size--) - crc = g_crc32_tab[(crc ^ *p++) & 0xFF] ^ (crc >> 8); - return crc ^ ~0U; -} - -static uint32_t calc_gnu_debuglink_crc32(const void *buf, size_t size) { - return calc_crc32(0U, buf, size); +static uint32_t calc_crc32(uint32_t init, const DataExtractor &data) { + return llvm::crc32( + init, llvm::makeArrayRef(data.GetDataStart(), data.GetByteSize())); } uint32_t ObjectFileELF::CalculateELFNotesSegmentsCRC32( @@ -509,8 +419,7 @@ uint32_t ObjectFileELF::CalculateELFNotesSegmentsCRC32( break; } - core_notes_crc = calc_crc32(core_notes_crc, segment_data.GetDataStart(), - segment_data.GetByteSize()); + core_notes_crc = calc_crc32(core_notes_crc, segment_data); } } @@ -608,10 +517,9 @@ size_t ObjectFileELF::GetModuleSpecifications( llvm::Triple::OSType spec_ostype = spec.GetArchitecture().GetTriple().getOS(); - if (log) - log->Printf("ObjectFileELF::%s file '%s' module OSABI: %s", - __FUNCTION__, file.GetPath().c_str(), - OSABIAsCString(header.e_ident[EI_OSABI])); + LLDB_LOGF(log, "ObjectFileELF::%s file '%s' module OSABI: %s", + __FUNCTION__, file.GetPath().c_str(), + OSABIAsCString(header.e_ident[EI_OSABI])); // SetArchitecture should have set the vendor to unknown vendor = spec.GetArchitecture().GetTriple().getVendor(); @@ -623,10 +531,10 @@ size_t ObjectFileELF::GetModuleSpecifications( GetOsFromOSABI(header.e_ident[EI_OSABI], ostype); assert(spec_ostype == ostype); if (spec_ostype != llvm::Triple::OSType::UnknownOS) { - if (log) - log->Printf("ObjectFileELF::%s file '%s' set ELF module OS type " - "from ELF header OSABI.", - __FUNCTION__, file.GetPath().c_str()); + LLDB_LOGF(log, + "ObjectFileELF::%s file '%s' set ELF module OS type " + "from ELF header OSABI.", + __FUNCTION__, file.GetPath().c_str()); } data_sp = MapFileData(file, -1, file_offset); @@ -652,12 +560,12 @@ size_t ObjectFileELF::GetModuleSpecifications( llvm::Triple &spec_triple = spec.GetArchitecture().GetTriple(); - if (log) - log->Printf("ObjectFileELF::%s file '%s' module set to triple: %s " - "(architecture %s)", - __FUNCTION__, file.GetPath().c_str(), - spec_triple.getTriple().c_str(), - spec.GetArchitecture().GetArchitectureName()); + LLDB_LOGF(log, + "ObjectFileELF::%s file '%s' module set to triple: %s " + "(architecture %s)", + __FUNCTION__, file.GetPath().c_str(), + spec_triple.getTriple().c_str(), + spec.GetArchitecture().GetArchitectureName()); if (!uuid.IsValid()) { uint32_t core_notes_crc = 0; @@ -682,8 +590,7 @@ size_t ObjectFileELF::GetModuleSpecifications( core_notes_crc = CalculateELFNotesSegmentsCRC32(program_headers, data); } else { - gnu_debuglink_crc = calc_gnu_debuglink_crc32( - data.GetDataStart(), data.GetByteSize()); + gnu_debuglink_crc = calc_crc32(0, data); } } using u32le = llvm::support::ulittle32_t; @@ -721,27 +628,16 @@ ObjectFileELF::ObjectFileELF(const lldb::ModuleSP &module_sp, DataBufferSP &data_sp, lldb::offset_t data_offset, const FileSpec *file, lldb::offset_t file_offset, lldb::offset_t length) - : ObjectFile(module_sp, file, file_offset, length, data_sp, data_offset), - m_header(), m_uuid(), m_gnu_debuglink_file(), m_gnu_debuglink_crc(0), - m_program_headers(), m_section_headers(), m_dynamic_symbols(), - m_filespec_up(), m_entry_point_address(), m_arch_spec() { + : ObjectFile(module_sp, file, file_offset, length, data_sp, data_offset) { if (file) m_file = *file; - ::memset(&m_header, 0, sizeof(m_header)); } ObjectFileELF::ObjectFileELF(const lldb::ModuleSP &module_sp, DataBufferSP &header_data_sp, const lldb::ProcessSP &process_sp, addr_t header_addr) - : ObjectFile(module_sp, process_sp, header_addr, header_data_sp), - m_header(), m_uuid(), m_gnu_debuglink_file(), m_gnu_debuglink_crc(0), - m_program_headers(), m_section_headers(), m_dynamic_symbols(), - m_filespec_up(), m_entry_point_address(), m_arch_spec() { - ::memset(&m_header, 0, sizeof(m_header)); -} - -ObjectFileELF::~ObjectFileELF() {} + : ObjectFile(module_sp, process_sp, header_addr, header_data_sp) {} bool ObjectFileELF::IsExecutable() const { return ((m_header.e_type & ET_EXEC) != 0) || (m_header.e_entry != 0); @@ -872,8 +768,7 @@ UUID ObjectFileELF::GetUUID() { } } else { if (!m_gnu_debuglink_crc) - m_gnu_debuglink_crc = calc_gnu_debuglink_crc32(m_data.GetDataStart(), - m_data.GetByteSize()); + m_gnu_debuglink_crc = calc_crc32(0, m_data); if (m_gnu_debuglink_crc) { // Use 4 bytes of crc from the .gnu_debuglink section. u32le data(m_gnu_debuglink_crc); @@ -885,14 +780,10 @@ UUID ObjectFileELF::GetUUID() { return m_uuid; } -lldb_private::FileSpecList ObjectFileELF::GetDebugSymbolFilePaths() { - FileSpecList file_spec_list; - - if (!m_gnu_debuglink_file.empty()) { - FileSpec file_spec(m_gnu_debuglink_file); - file_spec_list.Append(file_spec); - } - return file_spec_list; +llvm::Optional<FileSpec> ObjectFileELF::GetDebugLink() { + if (m_gnu_debuglink_file.empty()) + return llvm::None; + return FileSpec(m_gnu_debuglink_file); } uint32_t ObjectFileELF::GetDependentModules(FileSpecList &files) { @@ -1120,9 +1011,8 @@ ObjectFileELF::RefineModuleDetailsFromNote(lldb_private::DataExtractor &data, return error; } - if (log) - log->Printf("ObjectFileELF::%s parsing note name='%s', type=%" PRIu32, - __FUNCTION__, note.n_name.c_str(), note.n_type); + LLDB_LOGF(log, "ObjectFileELF::%s parsing note name='%s', type=%" PRIu32, + __FUNCTION__, note.n_name.c_str(), note.n_type); // Process FreeBSD ELF notes. if ((note.n_name == LLDB_NT_OWNER_FREEBSD) && @@ -1147,11 +1037,11 @@ ObjectFileELF::RefineModuleDetailsFromNote(lldb_private::DataExtractor &data, arch_spec.GetTriple().setOSName(os_name); arch_spec.GetTriple().setVendor(llvm::Triple::VendorType::UnknownVendor); - if (log) - log->Printf("ObjectFileELF::%s detected FreeBSD %" PRIu32 ".%" PRIu32 - ".%" PRIu32, - __FUNCTION__, version_major, version_minor, - static_cast<uint32_t>(version_info % 1000)); + LLDB_LOGF(log, + "ObjectFileELF::%s detected FreeBSD %" PRIu32 ".%" PRIu32 + ".%" PRIu32, + __FUNCTION__, version_major, version_minor, + static_cast<uint32_t>(version_info % 1000)); } // Process GNU ELF notes. else if (note.n_name == LLDB_NT_OWNER_GNU) { @@ -1172,12 +1062,11 @@ ObjectFileELF::RefineModuleDetailsFromNote(lldb_private::DataExtractor &data, arch_spec.GetTriple().setOS(llvm::Triple::OSType::Linux); arch_spec.GetTriple().setVendor( llvm::Triple::VendorType::UnknownVendor); - if (log) - log->Printf( - "ObjectFileELF::%s detected Linux, min version %" PRIu32 - ".%" PRIu32 ".%" PRIu32, - __FUNCTION__, version_info[1], version_info[2], - version_info[3]); + LLDB_LOGF(log, + "ObjectFileELF::%s detected Linux, min version %" PRIu32 + ".%" PRIu32 ".%" PRIu32, + __FUNCTION__, version_info[1], version_info[2], + version_info[3]); // FIXME we have the minimal version number, we could be propagating // that. version_info[1] = OS Major, version_info[2] = OS Minor, // version_info[3] = Revision. @@ -1186,30 +1075,28 @@ ObjectFileELF::RefineModuleDetailsFromNote(lldb_private::DataExtractor &data, arch_spec.GetTriple().setOS(llvm::Triple::OSType::UnknownOS); arch_spec.GetTriple().setVendor( llvm::Triple::VendorType::UnknownVendor); - if (log) - log->Printf("ObjectFileELF::%s detected Hurd (unsupported), min " - "version %" PRIu32 ".%" PRIu32 ".%" PRIu32, - __FUNCTION__, version_info[1], version_info[2], - version_info[3]); + LLDB_LOGF(log, + "ObjectFileELF::%s detected Hurd (unsupported), min " + "version %" PRIu32 ".%" PRIu32 ".%" PRIu32, + __FUNCTION__, version_info[1], version_info[2], + version_info[3]); break; case LLDB_NT_GNU_ABI_OS_SOLARIS: arch_spec.GetTriple().setOS(llvm::Triple::OSType::Solaris); arch_spec.GetTriple().setVendor( llvm::Triple::VendorType::UnknownVendor); - if (log) - log->Printf( - "ObjectFileELF::%s detected Solaris, min version %" PRIu32 - ".%" PRIu32 ".%" PRIu32, - __FUNCTION__, version_info[1], version_info[2], - version_info[3]); + LLDB_LOGF(log, + "ObjectFileELF::%s detected Solaris, min version %" PRIu32 + ".%" PRIu32 ".%" PRIu32, + __FUNCTION__, version_info[1], version_info[2], + version_info[3]); break; default: - if (log) - log->Printf( - "ObjectFileELF::%s unrecognized OS in note, id %" PRIu32 - ", min version %" PRIu32 ".%" PRIu32 ".%" PRIu32, - __FUNCTION__, version_info[0], version_info[1], - version_info[2], version_info[3]); + LLDB_LOGF(log, + "ObjectFileELF::%s unrecognized OS in note, id %" PRIu32 + ", min version %" PRIu32 ".%" PRIu32 ".%" PRIu32, + __FUNCTION__, version_info[0], version_info[1], + version_info[2], version_info[3]); break; } } @@ -1618,9 +1505,8 @@ size_t ObjectFileELF::GetSectionHeaderInfo(SectionHeaderColl §ion_headers, section_size) == section_size)) { Status error = RefineModuleDetailsFromNote(data, arch_spec, uuid); if (error.Fail()) { - if (log) - log->Printf("ObjectFileELF::%s ELF note processing failed: %s", - __FUNCTION__, error.AsCString()); + LLDB_LOGF(log, "ObjectFileELF::%s ELF note processing failed: %s", + __FUNCTION__, error.AsCString()); } } } @@ -1790,6 +1676,8 @@ class VMAddressProvider { VMMap Segments = VMMap(Alloc); VMMap Sections = VMMap(Alloc); lldb_private::Log *Log = GetLogIfAllCategoriesSet(LIBLLDB_LOG_MODULES); + size_t SegmentCount = 0; + std::string SegmentName; VMRange GetVMRange(const ELFSectionHeader &H) { addr_t Address = H.sh_addr; @@ -1804,18 +1692,23 @@ class VMAddressProvider { } public: - VMAddressProvider(ObjectFile::Type Type) : ObjectType(Type) {} + VMAddressProvider(ObjectFile::Type Type, llvm::StringRef SegmentName) + : ObjectType(Type), SegmentName(SegmentName) {} + + std::string GetNextSegmentName() const { + return llvm::formatv("{0}[{1}]", SegmentName, SegmentCount).str(); + } llvm::Optional<VMRange> GetAddressInfo(const ELFProgramHeader &H) { if (H.p_memsz == 0) { - LLDB_LOG(Log, - "Ignoring zero-sized PT_LOAD segment. Corrupt object file?"); + LLDB_LOG(Log, "Ignoring zero-sized {0} segment. Corrupt object file?", + SegmentName); return llvm::None; } if (Segments.overlaps(H.p_vaddr, H.p_vaddr + H.p_memsz)) { - LLDB_LOG(Log, - "Ignoring overlapping PT_LOAD segment. Corrupt object file?"); + LLDB_LOG(Log, "Ignoring overlapping {0} segment. Corrupt object file?", + SegmentName); return llvm::None; } return VMRange(H.p_vaddr, H.p_memsz); @@ -1850,6 +1743,7 @@ public: void AddSegment(const VMRange &Range, SectionSP Seg) { Segments.insert(Range.GetRangeBase(), Range.GetRangeEnd(), std::move(Seg)); + ++SegmentCount; } void AddSection(SectionAddressInfo Info, SectionSP Sect) { @@ -1867,29 +1761,32 @@ void ObjectFileELF::CreateSections(SectionList &unified_section_list) { if (m_sections_up) return; - m_sections_up = llvm::make_unique<SectionList>(); - VMAddressProvider address_provider(GetType()); + m_sections_up = std::make_unique<SectionList>(); + VMAddressProvider regular_provider(GetType(), "PT_LOAD"); + VMAddressProvider tls_provider(GetType(), "PT_TLS"); - size_t LoadID = 0; for (const auto &EnumPHdr : llvm::enumerate(ProgramHeaders())) { const ELFProgramHeader &PHdr = EnumPHdr.value(); - if (PHdr.p_type != PT_LOAD) + if (PHdr.p_type != PT_LOAD && PHdr.p_type != PT_TLS) continue; - auto InfoOr = address_provider.GetAddressInfo(PHdr); + VMAddressProvider &provider = + PHdr.p_type == PT_TLS ? tls_provider : regular_provider; + auto InfoOr = provider.GetAddressInfo(PHdr); if (!InfoOr) continue; - ConstString Name(("PT_LOAD[" + llvm::Twine(LoadID++) + "]").str()); uint32_t Log2Align = llvm::Log2_64(std::max<elf_xword>(PHdr.p_align, 1)); SectionSP Segment = std::make_shared<Section>( - GetModule(), this, SegmentID(EnumPHdr.index()), Name, - eSectionTypeContainer, InfoOr->GetRangeBase(), InfoOr->GetByteSize(), - PHdr.p_offset, PHdr.p_filesz, Log2Align, /*flags*/ 0); + GetModule(), this, SegmentID(EnumPHdr.index()), + ConstString(provider.GetNextSegmentName()), eSectionTypeContainer, + InfoOr->GetRangeBase(), InfoOr->GetByteSize(), PHdr.p_offset, + PHdr.p_filesz, Log2Align, /*flags*/ 0); Segment->SetPermissions(GetPermissions(PHdr)); + Segment->SetIsThreadSpecific(PHdr.p_type == PT_TLS); m_sections_up->AddSection(Segment); - address_provider.AddSegment(*InfoOr, std::move(Segment)); + provider.AddSegment(*InfoOr, std::move(Segment)); } ParseSectionHeaders(); @@ -1904,7 +1801,9 @@ void ObjectFileELF::CreateSections(SectionList &unified_section_list) { const uint64_t file_size = header.sh_type == SHT_NOBITS ? 0 : header.sh_size; - auto InfoOr = address_provider.GetAddressInfo(header); + VMAddressProvider &provider = + header.sh_flags & SHF_TLS ? tls_provider : regular_provider; + auto InfoOr = provider.GetAddressInfo(header); if (!InfoOr) continue; @@ -1935,13 +1834,77 @@ void ObjectFileELF::CreateSections(SectionList &unified_section_list) { section_sp->SetIsThreadSpecific(header.sh_flags & SHF_TLS); (InfoOr->Segment ? InfoOr->Segment->GetChildren() : *m_sections_up) .AddSection(section_sp); - address_provider.AddSection(std::move(*InfoOr), std::move(section_sp)); + provider.AddSection(std::move(*InfoOr), std::move(section_sp)); } // For eTypeDebugInfo files, the Symbol Vendor will take care of updating the // unified section list. if (GetType() != eTypeDebugInfo) unified_section_list = *m_sections_up; + + // If there's a .gnu_debugdata section, we'll try to read the .symtab that's + // embedded in there and replace the one in the original object file (if any). + // If there's none in the orignal object file, we add it to it. + if (auto gdd_obj_file = GetGnuDebugDataObjectFile()) { + if (auto gdd_objfile_section_list = gdd_obj_file->GetSectionList()) { + if (SectionSP symtab_section_sp = + gdd_objfile_section_list->FindSectionByType( + eSectionTypeELFSymbolTable, true)) { + SectionSP module_section_sp = unified_section_list.FindSectionByType( + eSectionTypeELFSymbolTable, true); + if (module_section_sp) + unified_section_list.ReplaceSection(module_section_sp->GetID(), + symtab_section_sp); + else + unified_section_list.AddSection(symtab_section_sp); + } + } + } +} + +std::shared_ptr<ObjectFileELF> ObjectFileELF::GetGnuDebugDataObjectFile() { + if (m_gnu_debug_data_object_file != nullptr) + return m_gnu_debug_data_object_file; + + SectionSP section = + GetSectionList()->FindSectionByName(ConstString(".gnu_debugdata")); + if (!section) + return nullptr; + + if (!lldb_private::lzma::isAvailable()) { + GetModule()->ReportWarning( + "No LZMA support found for reading .gnu_debugdata section"); + return nullptr; + } + + // Uncompress the data + DataExtractor data; + section->GetSectionData(data); + llvm::SmallVector<uint8_t, 0> uncompressedData; + auto err = lldb_private::lzma::uncompress(data.GetData(), uncompressedData); + if (err) { + GetModule()->ReportWarning( + "An error occurred while decompression the section %s: %s", + section->GetName().AsCString(), llvm::toString(std::move(err)).c_str()); + return nullptr; + } + + // Construct ObjectFileELF object from decompressed buffer + DataBufferSP gdd_data_buf( + new DataBufferHeap(uncompressedData.data(), uncompressedData.size())); + auto fspec = GetFileSpec().CopyByAppendingPathComponent( + llvm::StringRef("gnu_debugdata")); + m_gnu_debug_data_object_file.reset(new ObjectFileELF( + GetModule(), gdd_data_buf, 0, &fspec, 0, gdd_data_buf->GetByteSize())); + + // This line is essential; otherwise a breakpoint can be set but not hit. + m_gnu_debug_data_object_file->SetType(ObjectFile::eTypeDebugInfo); + + ArchSpec spec = m_gnu_debug_data_object_file->GetArchitecture(); + if (spec && m_gnu_debug_data_object_file->SetModulesArchitecture(spec)) + return m_gnu_debug_data_object_file; + + return nullptr; } // Find the arm/aarch64 mapping symbol character in the given symbol name. @@ -2246,8 +2209,6 @@ unsigned ObjectFileELF::ParseSymbols(Symtab *symtab, user_id_t start_id, bool is_global = symbol.getBinding() == STB_GLOBAL; uint32_t flags = symbol.st_other << 8 | symbol.st_info | additional_flags; - bool is_mangled = (symbol_name[0] == '_' && symbol_name[1] == 'Z'); - llvm::StringRef symbol_ref(symbol_name); // Symbol names may contain @VERSION suffixes. Find those and strip them @@ -2255,7 +2216,7 @@ unsigned ObjectFileELF::ParseSymbols(Symtab *symtab, user_id_t start_id, size_t version_pos = symbol_ref.find('@'); bool has_suffix = version_pos != llvm::StringRef::npos; llvm::StringRef symbol_bare = symbol_ref.substr(0, version_pos); - Mangled mangled(ConstString(symbol_bare), is_mangled); + Mangled mangled(symbol_bare); // Now append the suffix back to mangled and unmangled names. Only do it if // the demangling was successful (string is not empty). @@ -2486,14 +2447,11 @@ static unsigned ParsePLTRelocations( break; const char *symbol_name = strtab_data.PeekCStr(symbol.st_name); - bool is_mangled = - symbol_name ? (symbol_name[0] == '_' && symbol_name[1] == 'Z') : false; uint64_t plt_index = plt_offset + i * plt_entsize; Symbol jump_symbol( i + start_id, // Symbol table index symbol_name, // symbol name. - is_mangled, // is the symbol name mangled? eSymbolTypeTrampoline, // Type of this symbol false, // Is this globally visible? false, // Is this symbol debug info? @@ -2654,7 +2612,7 @@ unsigned ObjectFileELF::ApplyRelocations( ((int64_t)value > INT32_MAX && (int64_t)value < INT32_MIN))) { Log *log = lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_MODULES); - log->Printf("Failed to apply debug info relocations"); + LLDB_LOGF(log, "Failed to apply debug info relocations"); break; } uint32_t truncated_addr = (value & 0xFFFFFFFF); @@ -2749,19 +2707,29 @@ Symtab *ObjectFileELF::GetSymtab() { // while the reverse is not necessarily true. Section *symtab = section_list->FindSectionByType(eSectionTypeELFSymbolTable, true).get(); - if (!symtab) { - // The symtab section is non-allocable and can be stripped, so if it - // doesn't exist then use the dynsym section which should always be - // there. - symtab = - section_list->FindSectionByType(eSectionTypeELFDynamicSymbols, true) - .get(); - } if (symtab) { m_symtab_up.reset(new Symtab(symtab->GetObjectFile())); symbol_id += ParseSymbolTable(m_symtab_up.get(), symbol_id, symtab); } + // The symtab section is non-allocable and can be stripped, while the + // .dynsym section which should always be always be there. To support the + // minidebuginfo case we parse .dynsym when there's a .gnu_debuginfo + // section, nomatter if .symtab was already parsed or not. This is because + // minidebuginfo normally removes the .symtab symbols which have their + // matching .dynsym counterparts. + if (!symtab || + GetSectionList()->FindSectionByName(ConstString(".gnu_debugdata"))) { + Section *dynsym = + section_list->FindSectionByType(eSectionTypeELFDynamicSymbols, true) + .get(); + if (dynsym) { + if (!m_symtab_up) + m_symtab_up.reset(new Symtab(dynsym->GetObjectFile())); + symbol_id += ParseSymbolTable(m_symtab_up.get(), symbol_id, dynsym); + } + } + // DT_JMPREL // If present, this entry's d_ptr member holds the address of // relocation @@ -2803,6 +2771,50 @@ Symtab *ObjectFileELF::GetSymtab() { if (m_symtab_up == nullptr) m_symtab_up.reset(new Symtab(this)); + // In the event that there's no symbol entry for the entry point we'll + // artifically create one. We delegate to the symtab object the figuring + // out of the proper size, this will usually make it span til the next + // symbol it finds in the section. This means that if there are missing + // symbols the entry point might span beyond its function definition. + // We're fine with this as it doesn't make it worse than not having a + // symbol entry at all. + if (CalculateType() == eTypeExecutable) { + ArchSpec arch = GetArchitecture(); + auto entry_point_addr = GetEntryPointAddress(); + bool is_valid_entry_point = + entry_point_addr.IsValid() && entry_point_addr.IsSectionOffset(); + addr_t entry_point_file_addr = entry_point_addr.GetFileAddress(); + if (is_valid_entry_point && !m_symtab_up->FindSymbolContainingFileAddress( + entry_point_file_addr)) { + uint64_t symbol_id = m_symtab_up->GetNumSymbols(); + Symbol symbol(symbol_id, + GetNextSyntheticSymbolName().GetCString(), // Symbol name. + eSymbolTypeCode, // Type of this symbol. + true, // Is this globally visible? + false, // Is this symbol debug info? + false, // Is this symbol a trampoline? + true, // Is this symbol artificial? + entry_point_addr.GetSection(), // Section where this + // symbol is defined. + 0, // Offset in section or symbol value. + 0, // Size. + false, // Size is valid. + false, // Contains linker annotations? + 0); // Symbol flags. + m_symtab_up->AddSymbol(symbol); + // When the entry point is arm thumb we need to explicitly set its + // class address to reflect that. This is important because expression + // evaluation relies on correctly setting a breakpoint at this + // address. + if (arch.GetMachine() == llvm::Triple::arm && + (entry_point_file_addr & 1)) + m_address_class_map[entry_point_file_addr ^ 1] = + AddressClass::eCodeAlternateISA; + else + m_address_class_map[entry_point_file_addr] = AddressClass::eCode; + } + } + m_symtab_up->CalculateSymbolSizes(); } @@ -2881,7 +2893,6 @@ void ObjectFileELF::ParseUnwindSymbols(Symtab *symbol_table, Symbol eh_symbol( symbol_id, // Symbol table index. symbol_name, // Symbol name. - false, // Is the symbol name mangled? eSymbolTypeCode, // Type of this symbol. true, // Is this globally visible? false, // Is this symbol debug info? diff --git a/source/Plugins/ObjectFile/ELF/ObjectFileELF.h b/source/Plugins/ObjectFile/ELF/ObjectFileELF.h index b63a5d14d4f5..3b273896cb59 100644 --- a/source/Plugins/ObjectFile/ELF/ObjectFileELF.h +++ b/source/Plugins/ObjectFile/ELF/ObjectFileELF.h @@ -56,8 +56,6 @@ struct ELFNote { /// the ObjectFile protocol. class ObjectFileELF : public lldb_private::ObjectFile { public: - ~ObjectFileELF() override; - // Static Functions static void Initialize(); @@ -91,6 +89,13 @@ public: uint32_t GetPluginVersion() override; + // LLVM RTTI support + static char ID; + bool isA(const void *ClassID) const override { + return ClassID == &ID || ObjectFile::isA(ClassID); + } + static bool classof(const ObjectFile *obj) { return obj->isA(&ID); } + // ObjectFile Protocol. bool ParseHeader() override; @@ -117,7 +122,9 @@ public: lldb_private::UUID GetUUID() override; - lldb_private::FileSpecList GetDebugSymbolFilePaths() override; + /// Return the contents of the .gnu_debuglink section, if the object file + /// contains it. + llvm::Optional<lldb_private::FileSpec> GetDebugLink(); uint32_t GetDependentModules(lldb_private::FileSpecList &files) override; @@ -190,7 +197,7 @@ private: /// ELF .gnu_debuglink file and crc data if available. std::string m_gnu_debuglink_file; - uint32_t m_gnu_debuglink_crc; + uint32_t m_gnu_debuglink_crc = 0; /// Collection of program headers. ProgramHeaderColl m_program_headers; @@ -201,6 +208,10 @@ private: /// Collection of symbols from the dynamic table. DynamicSymbolColl m_dynamic_symbols; + /// Object file parsed from .gnu_debugdata section (\sa + /// GetGnuDebugDataObjectFile()) + std::shared_ptr<ObjectFileELF> m_gnu_debug_data_object_file; + /// List of file specifications corresponding to the modules (shared /// libraries) on which this object file depends. mutable std::unique_ptr<lldb_private::FileSpecList> m_filespec_up; @@ -376,6 +387,14 @@ private: lldb_private::UUID &uuid); bool AnySegmentHasPhysicalAddress(); + + /// Takes the .gnu_debugdata and returns the decompressed object file that is + /// stored within that section. + /// + /// \returns either the decompressed object file stored within the + /// .gnu_debugdata section or \c nullptr if an error occured or if there's no + /// section with that name. + std::shared_ptr<ObjectFileELF> GetGnuDebugDataObjectFile(); }; #endif // liblldb_ObjectFileELF_h_ diff --git a/source/Plugins/ObjectFile/JIT/ObjectFileJIT.cpp b/source/Plugins/ObjectFile/JIT/ObjectFileJIT.cpp index eaf973da3835..c55b96d9110b 100644 --- a/source/Plugins/ObjectFile/JIT/ObjectFileJIT.cpp +++ b/source/Plugins/ObjectFile/JIT/ObjectFileJIT.cpp @@ -39,6 +39,8 @@ using namespace lldb; using namespace lldb_private; +char ObjectFileJIT::ID; + void ObjectFileJIT::Initialize() { PluginManager::RegisterPlugin(GetPluginNameStatic(), GetPluginDescriptionStatic(), CreateInstance, diff --git a/source/Plugins/ObjectFile/JIT/ObjectFileJIT.h b/source/Plugins/ObjectFile/JIT/ObjectFileJIT.h index 99241126cd1a..c992683cfc3c 100644 --- a/source/Plugins/ObjectFile/JIT/ObjectFileJIT.h +++ b/source/Plugins/ObjectFile/JIT/ObjectFileJIT.h @@ -46,6 +46,13 @@ public: lldb::offset_t length, lldb_private::ModuleSpecList &specs); + // LLVM RTTI support + static char ID; + bool isA(const void *ClassID) const override { + return ClassID == &ID || ObjectFile::isA(ClassID); + } + static bool classof(const ObjectFile *obj) { return obj->isA(&ID); } + // Member Functions bool ParseHeader() override; diff --git a/source/Plugins/OperatingSystem/Python/OperatingSystemPython.cpp b/source/Plugins/OperatingSystem/Python/OperatingSystemPython.cpp index c1fe0cc8ddda..b777a5319104 100644 --- a/source/Plugins/OperatingSystem/Python/OperatingSystemPython.cpp +++ b/source/Plugins/OperatingSystem/Python/OperatingSystemPython.cpp @@ -120,10 +120,10 @@ DynamicRegisterInfo *OperatingSystemPython::GetDynamicRegisterInfo() { return nullptr; Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_OS)); - if (log) - log->Printf("OperatingSystemPython::GetDynamicRegisterInfo() fetching " - "thread register definitions from python for pid %" PRIu64, - m_process->GetID()); + LLDB_LOGF(log, + "OperatingSystemPython::GetDynamicRegisterInfo() fetching " + "thread register definitions from python for pid %" PRIu64, + m_process->GetID()); StructuredData::DictionarySP dictionary = m_interpreter->OSPlugin_RegisterInfo(m_python_object_sp); @@ -169,12 +169,12 @@ bool OperatingSystemPython::UpdateThreadList(ThreadList &old_thread_list, api_lock.try_lock(); auto interpreter_lock = m_interpreter->AcquireInterpreterLock(); - if (log) - log->Printf("OperatingSystemPython::UpdateThreadList() fetching thread " - "data from python for pid %" PRIu64, - m_process->GetID()); + LLDB_LOGF(log, + "OperatingSystemPython::UpdateThreadList() fetching thread " + "data from python for pid %" PRIu64, + m_process->GetID()); - // The threads that are in "new_thread_list" upon entry are the threads from + // The threads that are in "core_thread_list" upon entry are the threads from // the lldb_private::Process subclass, no memory threads will be in this // list. StructuredData::ArraySP threads_list = @@ -190,7 +190,7 @@ bool OperatingSystemPython::UpdateThreadList(ThreadList &old_thread_list, if (log) { StreamString strm; threads_list->Dump(strm); - log->Printf("threads_list = %s", strm.GetData()); + LLDB_LOGF(log, "threads_list = %s", strm.GetData()); } const uint32_t num_threads = threads_list->GetSize(); @@ -316,21 +316,21 @@ OperatingSystemPython::CreateRegisterContextForThread(Thread *thread, if (reg_data_addr != LLDB_INVALID_ADDRESS) { // The registers data is in contiguous memory, just create the register // context using the address provided - if (log) - log->Printf("OperatingSystemPython::CreateRegisterContextForThread (tid " - "= 0x%" PRIx64 ", 0x%" PRIx64 ", reg_data_addr = 0x%" PRIx64 - ") creating memory register context", - thread->GetID(), thread->GetProtocolID(), reg_data_addr); + LLDB_LOGF(log, + "OperatingSystemPython::CreateRegisterContextForThread (tid " + "= 0x%" PRIx64 ", 0x%" PRIx64 ", reg_data_addr = 0x%" PRIx64 + ") creating memory register context", + thread->GetID(), thread->GetProtocolID(), reg_data_addr); reg_ctx_sp = std::make_shared<RegisterContextMemory>( *thread, 0, *GetDynamicRegisterInfo(), reg_data_addr); } else { // No register data address is provided, query the python plug-in to let it // make up the data as it sees fit - if (log) - log->Printf("OperatingSystemPython::CreateRegisterContextForThread (tid " - "= 0x%" PRIx64 ", 0x%" PRIx64 - ") fetching register data from python", - thread->GetID(), thread->GetProtocolID()); + LLDB_LOGF(log, + "OperatingSystemPython::CreateRegisterContextForThread (tid " + "= 0x%" PRIx64 ", 0x%" PRIx64 + ") fetching register data from python", + thread->GetID(), thread->GetProtocolID()); StructuredData::StringSP reg_context_data = m_interpreter->OSPlugin_RegisterContextData(m_python_object_sp, @@ -351,10 +351,10 @@ OperatingSystemPython::CreateRegisterContextForThread(Thread *thread, // if we still have no register data, fallback on a dummy context to avoid // crashing if (!reg_ctx_sp) { - if (log) - log->Printf("OperatingSystemPython::CreateRegisterContextForThread (tid " - "= 0x%" PRIx64 ") forcing a dummy register context", - thread->GetID()); + LLDB_LOGF(log, + "OperatingSystemPython::CreateRegisterContextForThread (tid " + "= 0x%" PRIx64 ") forcing a dummy register context", + thread->GetID()); reg_ctx_sp = std::make_shared<RegisterContextDummy>( *thread, 0, target.GetArchitecture().GetAddressByteSize()); } @@ -375,10 +375,10 @@ lldb::ThreadSP OperatingSystemPython::CreateThread(lldb::tid_t tid, addr_t context) { Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_THREAD)); - if (log) - log->Printf("OperatingSystemPython::CreateThread (tid = 0x%" PRIx64 - ", context = 0x%" PRIx64 ") fetching register data from python", - tid, context); + LLDB_LOGF(log, + "OperatingSystemPython::CreateThread (tid = 0x%" PRIx64 + ", context = 0x%" PRIx64 ") fetching register data from python", + tid, context); if (m_interpreter && m_python_object_sp) { // First thing we have to do is to try to get the API lock, and the diff --git a/source/Plugins/Platform/POSIX/PlatformPOSIX.cpp b/source/Plugins/Platform/POSIX/PlatformPOSIX.cpp index d10557596ff8..b12e21deb459 100644 --- a/source/Plugins/Platform/POSIX/PlatformPOSIX.cpp +++ b/source/Plugins/Platform/POSIX/PlatformPOSIX.cpp @@ -27,11 +27,11 @@ #include "lldb/Target/ExecutionContext.h" #include "lldb/Target/Process.h" #include "lldb/Target/Thread.h" -#include "lldb/Utility/CleanUp.h" #include "lldb/Utility/DataBufferHeap.h" #include "lldb/Utility/FileSpec.h" #include "lldb/Utility/Log.h" #include "lldb/Utility/StreamString.h" +#include "llvm/ADT/ScopeExit.h" using namespace lldb; using namespace lldb_private; @@ -276,8 +276,7 @@ PlatformPOSIX::PutFile(const lldb_private::FileSpec &source, } else command.Printf("rsync %s %s %s:%s", GetRSyncOpts(), src_path.c_str(), GetHostname(), dst_path.c_str()); - if (log) - log->Printf("[PutFile] Running command: %s\n", command.GetData()); + LLDB_LOGF(log, "[PutFile] Running command: %s\n", command.GetData()); int retcode; Host::RunShellCommand(command.GetData(), nullptr, &retcode, nullptr, nullptr, std::chrono::minutes(1)); @@ -334,8 +333,7 @@ lldb_private::Status PlatformPOSIX::GetFile( command.Printf("rsync %s %s:%s %s", GetRSyncOpts(), m_remote_platform_sp->GetHostname(), src_path.c_str(), dst_path.c_str()); - if (log) - log->Printf("[GetFile] Running command: %s\n", command.GetData()); + LLDB_LOGF(log, "[GetFile] Running command: %s\n", command.GetData()); int retcode; Host::RunShellCommand(command.GetData(), nullptr, &retcode, nullptr, nullptr, std::chrono::minutes(1)); @@ -348,8 +346,7 @@ lldb_private::Status PlatformPOSIX::GetFile( // read/write, read/write, read/write, ... // close src // close dst - if (log) - log->Printf("[GetFile] Using block by block transfer....\n"); + LLDB_LOGF(log, "[GetFile] Using block by block transfer....\n"); Status error; user_id_t fd_src = OpenFile(source, File::eOpenOptionRead, lldb::eFilePermissionsFileDefault, error); @@ -515,24 +512,21 @@ lldb::ProcessSP PlatformPOSIX::Attach(ProcessAttachInfo &attach_info, error = debugger.GetTargetList().CreateTarget( debugger, "", "", eLoadDependentsNo, nullptr, new_target_sp); target = new_target_sp.get(); - if (log) - log->Printf("PlatformPOSIX::%s created new target", __FUNCTION__); + LLDB_LOGF(log, "PlatformPOSIX::%s created new target", __FUNCTION__); } else { error.Clear(); - if (log) - log->Printf("PlatformPOSIX::%s target already existed, setting target", - __FUNCTION__); + LLDB_LOGF(log, "PlatformPOSIX::%s target already existed, setting target", + __FUNCTION__); } if (target && error.Success()) { debugger.GetTargetList().SetSelectedTarget(target); if (log) { ModuleSP exe_module_sp = target->GetExecutableModule(); - log->Printf("PlatformPOSIX::%s set selected target to %p %s", - __FUNCTION__, (void *)target, - exe_module_sp - ? exe_module_sp->GetFileSpec().GetPath().c_str() - : "<null>"); + LLDB_LOGF(log, "PlatformPOSIX::%s set selected target to %p %s", + __FUNCTION__, (void *)target, + exe_module_sp ? exe_module_sp->GetFileSpec().GetPath().c_str() + : "<null>"); } process_sp = @@ -804,12 +798,13 @@ uint32_t PlatformPOSIX::DoLoadImage(lldb_private::Process *process, "for path: %s", utility_error.AsCString()); return LLDB_INVALID_IMAGE_TOKEN; } - + // Make sure we deallocate the input string memory: - CleanUp path_cleanup([process, path_addr] { - process->DeallocateMemory(path_addr); + auto path_cleanup = llvm::make_scope_exit([process, path_addr] { + // Deallocate the buffer. + process->DeallocateMemory(path_addr); }); - + process->WriteMemory(path_addr, path.c_str(), path_len, utility_error); if (utility_error.Fail()) { error.SetErrorStringWithFormat("dlopen error: could not write path string:" @@ -830,21 +825,24 @@ uint32_t PlatformPOSIX::DoLoadImage(lldb_private::Process *process, } // Make sure we deallocate the result structure memory - CleanUp return_cleanup([process, return_addr] { - process->DeallocateMemory(return_addr); + auto return_cleanup = llvm::make_scope_exit([process, return_addr] { + // Deallocate the buffer + process->DeallocateMemory(return_addr); }); - + // This will be the address of the storage for paths, if we are using them, // or nullptr to signal we aren't. lldb::addr_t path_array_addr = 0x0; - llvm::Optional<CleanUp> path_array_cleanup; + llvm::Optional<llvm::detail::scope_exit<std::function<void()>>> + path_array_cleanup; // This is the address to a buffer large enough to hold the largest path // conjoined with the library name we're passing in. This is a convenience // to avoid having to call malloc in the dlopen function. lldb::addr_t buffer_addr = 0x0; - llvm::Optional<CleanUp> buffer_cleanup; - + llvm::Optional<llvm::detail::scope_exit<std::function<void()>>> + buffer_cleanup; + // Set the values into our args and write them to the target: if (paths != nullptr) { // First insert the paths into the target. This is expected to be a @@ -877,8 +875,9 @@ uint32_t PlatformPOSIX::DoLoadImage(lldb_private::Process *process, } // Make sure we deallocate the paths array. - path_array_cleanup.emplace([process, path_array_addr] { - process->DeallocateMemory(path_array_addr); + path_array_cleanup.emplace([process, path_array_addr]() { + // Deallocate the path array. + process->DeallocateMemory(path_array_addr); }); process->WriteMemory(path_array_addr, path_array.data(), @@ -904,8 +903,9 @@ uint32_t PlatformPOSIX::DoLoadImage(lldb_private::Process *process, } // Make sure we deallocate the buffer memory: - buffer_cleanup.emplace([process, buffer_addr] { - process->DeallocateMemory(buffer_addr); + buffer_cleanup.emplace([process, buffer_addr]() { + // Deallocate the buffer. + process->DeallocateMemory(buffer_addr); }); } @@ -930,10 +930,11 @@ uint32_t PlatformPOSIX::DoLoadImage(lldb_private::Process *process, // Make sure we clean up the args structure. We can't reuse it because the // Platform lives longer than the process and the Platforms don't get a // signal to clean up cached data when a process goes away. - CleanUp args_cleanup([do_dlopen_function, &exe_ctx, func_args_addr] { - do_dlopen_function->DeallocateFunctionResults(exe_ctx, func_args_addr); - }); - + auto args_cleanup = + llvm::make_scope_exit([do_dlopen_function, &exe_ctx, func_args_addr] { + do_dlopen_function->DeallocateFunctionResults(exe_ctx, func_args_addr); + }); + // Now run the caller: EvaluateExpressionOptions options; options.SetExecutionPolicy(eExecutionPolicyAlways); diff --git a/source/Plugins/Platform/gdb-server/PlatformRemoteGDBServer.cpp b/source/Plugins/Platform/gdb-server/PlatformRemoteGDBServer.cpp index 9c52b59e2b06..1e62ddfe94fd 100644 --- a/source/Plugins/Platform/gdb-server/PlatformRemoteGDBServer.cpp +++ b/source/Plugins/Platform/gdb-server/PlatformRemoteGDBServer.cpp @@ -169,21 +169,21 @@ bool PlatformRemoteGDBServer::GetModuleSpec(const FileSpec &module_file_spec, const auto module_path = module_file_spec.GetPath(false); if (!m_gdb_client.GetModuleInfo(module_file_spec, arch, module_spec)) { - if (log) - log->Printf( - "PlatformRemoteGDBServer::%s - failed to get module info for %s:%s", - __FUNCTION__, module_path.c_str(), - arch.GetTriple().getTriple().c_str()); + LLDB_LOGF( + log, + "PlatformRemoteGDBServer::%s - failed to get module info for %s:%s", + __FUNCTION__, module_path.c_str(), + arch.GetTriple().getTriple().c_str()); return false; } if (log) { StreamString stream; module_spec.Dump(stream); - log->Printf( - "PlatformRemoteGDBServer::%s - got module info for (%s:%s) : %s", - __FUNCTION__, module_path.c_str(), arch.GetTriple().getTriple().c_str(), - stream.GetData()); + LLDB_LOGF(log, + "PlatformRemoteGDBServer::%s - got module info for (%s:%s) : %s", + __FUNCTION__, module_path.c_str(), + arch.GetTriple().getTriple().c_str(), stream.GetData()); } return true; @@ -253,9 +253,9 @@ FileSpec PlatformRemoteGDBServer::GetRemoteWorkingDirectory() { Log *log = GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PLATFORM); FileSpec working_dir; if (m_gdb_client.GetWorkingDir(working_dir) && log) - log->Printf( - "PlatformRemoteGDBServer::GetRemoteWorkingDirectory() -> '%s'", - working_dir.GetCString()); + LLDB_LOGF(log, + "PlatformRemoteGDBServer::GetRemoteWorkingDirectory() -> '%s'", + working_dir.GetCString()); return working_dir; } else { return Platform::GetRemoteWorkingDirectory(); @@ -268,9 +268,8 @@ bool PlatformRemoteGDBServer::SetRemoteWorkingDirectory( // Clear the working directory it case it doesn't get set correctly. This // will for use to re-read it Log *log = GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PLATFORM); - if (log) - log->Printf("PlatformRemoteGDBServer::SetRemoteWorkingDirectory('%s')", - working_dir.GetCString()); + LLDB_LOGF(log, "PlatformRemoteGDBServer::SetRemoteWorkingDirectory('%s')", + working_dir.GetCString()); return m_gdb_client.SetWorkingDir(working_dir) == 0; } else return Platform::SetRemoteWorkingDirectory(working_dir); @@ -370,8 +369,7 @@ Status PlatformRemoteGDBServer::LaunchProcess(ProcessLaunchInfo &launch_info) { Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_PLATFORM)); Status error; - if (log) - log->Printf("PlatformRemoteGDBServer::%s() called", __FUNCTION__); + LLDB_LOGF(log, "PlatformRemoteGDBServer::%s() called", __FUNCTION__); auto num_file_actions = launch_info.GetNumFileActions(); for (decltype(num_file_actions) i = 0; i < num_file_actions; ++i) { @@ -408,10 +406,10 @@ Status PlatformRemoteGDBServer::LaunchProcess(ProcessLaunchInfo &launch_info) { const char *arch_triple = arch_spec.GetTriple().str().c_str(); m_gdb_client.SendLaunchArchPacket(arch_triple); - if (log) - log->Printf( - "PlatformRemoteGDBServer::%s() set launch architecture triple to '%s'", - __FUNCTION__, arch_triple ? arch_triple : "<NULL>"); + LLDB_LOGF( + log, + "PlatformRemoteGDBServer::%s() set launch architecture triple to '%s'", + __FUNCTION__, arch_triple ? arch_triple : "<NULL>"); int arg_packet_err; { @@ -427,22 +425,21 @@ Status PlatformRemoteGDBServer::LaunchProcess(ProcessLaunchInfo &launch_info) { const auto pid = m_gdb_client.GetCurrentProcessID(false); if (pid != LLDB_INVALID_PROCESS_ID) { launch_info.SetProcessID(pid); - if (log) - log->Printf("PlatformRemoteGDBServer::%s() pid %" PRIu64 - " launched successfully", - __FUNCTION__, pid); + LLDB_LOGF(log, + "PlatformRemoteGDBServer::%s() pid %" PRIu64 + " launched successfully", + __FUNCTION__, pid); } else { - if (log) - log->Printf("PlatformRemoteGDBServer::%s() launch succeeded but we " - "didn't get a valid process id back!", - __FUNCTION__); + LLDB_LOGF(log, + "PlatformRemoteGDBServer::%s() launch succeeded but we " + "didn't get a valid process id back!", + __FUNCTION__); error.SetErrorString("failed to get PID"); } } else { error.SetErrorString(error_str.c_str()); - if (log) - log->Printf("PlatformRemoteGDBServer::%s() launch failed: %s", - __FUNCTION__, error.AsCString()); + LLDB_LOGF(log, "PlatformRemoteGDBServer::%s() launch failed: %s", + __FUNCTION__, error.AsCString()); } } else { error.SetErrorStringWithFormat("'A' packet returned an error: %i", @@ -600,11 +597,10 @@ Status PlatformRemoteGDBServer::MakeDirectory(const FileSpec &file_spec, uint32_t mode) { Status error = m_gdb_client.MakeDirectory(file_spec, mode); Log *log = GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PLATFORM); - if (log) - log->Printf("PlatformRemoteGDBServer::MakeDirectory(path='%s', mode=%o) " - "error = %u (%s)", - file_spec.GetCString(), mode, error.GetError(), - error.AsCString()); + LLDB_LOGF(log, + "PlatformRemoteGDBServer::MakeDirectory(path='%s', mode=%o) " + "error = %u (%s)", + file_spec.GetCString(), mode, error.GetError(), error.AsCString()); return error; } @@ -612,11 +608,11 @@ Status PlatformRemoteGDBServer::GetFilePermissions(const FileSpec &file_spec, uint32_t &file_permissions) { Status error = m_gdb_client.GetFilePermissions(file_spec, file_permissions); Log *log = GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PLATFORM); - if (log) - log->Printf("PlatformRemoteGDBServer::GetFilePermissions(path='%s', " - "file_permissions=%o) error = %u (%s)", - file_spec.GetCString(), file_permissions, error.GetError(), - error.AsCString()); + LLDB_LOGF(log, + "PlatformRemoteGDBServer::GetFilePermissions(path='%s', " + "file_permissions=%o) error = %u (%s)", + file_spec.GetCString(), file_permissions, error.GetError(), + error.AsCString()); return error; } @@ -624,16 +620,17 @@ Status PlatformRemoteGDBServer::SetFilePermissions(const FileSpec &file_spec, uint32_t file_permissions) { Status error = m_gdb_client.SetFilePermissions(file_spec, file_permissions); Log *log = GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PLATFORM); - if (log) - log->Printf("PlatformRemoteGDBServer::SetFilePermissions(path='%s', " - "file_permissions=%o) error = %u (%s)", - file_spec.GetCString(), file_permissions, error.GetError(), - error.AsCString()); + LLDB_LOGF(log, + "PlatformRemoteGDBServer::SetFilePermissions(path='%s', " + "file_permissions=%o) error = %u (%s)", + file_spec.GetCString(), file_permissions, error.GetError(), + error.AsCString()); return error; } lldb::user_id_t PlatformRemoteGDBServer::OpenFile(const FileSpec &file_spec, - uint32_t flags, uint32_t mode, + File::OpenOptions flags, + uint32_t mode, Status &error) { return m_gdb_client.OpenFile(file_spec, flags, mode, error); } @@ -671,20 +668,19 @@ Status PlatformRemoteGDBServer::CreateSymlink( { Status error = m_gdb_client.CreateSymlink(src, dst); Log *log = GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PLATFORM); - if (log) - log->Printf("PlatformRemoteGDBServer::CreateSymlink(src='%s', dst='%s') " - "error = %u (%s)", - src.GetCString(), dst.GetCString(), error.GetError(), - error.AsCString()); + LLDB_LOGF(log, + "PlatformRemoteGDBServer::CreateSymlink(src='%s', dst='%s') " + "error = %u (%s)", + src.GetCString(), dst.GetCString(), error.GetError(), + error.AsCString()); return error; } Status PlatformRemoteGDBServer::Unlink(const FileSpec &file_spec) { Status error = m_gdb_client.Unlink(file_spec); Log *log = GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PLATFORM); - if (log) - log->Printf("PlatformRemoteGDBServer::Unlink(path='%s') error = %u (%s)", - file_spec.GetCString(), error.GetError(), error.AsCString()); + LLDB_LOGF(log, "PlatformRemoteGDBServer::Unlink(path='%s') error = %u (%s)", + file_spec.GetCString(), error.GetError(), error.AsCString()); return error; } diff --git a/source/Plugins/Platform/gdb-server/PlatformRemoteGDBServer.h b/source/Plugins/Platform/gdb-server/PlatformRemoteGDBServer.h index c774daa8ab73..13edcbab9f59 100644 --- a/source/Plugins/Platform/gdb-server/PlatformRemoteGDBServer.h +++ b/source/Plugins/Platform/gdb-server/PlatformRemoteGDBServer.h @@ -113,7 +113,7 @@ public: Status SetFilePermissions(const FileSpec &file_spec, uint32_t file_permissions) override; - lldb::user_id_t OpenFile(const FileSpec &file_spec, uint32_t flags, + lldb::user_id_t OpenFile(const FileSpec &file_spec, File::OpenOptions flags, uint32_t mode, Status &error) override; bool CloseFile(lldb::user_id_t fd, Status &error) override; diff --git a/source/Plugins/Process/Darwin/DarwinProcessLauncher.cpp b/source/Plugins/Process/Darwin/DarwinProcessLauncher.cpp index 3ec410fe7d76..f70ef97a2bc5 100644 --- a/source/Plugins/Process/Darwin/DarwinProcessLauncher.cpp +++ b/source/Plugins/Process/Darwin/DarwinProcessLauncher.cpp @@ -254,9 +254,8 @@ CreatePosixSpawnFileAction(const FileAction &action, case FileAction::eFileActionNone: default: - if (log) - log->Printf("%s(): unsupported file action %u", __FUNCTION__, - action.GetAction()); + LLDB_LOGF(log, "%s(): unsupported file action %u", __FUNCTION__, + action.GetAction()); break; } @@ -288,8 +287,7 @@ static Status PosixSpawnChildForPTraceDebugging(const char *path, int error_code; if ((error_code = ::posix_spawnattr_init(&attr)) != 0) { - if (log) - log->Printf("::posix_spawnattr_init(&attr) failed"); + LLDB_LOGF(log, "::posix_spawnattr_init(&attr) failed"); error.SetError(error_code, eErrorTypePOSIX); return error; } @@ -378,10 +376,10 @@ static Status PosixSpawnChildForPTraceDebugging(const char *path, error = CreatePosixSpawnFileAction(*action, &file_actions); if (!error.Success()) { - if (log) - log->Printf("%s(): error converting FileAction to posix_spawn " - "file action: %s", - __FUNCTION__, error.AsCString()); + LLDB_LOGF(log, + "%s(): error converting FileAction to posix_spawn " + "file action: %s", + __FUNCTION__, error.AsCString()); return error; } } @@ -416,10 +414,10 @@ static Status PosixSpawnChildForPTraceDebugging(const char *path, if (actual_cpu_type) { *actual_cpu_type = GetCPUTypeForLocalProcess(*pid); - if (log) - log->Printf("%s(): cpu type for launched process pid=%i: " - "cpu_type=0x%8.8x", - __FUNCTION__, *pid, *actual_cpu_type); + LLDB_LOGF(log, + "%s(): cpu type for launched process pid=%i: " + "cpu_type=0x%8.8x", + __FUNCTION__, *pid, *actual_cpu_type); } return error; @@ -477,23 +475,21 @@ Status LaunchInferior(ProcessLaunchInfo &launch_info, int *pty_master_fd, char resolved_path[PATH_MAX]; resolved_path[0] = '\0'; - if (log) - log->Printf("%s(): attempting to resolve given binary path: \"%s\"", - __FUNCTION__, given_path); + LLDB_LOGF(log, "%s(): attempting to resolve given binary path: \"%s\"", + __FUNCTION__, given_path); // If we fail to resolve the path to our executable, then just use what we // were given and hope for the best if (!ResolveExecutablePath(given_path, resolved_path, sizeof(resolved_path))) { - if (log) - log->Printf("%s(): failed to resolve binary path, using " - "what was given verbatim and hoping for the best", - __FUNCTION__); + LLDB_LOGF(log, + "%s(): failed to resolve binary path, using " + "what was given verbatim and hoping for the best", + __FUNCTION__); ::strncpy(resolved_path, given_path, sizeof(resolved_path)); } else { - if (log) - log->Printf("%s(): resolved given binary path to: \"%s\"", __FUNCTION__, - resolved_path); + LLDB_LOGF(log, "%s(): resolved given binary path to: \"%s\"", __FUNCTION__, + resolved_path); } char launch_err_str[PATH_MAX]; diff --git a/source/Plugins/Process/Darwin/MachException.cpp b/source/Plugins/Process/Darwin/MachException.cpp index 70ad6736a748..073ad64b300c 100644 --- a/source/Plugins/Process/Darwin/MachException.cpp +++ b/source/Plugins/Process/Darwin/MachException.cpp @@ -67,10 +67,11 @@ extern "C" kern_return_t catch_mach_exception_raise_state( // TODO change to LIBLLDB_LOG_EXCEPTION Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_PROCESS | LIBLLDB_LOG_VERBOSE)); if (log) { - log->Printf("::%s(exc_port = 0x%4.4x, exc_type = %d (%s), " - "exc_data = 0x%llx, exc_data_count = %d)", - __FUNCTION__, exc_port, exc_type, MachException::Name(exc_type), - (uint64_t)exc_data, exc_data_count); + LLDB_LOGF(log, + "::%s(exc_port = 0x%4.4x, exc_type = %d (%s), " + "exc_data = 0x%llx, exc_data_count = %d)", + __FUNCTION__, exc_port, exc_type, MachException::Name(exc_type), + (uint64_t)exc_data, exc_data_count); } return KERN_FAILURE; } @@ -83,13 +84,14 @@ extern "C" kern_return_t catch_mach_exception_raise_state_identity( thread_state_t new_state, mach_msg_type_number_t *new_stateCnt) { Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_PROCESS | LIBLLDB_LOG_VERBOSE)); if (log) { - log->Printf("::%s(exc_port = 0x%4.4x, thd_port = 0x%4.4x, " - "tsk_port = 0x%4.4x, exc_type = %d (%s), exc_data[%d] = " - "{ 0x%llx, 0x%llx })", - __FUNCTION__, exc_port, thread_port, task_port, exc_type, - MachException::Name(exc_type), exc_data_count, - (uint64_t)(exc_data_count > 0 ? exc_data[0] : 0xBADDBADD), - (uint64_t)(exc_data_count > 1 ? exc_data[1] : 0xBADDBADD)); + LLDB_LOGF(log, + "::%s(exc_port = 0x%4.4x, thd_port = 0x%4.4x, " + "tsk_port = 0x%4.4x, exc_type = %d (%s), exc_data[%d] = " + "{ 0x%llx, 0x%llx })", + __FUNCTION__, exc_port, thread_port, task_port, exc_type, + MachException::Name(exc_type), exc_data_count, + (uint64_t)(exc_data_count > 0 ? exc_data[0] : 0xBADDBADD), + (uint64_t)(exc_data_count > 1 ? exc_data[1] : 0xBADDBADD)); } return KERN_FAILURE; @@ -102,13 +104,14 @@ catch_mach_exception_raise(mach_port_t exc_port, mach_port_t thread_port, mach_msg_type_number_t exc_data_count) { Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_PROCESS | LIBLLDB_LOG_VERBOSE)); if (log) { - log->Printf("::%s(exc_port = 0x%4.4x, thd_port = 0x%4.4x, " - "tsk_port = 0x%4.4x, exc_type = %d (%s), exc_data[%d] " - "= { 0x%llx, 0x%llx })", - __FUNCTION__, exc_port, thread_port, task_port, exc_type, - MachException::Name(exc_type), exc_data_count, - (uint64_t)(exc_data_count > 0 ? exc_data[0] : 0xBADDBADD), - (uint64_t)(exc_data_count > 1 ? exc_data[1] : 0xBADDBADD)); + LLDB_LOGF(log, + "::%s(exc_port = 0x%4.4x, thd_port = 0x%4.4x, " + "tsk_port = 0x%4.4x, exc_type = %d (%s), exc_data[%d] " + "= { 0x%llx, 0x%llx })", + __FUNCTION__, exc_port, thread_port, task_port, exc_type, + MachException::Name(exc_type), exc_data_count, + (uint64_t)(exc_data_count > 0 ? exc_data[0] : 0xBADDBADD), + (uint64_t)(exc_data_count > 1 ? exc_data[1] : 0xBADDBADD)); } if (task_port == g_message->task_port) { @@ -187,15 +190,16 @@ Status MachException::Message::Receive(mach_port_t port, options & MACH_RCV_TIMEOUT ? timeout : 0; if (log && ((options & MACH_RCV_TIMEOUT) == 0)) { // Dump this log message if we have no timeout in case it never returns - log->Printf("::mach_msg(msg->{bits = %#x, size = %u remote_port = %#x, " - "local_port = %#x, reserved = 0x%x, id = 0x%x}, " - "option = %#x, send_size = 0, rcv_size = %llu, " - "rcv_name = %#x, timeout = %u, notify = %#x)", - exc_msg.hdr.msgh_bits, exc_msg.hdr.msgh_size, - exc_msg.hdr.msgh_remote_port, exc_msg.hdr.msgh_local_port, - exc_msg.hdr.msgh_reserved, exc_msg.hdr.msgh_id, options, - (uint64_t)sizeof(exc_msg.data), port, mach_msg_timeout, - notify_port); + LLDB_LOGF(log, + "::mach_msg(msg->{bits = %#x, size = %u remote_port = %#x, " + "local_port = %#x, reserved = 0x%x, id = 0x%x}, " + "option = %#x, send_size = 0, rcv_size = %llu, " + "rcv_name = %#x, timeout = %u, notify = %#x)", + exc_msg.hdr.msgh_bits, exc_msg.hdr.msgh_size, + exc_msg.hdr.msgh_remote_port, exc_msg.hdr.msgh_local_port, + exc_msg.hdr.msgh_reserved, exc_msg.hdr.msgh_id, options, + (uint64_t)sizeof(exc_msg.data), port, mach_msg_timeout, + notify_port); } mach_msg_return_t mach_err = @@ -213,15 +217,16 @@ Status MachException::Message::Receive(mach_port_t port, // Dump any errors we get if (error.Fail() && log) { - log->Printf("::mach_msg(msg->{bits = %#x, size = %u remote_port = %#x, " - "local_port = %#x, reserved = 0x%x, id = 0x%x}, " - "option = %#x, send_size = %u, rcv_size = %lu, rcv_name " - "= %#x, timeout = %u, notify = %#x) failed: %s", - exc_msg.hdr.msgh_bits, exc_msg.hdr.msgh_size, - exc_msg.hdr.msgh_remote_port, exc_msg.hdr.msgh_local_port, - exc_msg.hdr.msgh_reserved, exc_msg.hdr.msgh_id, options, 0, - sizeof(exc_msg.data), port, mach_msg_timeout, notify_port, - error.AsCString()); + LLDB_LOGF(log, + "::mach_msg(msg->{bits = %#x, size = %u remote_port = %#x, " + "local_port = %#x, reserved = 0x%x, id = 0x%x}, " + "option = %#x, send_size = %u, rcv_size = %lu, rcv_name " + "= %#x, timeout = %u, notify = %#x) failed: %s", + exc_msg.hdr.msgh_bits, exc_msg.hdr.msgh_size, + exc_msg.hdr.msgh_remote_port, exc_msg.hdr.msgh_local_port, + exc_msg.hdr.msgh_reserved, exc_msg.hdr.msgh_id, options, 0, + sizeof(exc_msg.data), port, mach_msg_timeout, notify_port, + error.AsCString()); } return error; } @@ -264,10 +269,10 @@ bool MachException::Message::CatchExceptionRaise(task_t task) { } else { Log *log( GetLogIfAllCategoriesSet(LIBLLDB_LOG_PROCESS | LIBLLDB_LOG_VERBOSE)); - if (log) - log->Printf("MachException::Message::%s(): mach_exc_server " - "returned zero...", - __FUNCTION__); + LLDB_LOGF(log, + "MachException::Message::%s(): mach_exc_server " + "returned zero...", + __FUNCTION__); } g_message = NULL; return success; @@ -293,10 +298,10 @@ Status MachException::Message::Reply(::pid_t inferior_pid, task_t inferior_task, auto mach_err = ::pid_for_task(state.task_port, &state_pid); if (mach_err) { error.SetError(mach_err, eErrorTypeMachKernel); - if (log) - log->Printf("MachException::Message::%s(): pid_for_task() " - "failed: %s", - __FUNCTION__, error.AsCString()); + LLDB_LOGF(log, + "MachException::Message::%s(): pid_for_task() " + "failed: %s", + __FUNCTION__, error.AsCString()); return error; } } @@ -309,25 +314,25 @@ Status MachException::Message::Reply(::pid_t inferior_pid, task_t inferior_task, error.SetError(errno, eErrorTypePOSIX); if (!error.Success()) { - if (log) - log->Printf("::ptrace(request = PT_THUPDATE, pid = " - "0x%4.4x, tid = 0x%4.4x, signal = %i)", - state_pid, state.thread_port, soft_signal); + LLDB_LOGF(log, + "::ptrace(request = PT_THUPDATE, pid = " + "0x%4.4x, tid = 0x%4.4x, signal = %i)", + state_pid, state.thread_port, soft_signal); return error; } } } - if (log) - log->Printf("::mach_msg ( msg->{bits = %#x, size = %u, remote_port " - "= %#x, local_port = %#x, reserved = 0x%x, id = 0x%x}, " - "option = %#x, send_size = %u, rcv_size = %u, rcv_name " - "= %#x, timeout = %u, notify = %#x)", - reply_msg.hdr.msgh_bits, reply_msg.hdr.msgh_size, - reply_msg.hdr.msgh_remote_port, reply_msg.hdr.msgh_local_port, - reply_msg.hdr.msgh_reserved, reply_msg.hdr.msgh_id, - MACH_SEND_MSG | MACH_SEND_INTERRUPT, reply_msg.hdr.msgh_size, 0, - MACH_PORT_NULL, MACH_MSG_TIMEOUT_NONE, MACH_PORT_NULL); + LLDB_LOGF(log, + "::mach_msg ( msg->{bits = %#x, size = %u, remote_port " + "= %#x, local_port = %#x, reserved = 0x%x, id = 0x%x}, " + "option = %#x, send_size = %u, rcv_size = %u, rcv_name " + "= %#x, timeout = %u, notify = %#x)", + reply_msg.hdr.msgh_bits, reply_msg.hdr.msgh_size, + reply_msg.hdr.msgh_remote_port, reply_msg.hdr.msgh_local_port, + reply_msg.hdr.msgh_reserved, reply_msg.hdr.msgh_id, + MACH_SEND_MSG | MACH_SEND_INTERRUPT, reply_msg.hdr.msgh_size, 0, + MACH_PORT_NULL, MACH_MSG_TIMEOUT_NONE, MACH_PORT_NULL); auto mach_err = ::mach_msg(&reply_msg.hdr, MACH_SEND_MSG | MACH_SEND_INTERRUPT, @@ -342,12 +347,13 @@ Status MachException::Message::Reply(::pid_t inferior_pid, task_t inferior_task, log->PutCString("::mach_msg() - send interrupted"); // TODO: keep retrying to reply??? } else if (state.task_port == inferior_task) { - log->Printf("mach_msg(): returned an error when replying " - "to a mach exception: error = %u (%s)", - error.GetError(), error.AsCString()); + LLDB_LOGF(log, + "mach_msg(): returned an error when replying " + "to a mach exception: error = %u (%s)", + error.GetError(), error.AsCString()); } else { - log->Printf("::mach_msg() - failed (child of task): %u (%s)", - error.GetError(), error.AsCString()); + LLDB_LOGF(log, "::mach_msg() - failed (child of task): %u (%s)", + error.GetError(), error.AsCString()); } } @@ -377,9 +383,8 @@ Status MachException::PortInfo::Save(task_t task) { Status error; Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_PROCESS | LIBLLDB_LOG_VERBOSE)); - if (log) - log->Printf("MachException::PortInfo::%s(task = 0x%4.4x)", __FUNCTION__, - task); + LLDB_LOGF(log, "MachException::PortInfo::%s(task = 0x%4.4x)", __FUNCTION__, + task); // Be careful to be able to have debugserver built on a newer OS than what it // is currently running on by being able to start with all exceptions and @@ -394,13 +399,15 @@ Status MachException::PortInfo::Save(task_t task) { if (log) { if (error.Success()) { - log->Printf("::task_get_exception_ports(task = 0x%4.4x, mask = " - "0x%x, maskCnt => %u, ports, behaviors, flavors)", - task, mask, count); + LLDB_LOGF(log, + "::task_get_exception_ports(task = 0x%4.4x, mask = " + "0x%x, maskCnt => %u, ports, behaviors, flavors)", + task, mask, count); } else { - log->Printf("::task_get_exception_ports(task = 0x%4.4x, mask = 0x%x, " - "maskCnt => %u, ports, behaviors, flavors) error: %u (%s)", - task, mask, count, error.GetError(), error.AsCString()); + LLDB_LOGF(log, + "::task_get_exception_ports(task = 0x%4.4x, mask = 0x%x, " + "maskCnt => %u, ports, behaviors, flavors) error: %u (%s)", + task, mask, count, error.GetError(), error.AsCString()); } } @@ -413,15 +420,17 @@ Status MachException::PortInfo::Save(task_t task) { error.SetError(mach_err, eErrorTypeMachKernel); if (log) { if (error.Success()) { - log->Printf("::task_get_exception_ports(task = 0x%4.4x, " - "mask = 0x%x, maskCnt => %u, ports, behaviors, " - "flavors)", - task, mask, count); + LLDB_LOGF(log, + "::task_get_exception_ports(task = 0x%4.4x, " + "mask = 0x%x, maskCnt => %u, ports, behaviors, " + "flavors)", + task, mask, count); } else { - log->Printf("::task_get_exception_ports(task = 0x%4.4x, mask = " - "0x%x, maskCnt => %u, ports, behaviors, flavors) " - "error: %u (%s)", - task, mask, count, error.GetError(), error.AsCString()); + LLDB_LOGF(log, + "::task_get_exception_ports(task = 0x%4.4x, mask = " + "0x%x, maskCnt => %u, ports, behaviors, flavors) " + "error: %u (%s)", + task, mask, count, error.GetError(), error.AsCString()); } } } @@ -437,8 +446,7 @@ Status MachException::PortInfo::Restore(task_t task) { Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_PROCESS | LIBLLDB_LOG_VERBOSE)); - if (log) - log->Printf("MachException::PortInfo::Restore(task = 0x%4.4x)", task); + LLDB_LOGF(log, "MachException::PortInfo::Restore(task = 0x%4.4x)", task); uint32_t i = 0; if (count > 0) { @@ -449,17 +457,19 @@ Status MachException::PortInfo::Restore(task_t task) { error.SetError(mach_err, eErrorTypeMachKernel); if (log) { if (error.Success()) { - log->Printf("::task_set_exception_ports(task = 0x%4.4x, " - "exception_mask = 0x%8.8x, new_port = 0x%4.4x, " - "behavior = 0x%8.8x, new_flavor = 0x%8.8x)", - task, masks[i], ports[i], behaviors[i], flavors[i]); + LLDB_LOGF(log, + "::task_set_exception_ports(task = 0x%4.4x, " + "exception_mask = 0x%8.8x, new_port = 0x%4.4x, " + "behavior = 0x%8.8x, new_flavor = 0x%8.8x)", + task, masks[i], ports[i], behaviors[i], flavors[i]); } else { - log->Printf("::task_set_exception_ports(task = 0x%4.4x, " - "exception_mask = 0x%8.8x, new_port = 0x%4.4x, " - "behavior = 0x%8.8x, new_flavor = 0x%8.8x): " - "error %u (%s)", - task, masks[i], ports[i], behaviors[i], flavors[i], - error.GetError(), error.AsCString()); + LLDB_LOGF(log, + "::task_set_exception_ports(task = 0x%4.4x, " + "exception_mask = 0x%8.8x, new_port = 0x%4.4x, " + "behavior = 0x%8.8x, new_flavor = 0x%8.8x): " + "error %u (%s)", + task, masks[i], ports[i], behaviors[i], flavors[i], + error.GetError(), error.AsCString()); } } diff --git a/source/Plugins/Process/Darwin/NativeProcessDarwin.cpp b/source/Plugins/Process/Darwin/NativeProcessDarwin.cpp index fe7de27e0ee6..18dbdda9a33b 100644 --- a/source/Plugins/Process/Darwin/NativeProcessDarwin.cpp +++ b/source/Plugins/Process/Darwin/NativeProcessDarwin.cpp @@ -75,19 +75,19 @@ Status NativeProcessProtocol::Launch( // Handle launch failure. if (!error.Success()) { - if (log) - log->Printf("NativeProcessDarwin::%s() failed to launch process: " - "%s", - __FUNCTION__, error.AsCString()); + LLDB_LOGF(log, + "NativeProcessDarwin::%s() failed to launch process: " + "%s", + __FUNCTION__, error.AsCString()); return error; } // Handle failure to return a pid. if (launch_info.GetProcessID() == LLDB_INVALID_PROCESS_ID) { - if (log) - log->Printf("NativeProcessDarwin::%s() launch succeeded but no " - "pid was returned! Aborting.", - __FUNCTION__); + LLDB_LOGF(log, + "NativeProcessDarwin::%s() launch succeeded but no " + "pid was returned! Aborting.", + __FUNCTION__); return error; } @@ -104,10 +104,10 @@ Status NativeProcessProtocol::Launch( // NativeProcessDarwin instance. error = np_darwin_sp->FinalizeLaunch(launch_flavor, mainloop); if (!error.Success()) { - if (log) - log->Printf("NativeProcessDarwin::%s() aborting, failed to finalize" - " the launching of the process: %s", - __FUNCTION__, error.AsCString()); + LLDB_LOGF(log, + "NativeProcessDarwin::%s() aborting, failed to finalize" + " the launching of the process: %s", + __FUNCTION__, error.AsCString()); return error; } @@ -120,9 +120,8 @@ Status NativeProcessProtocol::Attach( lldb::pid_t pid, NativeProcessProtocol::NativeDelegate &native_delegate, MainLoop &mainloop, NativeProcessProtocolSP &native_process_sp) { Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_PROCESS)); - if (log) - log->Printf("NativeProcessDarwin::%s(pid = %" PRIi64 ")", __FUNCTION__, - pid); + LLDB_LOGF(log, "NativeProcessDarwin::%s(pid = %" PRIi64 ")", __FUNCTION__, + pid); // Retrieve the architecture for the running process. ArchSpec process_arch; @@ -173,10 +172,10 @@ Status NativeProcessDarwin::FinalizeLaunch(LaunchFlavor launch_flavor, error = StartExceptionThread(); if (!error.Success()) { - if (log) - log->Printf("NativeProcessDarwin::%s(): failure starting the " - "mach exception port monitor thread: %s", - __FUNCTION__, error.AsCString()); + LLDB_LOGF(log, + "NativeProcessDarwin::%s(): failure starting the " + "mach exception port monitor thread: %s", + __FUNCTION__, error.AsCString()); // Terminate the inferior process. There's nothing meaningful we can do if // we can't receive signals and exceptions. Since we launched the process, @@ -195,33 +194,31 @@ Status NativeProcessDarwin::FinalizeLaunch(LaunchFlavor launch_flavor, int err = ::ptrace(PT_ATTACHEXC, m_pid, 0, 0); if (err == 0) { // m_flags |= eMachProcessFlagsAttached; - if (log) - log->Printf("NativeProcessDarwin::%s(): successfully spawned " - "process with pid %" PRIu64, - __FUNCTION__, m_pid); + LLDB_LOGF(log, + "NativeProcessDarwin::%s(): successfully spawned " + "process with pid %" PRIu64, + __FUNCTION__, m_pid); } else { error.SetErrorToErrno(); SetState(eStateExited); - if (log) - log->Printf("NativeProcessDarwin::%s(): error: failed to " - "attach to spawned pid %" PRIu64 " (error=%d (%s))", - __FUNCTION__, m_pid, (int)error.GetError(), - error.AsCString()); + LLDB_LOGF(log, + "NativeProcessDarwin::%s(): error: failed to " + "attach to spawned pid %" PRIu64 " (error=%d (%s))", + __FUNCTION__, m_pid, (int)error.GetError(), error.AsCString()); return error; } } - if (log) - log->Printf("NativeProcessDarwin::%s(): new pid is %" PRIu64 "...", - __FUNCTION__, m_pid); + LLDB_LOGF(log, "NativeProcessDarwin::%s(): new pid is %" PRIu64 "...", + __FUNCTION__, m_pid); // Spawn a thread to reap our child inferior process... error = StartWaitpidThread(main_loop); if (error.Fail()) { - if (log) - log->Printf("NativeProcessDarwin::%s(): failed to start waitpid() " - "thread: %s", - __FUNCTION__, error.AsCString()); + LLDB_LOGF(log, + "NativeProcessDarwin::%s(): failed to start waitpid() " + "thread: %s", + __FUNCTION__, error.AsCString()); kill(SIGKILL, static_cast<::pid_t>(m_pid)); return error; } @@ -230,10 +227,10 @@ Status NativeProcessDarwin::FinalizeLaunch(LaunchFlavor launch_flavor, // We failed to get the task for our process ID which is bad. Kill our // process; otherwise, it will be stopped at the entry point and get // reparented to someone else and never go away. - if (log) - log->Printf("NativeProcessDarwin::%s(): could not get task port " - "for process, sending SIGKILL and exiting: %s", - __FUNCTION__, error.AsCString()); + LLDB_LOGF(log, + "NativeProcessDarwin::%s(): could not get task port " + "for process, sending SIGKILL and exiting: %s", + __FUNCTION__, error.AsCString()); kill(SIGKILL, static_cast<::pid_t>(m_pid)); return error; } @@ -278,18 +275,17 @@ void NativeProcessDarwin::ExceptionMessageReceived( // the exception to our internal exception stack m_exception_messages.push_back(message); - if (log) - log->Printf("NativeProcessDarwin::%s(): new queued message count: %lu", - __FUNCTION__, m_exception_messages.size()); + LLDB_LOGF(log, "NativeProcessDarwin::%s(): new queued message count: %lu", + __FUNCTION__, m_exception_messages.size()); } void *NativeProcessDarwin::ExceptionThread(void *arg) { Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_PROCESS | LIBLLDB_LOG_VERBOSE)); if (!arg) { - if (log) - log->Printf("NativeProcessDarwin::%s(): cannot run mach exception " - "thread, mandatory process arg was null", - __FUNCTION__); + LLDB_LOGF(log, + "NativeProcessDarwin::%s(): cannot run mach exception " + "thread, mandatory process arg was null", + __FUNCTION__); return nullptr; } @@ -299,9 +295,8 @@ void *NativeProcessDarwin::ExceptionThread(void *arg) { void *NativeProcessDarwin::DoExceptionThread() { Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_PROCESS | LIBLLDB_LOG_VERBOSE)); - if (log) - log->Printf("NativeProcessDarwin::%s(arg=%p) starting thread...", - __FUNCTION__, this); + LLDB_LOGF(log, "NativeProcessDarwin::%s(arg=%p) starting thread...", + __FUNCTION__, this); pthread_setname_np("exception monitoring thread"); @@ -344,20 +339,20 @@ void *NativeProcessDarwin::DoExceptionThread() { if (process->ProcessUsingSpringBoard()) { // Request a renewal for every 60 seconds if we attached using SpringBoard. watchdog.reset(::SBSWatchdogAssertionCreateForPID(nullptr, pid, 60)); - if (log) - log->Printf("::SBSWatchdogAssertionCreateForPID(NULL, %4.4x, 60) " - "=> %p", - pid, watchdog.get()); + LLDB_LOGF(log, + "::SBSWatchdogAssertionCreateForPID(NULL, %4.4x, 60) " + "=> %p", + pid, watchdog.get()); if (watchdog.get()) { ::SBSWatchdogAssertionRenew(watchdog.get()); CFTimeInterval watchdogRenewalInterval = ::SBSWatchdogAssertionGetRenewalInterval(watchdog.get()); - if (log) - log->Printf("::SBSWatchdogAssertionGetRenewalInterval(%p) => " - "%g seconds", - watchdog.get(), watchdogRenewalInterval); + LLDB_LOGF(log, + "::SBSWatchdogAssertionGetRenewalInterval(%p) => " + "%g seconds", + watchdog.get(), watchdogRenewalInterval); if (watchdogRenewalInterval > 0.0) { watchdog_timeout = (mach_msg_timeout_t)watchdogRenewalInterval * 1000; if (watchdog_timeout > 3000) { @@ -425,11 +420,11 @@ void *NativeProcessDarwin::DoExceptionThread() { // If we have no task port we should exit this thread, as it implies // the inferior went down. if (!IsExceptionPortValid()) { - if (log) - log->Printf("NativeProcessDarwin::%s(): the inferior " - "exception port is no longer valid, " - "canceling exception thread...", - __FUNCTION__); + LLDB_LOGF(log, + "NativeProcessDarwin::%s(): the inferior " + "exception port is no longer valid, " + "canceling exception thread...", + __FUNCTION__); // Should we be setting a process state here? break; } @@ -437,19 +432,19 @@ void *NativeProcessDarwin::DoExceptionThread() { // Make sure the inferior task is still valid. if (IsTaskValid()) { // Task is still ok. - if (log) - log->Printf("NativeProcessDarwin::%s(): interrupted, but " - "the inferior task iss till valid, " - "continuing...", - __FUNCTION__); + LLDB_LOGF(log, + "NativeProcessDarwin::%s(): interrupted, but " + "the inferior task iss till valid, " + "continuing...", + __FUNCTION__); continue; } else { // The inferior task is no longer valid. Time to exit as the process // has gone away. - if (log) - log->Printf("NativeProcessDarwin::%s(): the inferior task " - "has exited, and so will we...", - __FUNCTION__); + LLDB_LOGF(log, + "NativeProcessDarwin::%s(): the inferior task " + "has exited, and so will we...", + __FUNCTION__); // Does this race at all with our waitpid()? SetState(eStateExited); break; @@ -471,18 +466,18 @@ void *NativeProcessDarwin::DoExceptionThread() { // our task is still valid. if (IsTaskValid(task)) { // Task is still ok. - if (log) - log->Printf("NativeProcessDarwin::%s(): got a timeout, " - "continuing...", - __FUNCTION__); + LLDB_LOGF(log, + "NativeProcessDarwin::%s(): got a timeout, " + "continuing...", + __FUNCTION__); continue; } else { // The inferior task is no longer valid. Time to exit as the // process has gone away. - if (log) - log->Printf("NativeProcessDarwin::%s(): the inferior " - "task has exited, and so will we...", - __FUNCTION__); + LLDB_LOGF(log, + "NativeProcessDarwin::%s(): the inferior " + "task has exited, and so will we...", + __FUNCTION__); // Does this race at all with our waitpid()? SetState(eStateExited); break; @@ -493,18 +488,17 @@ void *NativeProcessDarwin::DoExceptionThread() { if (watchdog.get()) { watchdog_elapsed += periodic_timeout; if (watchdog_elapsed >= watchdog_timeout) { - if (log) - log->Printf("SBSWatchdogAssertionRenew(%p)", watchdog.get()); + LLDB_LOGF(log, "SBSWatchdogAssertionRenew(%p)", watchdog.get()); ::SBSWatchdogAssertionRenew(watchdog.get()); watchdog_elapsed = 0; } } #endif } else { - if (log) - log->Printf("NativeProcessDarwin::%s(): continuing after " - "receiving an unexpected error: %u (%s)", - __FUNCTION__, error.GetError(), error.AsCString()); + LLDB_LOGF(log, + "NativeProcessDarwin::%s(): continuing after " + "receiving an unexpected error: %u (%s)", + __FUNCTION__, error.GetError(), error.AsCString()); // TODO: notify of error? } } @@ -523,17 +517,15 @@ void *NativeProcessDarwin::DoExceptionThread() { } #endif // #if defined (WITH_SPRINGBOARD) && !defined (WITH_BKS) - if (log) - log->Printf("NativeProcessDarwin::%s(%p): thread exiting...", __FUNCTION__, - this); + LLDB_LOGF(log, "NativeProcessDarwin::%s(%p): thread exiting...", __FUNCTION__, + this); return nullptr; } Status NativeProcessDarwin::StartExceptionThread() { Status error; Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_PROCESS)); - if (log) - log->Printf("NativeProcessDarwin::%s() called", __FUNCTION__); + LLDB_LOGF(log, "NativeProcessDarwin::%s() called", __FUNCTION__); // Make sure we've looked up the inferior port. TaskPortForProcessID(error); @@ -554,11 +546,11 @@ Status NativeProcessDarwin::StartExceptionThread() { &m_exception_port); error.SetError(mach_err, eErrorTypeMachKernel); if (error.Fail()) { - if (log) - log->Printf("NativeProcessDarwin::%s(): mach_port_allocate(" - "task_self=0x%4.4x, MACH_PORT_RIGHT_RECEIVE, " - "&m_exception_port) failed: %u (%s)", - __FUNCTION__, task_self, error.GetError(), error.AsCString()); + LLDB_LOGF(log, + "NativeProcessDarwin::%s(): mach_port_allocate(" + "task_self=0x%4.4x, MACH_PORT_RIGHT_RECEIVE, " + "&m_exception_port) failed: %u (%s)", + __FUNCTION__, task_self, error.GetError(), error.AsCString()); return error; } @@ -567,23 +559,23 @@ Status NativeProcessDarwin::StartExceptionThread() { task_self, m_exception_port, m_exception_port, MACH_MSG_TYPE_MAKE_SEND); error.SetError(mach_err, eErrorTypeMachKernel); if (error.Fail()) { - if (log) - log->Printf("NativeProcessDarwin::%s(): mach_port_insert_right(" - "task_self=0x%4.4x, m_exception_port=0x%4.4x, " - "m_exception_port=0x%4.4x, MACH_MSG_TYPE_MAKE_SEND) " - "failed: %u (%s)", - __FUNCTION__, task_self, m_exception_port, m_exception_port, - error.GetError(), error.AsCString()); + LLDB_LOGF(log, + "NativeProcessDarwin::%s(): mach_port_insert_right(" + "task_self=0x%4.4x, m_exception_port=0x%4.4x, " + "m_exception_port=0x%4.4x, MACH_MSG_TYPE_MAKE_SEND) " + "failed: %u (%s)", + __FUNCTION__, task_self, m_exception_port, m_exception_port, + error.GetError(), error.AsCString()); return error; } // Save the original state of the exception ports for our child process. error = SaveExceptionPortInfo(); if (error.Fail() || (m_exc_port_info.mask == 0)) { - if (log) - log->Printf("NativeProcessDarwin::%s(): SaveExceptionPortInfo() " - "failed, cannot install exception handler: %s", - __FUNCTION__, error.AsCString()); + LLDB_LOGF(log, + "NativeProcessDarwin::%s(): SaveExceptionPortInfo() " + "failed, cannot install exception handler: %s", + __FUNCTION__, error.AsCString()); return error; } @@ -593,14 +585,14 @@ Status NativeProcessDarwin::StartExceptionThread() { EXCEPTION_DEFAULT | MACH_EXCEPTION_CODES, THREAD_STATE_NONE); error.SetError(mach_err, eErrorTypeMachKernel); if (error.Fail()) { - if (log) - log->Printf("::task_set_exception_ports (task = 0x%4.4x, " - "exception_mask = 0x%8.8x, new_port = 0x%4.4x, " - "behavior = 0x%8.8x, new_flavor = 0x%8.8x) failed: " - "%u (%s)", - m_task, m_exc_port_info.mask, m_exception_port, - (EXCEPTION_DEFAULT | MACH_EXCEPTION_CODES), THREAD_STATE_NONE, - error.GetError(), error.AsCString()); + LLDB_LOGF(log, + "::task_set_exception_ports (task = 0x%4.4x, " + "exception_mask = 0x%8.8x, new_port = 0x%4.4x, " + "behavior = 0x%8.8x, new_flavor = 0x%8.8x) failed: " + "%u (%s)", + m_task, m_exc_port_info.mask, m_exception_port, + (EXCEPTION_DEFAULT | MACH_EXCEPTION_CODES), THREAD_STATE_NONE, + error.GetError(), error.AsCString()); return error; } @@ -609,10 +601,10 @@ Status NativeProcessDarwin::StartExceptionThread() { ::pthread_create(&m_exception_thread, nullptr, ExceptionThread, this); error.SetError(pthread_err, eErrorTypePOSIX); if (error.Fail()) { - if (log) - log->Printf("NativeProcessDarwin::%s(): failed to create Mach " - "exception-handling thread: %u (%s)", - __FUNCTION__, error.GetError(), error.AsCString()); + LLDB_LOGF(log, + "NativeProcessDarwin::%s(): failed to create Mach " + "exception-handling thread: %u (%s)", + __FUNCTION__, error.GetError(), error.AsCString()); } return error; @@ -677,10 +669,10 @@ task_t NativeProcessDarwin::ExceptionMessageBundleComplete() { Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_PROCESS | LIBLLDB_LOG_VERBOSE)); std::lock_guard<std::recursive_mutex> locker(m_exception_messages_mutex); - if (log) - log->Printf("NativeProcessDarwin::%s(): processing %lu exception " - "messages.", - __FUNCTION__, m_exception_messages.size()); + LLDB_LOGF(log, + "NativeProcessDarwin::%s(): processing %lu exception " + "messages.", + __FUNCTION__, m_exception_messages.size()); if (m_exception_messages.empty()) { // Not particularly useful... @@ -733,18 +725,18 @@ task_t NativeProcessDarwin::ExceptionMessageBundleComplete() { const bool force_update = true; const task_t new_task = TaskPortForProcessID(error, force_update); if (old_task != new_task) { - if (log) - log->Printf("exec: inferior task port changed " - "from 0x%4.4x to 0x%4.4x", - old_task, new_task); + LLDB_LOGF(log, + "exec: inferior task port changed " + "from 0x%4.4x to 0x%4.4x", + old_task, new_task); } } } else { - if (log) - log->Printf("NativeProcessDarwin::%s() warning: " - "failed to read all_image_infos." - "infoArrayCount from 0x%8.8llx", - __FUNCTION__, info_array_count_addr); + LLDB_LOGF(log, + "NativeProcessDarwin::%s() warning: " + "failed to read all_image_infos." + "infoArrayCount from 0x%8.8llx", + __FUNCTION__, info_array_count_addr); } } else if ((m_sent_interrupt_signo != 0) && (signo == m_sent_interrupt_signo)) { @@ -756,10 +748,10 @@ task_t NativeProcessDarwin::ExceptionMessageBundleComplete() { if (m_did_exec) { cpu_type_t process_cpu_type = GetCPUTypeForLocalProcess(m_pid); if (m_cpu_type != process_cpu_type) { - if (log) - log->Printf("NativeProcessDarwin::%s(): arch changed from " - "0x%8.8x to 0x%8.8x", - __FUNCTION__, m_cpu_type, process_cpu_type); + LLDB_LOGF(log, + "NativeProcessDarwin::%s(): arch changed from " + "0x%8.8x to 0x%8.8x", + __FUNCTION__, m_cpu_type, process_cpu_type); m_cpu_type = process_cpu_type; // TODO figure out if we need to do something here. // DNBArchProtocol::SetArchitecture (process_cpu_type); @@ -772,10 +764,10 @@ task_t NativeProcessDarwin::ExceptionMessageBundleComplete() { if (m_sent_interrupt_signo != 0) { if (received_interrupt) { - if (log) - log->Printf("NativeProcessDarwin::%s(): process " - "successfully interrupted with signal %i", - __FUNCTION__, m_sent_interrupt_signo); + LLDB_LOGF(log, + "NativeProcessDarwin::%s(): process " + "successfully interrupted with signal %i", + __FUNCTION__, m_sent_interrupt_signo); // Mark that we received the interrupt signal m_sent_interrupt_signo = 0; @@ -792,19 +784,19 @@ task_t NativeProcessDarwin::ExceptionMessageBundleComplete() { // Only auto_resume if we stopped with _only_ the interrupt signal. if (num_task_exceptions == 1) { auto_resume = true; - if (log) - log->Printf("NativeProcessDarwin::%s(): auto " - "resuming due to unhandled interrupt " - "signal %i", - __FUNCTION__, m_auto_resume_signo); + LLDB_LOGF(log, + "NativeProcessDarwin::%s(): auto " + "resuming due to unhandled interrupt " + "signal %i", + __FUNCTION__, m_auto_resume_signo); } m_auto_resume_signo = 0; } } else { - if (log) - log->Printf("NativeProcessDarwin::%s(): didn't get signal " - "%i after MachProcess::Interrupt()", - __FUNCTION__, m_sent_interrupt_signo); + LLDB_LOGF(log, + "NativeProcessDarwin::%s(): didn't get signal " + "%i after MachProcess::Interrupt()", + __FUNCTION__, m_sent_interrupt_signo); } } } @@ -878,10 +870,10 @@ Status NativeProcessDarwin::StartWaitpidThread(MainLoop &main_loop) { const bool child_inherits = false; error = m_waitpid_pipe.CreateNew(child_inherits); if (error.Fail()) { - if (log) - log->Printf("NativeProcessDarwin::%s(): failed to create waitpid " - "communication pipe: %s", - __FUNCTION__, error.AsCString()); + LLDB_LOGF(log, + "NativeProcessDarwin::%s(): failed to create waitpid " + "communication pipe: %s", + __FUNCTION__, error.AsCString()); return error; } @@ -889,8 +881,8 @@ Status NativeProcessDarwin::StartWaitpidThread(MainLoop &main_loop) { // TODO make PipePOSIX derive from IOObject. This is goofy here. const bool transfer_ownership = false; - auto io_sp = IOObjectSP( - new File(m_waitpid_pipe.GetReadFileDescriptor(), transfer_ownership)); + auto io_sp = IOObjectSP(new NativeFile(m_waitpid_pipe.GetReadFileDescriptor(), + transfer_ownership)); m_waitpid_reader_handle = main_loop.RegisterReadObject( io_sp, [this](MainLoopBase &) { HandleWaitpidResult(); }, error); @@ -899,10 +891,10 @@ Status NativeProcessDarwin::StartWaitpidThread(MainLoop &main_loop) { ::pthread_create(&m_waitpid_thread, nullptr, WaitpidThread, this); error.SetError(pthread_err, eErrorTypePOSIX); if (error.Fail()) { - if (log) - log->Printf("NativeProcessDarwin::%s(): failed to create waitpid " - "handling thread: %u (%s)", - __FUNCTION__, error.GetError(), error.AsCString()); + LLDB_LOGF(log, + "NativeProcessDarwin::%s(): failed to create waitpid " + "handling thread: %u (%s)", + __FUNCTION__, error.GetError(), error.AsCString()); return error; } @@ -912,10 +904,10 @@ Status NativeProcessDarwin::StartWaitpidThread(MainLoop &main_loop) { void *NativeProcessDarwin::WaitpidThread(void *arg) { Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_PROCESS)); if (!arg) { - if (log) - log->Printf("NativeProcessDarwin::%s(): cannot run waitpid " - "thread, mandatory process arg was null", - __FUNCTION__); + LLDB_LOGF(log, + "NativeProcessDarwin::%s(): cannot run waitpid " + "thread, mandatory process arg was null", + __FUNCTION__); return nullptr; } @@ -938,10 +930,10 @@ void *NativeProcessDarwin::DoWaitpidThread() { Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_PROCESS)); if (m_pid == LLDB_INVALID_PROCESS_ID) { - if (log) - log->Printf("NativeProcessDarwin::%s(): inferior process ID is " - "not set, cannot waitpid on it", - __FUNCTION__); + LLDB_LOGF(log, + "NativeProcessDarwin::%s(): inferior process ID is " + "not set, cannot waitpid on it", + __FUNCTION__); return nullptr; } @@ -962,41 +954,41 @@ void *NativeProcessDarwin::DoWaitpidThread() { if (error.Fail()) { if (error.GetError() == EINTR) { // This is okay, we can keep going. - if (log) - log->Printf("NativeProcessDarwin::%s(): waitpid(pid = %" PRIu64 - ", &status, 0) interrupted, continuing", - __FUNCTION__, m_pid); + LLDB_LOGF(log, + "NativeProcessDarwin::%s(): waitpid(pid = %" PRIu64 + ", &status, 0) interrupted, continuing", + __FUNCTION__, m_pid); continue; } // This error is not okay, abort. - if (log) - log->Printf("NativeProcessDarwin::%s(): waitpid(pid = %" PRIu64 - ", &status, 0) aborting due to error: %u (%s)", - __FUNCTION__, m_pid, error.GetError(), error.AsCString()); + LLDB_LOGF(log, + "NativeProcessDarwin::%s(): waitpid(pid = %" PRIu64 + ", &status, 0) aborting due to error: %u (%s)", + __FUNCTION__, m_pid, error.GetError(), error.AsCString()); break; } // Log the successful result. - if (log) - log->Printf("NativeProcessDarwin::%s(): waitpid(pid = %" PRIu64 - ", &status, 0) => %i, status = %i", - __FUNCTION__, m_pid, child_pid, status); + LLDB_LOGF(log, + "NativeProcessDarwin::%s(): waitpid(pid = %" PRIu64 + ", &status, 0) => %i, status = %i", + __FUNCTION__, m_pid, child_pid, status); // Handle the result. if (WIFSTOPPED(status)) { - if (log) - log->Printf("NativeProcessDarwin::%s(): waitpid(pid = %" PRIu64 - ") received a stop, continuing waitpid() loop", - __FUNCTION__, m_pid); + LLDB_LOGF(log, + "NativeProcessDarwin::%s(): waitpid(pid = %" PRIu64 + ") received a stop, continuing waitpid() loop", + __FUNCTION__, m_pid); continue; } else // if (WIFEXITED(status) || WIFSIGNALED(status)) { - if (log) - log->Printf("NativeProcessDarwin::%s(pid = %" PRIu64 "): " - "waitpid thread is setting exit status for pid = " - "%i to %i", - __FUNCTION__, m_pid, child_pid, status); + LLDB_LOGF(log, + "NativeProcessDarwin::%s(pid = %" PRIu64 "): " + "waitpid thread is setting exit status for pid = " + "%i to %i", + __FUNCTION__, m_pid, child_pid, status); error = SendInferiorExitStatusToMainLoop(child_pid, status); return nullptr; @@ -1005,12 +997,11 @@ void *NativeProcessDarwin::DoWaitpidThread() { // We should never exit as long as our child process is alive. If we get // here, something completely unexpected went wrong and we should exit. - if (log) - log->Printf( - "NativeProcessDarwin::%s(): internal error: waitpid thread " - "exited out of its main loop in an unexpected way. pid = %" PRIu64 - ". Sending exit status of -1.", - __FUNCTION__, m_pid); + LLDB_LOGF(log, + "NativeProcessDarwin::%s(): internal error: waitpid thread " + "exited out of its main loop in an unexpected way. pid = %" PRIu64 + ". Sending exit status of -1.", + __FUNCTION__, m_pid); error = SendInferiorExitStatusToMainLoop((::pid_t)m_pid, -1); return nullptr; @@ -1026,11 +1017,11 @@ Status NativeProcessDarwin::SendInferiorExitStatusToMainLoop(::pid_t pid, // Send the pid. error = m_waitpid_pipe.Write(&pid, sizeof(pid), bytes_written); if (error.Fail() || (bytes_written < sizeof(pid))) { - if (log) - log->Printf("NativeProcessDarwin::%s() - failed to write " - "waitpid exiting pid to the pipe. Client will not " - "hear about inferior exit status!", - __FUNCTION__); + LLDB_LOGF(log, + "NativeProcessDarwin::%s() - failed to write " + "waitpid exiting pid to the pipe. Client will not " + "hear about inferior exit status!", + __FUNCTION__); return error; } @@ -1038,11 +1029,11 @@ Status NativeProcessDarwin::SendInferiorExitStatusToMainLoop(::pid_t pid, bytes_written = 0; error = m_waitpid_pipe.Write(&status, sizeof(status), bytes_written); if (error.Fail() || (bytes_written < sizeof(status))) { - if (log) - log->Printf("NativeProcessDarwin::%s() - failed to write " - "waitpid exit result to the pipe. Client will not " - "hear about inferior exit status!", - __FUNCTION__); + LLDB_LOGF(log, + "NativeProcessDarwin::%s() - failed to write " + "waitpid exit result to the pipe. Client will not " + "hear about inferior exit status!", + __FUNCTION__); } return error; } @@ -1058,11 +1049,11 @@ Status NativeProcessDarwin::HandleWaitpidResult() { size_t bytes_read = 0; error = m_waitpid_pipe.Read(&pid, sizeof(pid), bytes_read); if (error.Fail() || (bytes_read < sizeof(pid))) { - if (log) - log->Printf("NativeProcessDarwin::%s() - failed to read " - "waitpid exiting pid from the pipe. Will notify " - "as if parent process died with exit status -1.", - __FUNCTION__); + LLDB_LOGF(log, + "NativeProcessDarwin::%s() - failed to read " + "waitpid exiting pid from the pipe. Will notify " + "as if parent process died with exit status -1.", + __FUNCTION__); SetExitStatus(WaitStatus(WaitStatus::Exit, -1), notify_status); return error; } @@ -1071,21 +1062,21 @@ Status NativeProcessDarwin::HandleWaitpidResult() { int status = -1; error = m_waitpid_pipe.Read(&status, sizeof(status), bytes_read); if (error.Fail() || (bytes_read < sizeof(status))) { - if (log) - log->Printf("NativeProcessDarwin::%s() - failed to read " - "waitpid exit status from the pipe. Will notify " - "as if parent process died with exit status -1.", - __FUNCTION__); + LLDB_LOGF(log, + "NativeProcessDarwin::%s() - failed to read " + "waitpid exit status from the pipe. Will notify " + "as if parent process died with exit status -1.", + __FUNCTION__); SetExitStatus(WaitStatus(WaitStatus::Exit, -1), notify_status); return error; } // Notify the monitor that our state has changed. - if (log) - log->Printf("NativeProcessDarwin::%s(): main loop received waitpid " - "exit status info: pid=%i (%s), status=%i", - __FUNCTION__, pid, - (pid == m_pid) ? "the inferior" : "not the inferior", status); + LLDB_LOGF(log, + "NativeProcessDarwin::%s(): main loop received waitpid " + "exit status info: pid=%i (%s), status=%i", + __FUNCTION__, pid, + (pid == m_pid) ? "the inferior" : "not the inferior", status); SetExitStatus(WaitStatus::Decode(status), notify_status); return error; @@ -1096,10 +1087,10 @@ task_t NativeProcessDarwin::TaskPortForProcessID(Status &error, if ((m_task == TASK_NULL) || force) { Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_PROCESS)); if (m_pid == LLDB_INVALID_PROCESS_ID) { - if (log) - log->Printf("NativeProcessDarwin::%s(): cannot get task due " - "to invalid pid", - __FUNCTION__); + LLDB_LOGF(log, + "NativeProcessDarwin::%s(): cannot get task due " + "to invalid pid", + __FUNCTION__); return TASK_NULL; } @@ -1115,19 +1106,21 @@ task_t NativeProcessDarwin::TaskPortForProcessID(Status &error, // Succeeded. Save and return it. error.Clear(); m_task = task; - log->Printf("NativeProcessDarwin::%s(): ::task_for_pid(" - "stub_port = 0x%4.4x, pid = %llu, &task) " - "succeeded: inferior task port = 0x%4.4x", - __FUNCTION__, task_self, m_pid, m_task); + LLDB_LOGF(log, + "NativeProcessDarwin::%s(): ::task_for_pid(" + "stub_port = 0x%4.4x, pid = %llu, &task) " + "succeeded: inferior task port = 0x%4.4x", + __FUNCTION__, task_self, m_pid, m_task); return m_task; } else { // Failed to get the task for the inferior process. error.SetError(err, eErrorTypeMachKernel); if (log) { - log->Printf("NativeProcessDarwin::%s(): ::task_for_pid(" - "stub_port = 0x%4.4x, pid = %llu, &task) " - "failed, err = 0x%8.8x (%s)", - __FUNCTION__, task_self, m_pid, err, error.AsCString()); + LLDB_LOGF(log, + "NativeProcessDarwin::%s(): ::task_for_pid(" + "stub_port = 0x%4.4x, pid = %llu, &task) " + "failed, err = 0x%8.8x (%s)", + __FUNCTION__, task_self, m_pid, err, error.AsCString()); } } @@ -1156,20 +1149,21 @@ Status NativeProcessDarwin::PrivateResume() { if (log) { if (m_auto_resume_signo) - log->Printf("NativeProcessDarwin::%s(): task 0x%x resuming (with " - "unhandled interrupt signal %i)...", - __FUNCTION__, m_task, m_auto_resume_signo); + LLDB_LOGF(log, + "NativeProcessDarwin::%s(): task 0x%x resuming (with " + "unhandled interrupt signal %i)...", + __FUNCTION__, m_task, m_auto_resume_signo); else - log->Printf("NativeProcessDarwin::%s(): task 0x%x resuming...", - __FUNCTION__, m_task); + LLDB_LOGF(log, "NativeProcessDarwin::%s(): task 0x%x resuming...", + __FUNCTION__, m_task); } error = ReplyToAllExceptions(); if (error.Fail()) { - if (log) - log->Printf("NativeProcessDarwin::%s(): aborting, failed to " - "reply to exceptions: %s", - __FUNCTION__, error.AsCString()); + LLDB_LOGF(log, + "NativeProcessDarwin::%s(): aborting, failed to " + "reply to exceptions: %s", + __FUNCTION__, error.AsCString()); return error; } // bool stepOverBreakInstruction = step; @@ -1196,9 +1190,8 @@ Status NativeProcessDarwin::ReplyToAllExceptions() { TaskPortForProcessID(error); if (error.Fail()) { - if (log) - log->Printf("NativeProcessDarwin::%s(): no task port, aborting", - __FUNCTION__); + LLDB_LOGF(log, "NativeProcessDarwin::%s(): no task port, aborting", + __FUNCTION__); return error; } @@ -1211,9 +1204,10 @@ Status NativeProcessDarwin::ReplyToAllExceptions() { size_t index = 0; for (auto &message : m_exception_messages) { if (log) { - log->Printf("NativeProcessDarwin::%s(): replying to exception " - "%zu...", - __FUNCTION__, index++); + LLDB_LOGF(log, + "NativeProcessDarwin::%s(): replying to exception " + "%zu...", + __FUNCTION__, index++); } int thread_reply_signal = 0; @@ -1234,9 +1228,10 @@ Status NativeProcessDarwin::ReplyToAllExceptions() { if (error.Fail() && log) { // We log any error here, but we don't stop the exception response // handling. - log->Printf("NativeProcessDarwin::%s(): failed to reply to " - "exception: %s", - __FUNCTION__, error.AsCString()); + LLDB_LOGF(log, + "NativeProcessDarwin::%s(): failed to reply to " + "exception: %s", + __FUNCTION__, error.AsCString()); error.Clear(); } } @@ -1253,10 +1248,10 @@ Status NativeProcessDarwin::ResumeTask() { TaskPortForProcessID(error); if (error.Fail()) { - if (log) - log->Printf("NativeProcessDarwin::%s(): failed to get task port " - "for process when attempting to resume: %s", - __FUNCTION__, error.AsCString()); + LLDB_LOGF(log, + "NativeProcessDarwin::%s(): failed to get task port " + "for process when attempting to resume: %s", + __FUNCTION__, error.AsCString()); return error; } if (m_task == TASK_NULL) { @@ -1265,20 +1260,20 @@ Status NativeProcessDarwin::ResumeTask() { return error; } - if (log) - log->Printf("NativeProcessDarwin::%s(): requesting resume of task " - "0x%4.4x", - __FUNCTION__, m_task); + LLDB_LOGF(log, + "NativeProcessDarwin::%s(): requesting resume of task " + "0x%4.4x", + __FUNCTION__, m_task); // Get the BasicInfo struct to verify that we're suspended before we try to // resume the task. struct task_basic_info task_info; error = GetTaskBasicInfo(m_task, &task_info); if (error.Fail()) { - if (log) - log->Printf("NativeProcessDarwin::%s(): failed to get task " - "BasicInfo when attempting to resume: %s", - __FUNCTION__, error.AsCString()); + LLDB_LOGF(log, + "NativeProcessDarwin::%s(): failed to get task " + "BasicInfo when attempting to resume: %s", + __FUNCTION__, error.AsCString()); return error; } @@ -1289,16 +1284,16 @@ Status NativeProcessDarwin::ResumeTask() { error.SetError(mach_err, eErrorTypeMachKernel); if (log) { if (error.Success()) - log->Printf("::task_resume(target_task = 0x%4.4x): success", m_task); + LLDB_LOGF(log, "::task_resume(target_task = 0x%4.4x): success", m_task); else - log->Printf("::task_resume(target_task = 0x%4.4x) error: %s", m_task, - error.AsCString()); + LLDB_LOGF(log, "::task_resume(target_task = 0x%4.4x) error: %s", m_task, + error.AsCString()); } } else { - if (log) - log->Printf("::task_resume(target_task = 0x%4.4x): ignored, " - "already running", - m_task); + LLDB_LOGF(log, + "::task_resume(target_task = 0x%4.4x): ignored, " + "already running", + m_task); } return error; @@ -1353,11 +1348,11 @@ NativeProcessDarwin::GetTaskBasicInfo(task_t task, auto err = ::task_info(m_task, TASK_BASIC_INFO, (task_info_t)info, &count); error.SetError(err, eErrorTypeMachKernel); if (error.Fail()) { - if (log) - log->Printf("::task_info(target_task = 0x%4.4x, " - "flavor = TASK_BASIC_INFO, task_info_out => %p, " - "task_info_outCnt => %u) failed: %u (%s)", - m_task, info, count, error.GetError(), error.AsCString()); + LLDB_LOGF(log, + "::task_info(target_task = 0x%4.4x, " + "flavor = TASK_BASIC_INFO, task_info_out => %p, " + "task_info_outCnt => %u) failed: %u (%s)", + m_task, info, count, error.GetError(), error.AsCString()); return error; } @@ -1368,11 +1363,12 @@ NativeProcessDarwin::GetTaskBasicInfo(task_t task, (float)info->user_time.microseconds / 1000000.0f; float system = (float)info->user_time.seconds + (float)info->user_time.microseconds / 1000000.0f; - verbose_log->Printf("task_basic_info = { suspend_count = %i, " - "virtual_size = 0x%8.8llx, resident_size = " - "0x%8.8llx, user_time = %f, system_time = %f }", - info->suspend_count, (uint64_t)info->virtual_size, - (uint64_t)info->resident_size, user, system); + verbose_LLDB_LOGF(log, + "task_basic_info = { suspend_count = %i, " + "virtual_size = 0x%8.8llx, resident_size = " + "0x%8.8llx, user_time = %f, system_time = %f }", + info->suspend_count, (uint64_t)info->virtual_size, + (uint64_t)info->resident_size, user, system); } return error; } @@ -1383,16 +1379,15 @@ Status NativeProcessDarwin::SuspendTask() { if (m_task == TASK_NULL) { error.SetErrorString("task port is null, cannot suspend task"); - if (log) - log->Printf("NativeProcessDarwin::%s() failed: %s", __FUNCTION__, - error.AsCString()); + LLDB_LOGF(log, "NativeProcessDarwin::%s() failed: %s", __FUNCTION__, + error.AsCString()); return error; } auto mach_err = ::task_suspend(m_task); error.SetError(mach_err, eErrorTypeMachKernel); if (error.Fail() && log) - log->Printf("::task_suspend(target_task = 0x%4.4x)", m_task); + LLDB_LOGF(log, "::task_suspend(target_task = 0x%4.4x)", m_task); return error; } @@ -1401,8 +1396,7 @@ Status NativeProcessDarwin::Resume(const ResumeActionList &resume_actions) { Status error; Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_PROCESS)); - if (log) - log->Printf("NativeProcessDarwin::%s() called", __FUNCTION__); + LLDB_LOGF(log, "NativeProcessDarwin::%s() called", __FUNCTION__); if (CanResume()) { m_thread_actions = resume_actions; @@ -1412,10 +1406,10 @@ Status NativeProcessDarwin::Resume(const ResumeActionList &resume_actions) { auto state = GetState(); if (state == eStateRunning) { - if (log) - log->Printf("NativeProcessDarwin::%s(): task 0x%x is already " - "running, ignoring...", - __FUNCTION__, TaskPortForProcessID(error)); + LLDB_LOGF(log, + "NativeProcessDarwin::%s(): task 0x%x is already " + "running, ignoring...", + __FUNCTION__, TaskPortForProcessID(error)); return error; } diff --git a/source/Plugins/Process/Darwin/NativeThreadListDarwin.cpp b/source/Plugins/Process/Darwin/NativeThreadListDarwin.cpp index 89de92a6df4d..1faa5b219cbc 100644 --- a/source/Plugins/Process/Darwin/NativeThreadListDarwin.cpp +++ b/source/Plugins/Process/Darwin/NativeThreadListDarwin.cpp @@ -301,10 +301,10 @@ uint32_t NativeThreadListDarwin::UpdateThreadList(NativeProcessDarwin &process, Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_THREAD)); std::lock_guard<std::recursive_mutex> locker(m_threads_mutex); - if (log) - log->Printf("NativeThreadListDarwin::%s() (pid = %" PRIu64 ", update = " - "%u) process stop count = %u", - __FUNCTION__, process.GetID(), update, process.GetStopID()); + LLDB_LOGF(log, + "NativeThreadListDarwin::%s() (pid = %" PRIu64 ", update = " + "%u) process stop count = %u", + __FUNCTION__, process.GetID(), update, process.GetStopID()); if (process.GetStopID() == 0) { // On our first stop, we'll record details like 32/64 bitness and select @@ -346,11 +346,11 @@ uint32_t NativeThreadListDarwin::UpdateThreadList(NativeProcessDarwin &process, auto mach_err = ::task_threads(task, &thread_list, &thread_list_count); error.SetError(mach_err, eErrorTypeMachKernel); if (error.Fail()) { - if (log) - log->Printf("::task_threads(task = 0x%4.4x, thread_list => %p, " - "thread_list_count => %u) failed: %u (%s)", - task, thread_list, thread_list_count, error.GetError(), - error.AsCString()); + LLDB_LOGF(log, + "::task_threads(task = 0x%4.4x, thread_list => %p, " + "thread_list_count => %u) failed: %u (%s)", + task, thread_list, thread_list_count, error.GetError(), + error.AsCString()); return 0; } diff --git a/source/Plugins/Process/FreeBSD/FreeBSDThread.cpp b/source/Plugins/Process/FreeBSD/FreeBSDThread.cpp index 749835531279..0a49f96f54a1 100644 --- a/source/Plugins/Process/FreeBSD/FreeBSDThread.cpp +++ b/source/Plugins/Process/FreeBSD/FreeBSDThread.cpp @@ -288,9 +288,8 @@ void FreeBSDThread::DidStop() { void FreeBSDThread::WillResume(lldb::StateType resume_state) { Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_THREAD)); - if (log) - log->Printf("tid %lu resume_state = %s", GetID(), - lldb_private::StateAsCString(resume_state)); + LLDB_LOGF(log, "tid %lu resume_state = %s", GetID(), + lldb_private::StateAsCString(resume_state)); ProcessSP process_sp(GetProcess()); ProcessFreeBSD *process = static_cast<ProcessFreeBSD *>(process_sp.get()); int signo = GetResumeSignal(); @@ -322,9 +321,8 @@ bool FreeBSDThread::Resume() { bool status; Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_THREAD)); - if (log) - log->Printf("FreeBSDThread::%s (), resume_state = %s", __FUNCTION__, - StateAsCString(resume_state)); + LLDB_LOGF(log, "FreeBSDThread::%s (), resume_state = %s", __FUNCTION__, + StateAsCString(resume_state)); switch (resume_state) { default: @@ -352,9 +350,8 @@ bool FreeBSDThread::Resume() { void FreeBSDThread::Notify(const ProcessMessage &message) { Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_THREAD)); - if (log) - log->Printf("FreeBSDThread::%s () message kind = '%s' for tid %" PRIu64, - __FUNCTION__, message.PrintKind(), GetID()); + LLDB_LOGF(log, "FreeBSDThread::%s () message kind = '%s' for tid %" PRIu64, + __FUNCTION__, message.PrintKind(), GetID()); switch (message.GetKind()) { default: @@ -457,8 +454,7 @@ void FreeBSDThread::BreakNotify(const ProcessMessage &message) { // corresponding to our current PC. assert(GetRegisterContext()); lldb::addr_t pc = GetRegisterContext()->GetPC(); - if (log) - log->Printf("FreeBSDThread::%s () PC=0x%8.8" PRIx64, __FUNCTION__, pc); + LLDB_LOGF(log, "FreeBSDThread::%s () PC=0x%8.8" PRIx64, __FUNCTION__, pc); lldb::BreakpointSiteSP bp_site( GetProcess()->GetBreakpointSiteList().FindByAddress(pc)); @@ -490,10 +486,9 @@ void FreeBSDThread::WatchNotify(const ProcessMessage &message) { Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_THREAD)); lldb::addr_t halt_addr = message.GetHWAddress(); - if (log) - log->Printf( - "FreeBSDThread::%s () Hardware Watchpoint Address = 0x%8.8" PRIx64, - __FUNCTION__, halt_addr); + LLDB_LOGF(log, + "FreeBSDThread::%s () Hardware Watchpoint Address = 0x%8.8" PRIx64, + __FUNCTION__, halt_addr); POSIXBreakpointProtocol *reg_ctx = GetPOSIXBreakpointProtocol(); if (reg_ctx) { @@ -527,8 +522,7 @@ void FreeBSDThread::TraceNotify(const ProcessMessage &message) { // Try to resolve the breakpoint object corresponding to the current PC. assert(GetRegisterContext()); lldb::addr_t pc = GetRegisterContext()->GetPC(); - if (log) - log->Printf("FreeBSDThread::%s () PC=0x%8.8" PRIx64, __FUNCTION__, pc); + LLDB_LOGF(log, "FreeBSDThread::%s () PC=0x%8.8" PRIx64, __FUNCTION__, pc); lldb::BreakpointSiteSP bp_site( GetProcess()->GetBreakpointSiteList().FindByAddress(pc)); diff --git a/source/Plugins/Process/FreeBSD/ProcessFreeBSD.cpp b/source/Plugins/Process/FreeBSD/ProcessFreeBSD.cpp index 770794569f72..32e3320150f8 100644 --- a/source/Plugins/Process/FreeBSD/ProcessFreeBSD.cpp +++ b/source/Plugins/Process/FreeBSD/ProcessFreeBSD.cpp @@ -154,9 +154,8 @@ Status ProcessFreeBSD::DoResume() { do_step = true; } - if (log) - log->Printf("process %" PRIu64 " resuming (%s)", GetID(), - do_step ? "step" : "continue"); + LLDB_LOGF(log, "process %" PRIu64 " resuming (%s)", GetID(), + do_step ? "step" : "continue"); if (do_step && !software_single_step) m_monitor->SingleStep(GetID(), m_resume_signo); else @@ -168,9 +167,8 @@ Status ProcessFreeBSD::DoResume() { bool ProcessFreeBSD::UpdateThreadList(ThreadList &old_thread_list, ThreadList &new_thread_list) { Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_PROCESS)); - if (log) - log->Printf("ProcessFreeBSD::%s (pid = %" PRIu64 ")", __FUNCTION__, - GetID()); + LLDB_LOGF(log, "ProcessFreeBSD::%s (pid = %" PRIu64 ")", __FUNCTION__, + GetID()); std::vector<lldb::pid_t> tds; if (!GetMonitor().GetCurrentThreadIDs(tds)) { @@ -183,20 +181,18 @@ bool ProcessFreeBSD::UpdateThreadList(ThreadList &old_thread_list, ThreadSP thread_sp(old_thread_list_copy.RemoveThreadByID(tid, false)); if (!thread_sp) { thread_sp.reset(new FreeBSDThread(*this, tid)); - if (log) - log->Printf("ProcessFreeBSD::%s new tid = %" PRIu64, __FUNCTION__, tid); + LLDB_LOGF(log, "ProcessFreeBSD::%s new tid = %" PRIu64, __FUNCTION__, + tid); } else { - if (log) - log->Printf("ProcessFreeBSD::%s existing tid = %" PRIu64, __FUNCTION__, - tid); + LLDB_LOGF(log, "ProcessFreeBSD::%s existing tid = %" PRIu64, __FUNCTION__, + tid); } new_thread_list.AddThread(thread_sp); } for (size_t i = 0; i < old_thread_list_copy.GetSize(false); ++i) { ThreadSP old_thread_sp(old_thread_list_copy.GetThreadAtIndex(i, false)); if (old_thread_sp) { - if (log) - log->Printf("ProcessFreeBSD::%s remove tid", __FUNCTION__); + LLDB_LOGF(log, "ProcessFreeBSD::%s remove tid", __FUNCTION__); } } @@ -698,14 +694,13 @@ Status ProcessFreeBSD::EnableWatchpoint(Watchpoint *wp, bool notify) { user_id_t watchID = wp->GetID(); addr_t addr = wp->GetLoadAddress(); Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_WATCHPOINTS)); - if (log) - log->Printf("ProcessFreeBSD::EnableWatchpoint(watchID = %" PRIu64 ")", - watchID); + LLDB_LOGF(log, "ProcessFreeBSD::EnableWatchpoint(watchID = %" PRIu64 ")", + watchID); if (wp->IsEnabled()) { - if (log) - log->Printf("ProcessFreeBSD::EnableWatchpoint(watchID = %" PRIu64 - ") addr = 0x%8.8" PRIx64 ": watchpoint already enabled.", - watchID, (uint64_t)addr); + LLDB_LOGF(log, + "ProcessFreeBSD::EnableWatchpoint(watchID = %" PRIu64 + ") addr = 0x%8.8" PRIx64 ": watchpoint already enabled.", + watchID, (uint64_t)addr); return error; } @@ -753,14 +748,13 @@ Status ProcessFreeBSD::DisableWatchpoint(Watchpoint *wp, bool notify) { user_id_t watchID = wp->GetID(); addr_t addr = wp->GetLoadAddress(); Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_WATCHPOINTS)); - if (log) - log->Printf("ProcessFreeBSD::DisableWatchpoint(watchID = %" PRIu64 ")", - watchID); + LLDB_LOGF(log, "ProcessFreeBSD::DisableWatchpoint(watchID = %" PRIu64 ")", + watchID); if (!wp->IsEnabled()) { - if (log) - log->Printf("ProcessFreeBSD::DisableWatchpoint(watchID = %" PRIu64 - ") addr = 0x%8.8" PRIx64 ": watchpoint already disabled.", - watchID, (uint64_t)addr); + LLDB_LOGF(log, + "ProcessFreeBSD::DisableWatchpoint(watchID = %" PRIu64 + ") addr = 0x%8.8" PRIx64 ": watchpoint already disabled.", + watchID, (uint64_t)addr); // This is needed (for now) to keep watchpoints disabled correctly wp->SetEnabled(false, notify); return error; @@ -970,8 +964,9 @@ Status ProcessFreeBSD::SetSoftwareSingleStepBreakpoint(lldb::tid_t tid, Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_PROCESS)); if (log) { - log->Printf("ProcessFreeBSD::%s addr = 0x%" PRIx64, __FUNCTION__, addr); - log->Printf("SoftwareBreakpoint::%s addr = 0x%" PRIx64, __FUNCTION__, addr); + LLDB_LOGF(log, "ProcessFreeBSD::%s addr = 0x%" PRIx64, __FUNCTION__, addr); + LLDB_LOGF(log, "SoftwareBreakpoint::%s addr = 0x%" PRIx64, __FUNCTION__, + addr); } // Validate the address. @@ -982,11 +977,10 @@ Status ProcessFreeBSD::SetSoftwareSingleStepBreakpoint(lldb::tid_t tid, Breakpoint *const sw_step_break = m_process->GetTarget().CreateBreakpoint(addr, true, false).get(); sw_step_break->SetCallback(SingleStepBreakpointHit, this, true); - sw_step_break->SetBreakpointKind("software-signle-step"); + sw_step_break->SetBreakpointKind("software-single-step"); - if (log) - log->Printf("ProcessFreeBSD::%s addr = 0x%" PRIx64 " -- SUCCESS", - __FUNCTION__, addr); + LLDB_LOGF(log, "ProcessFreeBSD::%s addr = 0x%" PRIx64 " -- SUCCESS", + __FUNCTION__, addr); m_threads_stepping_with_breakpoint.insert({tid, sw_step_break->GetID()}); return Status(); diff --git a/source/Plugins/Process/FreeBSD/ProcessMonitor.cpp b/source/Plugins/Process/FreeBSD/ProcessMonitor.cpp index 4b9225db5e39..ff3fb0a75e2d 100644 --- a/source/Plugins/Process/FreeBSD/ProcessMonitor.cpp +++ b/source/Plugins/Process/FreeBSD/ProcessMonitor.cpp @@ -37,9 +37,6 @@ using namespace lldb; using namespace lldb_private; -// We disable the tracing of ptrace calls for integration builds to avoid the -// additional indirection and checks. -#ifndef LLDB_CONFIGURATION_BUILDANDINTEGRATION // Wrapper for ptrace to catch errors and log calls. const char *Get_PT_IO_OP(int op) { @@ -66,13 +63,14 @@ extern long PtraceWrapper(int req, lldb::pid_t pid, void *addr, int data, Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_PTRACE)); if (log) { - log->Printf("ptrace(%s, %" PRIu64 ", %p, %x) called from file %s line %d", - reqName, pid, addr, data, file, line); + LLDB_LOGF(log, + "ptrace(%s, %" PRIu64 ", %p, %x) called from file %s line %d", + reqName, pid, addr, data, file, line); if (req == PT_IO) { struct ptrace_io_desc *pi = (struct ptrace_io_desc *)addr; - log->Printf("PT_IO: op=%s offs=%zx size=%zu", Get_PT_IO_OP(pi->piod_op), - (size_t)pi->piod_offs, pi->piod_len); + LLDB_LOGF(log, "PT_IO: op=%s offs=%zx size=%zu", + Get_PT_IO_OP(pi->piod_op), (size_t)pi->piod_offs, pi->piod_len); } } @@ -101,7 +99,7 @@ extern long PtraceWrapper(int req, lldb::pid_t pid, void *addr, int data, default: str = "<unknown>"; } - log->Printf("ptrace() failed; errno=%d (%s)", errno, str); + LLDB_LOGF(log, "ptrace() failed; errno=%d (%s)", errno, str); } if (log) { @@ -109,15 +107,15 @@ extern long PtraceWrapper(int req, lldb::pid_t pid, void *addr, int data, if (req == PT_GETREGS) { struct reg *r = (struct reg *)addr; - log->Printf("PT_GETREGS: rip=0x%lx rsp=0x%lx rbp=0x%lx rax=0x%lx", - r->r_rip, r->r_rsp, r->r_rbp, r->r_rax); + LLDB_LOGF(log, "PT_GETREGS: rip=0x%lx rsp=0x%lx rbp=0x%lx rax=0x%lx", + r->r_rip, r->r_rsp, r->r_rbp, r->r_rax); } if (req == PT_GETDBREGS || req == PT_SETDBREGS) { struct dbreg *r = (struct dbreg *)addr; char setget = (req == PT_GETDBREGS) ? 'G' : 'S'; for (int i = 0; i <= 7; i++) - log->Printf("PT_%cETDBREGS: dr[%d]=0x%lx", setget, i, r->dr[i]); + LLDB_LOGF(log, "PT_%cETDBREGS: dr[%d]=0x%lx", setget, i, r->dr[i]); } #endif } @@ -136,9 +134,6 @@ extern long PtraceWrapper(int req, lldb::pid_t pid, void *addr, int data) { #define PTRACE(req, pid, addr, data) \ PtraceWrapper((req), (pid), (addr), (data), #req, __FILE__, __LINE__) -#else -PtraceWrapper((req), (pid), (addr), (data)) -#endif // Static implementations of ProcessMonitor::ReadMemory and // ProcessMonitor::WriteMemory. This enables mutual recursion between these @@ -708,7 +703,7 @@ ProcessMonitor::ProcessMonitor( const lldb_private::ProcessLaunchInfo & /* launch_info */, lldb_private::Status &error) : m_process(static_cast<ProcessFreeBSD *>(process)), - m_operation_thread(nullptr), m_monitor_thread(nullptr), m_pid(LLDB_INVALID_PROCESS_ID), m_terminal_fd(-1), m_operation(0) { + m_operation_thread(), m_monitor_thread(), m_pid(LLDB_INVALID_PROCESS_ID), m_terminal_fd(-1), m_operation(0) { using namespace std::placeholders; std::unique_ptr<LaunchArgs> args( @@ -735,20 +730,22 @@ ProcessMonitor::ProcessMonitor( } // Finally, start monitoring the child process for change in state. - m_monitor_thread = Host::StartMonitoringChildProcess( + llvm::Expected<lldb_private::HostThread> monitor_thread = + Host::StartMonitoringChildProcess( std::bind(&ProcessMonitor::MonitorCallback, this, _1, _2, _3, _4), GetPID(), true); - if (!m_monitor_thread->IsJoinable()) { + if (!monitor_thread || !monitor_thread->IsJoinable()) { error.SetErrorToGenericError(); error.SetErrorString("Process launch failed."); return; } + m_monitor_thread = *monitor_thread; } ProcessMonitor::ProcessMonitor(ProcessFreeBSD *process, lldb::pid_t pid, lldb_private::Status &error) : m_process(static_cast<ProcessFreeBSD *>(process)), - m_operation_thread(nullptr), m_monitor_thread(nullptr), m_pid(pid), m_terminal_fd(-1), m_operation(0) { + m_operation_thread(), m_monitor_thread(), m_pid(pid), m_terminal_fd(-1), m_operation(0) { using namespace std::placeholders; sem_init(&m_operation_pending, 0, 0); @@ -773,14 +770,16 @@ ProcessMonitor::ProcessMonitor(ProcessFreeBSD *process, lldb::pid_t pid, } // Finally, start monitoring the child process for change in state. - m_monitor_thread = Host::StartMonitoringChildProcess( + llvm::Expected<lldb_private::HostThread> monitor_thread = + Host::StartMonitoringChildProcess( std::bind(&ProcessMonitor::MonitorCallback, this, _1, _2, _3, _4), GetPID(), true); - if (!m_monitor_thread->IsJoinable()) { + if (!monitor_thread || !monitor_thread->IsJoinable()) { error.SetErrorToGenericError(); error.SetErrorString("Process attach failed."); return; } + m_monitor_thread = *monitor_thread; } ProcessMonitor::~ProcessMonitor() { StopMonitor(); } @@ -789,13 +788,15 @@ ProcessMonitor::~ProcessMonitor() { StopMonitor(); } void ProcessMonitor::StartLaunchOpThread(LaunchArgs *args, Status &error) { static const char *g_thread_name = "lldb.process.freebsd.operation"; - if (m_operation_thread->IsJoinable()) + if (m_operation_thread && m_operation_thread->IsJoinable()) return; - m_operation_thread = - ThreadLauncher::LaunchThread(g_thread_name, LaunchOpThread, args); - if (!m_operation_thread) - error = m_operation_thread.takeError(); + llvm::Expected<lldb_private::HostThread> operation_thread = + ThreadLauncher::LaunchThread(g_thread_name, LaunchOpThread, args); + if (operation_thread) + m_operation_thread = *operation_thread; + else + error = operation_thread.takeError(); } void *ProcessMonitor::LaunchOpThread(void *arg) { @@ -957,14 +958,15 @@ void ProcessMonitor::StartAttachOpThread(AttachArgs *args, lldb_private::Status &error) { static const char *g_thread_name = "lldb.process.freebsd.operation"; - if (m_operation_thread->IsJoinable()) + if (m_operation_thread && m_operation_thread->IsJoinable()) return; - m_operation_thread = - ThreadLauncher::LaunchThread(g_thread_name, AttachOpThread, args); - - if (!m_operation_thread) - error = m_operation_thread.takeError(); + llvm::Expected<lldb_private::HostThread> operation_thread = + ThreadLauncher::LaunchThread(g_thread_name, AttachOpThread, args); + if (operation_thread) + m_operation_thread = *operation_thread; + else + error = operation_thread.takeError(); } void *ProcessMonitor::AttachOpThread(void *arg) { @@ -1037,9 +1039,8 @@ bool ProcessMonitor::MonitorCallback(ProcessMonitor *monitor, lldb::pid_t pid, Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_PROCESS)); if (exited) { - if (log) - log->Printf("ProcessMonitor::%s() got exit signal, tid = %" PRIu64, - __FUNCTION__, pid); + LLDB_LOGF(log, "ProcessMonitor::%s() got exit signal, tid = %" PRIu64, + __FUNCTION__, pid); message = ProcessMessage::Exit(pid, status); process->SendMessage(message); return pid == process->GetID(); @@ -1087,10 +1088,10 @@ ProcessMessage ProcessMonitor::MonitorSIGTRAP(ProcessMonitor *monitor, unsigned long data = 0; if (!monitor->GetEventMessage(tid, &data)) data = -1; - if (log) - log->Printf("ProcessMonitor::%s() received exit? event, data = %lx, tid " - "= %" PRIu64, - __FUNCTION__, data, tid); + LLDB_LOGF(log, + "ProcessMonitor::%s() received exit? event, data = %lx, tid " + "= %" PRIu64, + __FUNCTION__, data, tid); message = ProcessMessage::Limbo(tid, (data >> 8)); break; } @@ -1101,26 +1102,25 @@ ProcessMessage ProcessMonitor::MonitorSIGTRAP(ProcessMonitor *monitor, // Map TRAP_CAP to a trace trap in the absense of a more specific handler. case TRAP_CAP: #endif - if (log) - log->Printf("ProcessMonitor::%s() received trace event, tid = %" PRIu64 - " : si_code = %d", - __FUNCTION__, tid, info->si_code); + LLDB_LOGF(log, + "ProcessMonitor::%s() received trace event, tid = %" PRIu64 + " : si_code = %d", + __FUNCTION__, tid, info->si_code); message = ProcessMessage::Trace(tid); break; case SI_KERNEL: case TRAP_BRKPT: if (monitor->m_process->IsSoftwareStepBreakpoint(tid)) { - if (log) - log->Printf("ProcessMonitor::%s() received sw single step breakpoint " - "event, tid = %" PRIu64, - __FUNCTION__, tid); + LLDB_LOGF(log, + "ProcessMonitor::%s() received sw single step breakpoint " + "event, tid = %" PRIu64, + __FUNCTION__, tid); message = ProcessMessage::Trace(tid); } else { - if (log) - log->Printf( - "ProcessMonitor::%s() received breakpoint event, tid = %" PRIu64, - __FUNCTION__, tid); + LLDB_LOGF( + log, "ProcessMonitor::%s() received breakpoint event, tid = %" PRIu64, + __FUNCTION__, tid); message = ProcessMessage::Break(tid); } break; @@ -1146,22 +1146,19 @@ ProcessMessage ProcessMonitor::MonitorSignal(ProcessMonitor *monitor, // // Similarly, ACK signals generated by this monitor. if (info->si_code == SI_USER) { - if (log) - log->Printf( - "ProcessMonitor::%s() received signal %s with code %s, pid = %d", - __FUNCTION__, - monitor->m_process->GetUnixSignals()->GetSignalAsCString(signo), - "SI_USER", info->si_pid); + LLDB_LOGF(log, + "ProcessMonitor::%s() received signal %s with code %s, pid = %d", + __FUNCTION__, + monitor->m_process->GetUnixSignals()->GetSignalAsCString(signo), + "SI_USER", info->si_pid); if (info->si_pid == getpid()) return ProcessMessage::SignalDelivered(tid, signo); else return ProcessMessage::Signal(tid, signo); } - if (log) - log->Printf( - "ProcessMonitor::%s() received signal %s", __FUNCTION__, - monitor->m_process->GetUnixSignals()->GetSignalAsCString(signo)); + LLDB_LOGF(log, "ProcessMonitor::%s() received signal %s", __FUNCTION__, + monitor->m_process->GetUnixSignals()->GetSignalAsCString(signo)); switch (signo) { case SIGSEGV: @@ -1313,14 +1310,14 @@ bool ProcessMonitor::Resume(lldb::tid_t unused, uint32_t signo) { m_process->GetUnixSignals()->GetSignalAsCString(signo); if (signame == nullptr) signame = "<none>"; - log->Printf("ProcessMonitor::%s() resuming pid %" PRIu64 " with signal %s", - __FUNCTION__, GetPID(), signame); + LLDB_LOGF(log, + "ProcessMonitor::%s() resuming pid %" PRIu64 " with signal %s", + __FUNCTION__, GetPID(), signame); } ResumeOperation op(signo, result); DoOperation(&op); - if (log) - log->Printf("ProcessMonitor::%s() resuming result = %s", __FUNCTION__, - result ? "true" : "false"); + LLDB_LOGF(log, "ProcessMonitor::%s() resuming result = %s", __FUNCTION__, + result ? "true" : "false"); return result; } @@ -1384,7 +1381,7 @@ bool ProcessMonitor::DupDescriptor(const FileSpec &file_spec, int fd, } void ProcessMonitor::StopMonitoringChildProcess() { - if (m_monitor_thread->IsJoinable()) { + if (m_monitor_thread && m_monitor_thread->IsJoinable()) { m_monitor_thread->Cancel(); m_monitor_thread->Join(nullptr); m_monitor_thread->Reset(); @@ -1422,10 +1419,9 @@ void ProcessMonitor::StopMonitor() { bool ProcessMonitor::WaitForInitialTIDStop(lldb::tid_t tid) { return true; } void ProcessMonitor::StopOpThread() { - if (!m_operation_thread->IsJoinable()) - return; - - m_operation_thread->Cancel(); - m_operation_thread->Join(nullptr); - m_operation_thread->Reset(); + if (m_operation_thread && m_operation_thread->IsJoinable()) { + m_operation_thread->Cancel(); + m_operation_thread->Join(nullptr); + m_operation_thread->Reset(); + } } diff --git a/source/Plugins/Process/FreeBSD/ProcessMonitor.h b/source/Plugins/Process/FreeBSD/ProcessMonitor.h index 2adcc449c5c6..c5edfc0be95a 100644 --- a/source/Plugins/Process/FreeBSD/ProcessMonitor.h +++ b/source/Plugins/Process/FreeBSD/ProcessMonitor.h @@ -183,8 +183,8 @@ public: private: ProcessFreeBSD *m_process; - llvm::Expected<lldb_private::HostThread> m_operation_thread; - llvm::Expected<lldb_private::HostThread> m_monitor_thread; + llvm::Optional<lldb_private::HostThread> m_operation_thread; + llvm::Optional<lldb_private::HostThread> m_monitor_thread; lldb::pid_t m_pid; int m_terminal_fd; diff --git a/source/Plugins/Process/NetBSD/NativeProcessNetBSD.cpp b/source/Plugins/Process/NetBSD/NativeProcessNetBSD.cpp index 32d20d2b1215..8b6f9fbc33c3 100644 --- a/source/Plugins/Process/NetBSD/NativeProcessNetBSD.cpp +++ b/source/Plugins/Process/NetBSD/NativeProcessNetBSD.cpp @@ -140,7 +140,7 @@ NativeProcessNetBSD::NativeProcessNetBSD(::pid_t pid, int terminal_fd, NativeDelegate &delegate, const ArchSpec &arch, MainLoop &mainloop) - : NativeProcessProtocol(pid, terminal_fd, delegate), m_arch(arch) { + : NativeProcessELF(pid, terminal_fd, delegate), m_arch(arch) { if (m_terminal_fd != -1) { Status status = EnsureFDFlags(m_terminal_fd, O_NONBLOCK); assert(status.Success()); @@ -195,6 +195,7 @@ void NativeProcessNetBSD::MonitorSIGSTOP(lldb::pid_t pid) { SIGSTOP, &info.psi_siginfo); } } + SetState(StateType::eStateStopped, true); } } @@ -339,12 +340,14 @@ Status NativeProcessNetBSD::Resume(const ResumeActionList &resume_actions) { } Status error; + int signal = + action->signal != LLDB_INVALID_SIGNAL_NUMBER ? action->signal : 0; switch (action->state) { case eStateRunning: { // Run the thread, possibly feeding it the signal. error = NativeProcessNetBSD::PtraceWrapper(PT_CONTINUE, GetID(), (void *)1, - action->signal); + signal); if (!error.Success()) return error; for (const auto &thread : m_threads) @@ -355,7 +358,7 @@ Status NativeProcessNetBSD::Resume(const ResumeActionList &resume_actions) { case eStateStepping: // Run the thread, possibly feeding it the signal. error = NativeProcessNetBSD::PtraceWrapper(PT_STEP, GetID(), (void *)1, - action->signal); + signal); if (!error.Success()) return error; for (const auto &thread : m_threads) @@ -658,7 +661,7 @@ NativeThreadNetBSD &NativeProcessNetBSD::AddThread(lldb::tid_t thread_id) { if (m_threads.empty()) SetCurrentThreadID(thread_id); - m_threads.push_back(llvm::make_unique<NativeThreadNetBSD>(*this, thread_id)); + m_threads.push_back(std::make_unique<NativeThreadNetBSD>(*this, thread_id)); return static_cast<NativeThreadNetBSD &>(*m_threads.back()); } diff --git a/source/Plugins/Process/NetBSD/NativeProcessNetBSD.h b/source/Plugins/Process/NetBSD/NativeProcessNetBSD.h index e85ca3b7a925..4e7f0a1c13ab 100644 --- a/source/Plugins/Process/NetBSD/NativeProcessNetBSD.h +++ b/source/Plugins/Process/NetBSD/NativeProcessNetBSD.h @@ -9,12 +9,12 @@ #ifndef liblldb_NativeProcessNetBSD_H_ #define liblldb_NativeProcessNetBSD_H_ +#include "Plugins/Process/POSIX/NativeProcessELF.h" #include "lldb/Target/MemoryRegionInfo.h" #include "lldb/Utility/ArchSpec.h" #include "lldb/Utility/FileSpec.h" #include "NativeThreadNetBSD.h" -#include "lldb/Host/common/NativeProcessProtocol.h" namespace lldb_private { namespace process_netbsd { @@ -25,7 +25,7 @@ namespace process_netbsd { /// for debugging. /// /// Changes in the inferior process state are broadcasted. -class NativeProcessNetBSD : public NativeProcessProtocol { +class NativeProcessNetBSD : public NativeProcessELF { public: class Factory : public NativeProcessProtocol::Factory { public: diff --git a/source/Plugins/Process/NetBSD/NativeRegisterContextNetBSD_x86_64.cpp b/source/Plugins/Process/NetBSD/NativeRegisterContextNetBSD_x86_64.cpp index a7cd637bf826..6cc2810fa235 100644 --- a/source/Plugins/Process/NetBSD/NativeRegisterContextNetBSD_x86_64.cpp +++ b/source/Plugins/Process/NetBSD/NativeRegisterContextNetBSD_x86_64.cpp @@ -906,8 +906,8 @@ uint32_t NativeRegisterContextNetBSD_x86_64::SetHardwareWatchpoint( return wp_index; } if (error.Fail() && log) { - log->Printf("NativeRegisterContextNetBSD_x86_64::%s Error: %s", - __FUNCTION__, error.AsCString()); + LLDB_LOGF(log, "NativeRegisterContextNetBSD_x86_64::%s Error: %s", + __FUNCTION__, error.AsCString()); } } return LLDB_INVALID_INDEX32; diff --git a/source/Plugins/Process/POSIX/CrashReason.cpp b/source/Plugins/Process/POSIX/CrashReason.cpp index 70c2687e3b8c..9678e48436e7 100644 --- a/source/Plugins/Process/POSIX/CrashReason.cpp +++ b/source/Plugins/Process/POSIX/CrashReason.cpp @@ -229,11 +229,6 @@ std::string GetCrashReasonString(CrashReason reason, lldb::addr_t fault_addr) { } const char *CrashReasonAsString(CrashReason reason) { -#ifdef LLDB_CONFIGURATION_BUILDANDINTEGRATION - // Just return the code in ascii for integration builds. - chcar str[8]; - sprintf(str, "%d", reason); -#else const char *str = nullptr; switch (reason) { @@ -315,8 +310,6 @@ const char *CrashReasonAsString(CrashReason reason) { str = "eFloatSubscriptRange"; break; } -#endif - return str; } diff --git a/source/Plugins/Process/POSIX/NativeProcessELF.cpp b/source/Plugins/Process/POSIX/NativeProcessELF.cpp index 559b16c8fd69..058dc5ae2338 100644 --- a/source/Plugins/Process/POSIX/NativeProcessELF.cpp +++ b/source/Plugins/Process/POSIX/NativeProcessELF.cpp @@ -21,7 +21,7 @@ NativeProcessELF::GetAuxValue(enum AuxVector::EntryType type) { DataExtractor auxv_data(buffer_or_error.get()->getBufferStart(), buffer_or_error.get()->getBufferSize(), GetByteOrder(), GetAddressByteSize()); - m_aux_vector = llvm::make_unique<AuxVector>(auxv_data); + m_aux_vector = std::make_unique<AuxVector>(auxv_data); } return m_aux_vector->GetAuxValue(type); @@ -107,4 +107,72 @@ lldb::addr_t NativeProcessELF::GetELFImageInfoAddress() { return LLDB_INVALID_ADDRESS; } -} // namespace lldb_private
\ No newline at end of file +template <typename T> +llvm::Expected<SVR4LibraryInfo> +NativeProcessELF::ReadSVR4LibraryInfo(lldb::addr_t link_map_addr) { + ELFLinkMap<T> link_map; + size_t bytes_read; + auto error = + ReadMemory(link_map_addr, &link_map, sizeof(link_map), bytes_read); + if (!error.Success()) + return error.ToError(); + + char name_buffer[PATH_MAX]; + llvm::Expected<llvm::StringRef> string_or_error = ReadCStringFromMemory( + link_map.l_name, &name_buffer[0], sizeof(name_buffer), bytes_read); + if (!string_or_error) + return string_or_error.takeError(); + + SVR4LibraryInfo info; + info.name = string_or_error->str(); + info.link_map = link_map_addr; + info.base_addr = link_map.l_addr; + info.ld_addr = link_map.l_ld; + info.next = link_map.l_next; + + return info; +} + +llvm::Expected<std::vector<SVR4LibraryInfo>> +NativeProcessELF::GetLoadedSVR4Libraries() { + // Address of DT_DEBUG.d_ptr which points to r_debug + lldb::addr_t info_address = GetSharedLibraryInfoAddress(); + if (info_address == LLDB_INVALID_ADDRESS) + return llvm::createStringError(llvm::inconvertibleErrorCode(), + "Invalid shared library info address"); + // Address of r_debug + lldb::addr_t address = 0; + size_t bytes_read; + auto status = + ReadMemory(info_address, &address, GetAddressByteSize(), bytes_read); + if (!status.Success()) + return status.ToError(); + if (address == 0) + return llvm::createStringError(llvm::inconvertibleErrorCode(), + "Invalid r_debug address"); + // Read r_debug.r_map + lldb::addr_t link_map = 0; + status = ReadMemory(address + GetAddressByteSize(), &link_map, + GetAddressByteSize(), bytes_read); + if (!status.Success()) + return status.ToError(); + if (address == 0) + return llvm::createStringError(llvm::inconvertibleErrorCode(), + "Invalid link_map address"); + + std::vector<SVR4LibraryInfo> library_list; + while (link_map) { + llvm::Expected<SVR4LibraryInfo> info = + GetAddressByteSize() == 8 ? ReadSVR4LibraryInfo<uint64_t>(link_map) + : ReadSVR4LibraryInfo<uint32_t>(link_map); + if (!info) + return info.takeError(); + if (!info->name.empty() && info->base_addr != 0) + library_list.push_back(*info); + link_map = info->next; + } + + return library_list; +} + +} // namespace lldb_private diff --git a/source/Plugins/Process/POSIX/NativeProcessELF.h b/source/Plugins/Process/POSIX/NativeProcessELF.h index 84dc8d08a340..4fb513baebf0 100644 --- a/source/Plugins/Process/POSIX/NativeProcessELF.h +++ b/source/Plugins/Process/POSIX/NativeProcessELF.h @@ -37,6 +37,13 @@ protected: template <typename ELF_EHDR, typename ELF_PHDR, typename ELF_DYN> lldb::addr_t GetELFImageInfoAddress(); + llvm::Expected<std::vector<SVR4LibraryInfo>> + GetLoadedSVR4Libraries() override; + + template <typename T> + llvm::Expected<SVR4LibraryInfo> + ReadSVR4LibraryInfo(lldb::addr_t link_map_addr); + std::unique_ptr<AuxVector> m_aux_vector; llvm::Optional<lldb::addr_t> m_shared_library_info_addr; }; diff --git a/source/Plugins/Process/POSIX/ProcessMessage.cpp b/source/Plugins/Process/POSIX/ProcessMessage.cpp index aa8449131a68..66286dd3d9e3 100644 --- a/source/Plugins/Process/POSIX/ProcessMessage.cpp +++ b/source/Plugins/Process/POSIX/ProcessMessage.cpp @@ -15,11 +15,6 @@ const char *ProcessMessage::PrintCrashReason() const { } const char *ProcessMessage::PrintKind(Kind kind) { -#ifdef LLDB_CONFIGURATION_BUILDANDINTEGRATION - // Just return the code in ascii for integration builds. - chcar str[8]; - sprintf(str, "%d", reason); -#else const char *str = nullptr; switch (kind) { @@ -60,8 +55,6 @@ const char *ProcessMessage::PrintKind(Kind kind) { str = "eExecMessage"; break; } -#endif - return str; } diff --git a/source/Plugins/Process/Utility/AuxVector.cpp b/source/Plugins/Process/Utility/AuxVector.cpp index aab164ff93a6..25a1d0b5af06 100644 --- a/source/Plugins/Process/Utility/AuxVector.cpp +++ b/source/Plugins/Process/Utility/AuxVector.cpp @@ -43,9 +43,9 @@ void AuxVector::DumpToLog(lldb_private::Log *log) const { log->PutCString("AuxVector: "); for (auto entry : m_auxv_entries) { - log->Printf(" %s [%" PRIu64 "]: %" PRIx64, - GetEntryName(static_cast<EntryType>(entry.first)), entry.first, - entry.second); + LLDB_LOGF(log, " %s [%" PRIu64 "]: %" PRIx64, + GetEntryName(static_cast<EntryType>(entry.first)), entry.first, + entry.second); } } diff --git a/source/Plugins/Process/Utility/DynamicRegisterInfo.cpp b/source/Plugins/Process/Utility/DynamicRegisterInfo.cpp index 1afe4d920599..a86880af2260 100644 --- a/source/Plugins/Process/Utility/DynamicRegisterInfo.cpp +++ b/source/Plugins/Process/Utility/DynamicRegisterInfo.cpp @@ -137,76 +137,67 @@ DynamicRegisterInfo::SetRegisterInfo(const StructuredData::Dictionary &dict, // ends at static RegularExpression g_bitfield_regex( llvm::StringRef("([A-Za-z_][A-Za-z0-9_]*)\\[([0-9]+):([0-9]+)\\]")); - RegularExpression::Match regex_match(3); - if (g_bitfield_regex.Execute(slice_str, ®ex_match)) { - llvm::StringRef reg_name_str; - std::string msbit_str; - std::string lsbit_str; - if (regex_match.GetMatchAtIndex(slice_str, 1, reg_name_str) && - regex_match.GetMatchAtIndex(slice_str, 2, msbit_str) && - regex_match.GetMatchAtIndex(slice_str, 3, lsbit_str)) { - const uint32_t msbit = - StringConvert::ToUInt32(msbit_str.c_str(), UINT32_MAX); - const uint32_t lsbit = - StringConvert::ToUInt32(lsbit_str.c_str(), UINT32_MAX); - if (msbit != UINT32_MAX && lsbit != UINT32_MAX) { - if (msbit > lsbit) { - const uint32_t msbyte = msbit / 8; - const uint32_t lsbyte = lsbit / 8; - - ConstString containing_reg_name(reg_name_str); - - const RegisterInfo *containing_reg_info = - GetRegisterInfo(containing_reg_name); - if (containing_reg_info) { - const uint32_t max_bit = containing_reg_info->byte_size * 8; - if (msbit < max_bit && lsbit < max_bit) { - m_invalidate_regs_map[containing_reg_info - ->kinds[eRegisterKindLLDB]] - .push_back(i); - m_value_regs_map[i].push_back( - containing_reg_info->kinds[eRegisterKindLLDB]); - m_invalidate_regs_map[i].push_back( - containing_reg_info->kinds[eRegisterKindLLDB]); - - if (byte_order == eByteOrderLittle) { - success = true; - reg_info.byte_offset = - containing_reg_info->byte_offset + lsbyte; - } else if (byte_order == eByteOrderBig) { - success = true; - reg_info.byte_offset = - containing_reg_info->byte_offset + msbyte; - } else { - llvm_unreachable("Invalid byte order"); - } + llvm::SmallVector<llvm::StringRef, 4> matches; + if (g_bitfield_regex.Execute(slice_str, &matches)) { + std::string reg_name_str = matches[1].str(); + std::string msbit_str = matches[2].str(); + std::string lsbit_str = matches[3].str(); + const uint32_t msbit = + StringConvert::ToUInt32(msbit_str.c_str(), UINT32_MAX); + const uint32_t lsbit = + StringConvert::ToUInt32(lsbit_str.c_str(), UINT32_MAX); + if (msbit != UINT32_MAX && lsbit != UINT32_MAX) { + if (msbit > lsbit) { + const uint32_t msbyte = msbit / 8; + const uint32_t lsbyte = lsbit / 8; + + ConstString containing_reg_name(reg_name_str); + + const RegisterInfo *containing_reg_info = + GetRegisterInfo(containing_reg_name); + if (containing_reg_info) { + const uint32_t max_bit = containing_reg_info->byte_size * 8; + if (msbit < max_bit && lsbit < max_bit) { + m_invalidate_regs_map[containing_reg_info + ->kinds[eRegisterKindLLDB]] + .push_back(i); + m_value_regs_map[i].push_back( + containing_reg_info->kinds[eRegisterKindLLDB]); + m_invalidate_regs_map[i].push_back( + containing_reg_info->kinds[eRegisterKindLLDB]); + + if (byte_order == eByteOrderLittle) { + success = true; + reg_info.byte_offset = + containing_reg_info->byte_offset + lsbyte; + } else if (byte_order == eByteOrderBig) { + success = true; + reg_info.byte_offset = + containing_reg_info->byte_offset + msbyte; } else { - if (msbit > max_bit) - printf("error: msbit (%u) must be less than the bitsize " - "of the register (%u)\n", - msbit, max_bit); - else - printf("error: lsbit (%u) must be less than the bitsize " - "of the register (%u)\n", - lsbit, max_bit); + llvm_unreachable("Invalid byte order"); } } else { - printf("error: invalid concrete register \"%s\"\n", - containing_reg_name.GetCString()); + if (msbit > max_bit) + printf("error: msbit (%u) must be less than the bitsize " + "of the register (%u)\n", + msbit, max_bit); + else + printf("error: lsbit (%u) must be less than the bitsize " + "of the register (%u)\n", + lsbit, max_bit); } } else { - printf("error: msbit (%u) must be greater than lsbit (%u)\n", - msbit, lsbit); + printf("error: invalid concrete register \"%s\"\n", + containing_reg_name.GetCString()); } } else { - printf("error: msbit (%u) and lsbit (%u) must be valid\n", msbit, - lsbit); + printf("error: msbit (%u) must be greater than lsbit (%u)\n", + msbit, lsbit); } } else { - // TODO: print error invalid slice string that doesn't follow the - // format - printf("error: failed to extract regex matches for parsing the " - "register bitfield regex\n"); + printf("error: msbit (%u) and lsbit (%u) must be valid\n", msbit, + lsbit); } } else { // TODO: print error invalid slice string that doesn't follow the @@ -545,6 +536,7 @@ void DynamicRegisterInfo::Finalize(const ArchSpec &arch) { if (!generic_regs_specified) { switch (arch.GetMachine()) { case llvm::Triple::aarch64: + case llvm::Triple::aarch64_32: case llvm::Triple::aarch64_be: for (auto ® : m_regs) { if (strcmp(reg.name, "pc") == 0) diff --git a/source/Plugins/Process/Utility/HistoryThread.cpp b/source/Plugins/Process/Utility/HistoryThread.cpp index 3cb583172623..295c17e474fb 100644 --- a/source/Plugins/Process/Utility/HistoryThread.cpp +++ b/source/Plugins/Process/Utility/HistoryThread.cpp @@ -32,17 +32,15 @@ HistoryThread::HistoryThread(lldb_private::Process &process, lldb::tid_t tid, m_queue_id(LLDB_INVALID_QUEUE_ID) { m_unwinder_up.reset(new HistoryUnwind(*this, pcs)); Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_OBJECT)); - if (log) - log->Printf("%p HistoryThread::HistoryThread", static_cast<void *>(this)); + LLDB_LOGF(log, "%p HistoryThread::HistoryThread", static_cast<void *>(this)); } // Destructor HistoryThread::~HistoryThread() { Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_OBJECT)); - if (log) - log->Printf("%p HistoryThread::~HistoryThread (tid=0x%" PRIx64 ")", - static_cast<void *>(this), GetID()); + LLDB_LOGF(log, "%p HistoryThread::~HistoryThread (tid=0x%" PRIx64 ")", + static_cast<void *>(this), GetID()); DestroyThread(); } diff --git a/source/Plugins/Process/Utility/HistoryUnwind.cpp b/source/Plugins/Process/Utility/HistoryUnwind.cpp index 7d473bff8200..83fdb011f5a1 100644 --- a/source/Plugins/Process/Utility/HistoryUnwind.cpp +++ b/source/Plugins/Process/Utility/HistoryUnwind.cpp @@ -51,13 +51,15 @@ HistoryUnwind::DoCreateRegisterContextForFrame(StackFrame *frame) { } bool HistoryUnwind::DoGetFrameInfoAtIndex(uint32_t frame_idx, lldb::addr_t &cfa, - lldb::addr_t &pc) { + lldb::addr_t &pc, + bool &behaves_like_zeroth_frame) { // FIXME do not throw away the lock after we acquire it.. std::unique_lock<std::recursive_mutex> guard(m_unwind_mutex); guard.unlock(); if (frame_idx < m_pcs.size()) { cfa = frame_idx; pc = m_pcs[frame_idx]; + behaves_like_zeroth_frame = (frame_idx == 0); return true; } return false; diff --git a/source/Plugins/Process/Utility/HistoryUnwind.h b/source/Plugins/Process/Utility/HistoryUnwind.h index 6c4522e6b35b..4d16608bd8c2 100644 --- a/source/Plugins/Process/Utility/HistoryUnwind.h +++ b/source/Plugins/Process/Utility/HistoryUnwind.h @@ -29,7 +29,8 @@ protected: DoCreateRegisterContextForFrame(StackFrame *frame) override; bool DoGetFrameInfoAtIndex(uint32_t frame_idx, lldb::addr_t &cfa, - lldb::addr_t &pc) override; + lldb::addr_t &pc, + bool &behaves_like_zeroth_frame) override; uint32_t DoGetFrameCount() override; private: diff --git a/source/Plugins/Process/Utility/InferiorCallPOSIX.cpp b/source/Plugins/Process/Utility/InferiorCallPOSIX.cpp index 9beaf2fc7ac8..2ccbeacc4960 100644 --- a/source/Plugins/Process/Utility/InferiorCallPOSIX.cpp +++ b/source/Plugins/Process/Utility/InferiorCallPOSIX.cpp @@ -12,7 +12,7 @@ #include "lldb/Core/ValueObject.h" #include "lldb/Expression/DiagnosticManager.h" #include "lldb/Host/Config.h" -#include "lldb/Symbol/ClangASTContext.h" +#include "lldb/Symbol/TypeSystem.h" #include "lldb/Symbol/SymbolContext.h" #include "lldb/Target/ExecutionContext.h" #include "lldb/Target/Platform.h" @@ -41,13 +41,13 @@ bool lldb_private::InferiorCallMmap(Process *process, addr_t &allocated_addr, if (thread == nullptr) return false; - const bool append = true; const bool include_symbols = true; const bool include_inlines = false; SymbolContextList sc_list; - const uint32_t count = process->GetTarget().GetImages().FindFunctions( + process->GetTarget().GetImages().FindFunctions( ConstString("mmap"), eFunctionNameTypeFull, include_symbols, - include_inlines, append, sc_list); + include_inlines, sc_list); + const uint32_t count = sc_list.GetSize(); if (count > 0) { SymbolContext sc; if (sc_list.GetContextAtIndex(0, sc)) { @@ -79,17 +79,23 @@ bool lldb_private::InferiorCallMmap(Process *process, addr_t &allocated_addr, AddressRange mmap_range; if (sc.GetAddressRange(range_scope, 0, use_inline_block_range, mmap_range)) { - ClangASTContext *clang_ast_context = - process->GetTarget().GetScratchClangASTContext(); - CompilerType clang_void_ptr_type = - clang_ast_context->GetBasicType(eBasicTypeVoid).GetPointerType(); + auto type_system_or_err = + process->GetTarget().GetScratchTypeSystemForLanguage( + eLanguageTypeC); + if (!type_system_or_err) { + llvm::consumeError(type_system_or_err.takeError()); + return false; + } + CompilerType void_ptr_type = + type_system_or_err->GetBasicTypeFromAST(eBasicTypeVoid) + .GetPointerType(); const ArchSpec arch = process->GetTarget().GetArchitecture(); MmapArgList args = process->GetTarget().GetPlatform()->GetMmapArgumentList( arch, addr, length, prot_arg, flags, fd, offset); lldb::ThreadPlanSP call_plan_sp( new ThreadPlanCallFunction(*thread, mmap_range.GetBaseAddress(), - clang_void_ptr_type, args, options)); + void_ptr_type, args, options)); if (call_plan_sp) { DiagnosticManager diagnostics; @@ -129,13 +135,13 @@ bool lldb_private::InferiorCallMunmap(Process *process, addr_t addr, if (thread == nullptr) return false; - const bool append = true; const bool include_symbols = true; const bool include_inlines = false; SymbolContextList sc_list; - const uint32_t count = process->GetTarget().GetImages().FindFunctions( + process->GetTarget().GetImages().FindFunctions( ConstString("munmap"), eFunctionNameTypeFull, include_symbols, - include_inlines, append, sc_list); + include_inlines, sc_list); + const uint32_t count = sc_list.GetSize(); if (count > 0) { SymbolContext sc; if (sc_list.GetContextAtIndex(0, sc)) { @@ -178,60 +184,3 @@ bool lldb_private::InferiorCallMunmap(Process *process, addr_t addr, return false; } - -// FIXME: This has nothing to do with Posix, it is just a convenience function -// that calls a -// function of the form "void * (*)(void)". We should find a better place to -// put this. - -bool lldb_private::InferiorCall(Process *process, const Address *address, - addr_t &returned_func, bool trap_exceptions) { - Thread *thread = - process->GetThreadList().GetExpressionExecutionThread().get(); - if (thread == nullptr || address == nullptr) - return false; - - EvaluateExpressionOptions options; - options.SetStopOthers(true); - options.SetUnwindOnError(true); - options.SetIgnoreBreakpoints(true); - options.SetTryAllThreads(true); - options.SetDebug(false); - options.SetTimeout(process->GetUtilityExpressionTimeout()); - options.SetTrapExceptions(trap_exceptions); - - ClangASTContext *clang_ast_context = - process->GetTarget().GetScratchClangASTContext(); - CompilerType clang_void_ptr_type = - clang_ast_context->GetBasicType(eBasicTypeVoid).GetPointerType(); - lldb::ThreadPlanSP call_plan_sp( - new ThreadPlanCallFunction(*thread, *address, clang_void_ptr_type, - llvm::ArrayRef<addr_t>(), options)); - if (call_plan_sp) { - DiagnosticManager diagnostics; - - StackFrame *frame = thread->GetStackFrameAtIndex(0).get(); - if (frame) { - ExecutionContext exe_ctx; - frame->CalculateExecutionContext(exe_ctx); - ExpressionResults result = - process->RunThreadPlan(exe_ctx, call_plan_sp, options, diagnostics); - if (result == eExpressionCompleted) { - returned_func = - call_plan_sp->GetReturnValueObject()->GetValueAsUnsigned( - LLDB_INVALID_ADDRESS); - - if (process->GetAddressByteSize() == 4) { - if (returned_func == UINT32_MAX) - return false; - } else if (process->GetAddressByteSize() == 8) { - if (returned_func == UINT64_MAX) - return false; - } - return true; - } - } - } - - return false; -} diff --git a/source/Plugins/Process/Utility/InferiorCallPOSIX.h b/source/Plugins/Process/Utility/InferiorCallPOSIX.h index 04316801b351..2008c5fe0b91 100644 --- a/source/Plugins/Process/Utility/InferiorCallPOSIX.h +++ b/source/Plugins/Process/Utility/InferiorCallPOSIX.h @@ -30,9 +30,6 @@ bool InferiorCallMmap(Process *proc, lldb::addr_t &allocated_addr, bool InferiorCallMunmap(Process *proc, lldb::addr_t addr, lldb::addr_t length); -bool InferiorCall(Process *proc, const Address *address, - lldb::addr_t &returned_func, bool trap_exceptions = false); - } // namespace lldb_private #endif // lldb_InferiorCallPOSIX_h_ diff --git a/source/Plugins/Process/Utility/RegisterContextDarwin_arm.cpp b/source/Plugins/Process/Utility/RegisterContextDarwin_arm.cpp index e804a4d251f7..4ca33c248c6f 100644 --- a/source/Plugins/Process/Utility/RegisterContextDarwin_arm.cpp +++ b/source/Plugins/Process/Utility/RegisterContextDarwin_arm.cpp @@ -1111,9 +1111,10 @@ int RegisterContextDarwin_arm::WriteRegisterSet(uint32_t set) { void RegisterContextDarwin_arm::LogDBGRegisters(Log *log, const DBG &dbg) { if (log) { for (uint32_t i = 0; i < 16; i++) - log->Printf("BVR%-2u/BCR%-2u = { 0x%8.8x, 0x%8.8x } WVR%-2u/WCR%-2u = { " - "0x%8.8x, 0x%8.8x }", - i, i, dbg.bvr[i], dbg.bcr[i], i, i, dbg.wvr[i], dbg.wcr[i]); + LLDB_LOGF(log, + "BVR%-2u/BCR%-2u = { 0x%8.8x, 0x%8.8x } WVR%-2u/WCR%-2u = { " + "0x%8.8x, 0x%8.8x }", + i, i, dbg.bvr[i], dbg.bcr[i], i, i, dbg.wvr[i], dbg.wcr[i]); } } @@ -1514,8 +1515,6 @@ uint32_t RegisterContextDarwin_arm::NumSupportedHardwareBreakpoints() { // Zero is reserved for the BRP count, so don't increment it if it is zero if (g_num_supported_hw_breakpoints > 0) g_num_supported_hw_breakpoints++; - // if (log) log->Printf ("DBGDIDR=0x%8.8x (number BRP pairs = %u)", - // register_DBGDIDR, g_num_supported_hw_breakpoints); } return g_num_supported_hw_breakpoints; #else @@ -1642,8 +1641,6 @@ uint32_t RegisterContextDarwin_arm::NumSupportedHardwareWatchpoints() { uint32_t register_DBGDIDR; asm("mrc p14, 0, %0, c0, c0, 0" : "=r"(register_DBGDIDR)); g_num_supported_hw_watchpoints = Bits32(register_DBGDIDR, 31, 28) + 1; - // if (log) log->Printf ("DBGDIDR=0x%8.8x (number WRP pairs = %u)", - // register_DBGDIDR, g_num_supported_hw_watchpoints); } return g_num_supported_hw_watchpoints; #else @@ -1656,10 +1653,6 @@ uint32_t RegisterContextDarwin_arm::SetHardwareWatchpoint(lldb::addr_t addr, size_t size, bool read, bool write) { - // if (log) log->Printf - // ("RegisterContextDarwin_arm::EnableHardwareWatchpoint(addr = %8.8p, size - // = %u, read = %u, write = %u)", addr, size, read, write); - const uint32_t num_hw_watchpoints = NumSupportedHardwareWatchpoints(); // Can't watch zero bytes diff --git a/source/Plugins/Process/Utility/RegisterContextDarwin_arm64.cpp b/source/Plugins/Process/Utility/RegisterContextDarwin_arm64.cpp index 85d518a487bf..b3ec24d8905d 100644 --- a/source/Plugins/Process/Utility/RegisterContextDarwin_arm64.cpp +++ b/source/Plugins/Process/Utility/RegisterContextDarwin_arm64.cpp @@ -25,6 +25,11 @@ #include <memory> +#if defined(__APPLE__) && (defined(__arm64__) || defined(__aarch64__)) +#include <sys/types.h> +#include <sys/sysctl.h> +#endif + // Support building against older versions of LLVM, this macro was added // recently. #ifndef LLVM_EXTENSION @@ -285,10 +290,11 @@ int RegisterContextDarwin_arm64::WriteRegisterSet(uint32_t set) { void RegisterContextDarwin_arm64::LogDBGRegisters(Log *log, const DBG &dbg) { if (log) { for (uint32_t i = 0; i < 16; i++) - log->Printf("BVR%-2u/BCR%-2u = { 0x%8.8" PRIu64 ", 0x%8.8" PRIu64 - " } WVR%-2u/WCR%-2u " - "= { 0x%8.8" PRIu64 ", 0x%8.8" PRIu64 " }", - i, i, dbg.bvr[i], dbg.bcr[i], i, i, dbg.wvr[i], dbg.wcr[i]); + LLDB_LOGF(log, + "BVR%-2u/BCR%-2u = { 0x%8.8" PRIu64 ", 0x%8.8" PRIu64 + " } WVR%-2u/WCR%-2u " + "= { 0x%8.8" PRIu64 ", 0x%8.8" PRIu64 " }", + i, i, dbg.bvr[i], dbg.bcr[i], i, i, dbg.wvr[i], dbg.wcr[i]); } } @@ -423,7 +429,7 @@ bool RegisterContextDarwin_arm64::ReadRegister(const RegisterInfo *reg_info, case fpu_v29: case fpu_v30: case fpu_v31: - value.SetBytes(fpu.v[reg - fpu_v0].bytes.buffer, reg_info->byte_size, + value.SetBytes(fpu.v[reg - fpu_v0].bytes, reg_info->byte_size, endian::InlHostByteOrder()); break; @@ -502,7 +508,7 @@ bool RegisterContextDarwin_arm64::ReadRegister(const RegisterInfo *reg_info, case fpu_d31: { ProcessSP process_sp(m_thread.GetProcess()); if (process_sp.get()) { - DataExtractor regdata(&fpu.v[reg - fpu_s0], 8, process_sp->GetByteOrder(), + DataExtractor regdata(&fpu.v[reg - fpu_d0], 8, process_sp->GetByteOrder(), process_sp->GetAddressByteSize()); offset_t offset = 0; value.SetDouble(regdata.GetDouble(&offset)); @@ -615,7 +621,7 @@ bool RegisterContextDarwin_arm64::WriteRegister(const RegisterInfo *reg_info, case fpu_v29: case fpu_v30: case fpu_v31: - ::memcpy(fpu.v[reg - fpu_v0].bytes.buffer, value.GetBytes(), + ::memcpy(fpu.v[reg - fpu_v0].bytes, value.GetBytes(), value.GetByteSize()); break; diff --git a/source/Plugins/Process/Utility/RegisterContextDarwin_arm64.h b/source/Plugins/Process/Utility/RegisterContextDarwin_arm64.h index 2f691c807d50..abb87e3c2348 100644 --- a/source/Plugins/Process/Utility/RegisterContextDarwin_arm64.h +++ b/source/Plugins/Process/Utility/RegisterContextDarwin_arm64.h @@ -73,7 +73,7 @@ public: }; struct VReg { - llvm::AlignedCharArray<16, 16> bytes; + alignas(16) char bytes[16]; }; // mirrors <mach/arm/thread_status.h> arm_neon_state64_t diff --git a/source/Plugins/Process/Utility/RegisterContextDarwin_i386.cpp b/source/Plugins/Process/Utility/RegisterContextDarwin_i386.cpp index 820d280c37f7..873713fd8373 100644 --- a/source/Plugins/Process/Utility/RegisterContextDarwin_i386.cpp +++ b/source/Plugins/Process/Utility/RegisterContextDarwin_i386.cpp @@ -496,11 +496,11 @@ int RegisterContextDarwin_i386::GetSetForNativeRegNum(int reg_num) { void RegisterContextDarwin_i386::LogGPR(Log *log, const char *title) { if (log) { if (title) - log->Printf("%s", title); + LLDB_LOGF(log, "%s", title); for (uint32_t i = 0; i < k_num_gpr_registers; i++) { uint32_t reg = gpr_eax + i; - log->Printf("%12s = 0x%8.8x", g_register_infos[reg].name, - (&gpr.eax)[reg]); + LLDB_LOGF(log, "%12s = 0x%8.8x", g_register_infos[reg].name, + (&gpr.eax)[reg]); } } } diff --git a/source/Plugins/Process/Utility/RegisterContextDarwin_x86_64.cpp b/source/Plugins/Process/Utility/RegisterContextDarwin_x86_64.cpp index 62e512adc9f7..47758ce85eb2 100644 --- a/source/Plugins/Process/Utility/RegisterContextDarwin_x86_64.cpp +++ b/source/Plugins/Process/Utility/RegisterContextDarwin_x86_64.cpp @@ -554,22 +554,6 @@ int RegisterContextDarwin_x86_64::GetSetForNativeRegNum(int reg_num) { return -1; } -void RegisterContextDarwin_x86_64::LogGPR(Log *log, const char *format, ...) { - if (log) { - if (format) { - va_list args; - va_start(args, format); - log->VAPrintf(format, args); - va_end(args); - } - for (uint32_t i = 0; i < k_num_gpr_registers; i++) { - uint32_t reg = gpr_rax + i; - log->Printf("%12s = 0x%16.16" PRIx64, g_register_infos[reg].name, - (&gpr.rax)[reg]); - } - } -} - int RegisterContextDarwin_x86_64::ReadGPR(bool force) { int set = GPRRegSet; if (force || !RegisterSetIsCached(set)) { diff --git a/source/Plugins/Process/Utility/RegisterContextLLDB.cpp b/source/Plugins/Process/Utility/RegisterContextLLDB.cpp index 76646d8897d1..49a589f14989 100644 --- a/source/Plugins/Process/Utility/RegisterContextLLDB.cpp +++ b/source/Plugins/Process/Utility/RegisterContextLLDB.cpp @@ -12,12 +12,14 @@ #include "lldb/Core/Value.h" #include "lldb/Expression/DWARFExpression.h" #include "lldb/Symbol/ArmUnwindInfo.h" +#include "lldb/Symbol/CallFrameInfo.h" #include "lldb/Symbol/DWARFCallFrameInfo.h" #include "lldb/Symbol/FuncUnwinders.h" #include "lldb/Symbol/Function.h" #include "lldb/Symbol/ObjectFile.h" #include "lldb/Symbol/Symbol.h" #include "lldb/Symbol/SymbolContext.h" +#include "lldb/Symbol/SymbolFile.h" #include "lldb/Target/ABI.h" #include "lldb/Target/DynamicLoader.h" #include "lldb/Target/ExecutionContext.h" @@ -150,15 +152,8 @@ void RegisterContextLLDB::InitializeZerothFrame() { UnwindLogMsg("using architectural default unwind method"); } - // We require either a symbol or function in the symbols context to be - // successfully filled in or this context is of no use to us. - const SymbolContextItem resolve_scope = - eSymbolContextFunction | eSymbolContextSymbol; - if (pc_module_sp.get() && (pc_module_sp->ResolveSymbolContextForAddress( - m_current_pc, resolve_scope, m_sym_ctx) & - resolve_scope)) { - m_sym_ctx_valid = true; - } + AddressRange addr_range; + m_sym_ctx_valid = m_current_pc.ResolveFunctionScope(m_sym_ctx, &addr_range); if (m_sym_ctx.symbol) { UnwindLogMsg("with pc value of 0x%" PRIx64 ", symbol name is '%s'", @@ -172,9 +167,6 @@ void RegisterContextLLDB::InitializeZerothFrame() { current_pc); } - AddressRange addr_range; - m_sym_ctx.GetAddressRange(resolve_scope, 0, false, addr_range); - if (IsTrapHandlerSymbol(process, m_sym_ctx)) { m_frame_type = eTrapHandlerFrame; } else { @@ -436,24 +428,8 @@ void RegisterContextLLDB::InitializeNonZerothFrame() { return; } - bool resolve_tail_call_address = false; // m_current_pc can be one past the - // address range of the function... - // If the saved pc does not point to a function/symbol because it is beyond - // the bounds of the correct function and there's no symbol there, we do - // *not* want ResolveSymbolContextForAddress to back up the pc by 1, because - // then we might not find the correct unwind information later. Instead, let - // ResolveSymbolContextForAddress fail, and handle the case via - // decr_pc_and_recompute_addr_range below. - const SymbolContextItem resolve_scope = - eSymbolContextFunction | eSymbolContextSymbol; - uint32_t resolved_scope = pc_module_sp->ResolveSymbolContextForAddress( - m_current_pc, resolve_scope, m_sym_ctx, resolve_tail_call_address); - - // We require either a symbol or function in the symbols context to be - // successfully filled in or this context is of no use to us. - if (resolve_scope & resolved_scope) { - m_sym_ctx_valid = true; - } + AddressRange addr_range; + m_sym_ctx_valid = m_current_pc.ResolveFunctionScope(m_sym_ctx, &addr_range); if (m_sym_ctx.symbol) { UnwindLogMsg("with pc value of 0x%" PRIx64 ", symbol name is '%s'", pc, @@ -467,25 +443,30 @@ void RegisterContextLLDB::InitializeNonZerothFrame() { pc); } - AddressRange addr_range; - if (!m_sym_ctx.GetAddressRange(resolve_scope, 0, false, addr_range)) { - m_sym_ctx_valid = false; - } + bool decr_pc_and_recompute_addr_range; - bool decr_pc_and_recompute_addr_range = false; - - // If the symbol lookup failed... - if (!m_sym_ctx_valid) + if (!m_sym_ctx_valid) { + // Always decrement and recompute if the symbol lookup failed decr_pc_and_recompute_addr_range = true; - - // Or if we're in the middle of the stack (and not "above" an asynchronous - // event like sigtramp), and our "current" pc is the start of a function... - if (GetNextFrame()->m_frame_type != eTrapHandlerFrame && - GetNextFrame()->m_frame_type != eDebuggerFrame && - (!m_sym_ctx_valid || - (addr_range.GetBaseAddress().IsValid() && - addr_range.GetBaseAddress().GetSection() == m_current_pc.GetSection() && - addr_range.GetBaseAddress().GetOffset() == m_current_pc.GetOffset()))) { + } else if (GetNextFrame()->m_frame_type == eTrapHandlerFrame || + GetNextFrame()->m_frame_type == eDebuggerFrame) { + // Don't decrement if we're "above" an asynchronous event like + // sigtramp. + decr_pc_and_recompute_addr_range = false; + } else if (!addr_range.GetBaseAddress().IsValid() || + addr_range.GetBaseAddress().GetSection() != m_current_pc.GetSection() || + addr_range.GetBaseAddress().GetOffset() != m_current_pc.GetOffset()) { + // If our "current" pc isn't the start of a function, no need + // to decrement and recompute. + decr_pc_and_recompute_addr_range = false; + } else if (IsTrapHandlerSymbol(process, m_sym_ctx)) { + // Signal dispatch may set the return address of the handler it calls to + // point to the first byte of a return trampoline (like __kernel_rt_sigreturn), + // so do not decrement and recompute if the symbol we already found is a trap + // handler. + decr_pc_and_recompute_addr_range = false; + } else { + // Decrement to find the function containing the call. decr_pc_and_recompute_addr_range = true; } @@ -502,18 +483,8 @@ void RegisterContextLLDB::InitializeNonZerothFrame() { Address temporary_pc; temporary_pc.SetLoadAddress(pc - 1, &process->GetTarget()); m_sym_ctx.Clear(false); - m_sym_ctx_valid = false; - SymbolContextItem resolve_scope = - eSymbolContextFunction | eSymbolContextSymbol; - - ModuleSP temporary_module_sp = temporary_pc.GetModule(); - if (temporary_module_sp && - temporary_module_sp->ResolveSymbolContextForAddress( - temporary_pc, resolve_scope, m_sym_ctx) & - resolve_scope) { - if (m_sym_ctx.GetAddressRange(resolve_scope, 0, false, addr_range)) - m_sym_ctx_valid = true; - } + m_sym_ctx_valid = temporary_pc.ResolveFunctionScope(m_sym_ctx, &addr_range); + UnwindLogMsg("Symbol is now %s", GetSymbolOrFunctionName(m_sym_ctx).AsCString("")); } @@ -563,6 +534,7 @@ void RegisterContextLLDB::InitializeNonZerothFrame() { active_row = m_fast_unwind_plan_sp->GetRowForFunctionOffset(m_current_offset); row_register_kind = m_fast_unwind_plan_sp->GetRegisterKind(); + PropagateTrapHandlerFlagFromUnwindPlan(m_fast_unwind_plan_sp); if (active_row.get() && log) { StreamString active_row_strm; active_row->Dump(active_row_strm, m_fast_unwind_plan_sp.get(), &m_thread, @@ -575,6 +547,7 @@ void RegisterContextLLDB::InitializeNonZerothFrame() { if (IsUnwindPlanValidForCurrentPC(m_full_unwind_plan_sp, valid_offset)) { active_row = m_full_unwind_plan_sp->GetRowForFunctionOffset(valid_offset); row_register_kind = m_full_unwind_plan_sp->GetRegisterKind(); + PropagateTrapHandlerFlagFromUnwindPlan(m_full_unwind_plan_sp); if (active_row.get() && log) { StreamString active_row_strm; active_row->Dump(active_row_strm, m_full_unwind_plan_sp.get(), @@ -812,6 +785,16 @@ UnwindPlanSP RegisterContextLLDB::GetFullUnwindPlanForFrame() { unwind_plan_sp.reset(); } + CallFrameInfo *object_file_unwind = + pc_module_sp->GetUnwindTable().GetObjectFileUnwindInfo(); + if (object_file_unwind) { + unwind_plan_sp = std::make_shared<UnwindPlan>(lldb::eRegisterKindGeneric); + if (object_file_unwind->GetUnwindPlan(m_current_pc, *unwind_plan_sp)) + return unwind_plan_sp; + else + unwind_plan_sp.reset(); + } + return arch_default_unwind_plan_sp; } @@ -824,6 +807,9 @@ UnwindPlanSP RegisterContextLLDB::GetFullUnwindPlanForFrame() { m_fast_unwind_plan_sp.reset(); unwind_plan_sp = func_unwinders_sp->GetEHFrameUnwindPlan(process->GetTarget()); + if (!unwind_plan_sp) + unwind_plan_sp = + func_unwinders_sp->GetObjectFileUnwindPlan(process->GetTarget()); if (unwind_plan_sp && unwind_plan_sp->PlanValidAtAddress(m_current_pc) && unwind_plan_sp->GetSourcedFromCompiler() == eLazyBoolYes) { return unwind_plan_sp; @@ -846,6 +832,9 @@ UnwindPlanSP RegisterContextLLDB::GetFullUnwindPlanForFrame() { // intend) or compact unwind (this won't work) unwind_plan_sp = func_unwinders_sp->GetEHFrameUnwindPlan(process->GetTarget()); + if (!unwind_plan_sp) + unwind_plan_sp = + func_unwinders_sp->GetObjectFileUnwindPlan(process->GetTarget()); if (unwind_plan_sp && unwind_plan_sp->PlanValidAtAddress(m_current_pc)) { UnwindLogMsgVerbose("frame uses %s for full UnwindPlan because the " "DynamicLoader suggested we prefer it", @@ -1512,8 +1501,7 @@ RegisterContextLLDB::SavedLocationForRegister( process->GetByteOrder(), process->GetAddressByteSize()); ModuleSP opcode_ctx; - DWARFExpression dwarfexpr(opcode_ctx, dwarfdata, nullptr, 0, - unwindplan_regloc.GetDWARFExpressionLength()); + DWARFExpression dwarfexpr(opcode_ctx, dwarfdata, nullptr); dwarfexpr.SetRegisterKind(unwindplan_registerkind); Value cfa_val = Scalar(m_cfa); cfa_val.SetValueType(Value::eValueTypeLoadAddress); @@ -1698,6 +1686,7 @@ bool RegisterContextLLDB::TryFallbackUnwindPlan() { // We've copied the fallback unwind plan into the full - now clear the // fallback. m_fallback_unwind_plan_sp.reset(); + PropagateTrapHandlerFlagFromUnwindPlan(m_full_unwind_plan_sp); } return true; @@ -1741,6 +1730,8 @@ bool RegisterContextLLDB::ForceSwitchToFallbackUnwindPlan() { m_cfa = new_cfa; + PropagateTrapHandlerFlagFromUnwindPlan(m_full_unwind_plan_sp); + UnwindLogMsg("switched unconditionally to the fallback unwindplan %s", m_full_unwind_plan_sp->GetSourceName().GetCString()); return true; @@ -1748,6 +1739,53 @@ bool RegisterContextLLDB::ForceSwitchToFallbackUnwindPlan() { return false; } +void RegisterContextLLDB::PropagateTrapHandlerFlagFromUnwindPlan( + lldb::UnwindPlanSP unwind_plan) { + if (unwind_plan->GetUnwindPlanForSignalTrap() != eLazyBoolYes) { + // Unwind plan does not indicate trap handler. Do nothing. We may + // already be flagged as trap handler flag due to the symbol being + // in the trap handler symbol list, and that should take precedence. + return; + } else if (m_frame_type != eNormalFrame) { + // If this is already a trap handler frame, nothing to do. + // If this is a skip or debug or invalid frame, don't override that. + return; + } + + m_frame_type = eTrapHandlerFrame; + + if (m_current_offset_backed_up_one != m_current_offset) { + // We backed up the pc by 1 to compute the symbol context, but + // now need to undo that because the pc of the trap handler + // frame may in fact be the first instruction of a signal return + // trampoline, rather than the instruction after a call. This + // happens on systems where the signal handler dispatch code, rather + // than calling the handler and being returned to, jumps to the + // handler after pushing the address of a return trampoline on the + // stack -- on these systems, when the handler returns, control will + // be transferred to the return trampoline, so that's the best + // symbol we can present in the callstack. + UnwindLogMsg("Resetting current offset and re-doing symbol lookup; " + "old symbol was %s", + GetSymbolOrFunctionName(m_sym_ctx).AsCString("")); + m_current_offset_backed_up_one = m_current_offset; + + AddressRange addr_range; + m_sym_ctx_valid = m_current_pc.ResolveFunctionScope(m_sym_ctx, &addr_range); + + UnwindLogMsg("Symbol is now %s", + GetSymbolOrFunctionName(m_sym_ctx).AsCString("")); + + ExecutionContext exe_ctx(m_thread.shared_from_this()); + Process *process = exe_ctx.GetProcessPtr(); + Target *target = &process->GetTarget(); + + m_start_pc = addr_range.GetBaseAddress(); + m_current_offset = + m_current_pc.GetLoadAddress(target) - m_start_pc.GetLoadAddress(target); + } +} + bool RegisterContextLLDB::ReadFrameAddress( lldb::RegisterKind row_register_kind, UnwindPlan::Row::FAValue &fa, addr_t &address) { @@ -1816,8 +1854,7 @@ bool RegisterContextLLDB::ReadFrameAddress( process->GetByteOrder(), process->GetAddressByteSize()); ModuleSP opcode_ctx; - DWARFExpression dwarfexpr(opcode_ctx, dwarfdata, nullptr, 0, - fa.GetDWARFExpressionLength()); + DWARFExpression dwarfexpr(opcode_ctx, dwarfdata, nullptr); dwarfexpr.SetRegisterKind(row_register_kind); Value result; Status error; @@ -1833,12 +1870,66 @@ bool RegisterContextLLDB::ReadFrameAddress( error.AsCString()); break; } + case UnwindPlan::Row::FAValue::isRaSearch: { + Process &process = *m_thread.GetProcess(); + lldb::addr_t return_address_hint = GetReturnAddressHint(fa.GetOffset()); + if (return_address_hint == LLDB_INVALID_ADDRESS) + return false; + const unsigned max_iterations = 256; + for (unsigned i = 0; i < max_iterations; ++i) { + Status st; + lldb::addr_t candidate_addr = + return_address_hint + i * process.GetAddressByteSize(); + lldb::addr_t candidate = + process.ReadPointerFromMemory(candidate_addr, st); + if (st.Fail()) { + UnwindLogMsg("Cannot read memory at 0x%" PRIx64 ": %s", candidate_addr, + st.AsCString()); + return false; + } + Address addr; + uint32_t permissions; + if (process.GetLoadAddressPermissions(candidate, permissions) && + permissions & lldb::ePermissionsExecutable) { + address = candidate_addr; + UnwindLogMsg("Heuristically found CFA: 0x%" PRIx64, address); + return true; + } + } + UnwindLogMsg("No suitable CFA found"); + break; + } default: return false; } return false; } +lldb::addr_t RegisterContextLLDB::GetReturnAddressHint(int32_t plan_offset) { + addr_t hint; + if (!ReadGPRValue(eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP, hint)) + return LLDB_INVALID_ADDRESS; + if (!m_sym_ctx.module_sp || !m_sym_ctx.symbol) + return LLDB_INVALID_ADDRESS; + + hint += plan_offset; + + if (auto next = GetNextFrame()) { + if (!next->m_sym_ctx.module_sp || !next->m_sym_ctx.symbol) + return LLDB_INVALID_ADDRESS; + if (auto expected_size = + next->m_sym_ctx.module_sp->GetSymbolFile()->GetParameterStackSize( + *next->m_sym_ctx.symbol)) + hint += *expected_size; + else { + UnwindLogMsgVerbose("Could not retrieve parameter size: %s", + llvm::toString(expected_size.takeError()).c_str()); + return LLDB_INVALID_ADDRESS; + } + } + return hint; +} + // Retrieve a general purpose register value for THIS frame, as saved by the // NEXT frame, i.e. the frame that // this frame called. e.g. @@ -2077,8 +2168,9 @@ void RegisterContextLLDB::UnwindLogMsg(const char *fmt, ...) { } va_end(args); - log->Printf("%*sth%d/fr%u %s", m_frame_number < 100 ? m_frame_number : 100, - "", m_thread.GetIndexID(), m_frame_number, logmsg); + LLDB_LOGF(log, "%*sth%d/fr%u %s", + m_frame_number < 100 ? m_frame_number : 100, "", + m_thread.GetIndexID(), m_frame_number, logmsg); free(logmsg); } } @@ -2098,8 +2190,9 @@ void RegisterContextLLDB::UnwindLogMsgVerbose(const char *fmt, ...) { } va_end(args); - log->Printf("%*sth%d/fr%u %s", m_frame_number < 100 ? m_frame_number : 100, - "", m_thread.GetIndexID(), m_frame_number, logmsg); + LLDB_LOGF(log, "%*sth%d/fr%u %s", + m_frame_number < 100 ? m_frame_number : 100, "", + m_thread.GetIndexID(), m_frame_number, logmsg); free(logmsg); } } diff --git a/source/Plugins/Process/Utility/RegisterContextLLDB.h b/source/Plugins/Process/Utility/RegisterContextLLDB.h index 64dd394d233b..114ac35591e7 100644 --- a/source/Plugins/Process/Utility/RegisterContextLLDB.h +++ b/source/Plugins/Process/Utility/RegisterContextLLDB.h @@ -120,6 +120,10 @@ private: bool IsTrapHandlerSymbol(lldb_private::Process *process, const lldb_private::SymbolContext &m_sym_ctx) const; + /// Check if the given unwind plan indicates a signal trap handler, and + /// update frame type and symbol context if so. + void PropagateTrapHandlerFlagFromUnwindPlan(lldb::UnwindPlanSP unwind_plan); + // Provide a location for where THIS function saved the CALLER's register // value // Or a frame "below" this one saved it, i.e. a function called by this one, @@ -197,6 +201,8 @@ private: bool IsUnwindPlanValidForCurrentPC(lldb::UnwindPlanSP unwind_plan_sp, int &valid_pc_offset); + lldb::addr_t GetReturnAddressHint(int32_t plan_offset); + lldb_private::Thread &m_thread; /// diff --git a/source/Plugins/Process/Utility/RegisterContextPOSIX_arm64.cpp b/source/Plugins/Process/Utility/RegisterContextPOSIX_arm64.cpp index 99b897d441b5..db1aa1b8b093 100644 --- a/source/Plugins/Process/Utility/RegisterContextPOSIX_arm64.cpp +++ b/source/Plugins/Process/Utility/RegisterContextPOSIX_arm64.cpp @@ -109,6 +109,7 @@ RegisterContextPOSIX_arm64::RegisterContextPOSIX_arm64( switch (register_info->m_target_arch.GetMachine()) { case llvm::Triple::aarch64: + case llvm::Triple::aarch64_32: m_reg_info.num_registers = k_num_registers_arm64; m_reg_info.num_gpr_registers = k_num_gpr_registers_arm64; m_reg_info.num_fpr_registers = k_num_fpr_registers_arm64; @@ -184,6 +185,7 @@ RegisterContextPOSIX_arm64::GetRegisterSet(size_t set) { if (IsRegisterSetAvailable(set)) { switch (m_register_info_up->m_target_arch.GetMachine()) { case llvm::Triple::aarch64: + case llvm::Triple::aarch64_32: return &g_reg_sets_arm64[set]; default: assert(false && "Unhandled target architecture."); diff --git a/source/Plugins/Process/Utility/RegisterContextWindows_i386.cpp b/source/Plugins/Process/Utility/RegisterContextWindows_i386.cpp new file mode 100644 index 000000000000..916d3233cde5 --- /dev/null +++ b/source/Plugins/Process/Utility/RegisterContextWindows_i386.cpp @@ -0,0 +1,89 @@ +//===-- RegisterContextWindows_i386.cpp -------------------------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#include "RegisterContextWindows_i386.h" +#include "RegisterContext_x86.h" +#include "lldb-x86-register-enums.h" + +using namespace lldb_private; +using namespace lldb; + +namespace { +// Declare our g_register_infos structure. +typedef struct _GPR { + uint32_t eax; + uint32_t ebx; + uint32_t ecx; + uint32_t edx; + uint32_t edi; + uint32_t esi; + uint32_t ebp; + uint32_t esp; + uint32_t eip; + uint32_t eflags; + uint32_t cs; + uint32_t fs; + uint32_t gs; + uint32_t ss; + uint32_t ds; + uint32_t es; +} GPR; + +#define GPR_OFFSET(regname) (LLVM_EXTENSION offsetof(GPR, regname)) + +#define DEFINE_GPR(reg, alt, kind1, kind2, kind3, kind4) \ + { \ +#reg, alt, sizeof(((GPR *)nullptr)->reg), GPR_OFFSET(reg), eEncodingUint, \ + eFormatHex, \ + {kind1, kind2, kind3, kind4, lldb_##reg##_i386 }, nullptr, nullptr, \ + nullptr, 0 \ + } + +// clang-format off +static RegisterInfo g_register_infos_i386[] = { +// General purpose registers EH_Frame DWARF Generic Process Plugin +// =========================== ================== ================ ========================= ==================== + DEFINE_GPR(eax, nullptr, ehframe_eax_i386, dwarf_eax_i386, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), + DEFINE_GPR(ebx, nullptr, ehframe_ebx_i386, dwarf_ebx_i386, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), + DEFINE_GPR(ecx, nullptr, ehframe_ecx_i386, dwarf_ecx_i386, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), + DEFINE_GPR(edx, nullptr, ehframe_edx_i386, dwarf_edx_i386, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), + DEFINE_GPR(edi, nullptr, ehframe_edi_i386, dwarf_edi_i386, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), + DEFINE_GPR(esi, nullptr, ehframe_esi_i386, dwarf_esi_i386, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), + DEFINE_GPR(ebp, "fp", ehframe_ebp_i386, dwarf_ebp_i386, LLDB_REGNUM_GENERIC_FP, LLDB_INVALID_REGNUM), + DEFINE_GPR(esp, "sp", ehframe_esp_i386, dwarf_esp_i386, LLDB_REGNUM_GENERIC_SP, LLDB_INVALID_REGNUM), + DEFINE_GPR(eip, "pc", ehframe_eip_i386, dwarf_eip_i386, LLDB_REGNUM_GENERIC_PC, LLDB_INVALID_REGNUM), + DEFINE_GPR(eflags, "flags", ehframe_eflags_i386, dwarf_eflags_i386, LLDB_REGNUM_GENERIC_FLAGS, LLDB_INVALID_REGNUM), + DEFINE_GPR(cs, nullptr, LLDB_INVALID_REGNUM, dwarf_cs_i386, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), + DEFINE_GPR(fs, nullptr, LLDB_INVALID_REGNUM, dwarf_fs_i386, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), + DEFINE_GPR(gs, nullptr, LLDB_INVALID_REGNUM, dwarf_gs_i386, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), + DEFINE_GPR(ss, nullptr, LLDB_INVALID_REGNUM, dwarf_ss_i386, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), + DEFINE_GPR(ds, nullptr, LLDB_INVALID_REGNUM, dwarf_ds_i386, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), + DEFINE_GPR(es, nullptr, LLDB_INVALID_REGNUM, dwarf_es_i386, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), +}; +// clang-format on +} // namespace + +RegisterContextWindows_i386::RegisterContextWindows_i386( + const ArchSpec &target_arch) + : lldb_private::RegisterInfoInterface(target_arch) { + assert(target_arch.GetMachine() == llvm::Triple::x86); +} + +const RegisterInfo *RegisterContextWindows_i386::GetRegisterInfo() const { + return g_register_infos_i386; +} + +uint32_t RegisterContextWindows_i386::GetRegisterCount() const { + return llvm::array_lengthof(g_register_infos_i386); +} + +uint32_t RegisterContextWindows_i386::GetUserRegisterCount() const { + return llvm::array_lengthof(g_register_infos_i386); +} + +size_t RegisterContextWindows_i386::GetGPRSize() const { return sizeof(GPR); } diff --git a/source/Plugins/Process/Utility/RegisterContextWindows_i386.h b/source/Plugins/Process/Utility/RegisterContextWindows_i386.h new file mode 100644 index 000000000000..7779cc357526 --- /dev/null +++ b/source/Plugins/Process/Utility/RegisterContextWindows_i386.h @@ -0,0 +1,27 @@ +//===-- RegisterContextWindows_i386.h ---------------------------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef liblldb_RegisterContextWindows_i386_H_ +#define liblldb_RegisterContextWindows_i386_H_ + +#include "RegisterInfoInterface.h" + +class RegisterContextWindows_i386 : public lldb_private::RegisterInfoInterface { +public: + RegisterContextWindows_i386(const lldb_private::ArchSpec &target_arch); + + size_t GetGPRSize() const override; + + const lldb_private::RegisterInfo *GetRegisterInfo() const override; + + uint32_t GetRegisterCount() const override; + + uint32_t GetUserRegisterCount() const override; +}; + +#endif diff --git a/source/Plugins/Process/Utility/RegisterContextWindows_x86_64.cpp b/source/Plugins/Process/Utility/RegisterContextWindows_x86_64.cpp new file mode 100644 index 000000000000..e90584de1a44 --- /dev/null +++ b/source/Plugins/Process/Utility/RegisterContextWindows_x86_64.cpp @@ -0,0 +1,152 @@ +//===-- RegisterContextWindows_x86_64.cpp -----------------------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#include "RegisterContextWindows_x86_64.h" +#include "RegisterContext_x86.h" +#include "lldb-x86-register-enums.h" + +#include <vector> + +using namespace lldb_private; +using namespace lldb; + +namespace { +typedef struct _GPR { + uint64_t rax; + uint64_t rcx; + uint64_t rdx; + uint64_t rbx; + uint64_t rsp; + uint64_t rbp; + uint64_t rsi; + uint64_t rdi; + uint64_t r8; + uint64_t r9; + uint64_t r10; + uint64_t r11; + uint64_t r12; + uint64_t r13; + uint64_t r14; + uint64_t r15; + uint64_t rip; + uint64_t rflags; + uint16_t cs; + uint16_t fs; + uint16_t gs; + uint16_t ss; + uint16_t ds; + uint16_t es; +} GPR; + +#define GPR_OFFSET(regname) (LLVM_EXTENSION offsetof(GPR, regname)) +#define DEFINE_GPR(reg, alt, kind1, kind2, kind3, kind4) \ + { \ +#reg, alt, sizeof(((GPR *)nullptr)->reg), GPR_OFFSET(reg), eEncodingUint, \ + eFormatHex, \ + {kind1, kind2, kind3, kind4, lldb_##reg##_x86_64 }, nullptr, nullptr, \ + nullptr, 0 \ + } + +typedef struct _FPReg { + XMMReg xmm0; + XMMReg xmm1; + XMMReg xmm2; + XMMReg xmm3; + XMMReg xmm4; + XMMReg xmm5; + XMMReg xmm6; + XMMReg xmm7; + XMMReg xmm8; + XMMReg xmm9; + XMMReg xmm10; + XMMReg xmm11; + XMMReg xmm12; + XMMReg xmm13; + XMMReg xmm14; + XMMReg xmm15; +} FPReg; + +#define FPR_OFFSET(regname) \ + (sizeof(GPR) + LLVM_EXTENSION offsetof(FPReg, regname)) + +#define DEFINE_XMM(reg) \ + { \ +#reg, NULL, sizeof(((FPReg *)nullptr)->reg), FPR_OFFSET(reg), \ + eEncodingUint, eFormatVectorOfUInt64, \ + {dwarf_##reg##_x86_64, dwarf_##reg##_x86_64, LLDB_INVALID_REGNUM, \ + LLDB_INVALID_REGNUM, lldb_##reg##_x86_64 }, \ + nullptr, nullptr, nullptr, 0 \ + } + +// clang-format off +static RegisterInfo g_register_infos_x86_64[] = { +// General purpose registers EH_Frame DWARF Generic Process Plugin +// =========================== ================== ================ ========================= ==================== + DEFINE_GPR(rax, nullptr, dwarf_rax_x86_64, dwarf_rax_x86_64, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), + DEFINE_GPR(rbx, nullptr, dwarf_rbx_x86_64, dwarf_rbx_x86_64, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), + DEFINE_GPR(rcx, "arg4", dwarf_rcx_x86_64, dwarf_rcx_x86_64, LLDB_REGNUM_GENERIC_ARG4, LLDB_INVALID_REGNUM), + DEFINE_GPR(rdx, "arg3", dwarf_rdx_x86_64, dwarf_rdx_x86_64, LLDB_REGNUM_GENERIC_ARG3, LLDB_INVALID_REGNUM), + DEFINE_GPR(rdi, "arg1", dwarf_rdi_x86_64, dwarf_rdi_x86_64, LLDB_REGNUM_GENERIC_ARG1, LLDB_INVALID_REGNUM), + DEFINE_GPR(rsi, "arg2", dwarf_rsi_x86_64, dwarf_rsi_x86_64, LLDB_REGNUM_GENERIC_ARG2, LLDB_INVALID_REGNUM), + DEFINE_GPR(rbp, "fp", dwarf_rbp_x86_64, dwarf_rbp_x86_64, LLDB_REGNUM_GENERIC_FP, LLDB_INVALID_REGNUM), + DEFINE_GPR(rsp, "sp", dwarf_rsp_x86_64, dwarf_rsp_x86_64, LLDB_REGNUM_GENERIC_SP, LLDB_INVALID_REGNUM), + DEFINE_GPR(r8, "arg5", dwarf_r8_x86_64, dwarf_r8_x86_64, LLDB_REGNUM_GENERIC_ARG5, LLDB_INVALID_REGNUM), + DEFINE_GPR(r9, "arg6", dwarf_r9_x86_64, dwarf_r9_x86_64, LLDB_REGNUM_GENERIC_ARG6, LLDB_INVALID_REGNUM), + DEFINE_GPR(r10, nullptr, dwarf_r10_x86_64, dwarf_r10_x86_64, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), + DEFINE_GPR(r11, nullptr, dwarf_r11_x86_64, dwarf_r11_x86_64, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), + DEFINE_GPR(r12, nullptr, dwarf_r12_x86_64, dwarf_r12_x86_64, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), + DEFINE_GPR(r13, nullptr, dwarf_r13_x86_64, dwarf_r13_x86_64, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), + DEFINE_GPR(r14, nullptr, dwarf_r14_x86_64, dwarf_r14_x86_64, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), + DEFINE_GPR(r15, nullptr, dwarf_r15_x86_64, dwarf_r15_x86_64, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), + DEFINE_GPR(rip, "pc", dwarf_rip_x86_64, dwarf_rip_x86_64, LLDB_REGNUM_GENERIC_PC, LLDB_INVALID_REGNUM), + DEFINE_GPR(rflags, "flags", dwarf_rflags_x86_64, dwarf_rflags_x86_64, LLDB_REGNUM_GENERIC_FLAGS, LLDB_INVALID_REGNUM), + DEFINE_GPR(cs, nullptr, dwarf_cs_x86_64, dwarf_cs_x86_64, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), + DEFINE_GPR(fs, nullptr, dwarf_fs_x86_64, dwarf_fs_x86_64, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), + DEFINE_GPR(gs, nullptr, dwarf_gs_x86_64, dwarf_gs_x86_64, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), + DEFINE_GPR(ss, nullptr, dwarf_ss_x86_64, dwarf_ss_x86_64, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), + DEFINE_GPR(ds, nullptr, dwarf_ds_x86_64, dwarf_ds_x86_64, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), + DEFINE_GPR(es, nullptr, dwarf_es_x86_64, dwarf_es_x86_64, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), + DEFINE_XMM(xmm0), + DEFINE_XMM(xmm1), + DEFINE_XMM(xmm2), + DEFINE_XMM(xmm3), + DEFINE_XMM(xmm4), + DEFINE_XMM(xmm5), + DEFINE_XMM(xmm6), + DEFINE_XMM(xmm7), + DEFINE_XMM(xmm8), + DEFINE_XMM(xmm9), + DEFINE_XMM(xmm10), + DEFINE_XMM(xmm11), + DEFINE_XMM(xmm12), + DEFINE_XMM(xmm13), + DEFINE_XMM(xmm14), + DEFINE_XMM(xmm15) +}; +// clang-format on +} // namespace + +RegisterContextWindows_x86_64::RegisterContextWindows_x86_64( + const ArchSpec &target_arch) + : lldb_private::RegisterInfoInterface(target_arch) { + assert(target_arch.GetMachine() == llvm::Triple::x86_64); +} + +const RegisterInfo *RegisterContextWindows_x86_64::GetRegisterInfo() const { + return g_register_infos_x86_64; +} + +uint32_t RegisterContextWindows_x86_64::GetRegisterCount() const { + return llvm::array_lengthof(g_register_infos_x86_64); +} + +uint32_t RegisterContextWindows_x86_64::GetUserRegisterCount() const { + return llvm::array_lengthof(g_register_infos_x86_64); +} + +size_t RegisterContextWindows_x86_64::GetGPRSize() const { return sizeof(GPR); } diff --git a/source/Plugins/Process/Utility/RegisterContextWindows_x86_64.h b/source/Plugins/Process/Utility/RegisterContextWindows_x86_64.h new file mode 100644 index 000000000000..18198b5b25b3 --- /dev/null +++ b/source/Plugins/Process/Utility/RegisterContextWindows_x86_64.h @@ -0,0 +1,28 @@ +//===-- RegisterContextWindows_x86_64.h --- ---------------------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef liblldb_RegisterContextWindows_x86_64_H_ +#define liblldb_RegisterContextWindows_x86_64_H_ + +#include "RegisterInfoInterface.h" + +class RegisterContextWindows_x86_64 + : public lldb_private::RegisterInfoInterface { +public: + RegisterContextWindows_x86_64(const lldb_private::ArchSpec &target_arch); + + size_t GetGPRSize() const override; + + const lldb_private::RegisterInfo *GetRegisterInfo() const override; + + uint32_t GetRegisterCount() const override; + + uint32_t GetUserRegisterCount() const override; +}; + +#endif diff --git a/source/Plugins/Process/Utility/RegisterInfoPOSIX_arm64.cpp b/source/Plugins/Process/Utility/RegisterInfoPOSIX_arm64.cpp index f7471526d054..8b367bdc6448 100644 --- a/source/Plugins/Process/Utility/RegisterInfoPOSIX_arm64.cpp +++ b/source/Plugins/Process/Utility/RegisterInfoPOSIX_arm64.cpp @@ -57,6 +57,7 @@ static const lldb_private::RegisterInfo * GetRegisterInfoPtr(const lldb_private::ArchSpec &target_arch) { switch (target_arch.GetMachine()) { case llvm::Triple::aarch64: + case llvm::Triple::aarch64_32: return g_register_infos_arm64_le; default: assert(false && "Unhandled target architecture."); @@ -68,6 +69,7 @@ static uint32_t GetRegisterInfoCount(const lldb_private::ArchSpec &target_arch) { switch (target_arch.GetMachine()) { case llvm::Triple::aarch64: + case llvm::Triple::aarch64_32: return static_cast<uint32_t>(sizeof(g_register_infos_arm64_le) / sizeof(g_register_infos_arm64_le[0])); default: diff --git a/source/Plugins/Process/Utility/RegisterInfos_arm64.h b/source/Plugins/Process/Utility/RegisterInfos_arm64.h index 4ee0b528f229..68c12aa6e529 100644 --- a/source/Plugins/Process/Utility/RegisterInfos_arm64.h +++ b/source/Plugins/Process/Utility/RegisterInfos_arm64.h @@ -456,188 +456,265 @@ static uint32_t g_d29_invalidates[] = {fpu_v29, fpu_s29, LLDB_INVALID_REGNUM}; static uint32_t g_d30_invalidates[] = {fpu_v30, fpu_s30, LLDB_INVALID_REGNUM}; static uint32_t g_d31_invalidates[] = {fpu_v31, fpu_s31, LLDB_INVALID_REGNUM}; +// Generates register kinds array for 64-bit general purpose registers +#define GPR64_KIND(reg, generic_kind) \ + { \ + arm64_ehframe::reg, arm64_dwarf::reg, generic_kind, LLDB_INVALID_REGNUM, \ + gpr_##reg \ + } + +// Generates register kinds array for registers with lldb kind +#define MISC_KIND(lldb_kind) \ + { \ + LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, \ + LLDB_INVALID_REGNUM, lldb_kind \ + } + +// Generates register kinds array for vector registers +#define VREG_KIND(reg) \ + { \ + LLDB_INVALID_REGNUM, arm64_dwarf::reg, LLDB_INVALID_REGNUM, \ + LLDB_INVALID_REGNUM, fpu_##reg \ + } + +// Generates register kinds array for cpsr +#define CPSR_KIND(lldb_kind) \ + { \ + arm64_ehframe::cpsr, arm64_dwarf::cpsr, LLDB_REGNUM_GENERIC_FLAGS, \ + LLDB_INVALID_REGNUM, lldb_kind \ + } + +#define MISC_GPR_KIND(lldb_kind) CPSR_KIND(lldb_kind) +#define MISC_FPU_KIND(lldb_kind) MISC_KIND(lldb_kind) +#define MISC_EXC_KIND(lldb_kind) MISC_KIND(lldb_kind) + +// Defines a 64-bit general purpose register +#define DEFINE_GPR64(reg, generic_kind) \ + { \ + #reg, nullptr, 8, GPR_OFFSET(gpr_##reg), lldb::eEncodingUint, \ + lldb::eFormatHex, GPR64_KIND(reg, generic_kind), nullptr, nullptr, \ + nullptr, 0 \ + } + +// Defines a 64-bit general purpose register +#define DEFINE_GPR64_ALT(reg, alt, generic_kind) \ + { \ + #reg, #alt, 8, GPR_OFFSET(gpr_##reg), lldb::eEncodingUint, \ + lldb::eFormatHex, GPR64_KIND(reg, generic_kind), nullptr, nullptr, \ + nullptr, 0 \ + } + +// Defines a 32-bit general purpose pseudo register +#define DEFINE_GPR32(wreg, xreg) \ + { \ + #wreg, nullptr, 4, \ + GPR_OFFSET(gpr_##xreg) + GPR_W_PSEUDO_REG_ENDIAN_OFFSET, \ + lldb::eEncodingUint, lldb::eFormatHex, MISC_KIND(gpr_##wreg), \ + g_contained_##xreg, g_##wreg##_invalidates, nullptr, 0 \ + } + +// Defines a vector register with 16-byte size +#define DEFINE_VREG(reg) \ + { \ + #reg, nullptr, 16, FPU_OFFSET(fpu_##reg - fpu_v0), lldb::eEncodingVector, \ + lldb::eFormatVectorOfUInt8, VREG_KIND(reg), nullptr, nullptr, nullptr, \ + 0 \ + } + +// Defines S and D pseudo registers mapping over correspondig vector register +#define DEFINE_FPU_PSEUDO(reg, size, offset, vreg) \ + { \ + #reg, nullptr, size, FPU_OFFSET(fpu_##vreg - fpu_v0) + offset, \ + lldb::eEncodingIEEE754, lldb::eFormatFloat, MISC_KIND(fpu_##reg), \ + g_contained_##vreg, g_##reg##_invalidates, nullptr, 0 \ + } + +// Defines miscellaneous status and control registers like cpsr, fpsr etc +#define DEFINE_MISC_REGS(reg, size, TYPE, lldb_kind) \ + { \ + #reg, nullptr, size, TYPE##_OFFSET_NAME(reg), lldb::eEncodingUint, \ + lldb::eFormatHex, MISC_##TYPE##_KIND(lldb_kind), nullptr, nullptr, \ + nullptr, 0 \ + } + static lldb_private::RegisterInfo g_register_infos_arm64_le[] = { - // clang-format off - // General purpose registers - // NAME ALT SZ OFFSET ENCODING FORMAT EH_FRAME DWARF GENERIC PROCESS PLUGIN LLDB VALUE REGS INVAL DYNEXPR SZ - // ===== ======= == ============= =================== ================ ================= =============== ======================== =================== ====== ============== ======= ======= == - {"x0", nullptr, 8, GPR_OFFSET(0), lldb::eEncodingUint, lldb::eFormatHex, {arm64_ehframe::x0, arm64_dwarf::x0, LLDB_REGNUM_GENERIC_ARG1, LLDB_INVALID_REGNUM, gpr_x0}, nullptr, nullptr, nullptr, 0}, - {"x1", nullptr, 8, GPR_OFFSET(1), lldb::eEncodingUint, lldb::eFormatHex, {arm64_ehframe::x1, arm64_dwarf::x1, LLDB_REGNUM_GENERIC_ARG2, LLDB_INVALID_REGNUM, gpr_x1}, nullptr, nullptr, nullptr, 0}, - {"x2", nullptr, 8, GPR_OFFSET(2), lldb::eEncodingUint, lldb::eFormatHex, {arm64_ehframe::x2, arm64_dwarf::x2, LLDB_REGNUM_GENERIC_ARG3, LLDB_INVALID_REGNUM, gpr_x2}, nullptr, nullptr, nullptr, 0}, - {"x3", nullptr, 8, GPR_OFFSET(3), lldb::eEncodingUint, lldb::eFormatHex, {arm64_ehframe::x3, arm64_dwarf::x3, LLDB_REGNUM_GENERIC_ARG4, LLDB_INVALID_REGNUM, gpr_x3}, nullptr, nullptr, nullptr, 0}, - {"x4", nullptr, 8, GPR_OFFSET(4), lldb::eEncodingUint, lldb::eFormatHex, {arm64_ehframe::x4, arm64_dwarf::x4, LLDB_REGNUM_GENERIC_ARG5, LLDB_INVALID_REGNUM, gpr_x4}, nullptr, nullptr, nullptr, 0}, - {"x5", nullptr, 8, GPR_OFFSET(5), lldb::eEncodingUint, lldb::eFormatHex, {arm64_ehframe::x5, arm64_dwarf::x5, LLDB_REGNUM_GENERIC_ARG6, LLDB_INVALID_REGNUM, gpr_x5}, nullptr, nullptr, nullptr, 0}, - {"x6", nullptr, 8, GPR_OFFSET(6), lldb::eEncodingUint, lldb::eFormatHex, {arm64_ehframe::x6, arm64_dwarf::x6, LLDB_REGNUM_GENERIC_ARG7, LLDB_INVALID_REGNUM, gpr_x6}, nullptr, nullptr, nullptr, 0}, - {"x7", nullptr, 8, GPR_OFFSET(7), lldb::eEncodingUint, lldb::eFormatHex, {arm64_ehframe::x7, arm64_dwarf::x7, LLDB_REGNUM_GENERIC_ARG8, LLDB_INVALID_REGNUM, gpr_x7}, nullptr, nullptr, nullptr, 0}, - {"x8", nullptr, 8, GPR_OFFSET(8), lldb::eEncodingUint, lldb::eFormatHex, {arm64_ehframe::x8, arm64_dwarf::x8, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gpr_x8}, nullptr, nullptr, nullptr, 0}, - {"x9", nullptr, 8, GPR_OFFSET(9), lldb::eEncodingUint, lldb::eFormatHex, {arm64_ehframe::x9, arm64_dwarf::x9, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gpr_x9}, nullptr, nullptr, nullptr, 0}, - {"x10", nullptr, 8, GPR_OFFSET(10), lldb::eEncodingUint, lldb::eFormatHex, {arm64_ehframe::x10, arm64_dwarf::x10, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gpr_x10}, nullptr, nullptr, nullptr, 0}, - {"x11", nullptr, 8, GPR_OFFSET(11), lldb::eEncodingUint, lldb::eFormatHex, {arm64_ehframe::x11, arm64_dwarf::x11, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gpr_x11}, nullptr, nullptr, nullptr, 0}, - {"x12", nullptr, 8, GPR_OFFSET(12), lldb::eEncodingUint, lldb::eFormatHex, {arm64_ehframe::x12, arm64_dwarf::x12, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gpr_x12}, nullptr, nullptr, nullptr, 0}, - {"x13", nullptr, 8, GPR_OFFSET(13), lldb::eEncodingUint, lldb::eFormatHex, {arm64_ehframe::x13, arm64_dwarf::x13, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gpr_x13}, nullptr, nullptr, nullptr, 0}, - {"x14", nullptr, 8, GPR_OFFSET(14), lldb::eEncodingUint, lldb::eFormatHex, {arm64_ehframe::x14, arm64_dwarf::x14, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gpr_x14}, nullptr, nullptr, nullptr, 0}, - {"x15", nullptr, 8, GPR_OFFSET(15), lldb::eEncodingUint, lldb::eFormatHex, {arm64_ehframe::x15, arm64_dwarf::x15, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gpr_x15}, nullptr, nullptr, nullptr, 0}, - {"x16", nullptr, 8, GPR_OFFSET(16), lldb::eEncodingUint, lldb::eFormatHex, {arm64_ehframe::x16, arm64_dwarf::x16, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gpr_x16}, nullptr, nullptr, nullptr, 0}, - {"x17", nullptr, 8, GPR_OFFSET(17), lldb::eEncodingUint, lldb::eFormatHex, {arm64_ehframe::x17, arm64_dwarf::x17, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gpr_x17}, nullptr, nullptr, nullptr, 0}, - {"x18", nullptr, 8, GPR_OFFSET(18), lldb::eEncodingUint, lldb::eFormatHex, {arm64_ehframe::x18, arm64_dwarf::x18, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gpr_x18}, nullptr, nullptr, nullptr, 0}, - {"x19", nullptr, 8, GPR_OFFSET(19), lldb::eEncodingUint, lldb::eFormatHex, {arm64_ehframe::x19, arm64_dwarf::x19, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gpr_x19}, nullptr, nullptr, nullptr, 0}, - {"x20", nullptr, 8, GPR_OFFSET(20), lldb::eEncodingUint, lldb::eFormatHex, {arm64_ehframe::x20, arm64_dwarf::x20, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gpr_x20}, nullptr, nullptr, nullptr, 0}, - {"x21", nullptr, 8, GPR_OFFSET(21), lldb::eEncodingUint, lldb::eFormatHex, {arm64_ehframe::x21, arm64_dwarf::x21, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gpr_x21}, nullptr, nullptr, nullptr, 0}, - {"x22", nullptr, 8, GPR_OFFSET(22), lldb::eEncodingUint, lldb::eFormatHex, {arm64_ehframe::x22, arm64_dwarf::x22, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gpr_x22}, nullptr, nullptr, nullptr, 0}, - {"x23", nullptr, 8, GPR_OFFSET(23), lldb::eEncodingUint, lldb::eFormatHex, {arm64_ehframe::x23, arm64_dwarf::x23, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gpr_x23}, nullptr, nullptr, nullptr, 0}, - {"x24", nullptr, 8, GPR_OFFSET(24), lldb::eEncodingUint, lldb::eFormatHex, {arm64_ehframe::x24, arm64_dwarf::x24, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gpr_x24}, nullptr, nullptr, nullptr, 0}, - {"x25", nullptr, 8, GPR_OFFSET(25), lldb::eEncodingUint, lldb::eFormatHex, {arm64_ehframe::x25, arm64_dwarf::x25, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gpr_x25}, nullptr, nullptr, nullptr, 0}, - {"x26", nullptr, 8, GPR_OFFSET(26), lldb::eEncodingUint, lldb::eFormatHex, {arm64_ehframe::x26, arm64_dwarf::x26, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gpr_x26}, nullptr, nullptr, nullptr, 0}, - {"x27", nullptr, 8, GPR_OFFSET(27), lldb::eEncodingUint, lldb::eFormatHex, {arm64_ehframe::x27, arm64_dwarf::x27, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gpr_x27}, nullptr, nullptr, nullptr, 0}, - {"x28", nullptr, 8, GPR_OFFSET(28), lldb::eEncodingUint, lldb::eFormatHex, {arm64_ehframe::x28, arm64_dwarf::x28, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gpr_x28}, nullptr, nullptr, nullptr, 0}, - {"fp", "x29", 8, GPR_OFFSET(29), lldb::eEncodingUint, lldb::eFormatHex, {arm64_ehframe::fp, arm64_dwarf::fp, LLDB_REGNUM_GENERIC_FP, LLDB_INVALID_REGNUM, gpr_fp}, nullptr, nullptr, nullptr, 0}, - {"lr", "x30", 8, GPR_OFFSET(30), lldb::eEncodingUint, lldb::eFormatHex, {arm64_ehframe::lr, arm64_dwarf::lr, LLDB_REGNUM_GENERIC_RA, LLDB_INVALID_REGNUM, gpr_lr}, nullptr, nullptr, nullptr, 0}, - {"sp", "x31", 8, GPR_OFFSET(31), lldb::eEncodingUint, lldb::eFormatHex, {arm64_ehframe::sp, arm64_dwarf::sp, LLDB_REGNUM_GENERIC_SP, LLDB_INVALID_REGNUM, gpr_sp}, nullptr, nullptr, nullptr, 0}, - {"pc", nullptr, 8, GPR_OFFSET(32), lldb::eEncodingUint, lldb::eFormatHex, {arm64_ehframe::pc, arm64_dwarf::pc, LLDB_REGNUM_GENERIC_PC, LLDB_INVALID_REGNUM, gpr_pc}, nullptr, nullptr, nullptr, 0}, - - {"cpsr",nullptr, 4, GPR_OFFSET_NAME(cpsr), lldb::eEncodingUint, lldb::eFormatHex, {arm64_ehframe::cpsr, arm64_dwarf::cpsr, LLDB_REGNUM_GENERIC_FLAGS, LLDB_INVALID_REGNUM, gpr_cpsr}, nullptr, nullptr, nullptr, 0}, - - // NAME ALT SZ OFFSET ENCODING FORMAT EH_FRAME DWARF GENERIC PROCESS PLUGIN LLDB VALUE INVALIDATES DYNEXPR SZ - // ===== ======= == ============================================== =================== ================ ================= =============== =================== =================== ====== =============== ================= ======= == - {"w0", nullptr, 4, GPR_OFFSET(0) + GPR_W_PSEUDO_REG_ENDIAN_OFFSET, lldb::eEncodingUint, lldb::eFormatHex, {LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gpr_w0}, g_contained_x0, g_w0_invalidates, nullptr, 0}, - {"w1", nullptr, 4, GPR_OFFSET(1) + GPR_W_PSEUDO_REG_ENDIAN_OFFSET, lldb::eEncodingUint, lldb::eFormatHex, {LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gpr_w1}, g_contained_x1, g_w1_invalidates, nullptr, 0}, - {"w2", nullptr, 4, GPR_OFFSET(2) + GPR_W_PSEUDO_REG_ENDIAN_OFFSET, lldb::eEncodingUint, lldb::eFormatHex, {LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gpr_w2}, g_contained_x2, g_w2_invalidates, nullptr, 0}, - {"w3", nullptr, 4, GPR_OFFSET(3) + GPR_W_PSEUDO_REG_ENDIAN_OFFSET, lldb::eEncodingUint, lldb::eFormatHex, {LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gpr_w3}, g_contained_x3, g_w3_invalidates, nullptr, 0}, - {"w4", nullptr, 4, GPR_OFFSET(4) + GPR_W_PSEUDO_REG_ENDIAN_OFFSET, lldb::eEncodingUint, lldb::eFormatHex, {LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gpr_w4}, g_contained_x4, g_w4_invalidates, nullptr, 0}, - {"w5", nullptr, 4, GPR_OFFSET(5) + GPR_W_PSEUDO_REG_ENDIAN_OFFSET, lldb::eEncodingUint, lldb::eFormatHex, {LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gpr_w5}, g_contained_x5, g_w5_invalidates, nullptr, 0}, - {"w6", nullptr, 4, GPR_OFFSET(6) + GPR_W_PSEUDO_REG_ENDIAN_OFFSET, lldb::eEncodingUint, lldb::eFormatHex, {LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gpr_w6}, g_contained_x6, g_w6_invalidates, nullptr, 0}, - {"w7", nullptr, 4, GPR_OFFSET(7) + GPR_W_PSEUDO_REG_ENDIAN_OFFSET, lldb::eEncodingUint, lldb::eFormatHex, {LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gpr_w7}, g_contained_x7, g_w7_invalidates, nullptr, 0}, - {"w8", nullptr, 4, GPR_OFFSET(8) + GPR_W_PSEUDO_REG_ENDIAN_OFFSET, lldb::eEncodingUint, lldb::eFormatHex, {LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gpr_w8}, g_contained_x8, g_w8_invalidates, nullptr, 0}, - {"w9", nullptr, 4, GPR_OFFSET(9) + GPR_W_PSEUDO_REG_ENDIAN_OFFSET, lldb::eEncodingUint, lldb::eFormatHex, {LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gpr_w9}, g_contained_x9, g_w9_invalidates, nullptr, 0}, - {"w10", nullptr, 4, GPR_OFFSET(10) + GPR_W_PSEUDO_REG_ENDIAN_OFFSET, lldb::eEncodingUint, lldb::eFormatHex, {LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gpr_w10}, g_contained_x10, g_w10_invalidates, nullptr, 0}, - {"w11", nullptr, 4, GPR_OFFSET(11) + GPR_W_PSEUDO_REG_ENDIAN_OFFSET, lldb::eEncodingUint, lldb::eFormatHex, {LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gpr_w11}, g_contained_x11, g_w11_invalidates, nullptr, 0}, - {"w12", nullptr, 4, GPR_OFFSET(12) + GPR_W_PSEUDO_REG_ENDIAN_OFFSET, lldb::eEncodingUint, lldb::eFormatHex, {LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gpr_w12}, g_contained_x12, g_w12_invalidates, nullptr, 0}, - {"w13", nullptr, 4, GPR_OFFSET(13) + GPR_W_PSEUDO_REG_ENDIAN_OFFSET, lldb::eEncodingUint, lldb::eFormatHex, {LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gpr_w13}, g_contained_x13, g_w13_invalidates, nullptr, 0}, - {"w14", nullptr, 4, GPR_OFFSET(14) + GPR_W_PSEUDO_REG_ENDIAN_OFFSET, lldb::eEncodingUint, lldb::eFormatHex, {LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gpr_w14}, g_contained_x14, g_w14_invalidates, nullptr, 0}, - {"w15", nullptr, 4, GPR_OFFSET(15) + GPR_W_PSEUDO_REG_ENDIAN_OFFSET, lldb::eEncodingUint, lldb::eFormatHex, {LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gpr_w15}, g_contained_x15, g_w15_invalidates, nullptr, 0}, - {"w16", nullptr, 4, GPR_OFFSET(16) + GPR_W_PSEUDO_REG_ENDIAN_OFFSET, lldb::eEncodingUint, lldb::eFormatHex, {LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gpr_w16}, g_contained_x16, g_w16_invalidates, nullptr, 0}, - {"w17", nullptr, 4, GPR_OFFSET(17) + GPR_W_PSEUDO_REG_ENDIAN_OFFSET, lldb::eEncodingUint, lldb::eFormatHex, {LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gpr_w17}, g_contained_x17, g_w17_invalidates, nullptr, 0}, - {"w18", nullptr, 4, GPR_OFFSET(18) + GPR_W_PSEUDO_REG_ENDIAN_OFFSET, lldb::eEncodingUint, lldb::eFormatHex, {LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gpr_w18}, g_contained_x18, g_w18_invalidates, nullptr, 0}, - {"w19", nullptr, 4, GPR_OFFSET(19) + GPR_W_PSEUDO_REG_ENDIAN_OFFSET, lldb::eEncodingUint, lldb::eFormatHex, {LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gpr_w19}, g_contained_x19, g_w19_invalidates, nullptr, 0}, - {"w20", nullptr, 4, GPR_OFFSET(20) + GPR_W_PSEUDO_REG_ENDIAN_OFFSET, lldb::eEncodingUint, lldb::eFormatHex, {LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gpr_w20}, g_contained_x20, g_w20_invalidates, nullptr, 0}, - {"w21", nullptr, 4, GPR_OFFSET(21) + GPR_W_PSEUDO_REG_ENDIAN_OFFSET, lldb::eEncodingUint, lldb::eFormatHex, {LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gpr_w21}, g_contained_x21, g_w21_invalidates, nullptr, 0}, - {"w22", nullptr, 4, GPR_OFFSET(22) + GPR_W_PSEUDO_REG_ENDIAN_OFFSET, lldb::eEncodingUint, lldb::eFormatHex, {LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gpr_w22}, g_contained_x22, g_w22_invalidates, nullptr, 0}, - {"w23", nullptr, 4, GPR_OFFSET(23) + GPR_W_PSEUDO_REG_ENDIAN_OFFSET, lldb::eEncodingUint, lldb::eFormatHex, {LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gpr_w23}, g_contained_x23, g_w23_invalidates, nullptr, 0}, - {"w24", nullptr, 4, GPR_OFFSET(24) + GPR_W_PSEUDO_REG_ENDIAN_OFFSET, lldb::eEncodingUint, lldb::eFormatHex, {LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gpr_w24}, g_contained_x24, g_w24_invalidates, nullptr, 0}, - {"w25", nullptr, 4, GPR_OFFSET(25) + GPR_W_PSEUDO_REG_ENDIAN_OFFSET, lldb::eEncodingUint, lldb::eFormatHex, {LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gpr_w25}, g_contained_x25, g_w25_invalidates, nullptr, 0}, - {"w26", nullptr, 4, GPR_OFFSET(26) + GPR_W_PSEUDO_REG_ENDIAN_OFFSET, lldb::eEncodingUint, lldb::eFormatHex, {LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gpr_w26}, g_contained_x26, g_w26_invalidates, nullptr, 0}, - {"w27", nullptr, 4, GPR_OFFSET(27) + GPR_W_PSEUDO_REG_ENDIAN_OFFSET, lldb::eEncodingUint, lldb::eFormatHex, {LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gpr_w27}, g_contained_x27, g_w27_invalidates, nullptr, 0}, - {"w28", nullptr, 4, GPR_OFFSET(28) + GPR_W_PSEUDO_REG_ENDIAN_OFFSET, lldb::eEncodingUint, lldb::eFormatHex, {LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gpr_w28}, g_contained_x28, g_w28_invalidates, nullptr, 0}, - - // NAME ALT SZ OFFSET ENCODING FORMAT EH_FRAME DWARF GENERIC PROCESS PLUGIN LLDB VALUE REGS INVAL DYNEXPR SZ - // ===== ======= == ============= =================== ================ ================= =============== =================== =================== ====== ============== ======= ======= == - {"v0", nullptr, 16, FPU_OFFSET(0), lldb::eEncodingVector, lldb::eFormatVectorOfUInt8, {LLDB_INVALID_REGNUM, arm64_dwarf::v0, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, fpu_v0}, nullptr, nullptr, nullptr, 0}, - {"v1", nullptr, 16, FPU_OFFSET(1), lldb::eEncodingVector, lldb::eFormatVectorOfUInt8, {LLDB_INVALID_REGNUM, arm64_dwarf::v1, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, fpu_v1}, nullptr, nullptr, nullptr, 0}, - {"v2", nullptr, 16, FPU_OFFSET(2), lldb::eEncodingVector, lldb::eFormatVectorOfUInt8, {LLDB_INVALID_REGNUM, arm64_dwarf::v2, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, fpu_v2}, nullptr, nullptr, nullptr, 0}, - {"v3", nullptr, 16, FPU_OFFSET(3), lldb::eEncodingVector, lldb::eFormatVectorOfUInt8, {LLDB_INVALID_REGNUM, arm64_dwarf::v3, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, fpu_v3}, nullptr, nullptr, nullptr, 0}, - {"v4", nullptr, 16, FPU_OFFSET(4), lldb::eEncodingVector, lldb::eFormatVectorOfUInt8, {LLDB_INVALID_REGNUM, arm64_dwarf::v4, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, fpu_v4}, nullptr, nullptr, nullptr, 0}, - {"v5", nullptr, 16, FPU_OFFSET(5), lldb::eEncodingVector, lldb::eFormatVectorOfUInt8, {LLDB_INVALID_REGNUM, arm64_dwarf::v5, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, fpu_v5}, nullptr, nullptr, nullptr, 0}, - {"v6", nullptr, 16, FPU_OFFSET(6), lldb::eEncodingVector, lldb::eFormatVectorOfUInt8, {LLDB_INVALID_REGNUM, arm64_dwarf::v6, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, fpu_v6}, nullptr, nullptr, nullptr, 0}, - {"v7", nullptr, 16, FPU_OFFSET(7), lldb::eEncodingVector, lldb::eFormatVectorOfUInt8, {LLDB_INVALID_REGNUM, arm64_dwarf::v7, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, fpu_v7}, nullptr, nullptr, nullptr, 0}, - {"v8", nullptr, 16, FPU_OFFSET(8), lldb::eEncodingVector, lldb::eFormatVectorOfUInt8, {LLDB_INVALID_REGNUM, arm64_dwarf::v8, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, fpu_v8}, nullptr, nullptr, nullptr, 0}, - {"v9", nullptr, 16, FPU_OFFSET(9), lldb::eEncodingVector, lldb::eFormatVectorOfUInt8, {LLDB_INVALID_REGNUM, arm64_dwarf::v9, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, fpu_v9}, nullptr, nullptr, nullptr, 0}, - {"v10", nullptr, 16, FPU_OFFSET(10), lldb::eEncodingVector, lldb::eFormatVectorOfUInt8, {LLDB_INVALID_REGNUM, arm64_dwarf::v10, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, fpu_v10}, nullptr, nullptr, nullptr, 0}, - {"v11", nullptr, 16, FPU_OFFSET(11), lldb::eEncodingVector, lldb::eFormatVectorOfUInt8, {LLDB_INVALID_REGNUM, arm64_dwarf::v11, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, fpu_v11}, nullptr, nullptr, nullptr, 0}, - {"v12", nullptr, 16, FPU_OFFSET(12), lldb::eEncodingVector, lldb::eFormatVectorOfUInt8, {LLDB_INVALID_REGNUM, arm64_dwarf::v12, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, fpu_v12}, nullptr, nullptr, nullptr, 0}, - {"v13", nullptr, 16, FPU_OFFSET(13), lldb::eEncodingVector, lldb::eFormatVectorOfUInt8, {LLDB_INVALID_REGNUM, arm64_dwarf::v13, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, fpu_v13}, nullptr, nullptr, nullptr, 0}, - {"v14", nullptr, 16, FPU_OFFSET(14), lldb::eEncodingVector, lldb::eFormatVectorOfUInt8, {LLDB_INVALID_REGNUM, arm64_dwarf::v14, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, fpu_v14}, nullptr, nullptr, nullptr, 0}, - {"v15", nullptr, 16, FPU_OFFSET(15), lldb::eEncodingVector, lldb::eFormatVectorOfUInt8, {LLDB_INVALID_REGNUM, arm64_dwarf::v15, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, fpu_v15}, nullptr, nullptr, nullptr, 0}, - {"v16", nullptr, 16, FPU_OFFSET(16), lldb::eEncodingVector, lldb::eFormatVectorOfUInt8, {LLDB_INVALID_REGNUM, arm64_dwarf::v16, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, fpu_v16}, nullptr, nullptr, nullptr, 0}, - {"v17", nullptr, 16, FPU_OFFSET(17), lldb::eEncodingVector, lldb::eFormatVectorOfUInt8, {LLDB_INVALID_REGNUM, arm64_dwarf::v17, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, fpu_v17}, nullptr, nullptr, nullptr, 0}, - {"v18", nullptr, 16, FPU_OFFSET(18), lldb::eEncodingVector, lldb::eFormatVectorOfUInt8, {LLDB_INVALID_REGNUM, arm64_dwarf::v18, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, fpu_v18}, nullptr, nullptr, nullptr, 0}, - {"v19", nullptr, 16, FPU_OFFSET(19), lldb::eEncodingVector, lldb::eFormatVectorOfUInt8, {LLDB_INVALID_REGNUM, arm64_dwarf::v19, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, fpu_v19}, nullptr, nullptr, nullptr, 0}, - {"v20", nullptr, 16, FPU_OFFSET(20), lldb::eEncodingVector, lldb::eFormatVectorOfUInt8, {LLDB_INVALID_REGNUM, arm64_dwarf::v20, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, fpu_v20}, nullptr, nullptr, nullptr, 0}, - {"v21", nullptr, 16, FPU_OFFSET(21), lldb::eEncodingVector, lldb::eFormatVectorOfUInt8, {LLDB_INVALID_REGNUM, arm64_dwarf::v21, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, fpu_v21}, nullptr, nullptr, nullptr, 0}, - {"v22", nullptr, 16, FPU_OFFSET(22), lldb::eEncodingVector, lldb::eFormatVectorOfUInt8, {LLDB_INVALID_REGNUM, arm64_dwarf::v22, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, fpu_v22}, nullptr, nullptr, nullptr, 0}, - {"v23", nullptr, 16, FPU_OFFSET(23), lldb::eEncodingVector, lldb::eFormatVectorOfUInt8, {LLDB_INVALID_REGNUM, arm64_dwarf::v23, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, fpu_v23}, nullptr, nullptr, nullptr, 0}, - {"v24", nullptr, 16, FPU_OFFSET(24), lldb::eEncodingVector, lldb::eFormatVectorOfUInt8, {LLDB_INVALID_REGNUM, arm64_dwarf::v24, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, fpu_v24}, nullptr, nullptr, nullptr, 0}, - {"v25", nullptr, 16, FPU_OFFSET(25), lldb::eEncodingVector, lldb::eFormatVectorOfUInt8, {LLDB_INVALID_REGNUM, arm64_dwarf::v25, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, fpu_v25}, nullptr, nullptr, nullptr, 0}, - {"v26", nullptr, 16, FPU_OFFSET(26), lldb::eEncodingVector, lldb::eFormatVectorOfUInt8, {LLDB_INVALID_REGNUM, arm64_dwarf::v26, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, fpu_v26}, nullptr, nullptr, nullptr, 0}, - {"v27", nullptr, 16, FPU_OFFSET(27), lldb::eEncodingVector, lldb::eFormatVectorOfUInt8, {LLDB_INVALID_REGNUM, arm64_dwarf::v27, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, fpu_v27}, nullptr, nullptr, nullptr, 0}, - {"v28", nullptr, 16, FPU_OFFSET(28), lldb::eEncodingVector, lldb::eFormatVectorOfUInt8, {LLDB_INVALID_REGNUM, arm64_dwarf::v28, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, fpu_v28}, nullptr, nullptr, nullptr, 0}, - {"v29", nullptr, 16, FPU_OFFSET(29), lldb::eEncodingVector, lldb::eFormatVectorOfUInt8, {LLDB_INVALID_REGNUM, arm64_dwarf::v29, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, fpu_v29}, nullptr, nullptr, nullptr, 0}, - {"v30", nullptr, 16, FPU_OFFSET(30), lldb::eEncodingVector, lldb::eFormatVectorOfUInt8, {LLDB_INVALID_REGNUM, arm64_dwarf::v30, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, fpu_v30}, nullptr, nullptr, nullptr, 0}, - {"v31", nullptr, 16, FPU_OFFSET(31), lldb::eEncodingVector, lldb::eFormatVectorOfUInt8, {LLDB_INVALID_REGNUM, arm64_dwarf::v31, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, fpu_v31}, nullptr, nullptr, nullptr, 0}, - - // NAME ALT SZ OFFSET ENCODING FORMAT EH_FRAME DWARF GENERIC PROCESS PLUGIN LLDB VALUE REGS INVALIDATES DYNEXPR SZ - // ===== ======= == ============================================== =================== ================ ================= =============== =================== =================== ====== =============== ================= ======= == - {"s0", nullptr, 4, FPU_OFFSET(0) + FPU_S_PSEUDO_REG_ENDIAN_OFFSET, lldb::eEncodingIEEE754, lldb::eFormatFloat, {LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, fpu_s0}, g_contained_v0, g_s0_invalidates, nullptr, 0}, - {"s1", nullptr, 4, FPU_OFFSET(1) + FPU_S_PSEUDO_REG_ENDIAN_OFFSET, lldb::eEncodingIEEE754, lldb::eFormatFloat, {LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, fpu_s1}, g_contained_v1, g_s1_invalidates, nullptr, 0}, - {"s2", nullptr, 4, FPU_OFFSET(2) + FPU_S_PSEUDO_REG_ENDIAN_OFFSET, lldb::eEncodingIEEE754, lldb::eFormatFloat, {LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, fpu_s2}, g_contained_v2, g_s2_invalidates, nullptr, 0}, - {"s3", nullptr, 4, FPU_OFFSET(3) + FPU_S_PSEUDO_REG_ENDIAN_OFFSET, lldb::eEncodingIEEE754, lldb::eFormatFloat, {LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, fpu_s3}, g_contained_v3, g_s3_invalidates, nullptr, 0}, - {"s4", nullptr, 4, FPU_OFFSET(4) + FPU_S_PSEUDO_REG_ENDIAN_OFFSET, lldb::eEncodingIEEE754, lldb::eFormatFloat, {LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, fpu_s4}, g_contained_v4, g_s4_invalidates, nullptr, 0}, - {"s5", nullptr, 4, FPU_OFFSET(5) + FPU_S_PSEUDO_REG_ENDIAN_OFFSET, lldb::eEncodingIEEE754, lldb::eFormatFloat, {LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, fpu_s5}, g_contained_v5, g_s5_invalidates, nullptr, 0}, - {"s6", nullptr, 4, FPU_OFFSET(6) + FPU_S_PSEUDO_REG_ENDIAN_OFFSET, lldb::eEncodingIEEE754, lldb::eFormatFloat, {LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, fpu_s6}, g_contained_v6, g_s6_invalidates, nullptr, 0}, - {"s7", nullptr, 4, FPU_OFFSET(7) + FPU_S_PSEUDO_REG_ENDIAN_OFFSET, lldb::eEncodingIEEE754, lldb::eFormatFloat, {LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, fpu_s7}, g_contained_v7, g_s7_invalidates, nullptr, 0}, - {"s8", nullptr, 4, FPU_OFFSET(8) + FPU_S_PSEUDO_REG_ENDIAN_OFFSET, lldb::eEncodingIEEE754, lldb::eFormatFloat, {LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, fpu_s8}, g_contained_v8, g_s8_invalidates, nullptr, 0}, - {"s9", nullptr, 4, FPU_OFFSET(9) + FPU_S_PSEUDO_REG_ENDIAN_OFFSET, lldb::eEncodingIEEE754, lldb::eFormatFloat, {LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, fpu_s9}, g_contained_v9, g_s9_invalidates, nullptr, 0}, - {"s10", nullptr, 4, FPU_OFFSET(10) + FPU_S_PSEUDO_REG_ENDIAN_OFFSET, lldb::eEncodingIEEE754, lldb::eFormatFloat, {LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, fpu_s10}, g_contained_v10, g_s10_invalidates, nullptr, 0}, - {"s11", nullptr, 4, FPU_OFFSET(11) + FPU_S_PSEUDO_REG_ENDIAN_OFFSET, lldb::eEncodingIEEE754, lldb::eFormatFloat, {LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, fpu_s11}, g_contained_v11, g_s11_invalidates, nullptr, 0}, - {"s12", nullptr, 4, FPU_OFFSET(12) + FPU_S_PSEUDO_REG_ENDIAN_OFFSET, lldb::eEncodingIEEE754, lldb::eFormatFloat, {LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, fpu_s12}, g_contained_v12, g_s12_invalidates, nullptr, 0}, - {"s13", nullptr, 4, FPU_OFFSET(13) + FPU_S_PSEUDO_REG_ENDIAN_OFFSET, lldb::eEncodingIEEE754, lldb::eFormatFloat, {LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, fpu_s13}, g_contained_v13, g_s13_invalidates, nullptr, 0}, - {"s14", nullptr, 4, FPU_OFFSET(14) + FPU_S_PSEUDO_REG_ENDIAN_OFFSET, lldb::eEncodingIEEE754, lldb::eFormatFloat, {LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, fpu_s14}, g_contained_v14, g_s14_invalidates, nullptr, 0}, - {"s15", nullptr, 4, FPU_OFFSET(15) + FPU_S_PSEUDO_REG_ENDIAN_OFFSET, lldb::eEncodingIEEE754, lldb::eFormatFloat, {LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, fpu_s15}, g_contained_v15, g_s15_invalidates, nullptr, 0}, - {"s16", nullptr, 4, FPU_OFFSET(16) + FPU_S_PSEUDO_REG_ENDIAN_OFFSET, lldb::eEncodingIEEE754, lldb::eFormatFloat, {LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, fpu_s16}, g_contained_v16, g_s16_invalidates, nullptr, 0}, - {"s17", nullptr, 4, FPU_OFFSET(17) + FPU_S_PSEUDO_REG_ENDIAN_OFFSET, lldb::eEncodingIEEE754, lldb::eFormatFloat, {LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, fpu_s17}, g_contained_v17, g_s17_invalidates, nullptr, 0}, - {"s18", nullptr, 4, FPU_OFFSET(18) + FPU_S_PSEUDO_REG_ENDIAN_OFFSET, lldb::eEncodingIEEE754, lldb::eFormatFloat, {LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, fpu_s18}, g_contained_v18, g_s18_invalidates, nullptr, 0}, - {"s19", nullptr, 4, FPU_OFFSET(19) + FPU_S_PSEUDO_REG_ENDIAN_OFFSET, lldb::eEncodingIEEE754, lldb::eFormatFloat, {LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, fpu_s19}, g_contained_v19, g_s19_invalidates, nullptr, 0}, - {"s20", nullptr, 4, FPU_OFFSET(20) + FPU_S_PSEUDO_REG_ENDIAN_OFFSET, lldb::eEncodingIEEE754, lldb::eFormatFloat, {LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, fpu_s20}, g_contained_v20, g_s20_invalidates, nullptr, 0}, - {"s21", nullptr, 4, FPU_OFFSET(21) + FPU_S_PSEUDO_REG_ENDIAN_OFFSET, lldb::eEncodingIEEE754, lldb::eFormatFloat, {LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, fpu_s21}, g_contained_v21, g_s21_invalidates, nullptr, 0}, - {"s22", nullptr, 4, FPU_OFFSET(22) + FPU_S_PSEUDO_REG_ENDIAN_OFFSET, lldb::eEncodingIEEE754, lldb::eFormatFloat, {LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, fpu_s22}, g_contained_v22, g_s22_invalidates, nullptr, 0}, - {"s23", nullptr, 4, FPU_OFFSET(23) + FPU_S_PSEUDO_REG_ENDIAN_OFFSET, lldb::eEncodingIEEE754, lldb::eFormatFloat, {LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, fpu_s23}, g_contained_v23, g_s23_invalidates, nullptr, 0}, - {"s24", nullptr, 4, FPU_OFFSET(24) + FPU_S_PSEUDO_REG_ENDIAN_OFFSET, lldb::eEncodingIEEE754, lldb::eFormatFloat, {LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, fpu_s24}, g_contained_v24, g_s24_invalidates, nullptr, 0}, - {"s25", nullptr, 4, FPU_OFFSET(25) + FPU_S_PSEUDO_REG_ENDIAN_OFFSET, lldb::eEncodingIEEE754, lldb::eFormatFloat, {LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, fpu_s25}, g_contained_v25, g_s25_invalidates, nullptr, 0}, - {"s26", nullptr, 4, FPU_OFFSET(26) + FPU_S_PSEUDO_REG_ENDIAN_OFFSET, lldb::eEncodingIEEE754, lldb::eFormatFloat, {LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, fpu_s26}, g_contained_v26, g_s26_invalidates, nullptr, 0}, - {"s27", nullptr, 4, FPU_OFFSET(27) + FPU_S_PSEUDO_REG_ENDIAN_OFFSET, lldb::eEncodingIEEE754, lldb::eFormatFloat, {LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, fpu_s27}, g_contained_v27, g_s27_invalidates, nullptr, 0}, - {"s28", nullptr, 4, FPU_OFFSET(28) + FPU_S_PSEUDO_REG_ENDIAN_OFFSET, lldb::eEncodingIEEE754, lldb::eFormatFloat, {LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, fpu_s28}, g_contained_v28, g_s28_invalidates, nullptr, 0}, - {"s29", nullptr, 4, FPU_OFFSET(29) + FPU_S_PSEUDO_REG_ENDIAN_OFFSET, lldb::eEncodingIEEE754, lldb::eFormatFloat, {LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, fpu_s29}, g_contained_v29, g_s29_invalidates, nullptr, 0}, - {"s30", nullptr, 4, FPU_OFFSET(30) + FPU_S_PSEUDO_REG_ENDIAN_OFFSET, lldb::eEncodingIEEE754, lldb::eFormatFloat, {LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, fpu_s30}, g_contained_v30, g_s30_invalidates, nullptr, 0}, - {"s31", nullptr, 4, FPU_OFFSET(31) + FPU_S_PSEUDO_REG_ENDIAN_OFFSET, lldb::eEncodingIEEE754, lldb::eFormatFloat, {LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, fpu_s31}, g_contained_v31, g_s31_invalidates, nullptr, 0}, - - {"d0", nullptr, 8, FPU_OFFSET(0) + FPU_D_PSEUDO_REG_ENDIAN_OFFSET, lldb::eEncodingIEEE754, lldb::eFormatFloat, {LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, fpu_d0}, g_contained_v0, g_d0_invalidates, nullptr, 0}, - {"d1", nullptr, 8, FPU_OFFSET(1) + FPU_D_PSEUDO_REG_ENDIAN_OFFSET, lldb::eEncodingIEEE754, lldb::eFormatFloat, {LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, fpu_d1}, g_contained_v1, g_d1_invalidates, nullptr, 0}, - {"d2", nullptr, 8, FPU_OFFSET(2) + FPU_D_PSEUDO_REG_ENDIAN_OFFSET, lldb::eEncodingIEEE754, lldb::eFormatFloat, {LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, fpu_d2}, g_contained_v2, g_d2_invalidates, nullptr, 0}, - {"d3", nullptr, 8, FPU_OFFSET(3) + FPU_D_PSEUDO_REG_ENDIAN_OFFSET, lldb::eEncodingIEEE754, lldb::eFormatFloat, {LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, fpu_d3}, g_contained_v3, g_d3_invalidates, nullptr, 0}, - {"d4", nullptr, 8, FPU_OFFSET(4) + FPU_D_PSEUDO_REG_ENDIAN_OFFSET, lldb::eEncodingIEEE754, lldb::eFormatFloat, {LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, fpu_d4}, g_contained_v4, g_d4_invalidates, nullptr, 0}, - {"d5", nullptr, 8, FPU_OFFSET(5) + FPU_D_PSEUDO_REG_ENDIAN_OFFSET, lldb::eEncodingIEEE754, lldb::eFormatFloat, {LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, fpu_d5}, g_contained_v5, g_d5_invalidates, nullptr, 0}, - {"d6", nullptr, 8, FPU_OFFSET(6) + FPU_D_PSEUDO_REG_ENDIAN_OFFSET, lldb::eEncodingIEEE754, lldb::eFormatFloat, {LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, fpu_d6}, g_contained_v6, g_d6_invalidates, nullptr, 0}, - {"d7", nullptr, 8, FPU_OFFSET(7) + FPU_D_PSEUDO_REG_ENDIAN_OFFSET, lldb::eEncodingIEEE754, lldb::eFormatFloat, {LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, fpu_d7}, g_contained_v7, g_d7_invalidates, nullptr, 0}, - {"d8", nullptr, 8, FPU_OFFSET(8) + FPU_D_PSEUDO_REG_ENDIAN_OFFSET, lldb::eEncodingIEEE754, lldb::eFormatFloat, {LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, fpu_d8}, g_contained_v8, g_d8_invalidates, nullptr, 0}, - {"d9", nullptr, 8, FPU_OFFSET(9) + FPU_D_PSEUDO_REG_ENDIAN_OFFSET, lldb::eEncodingIEEE754, lldb::eFormatFloat, {LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, fpu_d9}, g_contained_v9, g_d9_invalidates, nullptr, 0}, - {"d10", nullptr, 8, FPU_OFFSET(10) + FPU_D_PSEUDO_REG_ENDIAN_OFFSET, lldb::eEncodingIEEE754, lldb::eFormatFloat, {LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, fpu_d10}, g_contained_v10, g_d10_invalidates, nullptr, 0}, - {"d11", nullptr, 8, FPU_OFFSET(11) + FPU_D_PSEUDO_REG_ENDIAN_OFFSET, lldb::eEncodingIEEE754, lldb::eFormatFloat, {LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, fpu_d11}, g_contained_v11, g_d11_invalidates, nullptr, 0}, - {"d12", nullptr, 8, FPU_OFFSET(12) + FPU_D_PSEUDO_REG_ENDIAN_OFFSET, lldb::eEncodingIEEE754, lldb::eFormatFloat, {LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, fpu_d12}, g_contained_v12, g_d12_invalidates, nullptr, 0}, - {"d13", nullptr, 8, FPU_OFFSET(13) + FPU_D_PSEUDO_REG_ENDIAN_OFFSET, lldb::eEncodingIEEE754, lldb::eFormatFloat, {LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, fpu_d13}, g_contained_v13, g_d13_invalidates, nullptr, 0}, - {"d14", nullptr, 8, FPU_OFFSET(14) + FPU_D_PSEUDO_REG_ENDIAN_OFFSET, lldb::eEncodingIEEE754, lldb::eFormatFloat, {LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, fpu_d14}, g_contained_v14, g_d14_invalidates, nullptr, 0}, - {"d15", nullptr, 8, FPU_OFFSET(15) + FPU_D_PSEUDO_REG_ENDIAN_OFFSET, lldb::eEncodingIEEE754, lldb::eFormatFloat, {LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, fpu_d15}, g_contained_v15, g_d15_invalidates, nullptr, 0}, - {"d16", nullptr, 8, FPU_OFFSET(16) + FPU_D_PSEUDO_REG_ENDIAN_OFFSET, lldb::eEncodingIEEE754, lldb::eFormatFloat, {LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, fpu_d16}, g_contained_v16, g_d16_invalidates, nullptr, 0}, - {"d17", nullptr, 8, FPU_OFFSET(17) + FPU_D_PSEUDO_REG_ENDIAN_OFFSET, lldb::eEncodingIEEE754, lldb::eFormatFloat, {LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, fpu_d17}, g_contained_v17, g_d17_invalidates, nullptr, 0}, - {"d18", nullptr, 8, FPU_OFFSET(18) + FPU_D_PSEUDO_REG_ENDIAN_OFFSET, lldb::eEncodingIEEE754, lldb::eFormatFloat, {LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, fpu_d18}, g_contained_v18, g_d18_invalidates, nullptr, 0}, - {"d19", nullptr, 8, FPU_OFFSET(19) + FPU_D_PSEUDO_REG_ENDIAN_OFFSET, lldb::eEncodingIEEE754, lldb::eFormatFloat, {LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, fpu_d19}, g_contained_v19, g_d19_invalidates, nullptr, 0}, - {"d20", nullptr, 8, FPU_OFFSET(20) + FPU_D_PSEUDO_REG_ENDIAN_OFFSET, lldb::eEncodingIEEE754, lldb::eFormatFloat, {LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, fpu_d20}, g_contained_v20, g_d20_invalidates, nullptr, 0}, - {"d21", nullptr, 8, FPU_OFFSET(21) + FPU_D_PSEUDO_REG_ENDIAN_OFFSET, lldb::eEncodingIEEE754, lldb::eFormatFloat, {LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, fpu_d21}, g_contained_v21, g_d21_invalidates, nullptr, 0}, - {"d22", nullptr, 8, FPU_OFFSET(22) + FPU_D_PSEUDO_REG_ENDIAN_OFFSET, lldb::eEncodingIEEE754, lldb::eFormatFloat, {LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, fpu_d22}, g_contained_v22, g_d22_invalidates, nullptr, 0}, - {"d23", nullptr, 8, FPU_OFFSET(23) + FPU_D_PSEUDO_REG_ENDIAN_OFFSET, lldb::eEncodingIEEE754, lldb::eFormatFloat, {LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, fpu_d23}, g_contained_v23, g_d23_invalidates, nullptr, 0}, - {"d24", nullptr, 8, FPU_OFFSET(24) + FPU_D_PSEUDO_REG_ENDIAN_OFFSET, lldb::eEncodingIEEE754, lldb::eFormatFloat, {LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, fpu_d24}, g_contained_v24, g_d24_invalidates, nullptr, 0}, - {"d25", nullptr, 8, FPU_OFFSET(25) + FPU_D_PSEUDO_REG_ENDIAN_OFFSET, lldb::eEncodingIEEE754, lldb::eFormatFloat, {LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, fpu_d25}, g_contained_v25, g_d25_invalidates, nullptr, 0}, - {"d26", nullptr, 8, FPU_OFFSET(26) + FPU_D_PSEUDO_REG_ENDIAN_OFFSET, lldb::eEncodingIEEE754, lldb::eFormatFloat, {LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, fpu_d26}, g_contained_v26, g_d26_invalidates, nullptr, 0}, - {"d27", nullptr, 8, FPU_OFFSET(27) + FPU_D_PSEUDO_REG_ENDIAN_OFFSET, lldb::eEncodingIEEE754, lldb::eFormatFloat, {LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, fpu_d27}, g_contained_v27, g_d27_invalidates, nullptr, 0}, - {"d28", nullptr, 8, FPU_OFFSET(28) + FPU_D_PSEUDO_REG_ENDIAN_OFFSET, lldb::eEncodingIEEE754, lldb::eFormatFloat, {LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, fpu_d28}, g_contained_v28, g_d28_invalidates, nullptr, 0}, - {"d29", nullptr, 8, FPU_OFFSET(29) + FPU_D_PSEUDO_REG_ENDIAN_OFFSET, lldb::eEncodingIEEE754, lldb::eFormatFloat, {LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, fpu_d29}, g_contained_v29, g_d29_invalidates, nullptr, 0}, - {"d30", nullptr, 8, FPU_OFFSET(30) + FPU_D_PSEUDO_REG_ENDIAN_OFFSET, lldb::eEncodingIEEE754, lldb::eFormatFloat, {LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, fpu_d30}, g_contained_v30, g_d30_invalidates, nullptr, 0}, - {"d31", nullptr, 8, FPU_OFFSET(31) + FPU_D_PSEUDO_REG_ENDIAN_OFFSET, lldb::eEncodingIEEE754, lldb::eFormatFloat, {LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, fpu_d31}, g_contained_v31, g_d31_invalidates, nullptr, 0}, - - {"fpsr", nullptr, 4, FPU_OFFSET_NAME(fpsr), lldb::eEncodingUint, lldb::eFormatHex, {LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, fpu_fpsr}, nullptr, nullptr, nullptr, 0}, - {"fpcr", nullptr, 4, FPU_OFFSET_NAME(fpcr), lldb::eEncodingUint, lldb::eFormatHex, {LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, fpu_fpcr}, nullptr, nullptr, nullptr, 0}, - - {"far", nullptr, 8, EXC_OFFSET_NAME(far), lldb::eEncodingUint, lldb::eFormatHex, {LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, exc_far}, nullptr, nullptr, nullptr, 0}, - {"esr", nullptr, 4, EXC_OFFSET_NAME(esr), lldb::eEncodingUint, lldb::eFormatHex, {LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, exc_esr}, nullptr, nullptr, nullptr, 0}, - {"exception", nullptr, 4, EXC_OFFSET_NAME(exception), lldb::eEncodingUint, lldb::eFormatHex, {LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, exc_exception}, nullptr, nullptr, nullptr, 0}, + // DEFINE_GPR64(name, GENERIC KIND) + DEFINE_GPR64(x0, LLDB_REGNUM_GENERIC_ARG1), + DEFINE_GPR64(x1, LLDB_REGNUM_GENERIC_ARG2), + DEFINE_GPR64(x2, LLDB_REGNUM_GENERIC_ARG3), + DEFINE_GPR64(x3, LLDB_REGNUM_GENERIC_ARG4), + DEFINE_GPR64(x4, LLDB_REGNUM_GENERIC_ARG5), + DEFINE_GPR64(x5, LLDB_REGNUM_GENERIC_ARG6), + DEFINE_GPR64(x6, LLDB_REGNUM_GENERIC_ARG7), + DEFINE_GPR64(x7, LLDB_REGNUM_GENERIC_ARG8), + DEFINE_GPR64(x8, LLDB_INVALID_REGNUM), + DEFINE_GPR64(x9, LLDB_INVALID_REGNUM), + DEFINE_GPR64(x10, LLDB_INVALID_REGNUM), + DEFINE_GPR64(x11, LLDB_INVALID_REGNUM), + DEFINE_GPR64(x12, LLDB_INVALID_REGNUM), + DEFINE_GPR64(x13, LLDB_INVALID_REGNUM), + DEFINE_GPR64(x14, LLDB_INVALID_REGNUM), + DEFINE_GPR64(x15, LLDB_INVALID_REGNUM), + DEFINE_GPR64(x16, LLDB_INVALID_REGNUM), + DEFINE_GPR64(x17, LLDB_INVALID_REGNUM), + DEFINE_GPR64(x18, LLDB_INVALID_REGNUM), + DEFINE_GPR64(x19, LLDB_INVALID_REGNUM), + DEFINE_GPR64(x20, LLDB_INVALID_REGNUM), + DEFINE_GPR64(x21, LLDB_INVALID_REGNUM), + DEFINE_GPR64(x22, LLDB_INVALID_REGNUM), + DEFINE_GPR64(x23, LLDB_INVALID_REGNUM), + DEFINE_GPR64(x24, LLDB_INVALID_REGNUM), + DEFINE_GPR64(x25, LLDB_INVALID_REGNUM), + DEFINE_GPR64(x26, LLDB_INVALID_REGNUM), + DEFINE_GPR64(x27, LLDB_INVALID_REGNUM), + DEFINE_GPR64(x28, LLDB_INVALID_REGNUM), + // DEFINE_GPR64(name, GENERIC KIND) + DEFINE_GPR64_ALT(fp, x29, LLDB_REGNUM_GENERIC_FP), + DEFINE_GPR64_ALT(lr, x30, LLDB_REGNUM_GENERIC_RA), + DEFINE_GPR64_ALT(sp, x31, LLDB_REGNUM_GENERIC_SP), + DEFINE_GPR64(pc, LLDB_REGNUM_GENERIC_PC), + + // DEFINE_MISC_REGS(name, size, TYPE, lldb kind) + DEFINE_MISC_REGS(cpsr, 4, GPR, gpr_cpsr), + + // DEFINE_GPR32(name, parent name) + DEFINE_GPR32(w0, x0), + DEFINE_GPR32(w1, x1), + DEFINE_GPR32(w2, x2), + DEFINE_GPR32(w3, x3), + DEFINE_GPR32(w4, x4), + DEFINE_GPR32(w5, x5), + DEFINE_GPR32(w6, x6), + DEFINE_GPR32(w7, x7), + DEFINE_GPR32(w8, x8), + DEFINE_GPR32(w9, x9), + DEFINE_GPR32(w10, x10), + DEFINE_GPR32(w11, x11), + DEFINE_GPR32(w12, x12), + DEFINE_GPR32(w13, x13), + DEFINE_GPR32(w14, x14), + DEFINE_GPR32(w15, x15), + DEFINE_GPR32(w16, x16), + DEFINE_GPR32(w17, x17), + DEFINE_GPR32(w18, x18), + DEFINE_GPR32(w19, x19), + DEFINE_GPR32(w20, x20), + DEFINE_GPR32(w21, x21), + DEFINE_GPR32(w22, x22), + DEFINE_GPR32(w23, x23), + DEFINE_GPR32(w24, x24), + DEFINE_GPR32(w25, x25), + DEFINE_GPR32(w26, x26), + DEFINE_GPR32(w27, x27), + DEFINE_GPR32(w28, x28), + + // DEFINE_VREG(name) + DEFINE_VREG(v0), + DEFINE_VREG(v1), + DEFINE_VREG(v2), + DEFINE_VREG(v3), + DEFINE_VREG(v4), + DEFINE_VREG(v5), + DEFINE_VREG(v6), + DEFINE_VREG(v7), + DEFINE_VREG(v8), + DEFINE_VREG(v9), + DEFINE_VREG(v10), + DEFINE_VREG(v11), + DEFINE_VREG(v12), + DEFINE_VREG(v13), + DEFINE_VREG(v14), + DEFINE_VREG(v15), + DEFINE_VREG(v16), + DEFINE_VREG(v17), + DEFINE_VREG(v18), + DEFINE_VREG(v19), + DEFINE_VREG(v20), + DEFINE_VREG(v21), + DEFINE_VREG(v22), + DEFINE_VREG(v23), + DEFINE_VREG(v24), + DEFINE_VREG(v25), + DEFINE_VREG(v26), + DEFINE_VREG(v27), + DEFINE_VREG(v28), + DEFINE_VREG(v29), + DEFINE_VREG(v30), + DEFINE_VREG(v31), + + // DEFINE_FPU_PSEUDO(name, size, ENDIAN OFFSET, parent register) + DEFINE_FPU_PSEUDO(s0, 4, FPU_S_PSEUDO_REG_ENDIAN_OFFSET, v0), + DEFINE_FPU_PSEUDO(s1, 4, FPU_S_PSEUDO_REG_ENDIAN_OFFSET, v1), + DEFINE_FPU_PSEUDO(s2, 4, FPU_S_PSEUDO_REG_ENDIAN_OFFSET, v2), + DEFINE_FPU_PSEUDO(s3, 4, FPU_S_PSEUDO_REG_ENDIAN_OFFSET, v3), + DEFINE_FPU_PSEUDO(s4, 4, FPU_S_PSEUDO_REG_ENDIAN_OFFSET, v4), + DEFINE_FPU_PSEUDO(s5, 4, FPU_S_PSEUDO_REG_ENDIAN_OFFSET, v5), + DEFINE_FPU_PSEUDO(s6, 4, FPU_S_PSEUDO_REG_ENDIAN_OFFSET, v6), + DEFINE_FPU_PSEUDO(s7, 4, FPU_S_PSEUDO_REG_ENDIAN_OFFSET, v7), + DEFINE_FPU_PSEUDO(s8, 4, FPU_S_PSEUDO_REG_ENDIAN_OFFSET, v8), + DEFINE_FPU_PSEUDO(s9, 4, FPU_S_PSEUDO_REG_ENDIAN_OFFSET, v9), + DEFINE_FPU_PSEUDO(s10, 4, FPU_S_PSEUDO_REG_ENDIAN_OFFSET, v10), + DEFINE_FPU_PSEUDO(s11, 4, FPU_S_PSEUDO_REG_ENDIAN_OFFSET, v11), + DEFINE_FPU_PSEUDO(s12, 4, FPU_S_PSEUDO_REG_ENDIAN_OFFSET, v12), + DEFINE_FPU_PSEUDO(s13, 4, FPU_S_PSEUDO_REG_ENDIAN_OFFSET, v13), + DEFINE_FPU_PSEUDO(s14, 4, FPU_S_PSEUDO_REG_ENDIAN_OFFSET, v14), + DEFINE_FPU_PSEUDO(s15, 4, FPU_S_PSEUDO_REG_ENDIAN_OFFSET, v15), + DEFINE_FPU_PSEUDO(s16, 4, FPU_S_PSEUDO_REG_ENDIAN_OFFSET, v16), + DEFINE_FPU_PSEUDO(s17, 4, FPU_S_PSEUDO_REG_ENDIAN_OFFSET, v17), + DEFINE_FPU_PSEUDO(s18, 4, FPU_S_PSEUDO_REG_ENDIAN_OFFSET, v18), + DEFINE_FPU_PSEUDO(s19, 4, FPU_S_PSEUDO_REG_ENDIAN_OFFSET, v19), + DEFINE_FPU_PSEUDO(s20, 4, FPU_S_PSEUDO_REG_ENDIAN_OFFSET, v20), + DEFINE_FPU_PSEUDO(s21, 4, FPU_S_PSEUDO_REG_ENDIAN_OFFSET, v21), + DEFINE_FPU_PSEUDO(s22, 4, FPU_S_PSEUDO_REG_ENDIAN_OFFSET, v22), + DEFINE_FPU_PSEUDO(s23, 4, FPU_S_PSEUDO_REG_ENDIAN_OFFSET, v23), + DEFINE_FPU_PSEUDO(s24, 4, FPU_S_PSEUDO_REG_ENDIAN_OFFSET, v24), + DEFINE_FPU_PSEUDO(s25, 4, FPU_S_PSEUDO_REG_ENDIAN_OFFSET, v25), + DEFINE_FPU_PSEUDO(s26, 4, FPU_S_PSEUDO_REG_ENDIAN_OFFSET, v26), + DEFINE_FPU_PSEUDO(s27, 4, FPU_S_PSEUDO_REG_ENDIAN_OFFSET, v27), + DEFINE_FPU_PSEUDO(s28, 4, FPU_S_PSEUDO_REG_ENDIAN_OFFSET, v28), + DEFINE_FPU_PSEUDO(s29, 4, FPU_S_PSEUDO_REG_ENDIAN_OFFSET, v29), + DEFINE_FPU_PSEUDO(s30, 4, FPU_S_PSEUDO_REG_ENDIAN_OFFSET, v30), + DEFINE_FPU_PSEUDO(s31, 4, FPU_S_PSEUDO_REG_ENDIAN_OFFSET, v31), + + DEFINE_FPU_PSEUDO(d0, 8, FPU_D_PSEUDO_REG_ENDIAN_OFFSET, v0), + DEFINE_FPU_PSEUDO(d1, 8, FPU_D_PSEUDO_REG_ENDIAN_OFFSET, v1), + DEFINE_FPU_PSEUDO(d2, 8, FPU_D_PSEUDO_REG_ENDIAN_OFFSET, v2), + DEFINE_FPU_PSEUDO(d3, 8, FPU_D_PSEUDO_REG_ENDIAN_OFFSET, v3), + DEFINE_FPU_PSEUDO(d4, 8, FPU_D_PSEUDO_REG_ENDIAN_OFFSET, v4), + DEFINE_FPU_PSEUDO(d5, 8, FPU_D_PSEUDO_REG_ENDIAN_OFFSET, v5), + DEFINE_FPU_PSEUDO(d6, 8, FPU_D_PSEUDO_REG_ENDIAN_OFFSET, v6), + DEFINE_FPU_PSEUDO(d7, 8, FPU_D_PSEUDO_REG_ENDIAN_OFFSET, v7), + DEFINE_FPU_PSEUDO(d8, 8, FPU_D_PSEUDO_REG_ENDIAN_OFFSET, v8), + DEFINE_FPU_PSEUDO(d9, 8, FPU_D_PSEUDO_REG_ENDIAN_OFFSET, v9), + DEFINE_FPU_PSEUDO(d10, 8, FPU_D_PSEUDO_REG_ENDIAN_OFFSET, v10), + DEFINE_FPU_PSEUDO(d11, 8, FPU_D_PSEUDO_REG_ENDIAN_OFFSET, v11), + DEFINE_FPU_PSEUDO(d12, 8, FPU_D_PSEUDO_REG_ENDIAN_OFFSET, v12), + DEFINE_FPU_PSEUDO(d13, 8, FPU_D_PSEUDO_REG_ENDIAN_OFFSET, v13), + DEFINE_FPU_PSEUDO(d14, 8, FPU_D_PSEUDO_REG_ENDIAN_OFFSET, v14), + DEFINE_FPU_PSEUDO(d15, 8, FPU_D_PSEUDO_REG_ENDIAN_OFFSET, v15), + DEFINE_FPU_PSEUDO(d16, 8, FPU_D_PSEUDO_REG_ENDIAN_OFFSET, v16), + DEFINE_FPU_PSEUDO(d17, 8, FPU_D_PSEUDO_REG_ENDIAN_OFFSET, v17), + DEFINE_FPU_PSEUDO(d18, 8, FPU_D_PSEUDO_REG_ENDIAN_OFFSET, v18), + DEFINE_FPU_PSEUDO(d19, 8, FPU_D_PSEUDO_REG_ENDIAN_OFFSET, v19), + DEFINE_FPU_PSEUDO(d20, 8, FPU_D_PSEUDO_REG_ENDIAN_OFFSET, v20), + DEFINE_FPU_PSEUDO(d21, 8, FPU_D_PSEUDO_REG_ENDIAN_OFFSET, v21), + DEFINE_FPU_PSEUDO(d22, 8, FPU_D_PSEUDO_REG_ENDIAN_OFFSET, v22), + DEFINE_FPU_PSEUDO(d23, 8, FPU_D_PSEUDO_REG_ENDIAN_OFFSET, v23), + DEFINE_FPU_PSEUDO(d24, 8, FPU_D_PSEUDO_REG_ENDIAN_OFFSET, v24), + DEFINE_FPU_PSEUDO(d25, 8, FPU_D_PSEUDO_REG_ENDIAN_OFFSET, v25), + DEFINE_FPU_PSEUDO(d26, 8, FPU_D_PSEUDO_REG_ENDIAN_OFFSET, v26), + DEFINE_FPU_PSEUDO(d27, 8, FPU_D_PSEUDO_REG_ENDIAN_OFFSET, v27), + DEFINE_FPU_PSEUDO(d28, 8, FPU_D_PSEUDO_REG_ENDIAN_OFFSET, v28), + DEFINE_FPU_PSEUDO(d29, 8, FPU_D_PSEUDO_REG_ENDIAN_OFFSET, v29), + DEFINE_FPU_PSEUDO(d30, 8, FPU_D_PSEUDO_REG_ENDIAN_OFFSET, v30), + DEFINE_FPU_PSEUDO(d31, 8, FPU_D_PSEUDO_REG_ENDIAN_OFFSET, v31), + + // DEFINE_MISC_REGS(name, size, TYPE, lldb kind) + DEFINE_MISC_REGS(fpsr, 4, FPU, fpu_fpsr), + DEFINE_MISC_REGS(fpcr, 4, FPU, fpu_fpcr), + DEFINE_MISC_REGS(far, 8, EXC, exc_far), + DEFINE_MISC_REGS(esr, 4, EXC, exc_esr), + DEFINE_MISC_REGS(exception, 4, EXC, exc_exception), {DEFINE_DBG(bvr, 0)}, {DEFINE_DBG(bvr, 1)}, diff --git a/source/Plugins/Process/Utility/StopInfoMachException.cpp b/source/Plugins/Process/Utility/StopInfoMachException.cpp index 588015a51ef1..6d03bd534f37 100644 --- a/source/Plugins/Process/Utility/StopInfoMachException.cpp +++ b/source/Plugins/Process/Utility/StopInfoMachException.cpp @@ -30,331 +30,266 @@ using namespace lldb; using namespace lldb_private; const char *StopInfoMachException::GetDescription() { - if (m_description.empty() && m_value != 0) { - ExecutionContext exe_ctx(m_thread_wp.lock()); - Target *target = exe_ctx.GetTargetPtr(); - const llvm::Triple::ArchType cpu = - target ? target->GetArchitecture().GetMachine() - : llvm::Triple::UnknownArch; - - const char *exc_desc = nullptr; - const char *code_label = "code"; - const char *code_desc = nullptr; - const char *subcode_label = "subcode"; - const char *subcode_desc = nullptr; + if (!m_description.empty()) + return m_description.c_str(); + if (GetValue() == eStopReasonInvalid) + return "invalid stop reason!"; + + ExecutionContext exe_ctx(m_thread_wp.lock()); + Target *target = exe_ctx.GetTargetPtr(); + const llvm::Triple::ArchType cpu = + target ? target->GetArchitecture().GetMachine() + : llvm::Triple::UnknownArch; + + const char *exc_desc = nullptr; + const char *code_label = "code"; + const char *code_desc = nullptr; + const char *subcode_label = "subcode"; + const char *subcode_desc = nullptr; #if defined(__APPLE__) - char code_desc_buf[32]; - char subcode_desc_buf[32]; + char code_desc_buf[32]; + char subcode_desc_buf[32]; #endif - switch (m_value) { - case 1: // EXC_BAD_ACCESS - exc_desc = "EXC_BAD_ACCESS"; - subcode_label = "address"; - switch (cpu) { - case llvm::Triple::x86: - case llvm::Triple::x86_64: - switch (m_exc_code) { - case 0xd: - code_desc = "EXC_I386_GPFLT"; - m_exc_data_count = 1; - break; - } - break; - case llvm::Triple::arm: - case llvm::Triple::thumb: - switch (m_exc_code) { - case 0x101: - code_desc = "EXC_ARM_DA_ALIGN"; - break; - case 0x102: - code_desc = "EXC_ARM_DA_DEBUG"; - break; - } + switch (m_value) { + case 1: // EXC_BAD_ACCESS + exc_desc = "EXC_BAD_ACCESS"; + subcode_label = "address"; + switch (cpu) { + case llvm::Triple::x86: + case llvm::Triple::x86_64: + switch (m_exc_code) { + case 0xd: + code_desc = "EXC_I386_GPFLT"; + m_exc_data_count = 1; break; - - case llvm::Triple::ppc: - case llvm::Triple::ppc64: - switch (m_exc_code) { - case 0x101: - code_desc = "EXC_PPC_VM_PROT_READ"; - break; - case 0x102: - code_desc = "EXC_PPC_BADSPACE"; - break; - case 0x103: - code_desc = "EXC_PPC_UNALIGNED"; - break; - } + } + break; + case llvm::Triple::arm: + case llvm::Triple::thumb: + switch (m_exc_code) { + case 0x101: + code_desc = "EXC_ARM_DA_ALIGN"; break; - - default: + case 0x102: + code_desc = "EXC_ARM_DA_DEBUG"; break; } break; - case 2: // EXC_BAD_INSTRUCTION - exc_desc = "EXC_BAD_INSTRUCTION"; - switch (cpu) { - case llvm::Triple::x86: - case llvm::Triple::x86_64: - if (m_exc_code == 1) - code_desc = "EXC_I386_INVOP"; - break; + default: + break; + } + break; + + case 2: // EXC_BAD_INSTRUCTION + exc_desc = "EXC_BAD_INSTRUCTION"; + switch (cpu) { + case llvm::Triple::x86: + case llvm::Triple::x86_64: + if (m_exc_code == 1) + code_desc = "EXC_I386_INVOP"; + break; - case llvm::Triple::ppc: - case llvm::Triple::ppc64: - switch (m_exc_code) { - case 1: - code_desc = "EXC_PPC_INVALID_SYSCALL"; - break; - case 2: - code_desc = "EXC_PPC_UNIPL_INST"; - break; - case 3: - code_desc = "EXC_PPC_PRIVINST"; - break; - case 4: - code_desc = "EXC_PPC_PRIVREG"; - break; - case 5: - code_desc = "EXC_PPC_TRACE"; - break; - case 6: - code_desc = "EXC_PPC_PERFMON"; - break; - } - break; + case llvm::Triple::arm: + case llvm::Triple::thumb: + if (m_exc_code == 1) + code_desc = "EXC_ARM_UNDEFINED"; + break; - case llvm::Triple::arm: - case llvm::Triple::thumb: - if (m_exc_code == 1) - code_desc = "EXC_ARM_UNDEFINED"; + default: + break; + } + break; + + case 3: // EXC_ARITHMETIC + exc_desc = "EXC_ARITHMETIC"; + switch (cpu) { + case llvm::Triple::x86: + case llvm::Triple::x86_64: + switch (m_exc_code) { + case 1: + code_desc = "EXC_I386_DIV"; break; - - default: + case 2: + code_desc = "EXC_I386_INTO"; break; - } - break; - - case 3: // EXC_ARITHMETIC - exc_desc = "EXC_ARITHMETIC"; - switch (cpu) { - case llvm::Triple::x86: - case llvm::Triple::x86_64: - switch (m_exc_code) { - case 1: - code_desc = "EXC_I386_DIV"; - break; - case 2: - code_desc = "EXC_I386_INTO"; - break; - case 3: - code_desc = "EXC_I386_NOEXT"; - break; - case 4: - code_desc = "EXC_I386_EXTOVR"; - break; - case 5: - code_desc = "EXC_I386_EXTERR"; - break; - case 6: - code_desc = "EXC_I386_EMERR"; - break; - case 7: - code_desc = "EXC_I386_BOUND"; - break; - case 8: - code_desc = "EXC_I386_SSEEXTERR"; - break; - } + case 3: + code_desc = "EXC_I386_NOEXT"; break; - - case llvm::Triple::ppc: - case llvm::Triple::ppc64: - switch (m_exc_code) { - case 1: - code_desc = "EXC_PPC_OVERFLOW"; - break; - case 2: - code_desc = "EXC_PPC_ZERO_DIVIDE"; - break; - case 3: - code_desc = "EXC_PPC_FLT_INEXACT"; - break; - case 4: - code_desc = "EXC_PPC_FLT_ZERO_DIVIDE"; - break; - case 5: - code_desc = "EXC_PPC_FLT_UNDERFLOW"; - break; - case 6: - code_desc = "EXC_PPC_FLT_OVERFLOW"; - break; - case 7: - code_desc = "EXC_PPC_FLT_NOT_A_NUMBER"; - break; - } + case 4: + code_desc = "EXC_I386_EXTOVR"; break; - - default: + case 5: + code_desc = "EXC_I386_EXTERR"; + break; + case 6: + code_desc = "EXC_I386_EMERR"; + break; + case 7: + code_desc = "EXC_I386_BOUND"; + break; + case 8: + code_desc = "EXC_I386_SSEEXTERR"; break; } break; - case 4: // EXC_EMULATION - exc_desc = "EXC_EMULATION"; + default: break; + } + break; - case 5: // EXC_SOFTWARE - exc_desc = "EXC_SOFTWARE"; - if (m_exc_code == 0x10003) { - subcode_desc = "EXC_SOFT_SIGNAL"; - subcode_label = "signo"; + case 4: // EXC_EMULATION + exc_desc = "EXC_EMULATION"; + break; + + case 5: // EXC_SOFTWARE + exc_desc = "EXC_SOFTWARE"; + if (m_exc_code == 0x10003) { + subcode_desc = "EXC_SOFT_SIGNAL"; + subcode_label = "signo"; + } + break; + + case 6: // EXC_BREAKPOINT + { + exc_desc = "EXC_BREAKPOINT"; + switch (cpu) { + case llvm::Triple::x86: + case llvm::Triple::x86_64: + switch (m_exc_code) { + case 1: + code_desc = "EXC_I386_SGL"; + break; + case 2: + code_desc = "EXC_I386_BPT"; + break; } break; - case 6: // EXC_BREAKPOINT - { - exc_desc = "EXC_BREAKPOINT"; - switch (cpu) { - case llvm::Triple::x86: - case llvm::Triple::x86_64: - switch (m_exc_code) { - case 1: - code_desc = "EXC_I386_SGL"; - break; - case 2: - code_desc = "EXC_I386_BPT"; - break; - } + case llvm::Triple::arm: + case llvm::Triple::thumb: + switch (m_exc_code) { + case 0x101: + code_desc = "EXC_ARM_DA_ALIGN"; break; - - case llvm::Triple::ppc: - case llvm::Triple::ppc64: - switch (m_exc_code) { - case 1: - code_desc = "EXC_PPC_BREAKPOINT"; - break; - } + case 0x102: + code_desc = "EXC_ARM_DA_DEBUG"; break; - - case llvm::Triple::arm: - case llvm::Triple::thumb: - switch (m_exc_code) { - case 0x101: - code_desc = "EXC_ARM_DA_ALIGN"; - break; - case 0x102: - code_desc = "EXC_ARM_DA_DEBUG"; - break; - case 1: - code_desc = "EXC_ARM_BREAKPOINT"; - break; - // FIXME temporary workaround, exc_code 0 does not really mean - // EXC_ARM_BREAKPOINT - case 0: - code_desc = "EXC_ARM_BREAKPOINT"; - break; - } + case 1: + code_desc = "EXC_ARM_BREAKPOINT"; break; - - default: + // FIXME temporary workaround, exc_code 0 does not really mean + // EXC_ARM_BREAKPOINT + case 0: + code_desc = "EXC_ARM_BREAKPOINT"; break; } - } break; - - case 7: - exc_desc = "EXC_SYSCALL"; break; - case 8: - exc_desc = "EXC_MACH_SYSCALL"; + default: break; + } + } break; - case 9: - exc_desc = "EXC_RPC_ALERT"; - break; + case 7: + exc_desc = "EXC_SYSCALL"; + break; - case 10: - exc_desc = "EXC_CRASH"; - break; - case 11: - exc_desc = "EXC_RESOURCE"; + case 8: + exc_desc = "EXC_MACH_SYSCALL"; + break; + + case 9: + exc_desc = "EXC_RPC_ALERT"; + break; + + case 10: + exc_desc = "EXC_CRASH"; + break; + case 11: + exc_desc = "EXC_RESOURCE"; #if defined(__APPLE__) - { - int resource_type = EXC_RESOURCE_DECODE_RESOURCE_TYPE(m_exc_code); - - code_label = "limit"; - code_desc = code_desc_buf; - subcode_label = "observed"; - subcode_desc = subcode_desc_buf; - - switch (resource_type) { - case RESOURCE_TYPE_CPU: - exc_desc = "EXC_RESOURCE RESOURCE_TYPE_CPU"; - snprintf(code_desc_buf, sizeof(code_desc_buf), "%d%%", - (int)EXC_RESOURCE_CPUMONITOR_DECODE_PERCENTAGE(m_exc_code)); - snprintf(subcode_desc_buf, sizeof(subcode_desc_buf), "%d%%", - (int)EXC_RESOURCE_CPUMONITOR_DECODE_PERCENTAGE_OBSERVED(m_exc_subcode)); - break; - case RESOURCE_TYPE_WAKEUPS: - exc_desc = "EXC_RESOURCE RESOURCE_TYPE_WAKEUPS"; - snprintf(code_desc_buf, sizeof(code_desc_buf), "%d w/s", + { + int resource_type = EXC_RESOURCE_DECODE_RESOURCE_TYPE(m_exc_code); + + code_label = "limit"; + code_desc = code_desc_buf; + subcode_label = "observed"; + subcode_desc = subcode_desc_buf; + + switch (resource_type) { + case RESOURCE_TYPE_CPU: + exc_desc = "EXC_RESOURCE RESOURCE_TYPE_CPU"; + snprintf(code_desc_buf, sizeof(code_desc_buf), "%d%%", + (int)EXC_RESOURCE_CPUMONITOR_DECODE_PERCENTAGE(m_exc_code)); + snprintf(subcode_desc_buf, sizeof(subcode_desc_buf), "%d%%", + (int)EXC_RESOURCE_CPUMONITOR_DECODE_PERCENTAGE_OBSERVED( + m_exc_subcode)); + break; + case RESOURCE_TYPE_WAKEUPS: + exc_desc = "EXC_RESOURCE RESOURCE_TYPE_WAKEUPS"; + snprintf( + code_desc_buf, sizeof(code_desc_buf), "%d w/s", (int)EXC_RESOURCE_CPUMONITOR_DECODE_WAKEUPS_PERMITTED(m_exc_code)); - snprintf(subcode_desc_buf, sizeof(subcode_desc_buf), "%d w/s", - (int)EXC_RESOURCE_CPUMONITOR_DECODE_WAKEUPS_OBSERVED(m_exc_subcode)); - break; - case RESOURCE_TYPE_MEMORY: - exc_desc = "EXC_RESOURCE RESOURCE_TYPE_MEMORY"; - snprintf(code_desc_buf, sizeof(code_desc_buf), "%d MB", - (int)EXC_RESOURCE_HWM_DECODE_LIMIT(m_exc_code)); - subcode_desc = nullptr; - subcode_label = "unused"; - break; - case RESOURCE_TYPE_IO: - exc_desc = "EXC_RESOURCE RESOURCE_TYPE_IO"; - snprintf(code_desc_buf, sizeof(code_desc_buf), "%d MB", - (int)EXC_RESOURCE_IO_DECODE_LIMIT(m_exc_code)); - snprintf(subcode_desc_buf, sizeof(subcode_desc_buf), "%d MB", - (int)EXC_RESOURCE_IO_OBSERVED(m_exc_subcode));; - break; - } - } + snprintf(subcode_desc_buf, sizeof(subcode_desc_buf), "%d w/s", + (int)EXC_RESOURCE_CPUMONITOR_DECODE_WAKEUPS_OBSERVED( + m_exc_subcode)); + break; + case RESOURCE_TYPE_MEMORY: + exc_desc = "EXC_RESOURCE RESOURCE_TYPE_MEMORY"; + snprintf(code_desc_buf, sizeof(code_desc_buf), "%d MB", + (int)EXC_RESOURCE_HWM_DECODE_LIMIT(m_exc_code)); + subcode_desc = nullptr; + subcode_label = "unused"; + break; +#if defined(RESOURCE_TYPE_IO) + // RESOURCE_TYPE_IO is introduced in macOS SDK 10.12. + case RESOURCE_TYPE_IO: + exc_desc = "EXC_RESOURCE RESOURCE_TYPE_IO"; + snprintf(code_desc_buf, sizeof(code_desc_buf), "%d MB", + (int)EXC_RESOURCE_IO_DECODE_LIMIT(m_exc_code)); + snprintf(subcode_desc_buf, sizeof(subcode_desc_buf), "%d MB", + (int)EXC_RESOURCE_IO_OBSERVED(m_exc_subcode)); + ; + break; #endif - break; - case 12: - exc_desc = "EXC_GUARD"; - break; + } } +#endif + break; + case 12: + exc_desc = "EXC_GUARD"; + break; + } - StreamString strm; + StreamString strm; - if (exc_desc) - strm.PutCString(exc_desc); - else - strm.Printf("EXC_??? (%" PRIu64 ")", m_value); + if (exc_desc) + strm.PutCString(exc_desc); + else + strm.Printf("EXC_??? (%" PRIu64 ")", m_value); - if (m_exc_data_count >= 1) { - if (code_desc) - strm.Printf(" (%s=%s", code_label, code_desc); - else - strm.Printf(" (%s=%" PRIu64, code_label, m_exc_code); - } + if (m_exc_data_count >= 1) { + if (code_desc) + strm.Printf(" (%s=%s", code_label, code_desc); + else + strm.Printf(" (%s=%" PRIu64, code_label, m_exc_code); + } - if (m_exc_data_count >= 2) { - if (subcode_desc) - strm.Printf(", %s=%s", subcode_label, subcode_desc); - else - strm.Printf(", %s=0x%" PRIx64, subcode_label, m_exc_subcode); - } + if (m_exc_data_count >= 2) { + if (subcode_desc) + strm.Printf(", %s=%s", subcode_label, subcode_desc); + else + strm.Printf(", %s=0x%" PRIx64, subcode_label, m_exc_subcode); + } - if (m_exc_data_count > 0) - strm.PutChar(')'); + if (m_exc_data_count > 0) + strm.PutChar(')'); - m_description = strm.GetString(); - } + m_description = strm.GetString(); return m_description.c_str(); } @@ -362,141 +297,62 @@ StopInfoSP StopInfoMachException::CreateStopReasonWithMachException( Thread &thread, uint32_t exc_type, uint32_t exc_data_count, uint64_t exc_code, uint64_t exc_sub_code, uint64_t exc_sub_sub_code, bool pc_already_adjusted, bool adjust_pc_if_needed) { - if (exc_type != 0) { - uint32_t pc_decrement = 0; - ExecutionContext exe_ctx(thread.shared_from_this()); - Target *target = exe_ctx.GetTargetPtr(); - const llvm::Triple::ArchType cpu = - target ? target->GetArchitecture().GetMachine() - : llvm::Triple::UnknownArch; - - switch (exc_type) { - case 1: // EXC_BAD_ACCESS - break; - - case 2: // EXC_BAD_INSTRUCTION - switch (cpu) { - case llvm::Triple::ppc: - case llvm::Triple::ppc64: - switch (exc_code) { - case 1: // EXC_PPC_INVALID_SYSCALL - case 2: // EXC_PPC_UNIPL_INST - case 3: // EXC_PPC_PRIVINST - case 4: // EXC_PPC_PRIVREG - break; - case 5: // EXC_PPC_TRACE - return StopInfo::CreateStopReasonToTrace(thread); - case 6: // EXC_PPC_PERFMON - break; - } - break; - - default: - break; - } - break; - - case 3: // EXC_ARITHMETIC - case 4: // EXC_EMULATION - break; - - case 5: // EXC_SOFTWARE - if (exc_code == 0x10003) // EXC_SOFT_SIGNAL - { - if (exc_sub_code == 5) { - // On MacOSX, a SIGTRAP can signify that a process has called exec, - // so we should check with our dynamic loader to verify. - ProcessSP process_sp(thread.GetProcess()); - if (process_sp) { - DynamicLoader *dynamic_loader = process_sp->GetDynamicLoader(); - if (dynamic_loader && dynamic_loader->ProcessDidExec()) { - // The program was re-exec'ed - return StopInfo::CreateStopReasonWithExec(thread); - } - // if (!process_did_exec) - // { - // // We have a SIGTRAP, make sure we - // didn't exec by checking - // // for the PC being at - // "_dyld_start"... - // lldb::StackFrameSP frame_sp - // (thread.GetStackFrameAtIndex(0)); - // if (frame_sp) - // { - // const Symbol *symbol = - // frame_sp->GetSymbolContext(eSymbolContextSymbol).symbol; - // if (symbol) - // { - // if (symbol->GetName() == - // ConstString("_dyld_start")) - // process_did_exec = true; - // } - // } - // } + if (exc_type == 0) + return StopInfoSP(); + + uint32_t pc_decrement = 0; + ExecutionContext exe_ctx(thread.shared_from_this()); + Target *target = exe_ctx.GetTargetPtr(); + const llvm::Triple::ArchType cpu = + target ? target->GetArchitecture().GetMachine() + : llvm::Triple::UnknownArch; + + switch (exc_type) { + case 1: // EXC_BAD_ACCESS + case 2: // EXC_BAD_INSTRUCTION + case 3: // EXC_ARITHMETIC + case 4: // EXC_EMULATION + break; + + case 5: // EXC_SOFTWARE + if (exc_code == 0x10003) // EXC_SOFT_SIGNAL + { + if (exc_sub_code == 5) { + // On MacOSX, a SIGTRAP can signify that a process has called exec, + // so we should check with our dynamic loader to verify. + ProcessSP process_sp(thread.GetProcess()); + if (process_sp) { + DynamicLoader *dynamic_loader = process_sp->GetDynamicLoader(); + if (dynamic_loader && dynamic_loader->ProcessDidExec()) { + // The program was re-exec'ed + return StopInfo::CreateStopReasonWithExec(thread); } } - return StopInfo::CreateStopReasonWithSignal(thread, exc_sub_code); } - break; - - case 6: // EXC_BREAKPOINT - { - bool is_actual_breakpoint = false; - bool is_trace_if_actual_breakpoint_missing = false; - switch (cpu) { - case llvm::Triple::x86: - case llvm::Triple::x86_64: - if (exc_code == 1) // EXC_I386_SGL - { - if (!exc_sub_code) { - // This looks like a plain trap. - // Have to check if there is a breakpoint here as well. When you - // single-step onto a trap, the single step stops you not to trap. - // Since we also do that check below, let's just use that logic. - is_actual_breakpoint = true; - is_trace_if_actual_breakpoint_missing = true; - } else { - - // It's a watchpoint, then. - // The exc_sub_code indicates the data break address. - lldb::WatchpointSP wp_sp; - if (target) - wp_sp = target->GetWatchpointList().FindByAddress( - (lldb::addr_t)exc_sub_code); - if (wp_sp && wp_sp->IsEnabled()) { - // Debugserver may piggyback the hardware index of the fired - // watchpoint in the exception data. Set the hardware index if - // that's the case. - if (exc_data_count >= 3) - wp_sp->SetHardwareIndex((uint32_t)exc_sub_sub_code); - return StopInfo::CreateStopReasonWithWatchpointID(thread, - wp_sp->GetID()); - } - } - } else if (exc_code == 2 || // EXC_I386_BPT - exc_code == 3) // EXC_I386_BPTFLT - { - // KDP returns EXC_I386_BPTFLT for trace breakpoints - if (exc_code == 3) - is_trace_if_actual_breakpoint_missing = true; - + return StopInfo::CreateStopReasonWithSignal(thread, exc_sub_code); + } + break; + + case 6: // EXC_BREAKPOINT + { + bool is_actual_breakpoint = false; + bool is_trace_if_actual_breakpoint_missing = false; + switch (cpu) { + case llvm::Triple::x86: + case llvm::Triple::x86_64: + if (exc_code == 1) // EXC_I386_SGL + { + if (!exc_sub_code) { + // This looks like a plain trap. + // Have to check if there is a breakpoint here as well. When you + // single-step onto a trap, the single step stops you not to trap. + // Since we also do that check below, let's just use that logic. is_actual_breakpoint = true; - if (!pc_already_adjusted) - pc_decrement = 1; - } - break; - - case llvm::Triple::ppc: - case llvm::Triple::ppc64: - is_actual_breakpoint = exc_code == 1; // EXC_PPC_BREAKPOINT - break; + is_trace_if_actual_breakpoint_missing = true; + } else { - case llvm::Triple::arm: - case llvm::Triple::thumb: - if (exc_code == 0x102) // EXC_ARM_DA_DEBUG - { - // It's a watchpoint, then, if the exc_sub_code indicates a - // known/enabled data break address from our watchpoint list. + // It's a watchpoint, then. + // The exc_sub_code indicates the data break address. lldb::WatchpointSP wp_sp; if (target) wp_sp = target->GetWatchpointList().FindByAddress( @@ -509,116 +365,148 @@ StopInfoSP StopInfoMachException::CreateStopReasonWithMachException( wp_sp->SetHardwareIndex((uint32_t)exc_sub_sub_code); return StopInfo::CreateStopReasonWithWatchpointID(thread, wp_sp->GetID()); - } else { - is_actual_breakpoint = true; - is_trace_if_actual_breakpoint_missing = true; } - } else if (exc_code == 1) // EXC_ARM_BREAKPOINT - { - is_actual_breakpoint = true; - is_trace_if_actual_breakpoint_missing = true; - } else if (exc_code == 0) // FIXME not EXC_ARM_BREAKPOINT but a kernel - // is currently returning this so accept it - // as indicating a breakpoint until the - // kernel is fixed - { - is_actual_breakpoint = true; - is_trace_if_actual_breakpoint_missing = true; } - break; + } else if (exc_code == 2 || // EXC_I386_BPT + exc_code == 3) // EXC_I386_BPTFLT + { + // KDP returns EXC_I386_BPTFLT for trace breakpoints + if (exc_code == 3) + is_trace_if_actual_breakpoint_missing = true; - case llvm::Triple::aarch64: { - if (exc_code == 1 && exc_sub_code == 0) // EXC_ARM_BREAKPOINT - { - // This is hit when we single instruction step aka MDSCR_EL1 SS bit 0 - // is set - is_actual_breakpoint = false; + is_actual_breakpoint = true; + if (!pc_already_adjusted) + pc_decrement = 1; + } + break; + + case llvm::Triple::arm: + case llvm::Triple::thumb: + if (exc_code == 0x102) // EXC_ARM_DA_DEBUG + { + // It's a watchpoint, then, if the exc_sub_code indicates a + // known/enabled data break address from our watchpoint list. + lldb::WatchpointSP wp_sp; + if (target) + wp_sp = target->GetWatchpointList().FindByAddress( + (lldb::addr_t)exc_sub_code); + if (wp_sp && wp_sp->IsEnabled()) { + // Debugserver may piggyback the hardware index of the fired + // watchpoint in the exception data. Set the hardware index if + // that's the case. + if (exc_data_count >= 3) + wp_sp->SetHardwareIndex((uint32_t)exc_sub_sub_code); + return StopInfo::CreateStopReasonWithWatchpointID(thread, + wp_sp->GetID()); + } else { + is_actual_breakpoint = true; is_trace_if_actual_breakpoint_missing = true; } - if (exc_code == 0x102) // EXC_ARM_DA_DEBUG - { - // It's a watchpoint, then, if the exc_sub_code indicates a - // known/enabled data break address from our watchpoint list. - lldb::WatchpointSP wp_sp; - if (target) - wp_sp = target->GetWatchpointList().FindByAddress( - (lldb::addr_t)exc_sub_code); - if (wp_sp && wp_sp->IsEnabled()) { - // Debugserver may piggyback the hardware index of the fired - // watchpoint in the exception data. Set the hardware index if - // that's the case. - if (exc_data_count >= 3) - wp_sp->SetHardwareIndex((uint32_t)exc_sub_sub_code); - return StopInfo::CreateStopReasonWithWatchpointID(thread, - wp_sp->GetID()); - } - // EXC_ARM_DA_DEBUG seems to be reused for EXC_BREAKPOINT as well as - // EXC_BAD_ACCESS - if (thread.GetTemporaryResumeState() == eStateStepping) - return StopInfo::CreateStopReasonToTrace(thread); - } - // It looks like exc_sub_code has the 4 bytes of the instruction that - // triggered the exception, i.e. our breakpoint opcode - is_actual_breakpoint = exc_code == 1; - break; + } else if (exc_code == 1) // EXC_ARM_BREAKPOINT + { + is_actual_breakpoint = true; + is_trace_if_actual_breakpoint_missing = true; + } else if (exc_code == 0) // FIXME not EXC_ARM_BREAKPOINT but a kernel + // is currently returning this so accept it + // as indicating a breakpoint until the + // kernel is fixed + { + is_actual_breakpoint = true; + is_trace_if_actual_breakpoint_missing = true; } + break; - default: - break; + case llvm::Triple::aarch64_32: + case llvm::Triple::aarch64: { + if (exc_code == 1 && exc_sub_code == 0) // EXC_ARM_BREAKPOINT + { + // This is hit when we single instruction step aka MDSCR_EL1 SS bit 0 + // is set + is_actual_breakpoint = false; + is_trace_if_actual_breakpoint_missing = true; } - - if (is_actual_breakpoint) { - RegisterContextSP reg_ctx_sp(thread.GetRegisterContext()); - addr_t pc = reg_ctx_sp->GetPC() - pc_decrement; - - ProcessSP process_sp(thread.CalculateProcess()); - - lldb::BreakpointSiteSP bp_site_sp; - if (process_sp) - bp_site_sp = process_sp->GetBreakpointSiteList().FindByAddress(pc); - if (bp_site_sp && bp_site_sp->IsEnabled()) { - // Update the PC if we were asked to do so, but only do so if we find - // a breakpoint that we know about cause this could be a trap - // instruction in the code - if (pc_decrement > 0 && adjust_pc_if_needed) - reg_ctx_sp->SetPC(pc); - - // 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 we have an operating system - // plug-in, we might have set a thread specific breakpoint using the - // operating system thread ID, so we can't make any assumptions about - // the thread ID so we must always report the breakpoint regardless - // of the thread. - if (bp_site_sp->ValidForThisThread(&thread) || - thread.GetProcess()->GetOperatingSystem() != nullptr) - return StopInfo::CreateStopReasonWithBreakpointSiteID( - thread, bp_site_sp->GetID()); - else if (is_trace_if_actual_breakpoint_missing) - return StopInfo::CreateStopReasonToTrace(thread); - else - return StopInfoSP(); + if (exc_code == 0x102) // EXC_ARM_DA_DEBUG + { + // It's a watchpoint, then, if the exc_sub_code indicates a + // known/enabled data break address from our watchpoint list. + lldb::WatchpointSP wp_sp; + if (target) + wp_sp = target->GetWatchpointList().FindByAddress( + (lldb::addr_t)exc_sub_code); + if (wp_sp && wp_sp->IsEnabled()) { + // Debugserver may piggyback the hardware index of the fired + // watchpoint in the exception data. Set the hardware index if + // that's the case. + if (exc_data_count >= 3) + wp_sp->SetHardwareIndex((uint32_t)exc_sub_sub_code); + return StopInfo::CreateStopReasonWithWatchpointID(thread, + wp_sp->GetID()); } - - // Don't call this a trace if we weren't single stepping this thread. - if (is_trace_if_actual_breakpoint_missing && - thread.GetTemporaryResumeState() == eStateStepping) { + // EXC_ARM_DA_DEBUG seems to be reused for EXC_BREAKPOINT as well as + // EXC_BAD_ACCESS + if (thread.GetTemporaryResumeState() == eStateStepping) return StopInfo::CreateStopReasonToTrace(thread); - } } - } break; + // It looks like exc_sub_code has the 4 bytes of the instruction that + // triggered the exception, i.e. our breakpoint opcode + is_actual_breakpoint = exc_code == 1; + break; + } - case 7: // EXC_SYSCALL - case 8: // EXC_MACH_SYSCALL - case 9: // EXC_RPC_ALERT - case 10: // EXC_CRASH + default: break; } - return StopInfoSP(new StopInfoMachException( - thread, exc_type, exc_data_count, exc_code, exc_sub_code)); + if (is_actual_breakpoint) { + RegisterContextSP reg_ctx_sp(thread.GetRegisterContext()); + addr_t pc = reg_ctx_sp->GetPC() - pc_decrement; + + ProcessSP process_sp(thread.CalculateProcess()); + + lldb::BreakpointSiteSP bp_site_sp; + if (process_sp) + bp_site_sp = process_sp->GetBreakpointSiteList().FindByAddress(pc); + if (bp_site_sp && bp_site_sp->IsEnabled()) { + // Update the PC if we were asked to do so, but only do so if we find + // a breakpoint that we know about cause this could be a trap + // instruction in the code + if (pc_decrement > 0 && adjust_pc_if_needed) + reg_ctx_sp->SetPC(pc); + + // 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 we have an operating system + // plug-in, we might have set a thread specific breakpoint using the + // operating system thread ID, so we can't make any assumptions about + // the thread ID so we must always report the breakpoint regardless + // of the thread. + if (bp_site_sp->ValidForThisThread(&thread) || + thread.GetProcess()->GetOperatingSystem() != nullptr) + return StopInfo::CreateStopReasonWithBreakpointSiteID( + thread, bp_site_sp->GetID()); + else if (is_trace_if_actual_breakpoint_missing) + return StopInfo::CreateStopReasonToTrace(thread); + else + return StopInfoSP(); + } + + // Don't call this a trace if we weren't single stepping this thread. + if (is_trace_if_actual_breakpoint_missing && + thread.GetTemporaryResumeState() == eStateStepping) { + return StopInfo::CreateStopReasonToTrace(thread); + } + } + } break; + + case 7: // EXC_SYSCALL + case 8: // EXC_MACH_SYSCALL + case 9: // EXC_RPC_ALERT + case 10: // EXC_CRASH + break; } - return StopInfoSP(); + + return StopInfoSP(new StopInfoMachException(thread, exc_type, exc_data_count, + exc_code, exc_sub_code)); } diff --git a/source/Plugins/Process/Utility/UnwindLLDB.cpp b/source/Plugins/Process/Utility/UnwindLLDB.cpp index 38209fb24948..74fc90e88547 100644 --- a/source/Plugins/Process/Utility/UnwindLLDB.cpp +++ b/source/Plugins/Process/Utility/UnwindLLDB.cpp @@ -104,8 +104,8 @@ bool UnwindLLDB::AddFirstFrame() { unwind_done: Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_UNWIND)); if (log) { - log->Printf("th%d Unwind of this thread is complete.", - m_thread.GetIndexID()); + LLDB_LOGF(log, "th%d Unwind of this thread is complete.", + m_thread.GetIndexID()); } m_unwind_complete = true; return false; @@ -140,10 +140,10 @@ UnwindLLDB::CursorSP UnwindLLDB::GetOneMoreFrame(ABI *abi) { // is going to blow out the stack space. If we're still unwinding at that // point, we're probably never going to finish. if (cur_idx >= max_stack_depth) { - if (log) - log->Printf("%*sFrame %d unwound too many frames, assuming unwind has " - "gone astray, stopping.", - cur_idx < 100 ? cur_idx : 100, "", cur_idx); + LLDB_LOGF(log, + "%*sFrame %d unwound too many frames, assuming unwind has " + "gone astray, stopping.", + cur_idx < 100 ? cur_idx : 100, "", cur_idx); return nullptr; } @@ -161,9 +161,8 @@ UnwindLLDB::CursorSP UnwindLLDB::GetOneMoreFrame(ABI *abi) { return GetOneMoreFrame(abi); } - if (log) - log->Printf("%*sFrame %d did not get a RegisterContext, stopping.", - cur_idx < 100 ? cur_idx : 100, "", cur_idx); + LLDB_LOGF(log, "%*sFrame %d did not get a RegisterContext, stopping.", + cur_idx < 100 ? cur_idx : 100, "", cur_idx); return nullptr; } @@ -181,10 +180,10 @@ UnwindLLDB::CursorSP UnwindLLDB::GetOneMoreFrame(ABI *abi) { return GetOneMoreFrame(abi); } - if (log) - log->Printf("%*sFrame %d invalid RegisterContext for this frame, " - "stopping stack walk", - cur_idx < 100 ? cur_idx : 100, "", cur_idx); + LLDB_LOGF(log, + "%*sFrame %d invalid RegisterContext for this frame, " + "stopping stack walk", + cur_idx < 100 ? cur_idx : 100, "", cur_idx); return nullptr; } if (!reg_ctx_sp->GetCFA(cursor_sp->cfa)) { @@ -201,10 +200,9 @@ UnwindLLDB::CursorSP UnwindLLDB::GetOneMoreFrame(ABI *abi) { return GetOneMoreFrame(abi); } - if (log) - log->Printf( - "%*sFrame %d did not get CFA for this frame, stopping stack walk", - cur_idx < 100 ? cur_idx : 100, "", cur_idx); + LLDB_LOGF(log, + "%*sFrame %d did not get CFA for this frame, stopping stack walk", + cur_idx < 100 ? cur_idx : 100, "", cur_idx); return nullptr; } if (abi && !abi->CallFrameAddressIsValid(cursor_sp->cfa)) { @@ -230,17 +228,17 @@ UnwindLLDB::CursorSP UnwindLLDB::GetOneMoreFrame(ABI *abi) { return GetOneMoreFrame(abi); } - if (log) - log->Printf("%*sFrame %d did not get a valid CFA for this frame, " - "stopping stack walk", - cur_idx < 100 ? cur_idx : 100, "", cur_idx); + LLDB_LOGF(log, + "%*sFrame %d did not get a valid CFA for this frame, " + "stopping stack walk", + cur_idx < 100 ? cur_idx : 100, "", cur_idx); return nullptr; } else { - if (log) - log->Printf("%*sFrame %d had a bad CFA value but we switched the " - "UnwindPlan being used and got one that looks more " - "realistic.", - cur_idx < 100 ? cur_idx : 100, "", cur_idx); + LLDB_LOGF(log, + "%*sFrame %d had a bad CFA value but we switched the " + "UnwindPlan being used and got one that looks more " + "realistic.", + cur_idx < 100 ? cur_idx : 100, "", cur_idx); } } } @@ -258,10 +256,9 @@ UnwindLLDB::CursorSP UnwindLLDB::GetOneMoreFrame(ABI *abi) { return GetOneMoreFrame(abi); } - if (log) - log->Printf( - "%*sFrame %d did not get PC for this frame, stopping stack walk", - cur_idx < 100 ? cur_idx : 100, "", cur_idx); + LLDB_LOGF(log, + "%*sFrame %d did not get PC for this frame, stopping stack walk", + cur_idx < 100 ? cur_idx : 100, "", cur_idx); return nullptr; } if (abi && !abi->CodeAddressIsValid(cursor_sp->start_pc)) { @@ -278,18 +275,17 @@ UnwindLLDB::CursorSP UnwindLLDB::GetOneMoreFrame(ABI *abi) { return GetOneMoreFrame(abi); } - if (log) - log->Printf("%*sFrame %d did not get a valid PC, stopping stack walk", - cur_idx < 100 ? cur_idx : 100, "", cur_idx); + LLDB_LOGF(log, "%*sFrame %d did not get a valid PC, stopping stack walk", + cur_idx < 100 ? cur_idx : 100, "", cur_idx); return nullptr; } // Infinite loop where the current cursor is the same as the previous one... if (prev_frame->start_pc == cursor_sp->start_pc && prev_frame->cfa == cursor_sp->cfa) { - if (log) - log->Printf("th%d pc of this frame is the same as the previous frame and " - "CFAs for both frames are identical -- stopping unwind", - m_thread.GetIndexID()); + LLDB_LOGF(log, + "th%d pc of this frame is the same as the previous frame and " + "CFAs for both frames are identical -- stopping unwind", + m_thread.GetIndexID()); return nullptr; } @@ -337,9 +333,8 @@ bool UnwindLLDB::AddOneMoreFrame(ABI *abi) { new_frame = GetOneMoreFrame(abi); if (new_frame == nullptr) { - if (log) - log->Printf("th%d Unwind of this thread is complete.", - m_thread.GetIndexID()); + LLDB_LOGF(log, "th%d Unwind of this thread is complete.", + m_thread.GetIndexID()); m_unwind_complete = true; return false; } @@ -395,7 +390,8 @@ bool UnwindLLDB::AddOneMoreFrame(ABI *abi) { return true; } -bool UnwindLLDB::DoGetFrameInfoAtIndex(uint32_t idx, addr_t &cfa, addr_t &pc) { +bool UnwindLLDB::DoGetFrameInfoAtIndex(uint32_t idx, addr_t &cfa, addr_t &pc, + bool &behaves_like_zeroth_frame) { if (m_frames.size() == 0) { if (!AddFirstFrame()) return false; @@ -410,6 +406,24 @@ bool UnwindLLDB::DoGetFrameInfoAtIndex(uint32_t idx, addr_t &cfa, addr_t &pc) { if (idx < m_frames.size()) { cfa = m_frames[idx]->cfa; pc = m_frames[idx]->start_pc; + if (idx == 0) { + // Frame zero always behaves like it. + behaves_like_zeroth_frame = true; + } else if (m_frames[idx - 1]->reg_ctx_lldb_sp->IsTrapHandlerFrame()) { + // This could be an asynchronous signal, thus the + // pc might point to the interrupted instruction rather + // than a post-call instruction + behaves_like_zeroth_frame = true; + } else if (m_frames[idx]->reg_ctx_lldb_sp->IsTrapHandlerFrame()) { + // This frame may result from signal processing installing + // a pointer to the first byte of a signal-return trampoline + // in the return address slot of the frame below, so this + // too behaves like the zeroth frame (i.e. the pc might not + // be pointing just past a call in it) + behaves_like_zeroth_frame = true; + } else { + behaves_like_zeroth_frame = false; + } return true; } return false; diff --git a/source/Plugins/Process/Utility/UnwindLLDB.h b/source/Plugins/Process/Utility/UnwindLLDB.h index c512929c185b..ff5db39730b5 100644 --- a/source/Plugins/Process/Utility/UnwindLLDB.h +++ b/source/Plugins/Process/Utility/UnwindLLDB.h @@ -73,7 +73,8 @@ protected: uint32_t DoGetFrameCount() override; bool DoGetFrameInfoAtIndex(uint32_t frame_idx, lldb::addr_t &cfa, - lldb::addr_t &start_pc) override; + lldb::addr_t &start_pc, + bool &behaves_like_zeroth_frame) override; lldb::RegisterContextSP DoCreateRegisterContextForFrame(lldb_private::StackFrame *frame) override; diff --git a/source/Plugins/Process/Utility/UnwindMacOSXFrameBackchain.cpp b/source/Plugins/Process/Utility/UnwindMacOSXFrameBackchain.cpp index 7dc5a5f5fdd1..558edeec1a37 100644 --- a/source/Plugins/Process/Utility/UnwindMacOSXFrameBackchain.cpp +++ b/source/Plugins/Process/Utility/UnwindMacOSXFrameBackchain.cpp @@ -43,9 +43,8 @@ uint32_t UnwindMacOSXFrameBackchain::DoGetFrameCount() { return m_cursors.size(); } -bool UnwindMacOSXFrameBackchain::DoGetFrameInfoAtIndex(uint32_t idx, - addr_t &cfa, - addr_t &pc) { +bool UnwindMacOSXFrameBackchain::DoGetFrameInfoAtIndex( + uint32_t idx, addr_t &cfa, addr_t &pc, bool &behaves_like_zeroth_frame) { const uint32_t frame_count = GetFrameCount(); if (idx < frame_count) { if (m_cursors[idx].pc == LLDB_INVALID_ADDRESS) @@ -55,6 +54,7 @@ bool UnwindMacOSXFrameBackchain::DoGetFrameInfoAtIndex(uint32_t idx, pc = m_cursors[idx].pc; cfa = m_cursors[idx].fp; + behaves_like_zeroth_frame = (idx == 0); return true; } diff --git a/source/Plugins/Process/Utility/UnwindMacOSXFrameBackchain.h b/source/Plugins/Process/Utility/UnwindMacOSXFrameBackchain.h index 2208bcc2f2e4..f0bde90a53be 100644 --- a/source/Plugins/Process/Utility/UnwindMacOSXFrameBackchain.h +++ b/source/Plugins/Process/Utility/UnwindMacOSXFrameBackchain.h @@ -26,7 +26,8 @@ protected: uint32_t DoGetFrameCount() override; bool DoGetFrameInfoAtIndex(uint32_t frame_idx, lldb::addr_t &cfa, - lldb::addr_t &pc) override; + lldb::addr_t &pc, + bool &behaves_like_zeroth_frame) override; lldb::RegisterContextSP DoCreateRegisterContextForFrame(lldb_private::StackFrame *frame) override; diff --git a/source/Plugins/Process/elf-core/ProcessElfCore.cpp b/source/Plugins/Process/elf-core/ProcessElfCore.cpp index 980169e16c51..ab23589ae9a9 100644 --- a/source/Plugins/Process/elf-core/ProcessElfCore.cpp +++ b/source/Plugins/Process/elf-core/ProcessElfCore.cpp @@ -33,6 +33,7 @@ #include "ThreadElfCore.h" using namespace lldb_private; +namespace ELF = llvm::ELF; ConstString ProcessElfCore::GetPluginNameStatic() { static ConstString g_name("elf-core"); @@ -117,16 +118,20 @@ lldb::addr_t ProcessElfCore::AddAddressRangeFromLoadSegment( FileRange file_range(header.p_offset, header.p_filesz); VMRangeToFileOffset::Entry range_entry(addr, header.p_memsz, file_range); - VMRangeToFileOffset::Entry *last_entry = m_core_aranges.Back(); - if (last_entry && last_entry->GetRangeEnd() == range_entry.GetRangeBase() && - last_entry->data.GetRangeEnd() == range_entry.data.GetRangeBase() && - last_entry->GetByteSize() == last_entry->data.GetByteSize()) { - last_entry->SetRangeEnd(range_entry.GetRangeEnd()); - last_entry->data.SetRangeEnd(range_entry.data.GetRangeEnd()); - } else { - m_core_aranges.Append(range_entry); + // Only add to m_core_aranges if the file size is non zero. Some core files + // have PT_LOAD segments for all address ranges, but set f_filesz to zero for + // the .text sections since they can be retrieved from the object files. + if (header.p_filesz > 0) { + VMRangeToFileOffset::Entry *last_entry = m_core_aranges.Back(); + if (last_entry && last_entry->GetRangeEnd() == range_entry.GetRangeBase() && + last_entry->data.GetRangeEnd() == range_entry.data.GetRangeBase() && + last_entry->GetByteSize() == last_entry->data.GetByteSize()) { + last_entry->SetRangeEnd(range_entry.GetRangeEnd()); + last_entry->data.SetRangeEnd(range_entry.data.GetRangeEnd()); + } else { + m_core_aranges.Append(range_entry); + } } - // Keep a separate map of permissions that that isn't coalesced so all ranges // are maintained. const uint32_t permissions = @@ -417,7 +422,7 @@ static void ParseFreeBSDPrStatus(ThreadData &thread_data, Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_PROCESS)); if (log) { if (pr_version > 1) - log->Printf("FreeBSD PRSTATUS unexpected version %d", pr_version); + LLDB_LOGF(log, "FreeBSD PRSTATUS unexpected version %d", pr_version); } // Skip padding, pr_statussz, pr_gregsetsz, pr_fpregsetsz, pr_osreldate @@ -521,8 +526,8 @@ llvm::Error ProcessElfCore::parseFreeBSDNotes(llvm::ArrayRef<CoreNote> notes) { if (note.info.n_name != "FreeBSD") continue; - if ((note.info.n_type == FREEBSD::NT_PRSTATUS && have_prstatus) || - (note.info.n_type == FREEBSD::NT_PRPSINFO && have_prpsinfo)) { + if ((note.info.n_type == ELF::NT_PRSTATUS && have_prstatus) || + (note.info.n_type == ELF::NT_PRPSINFO && have_prpsinfo)) { assert(thread_data.gpregset.GetByteSize() > 0); // Add the new thread to thread list m_thread_data.push_back(thread_data); @@ -532,19 +537,19 @@ llvm::Error ProcessElfCore::parseFreeBSDNotes(llvm::ArrayRef<CoreNote> notes) { } switch (note.info.n_type) { - case FREEBSD::NT_PRSTATUS: + case ELF::NT_PRSTATUS: have_prstatus = true; ParseFreeBSDPrStatus(thread_data, note.data, GetArchitecture()); break; - case FREEBSD::NT_PRPSINFO: + case ELF::NT_PRPSINFO: have_prpsinfo = true; break; - case FREEBSD::NT_THRMISC: { + case ELF::NT_FREEBSD_THRMISC: { lldb::offset_t offset = 0; thread_data.name = note.data.GetCStr(&offset, 20); break; } - case FREEBSD::NT_PROCSTAT_AUXV: + case ELF::NT_FREEBSD_PROCSTAT_AUXV: // FIXME: FreeBSD sticks an int at the beginning of the note m_auxv = DataExtractor(note.data, 4, note.data.GetByteSize() - 4); break; @@ -771,8 +776,8 @@ llvm::Error ProcessElfCore::parseLinuxNotes(llvm::ArrayRef<CoreNote> notes) { if (note.info.n_name != "CORE" && note.info.n_name != "LINUX") continue; - if ((note.info.n_type == LINUX::NT_PRSTATUS && have_prstatus) || - (note.info.n_type == LINUX::NT_PRPSINFO && have_prpsinfo)) { + if ((note.info.n_type == ELF::NT_PRSTATUS && have_prstatus) || + (note.info.n_type == ELF::NT_PRPSINFO && have_prpsinfo)) { assert(thread_data.gpregset.GetByteSize() > 0); // Add the new thread to thread list m_thread_data.push_back(thread_data); @@ -782,7 +787,7 @@ llvm::Error ProcessElfCore::parseLinuxNotes(llvm::ArrayRef<CoreNote> notes) { } switch (note.info.n_type) { - case LINUX::NT_PRSTATUS: { + case ELF::NT_PRSTATUS: { have_prstatus = true; ELFLinuxPrStatus prstatus; Status status = prstatus.Parse(note.data, arch); @@ -795,7 +800,7 @@ llvm::Error ProcessElfCore::parseLinuxNotes(llvm::ArrayRef<CoreNote> notes) { thread_data.gpregset = DataExtractor(note.data, header_size, len); break; } - case LINUX::NT_PRPSINFO: { + case ELF::NT_PRPSINFO: { have_prpsinfo = true; ELFLinuxPrPsInfo prpsinfo; Status status = prpsinfo.Parse(note.data, arch); @@ -805,7 +810,7 @@ llvm::Error ProcessElfCore::parseLinuxNotes(llvm::ArrayRef<CoreNote> notes) { SetID(prpsinfo.pr_pid); break; } - case LINUX::NT_SIGINFO: { + case ELF::NT_SIGINFO: { ELFLinuxSigInfo siginfo; Status status = siginfo.Parse(note.data, arch); if (status.Fail()) @@ -813,7 +818,7 @@ llvm::Error ProcessElfCore::parseLinuxNotes(llvm::ArrayRef<CoreNote> notes) { thread_data.signo = siginfo.si_signo; break; } - case LINUX::NT_FILE: { + case ELF::NT_FILE: { m_nt_file_entries.clear(); lldb::offset_t offset = 0; const uint64_t count = note.data.GetAddress(&offset); @@ -832,7 +837,7 @@ llvm::Error ProcessElfCore::parseLinuxNotes(llvm::ArrayRef<CoreNote> notes) { } break; } - case LINUX::NT_AUXV: + case ELF::NT_AUXV: m_auxv = note.data; break; default: diff --git a/source/Plugins/Process/elf-core/RegisterUtilities.h b/source/Plugins/Process/elf-core/RegisterUtilities.h index d3b3373150f8..49ad425db445 100644 --- a/source/Plugins/Process/elf-core/RegisterUtilities.h +++ b/source/Plugins/Process/elf-core/RegisterUtilities.h @@ -11,21 +11,11 @@ #include "Plugins/ObjectFile/ELF/ObjectFileELF.h" #include "lldb/Utility/DataExtractor.h" +#include "llvm/BinaryFormat/ELF.h" namespace lldb_private { /// Core files PT_NOTE segment descriptor types -namespace FREEBSD { -enum { - NT_PRSTATUS = 1, - NT_FPREGSET, - NT_PRPSINFO, - NT_THRMISC = 7, - NT_PROCSTAT_AUXV = 16, - NT_PPC_VMX = 0x100 -}; -} - namespace NETBSD { enum { NT_PROCINFO = 1, NT_AUXV = 2 }; @@ -76,22 +66,6 @@ enum { }; } -namespace LINUX { -enum { - NT_PRSTATUS = 1, - NT_FPREGSET, - NT_PRPSINFO, - NT_TASKSTRUCT, - NT_PLATFORM, - NT_AUXV, - NT_FILE = 0x46494c45, - NT_SIGINFO = 0x53494749, - NT_PPC_VMX = 0x100, - NT_PPC_VSX = 0x102, - NT_PRXFPREG = 0x46e62b7f, -}; -} - struct CoreNote { ELFNote info; DataExtractor data; @@ -122,24 +96,24 @@ DataExtractor getRegset(llvm::ArrayRef<CoreNote> Notes, llvm::ArrayRef<RegsetDesc> RegsetDescs); constexpr RegsetDesc FPR_Desc[] = { - {llvm::Triple::FreeBSD, llvm::Triple::UnknownArch, FREEBSD::NT_FPREGSET}, + {llvm::Triple::FreeBSD, llvm::Triple::UnknownArch, llvm::ELF::NT_FPREGSET}, // In a i386 core file NT_FPREGSET is present, but it's not the result // of the FXSAVE instruction like in 64 bit files. // The result from FXSAVE is in NT_PRXFPREG for i386 core files - {llvm::Triple::Linux, llvm::Triple::x86, LINUX::NT_PRXFPREG}, - {llvm::Triple::Linux, llvm::Triple::UnknownArch, LINUX::NT_FPREGSET}, + {llvm::Triple::Linux, llvm::Triple::x86, llvm::ELF::NT_PRXFPREG}, + {llvm::Triple::Linux, llvm::Triple::UnknownArch, llvm::ELF::NT_FPREGSET}, {llvm::Triple::NetBSD, llvm::Triple::aarch64, NETBSD::AARCH64::NT_FPREGS}, {llvm::Triple::NetBSD, llvm::Triple::x86_64, NETBSD::AMD64::NT_FPREGS}, {llvm::Triple::OpenBSD, llvm::Triple::UnknownArch, OPENBSD::NT_FPREGS}, }; constexpr RegsetDesc PPC_VMX_Desc[] = { - {llvm::Triple::FreeBSD, llvm::Triple::UnknownArch, FREEBSD::NT_PPC_VMX}, - {llvm::Triple::Linux, llvm::Triple::UnknownArch, LINUX::NT_PPC_VMX}, + {llvm::Triple::FreeBSD, llvm::Triple::UnknownArch, llvm::ELF::NT_PPC_VMX}, + {llvm::Triple::Linux, llvm::Triple::UnknownArch, llvm::ELF::NT_PPC_VMX}, }; constexpr RegsetDesc PPC_VSX_Desc[] = { - {llvm::Triple::Linux, llvm::Triple::UnknownArch, LINUX::NT_PPC_VSX}, + {llvm::Triple::Linux, llvm::Triple::UnknownArch, llvm::ELF::NT_PPC_VSX}, }; } // namespace lldb_private diff --git a/source/Plugins/Process/elf-core/ThreadElfCore.cpp b/source/Plugins/Process/elf-core/ThreadElfCore.cpp index a5d1fc4a7bff..508c8a3108a6 100644 --- a/source/Plugins/Process/elf-core/ThreadElfCore.cpp +++ b/source/Plugins/Process/elf-core/ThreadElfCore.cpp @@ -181,9 +181,8 @@ ThreadElfCore::CreateRegisterContextForFrame(StackFrame *frame) { } if (!reg_interface) { - if (log) - log->Printf("elf-core::%s:: Architecture(%d) or OS(%d) not supported", - __FUNCTION__, arch.GetMachine(), arch.GetTriple().getOS()); + LLDB_LOGF(log, "elf-core::%s:: Architecture(%d) or OS(%d) not supported", + __FUNCTION__, arch.GetMachine(), arch.GetTriple().getOS()); assert(false && "Architecture or OS not supported"); } diff --git a/source/Plugins/Process/gdb-remote/GDBRemoteClientBase.cpp b/source/Plugins/Process/gdb-remote/GDBRemoteClientBase.cpp index fe7ef6b3acea..064bbde8442e 100644 --- a/source/Plugins/Process/gdb-remote/GDBRemoteClientBase.cpp +++ b/source/Plugins/Process/gdb-remote/GDBRemoteClientBase.cpp @@ -63,18 +63,16 @@ StateType GDBRemoteClientBase::SendContinuePacketAndWaitForResponse( case PacketResult::Success: break; default: - if (log) - log->Printf("GDBRemoteClientBase::%s () ReadPacket(...) => false", - __FUNCTION__); + LLDB_LOGF(log, "GDBRemoteClientBase::%s () ReadPacket(...) => false", + __FUNCTION__); return eStateInvalid; } if (response.Empty()) return eStateInvalid; const char stop_type = response.GetChar(); - if (log) - log->Printf("GDBRemoteClientBase::%s () got packet: %s", __FUNCTION__, - response.GetStringRef().c_str()); + LLDB_LOGF(log, "GDBRemoteClientBase::%s () got packet: %s", __FUNCTION__, + response.GetStringRef().data()); switch (stop_type) { case 'W': @@ -84,9 +82,8 @@ StateType GDBRemoteClientBase::SendContinuePacketAndWaitForResponse( // ERROR return eStateInvalid; default: - if (log) - log->Printf("GDBRemoteClientBase::%s () unrecognized async packet", - __FUNCTION__); + LLDB_LOGF(log, "GDBRemoteClientBase::%s () unrecognized async packet", + __FUNCTION__); return eStateInvalid; case 'O': { std::string inferior_stdout; @@ -162,10 +159,10 @@ GDBRemoteClientBase::SendPacketAndWaitForResponse( if (!lock) { if (Log *log = ProcessGDBRemoteLog::GetLogIfAllCategoriesSet(GDBR_LOG_PROCESS)) - log->Printf("GDBRemoteClientBase::%s failed to get mutex, not sending " - "packet '%.*s' (send_async=%d)", - __FUNCTION__, int(payload.size()), payload.data(), - send_async); + LLDB_LOGF(log, + "GDBRemoteClientBase::%s failed to get mutex, not sending " + "packet '%.*s' (send_async=%d)", + __FUNCTION__, int(payload.size()), payload.data(), send_async); return PacketResult::ErrorSendFailed; } @@ -181,10 +178,10 @@ GDBRemoteClientBase::SendPacketAndReceiveResponseWithOutputSupport( if (!lock) { if (Log *log = ProcessGDBRemoteLog::GetLogIfAllCategoriesSet(GDBR_LOG_PROCESS)) - log->Printf("GDBRemoteClientBase::%s failed to get mutex, not sending " - "packet '%.*s' (send_async=%d)", - __FUNCTION__, int(payload.size()), payload.data(), - send_async); + LLDB_LOGF(log, + "GDBRemoteClientBase::%s failed to get mutex, not sending " + "packet '%.*s' (send_async=%d)", + __FUNCTION__, int(payload.size()), payload.data(), send_async); return PacketResult::ErrorSendFailed; } @@ -214,13 +211,13 @@ GDBRemoteClientBase::SendPacketAndWaitForResponseNoLock( return packet_result; // Response says it wasn't valid Log *log = ProcessGDBRemoteLog::GetLogIfAllCategoriesSet(GDBR_LOG_PACKETS); - if (log) - log->Printf( - "error: packet with payload \"%.*s\" got invalid response \"%s\": %s", - int(payload.size()), payload.data(), response.GetStringRef().c_str(), - (i == (max_response_retries - 1)) - ? "using invalid response and giving up" - : "ignoring response and waiting for another"); + LLDB_LOGF( + log, + "error: packet with payload \"%.*s\" got invalid response \"%s\": %s", + int(payload.size()), payload.data(), response.GetStringRef().data(), + (i == (max_response_retries - 1)) + ? "using invalid response and giving up" + : "ignoring response and waiting for another"); } return packet_result; } @@ -228,16 +225,14 @@ GDBRemoteClientBase::SendPacketAndWaitForResponseNoLock( bool GDBRemoteClientBase::SendvContPacket(llvm::StringRef payload, StringExtractorGDBRemote &response) { Log *log(ProcessGDBRemoteLog::GetLogIfAllCategoriesSet(GDBR_LOG_PROCESS)); - if (log) - log->Printf("GDBRemoteCommunicationClient::%s ()", __FUNCTION__); + LLDB_LOGF(log, "GDBRemoteCommunicationClient::%s ()", __FUNCTION__); // we want to lock down packet sending while we continue Lock lock(*this, true); - if (log) - log->Printf( - "GDBRemoteCommunicationClient::%s () sending vCont packet: %.*s", - __FUNCTION__, int(payload.size()), payload.data()); + LLDB_LOGF(log, + "GDBRemoteCommunicationClient::%s () sending vCont packet: %.*s", + __FUNCTION__, int(payload.size()), payload.data()); if (SendPacketNoLock(payload) != PacketResult::Success) return false; @@ -315,18 +310,16 @@ void GDBRemoteClientBase::ContinueLock::unlock() { GDBRemoteClientBase::ContinueLock::LockResult GDBRemoteClientBase::ContinueLock::lock() { Log *log = ProcessGDBRemoteLog::GetLogIfAllCategoriesSet(GDBR_LOG_PROCESS); - if (log) - log->Printf("GDBRemoteClientBase::ContinueLock::%s() resuming with %s", - __FUNCTION__, m_comm.m_continue_packet.c_str()); + LLDB_LOGF(log, "GDBRemoteClientBase::ContinueLock::%s() resuming with %s", + __FUNCTION__, m_comm.m_continue_packet.c_str()); lldbassert(!m_acquired); std::unique_lock<std::mutex> lock(m_comm.m_mutex); m_comm.m_cv.wait(lock, [this] { return m_comm.m_async_count == 0; }); if (m_comm.m_should_stop) { m_comm.m_should_stop = false; - if (log) - log->Printf("GDBRemoteClientBase::ContinueLock::%s() cancelled", - __FUNCTION__); + LLDB_LOGF(log, "GDBRemoteClientBase::ContinueLock::%s() cancelled", + __FUNCTION__); return LockResult::Cancelled; } if (m_comm.SendPacketNoLock(m_comm.m_continue_packet) != @@ -368,9 +361,8 @@ void GDBRemoteClientBase::Lock::SyncWithContinueThread(bool interrupt) { size_t bytes_written = m_comm.Write(&ctrl_c, 1, status, nullptr); if (bytes_written == 0) { --m_comm.m_async_count; - if (log) - log->Printf("GDBRemoteClientBase::Lock::Lock failed to send " - "interrupt packet"); + LLDB_LOGF(log, "GDBRemoteClientBase::Lock::Lock failed to send " + "interrupt packet"); return; } if (log) diff --git a/source/Plugins/Process/gdb-remote/GDBRemoteClientBase.h b/source/Plugins/Process/gdb-remote/GDBRemoteClientBase.h index 54f69e8caac6..ea294ffcef26 100644 --- a/source/Plugins/Process/gdb-remote/GDBRemoteClientBase.h +++ b/source/Plugins/Process/gdb-remote/GDBRemoteClientBase.h @@ -24,12 +24,10 @@ public: virtual void HandleAsyncMisc(llvm::StringRef data) = 0; virtual void HandleStopReply() = 0; - // ========================================================================= /// Process asynchronously-received structured data. /// /// \param[in] data /// The complete data packet, expected to start with JSON-async. - // ========================================================================= virtual void HandleAsyncStructuredDataPacket(llvm::StringRef data) = 0; }; @@ -83,42 +81,48 @@ protected: virtual void OnRunPacketSent(bool first); private: - // Variables handling synchronization between the Continue thread and any - // other threads - // wishing to send packets over the connection. Either the continue thread has - // control over - // the connection (m_is_running == true) or the connection is free for an - // arbitrary number of - // other senders to take which indicate their interest by incrementing - // m_async_count. - // Semantics of individual states: - // - m_continue_packet == false, m_async_count == 0: connection is free - // - m_continue_packet == true, m_async_count == 0: only continue thread is - // present - // - m_continue_packet == true, m_async_count > 0: continue thread has - // control, async threads - // should interrupt it and wait for it to set m_continue_packet to false - // - m_continue_packet == false, m_async_count > 0: async threads have - // control, continue - // thread needs to wait for them to finish (m_async_count goes down to 0). + /// Variables handling synchronization between the Continue thread and any + /// other threads wishing to send packets over the connection. Either the + /// continue thread has control over the connection (m_is_running == true) or + /// the connection is free for an arbitrary number of other senders to take + /// which indicate their interest by incrementing m_async_count. + /// + /// Semantics of individual states: + /// + /// - m_continue_packet == false, m_async_count == 0: + /// connection is free + /// - m_continue_packet == true, m_async_count == 0: + /// only continue thread is present + /// - m_continue_packet == true, m_async_count > 0: + /// continue thread has control, async threads should interrupt it and wait + /// for it to set m_continue_packet to false + /// - m_continue_packet == false, m_async_count > 0: + /// async threads have control, continue thread needs to wait for them to + /// finish (m_async_count goes down to 0). + /// @{ std::mutex m_mutex; std::condition_variable m_cv; - // Packet with which to resume after an async interrupt. Can be changed by an - // async thread - // e.g. to inject a signal. + + /// Packet with which to resume after an async interrupt. Can be changed by + /// an async thread e.g. to inject a signal. std::string m_continue_packet; - // When was the interrupt packet sent. Used to make sure we time out if the - // stub does not - // respond to interrupt requests. + + /// When was the interrupt packet sent. Used to make sure we time out if the + /// stub does not respond to interrupt requests. std::chrono::time_point<std::chrono::steady_clock> m_interrupt_time; + + /// Number of threads interested in sending. uint32_t m_async_count; + + /// Whether the continue thread has control. bool m_is_running; - bool m_should_stop; // Whether we should resume after a stop. - // end of continue thread synchronization block - // This handles the synchronization between individual async threads. For now - // they just use a - // simple mutex. + /// Whether we should resume after a stop. + bool m_should_stop; + /// @} + + /// This handles the synchronization between individual async threads. For + /// now they just use a simple mutex. std::recursive_mutex m_async_mutex; bool ShouldStop(const UnixSignals &signals, diff --git a/source/Plugins/Process/gdb-remote/GDBRemoteCommunication.cpp b/source/Plugins/Process/gdb-remote/GDBRemoteCommunication.cpp index 11052eff948f..144ae103faa4 100644 --- a/source/Plugins/Process/gdb-remote/GDBRemoteCommunication.cpp +++ b/source/Plugins/Process/gdb-remote/GDBRemoteCommunication.cpp @@ -14,6 +14,7 @@ #include <sys/stat.h> #include "lldb/Core/StreamFile.h" +#include "lldb/Host/Config.h" #include "lldb/Host/ConnectionFileDescriptor.h" #include "lldb/Host/FileSystem.h" #include "lldb/Host/Host.h" @@ -38,6 +39,8 @@ #if defined(__APPLE__) #define DEBUGSERVER_BASENAME "debugserver" +#elif defined(_WIN32) +#define DEBUGSERVER_BASENAME "lldb-server.exe" #else #define DEBUGSERVER_BASENAME "lldb-server" #endif @@ -99,10 +102,8 @@ size_t GDBRemoteCommunication::SendAck() { ConnectionStatus status = eConnectionStatusSuccess; char ch = '+'; const size_t bytes_written = Write(&ch, 1, status, nullptr); - if (log) - log->Printf("<%4" PRIu64 "> send packet: %c", (uint64_t)bytes_written, ch); - m_history.AddPacket(ch, GDBRemoteCommunicationHistory::ePacketTypeSend, - bytes_written); + LLDB_LOGF(log, "<%4" PRIu64 "> send packet: %c", (uint64_t)bytes_written, ch); + m_history.AddPacket(ch, GDBRemotePacket::ePacketTypeSend, bytes_written); return bytes_written; } @@ -111,10 +112,8 @@ size_t GDBRemoteCommunication::SendNack() { ConnectionStatus status = eConnectionStatusSuccess; char ch = '-'; const size_t bytes_written = Write(&ch, 1, status, nullptr); - if (log) - log->Printf("<%4" PRIu64 "> send packet: %c", (uint64_t)bytes_written, ch); - m_history.AddPacket(ch, GDBRemoteCommunicationHistory::ePacketTypeSend, - bytes_written); + LLDB_LOGF(log, "<%4" PRIu64 "> send packet: %c", (uint64_t)bytes_written, ch); + m_history.AddPacket(ch, GDBRemotePacket::ePacketTypeSend, bytes_written); return bytes_written; } @@ -172,13 +171,12 @@ GDBRemoteCommunication::SendRawPacketNoLock(llvm::StringRef packet, strm.Printf("%*s", (int)3, p); log->PutString(strm.GetString()); } else - log->Printf("<%4" PRIu64 "> send packet: %.*s", (uint64_t)bytes_written, - (int)packet_length, packet_data); + LLDB_LOGF(log, "<%4" PRIu64 "> send packet: %.*s", + (uint64_t)bytes_written, (int)packet_length, packet_data); } m_history.AddPacket(packet.str(), packet_length, - GDBRemoteCommunicationHistory::ePacketTypeSend, - bytes_written); + GDBRemotePacket::ePacketTypeSend, bytes_written); if (bytes_written == packet_length) { if (!skip_ack && GetSendAcks()) @@ -186,9 +184,8 @@ GDBRemoteCommunication::SendRawPacketNoLock(llvm::StringRef packet, else return PacketResult::Success; } else { - if (log) - log->Printf("error: failed to send packet: %.*s", (int)packet_length, - packet_data); + LLDB_LOGF(log, "error: failed to send packet: %.*s", (int)packet_length, + packet_data); } } return PacketResult::ErrorSendFailed; @@ -332,11 +329,12 @@ GDBRemoteCommunication::WaitForPacketNoLock(StringExtractorGDBRemote &packet, std::string regex_str = "^"; regex_str += echo_packet; regex_str += "$"; - response_regex.Compile(regex_str); + response_regex = RegularExpression(regex_str); } else { echo_packet_len = ::snprintf(echo_packet, sizeof(echo_packet), "qC"); - response_regex.Compile(llvm::StringRef("^QC[0-9A-Fa-f]+$")); + response_regex = + RegularExpression(llvm::StringRef("^QC[0-9A-Fa-f]+$")); } PacketResult echo_packet_result = @@ -489,11 +487,10 @@ bool GDBRemoteCommunication::DecompressPacket() { llvm::StringRef(m_bytes).substr(1, hash_mark_idx - 1)); bool success = packet_checksum == actual_checksum; if (!success) { - if (log) - log->Printf( - "error: checksum mismatch: %.*s expected 0x%2.2x, got 0x%2.2x", - (int)(pkt_size), m_bytes.c_str(), (uint8_t)packet_checksum, - (uint8_t)actual_checksum); + LLDB_LOGF(log, + "error: checksum mismatch: %.*s expected 0x%2.2x, got 0x%2.2x", + (int)(pkt_size), m_bytes.c_str(), (uint8_t)packet_checksum, + (uint8_t)actual_checksum); } // Send the ack or nack if needed if (!success) { @@ -651,8 +648,8 @@ GDBRemoteCommunication::CheckForPacket(const uint8_t *src, size_t src_len, if (src && src_len > 0) { if (log && log->GetVerbose()) { StreamString s; - log->Printf("GDBRemoteCommunication::%s adding %u bytes: %.*s", - __FUNCTION__, (uint32_t)src_len, (uint32_t)src_len, src); + LLDB_LOGF(log, "GDBRemoteCommunication::%s adding %u bytes: %.*s", + __FUNCTION__, (uint32_t)src_len, (uint32_t)src_len, src); } m_bytes.append((const char *)src, src_len); } @@ -733,9 +730,8 @@ GDBRemoteCommunication::CheckForPacket(const uint8_t *src, size_t src_len, break; } } - if (log) - log->Printf("GDBRemoteCommunication::%s tossing %u junk bytes: '%.*s'", - __FUNCTION__, idx - 1, idx - 1, m_bytes.c_str()); + LLDB_LOGF(log, "GDBRemoteCommunication::%s tossing %u junk bytes: '%.*s'", + __FUNCTION__, idx - 1, idx - 1, m_bytes.c_str()); m_bytes.erase(0, idx - 1); } break; } @@ -752,7 +748,6 @@ GDBRemoteCommunication::CheckForPacket(const uint8_t *src, size_t src_len, size_t content_end = content_start + content_length; bool success = true; - std::string &packet_str = packet.GetStringRef(); if (log) { // If logging was just enabled and we have history, then dump out what // we have to the log so we get the historical context. The Dump() call @@ -800,25 +795,23 @@ GDBRemoteCommunication::CheckForPacket(const uint8_t *src, size_t src_len, log->PutString(strm.GetString()); } else { if (CompressionIsEnabled()) - log->Printf("<%4" PRIu64 ":%" PRIu64 "> read packet: %.*s", - (uint64_t)original_packet_size, (uint64_t)total_length, - (int)(total_length), m_bytes.c_str()); + LLDB_LOGF(log, "<%4" PRIu64 ":%" PRIu64 "> read packet: %.*s", + (uint64_t)original_packet_size, (uint64_t)total_length, + (int)(total_length), m_bytes.c_str()); else - log->Printf("<%4" PRIu64 "> read packet: %.*s", - (uint64_t)total_length, (int)(total_length), - m_bytes.c_str()); + LLDB_LOGF(log, "<%4" PRIu64 "> read packet: %.*s", + (uint64_t)total_length, (int)(total_length), + m_bytes.c_str()); } } m_history.AddPacket(m_bytes, total_length, - GDBRemoteCommunicationHistory::ePacketTypeRecv, - total_length); + GDBRemotePacket::ePacketTypeRecv, total_length); - // Clear packet_str in case there is some existing data in it. - packet_str.clear(); // Copy the packet from m_bytes to packet_str expanding the run-length // encoding in the process. Reserve enough byte for the most common case // (no RLE used) + std ::string packet_str; packet_str.reserve(m_bytes.length()); for (std::string::const_iterator c = m_bytes.begin() + content_start; c != m_bytes.begin() + content_end; ++c) { @@ -841,6 +834,7 @@ GDBRemoteCommunication::CheckForPacket(const uint8_t *src, size_t src_len, packet_str.push_back(*c); } } + packet = StringExtractorGDBRemote(packet_str); if (m_bytes[0] == '$' || m_bytes[0] == '%') { assert(checksum_idx < m_bytes.size()); @@ -853,11 +847,11 @@ GDBRemoteCommunication::CheckForPacket(const uint8_t *src, size_t src_len, llvm::StringRef(m_bytes).slice(content_start, content_end)); success = packet_checksum == actual_checksum; if (!success) { - if (log) - log->Printf("error: checksum mismatch: %.*s expected 0x%2.2x, " - "got 0x%2.2x", - (int)(total_length), m_bytes.c_str(), - (uint8_t)packet_checksum, (uint8_t)actual_checksum); + LLDB_LOGF(log, + "error: checksum mismatch: %.*s expected 0x%2.2x, " + "got 0x%2.2x", + (int)(total_length), m_bytes.c_str(), + (uint8_t)packet_checksum, (uint8_t)actual_checksum); } // Send the ack or nack if needed if (!success) @@ -867,9 +861,8 @@ GDBRemoteCommunication::CheckForPacket(const uint8_t *src, size_t src_len, } } else { success = false; - if (log) - log->Printf("error: invalid checksum in packet: '%s'\n", - m_bytes.c_str()); + LLDB_LOGF(log, "error: invalid checksum in packet: '%s'\n", + m_bytes.c_str()); } } @@ -933,10 +926,8 @@ Status GDBRemoteCommunication::StartDebugserverProcess( const char *url, Platform *platform, ProcessLaunchInfo &launch_info, uint16_t *port, const Args *inferior_args, int pass_comm_fd) { Log *log(ProcessGDBRemoteLog::GetLogIfAllCategoriesSet(GDBR_LOG_PROCESS)); - if (log) - log->Printf("GDBRemoteCommunication::%s(url=%s, port=%" PRIu16 ")", - __FUNCTION__, url ? url : "<empty>", - port ? *port : uint16_t(0)); + LLDB_LOGF(log, "GDBRemoteCommunication::%s(url=%s, port=%" PRIu16 ")", + __FUNCTION__, url ? url : "<empty>", port ? *port : uint16_t(0)); Status error; // If we locate debugserver, keep that located version around @@ -953,10 +944,10 @@ Status GDBRemoteCommunication::StartDebugserverProcess( if (!env_debugserver_path.empty()) { debugserver_file_spec.SetFile(env_debugserver_path, FileSpec::Style::native); - if (log) - log->Printf("GDBRemoteCommunication::%s() gdb-remote stub exe path set " - "from environment variable: %s", - __FUNCTION__, env_debugserver_path.c_str()); + LLDB_LOGF(log, + "GDBRemoteCommunication::%s() gdb-remote stub exe path set " + "from environment variable: %s", + __FUNCTION__, env_debugserver_path.c_str()); } else debugserver_file_spec = g_debugserver_file_spec; bool debugserver_exists = @@ -968,10 +959,9 @@ Status GDBRemoteCommunication::StartDebugserverProcess( debugserver_file_spec.AppendPathComponent(DEBUGSERVER_BASENAME); debugserver_exists = FileSystem::Instance().Exists(debugserver_file_spec); if (debugserver_exists) { - if (log) - log->Printf( - "GDBRemoteCommunication::%s() found gdb-remote stub exe '%s'", - __FUNCTION__, debugserver_file_spec.GetPath().c_str()); + LLDB_LOGF(log, + "GDBRemoteCommunication::%s() found gdb-remote stub exe '%s'", + __FUNCTION__, debugserver_file_spec.GetPath().c_str()); g_debugserver_file_spec = debugserver_file_spec; } else { @@ -985,10 +975,10 @@ Status GDBRemoteCommunication::StartDebugserverProcess( // exist debugserver_exists = true; } else { - if (log) - log->Printf("GDBRemoteCommunication::%s() could not find " - "gdb-remote stub exe '%s'", - __FUNCTION__, debugserver_file_spec.GetPath().c_str()); + LLDB_LOGF(log, + "GDBRemoteCommunication::%s() could not find " + "gdb-remote stub exe '%s'", + __FUNCTION__, debugserver_file_spec.GetPath().c_str()); } // Don't cache the platform specific GDB server binary as it could // change from platform to platform @@ -1052,10 +1042,10 @@ Status GDBRemoteCommunication::StartDebugserverProcess( error = socket_pipe.CreateWithUniqueName("debugserver-named-pipe", false, named_pipe_path); if (error.Fail()) { - if (log) - log->Printf("GDBRemoteCommunication::%s() " - "named pipe creation failed: %s", - __FUNCTION__, error.AsCString()); + LLDB_LOGF(log, + "GDBRemoteCommunication::%s() " + "named pipe creation failed: %s", + __FUNCTION__, error.AsCString()); return error; } debugserver_args.AppendArgument(llvm::StringRef("--named-pipe")); @@ -1065,10 +1055,10 @@ Status GDBRemoteCommunication::StartDebugserverProcess( // using using an unnamed pipe... error = socket_pipe.CreateNew(true); if (error.Fail()) { - if (log) - log->Printf("GDBRemoteCommunication::%s() " - "unnamed pipe creation failed: %s", - __FUNCTION__, error.AsCString()); + LLDB_LOGF(log, + "GDBRemoteCommunication::%s() " + "unnamed pipe creation failed: %s", + __FUNCTION__, error.AsCString()); return error; } pipe_t write = socket_pipe.GetWritePipe(); @@ -1081,10 +1071,10 @@ Status GDBRemoteCommunication::StartDebugserverProcess( // debugserver connect to us.. error = StartListenThread("127.0.0.1", 0); if (error.Fail()) { - if (log) - log->Printf("GDBRemoteCommunication::%s() unable to start listen " - "thread: %s", - __FUNCTION__, error.AsCString()); + LLDB_LOGF(log, + "GDBRemoteCommunication::%s() unable to start listen " + "thread: %s", + __FUNCTION__, error.AsCString()); return error; } @@ -1104,9 +1094,8 @@ Status GDBRemoteCommunication::StartDebugserverProcess( *port = port_; } else { error.SetErrorString("failed to bind to port 0 on 127.0.0.1"); - if (log) - log->Printf("GDBRemoteCommunication::%s() failed: %s", __FUNCTION__, - error.AsCString()); + LLDB_LOGF(log, "GDBRemoteCommunication::%s() failed: %s", + __FUNCTION__, error.AsCString()); return error; } } @@ -1148,10 +1137,10 @@ Status GDBRemoteCommunication::StartDebugserverProcess( if (has_env_var) { debugserver_args.AppendArgument(llvm::StringRef(extra_arg)); - if (log) - log->Printf("GDBRemoteCommunication::%s adding env var %s contents " - "to stub command line (%s)", - __FUNCTION__, env_var_name, extra_arg.c_str()); + LLDB_LOGF(log, + "GDBRemoteCommunication::%s adding env var %s contents " + "to stub command line (%s)", + __FUNCTION__, env_var_name, extra_arg.c_str()); } } while (has_env_var); @@ -1177,8 +1166,8 @@ Status GDBRemoteCommunication::StartDebugserverProcess( StreamString string_stream; Platform *const platform = nullptr; launch_info.Dump(string_stream, platform); - log->Printf("launch info for gdb-remote stub:\n%s", - string_stream.GetData()); + LLDB_LOGF(log, "launch info for gdb-remote stub:\n%s", + string_stream.GetData()); } error = Host::LaunchProcess(launch_info); @@ -1188,11 +1177,10 @@ Status GDBRemoteCommunication::StartDebugserverProcess( if (named_pipe_path.size() > 0) { error = socket_pipe.OpenAsReader(named_pipe_path, false); if (error.Fail()) - if (log) - log->Printf("GDBRemoteCommunication::%s() " - "failed to open named pipe %s for reading: %s", - __FUNCTION__, named_pipe_path.c_str(), - error.AsCString()); + LLDB_LOGF(log, + "GDBRemoteCommunication::%s() " + "failed to open named pipe %s for reading: %s", + __FUNCTION__, named_pipe_path.c_str(), error.AsCString()); } if (socket_pipe.CanWrite()) @@ -1209,24 +1197,22 @@ Status GDBRemoteCommunication::StartDebugserverProcess( uint16_t child_port = StringConvert::ToUInt32(port_cstr, 0); if (*port == 0 || *port == child_port) { *port = child_port; - if (log) - log->Printf("GDBRemoteCommunication::%s() " - "debugserver listens %u port", - __FUNCTION__, *port); + LLDB_LOGF(log, + "GDBRemoteCommunication::%s() " + "debugserver listens %u port", + __FUNCTION__, *port); } else { - if (log) - log->Printf("GDBRemoteCommunication::%s() " - "debugserver listening on port " - "%d but requested port was %d", - __FUNCTION__, (uint32_t)child_port, - (uint32_t)(*port)); + LLDB_LOGF(log, + "GDBRemoteCommunication::%s() " + "debugserver listening on port " + "%d but requested port was %d", + __FUNCTION__, (uint32_t)child_port, (uint32_t)(*port)); } } else { - if (log) - log->Printf("GDBRemoteCommunication::%s() " - "failed to read a port value from pipe %s: %s", - __FUNCTION__, named_pipe_path.c_str(), - error.AsCString()); + LLDB_LOGF(log, + "GDBRemoteCommunication::%s() " + "failed to read a port value from pipe %s: %s", + __FUNCTION__, named_pipe_path.c_str(), error.AsCString()); } socket_pipe.Close(); } @@ -1234,10 +1220,9 @@ Status GDBRemoteCommunication::StartDebugserverProcess( if (named_pipe_path.size() > 0) { const auto err = socket_pipe.Delete(named_pipe_path); if (err.Fail()) { - if (log) - log->Printf( - "GDBRemoteCommunication::%s failed to delete pipe %s: %s", - __FUNCTION__, named_pipe_path.c_str(), err.AsCString()); + LLDB_LOGF(log, + "GDBRemoteCommunication::%s failed to delete pipe %s: %s", + __FUNCTION__, named_pipe_path.c_str(), err.AsCString()); } } @@ -1249,9 +1234,8 @@ Status GDBRemoteCommunication::StartDebugserverProcess( } if (error.Fail()) { - if (log) - log->Printf("GDBRemoteCommunication::%s() failed: %s", __FUNCTION__, - error.AsCString()); + LLDB_LOGF(log, "GDBRemoteCommunication::%s() failed: %s", __FUNCTION__, + error.AsCString()); } return error; @@ -1351,7 +1335,7 @@ void GDBRemoteCommunication::AppendBytesToCache(const uint8_t *bytes, if (type == PacketType::Notify) { // put this packet into an event - const char *pdata = packet.GetStringRef().c_str(); + const char *pdata = packet.GetStringRef().data(); // as the communication class, we are a broadcaster and the async thread // is tuned to listen to us diff --git a/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.cpp b/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.cpp index 9797184026e0..feb9f0589cee 100644 --- a/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.cpp +++ b/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.cpp @@ -23,7 +23,6 @@ #include "lldb/Target/UnixSignals.h" #include "lldb/Utility/Args.h" #include "lldb/Utility/DataBufferHeap.h" -#include "lldb/Utility/JSON.h" #include "lldb/Utility/LLDBAssert.h" #include "lldb/Utility/Log.h" #include "lldb/Utility/State.h" @@ -35,17 +34,15 @@ #include "lldb/Utility/StringExtractorGDBRemote.h" #include "llvm/ADT/StringSwitch.h" +#include "llvm/Support/JSON.h" -#if defined(__APPLE__) -#ifndef HAVE_LIBCOMPRESSION -#define HAVE_LIBCOMPRESSION -#endif +#if defined(HAVE_LIBCOMPRESSION) #include <compression.h> #endif using namespace lldb; -using namespace lldb_private; using namespace lldb_private::process_gdb_remote; +using namespace lldb_private; using namespace std::chrono; // GDBRemoteCommunicationClient constructor @@ -342,7 +339,7 @@ void GDBRemoteCommunicationClient::GetRemoteQSupported() { // not, we assume no limit // build the qSupported packet - std::vector<std::string> features = {"xmlRegisters=i386,arm,mips"}; + std::vector<std::string> features = {"xmlRegisters=i386,arm,mips,arc"}; StreamString packet; packet.PutCString("qSupported"); for (uint32_t i = 0; i < features.size(); ++i) { @@ -354,7 +351,7 @@ void GDBRemoteCommunicationClient::GetRemoteQSupported() { if (SendPacketAndWaitForResponse(packet.GetString(), response, /*send_async=*/false) == PacketResult::Success) { - const char *response_cstr = response.GetStringRef().c_str(); + const char *response_cstr = response.GetStringRef().data(); // Hang on to the qSupported packet, so that platforms can do custom // configuration of the transport before attaching/launching the process. @@ -439,8 +436,7 @@ void GDBRemoteCommunicationClient::GetRemoteQSupported() { m_max_packet_size = UINT64_MAX; // Must have been a garbled response Log *log( ProcessGDBRemoteLog::GetLogIfAllCategoriesSet(GDBR_LOG_PROCESS)); - if (log) - log->Printf("Garbled PacketSize spec in qSupported response"); + LLDB_LOGF(log, "Garbled PacketSize spec in qSupported response"); } } } @@ -469,7 +465,7 @@ bool GDBRemoteCommunicationClient::GetVContSupported(char flavor) { m_supports_vCont_S = eLazyBoolNo; if (SendPacketAndWaitForResponse("vCont?", response, false) == PacketResult::Success) { - const char *response_cstr = response.GetStringRef().c_str(); + const char *response_cstr = response.GetStringRef().data(); if (::strstr(response_cstr, ";c")) m_supports_vCont_c = eLazyBoolYes; @@ -525,9 +521,10 @@ GDBRemoteCommunicationClient::SendThreadSpecificPacketAndWaitForResponse( if (!lock) { if (Log *log = ProcessGDBRemoteLog::GetLogIfAnyCategoryIsSet( GDBR_LOG_PROCESS | GDBR_LOG_PACKETS)) - log->Printf("GDBRemoteCommunicationClient::%s: Didn't get sequence mutex " - "for %s packet.", - __FUNCTION__, payload.GetData()); + LLDB_LOGF(log, + "GDBRemoteCommunicationClient::%s: Didn't get sequence mutex " + "for %s packet.", + __FUNCTION__, payload.GetData()); return PacketResult::ErrorNoSequenceLock; } @@ -660,10 +657,10 @@ GDBRemoteCommunicationClient::SendPacketsAndConcatenateResponses( if (!lock) { Log *log(ProcessGDBRemoteLog::GetLogIfAnyCategoryIsSet(GDBR_LOG_PROCESS | GDBR_LOG_PACKETS)); - if (log) - log->Printf("error: failed to get packet sequence mutex, not sending " - "packets with prefix '%s'", - payload_prefix); + LLDB_LOGF(log, + "error: failed to get packet sequence mutex, not sending " + "packets with prefix '%s'", + payload_prefix); return PacketResult::ErrorNoSequenceLock; } @@ -934,6 +931,11 @@ llvm::VersionTuple GDBRemoteCommunicationClient::GetOSVersion() { return m_os_version; } +llvm::VersionTuple GDBRemoteCommunicationClient::GetMacCatalystVersion() { + GetHostInfo(); + return m_maccatalyst_version; +} + bool GDBRemoteCommunicationClient::GetOSBuildString(std::string &s) { if (GetHostInfo()) { if (!m_os_build.empty()) { @@ -1136,6 +1138,7 @@ bool GDBRemoteCommunicationClient::GetHostInfo(bool force) { uint32_t sub = 0; std::string arch_name; std::string os_name; + std::string environment; std::string vendor_name; std::string triple; std::string distribution_id; @@ -1175,7 +1178,11 @@ bool GDBRemoteCommunicationClient::GetHostInfo(bool force) { extractor.GetHexByteString(m_os_kernel); ++num_keys_decoded; } else if (name.equals("ostype")) { - os_name = value; + if (value.equals("maccatalyst")) { + os_name = "ios"; + environment = "macabi"; + } else + os_name = value; ++num_keys_decoded; } else if (name.equals("vendor")) { vendor_name = value; @@ -1199,6 +1206,9 @@ bool GDBRemoteCommunicationClient::GetHostInfo(bool force) { { if (!m_os_version.tryParse(value)) ++num_keys_decoded; + } else if (name.equals("maccatalyst_version")) { + if (!m_maccatalyst_version.tryParse(value)) + ++num_keys_decoded; } else if (name.equals("watchpoint_exceptions_received")) { m_watchpoints_trigger_after_instruction = llvm::StringSwitch<LazyBool>(value) @@ -1236,6 +1246,8 @@ bool GDBRemoteCommunicationClient::GetHostInfo(bool force) { llvm::StringRef(vendor_name)); if (!os_name.empty()) m_host_arch.GetTriple().setOSName(llvm::StringRef(os_name)); + if (!environment.empty()) + m_host_arch.GetTriple().setEnvironmentName(environment); } } else { std::string triple; @@ -1259,6 +1271,7 @@ bool GDBRemoteCommunicationClient::GetHostInfo(bool force) { host_triple.getOS() == llvm::Triple::Darwin) { switch (m_host_arch.GetMachine()) { case llvm::Triple::aarch64: + case llvm::Triple::aarch64_32: case llvm::Triple::arm: case llvm::Triple::thumb: host_triple.setOS(llvm::Triple::IOS); @@ -1284,14 +1297,15 @@ bool GDBRemoteCommunicationClient::GetHostInfo(bool force) { assert(byte_order == m_host_arch.GetByteOrder()); } - if (log) - log->Printf("GDBRemoteCommunicationClient::%s parsed host " - "architecture as %s, triple as %s from triple text %s", - __FUNCTION__, m_host_arch.GetArchitectureName() - ? m_host_arch.GetArchitectureName() - : "<null-arch-name>", - m_host_arch.GetTriple().getTriple().c_str(), - triple.c_str()); + LLDB_LOGF(log, + "GDBRemoteCommunicationClient::%s parsed host " + "architecture as %s, triple as %s from triple text %s", + __FUNCTION__, + m_host_arch.GetArchitectureName() + ? m_host_arch.GetArchitectureName() + : "<null-arch-name>", + m_host_arch.GetTriple().getTriple().c_str(), + triple.c_str()); } if (!distribution_id.empty()) m_host_arch.SetDistributionId(distribution_id.c_str()); @@ -1893,7 +1907,7 @@ bool GDBRemoteCommunicationClient::DecodeProcessInfoResponse( } else if (name.equals("euid")) { uint32_t uid = UINT32_MAX; value.getAsInteger(0, uid); - process_info.SetEffectiveGroupID(uid); + process_info.SetEffectiveUserID(uid); } else if (name.equals("gid")) { uint32_t gid = UINT32_MAX; value.getAsInteger(0, gid); @@ -1914,6 +1928,26 @@ bool GDBRemoteCommunicationClient::DecodeProcessInfoResponse( std::string name; extractor.GetHexByteString(name); process_info.GetExecutableFile().SetFile(name, FileSpec::Style::native); + } else if (name.equals("args")) { + llvm::StringRef encoded_args(value), hex_arg; + + bool is_arg0 = true; + while (!encoded_args.empty()) { + std::tie(hex_arg, encoded_args) = encoded_args.split('-'); + std::string arg; + StringExtractor extractor(hex_arg); + if (extractor.GetHexByteString(arg) * 2 != hex_arg.size()) { + // In case of wrong encoding, we discard all the arguments + process_info.GetArguments().Clear(); + process_info.SetArg0(""); + break; + } + if (is_arg0) + process_info.SetArg0(arg); + else + process_info.GetArguments().AppendArgument(arg); + is_arg0 = false; + } } else if (name.equals("cputype")) { value.getAsInteger(0, cpu); } else if (name.equals("cpusubtype")) { @@ -1987,6 +2021,7 @@ bool GDBRemoteCommunicationClient::GetCurrentProcessInfo(bool allow_lazy) { uint32_t sub = 0; std::string arch_name; std::string os_name; + std::string environment; std::string vendor_name; std::string triple; std::string elf_abi; @@ -2007,7 +2042,11 @@ bool GDBRemoteCommunicationClient::GetCurrentProcessInfo(bool allow_lazy) { extractor.GetHexByteString(triple); ++num_keys_decoded; } else if (name.equals("ostype")) { - os_name = value; + if (value.equals("maccatalyst")) { + os_name = "ios"; + environment = "macabi"; + } else + os_name = value; ++num_keys_decoded; } else if (name.equals("vendor")) { vendor_name = value; @@ -2048,6 +2087,8 @@ bool GDBRemoteCommunicationClient::GetCurrentProcessInfo(bool allow_lazy) { } else if (cpu != LLDB_INVALID_CPUTYPE && !os_name.empty() && !vendor_name.empty()) { llvm::Triple triple(llvm::Twine("-") + vendor_name + "-" + os_name); + if (!environment.empty()) + triple.setEnvironmentName(environment); assert(triple.getObjectFormat() != llvm::Triple::UnknownObjectFormat); assert(triple.getObjectFormat() != llvm::Triple::Wasm); @@ -2064,12 +2105,10 @@ bool GDBRemoteCommunicationClient::GetCurrentProcessInfo(bool allow_lazy) { break; case llvm::Triple::Wasm: case llvm::Triple::XCOFF: - if (log) - log->Printf("error: not supported target architecture"); + LLDB_LOGF(log, "error: not supported target architecture"); return false; case llvm::Triple::UnknownObjectFormat: - if (log) - log->Printf("error: failed to determine target architecture"); + LLDB_LOGF(log, "error: failed to determine target architecture"); return false; } @@ -2081,8 +2120,10 @@ bool GDBRemoteCommunicationClient::GetCurrentProcessInfo(bool allow_lazy) { } m_process_arch.GetTriple().setVendorName(llvm::StringRef(vendor_name)); m_process_arch.GetTriple().setOSName(llvm::StringRef(os_name)); + m_process_arch.GetTriple().setEnvironmentName(llvm::StringRef(environment)); m_host_arch.GetTriple().setVendorName(llvm::StringRef(vendor_name)); m_host_arch.GetTriple().setOSName(llvm::StringRef(os_name)); + m_host_arch.GetTriple().setEnvironmentName(llvm::StringRef(environment)); } return true; } @@ -2156,8 +2197,7 @@ uint32_t GDBRemoteCommunicationClient::FindProcesses( if (match_info.GetProcessInfo().EffectiveGroupIDIsValid()) packet.Printf("egid:%u;", match_info.GetProcessInfo().GetEffectiveGroupID()); - if (match_info.GetProcessInfo().EffectiveGroupIDIsValid()) - packet.Printf("all_users:%u;", match_info.GetMatchAllUsers() ? 1 : 0); + packet.Printf("all_users:%u;", match_info.GetMatchAllUsers() ? 1 : 0); if (match_info.GetProcessInfo().GetArchitecture().IsValid()) { const ArchSpec &match_arch = match_info.GetProcessInfo().GetArchitecture(); @@ -2178,8 +2218,7 @@ uint32_t GDBRemoteCommunicationClient::FindProcesses( if (!DecodeProcessInfoResponse(response, process_info)) break; process_infos.Append(process_info); - response.GetStringRef().clear(); - response.SetFilePos(0); + response = StringExtractorGDBRemote(); } while (SendPacketAndWaitForResponse("qsProcessInfo", response, false) == PacketResult::Success); } else { @@ -2641,9 +2680,8 @@ bool GDBRemoteCommunicationClient::GetThreadStopInfo( uint8_t GDBRemoteCommunicationClient::SendGDBStoppointTypePacket( GDBStoppointType type, bool insert, addr_t addr, uint32_t length) { Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_BREAKPOINTS)); - if (log) - log->Printf("GDBRemoteCommunicationClient::%s() %s at addr = 0x%" PRIx64, - __FUNCTION__, insert ? "add" : "remove", addr); + LLDB_LOGF(log, "GDBRemoteCommunicationClient::%s() %s at addr = 0x%" PRIx64, + __FUNCTION__, insert ? "add" : "remove", addr); // Check if the stub is known not to support this breakpoint type if (!SupportsGDBStoppointPacket(type)) @@ -2745,9 +2783,8 @@ size_t GDBRemoteCommunicationClient::GetCurrentThreadIDs( #if !defined(LLDB_CONFIGURATION_DEBUG) Log *log(ProcessGDBRemoteLog::GetLogIfAnyCategoryIsSet(GDBR_LOG_PROCESS | GDBR_LOG_PACKETS)); - if (log) - log->Printf("error: failed to get packet sequence mutex, not sending " - "packet 'qfThreadInfo'"); + LLDB_LOGF(log, "error: failed to get packet sequence mutex, not sending " + "packet 'qfThreadInfo'"); #endif sequence_mutex_unavailable = true; } @@ -2879,7 +2916,7 @@ static uint64_t ParseHostIOPacketResponse(StringExtractorGDBRemote &response, } lldb::user_id_t GDBRemoteCommunicationClient::OpenFile(const lldb_private::FileSpec &file_spec, - uint32_t flags, mode_t mode, + File::OpenOptions flags, mode_t mode, Status &error) { std::string path(file_spec.GetPath(false)); lldb_private::StreamString stream; @@ -3146,7 +3183,8 @@ bool GDBRemoteCommunicationClient::AvoidGPackets(ProcessGDBRemote *process) { if (arch.IsValid() && arch.GetTriple().getVendor() == llvm::Triple::Apple && arch.GetTriple().getOS() == llvm::Triple::IOS && - arch.GetTriple().getArch() == llvm::Triple::aarch64) { + (arch.GetTriple().getArch() == llvm::Triple::aarch64 || + arch.GetTriple().getArch() == llvm::Triple::aarch64_32)) { m_avoid_g_packets = eLazyBoolYes; uint32_t gdb_server_version = GetGDBServerProgramVersion(); if (gdb_server_version != 0) { @@ -3592,21 +3630,21 @@ ParseModuleSpec(StructuredData::Dictionary *dict) { llvm::Optional<std::vector<ModuleSpec>> GDBRemoteCommunicationClient::GetModulesInfo( llvm::ArrayRef<FileSpec> module_file_specs, const llvm::Triple &triple) { + namespace json = llvm::json; + if (!m_supports_jModulesInfo) return llvm::None; - JSONArray::SP module_array_sp = std::make_shared<JSONArray>(); + json::Array module_array; for (const FileSpec &module_file_spec : module_file_specs) { - JSONObject::SP module_sp = std::make_shared<JSONObject>(); - module_array_sp->AppendObject(module_sp); - module_sp->SetObject( - "file", std::make_shared<JSONString>(module_file_spec.GetPath(false))); - module_sp->SetObject("triple", - std::make_shared<JSONString>(triple.getTriple())); + module_array.push_back( + json::Object{{"file", module_file_spec.GetPath(false)}, + {"triple", triple.getTriple()}}); } StreamString unescaped_payload; unescaped_payload.PutCString("jModulesInfo:"); - module_array_sp->Write(unescaped_payload); + unescaped_payload.AsRawOstream() << std::move(module_array); + StreamGDBRemote payload; payload.PutEscapedBytes(unescaped_payload.GetString().data(), unescaped_payload.GetSize()); @@ -3796,8 +3834,9 @@ void GDBRemoteCommunicationClient::ServeSymbolLookups( addr_t symbol_load_addr = LLDB_INVALID_ADDRESS; lldb_private::SymbolContextList sc_list; - if (process->GetTarget().GetImages().FindSymbolsWithNameAndType( - ConstString(symbol_name), eSymbolTypeAny, sc_list)) { + process->GetTarget().GetImages().FindSymbolsWithNameAndType( + ConstString(symbol_name), eSymbolTypeAny, sc_list); + if (!sc_list.IsEmpty()) { const size_t num_scs = sc_list.GetSize(); for (size_t sc_idx = 0; sc_idx < num_scs && @@ -3873,9 +3912,9 @@ void GDBRemoteCommunicationClient::ServeSymbolLookups( } else if (Log *log = ProcessGDBRemoteLog::GetLogIfAnyCategoryIsSet( GDBR_LOG_PROCESS | GDBR_LOG_PACKETS)) { - log->Printf( - "GDBRemoteCommunicationClient::%s: Didn't get sequence mutex.", - __FUNCTION__); + LLDB_LOGF(log, + "GDBRemoteCommunicationClient::%s: Didn't get sequence mutex.", + __FUNCTION__); } } } @@ -3899,26 +3938,27 @@ GDBRemoteCommunicationClient::GetSupportedStructuredDataPlugins() { !m_supported_async_json_packets_sp->GetAsArray()) { // We were returned something other than a JSON array. This is // invalid. Clear it out. - if (log) - log->Printf("GDBRemoteCommunicationClient::%s(): " - "QSupportedAsyncJSONPackets returned invalid " - "result: %s", - __FUNCTION__, response.GetStringRef().c_str()); + LLDB_LOGF(log, + "GDBRemoteCommunicationClient::%s(): " + "QSupportedAsyncJSONPackets returned invalid " + "result: %s", + __FUNCTION__, response.GetStringRef().data()); m_supported_async_json_packets_sp.reset(); } } else { - if (log) - log->Printf("GDBRemoteCommunicationClient::%s(): " - "QSupportedAsyncJSONPackets unsupported", - __FUNCTION__); + LLDB_LOGF(log, + "GDBRemoteCommunicationClient::%s(): " + "QSupportedAsyncJSONPackets unsupported", + __FUNCTION__); } if (log && m_supported_async_json_packets_sp) { StreamString stream; m_supported_async_json_packets_sp->Dump(stream); - log->Printf("GDBRemoteCommunicationClient::%s(): supported async " - "JSON packets: %s", - __FUNCTION__, stream.GetData()); + LLDB_LOGF(log, + "GDBRemoteCommunicationClient::%s(): supported async " + "JSON packets: %s", + __FUNCTION__, stream.GetData()); } } @@ -3980,14 +4020,14 @@ Status GDBRemoteCommunicationClient::ConfigureRemoteStructuredData( SendPacketAndWaitForResponse(stream.GetString(), response, send_async); if (result == PacketResult::Success) { // We failed if the config result comes back other than OK. - if (strcmp(response.GetStringRef().c_str(), "OK") == 0) { + if (strcmp(response.GetStringRef().data(), "OK") == 0) { // Okay! error.Clear(); } else { error.SetErrorStringWithFormat("configuring StructuredData feature " "%s failed with error %s", type_name.AsCString(), - response.GetStringRef().c_str()); + response.GetStringRef().data()); } } else { // Can we get more data here on the failure? diff --git a/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.h b/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.h index de85c9f8b67b..574cd0fd70c5 100644 --- a/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.h +++ b/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.h @@ -17,8 +17,9 @@ #include <string> #include <vector> +#include "lldb/Host/File.h" #include "lldb/Utility/ArchSpec.h" -#include "lldb/Utility/StreamGDBRemote.h" +#include "lldb/Utility/GDBRemote.h" #include "lldb/Utility/StructuredData.h" #if defined(_WIN32) #include "lldb/Host/windows/PosixApi.h" @@ -248,6 +249,8 @@ public: llvm::VersionTuple GetOSVersion(); + llvm::VersionTuple GetMacCatalystVersion(); + bool GetOSBuildString(std::string &s); bool GetOSKernelDescription(std::string &s); @@ -348,7 +351,7 @@ public: size_t GetCurrentThreadIDs(std::vector<lldb::tid_t> &thread_ids, bool &sequence_mutex_unavailable); - lldb::user_id_t OpenFile(const FileSpec &file_spec, uint32_t flags, + lldb::user_id_t OpenFile(const FileSpec &file_spec, File::OpenOptions flags, mode_t mode, Status &error); bool CloseFile(lldb::user_id_t fd, Status &error); @@ -548,6 +551,7 @@ protected: ArchSpec m_host_arch; ArchSpec m_process_arch; llvm::VersionTuple m_os_version; + llvm::VersionTuple m_maccatalyst_version; std::string m_os_build; std::string m_os_kernel; std::string m_hostname; diff --git a/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationHistory.cpp b/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationHistory.cpp index bcddb4faf863..d2cc32f63f20 100644 --- a/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationHistory.cpp +++ b/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationHistory.cpp @@ -18,12 +18,6 @@ using namespace lldb; using namespace lldb_private; using namespace lldb_private::process_gdb_remote; -void GDBRemoteCommunicationHistory::Entry::Serialize(raw_ostream &strm) const { - yaml::Output yout(strm); - yout << const_cast<GDBRemoteCommunicationHistory::Entry &>(*this); - strm.flush(); -} - GDBRemoteCommunicationHistory::GDBRemoteCommunicationHistory(uint32_t size) : m_packets(), m_curr_idx(0), m_total_packet_count(0), m_dumped_to_log(false) { @@ -33,7 +27,8 @@ GDBRemoteCommunicationHistory::GDBRemoteCommunicationHistory(uint32_t size) GDBRemoteCommunicationHistory::~GDBRemoteCommunicationHistory() {} -void GDBRemoteCommunicationHistory::AddPacket(char packet_char, PacketType type, +void GDBRemoteCommunicationHistory::AddPacket(char packet_char, + GDBRemotePacket::Type type, uint32_t bytes_transmitted) { const size_t size = m_packets.size(); if (size == 0) @@ -50,7 +45,8 @@ void GDBRemoteCommunicationHistory::AddPacket(char packet_char, PacketType type, } void GDBRemoteCommunicationHistory::AddPacket(const std::string &src, - uint32_t src_len, PacketType type, + uint32_t src_len, + GDBRemotePacket::Type type, uint32_t bytes_transmitted) { const size_t size = m_packets.size(); if (size == 0) @@ -72,13 +68,12 @@ void GDBRemoteCommunicationHistory::Dump(Stream &strm) const { const uint32_t stop_idx = m_curr_idx + size; for (uint32_t i = first_idx; i < stop_idx; ++i) { const uint32_t idx = NormalizeIndex(i); - const Entry &entry = m_packets[idx]; - if (entry.type == ePacketTypeInvalid || entry.packet.data.empty()) + const GDBRemotePacket &entry = m_packets[idx]; + if (entry.type == GDBRemotePacket::ePacketTypeInvalid || + entry.packet.data.empty()) break; - strm.Printf("history[%u] tid=0x%4.4" PRIx64 " <%4u> %s packet: %s\n", - entry.packet_idx, entry.tid, entry.bytes_transmitted, - (entry.type == ePacketTypeSend) ? "send" : "read", - entry.packet.data.c_str()); + strm.Printf("history[%u] ", entry.packet_idx); + entry.Dump(strm); } } @@ -92,51 +87,15 @@ void GDBRemoteCommunicationHistory::Dump(Log *log) const { const uint32_t stop_idx = m_curr_idx + size; for (uint32_t i = first_idx; i < stop_idx; ++i) { const uint32_t idx = NormalizeIndex(i); - const Entry &entry = m_packets[idx]; - if (entry.type == ePacketTypeInvalid || entry.packet.data.empty()) + const GDBRemotePacket &entry = m_packets[idx]; + if (entry.type == GDBRemotePacket::ePacketTypeInvalid || + entry.packet.data.empty()) break; - log->Printf("history[%u] tid=0x%4.4" PRIx64 " <%4u> %s packet: %s", - entry.packet_idx, entry.tid, entry.bytes_transmitted, - (entry.type == ePacketTypeSend) ? "send" : "read", - entry.packet.data.c_str()); + LLDB_LOGF(log, "history[%u] tid=0x%4.4" PRIx64 " <%4u> %s packet: %s", + entry.packet_idx, entry.tid, entry.bytes_transmitted, + (entry.type == GDBRemotePacket::ePacketTypeSend) ? "send" + : "read", + entry.packet.data.c_str()); } } -void yaml::ScalarEnumerationTraits<GDBRemoteCommunicationHistory::PacketType>:: - enumeration(IO &io, GDBRemoteCommunicationHistory::PacketType &value) { - io.enumCase(value, "Invalid", - GDBRemoteCommunicationHistory::ePacketTypeInvalid); - io.enumCase(value, "Send", GDBRemoteCommunicationHistory::ePacketTypeSend); - io.enumCase(value, "Recv", GDBRemoteCommunicationHistory::ePacketTypeRecv); -} - -void yaml::ScalarTraits<GDBRemoteCommunicationHistory::Entry::BinaryData>:: - output(const GDBRemoteCommunicationHistory::Entry::BinaryData &Val, void *, - raw_ostream &Out) { - Out << toHex(Val.data); -} - -StringRef -yaml::ScalarTraits<GDBRemoteCommunicationHistory::Entry::BinaryData>::input( - StringRef Scalar, void *, - GDBRemoteCommunicationHistory::Entry::BinaryData &Val) { - Val.data = fromHex(Scalar); - return {}; -} - -void yaml::MappingTraits<GDBRemoteCommunicationHistory::Entry>::mapping( - IO &io, GDBRemoteCommunicationHistory::Entry &Entry) { - io.mapRequired("packet", Entry.packet); - io.mapRequired("type", Entry.type); - io.mapRequired("bytes", Entry.bytes_transmitted); - io.mapRequired("index", Entry.packet_idx); - io.mapRequired("tid", Entry.tid); -} - -StringRef yaml::MappingTraits<GDBRemoteCommunicationHistory::Entry>::validate( - IO &io, GDBRemoteCommunicationHistory::Entry &Entry) { - if (Entry.bytes_transmitted != Entry.packet.data.size()) - return "BinaryData size doesn't match bytes transmitted"; - - return {}; -} diff --git a/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationHistory.h b/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationHistory.h index 85f112b50623..c006fbd34a4b 100644 --- a/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationHistory.h +++ b/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationHistory.h @@ -12,6 +12,7 @@ #include <string> #include <vector> +#include "lldb/Utility/GDBRemote.h" #include "lldb/lldb-public.h" #include "llvm/Support/YAMLTraits.h" #include "llvm/Support/raw_ostream.h" @@ -25,46 +26,17 @@ class GDBRemoteCommunicationHistory { public: friend llvm::yaml::MappingTraits<GDBRemoteCommunicationHistory>; - enum PacketType { ePacketTypeInvalid = 0, ePacketTypeSend, ePacketTypeRecv }; - - /// Entry in the ring buffer containing the packet data, its type, size and - /// index. Entries can be serialized to file. - struct Entry { - Entry() - : packet(), type(ePacketTypeInvalid), bytes_transmitted(0), - packet_idx(0), tid(LLDB_INVALID_THREAD_ID) {} - - void Clear() { - packet.data.clear(); - type = ePacketTypeInvalid; - bytes_transmitted = 0; - packet_idx = 0; - tid = LLDB_INVALID_THREAD_ID; - } - - struct BinaryData { - std::string data; - }; - - void Serialize(llvm::raw_ostream &strm) const; - - BinaryData packet; - PacketType type; - uint32_t bytes_transmitted; - uint32_t packet_idx; - lldb::tid_t tid; - }; - GDBRemoteCommunicationHistory(uint32_t size = 0); ~GDBRemoteCommunicationHistory(); // For single char packets for ack, nack and /x03 - void AddPacket(char packet_char, PacketType type, uint32_t bytes_transmitted); - - void AddPacket(const std::string &src, uint32_t src_len, PacketType type, + void AddPacket(char packet_char, GDBRemotePacket::Type type, uint32_t bytes_transmitted); + void AddPacket(const std::string &src, uint32_t src_len, + GDBRemotePacket::Type type, uint32_t bytes_transmitted); + void Dump(Stream &strm) const; void Dump(Log *log) const; bool DidDumpToLog() const { return m_dumped_to_log; } @@ -97,7 +69,7 @@ private: return m_packets.empty() ? 0 : i % m_packets.size(); } - std::vector<Entry> m_packets; + std::vector<GDBRemotePacket> m_packets; uint32_t m_curr_idx; uint32_t m_total_packet_count; mutable bool m_dumped_to_log; @@ -107,49 +79,4 @@ private: } // namespace process_gdb_remote } // namespace lldb_private -LLVM_YAML_IS_DOCUMENT_LIST_VECTOR( - lldb_private::process_gdb_remote::GDBRemoteCommunicationHistory::Entry) - -namespace llvm { -namespace yaml { - -template <> -struct ScalarEnumerationTraits<lldb_private::process_gdb_remote:: - GDBRemoteCommunicationHistory::PacketType> { - static void enumeration(IO &io, - lldb_private::process_gdb_remote:: - GDBRemoteCommunicationHistory::PacketType &value); -}; - -template <> -struct ScalarTraits<lldb_private::process_gdb_remote:: - GDBRemoteCommunicationHistory::Entry::BinaryData> { - static void output(const lldb_private::process_gdb_remote:: - GDBRemoteCommunicationHistory::Entry::BinaryData &, - void *, raw_ostream &); - - static StringRef - input(StringRef, void *, - lldb_private::process_gdb_remote::GDBRemoteCommunicationHistory::Entry:: - BinaryData &); - - static QuotingType mustQuote(StringRef S) { return QuotingType::None; } -}; - -template <> -struct MappingTraits< - lldb_private::process_gdb_remote::GDBRemoteCommunicationHistory::Entry> { - static void - mapping(IO &io, - lldb_private::process_gdb_remote::GDBRemoteCommunicationHistory::Entry - &Entry); - - static StringRef validate( - IO &io, - lldb_private::process_gdb_remote::GDBRemoteCommunicationHistory::Entry &); -}; - -} // namespace yaml -} // namespace llvm - #endif // liblldb_GDBRemoteCommunicationHistory_h_ diff --git a/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationReplayServer.cpp b/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationReplayServer.cpp index 417f5737a30f..2d26c550dc76 100644 --- a/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationReplayServer.cpp +++ b/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationReplayServer.cpp @@ -9,6 +9,7 @@ #include <errno.h> #include "lldb/Host/Config.h" +#include "llvm/ADT/ScopeExit.h" #include "GDBRemoteCommunicationReplayServer.h" #include "ProcessGDBRemoteLog.h" @@ -127,7 +128,7 @@ GDBRemoteCommunicationReplayServer::GetPacketAndSendResponse( Log *log(ProcessGDBRemoteLog::GetLogIfAllCategoriesSet(GDBR_LOG_PROCESS)); while (!m_packet_history.empty()) { // Pop last packet from the history. - GDBRemoteCommunicationHistory::Entry entry = m_packet_history.back(); + GDBRemotePacket entry = m_packet_history.back(); m_packet_history.pop_back(); // We've handled the handshake implicitly before. Skip the packet and move @@ -135,7 +136,7 @@ GDBRemoteCommunicationReplayServer::GetPacketAndSendResponse( if (entry.packet.data == "+") continue; - if (entry.type == GDBRemoteCommunicationHistory::ePacketTypeSend) { + if (entry.type == GDBRemotePacket::ePacketTypeSend) { if (unexpected(entry.packet.data, packet.GetStringRef())) { LLDB_LOG(log, "GDBRemoteCommunicationReplayServer expected packet: '{0}'", @@ -149,14 +150,14 @@ GDBRemoteCommunicationReplayServer::GetPacketAndSendResponse( // Ignore QEnvironment packets as they're handled earlier. if (entry.packet.data.find("QEnvironment") == 1) { assert(m_packet_history.back().type == - GDBRemoteCommunicationHistory::ePacketTypeRecv); + GDBRemotePacket::ePacketTypeRecv); m_packet_history.pop_back(); } continue; } - if (entry.type == GDBRemoteCommunicationHistory::ePacketTypeInvalid) { + if (entry.type == GDBRemotePacket::ePacketTypeInvalid) { LLDB_LOG( log, "GDBRemoteCommunicationReplayServer skipped invalid packet: '{0}'", @@ -175,10 +176,6 @@ GDBRemoteCommunicationReplayServer::GetPacketAndSendResponse( return packet_result; } -LLVM_YAML_IS_DOCUMENT_LIST_VECTOR( - std::vector< - lldb_private::process_gdb_remote::GDBRemoteCommunicationHistory::Entry>) - llvm::Error GDBRemoteCommunicationReplayServer::LoadReplayHistory(const FileSpec &path) { auto error_or_file = MemoryBuffer::getFile(path.GetPath()); @@ -256,11 +253,10 @@ void GDBRemoteCommunicationReplayServer::ReceivePacket( thread_result_t GDBRemoteCommunicationReplayServer::AsyncThread(void *arg) { GDBRemoteCommunicationReplayServer *server = (GDBRemoteCommunicationReplayServer *)arg; - + auto D = make_scope_exit([&]() { server->Disconnect(); }); EventSP event_sp; bool done = false; - - while (true) { + while (!done) { if (server->m_async_listener_sp->GetEvent(event_sp, llvm::None)) { const uint32_t event_type = event_sp->GetType(); if (event_sp->BroadcasterIs(&server->m_async_broadcaster)) { diff --git a/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationReplayServer.h b/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationReplayServer.h index 26d65e265463..0b5e910f7c6a 100644 --- a/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationReplayServer.h +++ b/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationReplayServer.h @@ -62,7 +62,7 @@ protected: static lldb::thread_result_t AsyncThread(void *arg); /// Replay history with the oldest packet at the end. - std::vector<GDBRemoteCommunicationHistory::Entry> m_packet_history; + std::vector<GDBRemotePacket> m_packet_history; /// Server thread. Broadcaster m_async_broadcaster; diff --git a/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServer.cpp b/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServer.cpp index 49cbeb023fd5..ac6ecffcf854 100644 --- a/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServer.cpp +++ b/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServer.cpp @@ -59,14 +59,13 @@ GDBRemoteCommunicationServer::GetPacketAndSendResponse( break; case StringExtractorGDBRemote::eServerPacketType_unimplemented: - packet_result = SendUnimplementedResponse(packet.GetStringRef().c_str()); + packet_result = SendUnimplementedResponse(packet.GetStringRef().data()); break; default: auto handler_it = m_packet_handlers.find(packet_type); if (handler_it == m_packet_handlers.end()) - packet_result = - SendUnimplementedResponse(packet.GetStringRef().c_str()); + packet_result = SendUnimplementedResponse(packet.GetStringRef().data()); else packet_result = handler_it->second(packet, error, interrupt, quit); break; @@ -139,10 +138,9 @@ GDBRemoteCommunication::PacketResult GDBRemoteCommunicationServer::SendIllFormedResponse( const StringExtractorGDBRemote &failed_packet, const char *message) { Log *log(ProcessGDBRemoteLog::GetLogIfAllCategoriesSet(GDBR_LOG_PACKETS)); - if (log) - log->Printf("GDBRemoteCommunicationServer::%s: ILLFORMED: '%s' (%s)", - __FUNCTION__, failed_packet.GetStringRef().c_str(), - message ? message : ""); + LLDB_LOGF(log, "GDBRemoteCommunicationServer::%s: ILLFORMED: '%s' (%s)", + __FUNCTION__, failed_packet.GetStringRef().data(), + message ? message : ""); return SendErrorResponse(0x03); } diff --git a/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerCommon.cpp b/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerCommon.cpp index d095c7a057ad..37980d914dc2 100644 --- a/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerCommon.cpp +++ b/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerCommon.cpp @@ -29,12 +29,13 @@ #include "lldb/Symbol/ObjectFile.h" #include "lldb/Target/Platform.h" #include "lldb/Utility/Endian.h" -#include "lldb/Utility/JSON.h" +#include "lldb/Utility/GDBRemote.h" #include "lldb/Utility/Log.h" -#include "lldb/Utility/StreamGDBRemote.h" #include "lldb/Utility/StreamString.h" #include "lldb/Utility/StructuredData.h" +#include "llvm/ADT/StringSwitch.h" #include "llvm/ADT/Triple.h" +#include "llvm/Support/JSON.h" #include "ProcessGDBRemoteLog.h" #include "lldb/Utility/StringExtractorGDBRemote.h" @@ -43,11 +44,10 @@ #include "lldb/Host/android/HostInfoAndroid.h" #endif -#include "llvm/ADT/StringSwitch.h" using namespace lldb; -using namespace lldb_private; using namespace lldb_private::process_gdb_remote; +using namespace lldb_private; #ifdef __ANDROID__ const static uint32_t g_default_packet_timeout_sec = 20; // seconds @@ -231,6 +231,7 @@ GDBRemoteCommunicationServerCommon::Handle_qHostInfo( #else if (host_arch.GetMachine() == llvm::Triple::aarch64 || + host_arch.GetMachine() == llvm::Triple::aarch64_32 || host_arch.GetMachine() == llvm::Triple::aarch64_be || host_arch.GetMachine() == llvm::Triple::arm || host_arch.GetMachine() == llvm::Triple::armeb || host_arch.IsMIPS()) @@ -260,6 +261,15 @@ GDBRemoteCommunicationServerCommon::Handle_qHostInfo( response.PutChar(';'); } +#if defined(__APPLE__) + llvm::VersionTuple maccatalyst_version = HostInfo::GetMacCatalystVersion(); + if (!maccatalyst_version.empty()) { + response.Format("maccatalyst_version:{0}", + maccatalyst_version.getAsString()); + response.PutChar(';'); + } +#endif + std::string s; if (HostInfo::GetOSBuildString(s)) { response.PutCString("os_build:"); @@ -421,8 +431,7 @@ GDBRemoteCommunicationServerCommon::Handle_qUserName( StringExtractorGDBRemote &packet) { #if !defined(LLDB_DISABLE_POSIX) Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PROCESS)); - if (log) - log->Printf("GDBRemoteCommunicationServerCommon::%s begin", __FUNCTION__); + LLDB_LOGF(log, "GDBRemoteCommunicationServerCommon::%s begin", __FUNCTION__); // Packet format: "qUserName:%i" where %i is the uid packet.SetFilePos(::strlen("qUserName:")); @@ -435,8 +444,7 @@ GDBRemoteCommunicationServerCommon::Handle_qUserName( return SendPacketNoLock(response.GetString()); } } - if (log) - log->Printf("GDBRemoteCommunicationServerCommon::%s end", __FUNCTION__); + LLDB_LOGF(log, "GDBRemoteCommunicationServerCommon::%s end", __FUNCTION__); #endif return SendErrorResponse(5); } @@ -500,19 +508,32 @@ GDBRemoteCommunicationServerCommon::Handle_vFile_Open( packet.GetHexByteStringTerminatedBy(path, ','); if (!path.empty()) { if (packet.GetChar() == ',') { - uint32_t flags = packet.GetHexMaxU32(false, 0); + // FIXME + // The flag values for OpenOptions do not match the values used by GDB + // * https://sourceware.org/gdb/onlinedocs/gdb/Open-Flags.html#Open-Flags + // * rdar://problem/46788934 + auto flags = File::OpenOptions(packet.GetHexMaxU32(false, 0)); if (packet.GetChar() == ',') { mode_t mode = packet.GetHexMaxU32(false, 0600); FileSpec path_spec(path); FileSystem::Instance().Resolve(path_spec); - File file; // Do not close fd. - Status error = - FileSystem::Instance().Open(file, path_spec, flags, mode, false); - const int save_errno = error.GetError(); + auto file = FileSystem::Instance().Open(path_spec, flags, mode, false); + + int save_errno = 0; + int descriptor = File::kInvalidDescriptor; + if (file) { + descriptor = file.get()->GetDescriptor(); + } else { + std::error_code code = errorToErrorCode(file.takeError()); + if (code.category() == std::system_category()) { + save_errno = code.value(); + } + } + StreamString response; response.PutChar('F'); - response.Printf("%i", file.GetDescriptor()); + response.Printf("%i", descriptor); if (save_errno) response.Printf(",%i", save_errno); return SendPacketNoLock(response.GetString()); @@ -530,7 +551,7 @@ GDBRemoteCommunicationServerCommon::Handle_vFile_Close( int err = -1; int save_errno = 0; if (fd >= 0) { - File file(fd, true); + NativeFile file(fd, File::OpenOptions(0), true); Status error = file.Close(); err = 0; save_errno = error.GetError(); @@ -552,16 +573,16 @@ GDBRemoteCommunicationServerCommon::Handle_vFile_pRead( packet.SetFilePos(::strlen("vFile:pread:")); int fd = packet.GetS32(-1); if (packet.GetChar() == ',') { - size_t count = packet.GetU64(UINT64_MAX); + size_t count = packet.GetU64(SIZE_MAX); if (packet.GetChar() == ',') { off_t offset = packet.GetU64(UINT32_MAX); - if (count == UINT64_MAX) { + if (count == SIZE_MAX) { response.Printf("F-1:%i", EINVAL); return SendPacketNoLock(response.GetString()); } std::string buffer(count, 0); - File file(fd, false); + NativeFile file(fd, File::eOpenOptionRead, false); Status error = file.Read(static_cast<void *>(&buffer[0]), count, offset); const ssize_t bytes_read = error.Success() ? count : -1; const int save_errno = error.GetError(); @@ -593,7 +614,7 @@ GDBRemoteCommunicationServerCommon::Handle_vFile_pWrite( if (packet.GetChar() == ',') { std::string buffer; if (packet.GetEscapedBinaryData(buffer)) { - File file(fd, false); + NativeFile file(fd, File::eOpenOptionWrite, false); size_t count = buffer.size(); Status error = file.Write(static_cast<const void *>(&buffer[0]), count, offset); @@ -825,6 +846,7 @@ GDBRemoteCommunicationServerCommon::Handle_qSupported( #if defined(__linux__) || defined(__NetBSD__) response.PutCString(";QPassSignals+"); response.PutCString(";qXfer:auxv:read+"); + response.PutCString(";qXfer:libraries-svr4:read+"); #endif return SendPacketNoLock(response.GetString()); @@ -1016,9 +1038,8 @@ GDBRemoteCommunicationServerCommon::Handle_A(StringExtractorGDBRemote &packet) { m_process_launch_info.GetExecutableFile().SetFile( arg, FileSpec::Style::native); m_process_launch_info.GetArguments().AppendArgument(arg); - if (log) - log->Printf("LLGSPacketHandler::%s added arg %d: \"%s\"", - __FUNCTION__, actual_arg_index, arg.c_str()); + LLDB_LOGF(log, "LLGSPacketHandler::%s added arg %d: \"%s\"", + __FUNCTION__, actual_arg_index, arg.c_str()); ++actual_arg_index; } } @@ -1104,6 +1125,8 @@ GDBRemoteCommunicationServerCommon::Handle_qModuleInfo( GDBRemoteCommunication::PacketResult GDBRemoteCommunicationServerCommon::Handle_jModulesInfo( StringExtractorGDBRemote &packet) { + namespace json = llvm::json; + packet.SetFilePos(::strlen("jModulesInfo:")); StructuredData::ObjectSP object_sp = StructuredData::ParseJSON(packet.Peek()); @@ -1114,7 +1137,7 @@ GDBRemoteCommunicationServerCommon::Handle_jModulesInfo( if (!packet_array) return SendErrorResponse(2); - JSONArray::SP response_array_sp = std::make_shared<JSONArray>(); + json::Array response_array; for (size_t i = 0; i < packet_array->GetSize(); ++i) { StructuredData::Dictionary *query = packet_array->GetItemAtIndex(i)->GetAsDictionary(); @@ -1132,27 +1155,22 @@ GDBRemoteCommunicationServerCommon::Handle_jModulesInfo( const auto file_offset = matched_module_spec.GetObjectOffset(); const auto file_size = matched_module_spec.GetObjectSize(); const auto uuid_str = matched_module_spec.GetUUID().GetAsString(""); - if (uuid_str.empty()) continue; - - JSONObject::SP response = std::make_shared<JSONObject>(); - response_array_sp->AppendObject(response); - response->SetObject("uuid", std::make_shared<JSONString>(uuid_str)); - response->SetObject( - "triple", - std::make_shared<JSONString>( - matched_module_spec.GetArchitecture().GetTriple().getTriple())); - response->SetObject("file_path", - std::make_shared<JSONString>( - matched_module_spec.GetFileSpec().GetPath())); - response->SetObject("file_offset", - std::make_shared<JSONNumber>(file_offset)); - response->SetObject("file_size", std::make_shared<JSONNumber>(file_size)); + const auto triple_str = + matched_module_spec.GetArchitecture().GetTriple().getTriple(); + const auto file_path = matched_module_spec.GetFileSpec().GetPath(); + + json::Object response{{"uuid", uuid_str}, + {"triple", triple_str}, + {"file_path", file_path}, + {"file_offset", static_cast<int64_t>(file_offset)}, + {"file_size", static_cast<int64_t>(file_size)}}; + response_array.push_back(std::move(response)); } StreamString response; - response_array_sp->Write(response); + response.AsRawOstream() << std::move(response_array); StreamGDBRemote escaped_response; escaped_response.PutEscapedBytes(response.GetString().data(), response.GetSize()); @@ -1168,6 +1186,15 @@ void GDBRemoteCommunicationServerCommon::CreateProcessInfoResponse( proc_info.GetEffectiveUserID(), proc_info.GetEffectiveGroupID()); response.PutCString("name:"); response.PutStringAsRawHex8(proc_info.GetExecutableFile().GetCString()); + + response.PutChar(';'); + response.PutCString("args:"); + response.PutStringAsRawHex8(proc_info.GetArg0()); + for (auto &arg : proc_info.GetArguments()) { + response.PutChar('-'); + response.PutStringAsRawHex8(arg.ref()); + } + response.PutChar(';'); const ArchSpec &proc_arch = proc_info.GetArchitecture(); if (proc_arch.IsValid()) { @@ -1217,6 +1244,7 @@ void GDBRemoteCommunicationServerCommon:: case llvm::Triple::arm: case llvm::Triple::thumb: case llvm::Triple::aarch64: + case llvm::Triple::aarch64_32: ostype = "ios"; break; default: diff --git a/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.cpp b/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.cpp index 196607665bba..ad1a39b57969 100644 --- a/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.cpp +++ b/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.cpp @@ -11,7 +11,7 @@ #include "lldb/Host/Config.h" #include "GDBRemoteCommunicationServerLLGS.h" -#include "lldb/Utility/StreamGDBRemote.h" +#include "lldb/Utility/GDBRemote.h" #include <chrono> #include <cstring> @@ -32,7 +32,6 @@ #include "lldb/Utility/Args.h" #include "lldb/Utility/DataBuffer.h" #include "lldb/Utility/Endian.h" -#include "lldb/Utility/JSON.h" #include "lldb/Utility/LLDBAssert.h" #include "lldb/Utility/Log.h" #include "lldb/Utility/RegisterValue.h" @@ -40,6 +39,7 @@ #include "lldb/Utility/StreamString.h" #include "lldb/Utility/UriParser.h" #include "llvm/ADT/Triple.h" +#include "llvm/Support/JSON.h" #include "llvm/Support/ScopedPrinter.h" #include "ProcessGDBRemote.h" @@ -217,8 +217,13 @@ Status GDBRemoteCommunicationServerLLGS::LaunchProcess() { m_process_launch_info.GetFlags().Set(eLaunchFlagDebug); if (should_forward_stdio) { + // Temporarily relax the following for Windows until we can take advantage + // of the recently added pty support. This doesn't really affect the use of + // lldb-server on Windows. +#if !defined(_WIN32) if (llvm::Error Err = m_process_launch_info.SetUpPtyRedirection()) return Status(std::move(Err)); +#endif } { @@ -249,18 +254,18 @@ Status GDBRemoteCommunicationServerLLGS::LaunchProcess() { // Setup stdout/stderr mapping from inferior to $O auto terminal_fd = m_debugged_process_up->GetTerminalFileDescriptor(); if (terminal_fd >= 0) { - if (log) - log->Printf("ProcessGDBRemoteCommunicationServerLLGS::%s setting " - "inferior STDIO fd to %d", - __FUNCTION__, terminal_fd); + LLDB_LOGF(log, + "ProcessGDBRemoteCommunicationServerLLGS::%s setting " + "inferior STDIO fd to %d", + __FUNCTION__, terminal_fd); Status status = SetSTDIOFileDescriptor(terminal_fd); if (status.Fail()) return status; } else { - if (log) - log->Printf("ProcessGDBRemoteCommunicationServerLLGS::%s ignoring " - "inferior STDIO since terminal fd reported as %d", - __FUNCTION__, terminal_fd); + LLDB_LOGF(log, + "ProcessGDBRemoteCommunicationServerLLGS::%s ignoring " + "inferior STDIO since terminal fd reported as %d", + __FUNCTION__, terminal_fd); } } else { LLDB_LOG(log, @@ -278,9 +283,8 @@ Status GDBRemoteCommunicationServerLLGS::LaunchProcess() { Status GDBRemoteCommunicationServerLLGS::AttachToProcess(lldb::pid_t pid) { Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PROCESS)); - if (log) - log->Printf("GDBRemoteCommunicationServerLLGS::%s pid %" PRIu64, - __FUNCTION__, pid); + LLDB_LOGF(log, "GDBRemoteCommunicationServerLLGS::%s pid %" PRIu64, + __FUNCTION__, pid); // Before we try to attach, make sure we aren't already monitoring something // else. @@ -304,18 +308,18 @@ Status GDBRemoteCommunicationServerLLGS::AttachToProcess(lldb::pid_t pid) { // Setup stdout/stderr mapping from inferior. auto terminal_fd = m_debugged_process_up->GetTerminalFileDescriptor(); if (terminal_fd >= 0) { - if (log) - log->Printf("ProcessGDBRemoteCommunicationServerLLGS::%s setting " - "inferior STDIO fd to %d", - __FUNCTION__, terminal_fd); + LLDB_LOGF(log, + "ProcessGDBRemoteCommunicationServerLLGS::%s setting " + "inferior STDIO fd to %d", + __FUNCTION__, terminal_fd); Status status = SetSTDIOFileDescriptor(terminal_fd); if (status.Fail()) return status; } else { - if (log) - log->Printf("ProcessGDBRemoteCommunicationServerLLGS::%s ignoring " - "inferior STDIO since terminal fd reported as %d", - __FUNCTION__, terminal_fd); + LLDB_LOGF(log, + "ProcessGDBRemoteCommunicationServerLLGS::%s ignoring " + "inferior STDIO since terminal fd reported as %d", + __FUNCTION__, terminal_fd); } printf("Attached to process %" PRIu64 "...\n", pid); @@ -327,10 +331,11 @@ void GDBRemoteCommunicationServerLLGS::InitializeDelegate( assert(process && "process cannot be NULL"); Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PROCESS)); if (log) { - log->Printf("GDBRemoteCommunicationServerLLGS::%s called with " - "NativeProcessProtocol pid %" PRIu64 ", current state: %s", - __FUNCTION__, process->GetID(), - StateAsCString(process->GetState())); + LLDB_LOGF(log, + "GDBRemoteCommunicationServerLLGS::%s called with " + "NativeProcessProtocol pid %" PRIu64 ", current state: %s", + __FUNCTION__, process->GetID(), + StateAsCString(process->GetState())); } } @@ -397,19 +402,21 @@ static void WriteRegisterValueInHexFixedWidth( } } -static JSONObject::SP GetRegistersAsJSON(NativeThreadProtocol &thread) { +static llvm::Expected<json::Object> +GetRegistersAsJSON(NativeThreadProtocol &thread) { Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_THREAD)); NativeRegisterContext& reg_ctx = thread.GetRegisterContext(); - JSONObject::SP register_object_sp = std::make_shared<JSONObject>(); + json::Object register_object; #ifdef LLDB_JTHREADSINFO_FULL_REGISTER_SET // Expedite all registers in the first register set (i.e. should be GPRs) // that are not contained in other registers. const RegisterSet *reg_set_p = reg_ctx_sp->GetRegisterSet(0); if (!reg_set_p) - return nullptr; + return llvm::make_error<llvm::StringError>("failed to get registers", + llvm::inconvertibleErrorCode()); for (const uint32_t *reg_num_p = reg_set_p->registers; *reg_num_p != LLDB_INVALID_REGNUM; ++reg_num_p) { uint32_t reg_num = *reg_num_p; @@ -431,10 +438,9 @@ static JSONObject::SP GetRegistersAsJSON(NativeThreadProtocol &thread) { const RegisterInfo *const reg_info_p = reg_ctx.GetRegisterInfoAtIndex(reg_num); if (reg_info_p == nullptr) { - if (log) - log->Printf( - "%s failed to get register info for register index %" PRIu32, - __FUNCTION__, reg_num); + LLDB_LOGF(log, + "%s failed to get register info for register index %" PRIu32, + __FUNCTION__, reg_num); continue; } @@ -445,11 +451,10 @@ static JSONObject::SP GetRegistersAsJSON(NativeThreadProtocol &thread) { RegisterValue reg_value; Status error = reg_ctx.ReadRegister(reg_info_p, reg_value); if (error.Fail()) { - if (log) - log->Printf("%s failed to read register '%s' index %" PRIu32 ": %s", - __FUNCTION__, - reg_info_p->name ? reg_info_p->name : "<unnamed-register>", - reg_num, error.AsCString()); + LLDB_LOGF(log, "%s failed to read register '%s' index %" PRIu32 ": %s", + __FUNCTION__, + reg_info_p->name ? reg_info_p->name : "<unnamed-register>", + reg_num, error.AsCString()); continue; } @@ -457,12 +462,11 @@ static JSONObject::SP GetRegistersAsJSON(NativeThreadProtocol &thread) { WriteRegisterValueInHexFixedWidth(stream, reg_ctx, *reg_info_p, ®_value, lldb::eByteOrderBig); - register_object_sp->SetObject( - llvm::to_string(reg_num), - std::make_shared<JSONString>(stream.GetString())); + register_object.try_emplace(llvm::to_string(reg_num), + stream.GetString().str()); } - return register_object_sp; + return register_object; } static const char *GetStopReasonString(StopReason stop_reason) { @@ -489,11 +493,11 @@ static const char *GetStopReasonString(StopReason stop_reason) { return nullptr; } -static JSONArray::SP GetJSONThreadsInfo(NativeProcessProtocol &process, - bool abridged) { +static llvm::Expected<json::Array> +GetJSONThreadsInfo(NativeProcessProtocol &process, bool abridged) { Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PROCESS | LIBLLDB_LOG_THREAD)); - JSONArray::SP threads_array_sp = std::make_shared<JSONArray>(); + json::Array threads_array; // Ensure we can get info on the given thread. uint32_t thread_idx = 0; @@ -507,61 +511,62 @@ static JSONArray::SP GetJSONThreadsInfo(NativeProcessProtocol &process, struct ThreadStopInfo tid_stop_info; std::string description; if (!thread->GetStopReason(tid_stop_info, description)) - return nullptr; + return llvm::make_error<llvm::StringError>( + "failed to get stop reason", llvm::inconvertibleErrorCode()); const int signum = tid_stop_info.details.signal.signo; if (log) { - log->Printf("GDBRemoteCommunicationServerLLGS::%s pid %" PRIu64 - " tid %" PRIu64 - " got signal signo = %d, reason = %d, exc_type = %" PRIu64, - __FUNCTION__, process.GetID(), tid, signum, - tid_stop_info.reason, tid_stop_info.details.exception.type); + LLDB_LOGF(log, + "GDBRemoteCommunicationServerLLGS::%s pid %" PRIu64 + " tid %" PRIu64 + " got signal signo = %d, reason = %d, exc_type = %" PRIu64, + __FUNCTION__, process.GetID(), tid, signum, + tid_stop_info.reason, tid_stop_info.details.exception.type); } - JSONObject::SP thread_obj_sp = std::make_shared<JSONObject>(); - threads_array_sp->AppendObject(thread_obj_sp); + json::Object thread_obj; if (!abridged) { - if (JSONObject::SP registers_sp = GetRegistersAsJSON(*thread)) - thread_obj_sp->SetObject("registers", registers_sp); + if (llvm::Expected<json::Object> registers = + GetRegistersAsJSON(*thread)) { + thread_obj.try_emplace("registers", std::move(*registers)); + } else { + return registers.takeError(); + } } - thread_obj_sp->SetObject("tid", std::make_shared<JSONNumber>(tid)); + thread_obj.try_emplace("tid", static_cast<int64_t>(tid)); + if (signum != 0) - thread_obj_sp->SetObject("signal", std::make_shared<JSONNumber>(signum)); + thread_obj.try_emplace("signal", signum); const std::string thread_name = thread->GetName(); if (!thread_name.empty()) - thread_obj_sp->SetObject("name", - std::make_shared<JSONString>(thread_name)); + thread_obj.try_emplace("name", thread_name); - if (const char *stop_reason_str = GetStopReasonString(tid_stop_info.reason)) - thread_obj_sp->SetObject("reason", - std::make_shared<JSONString>(stop_reason_str)); + const char *stop_reason = GetStopReasonString(tid_stop_info.reason); + if (stop_reason) + thread_obj.try_emplace("reason", stop_reason); if (!description.empty()) - thread_obj_sp->SetObject("description", - std::make_shared<JSONString>(description)); + thread_obj.try_emplace("description", description); if ((tid_stop_info.reason == eStopReasonException) && tid_stop_info.details.exception.type) { - thread_obj_sp->SetObject( - "metype", - std::make_shared<JSONNumber>(tid_stop_info.details.exception.type)); + thread_obj.try_emplace( + "metype", static_cast<int64_t>(tid_stop_info.details.exception.type)); - JSONArray::SP medata_array_sp = std::make_shared<JSONArray>(); + json::Array medata_array; for (uint32_t i = 0; i < tid_stop_info.details.exception.data_count; ++i) { - medata_array_sp->AppendObject(std::make_shared<JSONNumber>( - tid_stop_info.details.exception.data[i])); + medata_array.push_back( + static_cast<int64_t>(tid_stop_info.details.exception.data[i])); } - thread_obj_sp->SetObject("medata", medata_array_sp); + thread_obj.try_emplace("medata", std::move(medata_array)); } - - // TODO: Expedite interesting regions of inferior memory + threads_array.push_back(std::move(thread_obj)); } - - return threads_array_sp; + return threads_array; } GDBRemoteCommunication::PacketResult @@ -653,19 +658,21 @@ GDBRemoteCommunicationServerLLGS::SendStopReplyPacketForThread( // is hex ascii JSON that contains the thread IDs thread stop info only for // threads that have stop reasons. Only send this if we have more than one // thread otherwise this packet has all the info it needs. - if (thread_index > 0) { + if (thread_index > 1) { const bool threads_with_valid_stop_info_only = true; - JSONArray::SP threads_info_sp = GetJSONThreadsInfo( + llvm::Expected<json::Array> threads_info = GetJSONThreadsInfo( *m_debugged_process_up, threads_with_valid_stop_info_only); - if (threads_info_sp) { + if (threads_info) { response.PutCString("jstopinfo:"); StreamString unescaped_response; - threads_info_sp->Write(unescaped_response); + unescaped_response.AsRawOstream() << std::move(*threads_info); response.PutStringAsRawHex8(unescaped_response.GetData()); response.PutChar(';'); - } else - LLDB_LOG(log, "failed to prepare a jstopinfo field for pid {0}", - m_debugged_process_up->GetID()); + } else { + LLDB_LOG(log, "failed to prepare a jstopinfo field for pid {0}:", + m_debugged_process_up->GetID(), + llvm::toString(threads_info.takeError())); + } } uint32_t i = 0; @@ -684,12 +691,10 @@ GDBRemoteCommunicationServerLLGS::SendStopReplyPacketForThread( RegisterValue reg_value; Status error = reg_ctx.ReadRegister(reg_info_p, reg_value); if (error.Fail()) { - if (log) - log->Printf("%s failed to read register '%s' index %" PRIu32 ": %s", - __FUNCTION__, - reg_info_p->name ? reg_info_p->name - : "<unnamed-register>", - reg_to_read, error.AsCString()); + LLDB_LOGF(log, "%s failed to read register '%s' index %" PRIu32 ": %s", + __FUNCTION__, + reg_info_p->name ? reg_info_p->name : "<unnamed-register>", + reg_to_read, error.AsCString()); continue; } @@ -713,25 +718,24 @@ GDBRemoteCommunicationServerLLGS::SendStopReplyPacketForThread( const RegisterSet *reg_set_p; if (reg_ctx.GetRegisterSetCount() > 0 && ((reg_set_p = reg_ctx.GetRegisterSet(0)) != nullptr)) { - if (log) - log->Printf("GDBRemoteCommunicationServerLLGS::%s expediting registers " - "from set '%s' (registers set count: %zu)", - __FUNCTION__, - reg_set_p->name ? reg_set_p->name : "<unnamed-set>", - reg_set_p->num_registers); + LLDB_LOGF(log, + "GDBRemoteCommunicationServerLLGS::%s expediting registers " + "from set '%s' (registers set count: %zu)", + __FUNCTION__, reg_set_p->name ? reg_set_p->name : "<unnamed-set>", + reg_set_p->num_registers); for (const uint32_t *reg_num_p = reg_set_p->registers; *reg_num_p != LLDB_INVALID_REGNUM; ++reg_num_p) { const RegisterInfo *const reg_info_p = reg_ctx.GetRegisterInfoAtIndex(*reg_num_p); if (reg_info_p == nullptr) { - if (log) - log->Printf("GDBRemoteCommunicationServerLLGS::%s failed to get " - "register info for register set '%s', register index " - "%" PRIu32, - __FUNCTION__, - reg_set_p->name ? reg_set_p->name : "<unnamed-set>", - *reg_num_p); + LLDB_LOGF(log, + "GDBRemoteCommunicationServerLLGS::%s failed to get " + "register info for register set '%s', register index " + "%" PRIu32, + __FUNCTION__, + reg_set_p->name ? reg_set_p->name : "<unnamed-set>", + *reg_num_p); } else if (reg_info_p->value_regs == nullptr) { // Only expediate registers that are not contained in other registers. RegisterValue reg_value; @@ -742,13 +746,12 @@ GDBRemoteCommunicationServerLLGS::SendStopReplyPacketForThread( ®_value, lldb::eByteOrderBig); response.PutChar(';'); } else { - if (log) - log->Printf("GDBRemoteCommunicationServerLLGS::%s failed to read " - "register '%s' index %" PRIu32 ": %s", - __FUNCTION__, - reg_info_p->name ? reg_info_p->name - : "<unnamed-register>", - *reg_num_p, error.AsCString()); + LLDB_LOGF(log, + "GDBRemoteCommunicationServerLLGS::%s failed to read " + "register '%s' index %" PRIu32 ": %s", + __FUNCTION__, + reg_info_p->name ? reg_info_p->name : "<unnamed-register>", + *reg_num_p, error.AsCString()); } } } @@ -787,15 +790,14 @@ void GDBRemoteCommunicationServerLLGS::HandleInferiorState_Exited( assert(process && "process cannot be NULL"); Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PROCESS)); - if (log) - log->Printf("GDBRemoteCommunicationServerLLGS::%s called", __FUNCTION__); + LLDB_LOGF(log, "GDBRemoteCommunicationServerLLGS::%s called", __FUNCTION__); PacketResult result = SendStopReasonForState(StateType::eStateExited); if (result != PacketResult::Success) { - if (log) - log->Printf("GDBRemoteCommunicationServerLLGS::%s failed to send stop " - "notification for PID %" PRIu64 ", state: eStateExited", - __FUNCTION__, process->GetID()); + LLDB_LOGF(log, + "GDBRemoteCommunicationServerLLGS::%s failed to send stop " + "notification for PID %" PRIu64 ", state: eStateExited", + __FUNCTION__, process->GetID()); } // Close the pipe to the inferior terminal i/o if we launched it and set one @@ -812,8 +814,7 @@ void GDBRemoteCommunicationServerLLGS::HandleInferiorState_Stopped( assert(process && "process cannot be NULL"); Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PROCESS)); - if (log) - log->Printf("GDBRemoteCommunicationServerLLGS::%s called", __FUNCTION__); + LLDB_LOGF(log, "GDBRemoteCommunicationServerLLGS::%s called", __FUNCTION__); // Send the stop reason unless this is the stop after the launch or attach. switch (m_inferior_prev_state) { @@ -825,10 +826,10 @@ void GDBRemoteCommunicationServerLLGS::HandleInferiorState_Stopped( // In all other cases, send the stop reason. PacketResult result = SendStopReasonForState(StateType::eStateStopped); if (result != PacketResult::Success) { - if (log) - log->Printf("GDBRemoteCommunicationServerLLGS::%s failed to send stop " - "notification for PID %" PRIu64 ", state: eStateExited", - __FUNCTION__, process->GetID()); + LLDB_LOGF(log, + "GDBRemoteCommunicationServerLLGS::%s failed to send stop " + "notification for PID %" PRIu64 ", state: eStateExited", + __FUNCTION__, process->GetID()); } break; } @@ -839,9 +840,10 @@ void GDBRemoteCommunicationServerLLGS::ProcessStateChanged( assert(process && "process cannot be NULL"); Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PROCESS)); if (log) { - log->Printf("GDBRemoteCommunicationServerLLGS::%s called with " - "NativeProcessProtocol pid %" PRIu64 ", state: %s", - __FUNCTION__, process->GetID(), StateAsCString(state)); + LLDB_LOGF(log, + "GDBRemoteCommunicationServerLLGS::%s called with " + "NativeProcessProtocol pid %" PRIu64 ", state: %s", + __FUNCTION__, process->GetID(), StateAsCString(state)); } switch (state) { @@ -868,9 +870,10 @@ void GDBRemoteCommunicationServerLLGS::ProcessStateChanged( default: if (log) { - log->Printf("GDBRemoteCommunicationServerLLGS::%s didn't handle state " - "change for pid %" PRIu64 ", new state: %s", - __FUNCTION__, process->GetID(), StateAsCString(state)); + LLDB_LOGF(log, + "GDBRemoteCommunicationServerLLGS::%s didn't handle state " + "change for pid %" PRIu64 ", new state: %s", + __FUNCTION__, process->GetID(), StateAsCString(state)); } break; } @@ -888,10 +891,10 @@ void GDBRemoteCommunicationServerLLGS::DataAvailableCallback() { if (!m_handshake_completed) { if (!HandshakeWithClient()) { - if (log) - log->Printf("GDBRemoteCommunicationServerLLGS::%s handshake with " - "client failed, exiting", - __FUNCTION__); + LLDB_LOGF(log, + "GDBRemoteCommunicationServerLLGS::%s handshake with " + "client failed, exiting", + __FUNCTION__); m_mainloop.RequestTermination(); return; } @@ -908,10 +911,10 @@ void GDBRemoteCommunicationServerLLGS::DataAvailableCallback() { break; // No more packets in the queue if ((result != PacketResult::Success)) { - if (log) - log->Printf("GDBRemoteCommunicationServerLLGS::%s processing a packet " - "failed: %s", - __FUNCTION__, error.AsCString()); + LLDB_LOGF(log, + "GDBRemoteCommunicationServerLLGS::%s processing a packet " + "failed: %s", + __FUNCTION__, error.AsCString()); m_mainloop.RequestTermination(); break; } @@ -982,9 +985,10 @@ void GDBRemoteCommunicationServerLLGS::StartSTDIOForwarding() { // Not much we can do about the failure. Log it and continue without // forwarding. if (Log *log = GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PROCESS)) - log->Printf("GDBRemoteCommunicationServerLLGS::%s Failed to set up stdio " - "forwarding: %s", - __FUNCTION__, error.AsCString()); + LLDB_LOGF(log, + "GDBRemoteCommunicationServerLLGS::%s Failed to set up stdio " + "forwarding: %s", + __FUNCTION__, error.AsCString()); } } @@ -1008,10 +1012,11 @@ void GDBRemoteCommunicationServerLLGS::SendProcessOutput() { case eConnectionStatusError: case eConnectionStatusNoConnection: if (Log *log = GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PROCESS)) - log->Printf("GDBRemoteCommunicationServerLLGS::%s Stopping stdio " - "forwarding as communication returned status %d (error: " - "%s)", - __FUNCTION__, status, error.AsCString()); + LLDB_LOGF(log, + "GDBRemoteCommunicationServerLLGS::%s Stopping stdio " + "forwarding as communication returned status %d (error: " + "%s)", + __FUNCTION__, status, error.AsCString()); m_stdio_handle_up.reset(); return; @@ -1349,15 +1354,14 @@ GDBRemoteCommunicationServerLLGS::Handle_qGetWorkingDir( GDBRemoteCommunication::PacketResult GDBRemoteCommunicationServerLLGS::Handle_C(StringExtractorGDBRemote &packet) { Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PROCESS | LIBLLDB_LOG_THREAD)); - if (log) - log->Printf("GDBRemoteCommunicationServerLLGS::%s called", __FUNCTION__); + LLDB_LOGF(log, "GDBRemoteCommunicationServerLLGS::%s called", __FUNCTION__); // Ensure we have a native process. if (!m_debugged_process_up) { - if (log) - log->Printf("GDBRemoteCommunicationServerLLGS::%s no debugged process " - "shared pointer", - __FUNCTION__); + LLDB_LOGF(log, + "GDBRemoteCommunicationServerLLGS::%s no debugged process " + "shared pointer", + __FUNCTION__); return SendErrorResponse(0x36); } @@ -1376,13 +1380,14 @@ GDBRemoteCommunicationServerLLGS::Handle_C(StringExtractorGDBRemote &packet) { if (packet.GetBytesLeft() > 0) { // FIXME add continue at address support for $C{signo}[;{continue-address}]. if (*packet.Peek() == ';') - return SendUnimplementedResponse(packet.GetStringRef().c_str()); + return SendUnimplementedResponse(packet.GetStringRef().data()); else return SendIllFormedResponse( packet, "unexpected content after $C{signal-number}"); } - ResumeActionList resume_actions(StateType::eStateRunning, 0); + ResumeActionList resume_actions(StateType::eStateRunning, + LLDB_INVALID_SIGNAL_NUMBER); Status error; // We have two branches: what to do if a continue thread is specified (in @@ -1430,8 +1435,7 @@ GDBRemoteCommunicationServerLLGS::Handle_C(StringExtractorGDBRemote &packet) { GDBRemoteCommunication::PacketResult GDBRemoteCommunicationServerLLGS::Handle_c(StringExtractorGDBRemote &packet) { Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PROCESS | LIBLLDB_LOG_THREAD)); - if (log) - log->Printf("GDBRemoteCommunicationServerLLGS::%s called", __FUNCTION__); + LLDB_LOGF(log, "GDBRemoteCommunicationServerLLGS::%s called", __FUNCTION__); packet.SetFilePos(packet.GetFilePos() + ::strlen("c")); @@ -1440,20 +1444,21 @@ GDBRemoteCommunicationServerLLGS::Handle_c(StringExtractorGDBRemote &packet) { if (has_continue_address) { LLDB_LOG(log, "not implemented for c[address] variant [{0} remains]", packet.Peek()); - return SendUnimplementedResponse(packet.GetStringRef().c_str()); + return SendUnimplementedResponse(packet.GetStringRef().data()); } // Ensure we have a native process. if (!m_debugged_process_up) { - if (log) - log->Printf("GDBRemoteCommunicationServerLLGS::%s no debugged process " - "shared pointer", - __FUNCTION__); + LLDB_LOGF(log, + "GDBRemoteCommunicationServerLLGS::%s no debugged process " + "shared pointer", + __FUNCTION__); return SendErrorResponse(0x36); } // Build the ResumeActionList - ResumeActionList actions(StateType::eStateRunning, 0); + ResumeActionList actions(StateType::eStateRunning, + LLDB_INVALID_SIGNAL_NUMBER); Status error = m_debugged_process_up->Resume(actions); if (error.Fail()) { @@ -1480,17 +1485,16 @@ GDBRemoteCommunication::PacketResult GDBRemoteCommunicationServerLLGS::Handle_vCont( StringExtractorGDBRemote &packet) { Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PROCESS)); - if (log) - log->Printf("GDBRemoteCommunicationServerLLGS::%s handling vCont packet", - __FUNCTION__); + LLDB_LOGF(log, "GDBRemoteCommunicationServerLLGS::%s handling vCont packet", + __FUNCTION__); packet.SetFilePos(::strlen("vCont")); if (packet.GetBytesLeft() == 0) { - if (log) - log->Printf("GDBRemoteCommunicationServerLLGS::%s missing action from " - "vCont package", - __FUNCTION__); + LLDB_LOGF(log, + "GDBRemoteCommunicationServerLLGS::%s missing action from " + "vCont package", + __FUNCTION__); return SendIllFormedResponse(packet, "Missing action from vCont package"); } @@ -1521,7 +1525,7 @@ GDBRemoteCommunicationServerLLGS::Handle_vCont( ResumeAction thread_action; thread_action.tid = LLDB_INVALID_THREAD_ID; thread_action.state = eStateInvalid; - thread_action.signal = 0; + thread_action.signal = LLDB_INVALID_SIGNAL_NUMBER; const char action = packet.GetChar(); switch (action) { @@ -1958,10 +1962,10 @@ GDBRemoteCommunicationServerLLGS::Handle_p(StringExtractorGDBRemote &packet) { const uint32_t reg_index = packet.GetHexMaxU32(false, std::numeric_limits<uint32_t>::max()); if (reg_index == std::numeric_limits<uint32_t>::max()) { - if (log) - log->Printf("GDBRemoteCommunicationServerLLGS::%s failed, could not " - "parse register number from request \"%s\"", - __FUNCTION__, packet.GetStringRef().c_str()); + LLDB_LOGF(log, + "GDBRemoteCommunicationServerLLGS::%s failed, could not " + "parse register number from request \"%s\"", + __FUNCTION__, packet.GetStringRef().data()); return SendErrorResponse(0x15); } @@ -1978,20 +1982,19 @@ GDBRemoteCommunicationServerLLGS::Handle_p(StringExtractorGDBRemote &packet) { // Return the end of registers response if we've iterated one past the end of // the register set. if (reg_index >= reg_context.GetUserRegisterCount()) { - if (log) - log->Printf("GDBRemoteCommunicationServerLLGS::%s failed, requested " - "register %" PRIu32 " beyond register count %" PRIu32, - __FUNCTION__, reg_index, - reg_context.GetUserRegisterCount()); + LLDB_LOGF(log, + "GDBRemoteCommunicationServerLLGS::%s failed, requested " + "register %" PRIu32 " beyond register count %" PRIu32, + __FUNCTION__, reg_index, reg_context.GetUserRegisterCount()); return SendErrorResponse(0x15); } const RegisterInfo *reg_info = reg_context.GetRegisterInfoAtIndex(reg_index); if (!reg_info) { - if (log) - log->Printf("GDBRemoteCommunicationServerLLGS::%s failed, requested " - "register %" PRIu32 " returned NULL", - __FUNCTION__, reg_index); + LLDB_LOGF(log, + "GDBRemoteCommunicationServerLLGS::%s failed, requested " + "register %" PRIu32 " returned NULL", + __FUNCTION__, reg_index); return SendErrorResponse(0x15); } @@ -2002,20 +2005,20 @@ GDBRemoteCommunicationServerLLGS::Handle_p(StringExtractorGDBRemote &packet) { RegisterValue reg_value; Status error = reg_context.ReadRegister(reg_info, reg_value); if (error.Fail()) { - if (log) - log->Printf("GDBRemoteCommunicationServerLLGS::%s failed, read of " - "requested register %" PRIu32 " (%s) failed: %s", - __FUNCTION__, reg_index, reg_info->name, error.AsCString()); + LLDB_LOGF(log, + "GDBRemoteCommunicationServerLLGS::%s failed, read of " + "requested register %" PRIu32 " (%s) failed: %s", + __FUNCTION__, reg_index, reg_info->name, error.AsCString()); return SendErrorResponse(0x15); } const uint8_t *const data = reinterpret_cast<const uint8_t *>(reg_value.GetBytes()); if (!data) { - if (log) - log->Printf("GDBRemoteCommunicationServerLLGS::%s failed to get data " - "bytes from requested register %" PRIu32, - __FUNCTION__, reg_index); + LLDB_LOGF(log, + "GDBRemoteCommunicationServerLLGS::%s failed to get data " + "bytes from requested register %" PRIu32, + __FUNCTION__, reg_index); return SendErrorResponse(0x15); } @@ -2039,10 +2042,10 @@ GDBRemoteCommunicationServerLLGS::Handle_P(StringExtractorGDBRemote &packet) { const uint32_t reg_index = packet.GetHexMaxU32(false, std::numeric_limits<uint32_t>::max()); if (reg_index == std::numeric_limits<uint32_t>::max()) { - if (log) - log->Printf("GDBRemoteCommunicationServerLLGS::%s failed, could not " - "parse register number from request \"%s\"", - __FUNCTION__, packet.GetStringRef().c_str()); + LLDB_LOGF(log, + "GDBRemoteCommunicationServerLLGS::%s failed, could not " + "parse register number from request \"%s\"", + __FUNCTION__, packet.GetStringRef().data()); return SendErrorResponse(0x29); } @@ -2058,10 +2061,10 @@ GDBRemoteCommunicationServerLLGS::Handle_P(StringExtractorGDBRemote &packet) { // Get the thread to use. NativeThreadProtocol *thread = GetThreadFromSuffix(packet); if (!thread) { - if (log) - log->Printf("GDBRemoteCommunicationServerLLGS::%s failed, no thread " - "available (thread index 0)", - __FUNCTION__); + LLDB_LOGF(log, + "GDBRemoteCommunicationServerLLGS::%s failed, no thread " + "available (thread index 0)", + __FUNCTION__); return SendErrorResponse(0x28); } @@ -2069,20 +2072,20 @@ GDBRemoteCommunicationServerLLGS::Handle_P(StringExtractorGDBRemote &packet) { NativeRegisterContext ®_context = thread->GetRegisterContext(); const RegisterInfo *reg_info = reg_context.GetRegisterInfoAtIndex(reg_index); if (!reg_info) { - if (log) - log->Printf("GDBRemoteCommunicationServerLLGS::%s failed, requested " - "register %" PRIu32 " returned NULL", - __FUNCTION__, reg_index); + LLDB_LOGF(log, + "GDBRemoteCommunicationServerLLGS::%s failed, requested " + "register %" PRIu32 " returned NULL", + __FUNCTION__, reg_index); return SendErrorResponse(0x48); } // Return the end of registers response if we've iterated one past the end of // the register set. if (reg_index >= reg_context.GetUserRegisterCount()) { - if (log) - log->Printf("GDBRemoteCommunicationServerLLGS::%s failed, requested " - "register %" PRIu32 " beyond register count %" PRIu32, - __FUNCTION__, reg_index, reg_context.GetUserRegisterCount()); + LLDB_LOGF(log, + "GDBRemoteCommunicationServerLLGS::%s failed, requested " + "register %" PRIu32 " beyond register count %" PRIu32, + __FUNCTION__, reg_index, reg_context.GetUserRegisterCount()); return SendErrorResponse(0x47); } @@ -2101,10 +2104,10 @@ GDBRemoteCommunicationServerLLGS::Handle_P(StringExtractorGDBRemote &packet) { m_debugged_process_up->GetArchitecture().GetByteOrder()); Status error = reg_context.WriteRegister(reg_info, reg_value); if (error.Fail()) { - if (log) - log->Printf("GDBRemoteCommunicationServerLLGS::%s failed, write of " - "requested register %" PRIu32 " (%s) failed: %s", - __FUNCTION__, reg_index, reg_info->name, error.AsCString()); + LLDB_LOGF(log, + "GDBRemoteCommunicationServerLLGS::%s failed, write of " + "requested register %" PRIu32 " (%s) failed: %s", + __FUNCTION__, reg_index, reg_info->name, error.AsCString()); return SendErrorResponse(0x32); } @@ -2118,20 +2121,20 @@ GDBRemoteCommunicationServerLLGS::Handle_H(StringExtractorGDBRemote &packet) { // Fail if we don't have a current process. if (!m_debugged_process_up || (m_debugged_process_up->GetID() == LLDB_INVALID_PROCESS_ID)) { - if (log) - log->Printf( - "GDBRemoteCommunicationServerLLGS::%s failed, no process available", - __FUNCTION__); + LLDB_LOGF( + log, + "GDBRemoteCommunicationServerLLGS::%s failed, no process available", + __FUNCTION__); return SendErrorResponse(0x15); } // Parse out which variant of $H is requested. packet.SetFilePos(strlen("H")); if (packet.GetBytesLeft() < 1) { - if (log) - log->Printf("GDBRemoteCommunicationServerLLGS::%s failed, H command " - "missing {g,c} variant", - __FUNCTION__); + LLDB_LOGF(log, + "GDBRemoteCommunicationServerLLGS::%s failed, H command " + "missing {g,c} variant", + __FUNCTION__); return SendIllFormedResponse(packet, "H command missing {g,c} variant"); } @@ -2144,10 +2147,10 @@ GDBRemoteCommunicationServerLLGS::Handle_H(StringExtractorGDBRemote &packet) { break; default: - if (log) - log->Printf( - "GDBRemoteCommunicationServerLLGS::%s failed, invalid $H variant %c", - __FUNCTION__, h_variant); + LLDB_LOGF( + log, + "GDBRemoteCommunicationServerLLGS::%s failed, invalid $H variant %c", + __FUNCTION__, h_variant); return SendIllFormedResponse(packet, "H variant unsupported, should be c or g"); } @@ -2162,10 +2165,10 @@ GDBRemoteCommunicationServerLLGS::Handle_H(StringExtractorGDBRemote &packet) { if (tid != LLDB_INVALID_THREAD_ID && tid != 0) { NativeThreadProtocol *thread = m_debugged_process_up->GetThreadByID(tid); if (!thread) { - if (log) - log->Printf("GDBRemoteCommunicationServerLLGS::%s failed, tid %" PRIu64 - " not found", - __FUNCTION__, tid); + LLDB_LOGF(log, + "GDBRemoteCommunicationServerLLGS::%s failed, tid %" PRIu64 + " not found", + __FUNCTION__, tid); return SendErrorResponse(0x15); } } @@ -2196,10 +2199,10 @@ GDBRemoteCommunicationServerLLGS::Handle_I(StringExtractorGDBRemote &packet) { // Fail if we don't have a current process. if (!m_debugged_process_up || (m_debugged_process_up->GetID() == LLDB_INVALID_PROCESS_ID)) { - if (log) - log->Printf( - "GDBRemoteCommunicationServerLLGS::%s failed, no process available", - __FUNCTION__); + LLDB_LOGF( + log, + "GDBRemoteCommunicationServerLLGS::%s failed, no process available", + __FUNCTION__); return SendErrorResponse(0x15); } @@ -2257,10 +2260,10 @@ GDBRemoteCommunicationServerLLGS::Handle_memory_read( if (!m_debugged_process_up || (m_debugged_process_up->GetID() == LLDB_INVALID_PROCESS_ID)) { - if (log) - log->Printf( - "GDBRemoteCommunicationServerLLGS::%s failed, no process available", - __FUNCTION__); + LLDB_LOGF( + log, + "GDBRemoteCommunicationServerLLGS::%s failed, no process available", + __FUNCTION__); return SendErrorResponse(0x15); } @@ -2284,10 +2287,10 @@ GDBRemoteCommunicationServerLLGS::Handle_memory_read( const uint64_t byte_count = packet.GetHexMaxU64(false, 0); if (byte_count == 0) { - if (log) - log->Printf("GDBRemoteCommunicationServerLLGS::%s nothing to read: " - "zero-length packet", - __FUNCTION__); + LLDB_LOGF(log, + "GDBRemoteCommunicationServerLLGS::%s nothing to read: " + "zero-length packet", + __FUNCTION__); return SendOKResponse(); } @@ -2301,20 +2304,20 @@ GDBRemoteCommunicationServerLLGS::Handle_memory_read( Status error = m_debugged_process_up->ReadMemoryWithoutTrap( read_addr, &buf[0], byte_count, bytes_read); if (error.Fail()) { - if (log) - log->Printf("GDBRemoteCommunicationServerLLGS::%s pid %" PRIu64 - " mem 0x%" PRIx64 ": failed to read. Error: %s", - __FUNCTION__, m_debugged_process_up->GetID(), read_addr, - error.AsCString()); + LLDB_LOGF(log, + "GDBRemoteCommunicationServerLLGS::%s pid %" PRIu64 + " mem 0x%" PRIx64 ": failed to read. Error: %s", + __FUNCTION__, m_debugged_process_up->GetID(), read_addr, + error.AsCString()); return SendErrorResponse(0x08); } if (bytes_read == 0) { - if (log) - log->Printf("GDBRemoteCommunicationServerLLGS::%s pid %" PRIu64 - " mem 0x%" PRIx64 ": read 0 of %" PRIu64 " requested bytes", - __FUNCTION__, m_debugged_process_up->GetID(), read_addr, - byte_count); + LLDB_LOGF(log, + "GDBRemoteCommunicationServerLLGS::%s pid %" PRIu64 + " mem 0x%" PRIx64 ": read 0 of %" PRIu64 " requested bytes", + __FUNCTION__, m_debugged_process_up->GetID(), read_addr, + byte_count); return SendErrorResponse(0x08); } @@ -2338,10 +2341,10 @@ GDBRemoteCommunicationServerLLGS::Handle_M(StringExtractorGDBRemote &packet) { if (!m_debugged_process_up || (m_debugged_process_up->GetID() == LLDB_INVALID_PROCESS_ID)) { - if (log) - log->Printf( - "GDBRemoteCommunicationServerLLGS::%s failed, no process available", - __FUNCTION__); + LLDB_LOGF( + log, + "GDBRemoteCommunicationServerLLGS::%s failed, no process available", + __FUNCTION__); return SendErrorResponse(0x15); } @@ -2426,10 +2429,10 @@ GDBRemoteCommunicationServerLLGS::Handle_qMemoryRegionInfoSupported( // since we won't have a NativeProcessProtocol. if (!m_debugged_process_up || (m_debugged_process_up->GetID() == LLDB_INVALID_PROCESS_ID)) { - if (log) - log->Printf( - "GDBRemoteCommunicationServerLLGS::%s failed, no process available", - __FUNCTION__); + LLDB_LOGF( + log, + "GDBRemoteCommunicationServerLLGS::%s failed, no process available", + __FUNCTION__); return SendErrorResponse(0x15); } @@ -2454,10 +2457,10 @@ GDBRemoteCommunicationServerLLGS::Handle_qMemoryRegionInfo( // Ensure we have a process. if (!m_debugged_process_up || (m_debugged_process_up->GetID() == LLDB_INVALID_PROCESS_ID)) { - if (log) - log->Printf( - "GDBRemoteCommunicationServerLLGS::%s failed, no process available", - __FUNCTION__); + LLDB_LOGF( + log, + "GDBRemoteCommunicationServerLLGS::%s failed, no process available", + __FUNCTION__); return SendErrorResponse(0x15); } @@ -2703,10 +2706,10 @@ GDBRemoteCommunicationServerLLGS::Handle_s(StringExtractorGDBRemote &packet) { // Ensure we have a process. if (!m_debugged_process_up || (m_debugged_process_up->GetID() == LLDB_INVALID_PROCESS_ID)) { - if (log) - log->Printf( - "GDBRemoteCommunicationServerLLGS::%s failed, no process available", - __FUNCTION__); + LLDB_LOGF( + log, + "GDBRemoteCommunicationServerLLGS::%s failed, no process available", + __FUNCTION__); return SendErrorResponse(0x32); } @@ -2725,7 +2728,7 @@ GDBRemoteCommunicationServerLLGS::Handle_s(StringExtractorGDBRemote &packet) { return SendErrorResponse(0x33); // Create the step action for the given thread. - ResumeAction action = {tid, eStateStepping, 0}; + ResumeAction action = {tid, eStateStepping, LLDB_INVALID_SIGNAL_NUMBER}; // Setup the actions list. ResumeActionList actions; @@ -2735,11 +2738,11 @@ GDBRemoteCommunicationServerLLGS::Handle_s(StringExtractorGDBRemote &packet) { actions.SetDefaultThreadActionIfNeeded(eStateStopped, 0); Status error = m_debugged_process_up->Resume(actions); if (error.Fail()) { - if (log) - log->Printf("GDBRemoteCommunicationServerLLGS::%s pid %" PRIu64 - " tid %" PRIu64 " Resume() failed with error: %s", - __FUNCTION__, m_debugged_process_up->GetID(), tid, - error.AsCString()); + LLDB_LOGF(log, + "GDBRemoteCommunicationServerLLGS::%s pid %" PRIu64 + " tid %" PRIu64 " Resume() failed with error: %s", + __FUNCTION__, m_debugged_process_up->GetID(), tid, + error.AsCString()); return SendErrorResponse(0x49); } @@ -2765,6 +2768,24 @@ GDBRemoteCommunicationServerLLGS::ReadXferObject(llvm::StringRef object, return std::move(*buffer_or_error); } + if (object == "libraries-svr4") { + auto library_list = m_debugged_process_up->GetLoadedSVR4Libraries(); + if (!library_list) + return library_list.takeError(); + + StreamString response; + response.Printf("<library-list-svr4 version=\"1.0\">"); + for (auto const &library : *library_list) { + response.Printf("<library name=\"%s\" ", + XMLEncodeAttributeValue(library.name.c_str()).c_str()); + response.Printf("lm=\"0x%" PRIx64 "\" ", library.link_map); + response.Printf("l_addr=\"0x%" PRIx64 "\" ", library.base_addr); + response.Printf("l_ld=\"0x%" PRIx64 "\" />", library.ld_addr); + } + response.Printf("</library-list-svr4>"); + return MemoryBuffer::getMemBufferCopy(response.GetString(), __FUNCTION__); + } + return llvm::make_error<PacketUnimplementedError>( "Xfer object not supported"); } @@ -2968,18 +2989,18 @@ GDBRemoteCommunicationServerLLGS::Handle_vAttach( "vAttach failed to parse the process id"); // Attempt to attach. - if (log) - log->Printf("GDBRemoteCommunicationServerLLGS::%s attempting to attach to " - "pid %" PRIu64, - __FUNCTION__, pid); + LLDB_LOGF(log, + "GDBRemoteCommunicationServerLLGS::%s attempting to attach to " + "pid %" PRIu64, + __FUNCTION__, pid); Status error = AttachToProcess(pid); if (error.Fail()) { - if (log) - log->Printf("GDBRemoteCommunicationServerLLGS::%s failed to attach to " - "pid %" PRIu64 ": %s\n", - __FUNCTION__, pid, error.AsCString()); + LLDB_LOGF(log, + "GDBRemoteCommunicationServerLLGS::%s failed to attach to " + "pid %" PRIu64 ": %s\n", + __FUNCTION__, pid, error.AsCString()); return SendErrorResponse(error); } @@ -2996,10 +3017,10 @@ GDBRemoteCommunicationServerLLGS::Handle_D(StringExtractorGDBRemote &packet) { // Fail if we don't have a current process. if (!m_debugged_process_up || (m_debugged_process_up->GetID() == LLDB_INVALID_PROCESS_ID)) { - if (log) - log->Printf( - "GDBRemoteCommunicationServerLLGS::%s failed, no process available", - __FUNCTION__); + LLDB_LOGF( + log, + "GDBRemoteCommunicationServerLLGS::%s failed, no process available", + __FUNCTION__); return SendErrorResponse(0x15); } @@ -3023,11 +3044,10 @@ GDBRemoteCommunicationServerLLGS::Handle_D(StringExtractorGDBRemote &packet) { const Status error = m_debugged_process_up->Detach(); if (error.Fail()) { - if (log) - log->Printf("GDBRemoteCommunicationServerLLGS::%s failed to detach from " - "pid %" PRIu64 ": %s\n", - __FUNCTION__, m_debugged_process_up->GetID(), - error.AsCString()); + LLDB_LOGF(log, + "GDBRemoteCommunicationServerLLGS::%s failed to detach from " + "pid %" PRIu64 ": %s\n", + __FUNCTION__, m_debugged_process_up->GetID(), error.AsCString()); return SendErrorResponse(0x01); } @@ -3042,10 +3062,10 @@ GDBRemoteCommunicationServerLLGS::Handle_qThreadStopInfo( packet.SetFilePos(strlen("qThreadStopInfo")); const lldb::tid_t tid = packet.GetHexMaxU32(false, LLDB_INVALID_THREAD_ID); if (tid == LLDB_INVALID_THREAD_ID) { - if (log) - log->Printf("GDBRemoteCommunicationServerLLGS::%s failed, could not " - "parse thread id from request \"%s\"", - __FUNCTION__, packet.GetStringRef().c_str()); + LLDB_LOGF(log, + "GDBRemoteCommunicationServerLLGS::%s failed, could not " + "parse thread id from request \"%s\"", + __FUNCTION__, packet.GetStringRef().data()); return SendErrorResponse(0x15); } return SendStopReplyPacketForThread(tid); @@ -3064,15 +3084,16 @@ GDBRemoteCommunicationServerLLGS::Handle_jThreadsInfo( StreamString response; const bool threads_with_valid_stop_info_only = false; - JSONArray::SP threads_array_sp = GetJSONThreadsInfo( + llvm::Expected<json::Value> threads_info = GetJSONThreadsInfo( *m_debugged_process_up, threads_with_valid_stop_info_only); - if (!threads_array_sp) { - LLDB_LOG(log, "failed to prepare a packet for pid {0}", - m_debugged_process_up->GetID()); + if (!threads_info) { + LLDB_LOG(log, "failed to prepare a packet for pid {0}: {1}", + m_debugged_process_up->GetID(), + llvm::toString(threads_info.takeError())); return SendErrorResponse(52); } - threads_array_sp->Write(response); + response.AsRawOstream() << *threads_info; StreamGDBRemote escaped_response; escaped_response.PutEscapedBytes(response.GetData(), response.GetSize()); return SendPacketNoLock(escaped_response.GetString()); @@ -3177,15 +3198,15 @@ void GDBRemoteCommunicationServerLLGS::MaybeCloseInferiorTerminalConnection() { connection->Disconnect(&error); if (error.Success()) { - if (log) - log->Printf("GDBRemoteCommunicationServerLLGS::%s disconnect process " - "terminal stdio - SUCCESS", - __FUNCTION__); + LLDB_LOGF(log, + "GDBRemoteCommunicationServerLLGS::%s disconnect process " + "terminal stdio - SUCCESS", + __FUNCTION__); } else { - if (log) - log->Printf("GDBRemoteCommunicationServerLLGS::%s disconnect process " - "terminal stdio - FAIL: %s", - __FUNCTION__, error.AsCString()); + LLDB_LOGF(log, + "GDBRemoteCommunicationServerLLGS::%s disconnect process " + "terminal stdio - FAIL: %s", + __FUNCTION__, error.AsCString()); } } } @@ -3215,11 +3236,11 @@ NativeThreadProtocol *GDBRemoteCommunicationServerLLGS::GetThreadFromSuffix( // Parse out the ';'. if (packet.GetBytesLeft() < 1 || packet.GetChar() != ';') { - if (log) - log->Printf("GDBRemoteCommunicationServerLLGS::%s gdb-remote parse " - "error: expected ';' prior to start of thread suffix: packet " - "contents = '%s'", - __FUNCTION__, packet.GetStringRef().c_str()); + LLDB_LOGF(log, + "GDBRemoteCommunicationServerLLGS::%s gdb-remote parse " + "error: expected ';' prior to start of thread suffix: packet " + "contents = '%s'", + __FUNCTION__, packet.GetStringRef().data()); return nullptr; } @@ -3228,11 +3249,11 @@ NativeThreadProtocol *GDBRemoteCommunicationServerLLGS::GetThreadFromSuffix( // Parse out thread: portion. if (strncmp(packet.Peek(), "thread:", strlen("thread:")) != 0) { - if (log) - log->Printf("GDBRemoteCommunicationServerLLGS::%s gdb-remote parse " - "error: expected 'thread:' but not found, packet contents = " - "'%s'", - __FUNCTION__, packet.GetStringRef().c_str()); + LLDB_LOGF(log, + "GDBRemoteCommunicationServerLLGS::%s gdb-remote parse " + "error: expected 'thread:' but not found, packet contents = " + "'%s'", + __FUNCTION__, packet.GetStringRef().data()); return nullptr; } packet.SetFilePos(packet.GetFilePos() + strlen("thread:")); @@ -3283,3 +3304,28 @@ GDBRemoteCommunicationServerLLGS::FindModuleFile(const std::string &module_path, return GDBRemoteCommunicationServerCommon::FindModuleFile(module_path, arch); } + +std::string GDBRemoteCommunicationServerLLGS::XMLEncodeAttributeValue( + llvm::StringRef value) { + std::string result; + for (const char &c : value) { + switch (c) { + case '\'': + result += "'"; + break; + case '"': + result += """; + break; + case '<': + result += "<"; + break; + case '>': + result += ">"; + break; + default: + result += c; + break; + } + } + return result; +} diff --git a/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.h b/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.h index 068ea52caaaf..088ba92ad11a 100644 --- a/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.h +++ b/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.h @@ -196,6 +196,8 @@ protected: llvm::Expected<std::unique_ptr<llvm::MemoryBuffer>> ReadXferObject(llvm::StringRef object, llvm::StringRef annex); + static std::string XMLEncodeAttributeValue(llvm::StringRef value); + private: void HandleInferiorState_Exited(NativeProcessProtocol *process); diff --git a/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerPlatform.cpp b/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerPlatform.cpp index 6deb75f2f021..25cebbba8f7b 100644 --- a/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerPlatform.cpp +++ b/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerPlatform.cpp @@ -15,8 +15,10 @@ #include <cstring> #include <mutex> #include <sstream> +#include <thread> #include "llvm/Support/FileSystem.h" +#include "llvm/Support/JSON.h" #include "llvm/Support/Threading.h" #include "lldb/Host/Config.h" @@ -26,9 +28,8 @@ #include "lldb/Host/HostInfo.h" #include "lldb/Target/Platform.h" #include "lldb/Target/UnixSignals.h" -#include "lldb/Utility/JSON.h" +#include "lldb/Utility/GDBRemote.h" #include "lldb/Utility/Log.h" -#include "lldb/Utility/StreamGDBRemote.h" #include "lldb/Utility/StreamString.h" #include "lldb/Utility/StructuredData.h" #include "lldb/Utility/UriParser.h" @@ -36,8 +37,8 @@ #include "lldb/Utility/StringExtractorGDBRemote.h" using namespace lldb; -using namespace lldb_private; using namespace lldb_private::process_gdb_remote; +using namespace lldb_private; // GDBRemoteCommunicationServerPlatform constructor GDBRemoteCommunicationServerPlatform::GDBRemoteCommunicationServerPlatform( @@ -104,8 +105,8 @@ Status GDBRemoteCommunicationServerPlatform::LaunchGDBServer( hostname = "127.0.0.1"; Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PLATFORM)); - if (log) - log->Printf("Launching debugserver with: %s:%u...", hostname.c_str(), port); + LLDB_LOGF(log, "Launching debugserver with: %s:%u...", hostname.c_str(), + port); // Do not run in a new session so that it can not linger after the platform // closes. @@ -161,9 +162,8 @@ GDBRemoteCommunicationServerPlatform::Handle_qLaunchGDBServer( // process... Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PLATFORM)); - if (log) - log->Printf("GDBRemoteCommunicationServerPlatform::%s() called", - __FUNCTION__); + LLDB_LOGF(log, "GDBRemoteCommunicationServerPlatform::%s() called", + __FUNCTION__); ConnectionFileDescriptor file_conn; std::string hostname; @@ -183,17 +183,17 @@ GDBRemoteCommunicationServerPlatform::Handle_qLaunchGDBServer( Status error = LaunchGDBServer(Args(), hostname, debugserver_pid, port, socket_name); if (error.Fail()) { - if (log) - log->Printf("GDBRemoteCommunicationServerPlatform::%s() debugserver " - "launch failed: %s", - __FUNCTION__, error.AsCString()); + LLDB_LOGF(log, + "GDBRemoteCommunicationServerPlatform::%s() debugserver " + "launch failed: %s", + __FUNCTION__, error.AsCString()); return SendErrorResponse(9); } - if (log) - log->Printf("GDBRemoteCommunicationServerPlatform::%s() debugserver " - "launched successfully as pid %" PRIu64, - __FUNCTION__, debugserver_pid); + LLDB_LOGF(log, + "GDBRemoteCommunicationServerPlatform::%s() debugserver " + "launched successfully as pid %" PRIu64, + __FUNCTION__, debugserver_pid); StreamGDBRemote response; response.Printf("pid:%" PRIu64 ";port:%u;", debugserver_pid, @@ -215,22 +215,21 @@ GDBRemoteCommunicationServerPlatform::Handle_qLaunchGDBServer( GDBRemoteCommunication::PacketResult GDBRemoteCommunicationServerPlatform::Handle_qQueryGDBServer( StringExtractorGDBRemote &packet) { + namespace json = llvm::json; + if (m_pending_gdb_server.pid == LLDB_INVALID_PROCESS_ID) return SendErrorResponse(4); - JSONObject::SP server_sp = std::make_shared<JSONObject>(); - server_sp->SetObject("port", - std::make_shared<JSONNumber>(m_pending_gdb_server.port)); + json::Object server{{"port", m_pending_gdb_server.port}}; + if (!m_pending_gdb_server.socket_name.empty()) - server_sp->SetObject( - "socket_name", - std::make_shared<JSONString>(m_pending_gdb_server.socket_name.c_str())); + server.try_emplace("socket_name", m_pending_gdb_server.socket_name); - JSONArray server_list; - server_list.AppendObject(server_sp); + json::Array server_list; + server_list.push_back(std::move(server)); StreamGDBRemote response; - server_list.Write(response); + response.AsRawOstream() << std::move(server_list); StreamGDBRemote escaped_response; escaped_response.PutEscapedBytes(response.GetString().data(), @@ -281,10 +280,9 @@ bool GDBRemoteCommunicationServerPlatform::KillSpawnedProcess(lldb::pid_t pid) { return true; } } - usleep(10000); + std::this_thread::sleep_for(std::chrono::milliseconds(10)); } - // check one more time after the final usleep { std::lock_guard<std::recursive_mutex> guard(m_spawned_pids_mutex); if (m_spawned_pids.find(pid) == m_spawned_pids.end()) @@ -303,10 +301,10 @@ bool GDBRemoteCommunicationServerPlatform::KillSpawnedProcess(lldb::pid_t pid) { return true; } } - usleep(10000); + std::this_thread::sleep_for(std::chrono::milliseconds(10)); } - // check one more time after the final usleep Scope for locker + // check one more time after the final sleep { std::lock_guard<std::recursive_mutex> guard(m_spawned_pids_mutex); if (m_spawned_pids.find(pid) == m_spawned_pids.end()) diff --git a/source/Plugins/Process/gdb-remote/GDBRemoteRegisterContext.cpp b/source/Plugins/Process/gdb-remote/GDBRemoteRegisterContext.cpp index a77e659a55fa..c06c9527708e 100644 --- a/source/Plugins/Process/gdb-remote/GDBRemoteRegisterContext.cpp +++ b/source/Plugins/Process/gdb-remote/GDBRemoteRegisterContext.cpp @@ -206,11 +206,14 @@ bool GDBRemoteRegisterContext::ReadRegisterBytes(const RegisterInfo *reg_info, } else { Log *log(ProcessGDBRemoteLog::GetLogIfAnyCategoryIsSet(GDBR_LOG_THREAD | GDBR_LOG_PACKETS)); - if (log) - log->Printf ("error: GDBRemoteRegisterContext::ReadRegisterBytes tried to read the " - "entire register context at once, expected at least %" PRId64 " bytes " - "but only got %" PRId64 " bytes.", m_reg_data.GetByteSize(), - buffer_sp->GetByteSize()); + LLDB_LOGF( + log, + "error: GDBRemoteRegisterContext::ReadRegisterBytes tried " + "to read the " + "entire register context at once, expected at least %" PRId64 + " bytes " + "but only got %" PRId64 " bytes.", + m_reg_data.GetByteSize(), buffer_sp->GetByteSize()); } } return false; @@ -390,13 +393,15 @@ bool GDBRemoteRegisterContext::WriteRegisterBytes(const RegisterInfo *reg_info, if (log->GetVerbose()) { StreamString strm; gdb_comm.DumpHistory(strm); - log->Printf("error: failed to get packet sequence mutex, not sending " - "write register for \"%s\":\n%s", - reg_info->name, strm.GetData()); + LLDB_LOGF(log, + "error: failed to get packet sequence mutex, not sending " + "write register for \"%s\":\n%s", + reg_info->name, strm.GetData()); } else - log->Printf("error: failed to get packet sequence mutex, not sending " - "write register for \"%s\"", - reg_info->name); + LLDB_LOGF(log, + "error: failed to get packet sequence mutex, not sending " + "write register for \"%s\"", + reg_info->name); } } } @@ -494,12 +499,14 @@ bool GDBRemoteRegisterContext::ReadAllRegisterValues( if (log->GetVerbose()) { StreamString strm; gdb_comm.DumpHistory(strm); - log->Printf("error: failed to get packet sequence mutex, not sending " - "read all registers:\n%s", - strm.GetData()); + LLDB_LOGF(log, + "error: failed to get packet sequence mutex, not sending " + "read all registers:\n%s", + strm.GetData()); } else - log->Printf("error: failed to get packet sequence mutex, not sending " - "read all registers"); + LLDB_LOGF(log, + "error: failed to get packet sequence mutex, not sending " + "read all registers"); } } @@ -630,7 +637,9 @@ bool GDBRemoteRegisterContext::WriteAllRegisterValues( if (m_thread.GetProcess().get()) { const ArchSpec &arch = m_thread.GetProcess()->GetTarget().GetArchitecture(); - if (arch.IsValid() && arch.GetMachine() == llvm::Triple::aarch64 && + if (arch.IsValid() && + (arch.GetMachine() == llvm::Triple::aarch64 || + arch.GetMachine() == llvm::Triple::aarch64_32) && arch.GetTriple().getVendor() == llvm::Triple::Apple && arch.GetTriple().getOS() == llvm::Triple::IOS) { arm64_debugserver = true; @@ -667,12 +676,14 @@ bool GDBRemoteRegisterContext::WriteAllRegisterValues( if (log->GetVerbose()) { StreamString strm; gdb_comm.DumpHistory(strm); - log->Printf("error: failed to get packet sequence mutex, not sending " - "write all registers:\n%s", - strm.GetData()); + LLDB_LOGF(log, + "error: failed to get packet sequence mutex, not sending " + "write all registers:\n%s", + strm.GetData()); } else - log->Printf("error: failed to get packet sequence mutex, not sending " - "write all registers"); + LLDB_LOGF(log, + "error: failed to get packet sequence mutex, not sending " + "write all registers"); } } return false; diff --git a/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp b/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp index a6fdd8dd0707..f1762abc55f8 100644 --- a/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp +++ b/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp @@ -63,7 +63,6 @@ #include "lldb/Target/TargetList.h" #include "lldb/Target/ThreadPlanCallFunction.h" #include "lldb/Utility/Args.h" -#include "lldb/Utility/CleanUp.h" #include "lldb/Utility/FileSpec.h" #include "lldb/Utility/Reproducer.h" #include "lldb/Utility/State.h" @@ -81,12 +80,12 @@ #include "lldb/Host/Host.h" #include "lldb/Utility/StringExtractorGDBRemote.h" +#include "llvm/ADT/ScopeExit.h" #include "llvm/ADT/StringSwitch.h" #include "llvm/Support/Threading.h" #include "llvm/Support/raw_ostream.h" #define DEBUGSERVER_BASENAME "debugserver" -using namespace llvm; using namespace lldb; using namespace lldb_private; using namespace lldb_private::process_gdb_remote; @@ -99,51 +98,25 @@ namespace lldb { // namespace. This allows you to attach with a debugger and call this function // and get the packet history dumped to a file. void DumpProcessGDBRemotePacketHistory(void *p, const char *path) { - StreamFile strm; - Status error = FileSystem::Instance().Open(strm.GetFile(), FileSpec(path), - File::eOpenOptionWrite | - File::eOpenOptionCanCreate); - if (error.Success()) - ((ProcessGDBRemote *)p)->GetGDBRemote().DumpHistory(strm); + auto file = FileSystem::Instance().Open( + FileSpec(path), File::eOpenOptionWrite | File::eOpenOptionCanCreate); + if (!file) { + llvm::consumeError(file.takeError()); + return; + } + StreamFile stream(std::move(file.get())); + ((ProcessGDBRemote *)p)->GetGDBRemote().DumpHistory(stream); } } // namespace lldb namespace { -static constexpr PropertyDefinition g_properties[] = { - {"packet-timeout", - OptionValue::eTypeUInt64, - true, - 5 -#if defined(__has_feature) -#if __has_feature(address_sanitizer) - * 2 -#endif -#endif - , - nullptr, - {}, - "Specify the default packet timeout in seconds."}, - {"target-definition-file", - OptionValue::eTypeFileSpec, - true, - 0, - nullptr, - {}, - "The file that provides the description for remote target registers."}, - {"use-libraries-svr4", - OptionValue::eTypeBoolean, - true, - false, - nullptr, - {}, - "If true, the libraries-svr4 feature will be used to get a hold of the " - "process's loaded modules."}}; +#define LLDB_PROPERTIES_processgdbremote +#include "ProcessGDBRemoteProperties.inc" enum { - ePropertyPacketTimeout, - ePropertyTargetDefinitionFile, - ePropertyUseSVR4 +#define LLDB_PROPERTIES_processgdbremote +#include "ProcessGDBRemotePropertiesEnum.inc" }; class PluginProperties : public Properties { @@ -154,7 +127,7 @@ public: PluginProperties() : Properties() { m_collection_sp = std::make_shared<OptionValueProperties>(GetSettingName()); - m_collection_sp->Initialize(g_properties); + m_collection_sp->Initialize(g_processgdbremote_properties); } ~PluginProperties() override {} @@ -162,7 +135,7 @@ public: uint64_t GetPacketTimeout() { const uint32_t idx = ePropertyPacketTimeout; return m_collection_sp->GetPropertyAtIndexAsUInt64( - nullptr, idx, g_properties[idx].default_uint_value); + nullptr, idx, g_processgdbremote_properties[idx].default_uint_value); } bool SetPacketTimeout(uint64_t timeout) { @@ -178,7 +151,8 @@ public: bool GetUseSVR4() const { const uint32_t idx = ePropertyUseSVR4; return m_collection_sp->GetPropertyAtIndexAsBoolean( - nullptr, idx, g_properties[idx].default_uint_value != 0); + nullptr, idx, + g_processgdbremote_properties[idx].default_uint_value != 0); } }; @@ -191,45 +165,6 @@ static const ProcessKDPPropertiesSP &GetGlobalPluginProperties() { return g_settings_sp; } -class ProcessGDBRemoteProvider - : public repro::Provider<ProcessGDBRemoteProvider> { -public: - struct Info { - static const char *name; - static const char *file; - }; - - ProcessGDBRemoteProvider(const FileSpec &directory) : Provider(directory) { - } - - raw_ostream *GetHistoryStream() { - FileSpec history_file = GetRoot().CopyByAppendingPathComponent(Info::file); - - std::error_code EC; - m_stream_up = llvm::make_unique<raw_fd_ostream>(history_file.GetPath(), EC, - sys::fs::OpenFlags::F_Text); - return m_stream_up.get(); - } - - void SetCallback(std::function<void()> callback) { - m_callback = std::move(callback); - } - - void Keep() override { m_callback(); } - - void Discard() override { m_callback(); } - - static char ID; - -private: - std::function<void()> m_callback; - std::unique_ptr<raw_fd_ostream> m_stream_up; -}; - -char ProcessGDBRemoteProvider::ID = 0; -const char *ProcessGDBRemoteProvider::Info::name = "gdb-remote"; -const char *ProcessGDBRemoteProvider::Info::file = "gdb-remote.yaml"; - } // namespace // TODO Randomly assigning a port is unsafe. We should get an unused @@ -339,8 +274,8 @@ ProcessGDBRemote::ProcessGDBRemote(lldb::TargetSP target_sp, "async thread did exit"); if (repro::Generator *g = repro::Reproducer::Instance().GetGenerator()) { - ProcessGDBRemoteProvider &provider = - g->GetOrCreate<ProcessGDBRemoteProvider>(); + repro::ProcessGDBRemoteProvider &provider = + g->GetOrCreate<repro::ProcessGDBRemoteProvider>(); // Set the history stream to the stream owned by the provider. m_gdb_comm.SetHistoryStream(provider.GetHistoryStream()); // Make sure to clear the stream again when we're finished. @@ -354,10 +289,10 @@ ProcessGDBRemote::ProcessGDBRemote(lldb::TargetSP target_sp, if (m_async_listener_sp->StartListeningForEvents( &m_async_broadcaster, async_event_mask) != async_event_mask) { - if (log) - log->Printf("ProcessGDBRemote::%s failed to listen for " - "m_async_broadcaster events", - __FUNCTION__); + LLDB_LOGF(log, + "ProcessGDBRemote::%s failed to listen for " + "m_async_broadcaster events", + __FUNCTION__); } const uint32_t gdb_event_mask = @@ -365,9 +300,9 @@ ProcessGDBRemote::ProcessGDBRemote(lldb::TargetSP target_sp, GDBRemoteCommunication::eBroadcastBitGdbReadThreadGotNotify; if (m_async_listener_sp->StartListeningForEvents( &m_gdb_comm, gdb_event_mask) != gdb_event_mask) { - if (log) - log->Printf("ProcessGDBRemote::%s failed to listen for m_gdb_comm events", - __FUNCTION__); + LLDB_LOGF(log, + "ProcessGDBRemote::%s failed to listen for m_gdb_comm events", + __FUNCTION__); } const uint64_t timeout_seconds = @@ -785,15 +720,15 @@ Status ProcessGDBRemote::DoConnectRemote(Stream *strm, pid, remote_url.str().c_str()); } - if (log) - log->Printf("ProcessGDBRemote::%s pid %" PRIu64 - ": normalizing target architecture initial triple: %s " - "(GetTarget().GetArchitecture().IsValid() %s, " - "m_gdb_comm.GetHostArchitecture().IsValid(): %s)", - __FUNCTION__, GetID(), - GetTarget().GetArchitecture().GetTriple().getTriple().c_str(), - GetTarget().GetArchitecture().IsValid() ? "true" : "false", - m_gdb_comm.GetHostArchitecture().IsValid() ? "true" : "false"); + LLDB_LOGF(log, + "ProcessGDBRemote::%s pid %" PRIu64 + ": normalizing target architecture initial triple: %s " + "(GetTarget().GetArchitecture().IsValid() %s, " + "m_gdb_comm.GetHostArchitecture().IsValid(): %s)", + __FUNCTION__, GetID(), + GetTarget().GetArchitecture().GetTriple().getTriple().c_str(), + GetTarget().GetArchitecture().IsValid() ? "true" : "false", + m_gdb_comm.GetHostArchitecture().IsValid() ? "true" : "false"); if (error.Success() && !GetTarget().GetArchitecture().IsValid() && m_gdb_comm.GetHostArchitecture().IsValid()) { @@ -805,11 +740,11 @@ Status ProcessGDBRemote::DoConnectRemote(Stream *strm, GetTarget().SetArchitecture(m_gdb_comm.GetHostArchitecture()); } - if (log) - log->Printf("ProcessGDBRemote::%s pid %" PRIu64 - ": normalized target architecture triple: %s", - __FUNCTION__, GetID(), - GetTarget().GetArchitecture().GetTriple().getTriple().c_str()); + LLDB_LOGF(log, + "ProcessGDBRemote::%s pid %" PRIu64 + ": normalized target architecture triple: %s", + __FUNCTION__, GetID(), + GetTarget().GetArchitecture().GetTriple().getTriple().c_str()); if (error.Success()) { PlatformSP platform_sp = GetTarget().GetPlatform(); @@ -834,8 +769,7 @@ Status ProcessGDBRemote::DoLaunch(lldb_private::Module *exe_module, Log *log(ProcessGDBRemoteLog::GetLogIfAllCategoriesSet(GDBR_LOG_PROCESS)); Status error; - if (log) - log->Printf("ProcessGDBRemote::%s() entered", __FUNCTION__); + LLDB_LOGF(log, "ProcessGDBRemote::%s() entered", __FUNCTION__); uint32_t launch_flags = launch_info.GetFlags().Get(); FileSpec stdin_file_spec{}; @@ -862,15 +796,17 @@ Status ProcessGDBRemote::DoLaunch(lldb_private::Module *exe_module, if (log) { if (stdin_file_spec || stdout_file_spec || stderr_file_spec) - log->Printf("ProcessGDBRemote::%s provided with STDIO paths via " - "launch_info: stdin=%s, stdout=%s, stderr=%s", - __FUNCTION__, - stdin_file_spec ? stdin_file_spec.GetCString() : "<null>", - stdout_file_spec ? stdout_file_spec.GetCString() : "<null>", - stderr_file_spec ? stderr_file_spec.GetCString() : "<null>"); + LLDB_LOGF(log, + "ProcessGDBRemote::%s provided with STDIO paths via " + "launch_info: stdin=%s, stdout=%s, stderr=%s", + __FUNCTION__, + stdin_file_spec ? stdin_file_spec.GetCString() : "<null>", + stdout_file_spec ? stdout_file_spec.GetCString() : "<null>", + stderr_file_spec ? stderr_file_spec.GetCString() : "<null>"); else - log->Printf("ProcessGDBRemote::%s no STDIO paths given via launch_info", - __FUNCTION__); + LLDB_LOGF(log, + "ProcessGDBRemote::%s no STDIO paths given via launch_info", + __FUNCTION__); } const bool disable_stdio = (launch_flags & eLaunchFlagDisableSTDIO) != 0; @@ -925,24 +861,23 @@ Status ProcessGDBRemote::DoLaunch(lldb_private::Module *exe_module, if (!stderr_file_spec) stderr_file_spec = slave_name; } - if (log) - log->Printf( - "ProcessGDBRemote::%s adjusted STDIO paths for local platform " - "(IsHost() is true) using slave: stdin=%s, stdout=%s, stderr=%s", - __FUNCTION__, - stdin_file_spec ? stdin_file_spec.GetCString() : "<null>", - stdout_file_spec ? stdout_file_spec.GetCString() : "<null>", - stderr_file_spec ? stderr_file_spec.GetCString() : "<null>"); + LLDB_LOGF( + log, + "ProcessGDBRemote::%s adjusted STDIO paths for local platform " + "(IsHost() is true) using slave: stdin=%s, stdout=%s, stderr=%s", + __FUNCTION__, + stdin_file_spec ? stdin_file_spec.GetCString() : "<null>", + stdout_file_spec ? stdout_file_spec.GetCString() : "<null>", + stderr_file_spec ? stderr_file_spec.GetCString() : "<null>"); } - if (log) - log->Printf("ProcessGDBRemote::%s final STDIO paths after all " - "adjustments: stdin=%s, stdout=%s, stderr=%s", - __FUNCTION__, - stdin_file_spec ? stdin_file_spec.GetCString() : "<null>", - stdout_file_spec ? stdout_file_spec.GetCString() : "<null>", - stderr_file_spec ? stderr_file_spec.GetCString() - : "<null>"); + LLDB_LOGF(log, + "ProcessGDBRemote::%s final STDIO paths after all " + "adjustments: stdin=%s, stdout=%s, stderr=%s", + __FUNCTION__, + stdin_file_spec ? stdin_file_spec.GetCString() : "<null>", + stdout_file_spec ? stdout_file_spec.GetCString() : "<null>", + stderr_file_spec ? stderr_file_spec.GetCString() : "<null>"); if (stdin_file_spec) m_gdb_comm.SetSTDIN(stdin_file_spec); @@ -988,9 +923,8 @@ Status ProcessGDBRemote::DoLaunch(lldb_private::Module *exe_module, } if (GetID() == LLDB_INVALID_PROCESS_ID) { - if (log) - log->Printf("failed to connect to debugserver: %s", - error.AsCString()); + LLDB_LOGF(log, "failed to connect to debugserver: %s", + error.AsCString()); KillDebugserverProcess(); return error; } @@ -1020,8 +954,7 @@ Status ProcessGDBRemote::DoLaunch(lldb_private::Module *exe_module, } } } else { - if (log) - log->Printf("failed to connect to debugserver: %s", error.AsCString()); + LLDB_LOGF(log, "failed to connect to debugserver: %s", error.AsCString()); } } else { // Set our user ID to an invalid process ID. @@ -1040,9 +973,8 @@ Status ProcessGDBRemote::ConnectToDebugserver(llvm::StringRef connect_url) { Log *log(ProcessGDBRemoteLog::GetLogIfAllCategoriesSet(GDBR_LOG_PROCESS)); if (!connect_url.empty()) { - if (log) - log->Printf("ProcessGDBRemote::%s Connecting to %s", __FUNCTION__, - connect_url.str().c_str()); + LLDB_LOGF(log, "ProcessGDBRemote::%s Connecting to %s", __FUNCTION__, + connect_url.str().c_str()); std::unique_ptr<ConnectionFileDescriptor> conn_up( new ConnectionFileDescriptor()); if (conn_up) { @@ -1062,7 +994,7 @@ Status ProcessGDBRemote::ConnectToDebugserver(llvm::StringRef connect_url) { if (retry_count >= max_retry_count) break; - usleep(100000); + std::this_thread::sleep_for(std::chrono::milliseconds(100)); } } } @@ -1116,8 +1048,7 @@ Status ProcessGDBRemote::ConnectToDebugserver(llvm::StringRef connect_url) { void ProcessGDBRemote::DidLaunchOrAttach(ArchSpec &process_arch) { Log *log(ProcessGDBRemoteLog::GetLogIfAllCategoriesSet(GDBR_LOG_PROCESS)); - if (log) - log->Printf("ProcessGDBRemote::%s()", __FUNCTION__); + LLDB_LOGF(log, "ProcessGDBRemote::%s()", __FUNCTION__); if (GetID() != LLDB_INVALID_PROCESS_ID) { BuildDynamicRegisterInfo(false); @@ -1130,43 +1061,42 @@ void ProcessGDBRemote::DidLaunchOrAttach(ArchSpec &process_arch) { const ArchSpec &remote_process_arch = m_gdb_comm.GetProcessArchitecture(); if (remote_process_arch.IsValid()) { process_arch = remote_process_arch; - if (log) - log->Printf("ProcessGDBRemote::%s gdb-remote had process architecture, " - "using %s %s", - __FUNCTION__, - process_arch.GetArchitectureName() - ? process_arch.GetArchitectureName() - : "<null>", - process_arch.GetTriple().getTriple().c_str() - ? process_arch.GetTriple().getTriple().c_str() - : "<null>"); + LLDB_LOGF(log, + "ProcessGDBRemote::%s gdb-remote had process architecture, " + "using %s %s", + __FUNCTION__, + process_arch.GetArchitectureName() + ? process_arch.GetArchitectureName() + : "<null>", + process_arch.GetTriple().getTriple().c_str() + ? process_arch.GetTriple().getTriple().c_str() + : "<null>"); } else { process_arch = m_gdb_comm.GetHostArchitecture(); - if (log) - log->Printf("ProcessGDBRemote::%s gdb-remote did not have process " - "architecture, using gdb-remote host architecture %s %s", - __FUNCTION__, - process_arch.GetArchitectureName() - ? process_arch.GetArchitectureName() - : "<null>", - process_arch.GetTriple().getTriple().c_str() - ? process_arch.GetTriple().getTriple().c_str() - : "<null>"); + LLDB_LOGF(log, + "ProcessGDBRemote::%s gdb-remote did not have process " + "architecture, using gdb-remote host architecture %s %s", + __FUNCTION__, + process_arch.GetArchitectureName() + ? process_arch.GetArchitectureName() + : "<null>", + process_arch.GetTriple().getTriple().c_str() + ? process_arch.GetTriple().getTriple().c_str() + : "<null>"); } if (process_arch.IsValid()) { const ArchSpec &target_arch = GetTarget().GetArchitecture(); if (target_arch.IsValid()) { - if (log) - log->Printf( - "ProcessGDBRemote::%s analyzing target arch, currently %s %s", - __FUNCTION__, - target_arch.GetArchitectureName() - ? target_arch.GetArchitectureName() - : "<null>", - target_arch.GetTriple().getTriple().c_str() - ? target_arch.GetTriple().getTriple().c_str() - : "<null>"); + LLDB_LOGF(log, + "ProcessGDBRemote::%s analyzing target arch, currently %s %s", + __FUNCTION__, + target_arch.GetArchitectureName() + ? target_arch.GetArchitectureName() + : "<null>", + target_arch.GetTriple().getTriple().c_str() + ? target_arch.GetTriple().getTriple().c_str() + : "<null>"); // If the remote host is ARM and we have apple as the vendor, then // ARM executables and shared libraries can have mixed ARM @@ -1180,16 +1110,16 @@ void ProcessGDBRemote::DidLaunchOrAttach(ArchSpec &process_arch) { process_arch.GetMachine() == llvm::Triple::thumb) && process_arch.GetTriple().getVendor() == llvm::Triple::Apple) { GetTarget().SetArchitecture(process_arch); - if (log) - log->Printf("ProcessGDBRemote::%s remote process is ARM/Apple, " - "setting target arch to %s %s", - __FUNCTION__, - process_arch.GetArchitectureName() - ? process_arch.GetArchitectureName() - : "<null>", - process_arch.GetTriple().getTriple().c_str() - ? process_arch.GetTriple().getTriple().c_str() - : "<null>"); + LLDB_LOGF(log, + "ProcessGDBRemote::%s remote process is ARM/Apple, " + "setting target arch to %s %s", + __FUNCTION__, + process_arch.GetArchitectureName() + ? process_arch.GetArchitectureName() + : "<null>", + process_arch.GetTriple().getTriple().c_str() + ? process_arch.GetTriple().getTriple().c_str() + : "<null>"); } else { // Fill in what is missing in the triple const llvm::Triple &remote_triple = process_arch.GetTriple(); @@ -1211,16 +1141,16 @@ void ProcessGDBRemote::DidLaunchOrAttach(ArchSpec &process_arch) { } } - if (log) - log->Printf("ProcessGDBRemote::%s final target arch after " - "adjustments for remote architecture: %s %s", - __FUNCTION__, - target_arch.GetArchitectureName() - ? target_arch.GetArchitectureName() - : "<null>", - target_arch.GetTriple().getTriple().c_str() - ? target_arch.GetTriple().getTriple().c_str() - : "<null>"); + LLDB_LOGF(log, + "ProcessGDBRemote::%s final target arch after " + "adjustments for remote architecture: %s %s", + __FUNCTION__, + target_arch.GetArchitectureName() + ? target_arch.GetArchitectureName() + : "<null>", + target_arch.GetTriple().getTriple().c_str() + ? target_arch.GetTriple().getTriple().c_str() + : "<null>"); } else { // The target doesn't have a valid architecture yet, set it from the // architecture we got from the remote GDB server @@ -1247,8 +1177,7 @@ Status ProcessGDBRemote::DoAttachToProcessWithID( Log *log(ProcessGDBRemoteLog::GetLogIfAllCategoriesSet(GDBR_LOG_PROCESS)); Status error; - if (log) - log->Printf("ProcessGDBRemote::%s()", __FUNCTION__); + LLDB_LOGF(log, "ProcessGDBRemote::%s()", __FUNCTION__); // Clear out and clean up from any current state Clear(); @@ -1359,8 +1288,7 @@ Status ProcessGDBRemote::WillResume() { Status ProcessGDBRemote::DoResume() { Status error; Log *log(ProcessGDBRemoteLog::GetLogIfAllCategoriesSet(GDBR_LOG_PROCESS)); - if (log) - log->Printf("ProcessGDBRemote::Resume()"); + LLDB_LOGF(log, "ProcessGDBRemote::Resume()"); ListenerSP listener_sp( Listener::MakeListener("gdb-remote.resume-packet-sent")); @@ -1547,9 +1475,8 @@ Status ProcessGDBRemote::DoResume() { EventSP event_sp; if (!m_async_thread.IsJoinable()) { error.SetErrorString("Trying to resume but the async thread is dead."); - if (log) - log->Printf("ProcessGDBRemote::DoResume: Trying to resume but the " - "async thread is dead."); + LLDB_LOGF(log, "ProcessGDBRemote::DoResume: Trying to resume but the " + "async thread is dead."); return error; } @@ -1560,14 +1487,13 @@ Status ProcessGDBRemote::DoResume() { if (!listener_sp->GetEvent(event_sp, std::chrono::seconds(5))) { error.SetErrorString("Resume timed out."); - if (log) - log->Printf("ProcessGDBRemote::DoResume: Resume timed out."); + LLDB_LOGF(log, "ProcessGDBRemote::DoResume: Resume timed out."); } else if (event_sp->BroadcasterIs(&m_async_broadcaster)) { error.SetErrorString("Broadcast continue, but the async thread was " "killed before we got an ack back."); - if (log) - log->Printf("ProcessGDBRemote::DoResume: Broadcast continue, but the " - "async thread was killed before we got an ack back."); + LLDB_LOGF(log, + "ProcessGDBRemote::DoResume: Broadcast continue, but the " + "async thread was killed before we got an ack back."); return error; } } @@ -1864,8 +1790,7 @@ ThreadSP ProcessGDBRemote::SetThreadStopInfo( } for (const auto &pair : expedited_register_map) { - StringExtractor reg_value_extractor; - reg_value_extractor.GetStringRef() = pair.second; + StringExtractor reg_value_extractor(pair.second); DataBufferSP buffer_sp(new DataBufferHeap( reg_value_extractor.GetStringRef().size() / 2, 0)); reg_value_extractor.GetHexBytes(buffer_sp->GetData(), '\xcc'); @@ -1979,8 +1904,7 @@ ThreadSP ProcessGDBRemote::SetThreadStopInfo( if (watch_id == LLDB_INVALID_WATCH_ID) { Log *log(ProcessGDBRemoteLog::GetLogIfAllCategoriesSet( GDBR_LOG_WATCHPOINTS)); - if (log) - log->Printf("failed to find watchpoint"); + LLDB_LOGF(log, "failed to find watchpoint"); } thread_sp->SetStopInfo(StopInfo::CreateStopReasonWithWatchpointID( *thread_sp, watch_id, wp_hit_addr)); @@ -2400,7 +2324,12 @@ StateType ProcessGDBRemote::SetThreadStopInfo(StringExtractor &stop_packet) { ostr.Printf("%" PRIu64 " %" PRIu32, wp_addr, wp_index); description = ostr.GetString(); } else if (key.compare("library") == 0) { - LoadModules(); + auto error = LoadModules(); + if (error) { + Log *log( + ProcessGDBRemoteLog::GetLogIfAllCategoriesSet(GDBR_LOG_PROCESS)); + LLDB_LOG_ERROR(log, std::move(error), "Failed to load modules: {0}"); + } } else if (key.size() == 2 && ::isxdigit(key[0]) && ::isxdigit(key[1])) { uint32_t reg = UINT32_MAX; if (!key.getAsInteger(16, reg)) @@ -2474,7 +2403,7 @@ void ProcessGDBRemote::RefreshStateAfterStop() { // Clear the thread stop stack m_stop_packet_stack.clear(); } - + // If we have queried for a default thread id if (m_initial_tid != LLDB_INVALID_THREAD_ID) { m_thread_list.SetSelectedThreadByID(m_initial_tid); @@ -2501,8 +2430,7 @@ Status ProcessGDBRemote::DoHalt(bool &caused_stop) { Status ProcessGDBRemote::DoDetach(bool keep_stopped) { Status error; Log *log(ProcessGDBRemoteLog::GetLogIfAllCategoriesSet(GDBR_LOG_PROCESS)); - if (log) - log->Printf("ProcessGDBRemote::DoDetach(keep_stopped: %i)", keep_stopped); + LLDB_LOGF(log, "ProcessGDBRemote::DoDetach(keep_stopped: %i)", keep_stopped); error = m_gdb_comm.Detach(keep_stopped); if (log) { @@ -2510,8 +2438,9 @@ Status ProcessGDBRemote::DoDetach(bool keep_stopped) { log->PutCString( "ProcessGDBRemote::DoDetach() detach packet sent successfully"); else - log->Printf("ProcessGDBRemote::DoDetach() detach packet send failed: %s", - error.AsCString() ? error.AsCString() : "<unknown error>"); + LLDB_LOGF(log, + "ProcessGDBRemote::DoDetach() detach packet send failed: %s", + error.AsCString() ? error.AsCString() : "<unknown error>"); } if (!error.Success()) @@ -2530,8 +2459,7 @@ Status ProcessGDBRemote::DoDetach(bool keep_stopped) { Status ProcessGDBRemote::DoDestroy() { Status error; Log *log(ProcessGDBRemoteLog::GetLogIfAllCategoriesSet(GDBR_LOG_PROCESS)); - if (log) - log->Printf("ProcessGDBRemote::DoDestroy()"); + LLDB_LOGF(log, "ProcessGDBRemote::DoDestroy()"); // There is a bug in older iOS debugservers where they don't shut down the // process they are debugging properly. If the process is sitting at a @@ -2586,11 +2514,11 @@ Status ProcessGDBRemote::DoDestroy() { reason = stop_info_sp->GetStopReason(); if (reason == eStopReasonBreakpoint || reason == eStopReasonException) { - if (log) - log->Printf( - "ProcessGDBRemote::DoDestroy() - thread: 0x%4.4" PRIx64 - " stopped with reason: %s.", - thread_sp->GetProtocolID(), stop_info_sp->GetDescription()); + LLDB_LOGF(log, + "ProcessGDBRemote::DoDestroy() - thread: 0x%4.4" PRIx64 + " stopped with reason: %s.", + thread_sp->GetProtocolID(), + stop_info_sp->GetDescription()); stop_looks_like_crash = true; break; } @@ -2622,10 +2550,10 @@ Status ProcessGDBRemote::DoDestroy() { reason = stop_info_sp->GetStopReason(); if (reason != eStopReasonBreakpoint && reason != eStopReasonException) { - if (log) - log->Printf("ProcessGDBRemote::DoDestroy() - Suspending " - "thread: 0x%4.4" PRIx64 " before running.", - thread_sp->GetProtocolID()); + LLDB_LOGF(log, + "ProcessGDBRemote::DoDestroy() - Suspending " + "thread: 0x%4.4" PRIx64 " before running.", + thread_sp->GetProtocolID()); thread_sp->SetResumeState(eStateSuspended); } } @@ -2669,30 +2597,28 @@ Status ProcessGDBRemote::DoDestroy() { int status; ::pid_t reap_pid; reap_pid = waitpid(GetID(), &status, WNOHANG); - if (log) - log->Printf("Reaped pid: %d, status: %d.\n", reap_pid, status); + LLDB_LOGF(log, "Reaped pid: %d, status: %d.\n", reap_pid, status); } #endif SetLastStopPacket(response); ClearThreadIDList(); exit_status = response.GetHexU8(); } else { - if (log) - log->Printf("ProcessGDBRemote::DoDestroy - got unexpected response " - "to k packet: %s", - response.GetStringRef().c_str()); + LLDB_LOGF(log, + "ProcessGDBRemote::DoDestroy - got unexpected response " + "to k packet: %s", + response.GetStringRef().data()); exit_string.assign("got unexpected response to k packet: "); exit_string.append(response.GetStringRef()); } } else { - if (log) - log->Printf("ProcessGDBRemote::DoDestroy - failed to send k packet"); + LLDB_LOGF(log, "ProcessGDBRemote::DoDestroy - failed to send k packet"); exit_string.assign("failed to send the k packet"); } } else { - if (log) - log->Printf("ProcessGDBRemote::DoDestroy - killed or interrupted while " - "attaching"); + LLDB_LOGF(log, + "ProcessGDBRemote::DoDestroy - killed or interrupted while " + "attaching"); exit_string.assign("killed or interrupted while attaching."); } } else { @@ -2715,8 +2641,7 @@ void ProcessGDBRemote::SetLastStopPacket( response.GetStringRef().find(";reason:exec;") != std::string::npos; if (did_exec) { Log *log(ProcessGDBRemoteLog::GetLogIfAllCategoriesSet(GDBR_LOG_PROCESS)); - if (log) - log->Printf("ProcessGDBRemote::SetLastStopPacket () - detected exec"); + LLDB_LOGF(log, "ProcessGDBRemote::SetLastStopPacket () - detected exec"); m_thread_list_real.Clear(); m_thread_list.Clear(); @@ -2756,9 +2681,13 @@ addr_t ProcessGDBRemote::GetImageInfoAddress() { // the loaded module list can also provides a link map address if (addr == LLDB_INVALID_ADDRESS) { - LoadedModuleInfoList list; - if (GetLoadedModuleList(list).Success()) - addr = list.m_link_map; + llvm::Expected<LoadedModuleInfoList> list = GetLoadedModuleList(); + if (!list) { + Log *log(ProcessGDBRemoteLog::GetLogIfAllCategoriesSet(GDBR_LOG_PROCESS)); + LLDB_LOG_ERROR(log, list.takeError(), "Failed to read module list: {0}"); + } else { + addr = list->m_link_map; + } } return addr; @@ -2840,7 +2769,7 @@ size_t ProcessGDBRemote::DoReadMemory(addr_t addr, void *buf, size_t size, else error.SetErrorStringWithFormat( "unexpected response to GDB server memory read packet '%s': '%s'", - packet, response.GetStringRef().c_str()); + packet, response.GetStringRef().data()); } else { error.SetErrorStringWithFormat("failed to send packet: '%s'", packet); } @@ -2950,7 +2879,7 @@ Status ProcessGDBRemote::FlashErase(lldb::addr_t addr, size_t size) { else status.SetErrorStringWithFormat( "unexpected response to GDB server flash erase packet '%s': '%s'", - packet.GetData(), response.GetStringRef().c_str()); + packet.GetData(), response.GetStringRef().data()); } } else { status.SetErrorStringWithFormat("failed to send packet: '%s'", @@ -2978,7 +2907,7 @@ Status ProcessGDBRemote::FlashDone() { else status.SetErrorStringWithFormat( "unexpected response to GDB server flash done packet: '%s'", - response.GetStringRef().c_str()); + response.GetStringRef().data()); } } else { status.SetErrorStringWithFormat("failed to send flash done packet"); @@ -3041,7 +2970,7 @@ size_t ProcessGDBRemote::DoWriteMemory(addr_t addr, const void *buf, else error.SetErrorStringWithFormat( "unexpected response to GDB server memory write packet '%s': '%s'", - packet.GetData(), response.GetStringRef().c_str()); + packet.GetData(), response.GetStringRef().data()); } else { error.SetErrorStringWithFormat("failed to send packet: '%s'", packet.GetData()); @@ -3078,11 +3007,11 @@ lldb::addr_t ProcessGDBRemote::DoAllocateMemory(size_t size, m_addr_to_mmap_size[allocated_addr] = size; else { allocated_addr = LLDB_INVALID_ADDRESS; - if (log) - log->Printf("ProcessGDBRemote::%s no direct stub support for memory " - "allocation, and InferiorCallMmap also failed - is stub " - "missing register context save/restore capability?", - __FUNCTION__); + LLDB_LOGF(log, + "ProcessGDBRemote::%s no direct stub support for memory " + "allocation, and InferiorCallMmap also failed - is stub " + "missing register context save/restore capability?", + __FUNCTION__); } } @@ -3173,17 +3102,17 @@ Status ProcessGDBRemote::EnableBreakpointSite(BreakpointSite *bp_site) { const addr_t addr = bp_site->GetLoadAddress(); // Log that a breakpoint was requested - if (log) - log->Printf("ProcessGDBRemote::EnableBreakpointSite (size_id = %" PRIu64 - ") address = 0x%" PRIx64, - site_id, (uint64_t)addr); + LLDB_LOGF(log, + "ProcessGDBRemote::EnableBreakpointSite (size_id = %" PRIu64 + ") address = 0x%" PRIx64, + site_id, (uint64_t)addr); // Breakpoint already exists and is enabled if (bp_site->IsEnabled()) { - if (log) - log->Printf("ProcessGDBRemote::EnableBreakpointSite (size_id = %" PRIu64 - ") address = 0x%" PRIx64 " -- SUCCESS (already enabled)", - site_id, (uint64_t)addr); + LLDB_LOGF(log, + "ProcessGDBRemote::EnableBreakpointSite (size_id = %" PRIu64 + ") address = 0x%" PRIx64 " -- SUCCESS (already enabled)", + site_id, (uint64_t)addr); return error; } @@ -3231,8 +3160,7 @@ Status ProcessGDBRemote::EnableBreakpointSite(BreakpointSite *bp_site) { // We reach here when software breakpoints have been found to be // unsupported. For future calls to set a breakpoint, we will not attempt // to set a breakpoint with a type that is known not to be supported. - if (log) - log->Printf("Software breakpoints are unsupported"); + LLDB_LOGF(log, "Software breakpoints are unsupported"); // So we will fall through and try a hardware breakpoint } @@ -3270,8 +3198,7 @@ Status ProcessGDBRemote::EnableBreakpointSite(BreakpointSite *bp_site) { // We will reach here when the stub gives an unsupported response to a // hardware breakpoint - if (log) - log->Printf("Hardware breakpoints are unsupported"); + LLDB_LOGF(log, "Hardware breakpoints are unsupported"); // Finally we will falling through to a #trap style breakpoint } @@ -3293,10 +3220,10 @@ Status ProcessGDBRemote::DisableBreakpointSite(BreakpointSite *bp_site) { addr_t addr = bp_site->GetLoadAddress(); user_id_t site_id = bp_site->GetID(); Log *log(ProcessGDBRemoteLog::GetLogIfAllCategoriesSet(GDBR_LOG_BREAKPOINTS)); - if (log) - log->Printf("ProcessGDBRemote::DisableBreakpointSite (site_id = %" PRIu64 - ") addr = 0x%8.8" PRIx64, - site_id, (uint64_t)addr); + LLDB_LOGF(log, + "ProcessGDBRemote::DisableBreakpointSite (site_id = %" PRIu64 + ") addr = 0x%8.8" PRIx64, + site_id, (uint64_t)addr); if (bp_site->IsEnabled()) { const size_t bp_op_size = GetSoftwareBreakpointTrapOpcode(bp_site); @@ -3328,10 +3255,10 @@ Status ProcessGDBRemote::DisableBreakpointSite(BreakpointSite *bp_site) { if (error.Success()) bp_site->SetEnabled(false); } else { - if (log) - log->Printf("ProcessGDBRemote::DisableBreakpointSite (site_id = %" PRIu64 - ") addr = 0x%8.8" PRIx64 " -- SUCCESS (already disabled)", - site_id, (uint64_t)addr); + LLDB_LOGF(log, + "ProcessGDBRemote::DisableBreakpointSite (site_id = %" PRIu64 + ") addr = 0x%8.8" PRIx64 " -- SUCCESS (already disabled)", + site_id, (uint64_t)addr); return error; } @@ -3363,14 +3290,13 @@ Status ProcessGDBRemote::EnableWatchpoint(Watchpoint *wp, bool notify) { addr_t addr = wp->GetLoadAddress(); Log *log( ProcessGDBRemoteLog::GetLogIfAllCategoriesSet(GDBR_LOG_WATCHPOINTS)); - if (log) - log->Printf("ProcessGDBRemote::EnableWatchpoint(watchID = %" PRIu64 ")", - watchID); + LLDB_LOGF(log, "ProcessGDBRemote::EnableWatchpoint(watchID = %" PRIu64 ")", + watchID); if (wp->IsEnabled()) { - if (log) - log->Printf("ProcessGDBRemote::EnableWatchpoint(watchID = %" PRIu64 - ") addr = 0x%8.8" PRIx64 ": watchpoint already enabled.", - watchID, (uint64_t)addr); + LLDB_LOGF(log, + "ProcessGDBRemote::EnableWatchpoint(watchID = %" PRIu64 + ") addr = 0x%8.8" PRIx64 ": watchpoint already enabled.", + watchID, (uint64_t)addr); return error; } @@ -3403,16 +3329,16 @@ Status ProcessGDBRemote::DisableWatchpoint(Watchpoint *wp, bool notify) { addr_t addr = wp->GetLoadAddress(); - if (log) - log->Printf("ProcessGDBRemote::DisableWatchpoint (watchID = %" PRIu64 - ") addr = 0x%8.8" PRIx64, - watchID, (uint64_t)addr); + LLDB_LOGF(log, + "ProcessGDBRemote::DisableWatchpoint (watchID = %" PRIu64 + ") addr = 0x%8.8" PRIx64, + watchID, (uint64_t)addr); if (!wp->IsEnabled()) { - if (log) - log->Printf("ProcessGDBRemote::DisableWatchpoint (watchID = %" PRIu64 - ") addr = 0x%8.8" PRIx64 " -- SUCCESS (already disabled)", - watchID, (uint64_t)addr); + LLDB_LOGF(log, + "ProcessGDBRemote::DisableWatchpoint (watchID = %" PRIu64 + ") addr = 0x%8.8" PRIx64 " -- SUCCESS (already disabled)", + watchID, (uint64_t)addr); // See also 'class WatchpointSentry' within StopInfo.cpp. This disabling // attempt might come from the user-supplied actions, we'll route it in // order for the watchpoint object to intelligently process this action. @@ -3447,8 +3373,7 @@ void ProcessGDBRemote::Clear() { Status ProcessGDBRemote::DoSignal(int signo) { Status error; Log *log(ProcessGDBRemoteLog::GetLogIfAllCategoriesSet(GDBR_LOG_PROCESS)); - if (log) - log->Printf("ProcessGDBRemote::DoSignal (signal = %d)", signo); + LLDB_LOGF(log, "ProcessGDBRemote::DoSignal (signal = %d)", signo); if (!m_gdb_comm.SendAsyncSignal(signo)) error.SetErrorStringWithFormat("failed to send signal %i", signo); @@ -3460,7 +3385,8 @@ Status ProcessGDBRemote::ConnectToReplayServer(repro::Loader *loader) { return Status("No loader provided."); // Construct replay history path. - FileSpec history_file = loader->GetFile<ProcessGDBRemoteProvider::Info>(); + FileSpec history_file = + loader->GetFile<repro::ProcessGDBRemoteProvider::Info>(); if (!history_file) return Status("No provider for gdb-remote."); @@ -3556,8 +3482,8 @@ Status ProcessGDBRemote::LaunchAndConnectToDebugserver( int our_socket = sockets[0]; int gdb_socket = sockets[1]; - CleanUp cleanup_our(close, our_socket); - CleanUp cleanup_gdb(close, gdb_socket); + auto cleanup_our = llvm::make_scope_exit([&]() { close(our_socket); }); + auto cleanup_gdb = llvm::make_scope_exit([&]() { close(gdb_socket); }); // Don't let any child processes inherit our communication socket SetCloexecFlag(our_socket); @@ -3577,7 +3503,7 @@ Status ProcessGDBRemote::LaunchAndConnectToDebugserver( #ifdef USE_SOCKETPAIR_FOR_LOCAL_CONNECTION // Our process spawned correctly, we can now set our connection to use // our end of the socket pair - cleanup_our.disable(); + cleanup_our.release(); m_gdb_comm.SetConnection(new ConnectionFileDescriptor(our_socket, true)); #endif StartAsyncThread(); @@ -3586,9 +3512,8 @@ Status ProcessGDBRemote::LaunchAndConnectToDebugserver( if (error.Fail()) { Log *log(ProcessGDBRemoteLog::GetLogIfAllCategoriesSet(GDBR_LOG_PROCESS)); - if (log) - log->Printf("failed to start debugserver process: %s", - error.AsCString()); + LLDB_LOGF(log, "failed to start debugserver process: %s", + error.AsCString()); return error; } @@ -3614,22 +3539,22 @@ bool ProcessGDBRemote::MonitorDebugserverProcess( Log *log(ProcessGDBRemoteLog::GetLogIfAllCategoriesSet(GDBR_LOG_PROCESS)); const bool handled = true; - if (log) - log->Printf("ProcessGDBRemote::%s(process_wp, pid=%" PRIu64 - ", signo=%i (0x%x), exit_status=%i)", - __FUNCTION__, debugserver_pid, signo, signo, exit_status); + LLDB_LOGF(log, + "ProcessGDBRemote::%s(process_wp, pid=%" PRIu64 + ", signo=%i (0x%x), exit_status=%i)", + __FUNCTION__, debugserver_pid, signo, signo, exit_status); std::shared_ptr<ProcessGDBRemote> process_sp = process_wp.lock(); - if (log) - log->Printf("ProcessGDBRemote::%s(process = %p)", __FUNCTION__, - static_cast<void *>(process_sp.get())); + LLDB_LOGF(log, "ProcessGDBRemote::%s(process = %p)", __FUNCTION__, + static_cast<void *>(process_sp.get())); if (!process_sp || process_sp->m_debugserver_pid != debugserver_pid) return handled; // Sleep for a half a second to make sure our inferior process has time to // set its exit status before we set it incorrectly when both the debugserver // and the inferior process shut down. - usleep(500000); + std::this_thread::sleep_for(std::chrono::milliseconds(500)); + // If our process hasn't yet exited, debugserver might have died. If the // process did exit, then we are reaping it. const StateType state = process_sp->GetState(); @@ -3692,8 +3617,7 @@ void ProcessGDBRemote::DebuggerInitialize(Debugger &debugger) { bool ProcessGDBRemote::StartAsyncThread() { Log *log(ProcessGDBRemoteLog::GetLogIfAllCategoriesSet(GDBR_LOG_PROCESS)); - if (log) - log->Printf("ProcessGDBRemote::%s ()", __FUNCTION__); + LLDB_LOGF(log, "ProcessGDBRemote::%s ()", __FUNCTION__); std::lock_guard<std::recursive_mutex> guard(m_async_thread_state_mutex); if (!m_async_thread.IsJoinable()) { @@ -3709,10 +3633,11 @@ bool ProcessGDBRemote::StartAsyncThread() { return false; } m_async_thread = *async_thread; - } else if (log) - log->Printf("ProcessGDBRemote::%s () - Called when Async thread was " - "already running.", - __FUNCTION__); + } else + LLDB_LOGF(log, + "ProcessGDBRemote::%s () - Called when Async thread was " + "already running.", + __FUNCTION__); return m_async_thread.IsJoinable(); } @@ -3720,8 +3645,7 @@ bool ProcessGDBRemote::StartAsyncThread() { void ProcessGDBRemote::StopAsyncThread() { Log *log(ProcessGDBRemoteLog::GetLogIfAllCategoriesSet(GDBR_LOG_PROCESS)); - if (log) - log->Printf("ProcessGDBRemote::%s ()", __FUNCTION__); + LLDB_LOGF(log, "ProcessGDBRemote::%s ()", __FUNCTION__); std::lock_guard<std::recursive_mutex> guard(m_async_thread_state_mutex); if (m_async_thread.IsJoinable()) { @@ -3733,8 +3657,9 @@ void ProcessGDBRemote::StopAsyncThread() { // Stop the stdio thread m_async_thread.Join(nullptr); m_async_thread.Reset(); - } else if (log) - log->Printf( + } else + LLDB_LOGF( + log, "ProcessGDBRemote::%s () - Called when Async thread was not running.", __FUNCTION__); } @@ -3768,25 +3693,25 @@ thread_result_t ProcessGDBRemote::AsyncThread(void *arg) { ProcessGDBRemote *process = (ProcessGDBRemote *)arg; Log *log(ProcessGDBRemoteLog::GetLogIfAllCategoriesSet(GDBR_LOG_PROCESS)); - if (log) - log->Printf("ProcessGDBRemote::%s (arg = %p, pid = %" PRIu64 - ") thread starting...", - __FUNCTION__, arg, process->GetID()); + LLDB_LOGF(log, + "ProcessGDBRemote::%s (arg = %p, pid = %" PRIu64 + ") thread starting...", + __FUNCTION__, arg, process->GetID()); EventSP event_sp; bool done = false; while (!done) { - if (log) - log->Printf("ProcessGDBRemote::%s (arg = %p, pid = %" PRIu64 - ") listener.WaitForEvent (NULL, event_sp)...", - __FUNCTION__, arg, process->GetID()); + LLDB_LOGF(log, + "ProcessGDBRemote::%s (arg = %p, pid = %" PRIu64 + ") listener.WaitForEvent (NULL, event_sp)...", + __FUNCTION__, arg, process->GetID()); if (process->m_async_listener_sp->GetEvent(event_sp, llvm::None)) { const uint32_t event_type = event_sp->GetType(); if (event_sp->BroadcasterIs(&process->m_async_broadcaster)) { - if (log) - log->Printf("ProcessGDBRemote::%s (arg = %p, pid = %" PRIu64 - ") Got an event of type: %d...", - __FUNCTION__, arg, process->GetID(), event_type); + LLDB_LOGF(log, + "ProcessGDBRemote::%s (arg = %p, pid = %" PRIu64 + ") Got an event of type: %d...", + __FUNCTION__, arg, process->GetID(), event_type); switch (event_type) { case eBroadcastBitAsyncContinue: { @@ -3797,10 +3722,10 @@ thread_result_t ProcessGDBRemote::AsyncThread(void *arg) { const char *continue_cstr = (const char *)continue_packet->GetBytes(); const size_t continue_cstr_len = continue_packet->GetByteSize(); - if (log) - log->Printf("ProcessGDBRemote::%s (arg = %p, pid = %" PRIu64 - ") got eBroadcastBitAsyncContinue: %s", - __FUNCTION__, arg, process->GetID(), continue_cstr); + LLDB_LOGF(log, + "ProcessGDBRemote::%s (arg = %p, pid = %" PRIu64 + ") got eBroadcastBitAsyncContinue: %s", + __FUNCTION__, arg, process->GetID(), continue_cstr); if (::strstr(continue_cstr, "vAttach") == nullptr) process->SetPrivateState(eStateRunning); @@ -3891,18 +3816,18 @@ thread_result_t ProcessGDBRemote::AsyncThread(void *arg) { break; case eBroadcastBitAsyncThreadShouldExit: - if (log) - log->Printf("ProcessGDBRemote::%s (arg = %p, pid = %" PRIu64 - ") got eBroadcastBitAsyncThreadShouldExit...", - __FUNCTION__, arg, process->GetID()); + LLDB_LOGF(log, + "ProcessGDBRemote::%s (arg = %p, pid = %" PRIu64 + ") got eBroadcastBitAsyncThreadShouldExit...", + __FUNCTION__, arg, process->GetID()); done = true; break; default: - if (log) - log->Printf("ProcessGDBRemote::%s (arg = %p, pid = %" PRIu64 - ") got unknown event 0x%8.8x", - __FUNCTION__, arg, process->GetID(), event_type); + LLDB_LOGF(log, + "ProcessGDBRemote::%s (arg = %p, pid = %" PRIu64 + ") got unknown event 0x%8.8x", + __FUNCTION__, arg, process->GetID(), event_type); done = true; break; } @@ -3925,27 +3850,27 @@ thread_result_t ProcessGDBRemote::AsyncThread(void *arg) { } default: - if (log) - log->Printf("ProcessGDBRemote::%s (arg = %p, pid = %" PRIu64 - ") got unknown event 0x%8.8x", - __FUNCTION__, arg, process->GetID(), event_type); + LLDB_LOGF(log, + "ProcessGDBRemote::%s (arg = %p, pid = %" PRIu64 + ") got unknown event 0x%8.8x", + __FUNCTION__, arg, process->GetID(), event_type); done = true; break; } } } else { - if (log) - log->Printf("ProcessGDBRemote::%s (arg = %p, pid = %" PRIu64 - ") listener.WaitForEvent (NULL, event_sp) => false", - __FUNCTION__, arg, process->GetID()); + LLDB_LOGF(log, + "ProcessGDBRemote::%s (arg = %p, pid = %" PRIu64 + ") listener.WaitForEvent (NULL, event_sp) => false", + __FUNCTION__, arg, process->GetID()); done = true; } } - if (log) - log->Printf("ProcessGDBRemote::%s (arg = %p, pid = %" PRIu64 - ") thread exiting...", - __FUNCTION__, arg, process->GetID()); + LLDB_LOGF(log, + "ProcessGDBRemote::%s (arg = %p, pid = %" PRIu64 + ") thread exiting...", + __FUNCTION__, arg, process->GetID()); return {}; } @@ -3977,8 +3902,7 @@ bool ProcessGDBRemote::NewThreadNotifyBreakpointHit( // thread when it starts to // run so I can stop it if that's what I want to do. Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_STEP)); - if (log) - log->Printf("Hit New Thread Notification breakpoint."); + LLDB_LOGF(log, "Hit New Thread Notification breakpoint."); return false; } @@ -4023,7 +3947,7 @@ bool ProcessGDBRemote::StartNoticingNewThreads() { Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_STEP)); if (m_thread_create_bp_sp) { if (log && log->GetVerbose()) - log->Printf("Enabled noticing new thread breakpoint."); + LLDB_LOGF(log, "Enabled noticing new thread breakpoint."); m_thread_create_bp_sp->SetEnabled(true); } else { PlatformSP platform_sp(GetTarget().GetPlatform()); @@ -4032,14 +3956,13 @@ bool ProcessGDBRemote::StartNoticingNewThreads() { platform_sp->SetThreadCreationBreakpoint(GetTarget()); if (m_thread_create_bp_sp) { if (log && log->GetVerbose()) - log->Printf( - "Successfully created new thread notification breakpoint %i", + LLDB_LOGF( + log, "Successfully created new thread notification breakpoint %i", m_thread_create_bp_sp->GetID()); m_thread_create_bp_sp->SetCallback( ProcessGDBRemote::NewThreadNotifyBreakpointHit, this, true); } else { - if (log) - log->Printf("Failed to create new thread notification breakpoint."); + LLDB_LOGF(log, "Failed to create new thread notification breakpoint."); } } } @@ -4049,7 +3972,7 @@ bool ProcessGDBRemote::StartNoticingNewThreads() { bool ProcessGDBRemote::StopNoticingNewThreads() { Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_STEP)); if (log && log->GetVerbose()) - log->Printf("Disabling new thread notification breakpoint."); + LLDB_LOGF(log, "Disabling new thread notification breakpoint."); if (m_thread_create_bp_sp) m_thread_create_bp_sp->SetEnabled(false); @@ -4325,19 +4248,18 @@ bool ProcessGDBRemote::GetModuleSpec(const FileSpec &module_file_spec, } if (!m_gdb_comm.GetModuleInfo(module_file_spec, arch, module_spec)) { - if (log) - log->Printf("ProcessGDBRemote::%s - failed to get module info for %s:%s", - __FUNCTION__, module_file_spec.GetPath().c_str(), - arch.GetTriple().getTriple().c_str()); + LLDB_LOGF(log, "ProcessGDBRemote::%s - failed to get module info for %s:%s", + __FUNCTION__, module_file_spec.GetPath().c_str(), + arch.GetTriple().getTriple().c_str()); return false; } if (log) { StreamString stream; module_spec.Dump(stream); - log->Printf("ProcessGDBRemote::%s - got module info for (%s:%s) : %s", - __FUNCTION__, module_file_spec.GetPath().c_str(), - arch.GetTriple().getTriple().c_str(), stream.GetData()); + LLDB_LOGF(log, "ProcessGDBRemote::%s - got module info for (%s:%s) : %s", + __FUNCTION__, module_file_spec.GetPath().c_str(), + arch.GetTriple().getTriple().c_str(), stream.GetData()); } m_cached_module_specs[key] = module_spec; @@ -4361,6 +4283,10 @@ llvm::VersionTuple ProcessGDBRemote::GetHostOSVersion() { return m_gdb_comm.GetOSVersion(); } +llvm::VersionTuple ProcessGDBRemote::GetHostMacCatalystVersion() { + return m_gdb_comm.GetMacCatalystVersion(); +} + namespace { typedef std::vector<std::string> stringVec; @@ -4492,14 +4418,13 @@ bool ParseRegisters(XMLNode feature_node, GdbServerTargetInfo &target_info, } else if (name == "invalidate_regnums") { SplitCommaSeparatedRegisterNumberString(value, invalidate_regs, 0); } else if (name == "dynamic_size_dwarf_expr_bytes") { - StringExtractor opcode_extractor; std::string opcode_string = value.str(); size_t dwarf_opcode_len = opcode_string.length() / 2; assert(dwarf_opcode_len > 0); dwarf_opcode_bytes.resize(dwarf_opcode_len); reg_info.dynamic_size_dwarf_len = dwarf_opcode_len; - opcode_extractor.GetStringRef().swap(opcode_string); + StringExtractor opcode_extractor(opcode_string); uint32_t ret_val = opcode_extractor.GetHexBytesAvail(dwarf_opcode_bytes); assert(dwarf_opcode_len == ret_val); @@ -4565,16 +4490,15 @@ bool ParseRegisters(XMLNode feature_node, GdbServerTargetInfo &target_info, // information to the current process. It will call itself recursively // for nested register definition files. It returns true if it was able // to fetch and parse an xml file. -bool ProcessGDBRemote::GetGDBServerRegisterInfoXMLAndProcess(ArchSpec &arch_to_use, - std::string xml_filename, - uint32_t &cur_reg_num, - uint32_t ®_offset) { +bool ProcessGDBRemote::GetGDBServerRegisterInfoXMLAndProcess( + ArchSpec &arch_to_use, std::string xml_filename, uint32_t &cur_reg_num, + uint32_t ®_offset) { // request the target xml file std::string raw; lldb_private::Status lldberr; - if (!m_gdb_comm.ReadExtFeature(ConstString("features"), - ConstString(xml_filename.c_str()), - raw, lldberr)) { + if (!m_gdb_comm.ReadExtFeature(ConstString("features"), + ConstString(xml_filename.c_str()), raw, + lldberr)) { return false; } @@ -4676,8 +4600,8 @@ bool ProcessGDBRemote::GetGDBServerRegisterInfoXMLAndProcess(ArchSpec &arch_to_u } for (const auto &include : target_info.includes) { - GetGDBServerRegisterInfoXMLAndProcess(arch_to_use, include, - cur_reg_num, reg_offset); + GetGDBServerRegisterInfoXMLAndProcess(arch_to_use, include, cur_reg_num, + reg_offset); } } } else { @@ -4705,41 +4629,43 @@ bool ProcessGDBRemote::GetGDBServerRegisterInfo(ArchSpec &arch_to_use) { return m_register_info.GetNumRegisters() > 0; } -Status ProcessGDBRemote::GetLoadedModuleList(LoadedModuleInfoList &list) { +llvm::Expected<LoadedModuleInfoList> ProcessGDBRemote::GetLoadedModuleList() { // Make sure LLDB has an XML parser it can use first if (!XMLDocument::XMLEnabled()) - return Status(0, ErrorType::eErrorTypeGeneric); + return llvm::createStringError(llvm::inconvertibleErrorCode(), + "XML parsing not available"); Log *log = GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PROCESS); - if (log) - log->Printf("ProcessGDBRemote::%s", __FUNCTION__); + LLDB_LOGF(log, "ProcessGDBRemote::%s", __FUNCTION__); + LoadedModuleInfoList list; GDBRemoteCommunicationClient &comm = m_gdb_comm; bool can_use_svr4 = GetGlobalPluginProperties()->GetUseSVR4(); // check that we have extended feature read support if (can_use_svr4 && comm.GetQXferLibrariesSVR4ReadSupported()) { - list.clear(); - // request the loaded library list std::string raw; lldb_private::Status lldberr; if (!comm.ReadExtFeature(ConstString("libraries-svr4"), ConstString(""), raw, lldberr)) - return Status(0, ErrorType::eErrorTypeGeneric); + return llvm::createStringError(llvm::inconvertibleErrorCode(), + "Error in libraries-svr4 packet"); // parse the xml file in memory - if (log) - log->Printf("parsing: %s", raw.c_str()); + LLDB_LOGF(log, "parsing: %s", raw.c_str()); XMLDocument doc; if (!doc.ParseMemory(raw.c_str(), raw.size(), "noname.xml")) - return Status(0, ErrorType::eErrorTypeGeneric); + return llvm::createStringError(llvm::inconvertibleErrorCode(), + "Error reading noname.xml"); XMLNode root_element = doc.GetRootElement("library-list-svr4"); if (!root_element) - return Status(); + return llvm::createStringError( + llvm::inconvertibleErrorCode(), + "Error finding library-list-svr4 xml element"); // main link map structure llvm::StringRef main_lm = root_element.GetAttributeValue("main-lm"); @@ -4791,10 +4717,11 @@ Status ProcessGDBRemote::GetLoadedModuleList(LoadedModuleInfoList &list) { module.get_base_is_offset(base_is_offset); module.get_dynamic(ld); - log->Printf("found (link_map:0x%08" PRIx64 ", base:0x%08" PRIx64 - "[%s], ld:0x%08" PRIx64 ", name:'%s')", - lm, base, (base_is_offset ? "offset" : "absolute"), ld, - name.c_str()); + LLDB_LOGF(log, + "found (link_map:0x%08" PRIx64 ", base:0x%08" PRIx64 + "[%s], ld:0x%08" PRIx64 ", name:'%s')", + lm, base, (base_is_offset ? "offset" : "absolute"), ld, + name.c_str()); } list.add(module); @@ -4803,29 +4730,30 @@ Status ProcessGDBRemote::GetLoadedModuleList(LoadedModuleInfoList &list) { }); if (log) - log->Printf("found %" PRId32 " modules in total", - (int)list.m_list.size()); + LLDB_LOGF(log, "found %" PRId32 " modules in total", + (int)list.m_list.size()); + return list; } else if (comm.GetQXferLibrariesReadSupported()) { - list.clear(); - // request the loaded library list std::string raw; lldb_private::Status lldberr; if (!comm.ReadExtFeature(ConstString("libraries"), ConstString(""), raw, lldberr)) - return Status(0, ErrorType::eErrorTypeGeneric); + return llvm::createStringError(llvm::inconvertibleErrorCode(), + "Error in libraries packet"); - if (log) - log->Printf("parsing: %s", raw.c_str()); + LLDB_LOGF(log, "parsing: %s", raw.c_str()); XMLDocument doc; if (!doc.ParseMemory(raw.c_str(), raw.size(), "noname.xml")) - return Status(0, ErrorType::eErrorTypeGeneric); + return llvm::createStringError(llvm::inconvertibleErrorCode(), + "Error reading noname.xml"); XMLNode root_element = doc.GetRootElement("library-list"); if (!root_element) - return Status(); + return llvm::createStringError(llvm::inconvertibleErrorCode(), + "Error finding library-list xml element"); root_element.ForEachChildElementWithName( "library", [log, &list](const XMLNode &library) -> bool { @@ -4853,8 +4781,8 @@ Status ProcessGDBRemote::GetLoadedModuleList(LoadedModuleInfoList &list) { module.get_base(base); module.get_base_is_offset(base_is_offset); - log->Printf("found (base:0x%08" PRIx64 "[%s], name:'%s')", base, - (base_is_offset ? "offset" : "absolute"), name.c_str()); + LLDB_LOGF(log, "found (base:0x%08" PRIx64 "[%s], name:'%s')", base, + (base_is_offset ? "offset" : "absolute"), name.c_str()); } list.add(module); @@ -4863,13 +4791,13 @@ Status ProcessGDBRemote::GetLoadedModuleList(LoadedModuleInfoList &list) { }); if (log) - log->Printf("found %" PRId32 " modules in total", - (int)list.m_list.size()); + LLDB_LOGF(log, "found %" PRId32 " modules in total", + (int)list.m_list.size()); + return list; } else { - return Status(0, ErrorType::eErrorTypeGeneric); + return llvm::createStringError(llvm::inconvertibleErrorCode(), + "Remote libraries not supported"); } - - return Status(); } lldb::ModuleSP ProcessGDBRemote::LoadModuleAtAddress(const FileSpec &file, @@ -4884,17 +4812,18 @@ lldb::ModuleSP ProcessGDBRemote::LoadModuleAtAddress(const FileSpec &file, value_is_offset); } -size_t ProcessGDBRemote::LoadModules(LoadedModuleInfoList &module_list) { +llvm::Error ProcessGDBRemote::LoadModules() { using lldb_private::process_gdb_remote::ProcessGDBRemote; // request a list of loaded libraries from GDBServer - if (GetLoadedModuleList(module_list).Fail()) - return 0; + llvm::Expected<LoadedModuleInfoList> module_list = GetLoadedModuleList(); + if (!module_list) + return module_list.takeError(); // get a list of all the modules ModuleList new_modules; - for (LoadedModuleInfoList::LoadedModuleInfo &modInfo : module_list.m_list) { + for (LoadedModuleInfoList::LoadedModuleInfo &modInfo : module_list->m_list) { std::string mod_name; lldb::addr_t mod_base; lldb::addr_t link_map; @@ -4961,12 +4890,7 @@ size_t ProcessGDBRemote::LoadModules(LoadedModuleInfoList &module_list) { m_process->GetTarget().ModulesDidLoad(new_modules); } - return new_modules.GetSize(); -} - -size_t ProcessGDBRemote::LoadModules() { - LoadedModuleInfoList module_list; - return LoadModules(module_list); + return llvm::ErrorSuccess(); } Status ProcessGDBRemote::GetFileLoadAddress(const FileSpec &file, @@ -5149,7 +5073,8 @@ ParseStructuredDataPacket(llvm::StringRef packet) { if (!packet.consume_front(s_async_json_packet_prefix)) { if (log) { - log->Printf( + LLDB_LOGF( + log, "GDBRemoteCommunicationClientBase::%s() received $J packet " "but was not a StructuredData packet: packet starts with " "%s", @@ -5164,16 +5089,18 @@ ParseStructuredDataPacket(llvm::StringRef packet) { if (log) { if (json_sp) { StreamString json_str; - json_sp->Dump(json_str); + json_sp->Dump(json_str, true); json_str.Flush(); - log->Printf("ProcessGDBRemote::%s() " - "received Async StructuredData packet: %s", - __FUNCTION__, json_str.GetData()); + LLDB_LOGF(log, + "ProcessGDBRemote::%s() " + "received Async StructuredData packet: %s", + __FUNCTION__, json_str.GetData()); } else { - log->Printf("ProcessGDBRemote::%s" - "() received StructuredData packet:" - " parse failure", - __FUNCTION__); + LLDB_LOGF(log, + "ProcessGDBRemote::%s" + "() received StructuredData packet:" + " parse failure", + __FUNCTION__); } } return json_sp; @@ -5365,7 +5292,7 @@ public: result.SetStatus(eReturnStatusSuccessFinishResult); Stream &output_strm = result.GetOutputStream(); output_strm.Printf(" packet: %s\n", packet_cstr); - std::string &response_str = response.GetStringRef(); + std::string response_str = response.GetStringRef(); if (strstr(packet_cstr, "qGetProfileData") != nullptr) { response_str = process->HarmonizeThreadIdsForProfileData(response); @@ -5374,7 +5301,7 @@ public: if (response_str.empty()) output_strm.PutCString("response: \nerror: UNIMPLEMENTED\n"); else - output_strm.Printf("response: %s\n", response.GetStringRef().c_str()); + output_strm.Printf("response: %s\n", response.GetStringRef().data()); } } return true; @@ -5423,7 +5350,7 @@ public: if (response_str.empty()) output_strm.PutCString("response: \nerror: UNIMPLEMENTED\n"); else - output_strm.Printf("response: %s\n", response.GetStringRef().c_str()); + output_strm.Printf("response: %s\n", response.GetStringRef().data()); } return true; } diff --git a/source/Plugins/Process/gdb-remote/ProcessGDBRemote.h b/source/Plugins/Process/gdb-remote/ProcessGDBRemote.h index 9c41fc2e5e98..0e3e3b39d9c8 100644 --- a/source/Plugins/Process/gdb-remote/ProcessGDBRemote.h +++ b/source/Plugins/Process/gdb-remote/ProcessGDBRemote.h @@ -24,8 +24,8 @@ #include "lldb/Utility/ArchSpec.h" #include "lldb/Utility/Broadcaster.h" #include "lldb/Utility/ConstString.h" +#include "lldb/Utility/GDBRemote.h" #include "lldb/Utility/Status.h" -#include "lldb/Utility/StreamGDBRemote.h" #include "lldb/Utility/StreamString.h" #include "lldb/Utility/StringExtractor.h" #include "lldb/Utility/StringList.h" @@ -199,10 +199,11 @@ public: const llvm::Triple &triple) override; llvm::VersionTuple GetHostOSVersion() override; + llvm::VersionTuple GetHostMacCatalystVersion() override; - size_t LoadModules(LoadedModuleInfoList &module_list) override; + llvm::Error LoadModules() override; - size_t LoadModules() override; + llvm::Expected<LoadedModuleInfoList> GetLoadedModuleList() override; Status GetFileLoadAddress(const FileSpec &file, bool &is_loaded, lldb::addr_t &load_addr) override; @@ -391,9 +392,6 @@ protected: // Query remote GDBServer for register information bool GetGDBServerRegisterInfo(ArchSpec &arch); - // Query remote GDBServer for a detailed loaded library list - Status GetLoadedModuleList(LoadedModuleInfoList &); - lldb::ModuleSP LoadModuleAtAddress(const FileSpec &file, lldb::addr_t link_map, lldb::addr_t base_addr, diff --git a/source/Plugins/Process/gdb-remote/ProcessGDBRemoteProperties.td b/source/Plugins/Process/gdb-remote/ProcessGDBRemoteProperties.td new file mode 100644 index 000000000000..16e7723e3061 --- /dev/null +++ b/source/Plugins/Process/gdb-remote/ProcessGDBRemoteProperties.td @@ -0,0 +1,16 @@ +include "../../../../include/lldb/Core/PropertiesBase.td" + +let Definition = "processgdbremote" in { + def PacketTimeout: Property<"packet-timeout", "UInt64">, + Global, + DefaultUnsignedValue<5>, + Desc<"Specify the default packet timeout in seconds.">; + def TargetDefinitionFile: Property<"target-definition-file", "FileSpec">, + Global, + DefaultStringValue<"">, + Desc<"The file that provides the description for remote target registers.">; + def UseSVR4: Property<"use-libraries-svr4", "Boolean">, + Global, + DefaultFalse, + Desc<"If true, the libraries-svr4 feature will be used to get a hold of the process's loaded modules.">; +} diff --git a/source/Plugins/Process/gdb-remote/ThreadGDBRemote.cpp b/source/Plugins/Process/gdb-remote/ThreadGDBRemote.cpp index 6607bce4488b..8a6a58c55450 100644 --- a/source/Plugins/Process/gdb-remote/ThreadGDBRemote.cpp +++ b/source/Plugins/Process/gdb-remote/ThreadGDBRemote.cpp @@ -215,8 +215,7 @@ StructuredData::ObjectSP ThreadGDBRemote::FetchThreadExtendedInfo() { StructuredData::ObjectSP object_sp; const lldb::user_id_t tid = GetProtocolID(); Log *log(GetLogIfAnyCategoriesSet(GDBR_LOG_THREAD)); - if (log) - log->Printf("Fetching extended information for thread %4.4" PRIx64, tid); + LLDB_LOGF(log, "Fetching extended information for thread %4.4" PRIx64, tid); ProcessSP process_sp(GetProcess()); if (process_sp) { ProcessGDBRemote *gdb_process = @@ -230,9 +229,8 @@ void ThreadGDBRemote::WillResume(StateType resume_state) { int signo = GetResumeSignal(); const lldb::user_id_t tid = GetProtocolID(); Log *log(GetLogIfAnyCategoriesSet(GDBR_LOG_THREAD)); - if (log) - log->Printf("Resuming thread: %4.4" PRIx64 " with state: %s.", tid, - StateAsCString(resume_state)); + LLDB_LOGF(log, "Resuming thread: %4.4" PRIx64 " with state: %s.", tid, + StateAsCString(resume_state)); ProcessSP process_sp(GetProcess()); if (process_sp) { diff --git a/source/Plugins/Process/minidump/MinidumpParser.cpp b/source/Plugins/Process/minidump/MinidumpParser.cpp index ff015aa54b76..70933f91fe51 100644 --- a/source/Plugins/Process/minidump/MinidumpParser.cpp +++ b/source/Plugins/Process/minidump/MinidumpParser.cpp @@ -188,6 +188,7 @@ ArchSpec MinidumpParser::GetArchitecture() { case OSPlatform::Win32NT: case OSPlatform::Win32CE: triple.setOS(llvm::Triple::OSType::Win32); + triple.setVendor(llvm::Triple::VendorType::PC); break; case OSPlatform::Linux: triple.setOS(llvm::Triple::OSType::Linux); @@ -313,13 +314,15 @@ std::vector<const minidump::Module *> MinidumpParser::GetFilteredModuleList() { return filtered_modules; } -const MinidumpExceptionStream *MinidumpParser::GetExceptionStream() { - llvm::ArrayRef<uint8_t> data = GetStream(StreamType::Exception); +const minidump::ExceptionStream *MinidumpParser::GetExceptionStream() { + auto ExpectedStream = GetMinidumpFile().getExceptionStream(); + if (ExpectedStream) + return &*ExpectedStream; - if (data.size() == 0) - return nullptr; - - return MinidumpExceptionStream::Parse(data); + LLDB_LOG_ERROR(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PROCESS), + ExpectedStream.takeError(), + "Failed to read minidump exception stream: {0}"); + return nullptr; } llvm::Optional<minidump::Range> @@ -426,23 +429,35 @@ CreateRegionsCacheFromLinuxMaps(MinidumpParser &parser, static bool CreateRegionsCacheFromMemoryInfoList(MinidumpParser &parser, std::vector<MemoryRegionInfo> ®ions) { - auto data = parser.GetStream(StreamType::MemoryInfoList); - if (data.empty()) - return false; - auto mem_info_list = MinidumpMemoryInfo::ParseMemoryInfoList(data); - if (mem_info_list.empty()) + Log *log = GetLogIfAnyCategoriesSet(LIBLLDB_LOG_MODULES); + auto ExpectedInfo = parser.GetMinidumpFile().getMemoryInfoList(); + if (!ExpectedInfo) { + LLDB_LOG_ERROR(log, ExpectedInfo.takeError(), + "Failed to read memory info list: {0}"); return false; + } constexpr auto yes = MemoryRegionInfo::eYes; constexpr auto no = MemoryRegionInfo::eNo; - regions.reserve(mem_info_list.size()); - for (const auto &entry : mem_info_list) { + for (const MemoryInfo &entry : *ExpectedInfo) { MemoryRegionInfo region; - region.GetRange().SetRangeBase(entry->base_address); - region.GetRange().SetByteSize(entry->region_size); - region.SetReadable(entry->isReadable() ? yes : no); - region.SetWritable(entry->isWritable() ? yes : no); - region.SetExecutable(entry->isExecutable() ? yes : no); - region.SetMapped(entry->isMapped() ? yes : no); + region.GetRange().SetRangeBase(entry.BaseAddress); + region.GetRange().SetByteSize(entry.RegionSize); + + MemoryProtection prot = entry.Protect; + region.SetReadable(bool(prot & MemoryProtection::NoAccess) ? no : yes); + region.SetWritable( + bool(prot & (MemoryProtection::ReadWrite | MemoryProtection::WriteCopy | + MemoryProtection::ExecuteReadWrite | + MemoryProtection::ExeciteWriteCopy)) + ? yes + : no); + region.SetExecutable( + bool(prot & (MemoryProtection::Execute | MemoryProtection::ExecuteRead | + MemoryProtection::ExecuteReadWrite | + MemoryProtection::ExeciteWriteCopy)) + ? yes + : no); + region.SetMapped(entry.State != MemoryState::Free ? yes : no); regions.push_back(region); } return !regions.empty(); diff --git a/source/Plugins/Process/minidump/MinidumpParser.h b/source/Plugins/Process/minidump/MinidumpParser.h index fce64f0ed5fc..d206fe6c9a00 100644 --- a/source/Plugins/Process/minidump/MinidumpParser.h +++ b/source/Plugins/Process/minidump/MinidumpParser.h @@ -82,7 +82,7 @@ public: // have the same name, it keeps the copy with the lowest load address. std::vector<const minidump::Module *> GetFilteredModuleList(); - const MinidumpExceptionStream *GetExceptionStream(); + const llvm::minidump::ExceptionStream *GetExceptionStream(); llvm::Optional<Range> FindMemoryRange(lldb::addr_t addr); diff --git a/source/Plugins/Process/minidump/MinidumpTypes.cpp b/source/Plugins/Process/minidump/MinidumpTypes.cpp index d7fc6e43d090..ed00b1cc07db 100644 --- a/source/Plugins/Process/minidump/MinidumpTypes.cpp +++ b/source/Plugins/Process/minidump/MinidumpTypes.cpp @@ -57,17 +57,6 @@ LinuxProcStatus::Parse(llvm::ArrayRef<uint8_t> &data) { lldb::pid_t LinuxProcStatus::GetPid() const { return pid; } -// Exception stuff -const MinidumpExceptionStream * -MinidumpExceptionStream::Parse(llvm::ArrayRef<uint8_t> &data) { - const MinidumpExceptionStream *exception_stream = nullptr; - Status error = consumeObject(data, exception_stream); - if (error.Fail()) - return nullptr; - - return exception_stream; -} - std::pair<llvm::ArrayRef<MinidumpMemoryDescriptor64>, uint64_t> MinidumpMemoryDescriptor64::ParseMemory64List(llvm::ArrayRef<uint8_t> &data) { const llvm::support::ulittle64_t *mem_ranges_count; @@ -87,29 +76,3 @@ MinidumpMemoryDescriptor64::ParseMemory64List(llvm::ArrayRef<uint8_t> &data) { *mem_ranges_count), *base_rva); } - -std::vector<const MinidumpMemoryInfo *> -MinidumpMemoryInfo::ParseMemoryInfoList(llvm::ArrayRef<uint8_t> &data) { - const MinidumpMemoryInfoListHeader *header; - Status error = consumeObject(data, header); - if (error.Fail() || - header->size_of_header < sizeof(MinidumpMemoryInfoListHeader) || - header->size_of_entry < sizeof(MinidumpMemoryInfo)) - return {}; - - data = data.drop_front(header->size_of_header - - sizeof(MinidumpMemoryInfoListHeader)); - - if (header->size_of_entry * header->num_of_entries > data.size()) - return {}; - - std::vector<const MinidumpMemoryInfo *> result; - result.reserve(header->num_of_entries); - - for (uint64_t i = 0; i < header->num_of_entries; ++i) { - result.push_back(reinterpret_cast<const MinidumpMemoryInfo *>( - data.data() + i * header->size_of_entry)); - } - - return result; -} diff --git a/source/Plugins/Process/minidump/MinidumpTypes.h b/source/Plugins/Process/minidump/MinidumpTypes.h index b4878e82de5d..a9c807930ebf 100644 --- a/source/Plugins/Process/minidump/MinidumpTypes.h +++ b/source/Plugins/Process/minidump/MinidumpTypes.h @@ -85,90 +85,6 @@ struct MinidumpMemoryDescriptor64 { static_assert(sizeof(MinidumpMemoryDescriptor64) == 16, "sizeof MinidumpMemoryDescriptor64 is not correct!"); -// Reference: -// https://msdn.microsoft.com/en-us/library/windows/desktop/ms680385(v=vs.85).aspx -struct MinidumpMemoryInfoListHeader { - llvm::support::ulittle32_t size_of_header; - llvm::support::ulittle32_t size_of_entry; - llvm::support::ulittle64_t num_of_entries; -}; -static_assert(sizeof(MinidumpMemoryInfoListHeader) == 16, - "sizeof MinidumpMemoryInfoListHeader is not correct!"); - -enum class MinidumpMemoryInfoState : uint32_t { - MemCommit = 0x1000, - MemFree = 0x10000, - MemReserve = 0x2000, - LLVM_MARK_AS_BITMASK_ENUM(/* LargestValue = */ MemFree) -}; - -enum class MinidumpMemoryInfoType : uint32_t { - MemImage = 0x1000000, - MemMapped = 0x40000, - MemPrivate = 0x20000, - LLVM_MARK_AS_BITMASK_ENUM(/* LargestValue = */ MemImage) -}; - -// Reference: -// https://msdn.microsoft.com/en-us/library/windows/desktop/aa366786(v=vs.85).aspx -enum class MinidumpMemoryProtectionContants : uint32_t { - PageExecute = 0x10, - PageExecuteRead = 0x20, - PageExecuteReadWrite = 0x40, - PageExecuteWriteCopy = 0x80, - PageNoAccess = 0x01, - PageReadOnly = 0x02, - PageReadWrite = 0x04, - PageWriteCopy = 0x08, - PageTargetsInvalid = 0x40000000, - PageTargetsNoUpdate = 0x40000000, - - PageWritable = PageExecuteReadWrite | PageExecuteWriteCopy | PageReadWrite | - PageWriteCopy, - PageExecutable = PageExecute | PageExecuteRead | PageExecuteReadWrite | - PageExecuteWriteCopy, - LLVM_MARK_AS_BITMASK_ENUM(/* LargestValue = */ PageTargetsInvalid) -}; - -// Reference: -// https://msdn.microsoft.com/en-us/library/windows/desktop/ms680386(v=vs.85).aspx -struct MinidumpMemoryInfo { - llvm::support::ulittle64_t base_address; - llvm::support::ulittle64_t allocation_base; - llvm::support::ulittle32_t allocation_protect; - llvm::support::ulittle32_t alignment1; - llvm::support::ulittle64_t region_size; - llvm::support::ulittle32_t state; - llvm::support::ulittle32_t protect; - llvm::support::ulittle32_t type; - llvm::support::ulittle32_t alignment2; - - static std::vector<const MinidumpMemoryInfo *> - ParseMemoryInfoList(llvm::ArrayRef<uint8_t> &data); - - bool isReadable() const { - const auto mask = MinidumpMemoryProtectionContants::PageNoAccess; - return (static_cast<uint32_t>(mask) & protect) == 0; - } - - bool isWritable() const { - const auto mask = MinidumpMemoryProtectionContants::PageWritable; - return (static_cast<uint32_t>(mask) & protect) != 0; - } - - bool isExecutable() const { - const auto mask = MinidumpMemoryProtectionContants::PageExecutable; - return (static_cast<uint32_t>(mask) & protect) != 0; - } - - bool isMapped() const { - return state != static_cast<uint32_t>(MinidumpMemoryInfoState::MemFree); - } -}; - -static_assert(sizeof(MinidumpMemoryInfo) == 48, - "sizeof MinidumpMemoryInfo is not correct!"); - // TODO misc2, misc3 ? // Reference: // https://msdn.microsoft.com/en-us/library/windows/desktop/ms680389(v=vs.85).aspx @@ -202,35 +118,6 @@ private: LinuxProcStatus() = default; }; -// Exception stuff -struct MinidumpException { - enum : unsigned { - ExceptonInfoMaxParams = 15, - DumpRequested = 0xFFFFFFFF, - }; - - llvm::support::ulittle32_t exception_code; - llvm::support::ulittle32_t exception_flags; - llvm::support::ulittle64_t exception_record; - llvm::support::ulittle64_t exception_address; - llvm::support::ulittle32_t number_parameters; - llvm::support::ulittle32_t unused_alignment; - llvm::support::ulittle64_t exception_information[ExceptonInfoMaxParams]; -}; -static_assert(sizeof(MinidumpException) == 152, - "sizeof MinidumpException is not correct!"); - -struct MinidumpExceptionStream { - llvm::support::ulittle32_t thread_id; - llvm::support::ulittle32_t alignment; - MinidumpException exception_record; - LocationDescriptor thread_context; - - static const MinidumpExceptionStream *Parse(llvm::ArrayRef<uint8_t> &data); -}; -static_assert(sizeof(MinidumpExceptionStream) == 168, - "sizeof MinidumpExceptionStream is not correct!"); - } // namespace minidump } // namespace lldb_private #endif // liblldb_MinidumpTypes_h_ diff --git a/source/Plugins/Process/minidump/ProcessMinidump.cpp b/source/Plugins/Process/minidump/ProcessMinidump.cpp index a7fc42cad16c..e30a3c82a887 100644 --- a/source/Plugins/Process/minidump/ProcessMinidump.cpp +++ b/source/Plugins/Process/minidump/ProcessMinidump.cpp @@ -49,16 +49,19 @@ namespace { class PlaceholderObjectFile : public ObjectFile { public: PlaceholderObjectFile(const lldb::ModuleSP &module_sp, - const ModuleSpec &module_spec, lldb::offset_t base, - lldb::offset_t size) + const ModuleSpec &module_spec, lldb::addr_t base, + lldb::addr_t size) : ObjectFile(module_sp, &module_spec.GetFileSpec(), /*file_offset*/ 0, /*length*/ 0, /*data_sp*/ nullptr, /*data_offset*/ 0), m_arch(module_spec.GetArchitecture()), m_uuid(module_spec.GetUUID()), m_base(base), m_size(size) { - m_symtab_up = llvm::make_unique<Symtab>(this); + m_symtab_up = std::make_unique<Symtab>(this); } - ConstString GetPluginName() override { return ConstString("placeholder"); } + static ConstString GetStaticPluginName() { + return ConstString("placeholder"); + } + ConstString GetPluginName() override { return GetStaticPluginName(); } uint32_t GetPluginVersion() override { return 1; } bool ParseHeader() override { return true; } Type CalculateType() override { return eTypeUnknown; } @@ -80,7 +83,7 @@ public: } void CreateSections(SectionList &unified_section_list) override { - m_sections_up = llvm::make_unique<SectionList>(); + m_sections_up = std::make_unique<SectionList>(); auto section_sp = std::make_shared<Section>( GetModule(), this, /*sect_id*/ 0, ConstString(".module_image"), eSectionTypeOther, m_base, m_size, /*file_offset*/ 0, /*file_size*/ 0, @@ -109,11 +112,12 @@ public: GetFileSpec(), m_base, m_base + m_size); } + lldb::addr_t GetBaseImageAddress() const { return m_base; } private: ArchSpec m_arch; UUID m_uuid; - lldb::offset_t m_base; - lldb::offset_t m_size; + lldb::addr_t m_base; + lldb::addr_t m_size; }; } // namespace @@ -215,6 +219,9 @@ Status ProcessMinidump::DoLoadCore() { m_thread_list = m_minidump_parser->GetThreads(); m_active_exception = m_minidump_parser->GetExceptionStream(); + + SetUnixSignals(UnixSignals::Create(GetArchitecture())); + ReadModuleList(); llvm::Optional<lldb::pid_t> pid = m_minidump_parser->GetPid(); @@ -234,39 +241,56 @@ uint32_t ProcessMinidump::GetPluginVersion() { return 1; } Status ProcessMinidump::DoDestroy() { return Status(); } void ProcessMinidump::RefreshStateAfterStop() { + if (!m_active_exception) return; - if (m_active_exception->exception_record.exception_code == - MinidumpException::DumpRequested) { + constexpr uint32_t BreakpadDumpRequested = 0xFFFFFFFF; + if (m_active_exception->ExceptionRecord.ExceptionCode == + BreakpadDumpRequested) { + // This "ExceptionCode" value is a sentinel that is sometimes used + // when generating a dump for a process that hasn't crashed. + + // TODO: The definition and use of this "dump requested" constant + // in Breakpad are actually Linux-specific, and for similar use + // cases on Mac/Windows it defines differnt constants, referring + // to them as "simulated" exceptions; consider moving this check + // down to the OS-specific paths and checking each OS for its own + // constant. return; } lldb::StopInfoSP stop_info; lldb::ThreadSP stop_thread; - Process::m_thread_list.SetSelectedThreadByID(m_active_exception->thread_id); + Process::m_thread_list.SetSelectedThreadByID(m_active_exception->ThreadId); stop_thread = Process::m_thread_list.GetSelectedThread(); ArchSpec arch = GetArchitecture(); if (arch.GetTriple().getOS() == llvm::Triple::Linux) { + uint32_t signo = m_active_exception->ExceptionRecord.ExceptionCode; + + if (signo == 0) { + // No stop. + return; + } + stop_info = StopInfo::CreateStopReasonWithSignal( - *stop_thread, m_active_exception->exception_record.exception_code); + *stop_thread, signo); } else if (arch.GetTriple().getVendor() == llvm::Triple::Apple) { stop_info = StopInfoMachException::CreateStopReasonWithMachException( - *stop_thread, m_active_exception->exception_record.exception_code, 2, - m_active_exception->exception_record.exception_flags, - m_active_exception->exception_record.exception_address, 0); + *stop_thread, m_active_exception->ExceptionRecord.ExceptionCode, 2, + m_active_exception->ExceptionRecord.ExceptionFlags, + m_active_exception->ExceptionRecord.ExceptionAddress, 0); } else { std::string desc; llvm::raw_string_ostream desc_stream(desc); desc_stream << "Exception " << llvm::format_hex( - m_active_exception->exception_record.exception_code, 8) + m_active_exception->ExceptionRecord.ExceptionCode, 8) << " encountered at address " << llvm::format_hex( - m_active_exception->exception_record.exception_address, - 8); + m_active_exception->ExceptionRecord.ExceptionAddress, 8); stop_info = StopInfo::CreateStopReasonWithException( *stop_thread, desc_stream.str().c_str()); } @@ -331,8 +355,8 @@ bool ProcessMinidump::UpdateThreadList(ThreadList &old_thread_list, // If the minidump contains an exception context, use it if (m_active_exception != nullptr && - m_active_exception->thread_id == thread.ThreadId) { - context_location = m_active_exception->thread_context; + m_active_exception->ThreadId == thread.ThreadId) { + context_location = m_active_exception->ThreadContext; } llvm::ArrayRef<uint8_t> context; @@ -351,14 +375,15 @@ void ProcessMinidump::ReadModuleList() { std::vector<const minidump::Module *> filtered_modules = m_minidump_parser->GetFilteredModuleList(); - Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_MODULES)); + Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_DYNAMIC_LOADER)); for (auto module : filtered_modules) { std::string name = cantFail(m_minidump_parser->GetMinidumpFile().getString( module->ModuleNameRVA)); + const uint64_t load_addr = module->BaseOfImage; + const uint64_t load_size = module->SizeOfImage; LLDB_LOG(log, "found module: name: {0} {1:x10}-{2:x10} size: {3}", name, - module->BaseOfImage, module->BaseOfImage + module->SizeOfImage, - module->SizeOfImage); + load_addr, load_addr + load_size, load_size); // check if the process is wow64 - a 32 bit windows process running on a // 64 bit windows @@ -373,7 +398,7 @@ void ProcessMinidump::ReadModuleList() { Status error; // Try and find a module with a full UUID that matches. This function will // add the module to the target if it finds one. - lldb::ModuleSP module_sp = GetTarget().GetOrCreateModule(module_spec, + lldb::ModuleSP module_sp = GetTarget().GetOrCreateModule(module_spec, true /* notify */, &error); if (!module_sp) { // Try and find a module without specifying the UUID and only looking for @@ -386,8 +411,8 @@ void ProcessMinidump::ReadModuleList() { ModuleSpec basename_module_spec(module_spec); basename_module_spec.GetUUID().Clear(); basename_module_spec.GetFileSpec().GetDirectory().Clear(); - module_sp = GetTarget().GetOrCreateModule(basename_module_spec, - true /* notify */, &error); + module_sp = GetTarget().GetOrCreateModule(basename_module_spec, + true /* notify */, &error); if (module_sp) { // We consider the module to be a match if the minidump UUID is a // prefix of the actual UUID, or if either of the UUIDs are empty. @@ -401,6 +426,19 @@ void ProcessMinidump::ReadModuleList() { } } } + if (module_sp) { + // Watch out for place holder modules that have different paths, but the + // same UUID. If the base address is different, create a new module. If + // we don't then we will end up setting the load address of a different + // PlaceholderObjectFile and an assertion will fire. + auto *objfile = module_sp->GetObjectFile(); + if (objfile && objfile->GetPluginName() == + PlaceholderObjectFile::GetStaticPluginName()) { + if (((PlaceholderObjectFile *)objfile)->GetBaseImageAddress() != + load_addr) + module_sp.reset(); + } + } if (!module_sp) { // We failed to locate a matching local object file. Fortunately, the // minidump format encodes enough information about each module's memory @@ -415,12 +453,12 @@ void ProcessMinidump::ReadModuleList() { name); module_sp = Module::CreateModuleFromObjectFile<PlaceholderObjectFile>( - module_spec, module->BaseOfImage, module->SizeOfImage); + module_spec, load_addr, load_size); GetTarget().GetImages().Append(module_sp, true /* notify */); } bool load_addr_changed = false; - module_sp->SetLoadAddress(GetTarget(), module->BaseOfImage, false, + module_sp->SetLoadAddress(GetTarget(), load_addr, false, load_addr_changed); } } @@ -444,7 +482,7 @@ bool ProcessMinidump::GetProcessInfo(ProcessInstanceInfo &info) { // debug information than needed. JITLoaderList &ProcessMinidump::GetJITLoaders() { if (!m_jit_loaders_up) { - m_jit_loaders_up = llvm::make_unique<JITLoaderList>(); + m_jit_loaders_up = std::make_unique<JITLoaderList>(); } return *m_jit_loaders_up; } diff --git a/source/Plugins/Process/minidump/ProcessMinidump.h b/source/Plugins/Process/minidump/ProcessMinidump.h index c39040f61dc5..22dc24af7c0e 100644 --- a/source/Plugins/Process/minidump/ProcessMinidump.h +++ b/source/Plugins/Process/minidump/ProcessMinidump.h @@ -108,7 +108,7 @@ private: FileSpec m_core_file; lldb::DataBufferSP m_core_data; llvm::ArrayRef<minidump::Thread> m_thread_list; - const MinidumpExceptionStream *m_active_exception; + const minidump::ExceptionStream *m_active_exception; lldb::CommandObjectSP m_command_sp; bool m_is_wow64; }; diff --git a/source/Plugins/Process/minidump/RegisterContextMinidump_ARM.cpp b/source/Plugins/Process/minidump/RegisterContextMinidump_ARM.cpp index f2e456097dfc..72dead07dcb4 100644 --- a/source/Plugins/Process/minidump/RegisterContextMinidump_ARM.cpp +++ b/source/Plugins/Process/minidump/RegisterContextMinidump_ARM.cpp @@ -9,6 +9,7 @@ #include "RegisterContextMinidump_ARM.h" #include "Utility/ARM_DWARF_Registers.h" +#include "Utility/ARM_ehframe_Registers.h" #include "lldb/Utility/RegisterValue.h" #include "lldb/Utility/DataExtractor.h" #include "lldb/Utility/LLDBAssert.h" @@ -29,14 +30,14 @@ using namespace minidump; #define DEF_R(i) \ { \ "r" #i, nullptr, 4, OFFSET(r) + i * 4, eEncodingUint, eFormatHex, \ - {dwarf_r##i, dwarf_r##i, INV, INV, reg_r##i}, \ + {ehframe_r##i, dwarf_r##i, INV, INV, reg_r##i}, \ nullptr, nullptr, nullptr, 0 \ } #define DEF_R_ARG(i, n) \ { \ "r" #i, "arg" #n, 4, OFFSET(r) + i * 4, eEncodingUint, eFormatHex, \ - {dwarf_r##i, dwarf_r##i, LLDB_REGNUM_GENERIC_ARG1 + i, INV, reg_r##i}, \ + {ehframe_r##i, dwarf_r##i, LLDB_REGNUM_GENERIC_ARG1 + i, INV, reg_r##i}, \ nullptr, nullptr, nullptr, 0 \ } @@ -173,7 +174,7 @@ static RegisterInfo g_reg_info_apple_fp = { OFFSET(r) + 7 * 4, eEncodingUint, eFormatHex, - {INV, dwarf_r7, LLDB_REGNUM_GENERIC_FP, INV, reg_r7}, + {ehframe_r7, dwarf_r7, LLDB_REGNUM_GENERIC_FP, INV, reg_r7}, nullptr, nullptr, nullptr, @@ -186,7 +187,7 @@ static RegisterInfo g_reg_info_fp = { OFFSET(r) + 11 * 4, eEncodingUint, eFormatHex, - {INV, dwarf_r11, LLDB_REGNUM_GENERIC_FP, INV, reg_r11}, + {ehframe_r11, dwarf_r11, LLDB_REGNUM_GENERIC_FP, INV, reg_r11}, nullptr, nullptr, nullptr, @@ -213,7 +214,7 @@ static RegisterInfo g_reg_infos[] = { OFFSET(r) + 13 * 4, eEncodingUint, eFormatHex, - {INV, dwarf_sp, LLDB_REGNUM_GENERIC_SP, INV, reg_sp}, + {ehframe_sp, dwarf_sp, LLDB_REGNUM_GENERIC_SP, INV, reg_sp}, nullptr, nullptr, nullptr, @@ -224,7 +225,7 @@ static RegisterInfo g_reg_infos[] = { OFFSET(r) + 14 * 4, eEncodingUint, eFormatHex, - {INV, dwarf_lr, LLDB_REGNUM_GENERIC_RA, INV, reg_lr}, + {ehframe_lr, dwarf_lr, LLDB_REGNUM_GENERIC_RA, INV, reg_lr}, nullptr, nullptr, nullptr, @@ -235,7 +236,7 @@ static RegisterInfo g_reg_infos[] = { OFFSET(r) + 15 * 4, eEncodingUint, eFormatHex, - {INV, dwarf_pc, LLDB_REGNUM_GENERIC_PC, INV, reg_pc}, + {ehframe_pc, dwarf_pc, LLDB_REGNUM_GENERIC_PC, INV, reg_pc}, nullptr, nullptr, nullptr, @@ -246,7 +247,7 @@ static RegisterInfo g_reg_infos[] = { OFFSET(cpsr), eEncodingUint, eFormatHex, - {INV, dwarf_cpsr, LLDB_REGNUM_GENERIC_FLAGS, INV, reg_cpsr}, + {ehframe_cpsr, dwarf_cpsr, LLDB_REGNUM_GENERIC_FLAGS, INV, reg_cpsr}, nullptr, nullptr, nullptr, @@ -476,12 +477,22 @@ RegisterContextMinidump_ARM::RegisterContextMinidump_ARM( lldbassert(k_num_regs == k_num_reg_infos); } -size_t RegisterContextMinidump_ARM::GetRegisterCount() { return k_num_regs; } +size_t RegisterContextMinidump_ARM::GetRegisterCountStatic() { + return k_num_regs; +} + +// Used for unit testing so we can verify register info is filled in for +// all register flavors (DWARF, EH Frame, generic, etc). +size_t RegisterContextMinidump_ARM::GetRegisterCount() { + return GetRegisterCountStatic(); +} +// Used for unit testing so we can verify register info is filled in. const RegisterInfo * -RegisterContextMinidump_ARM::GetRegisterInfoAtIndex(size_t reg) { +RegisterContextMinidump_ARM::GetRegisterInfoAtIndexStatic(size_t reg, + bool apple) { if (reg < k_num_reg_infos) { - if (m_apple) { + if (apple) { if (reg == reg_r7) return &g_reg_info_apple_fp; } else { @@ -493,6 +504,11 @@ RegisterContextMinidump_ARM::GetRegisterInfoAtIndex(size_t reg) { return nullptr; } +const RegisterInfo * +RegisterContextMinidump_ARM::GetRegisterInfoAtIndex(size_t reg) { + return GetRegisterInfoAtIndexStatic(reg, m_apple); +} + size_t RegisterContextMinidump_ARM::GetRegisterSetCount() { return k_num_reg_sets; } diff --git a/source/Plugins/Process/minidump/RegisterContextMinidump_ARM.h b/source/Plugins/Process/minidump/RegisterContextMinidump_ARM.h index eff8cdfef00a..7af3b98a6fe7 100644 --- a/source/Plugins/Process/minidump/RegisterContextMinidump_ARM.h +++ b/source/Plugins/Process/minidump/RegisterContextMinidump_ARM.h @@ -38,6 +38,12 @@ public: // Do nothing... registers are always valid... } + // Used for unit testing. + static size_t GetRegisterCountStatic(); + // Used for unit testing. + static const lldb_private::RegisterInfo * + GetRegisterInfoAtIndexStatic(size_t reg, bool apple); + size_t GetRegisterCount() override; const lldb_private::RegisterInfo *GetRegisterInfoAtIndex(size_t reg) override; diff --git a/source/Plugins/ScriptInterpreter/None/ScriptInterpreterNone.cpp b/source/Plugins/ScriptInterpreter/None/ScriptInterpreterNone.cpp index 7b9598379553..3517f831970d 100644 --- a/source/Plugins/ScriptInterpreter/None/ScriptInterpreterNone.cpp +++ b/source/Plugins/ScriptInterpreter/None/ScriptInterpreterNone.cpp @@ -28,13 +28,13 @@ ScriptInterpreterNone::~ScriptInterpreterNone() {} bool ScriptInterpreterNone::ExecuteOneLine(llvm::StringRef command, CommandReturnObject *, const ExecuteScriptOptions &) { - m_debugger.GetErrorFile()->PutCString( + m_debugger.GetErrorStream().PutCString( "error: there is no embedded script interpreter in this mode.\n"); return false; } void ScriptInterpreterNone::ExecuteInterpreterLoop() { - m_debugger.GetErrorFile()->PutCString( + m_debugger.GetErrorStream().PutCString( "error: there is no embedded script interpreter in this mode.\n"); } diff --git a/source/Plugins/ScriptInterpreter/Python/PythonDataObjects.cpp b/source/Plugins/ScriptInterpreter/Python/PythonDataObjects.cpp index 29dd037efd86..70d93424fdec 100644 --- a/source/Plugins/ScriptInterpreter/Python/PythonDataObjects.cpp +++ b/source/Plugins/ScriptInterpreter/Python/PythonDataObjects.cpp @@ -18,9 +18,11 @@ #include "lldb/Host/File.h" #include "lldb/Host/FileSystem.h" #include "lldb/Interpreter/ScriptInterpreter.h" +#include "lldb/Utility/Log.h" #include "lldb/Utility/Stream.h" #include "llvm/ADT/StringSwitch.h" +#include "llvm/Support/Casting.h" #include "llvm/Support/ConvertUTF.h" #include "llvm/Support/Errno.h" @@ -28,9 +30,41 @@ using namespace lldb_private; using namespace lldb; +using namespace lldb_private::python; +using llvm::cantFail; +using llvm::Error; +using llvm::Expected; +using llvm::Twine; -void StructuredPythonObject::Dump(Stream &s, bool pretty_print) const { - s << "Python Obj: 0x" << GetValue(); +template <> Expected<bool> python::As<bool>(Expected<PythonObject> &&obj) { + if (!obj) + return obj.takeError(); + return obj.get().IsTrue(); +} + +template <> +Expected<long long> python::As<long long>(Expected<PythonObject> &&obj) { + if (!obj) + return obj.takeError(); + return obj.get().AsLongLong(); +} + +template <> +Expected<std::string> python::As<std::string>(Expected<PythonObject> &&obj) { + if (!obj) + return obj.takeError(); + PyObject *str_obj = PyObject_Str(obj.get().get()); + if (!obj) + return llvm::make_error<PythonException>(); + auto str = Take<PythonString>(str_obj); + auto utf8 = str.AsUTF8(); + if (!utf8) + return utf8.takeError(); + return utf8.get(); +} + +void StructuredPythonObject::Serialize(llvm::json::OStream &s) const { + s.value(llvm::formatv("Python Obj: {0:X}", GetValue()).str()); } // PythonObject @@ -167,12 +201,6 @@ PythonObject PythonObject::GetAttributeValue(llvm::StringRef attr) const { PyObject_GetAttr(m_py_obj, py_attr.get())); } -bool PythonObject::IsNone() const { return m_py_obj == Py_None; } - -bool PythonObject::IsValid() const { return m_py_obj != nullptr; } - -bool PythonObject::IsAllocated() const { return IsValid() && !IsNone(); } - StructuredData::ObjectSP PythonObject::CreateStructuredObject() const { switch (GetObjectType()) { case PyObjectType::Dictionary: @@ -201,43 +229,19 @@ StructuredData::ObjectSP PythonObject::CreateStructuredObject() const { } // PythonString -PythonBytes::PythonBytes() : PythonObject() {} -PythonBytes::PythonBytes(llvm::ArrayRef<uint8_t> bytes) : PythonObject() { - SetBytes(bytes); -} +PythonBytes::PythonBytes(llvm::ArrayRef<uint8_t> bytes) { SetBytes(bytes); } -PythonBytes::PythonBytes(const uint8_t *bytes, size_t length) : PythonObject() { +PythonBytes::PythonBytes(const uint8_t *bytes, size_t length) { SetBytes(llvm::ArrayRef<uint8_t>(bytes, length)); } -PythonBytes::PythonBytes(PyRefType type, PyObject *py_obj) : PythonObject() { - Reset(type, py_obj); // Use "Reset()" to ensure that py_obj is a string -} - -PythonBytes::~PythonBytes() {} - bool PythonBytes::Check(PyObject *py_obj) { if (!py_obj) return false; return PyBytes_Check(py_obj); } -void PythonBytes::Reset(PyRefType type, PyObject *py_obj) { - // Grab the desired reference type so that if we end up rejecting `py_obj` it - // still gets decremented if necessary. - PythonObject result(type, py_obj); - - if (!PythonBytes::Check(py_obj)) { - PythonObject::Reset(); - return; - } - - // Calling PythonObject::Reset(const PythonObject&) will lead to stack - // overflow since it calls back into the virtual implementation. - PythonObject::Reset(PyRefType::Borrowed, result.get()); -} - llvm::ArrayRef<uint8_t> PythonBytes::GetBytes() const { if (!IsValid()) return llvm::ArrayRef<uint8_t>(); @@ -257,8 +261,7 @@ size_t PythonBytes::GetSize() const { void PythonBytes::SetBytes(llvm::ArrayRef<uint8_t> bytes) { const char *data = reinterpret_cast<const char *>(bytes.data()); - PyObject *py_bytes = PyBytes_FromStringAndSize(data, bytes.size()); - PythonObject::Reset(PyRefType::Owned, py_bytes); + *this = Take<PythonBytes>(PyBytes_FromStringAndSize(data, bytes.size())); } StructuredData::StringSP PythonBytes::CreateStructuredString() const { @@ -275,39 +278,15 @@ PythonByteArray::PythonByteArray(llvm::ArrayRef<uint8_t> bytes) PythonByteArray::PythonByteArray(const uint8_t *bytes, size_t length) { const char *str = reinterpret_cast<const char *>(bytes); - Reset(PyRefType::Owned, PyByteArray_FromStringAndSize(str, length)); -} - -PythonByteArray::PythonByteArray(PyRefType type, PyObject *o) { - Reset(type, o); + *this = Take<PythonByteArray>(PyByteArray_FromStringAndSize(str, length)); } -PythonByteArray::PythonByteArray(const PythonBytes &object) - : PythonObject(object) {} - -PythonByteArray::~PythonByteArray() {} - bool PythonByteArray::Check(PyObject *py_obj) { if (!py_obj) return false; return PyByteArray_Check(py_obj); } -void PythonByteArray::Reset(PyRefType type, PyObject *py_obj) { - // Grab the desired reference type so that if we end up rejecting `py_obj` it - // still gets decremented if necessary. - PythonObject result(type, py_obj); - - if (!PythonByteArray::Check(py_obj)) { - PythonObject::Reset(); - return; - } - - // Calling PythonObject::Reset(const PythonObject&) will lead to stack - // overflow since it calls back into the virtual implementation. - PythonObject::Reset(PyRefType::Borrowed, result.get()); -} - llvm::ArrayRef<uint8_t> PythonByteArray::GetBytes() const { if (!IsValid()) return llvm::ArrayRef<uint8_t>(); @@ -334,21 +313,18 @@ StructuredData::StringSP PythonByteArray::CreateStructuredString() const { // PythonString -PythonString::PythonString(PyRefType type, PyObject *py_obj) : PythonObject() { - Reset(type, py_obj); // Use "Reset()" to ensure that py_obj is a string -} - -PythonString::PythonString(llvm::StringRef string) : PythonObject() { - SetString(string); -} - -PythonString::PythonString(const char *string) : PythonObject() { - SetString(llvm::StringRef(string)); +Expected<PythonString> PythonString::FromUTF8(llvm::StringRef string) { +#if PY_MAJOR_VERSION >= 3 + PyObject *str = PyUnicode_FromStringAndSize(string.data(), string.size()); +#else + PyObject *str = PyString_FromStringAndSize(string.data(), string.size()); +#endif + if (!str) + return llvm::make_error<PythonException>(); + return Take<PythonString>(str); } -PythonString::PythonString() : PythonObject() {} - -PythonString::~PythonString() {} +PythonString::PythonString(llvm::StringRef string) { SetString(string); } bool PythonString::Check(PyObject *py_obj) { if (!py_obj) @@ -363,30 +339,40 @@ bool PythonString::Check(PyObject *py_obj) { return false; } -void PythonString::Reset(PyRefType type, PyObject *py_obj) { - // Grab the desired reference type so that if we end up rejecting `py_obj` it - // still gets decremented if necessary. - PythonObject result(type, py_obj); - - if (!PythonString::Check(py_obj)) { - PythonObject::Reset(); - return; - } +void PythonString::Convert(PyRefType &type, PyObject *&py_obj) { #if PY_MAJOR_VERSION < 3 // In Python 2, Don't store PyUnicode objects directly, because we need // access to their underlying character buffers which Python 2 doesn't // provide. - if (PyUnicode_Check(py_obj)) - result.Reset(PyRefType::Owned, PyUnicode_AsUTF8String(result.get())); + if (PyUnicode_Check(py_obj)) { + PyObject *s = PyUnicode_AsUTF8String(py_obj); + if (s == nullptr) { + PyErr_Clear(); + if (type == PyRefType::Owned) + Py_DECREF(py_obj); + return; + } + if (type == PyRefType::Owned) + Py_DECREF(py_obj); + else + type = PyRefType::Owned; + py_obj = s; + } #endif - // Calling PythonObject::Reset(const PythonObject&) will lead to stack - // overflow since it calls back into the virtual implementation. - PythonObject::Reset(PyRefType::Borrowed, result.get()); } llvm::StringRef PythonString::GetString() const { + auto s = AsUTF8(); + if (!s) { + llvm::consumeError(s.takeError()); + return llvm::StringRef(""); + } + return s.get(); +} + +Expected<llvm::StringRef> PythonString::AsUTF8() const { if (!IsValid()) - return llvm::StringRef(); + return nullDeref(); Py_ssize_t size; const char *data; @@ -394,10 +380,16 @@ llvm::StringRef PythonString::GetString() const { #if PY_MAJOR_VERSION >= 3 data = PyUnicode_AsUTF8AndSize(m_py_obj, &size); #else - char *c; - PyString_AsStringAndSize(m_py_obj, &c, &size); + char *c = NULL; + int r = PyString_AsStringAndSize(m_py_obj, &c, &size); + if (r < 0) + c = NULL; data = c; #endif + + if (!data) + return exception(); + return llvm::StringRef(data, size); } @@ -413,13 +405,13 @@ size_t PythonString::GetSize() const { } void PythonString::SetString(llvm::StringRef string) { -#if PY_MAJOR_VERSION >= 3 - PyObject *unicode = PyUnicode_FromStringAndSize(string.data(), string.size()); - PythonObject::Reset(PyRefType::Owned, unicode); -#else - PyObject *str = PyString_FromStringAndSize(string.data(), string.size()); - PythonObject::Reset(PyRefType::Owned, str); -#endif + auto s = FromUTF8(string); + if (!s) { + llvm::consumeError(s.takeError()); + Reset(); + } else { + *this = std::move(s.get()); + } } StructuredData::StringSP PythonString::CreateStructuredString() const { @@ -430,18 +422,7 @@ StructuredData::StringSP PythonString::CreateStructuredString() const { // PythonInteger -PythonInteger::PythonInteger() : PythonObject() {} - -PythonInteger::PythonInteger(PyRefType type, PyObject *py_obj) - : PythonObject() { - Reset(type, py_obj); // Use "Reset()" to ensure that py_obj is a integer type -} - -PythonInteger::PythonInteger(int64_t value) : PythonObject() { - SetInteger(value); -} - -PythonInteger::~PythonInteger() {} +PythonInteger::PythonInteger(int64_t value) { SetInteger(value); } bool PythonInteger::Check(PyObject *py_obj) { if (!py_obj) @@ -456,16 +437,7 @@ bool PythonInteger::Check(PyObject *py_obj) { #endif } -void PythonInteger::Reset(PyRefType type, PyObject *py_obj) { - // Grab the desired reference type so that if we end up rejecting `py_obj` it - // still gets decremented if necessary. - PythonObject result(type, py_obj); - - if (!PythonInteger::Check(py_obj)) { - PythonObject::Reset(); - return; - } - +void PythonInteger::Convert(PyRefType &type, PyObject *&py_obj) { #if PY_MAJOR_VERSION < 3 // Always store this as a PyLong, which makes interoperability between Python // 2.x and Python 3.x easier. This is only necessary in 2.x, since 3.x @@ -474,16 +446,23 @@ void PythonInteger::Reset(PyRefType type, PyObject *py_obj) { // Since we converted the original object to a different type, the new // object is an owned object regardless of the ownership semantics // requested by the user. - result.Reset(PyRefType::Owned, PyLong_FromLongLong(PyInt_AsLong(py_obj))); + long long value = PyInt_AsLong(py_obj); + PyObject *l = nullptr; + if (!PyErr_Occurred()) + l = PyLong_FromLongLong(value); + if (l == nullptr) { + PyErr_Clear(); + if (type == PyRefType::Owned) + Py_DECREF(py_obj); + return; + } + if (type == PyRefType::Owned) + Py_DECREF(py_obj); + else + type = PyRefType::Owned; + py_obj = l; } #endif - - assert(PyLong_Check(result.get()) && - "Couldn't get a PyLong from this PyObject"); - - // Calling PythonObject::Reset(const PythonObject&) will lead to stack - // overflow since it calls back into the virtual implementation. - PythonObject::Reset(PyRefType::Borrowed, result.get()); } int64_t PythonInteger::GetInteger() const { @@ -506,7 +485,7 @@ int64_t PythonInteger::GetInteger() const { } void PythonInteger::SetInteger(int64_t value) { - PythonObject::Reset(PyRefType::Owned, PyLong_FromLongLong(value)); + *this = Take<PythonInteger>(PyLong_FromLongLong(value)); } StructuredData::IntegerSP PythonInteger::CreateStructuredInteger() const { @@ -517,11 +496,6 @@ StructuredData::IntegerSP PythonInteger::CreateStructuredInteger() const { // PythonBoolean -PythonBoolean::PythonBoolean(PyRefType type, PyObject *py_obj) - : PythonObject() { - Reset(type, py_obj); // Use "Reset()" to ensure that py_obj is a boolean type -} - PythonBoolean::PythonBoolean(bool value) { SetValue(value); } @@ -530,27 +504,12 @@ bool PythonBoolean::Check(PyObject *py_obj) { return py_obj ? PyBool_Check(py_obj) : false; } -void PythonBoolean::Reset(PyRefType type, PyObject *py_obj) { - // Grab the desired reference type so that if we end up rejecting `py_obj` it - // still gets decremented if necessary. - PythonObject result(type, py_obj); - - if (!PythonBoolean::Check(py_obj)) { - PythonObject::Reset(); - return; - } - - // Calling PythonObject::Reset(const PythonObject&) will lead to stack - // overflow since it calls back into the virtual implementation. - PythonObject::Reset(PyRefType::Borrowed, result.get()); -} - bool PythonBoolean::GetValue() const { return m_py_obj ? PyObject_IsTrue(m_py_obj) : false; } void PythonBoolean::SetValue(bool value) { - PythonObject::Reset(PyRefType::Owned, PyBool_FromLong(value)); + *this = Take<PythonBoolean>(PyBool_FromLong(value)); } StructuredData::BooleanSP PythonBoolean::CreateStructuredBoolean() const { @@ -561,42 +520,21 @@ StructuredData::BooleanSP PythonBoolean::CreateStructuredBoolean() const { // PythonList -PythonList::PythonList(PyInitialValue value) : PythonObject() { +PythonList::PythonList(PyInitialValue value) { if (value == PyInitialValue::Empty) - Reset(PyRefType::Owned, PyList_New(0)); -} - -PythonList::PythonList(int list_size) : PythonObject() { - Reset(PyRefType::Owned, PyList_New(list_size)); + *this = Take<PythonList>(PyList_New(0)); } -PythonList::PythonList(PyRefType type, PyObject *py_obj) : PythonObject() { - Reset(type, py_obj); // Use "Reset()" to ensure that py_obj is a list +PythonList::PythonList(int list_size) { + *this = Take<PythonList>(PyList_New(list_size)); } -PythonList::~PythonList() {} - bool PythonList::Check(PyObject *py_obj) { if (!py_obj) return false; return PyList_Check(py_obj); } -void PythonList::Reset(PyRefType type, PyObject *py_obj) { - // Grab the desired reference type so that if we end up rejecting `py_obj` it - // still gets decremented if necessary. - PythonObject result(type, py_obj); - - if (!PythonList::Check(py_obj)) { - PythonObject::Reset(); - return; - } - - // Calling PythonObject::Reset(const PythonObject&) will lead to stack - // overflow since it calls back into the virtual implementation. - PythonObject::Reset(PyRefType::Borrowed, result.get()); -} - uint32_t PythonList::GetSize() const { if (IsValid()) return PyList_GET_SIZE(m_py_obj); @@ -638,17 +576,13 @@ StructuredData::ArraySP PythonList::CreateStructuredArray() const { // PythonTuple -PythonTuple::PythonTuple(PyInitialValue value) : PythonObject() { +PythonTuple::PythonTuple(PyInitialValue value) { if (value == PyInitialValue::Empty) - Reset(PyRefType::Owned, PyTuple_New(0)); -} - -PythonTuple::PythonTuple(int tuple_size) : PythonObject() { - Reset(PyRefType::Owned, PyTuple_New(tuple_size)); + *this = Take<PythonTuple>(PyTuple_New(0)); } -PythonTuple::PythonTuple(PyRefType type, PyObject *py_obj) : PythonObject() { - Reset(type, py_obj); // Use "Reset()" to ensure that py_obj is a tuple +PythonTuple::PythonTuple(int tuple_size) { + *this = Take<PythonTuple>(PyTuple_New(tuple_size)); } PythonTuple::PythonTuple(std::initializer_list<PythonObject> objects) { @@ -674,29 +608,12 @@ PythonTuple::PythonTuple(std::initializer_list<PyObject *> objects) { } } -PythonTuple::~PythonTuple() {} - bool PythonTuple::Check(PyObject *py_obj) { if (!py_obj) return false; return PyTuple_Check(py_obj); } -void PythonTuple::Reset(PyRefType type, PyObject *py_obj) { - // Grab the desired reference type so that if we end up rejecting `py_obj` it - // still gets decremented if necessary. - PythonObject result(type, py_obj); - - if (!PythonTuple::Check(py_obj)) { - PythonObject::Reset(); - return; - } - - // Calling PythonObject::Reset(const PythonObject&) will lead to stack - // overflow since it calls back into the virtual implementation. - PythonObject::Reset(PyRefType::Borrowed, result.get()); -} - uint32_t PythonTuple::GetSize() const { if (IsValid()) return PyTuple_GET_SIZE(m_py_obj); @@ -730,18 +647,11 @@ StructuredData::ArraySP PythonTuple::CreateStructuredArray() const { // PythonDictionary -PythonDictionary::PythonDictionary(PyInitialValue value) : PythonObject() { +PythonDictionary::PythonDictionary(PyInitialValue value) { if (value == PyInitialValue::Empty) - Reset(PyRefType::Owned, PyDict_New()); + *this = Take<PythonDictionary>(PyDict_New()); } -PythonDictionary::PythonDictionary(PyRefType type, PyObject *py_obj) - : PythonObject() { - Reset(type, py_obj); // Use "Reset()" to ensure that py_obj is a dictionary -} - -PythonDictionary::~PythonDictionary() {} - bool PythonDictionary::Check(PyObject *py_obj) { if (!py_obj) return false; @@ -749,21 +659,6 @@ bool PythonDictionary::Check(PyObject *py_obj) { return PyDict_Check(py_obj); } -void PythonDictionary::Reset(PyRefType type, PyObject *py_obj) { - // Grab the desired reference type so that if we end up rejecting `py_obj` it - // still gets decremented if necessary. - PythonObject result(type, py_obj); - - if (!PythonDictionary::Check(py_obj)) { - PythonObject::Reset(); - return; - } - - // Calling PythonObject::Reset(const PythonObject&) will lead to stack - // overflow since it calls back into the virtual implementation. - PythonObject::Reset(PyRefType::Borrowed, result.get()); -} - uint32_t PythonDictionary::GetSize() const { if (IsValid()) return PyDict_Size(m_py_obj); @@ -777,16 +672,66 @@ PythonList PythonDictionary::GetKeys() const { } PythonObject PythonDictionary::GetItemForKey(const PythonObject &key) const { - if (IsAllocated() && key.IsValid()) - return PythonObject(PyRefType::Borrowed, - PyDict_GetItem(m_py_obj, key.get())); - return PythonObject(); + auto item = GetItem(key); + if (!item) { + llvm::consumeError(item.takeError()); + return PythonObject(); + } + return std::move(item.get()); +} + +Expected<PythonObject> +PythonDictionary::GetItem(const PythonObject &key) const { + if (!IsValid()) + return nullDeref(); +#if PY_MAJOR_VERSION >= 3 + PyObject *o = PyDict_GetItemWithError(m_py_obj, key.get()); + if (PyErr_Occurred()) + return exception(); +#else + PyObject *o = PyDict_GetItem(m_py_obj, key.get()); +#endif + if (!o) + return keyError(); + return Retain<PythonObject>(o); +} + +Expected<PythonObject> PythonDictionary::GetItem(const Twine &key) const { + if (!IsValid()) + return nullDeref(); + PyObject *o = PyDict_GetItemString(m_py_obj, NullTerminated(key)); + if (PyErr_Occurred()) + return exception(); + if (!o) + return keyError(); + return Retain<PythonObject>(o); +} + +Error PythonDictionary::SetItem(const PythonObject &key, + const PythonObject &value) const { + if (!IsValid() || !value.IsValid()) + return nullDeref(); + int r = PyDict_SetItem(m_py_obj, key.get(), value.get()); + if (r < 0) + return exception(); + return Error::success(); +} + +Error PythonDictionary::SetItem(const Twine &key, + const PythonObject &value) const { + if (!IsValid() || !value.IsValid()) + return nullDeref(); + int r = PyDict_SetItemString(m_py_obj, NullTerminated(key), value.get()); + if (r < 0) + return exception(); + return Error::success(); } void PythonDictionary::SetItemForKey(const PythonObject &key, const PythonObject &value) { - if (IsAllocated() && key.IsValid() && value.IsValid()) - PyDict_SetItem(m_py_obj, key.get(), value.get()); + Error error = SetItem(key, value); + if (error) + llvm::consumeError(std::move(error)); } StructuredData::DictionarySP @@ -803,14 +748,6 @@ PythonDictionary::CreateStructuredDictionary() const { return result; } -PythonModule::PythonModule() : PythonObject() {} - -PythonModule::PythonModule(PyRefType type, PyObject *py_obj) { - Reset(type, py_obj); // Use "Reset()" to ensure that py_obj is a module -} - -PythonModule::~PythonModule() {} - PythonModule PythonModule::BuiltinsModule() { #if PY_MAJOR_VERSION >= 3 return AddModule("builtins"); @@ -826,9 +763,23 @@ PythonModule PythonModule::AddModule(llvm::StringRef module) { return PythonModule(PyRefType::Borrowed, PyImport_AddModule(str.c_str())); } -PythonModule PythonModule::ImportModule(llvm::StringRef module) { - std::string str = module.str(); - return PythonModule(PyRefType::Owned, PyImport_ImportModule(str.c_str())); +Expected<PythonModule> PythonModule::Import(const Twine &name) { + PyObject *mod = PyImport_ImportModule(NullTerminated(name)); + if (!mod) + return exception(); + return Take<PythonModule>(mod); +} + +Expected<PythonObject> PythonModule::Get(const Twine &name) { + if (!IsValid()) + return nullDeref(); + PyObject *dict = PyModule_GetDict(m_py_obj); + if (!dict) + return exception(); + PyObject *item = PyDict_GetItemString(dict, NullTerminated(name)); + if (!item) + return exception(); + return Retain<PythonObject>(item); } bool PythonModule::Check(PyObject *py_obj) { @@ -838,33 +789,12 @@ bool PythonModule::Check(PyObject *py_obj) { return PyModule_Check(py_obj); } -void PythonModule::Reset(PyRefType type, PyObject *py_obj) { - // Grab the desired reference type so that if we end up rejecting `py_obj` it - // still gets decremented if necessary. - PythonObject result(type, py_obj); - - if (!PythonModule::Check(py_obj)) { - PythonObject::Reset(); - return; - } - - // Calling PythonObject::Reset(const PythonObject&) will lead to stack - // overflow since it calls back into the virtual implementation. - PythonObject::Reset(PyRefType::Borrowed, result.get()); -} - PythonDictionary PythonModule::GetDictionary() const { - return PythonDictionary(PyRefType::Borrowed, PyModule_GetDict(m_py_obj)); -} - -PythonCallable::PythonCallable() : PythonObject() {} - -PythonCallable::PythonCallable(PyRefType type, PyObject *py_obj) { - Reset(type, py_obj); // Use "Reset()" to ensure that py_obj is a callable + if (!IsValid()) + return PythonDictionary(); + return Retain<PythonDictionary>(PyModule_GetDict(m_py_obj)); } -PythonCallable::~PythonCallable() {} - bool PythonCallable::Check(PyObject *py_obj) { if (!py_obj) return false; @@ -872,32 +802,80 @@ bool PythonCallable::Check(PyObject *py_obj) { return PyCallable_Check(py_obj); } -void PythonCallable::Reset(PyRefType type, PyObject *py_obj) { - // Grab the desired reference type so that if we end up rejecting `py_obj` it - // still gets decremented if necessary. - PythonObject result(type, py_obj); - - if (!PythonCallable::Check(py_obj)) { - PythonObject::Reset(); - return; +PythonCallable::ArgInfo PythonCallable::GetNumInitArguments() const { + auto arginfo = GetInitArgInfo(); + if (!arginfo) { + llvm::consumeError(arginfo.takeError()); + return ArgInfo{}; } - - // Calling PythonObject::Reset(const PythonObject&) will lead to stack - // overflow since it calls back into the virtual implementation. - PythonObject::Reset(PyRefType::Borrowed, result.get()); + return arginfo.get(); } -PythonCallable::ArgInfo PythonCallable::GetNumArguments() const { - ArgInfo result = {0, false, false, false}; +Expected<PythonCallable::ArgInfo> PythonCallable::GetInitArgInfo() const { if (!IsValid()) - return result; + return nullDeref(); + auto init = As<PythonCallable>(GetAttribute("__init__")); + if (!init) + return init.takeError(); + return init.get().GetArgInfo(); +} + +#if PY_MAJOR_VERSION >= 3 && PY_MINOR_VERSION >= 3 +static const char get_arg_info_script[] = R"( +from inspect import signature, Parameter, ismethod +from collections import namedtuple +ArgInfo = namedtuple('ArgInfo', ['count', 'has_varargs', 'is_bound_method']) +def main(f): + count = 0 + varargs = False + for parameter in signature(f).parameters.values(): + kind = parameter.kind + if kind in (Parameter.POSITIONAL_ONLY, + Parameter.POSITIONAL_OR_KEYWORD): + count += 1 + elif kind == Parameter.VAR_POSITIONAL: + varargs = True + elif kind in (Parameter.KEYWORD_ONLY, + Parameter.VAR_KEYWORD): + pass + else: + raise Exception(f'unknown parameter kind: {kind}') + return ArgInfo(count, varargs, ismethod(f)) +)"; +#endif + +Expected<PythonCallable::ArgInfo> PythonCallable::GetArgInfo() const { + ArgInfo result = {}; + if (!IsValid()) + return nullDeref(); + +#if PY_MAJOR_VERSION >= 3 && PY_MINOR_VERSION >= 3 + + // no need to synchronize access to this global, we already have the GIL + static PythonScript get_arg_info(get_arg_info_script); + Expected<PythonObject> pyarginfo = get_arg_info(*this); + if (!pyarginfo) + return pyarginfo.takeError(); + result.count = cantFail(As<long long>(pyarginfo.get().GetAttribute("count"))); + result.has_varargs = + cantFail(As<bool>(pyarginfo.get().GetAttribute("has_varargs"))); + bool is_method = + cantFail(As<bool>(pyarginfo.get().GetAttribute("is_bound_method"))); + result.max_positional_args = + result.has_varargs ? ArgInfo::UNBOUNDED : result.count; + + // FIXME emulate old broken behavior + if (is_method) + result.count++; +#else + bool is_bound_method = false; PyObject *py_func_obj = m_py_obj; if (PyMethod_Check(py_func_obj)) { py_func_obj = PyMethod_GET_FUNCTION(py_func_obj); PythonObject im_self = GetAttributeValue("im_self"); if (im_self.IsValid() && !im_self.IsNone()) - result.is_bound_method = true; + is_bound_method = true; } else { // see if this is a callable object with an __call__ method if (!PyFunction_Check(py_func_obj)) { @@ -906,9 +884,9 @@ PythonCallable::ArgInfo PythonCallable::GetNumArguments() const { auto __callable__ = __call__.AsType<PythonCallable>(); if (__callable__.IsValid()) { py_func_obj = PyMethod_GET_FUNCTION(__callable__.get()); - PythonObject im_self = GetAttributeValue("im_self"); + PythonObject im_self = __callable__.GetAttributeValue("im_self"); if (im_self.IsValid() && !im_self.IsNone()) - result.is_bound_method = true; + is_bound_method = true; } } } @@ -923,10 +901,27 @@ PythonCallable::ArgInfo PythonCallable::GetNumArguments() const { result.count = code->co_argcount; result.has_varargs = !!(code->co_flags & CO_VARARGS); - result.has_kwargs = !!(code->co_flags & CO_VARKEYWORDS); + result.max_positional_args = result.has_varargs + ? ArgInfo::UNBOUNDED + : (result.count - (int)is_bound_method); + +#endif + return result; } +constexpr unsigned + PythonCallable::ArgInfo::UNBOUNDED; // FIXME delete after c++17 + +PythonCallable::ArgInfo PythonCallable::GetNumArguments() const { + auto arginfo = GetArgInfo(); + if (!arginfo) { + llvm::consumeError(arginfo.takeError()); + return ArgInfo{}; + } + return arginfo.get(); +} + PythonObject PythonCallable::operator()() { return PythonObject(PyRefType::Owned, PyObject_CallObject(m_py_obj, nullptr)); } @@ -945,21 +940,9 @@ operator()(std::initializer_list<PythonObject> args) { PyObject_CallObject(m_py_obj, arg_tuple.get())); } -PythonFile::PythonFile() : PythonObject() {} - -PythonFile::PythonFile(File &file, const char *mode) { Reset(file, mode); } - -PythonFile::PythonFile(const char *path, const char *mode) { - lldb_private::File file; - FileSystem::Instance().Open(file, FileSpec(path), GetOptionsFromMode(mode)); - Reset(file, mode); -} - -PythonFile::PythonFile(PyRefType type, PyObject *o) { Reset(type, o); } - -PythonFile::~PythonFile() {} - bool PythonFile::Check(PyObject *py_obj) { + if (!py_obj) + return false; #if PY_MAJOR_VERSION < 3 return PyFile_Check(py_obj); #else @@ -967,86 +950,633 @@ bool PythonFile::Check(PyObject *py_obj) { // first-class object type anymore. `PyFile_FromFd` is just a thin wrapper // over `io.open()`, which returns some object derived from `io.IOBase`. As a // result, the only way to detect a file in Python 3 is to check whether it - // inherits from `io.IOBase`. Since it is possible for non-files to also - // inherit from `io.IOBase`, we additionally verify that it has the `fileno` - // attribute, which should guarantee that it is backed by the file system. - PythonObject io_module(PyRefType::Owned, PyImport_ImportModule("io")); - PythonDictionary io_dict(PyRefType::Borrowed, - PyModule_GetDict(io_module.get())); - PythonObject io_base_class = io_dict.GetItemForKey(PythonString("IOBase")); - - PythonObject object_type(PyRefType::Owned, PyObject_Type(py_obj)); - - if (1 != PyObject_IsSubclass(object_type.get(), io_base_class.get())) + // inherits from `io.IOBase`. + auto io_module = PythonModule::Import("io"); + if (!io_module) { + llvm::consumeError(io_module.takeError()); return false; - if (!object_type.HasAttribute("fileno")) + } + auto iobase = io_module.get().Get("IOBase"); + if (!iobase) { + llvm::consumeError(iobase.takeError()); return false; - - return true; + } + int r = PyObject_IsInstance(py_obj, iobase.get().get()); + if (r < 0) { + llvm::consumeError(exception()); // clear the exception and log it. + return false; + } + return !!r; #endif } -void PythonFile::Reset(PyRefType type, PyObject *py_obj) { - // Grab the desired reference type so that if we end up rejecting `py_obj` it - // still gets decremented if necessary. - PythonObject result(type, py_obj); - - if (!PythonFile::Check(py_obj)) { - PythonObject::Reset(); - return; +namespace { +class GIL { +public: + GIL() { + m_state = PyGILState_Ensure(); + assert(!PyErr_Occurred()); } + ~GIL() { PyGILState_Release(m_state); } + +protected: + PyGILState_STATE m_state; +}; +} // namespace + +const char *PythonException::toCString() const { + if (!m_repr_bytes) + return "unknown exception"; + return PyBytes_AS_STRING(m_repr_bytes); +} + +PythonException::PythonException(const char *caller) { + assert(PyErr_Occurred()); + m_exception_type = m_exception = m_traceback = m_repr_bytes = NULL; + PyErr_Fetch(&m_exception_type, &m_exception, &m_traceback); + PyErr_NormalizeException(&m_exception_type, &m_exception, &m_traceback); + PyErr_Clear(); + if (m_exception) { + PyObject *repr = PyObject_Repr(m_exception); + if (repr) { + m_repr_bytes = PyUnicode_AsEncodedString(repr, "utf-8", nullptr); + if (!m_repr_bytes) { + PyErr_Clear(); + } + Py_XDECREF(repr); + } else { + PyErr_Clear(); + } + } + Log *log = GetLogIfAllCategoriesSet(LIBLLDB_LOG_SCRIPT); + if (caller) + LLDB_LOGF(log, "%s failed with exception: %s", caller, toCString()); + else + LLDB_LOGF(log, "python exception: %s", toCString()); +} +void PythonException::Restore() { + if (m_exception_type && m_exception) { + PyErr_Restore(m_exception_type, m_exception, m_traceback); + } else { + PyErr_SetString(PyExc_Exception, toCString()); + } + m_exception_type = m_exception = m_traceback = NULL; +} - // Calling PythonObject::Reset(const PythonObject&) will lead to stack - // overflow since it calls back into the virtual implementation. - PythonObject::Reset(PyRefType::Borrowed, result.get()); +PythonException::~PythonException() { + Py_XDECREF(m_exception_type); + Py_XDECREF(m_exception); + Py_XDECREF(m_traceback); + Py_XDECREF(m_repr_bytes); } -void PythonFile::Reset(File &file, const char *mode) { - if (!file.IsValid()) { - Reset(); - return; +void PythonException::log(llvm::raw_ostream &OS) const { OS << toCString(); } + +std::error_code PythonException::convertToErrorCode() const { + return llvm::inconvertibleErrorCode(); +} + +bool PythonException::Matches(PyObject *exc) const { + return PyErr_GivenExceptionMatches(m_exception_type, exc); +} + +const char read_exception_script[] = R"( +import sys +from traceback import print_exception +if sys.version_info.major < 3: + from StringIO import StringIO +else: + from io import StringIO +def main(exc_type, exc_value, tb): + f = StringIO() + print_exception(exc_type, exc_value, tb, file=f) + return f.getvalue() +)"; + +std::string PythonException::ReadBacktrace() const { + + if (!m_traceback) + return toCString(); + + // no need to synchronize access to this global, we already have the GIL + static PythonScript read_exception(read_exception_script); + + Expected<std::string> backtrace = As<std::string>( + read_exception(m_exception_type, m_exception, m_traceback)); + + if (!backtrace) { + std::string message = + std::string(toCString()) + "\n" + + "Traceback unavailble, an error occurred while reading it:\n"; + return (message + llvm::toString(backtrace.takeError())); } - char *cmode = const_cast<char *>(mode); + return std::move(backtrace.get()); +} + +char PythonException::ID = 0; + +llvm::Expected<File::OpenOptions> +GetOptionsForPyObject(const PythonObject &obj) { #if PY_MAJOR_VERSION >= 3 - Reset(PyRefType::Owned, PyFile_FromFd(file.GetDescriptor(), nullptr, cmode, - -1, nullptr, "ignore", nullptr, 0)); + auto options = File::OpenOptions(0); + auto readable = As<bool>(obj.CallMethod("readable")); + if (!readable) + return readable.takeError(); + auto writable = As<bool>(obj.CallMethod("writable")); + if (!writable) + return writable.takeError(); + if (readable.get()) + options |= File::eOpenOptionRead; + if (writable.get()) + options |= File::eOpenOptionWrite; + return options; #else - // Read through the Python source, doesn't seem to modify these strings - Reset(PyRefType::Owned, - PyFile_FromFile(file.GetStream(), const_cast<char *>(""), cmode, - nullptr)); + PythonString py_mode = obj.GetAttributeValue("mode").AsType<PythonString>(); + return File::GetOptionsFromMode(py_mode.GetString()); #endif } -uint32_t PythonFile::GetOptionsFromMode(llvm::StringRef mode) { - if (mode.empty()) - return 0; +// Base class template for python files. All it knows how to do +// is hold a reference to the python object and close or flush it +// when the File is closed. +namespace { +template <typename Base> class OwnedPythonFile : public Base { +public: + template <typename... Args> + OwnedPythonFile(const PythonFile &file, bool borrowed, Args... args) + : Base(args...), m_py_obj(file), m_borrowed(borrowed) { + assert(m_py_obj); + } + + ~OwnedPythonFile() override { + assert(m_py_obj); + GIL takeGIL; + Close(); + // we need to ensure the python object is released while we still + // hold the GIL + m_py_obj.Reset(); + } + + bool IsPythonSideValid() const { + GIL takeGIL; + auto closed = As<bool>(m_py_obj.GetAttribute("closed")); + if (!closed) { + llvm::consumeError(closed.takeError()); + return false; + } + return !closed.get(); + } + + bool IsValid() const override { + return IsPythonSideValid() && Base::IsValid(); + } + + Status Close() override { + assert(m_py_obj); + Status py_error, base_error; + GIL takeGIL; + if (!m_borrowed) { + auto r = m_py_obj.CallMethod("close"); + if (!r) + py_error = Status(r.takeError()); + } + base_error = Base::Close(); + if (py_error.Fail()) + return py_error; + return base_error; + }; + + PyObject *GetPythonObject() const { + assert(m_py_obj.IsValid()); + return m_py_obj.get(); + } + + static bool classof(const File *file) = delete; + +protected: + PythonFile m_py_obj; + bool m_borrowed; +}; +} // namespace + +// A SimplePythonFile is a OwnedPythonFile that just does all I/O as +// a NativeFile +namespace { +class SimplePythonFile : public OwnedPythonFile<NativeFile> { +public: + SimplePythonFile(const PythonFile &file, bool borrowed, int fd, + File::OpenOptions options) + : OwnedPythonFile(file, borrowed, fd, options, false) {} + + static char ID; + bool isA(const void *classID) const override { + return classID == &ID || NativeFile::isA(classID); + } + static bool classof(const File *file) { return file->isA(&ID); } +}; +char SimplePythonFile::ID = 0; +} // namespace + +#if PY_MAJOR_VERSION >= 3 + +namespace { +class PythonBuffer { +public: + PythonBuffer &operator=(const PythonBuffer &) = delete; + PythonBuffer(const PythonBuffer &) = delete; + + static Expected<PythonBuffer> Create(PythonObject &obj, + int flags = PyBUF_SIMPLE) { + Py_buffer py_buffer = {}; + PyObject_GetBuffer(obj.get(), &py_buffer, flags); + if (!py_buffer.obj) + return llvm::make_error<PythonException>(); + return PythonBuffer(py_buffer); + } + + PythonBuffer(PythonBuffer &&other) { + m_buffer = other.m_buffer; + other.m_buffer.obj = nullptr; + } - return llvm::StringSwitch<uint32_t>(mode.str()) - .Case("r", File::eOpenOptionRead) - .Case("w", File::eOpenOptionWrite) - .Case("a", File::eOpenOptionWrite | File::eOpenOptionAppend | - File::eOpenOptionCanCreate) - .Case("r+", File::eOpenOptionRead | File::eOpenOptionWrite) - .Case("w+", File::eOpenOptionRead | File::eOpenOptionWrite | - File::eOpenOptionCanCreate | File::eOpenOptionTruncate) - .Case("a+", File::eOpenOptionRead | File::eOpenOptionWrite | - File::eOpenOptionAppend | File::eOpenOptionCanCreate) - .Default(0); + ~PythonBuffer() { + if (m_buffer.obj) + PyBuffer_Release(&m_buffer); + } + + Py_buffer &get() { return m_buffer; } + +private: + // takes ownership of the buffer. + PythonBuffer(const Py_buffer &py_buffer) : m_buffer(py_buffer) {} + Py_buffer m_buffer; +}; +} // namespace + +// Shared methods between TextPythonFile and BinaryPythonFile +namespace { +class PythonIOFile : public OwnedPythonFile<File> { +public: + PythonIOFile(const PythonFile &file, bool borrowed) + : OwnedPythonFile(file, borrowed) {} + + ~PythonIOFile() override { Close(); } + + bool IsValid() const override { return IsPythonSideValid(); } + + Status Close() override { + assert(m_py_obj); + GIL takeGIL; + if (m_borrowed) + return Flush(); + auto r = m_py_obj.CallMethod("close"); + if (!r) + return Status(r.takeError()); + return Status(); + } + + Status Flush() override { + GIL takeGIL; + auto r = m_py_obj.CallMethod("flush"); + if (!r) + return Status(r.takeError()); + return Status(); + } + + Expected<File::OpenOptions> GetOptions() const override { + GIL takeGIL; + return GetOptionsForPyObject(m_py_obj); + } + + static char ID; + bool isA(const void *classID) const override { + return classID == &ID || File::isA(classID); + } + static bool classof(const File *file) { return file->isA(&ID); } +}; +char PythonIOFile::ID = 0; +} // namespace + +namespace { +class BinaryPythonFile : public PythonIOFile { +protected: + int m_descriptor; + +public: + BinaryPythonFile(int fd, const PythonFile &file, bool borrowed) + : PythonIOFile(file, borrowed), + m_descriptor(File::DescriptorIsValid(fd) ? fd + : File::kInvalidDescriptor) {} + + int GetDescriptor() const override { return m_descriptor; } + + Status Write(const void *buf, size_t &num_bytes) override { + GIL takeGIL; + PyObject *pybuffer_p = PyMemoryView_FromMemory( + const_cast<char *>((const char *)buf), num_bytes, PyBUF_READ); + if (!pybuffer_p) + return Status(llvm::make_error<PythonException>()); + auto pybuffer = Take<PythonObject>(pybuffer_p); + num_bytes = 0; + auto bytes_written = As<long long>(m_py_obj.CallMethod("write", pybuffer)); + if (!bytes_written) + return Status(bytes_written.takeError()); + if (bytes_written.get() < 0) + return Status(".write() method returned a negative number!"); + static_assert(sizeof(long long) >= sizeof(size_t), "overflow"); + num_bytes = bytes_written.get(); + return Status(); + } + + Status Read(void *buf, size_t &num_bytes) override { + GIL takeGIL; + static_assert(sizeof(long long) >= sizeof(size_t), "overflow"); + auto pybuffer_obj = + m_py_obj.CallMethod("read", (unsigned long long)num_bytes); + if (!pybuffer_obj) + return Status(pybuffer_obj.takeError()); + num_bytes = 0; + if (pybuffer_obj.get().IsNone()) { + // EOF + num_bytes = 0; + return Status(); + } + auto pybuffer = PythonBuffer::Create(pybuffer_obj.get()); + if (!pybuffer) + return Status(pybuffer.takeError()); + memcpy(buf, pybuffer.get().get().buf, pybuffer.get().get().len); + num_bytes = pybuffer.get().get().len; + return Status(); + } +}; +} // namespace + +namespace { +class TextPythonFile : public PythonIOFile { +protected: + int m_descriptor; + +public: + TextPythonFile(int fd, const PythonFile &file, bool borrowed) + : PythonIOFile(file, borrowed), + m_descriptor(File::DescriptorIsValid(fd) ? fd + : File::kInvalidDescriptor) {} + + int GetDescriptor() const override { return m_descriptor; } + + Status Write(const void *buf, size_t &num_bytes) override { + GIL takeGIL; + auto pystring = + PythonString::FromUTF8(llvm::StringRef((const char *)buf, num_bytes)); + if (!pystring) + return Status(pystring.takeError()); + num_bytes = 0; + auto bytes_written = + As<long long>(m_py_obj.CallMethod("write", pystring.get())); + if (!bytes_written) + return Status(bytes_written.takeError()); + if (bytes_written.get() < 0) + return Status(".write() method returned a negative number!"); + static_assert(sizeof(long long) >= sizeof(size_t), "overflow"); + num_bytes = bytes_written.get(); + return Status(); + } + + Status Read(void *buf, size_t &num_bytes) override { + GIL takeGIL; + size_t num_chars = num_bytes / 6; + size_t orig_num_bytes = num_bytes; + num_bytes = 0; + if (orig_num_bytes < 6) { + return Status("can't read less than 6 bytes from a utf8 text stream"); + } + auto pystring = As<PythonString>( + m_py_obj.CallMethod("read", (unsigned long long)num_chars)); + if (!pystring) + return Status(pystring.takeError()); + if (pystring.get().IsNone()) { + // EOF + return Status(); + } + auto stringref = pystring.get().AsUTF8(); + if (!stringref) + return Status(stringref.takeError()); + num_bytes = stringref.get().size(); + memcpy(buf, stringref.get().begin(), num_bytes); + return Status(); + } +}; +} // namespace + +#endif + +llvm::Expected<FileSP> PythonFile::ConvertToFile(bool borrowed) { + if (!IsValid()) + return llvm::createStringError(llvm::inconvertibleErrorCode(), + "invalid PythonFile"); + + int fd = PyObject_AsFileDescriptor(m_py_obj); + if (fd < 0) { + PyErr_Clear(); + return ConvertToFileForcingUseOfScriptingIOMethods(borrowed); + } + auto options = GetOptionsForPyObject(*this); + if (!options) + return options.takeError(); + + // LLDB and python will not share I/O buffers. We should probably + // flush the python buffers now. + auto r = CallMethod("flush"); + if (!r) + return r.takeError(); + + FileSP file_sp; + if (borrowed) { + // In this case we we don't need to retain the python + // object at all. + file_sp = std::make_shared<NativeFile>(fd, options.get(), false); + } else { + file_sp = std::static_pointer_cast<File>( + std::make_shared<SimplePythonFile>(*this, borrowed, fd, options.get())); + } + if (!file_sp->IsValid()) + return llvm::createStringError(llvm::inconvertibleErrorCode(), + "invalid File"); + + return file_sp; } -bool PythonFile::GetUnderlyingFile(File &file) const { +llvm::Expected<FileSP> +PythonFile::ConvertToFileForcingUseOfScriptingIOMethods(bool borrowed) { + + assert(!PyErr_Occurred()); + if (!IsValid()) - return false; + return llvm::createStringError(llvm::inconvertibleErrorCode(), + "invalid PythonFile"); + +#if PY_MAJOR_VERSION < 3 + + return llvm::createStringError(llvm::inconvertibleErrorCode(), + "not supported on python 2"); + +#else + + int fd = PyObject_AsFileDescriptor(m_py_obj); + if (fd < 0) { + PyErr_Clear(); + fd = File::kInvalidDescriptor; + } + + auto io_module = PythonModule::Import("io"); + if (!io_module) + return io_module.takeError(); + auto textIOBase = io_module.get().Get("TextIOBase"); + if (!textIOBase) + return textIOBase.takeError(); + auto rawIOBase = io_module.get().Get("RawIOBase"); + if (!rawIOBase) + return rawIOBase.takeError(); + auto bufferedIOBase = io_module.get().Get("BufferedIOBase"); + if (!bufferedIOBase) + return bufferedIOBase.takeError(); + + FileSP file_sp; + + auto isTextIO = IsInstance(textIOBase.get()); + if (!isTextIO) + return isTextIO.takeError(); + if (isTextIO.get()) + file_sp = std::static_pointer_cast<File>( + std::make_shared<TextPythonFile>(fd, *this, borrowed)); + + auto isRawIO = IsInstance(rawIOBase.get()); + if (!isRawIO) + return isRawIO.takeError(); + auto isBufferedIO = IsInstance(bufferedIOBase.get()); + if (!isBufferedIO) + return isBufferedIO.takeError(); + + if (isRawIO.get() || isBufferedIO.get()) { + file_sp = std::static_pointer_cast<File>( + std::make_shared<BinaryPythonFile>(fd, *this, borrowed)); + } + + if (!file_sp) + return llvm::createStringError(llvm::inconvertibleErrorCode(), + "python file is neither text nor binary"); + + if (!file_sp->IsValid()) + return llvm::createStringError(llvm::inconvertibleErrorCode(), + "invalid File"); + + return file_sp; + +#endif +} + +Expected<PythonFile> PythonFile::FromFile(File &file, const char *mode) { + if (!file.IsValid()) + return llvm::createStringError(llvm::inconvertibleErrorCode(), + "invalid file"); + + if (auto *simple = llvm::dyn_cast<SimplePythonFile>(&file)) + return Retain<PythonFile>(simple->GetPythonObject()); +#if PY_MAJOR_VERSION >= 3 + if (auto *pythonio = llvm::dyn_cast<PythonIOFile>(&file)) + return Retain<PythonFile>(pythonio->GetPythonObject()); +#endif + + if (!mode) { + auto m = file.GetOpenMode(); + if (!m) + return m.takeError(); + mode = m.get(); + } + + PyObject *file_obj; +#if PY_MAJOR_VERSION >= 3 + file_obj = PyFile_FromFd(file.GetDescriptor(), nullptr, mode, -1, nullptr, + "ignore", nullptr, 0); +#else + // Read through the Python source, doesn't seem to modify these strings + char *cmode = const_cast<char *>(mode); + // We pass ::flush instead of ::fclose here so we borrow the FILE* -- + // the lldb_private::File still owns it. + file_obj = + PyFile_FromFile(file.GetStream(), const_cast<char *>(""), cmode, ::fflush); +#endif + + if (!file_obj) + return exception(); + + return Take<PythonFile>(file_obj); +} + +Error PythonScript::Init() { + if (function.IsValid()) + return Error::success(); + + PythonDictionary globals(PyInitialValue::Empty); + auto builtins = PythonModule::BuiltinsModule(); + if (Error error = globals.SetItem("__builtins__", builtins)) + return error; + PyObject *o = + PyRun_String(script, Py_file_input, globals.get(), globals.get()); + if (!o) + return exception(); + Take<PythonObject>(o); + auto f = As<PythonCallable>(globals.GetItem("main")); + if (!f) + return f.takeError(); + function = std::move(f.get()); + + return Error::success(); +} + +llvm::Expected<PythonObject> +python::runStringOneLine(const llvm::Twine &string, + const PythonDictionary &globals, + const PythonDictionary &locals) { + if (!globals.IsValid() || !locals.IsValid()) + return nullDeref(); + + PyObject *code = + Py_CompileString(NullTerminated(string), "<string>", Py_eval_input); + if (!code) { + PyErr_Clear(); + code = + Py_CompileString(NullTerminated(string), "<string>", Py_single_input); + } + if (!code) + return exception(); + auto code_ref = Take<PythonObject>(code); + +#if PY_MAJOR_VERSION < 3 + PyObject *result = + PyEval_EvalCode((PyCodeObject *)code, globals.get(), locals.get()); +#else + PyObject *result = PyEval_EvalCode(code, globals.get(), locals.get()); +#endif + + if (!result) + return exception(); + + return Take<PythonObject>(result); +} - file.Close(); - // We don't own the file descriptor returned by this function, make sure the - // File object knows about that. - file.SetDescriptor(PyObject_AsFileDescriptor(m_py_obj), false); - PythonString py_mode = GetAttributeValue("mode").AsType<PythonString>(); - file.SetOptions(PythonFile::GetOptionsFromMode(py_mode.GetString())); - return file.IsValid(); +llvm::Expected<PythonObject> +python::runStringMultiLine(const llvm::Twine &string, + const PythonDictionary &globals, + const PythonDictionary &locals) { + if (!globals.IsValid() || !locals.IsValid()) + return nullDeref(); + PyObject *result = PyRun_String(NullTerminated(string), Py_file_input, + globals.get(), locals.get()); + if (!result) + return exception(); + return Take<PythonObject>(result); } #endif diff --git a/source/Plugins/ScriptInterpreter/Python/PythonDataObjects.h b/source/Plugins/ScriptInterpreter/Python/PythonDataObjects.h index 049ce90bb1b1..373d3212697d 100644 --- a/source/Plugins/ScriptInterpreter/Python/PythonDataObjects.h +++ b/source/Plugins/ScriptInterpreter/Python/PythonDataObjects.h @@ -6,6 +6,45 @@ // //===----------------------------------------------------------------------===// +// +// !! FIXME FIXME FIXME !! +// +// Python APIs nearly all can return an exception. They do this +// by returning NULL, or -1, or some such value and setting +// the exception state with PyErr_Set*(). Exceptions must be +// handled before further python API functions are called. Failure +// to do so will result in asserts on debug builds of python. +// It will also sometimes, but not usually result in crashes of +// release builds. +// +// Nearly all the code in this header does not handle python exceptions +// correctly. It should all be converted to return Expected<> or +// Error types to capture the exception. +// +// Everything in this file except functions that return Error or +// Expected<> is considered deprecated and should not be +// used in new code. If you need to use it, fix it first. +// +// +// TODOs for this file +// +// * Make all methods safe for exceptions. +// +// * Eliminate method signatures that must translate exceptions into +// empty objects or NULLs. Almost everything here should return +// Expected<>. It should be acceptable for certain operations that +// can never fail to assert instead, such as the creation of +// PythonString from a string literal. +// +// * Elimintate Reset(), and make all non-default constructors private. +// Python objects should be created with Retain<> or Take<>, and they +// should be assigned with operator= +// +// * Eliminate default constructors, make python objects always +// nonnull, and use optionals where necessary. +// + + #ifndef LLDB_PLUGINS_SCRIPTINTERPRETER_PYTHON_PYTHONDATAOBJECTS_H #define LLDB_PLUGINS_SCRIPTINTERPRETER_PYTHON_PYTHONDATAOBJECTS_H @@ -20,12 +59,15 @@ #include "llvm/ADT/ArrayRef.h" namespace lldb_private { +namespace python { +class PythonObject; class PythonBytes; class PythonString; class PythonList; class PythonDictionary; class PythonInteger; +class PythonException; class StructuredPythonObject : public StructuredData::Generic { public: @@ -43,7 +85,7 @@ public: bool IsValid() const override { return GetValue() && GetValue() != Py_None; } - void Dump(Stream &s, bool pretty_print = true) const override; + void Serialize(llvm::json::OStream &s) const override; private: DISALLOW_COPY_AND_ASSIGN(StructuredPythonObject); @@ -72,61 +114,137 @@ enum class PyRefType { // not call Py_INCREF. }; -enum class PyInitialValue { Invalid, Empty }; -class PythonObject { -public: - PythonObject() : m_py_obj(nullptr) {} +// Take a reference that you already own, and turn it into +// a PythonObject. +// +// Most python API methods will return a +1 reference +// if they succeed or NULL if and only if +// they set an exception. Use this to collect such return +// values, after checking for NULL. +// +// If T is not just PythonObject, then obj must be already be +// checked to be of the correct type. +template <typename T> T Take(PyObject *obj) { + assert(obj); + assert(!PyErr_Occurred()); + T thing(PyRefType::Owned, obj); + assert(thing.IsValid()); + return std::move(thing); +} + +// Retain a reference you have borrowed, and turn it into +// a PythonObject. +// +// A minority of python APIs return a borrowed reference +// instead of a +1. They will also return NULL if and only +// if they set an exception. Use this to collect such return +// values, after checking for NULL. +// +// If T is not just PythonObject, then obj must be already be +// checked to be of the correct type. +template <typename T> T Retain(PyObject *obj) { + assert(obj); + assert(!PyErr_Occurred()); + T thing(PyRefType::Borrowed, obj); + assert(thing.IsValid()); + return std::move(thing); +} + +// This class can be used like a utility function to convert from +// a llvm-friendly Twine into a null-terminated const char *, +// which is the form python C APIs want their strings in. +// +// Example: +// const llvm::Twine &some_twine; +// PyFoo_Bar(x, y, z, NullTerminated(some_twine)); +// +// Why a class instead of a function? If the twine isn't already null +// terminated, it will need a temporary buffer to copy the string +// into. We need that buffer to stick around for the lifetime of the +// statement. +class NullTerminated { + const char *str; + llvm::SmallString<32> storage; - PythonObject(PyRefType type, PyObject *py_obj) : m_py_obj(nullptr) { - Reset(type, py_obj); +public: + NullTerminated(const llvm::Twine &twine) { + llvm::StringRef ref = twine.toNullTerminatedStringRef(storage); + str = ref.begin(); } + operator const char *() { return str; } +}; - PythonObject(const PythonObject &rhs) : m_py_obj(nullptr) { Reset(rhs); } +inline llvm::Error nullDeref() { + return llvm::createStringError(llvm::inconvertibleErrorCode(), + "A NULL PyObject* was dereferenced"); +} - virtual ~PythonObject() { Reset(); } +inline llvm::Error exception(const char *s = nullptr) { + return llvm::make_error<PythonException>(s); +} - void Reset() { - // Avoid calling the virtual method since it's not necessary - // to actually validate the type of the PyObject if we're - // just setting to null. - if (Py_IsInitialized()) - Py_XDECREF(m_py_obj); - m_py_obj = nullptr; - } +inline llvm::Error keyError() { + return llvm::createStringError(llvm::inconvertibleErrorCode(), + "key not in dict"); +} - void Reset(const PythonObject &rhs) { - // Avoid calling the virtual method if it's not necessary - // to actually validate the type of the PyObject. - if (!rhs.IsValid()) - Reset(); - else - Reset(PyRefType::Borrowed, rhs.m_py_obj); - } +enum class PyInitialValue { Invalid, Empty }; - // PythonObject is implicitly convertible to PyObject *, which will call the - // wrong overload. We want to explicitly disallow this, since a PyObject - // *always* owns its reference. Therefore the overload which takes a - // PyRefType doesn't make sense, and the copy constructor should be used. - void Reset(PyRefType type, const PythonObject &ref) = delete; +template <typename T, typename Enable = void> struct PythonFormat; - virtual void Reset(PyRefType type, PyObject *py_obj) { - if (py_obj == m_py_obj) - return; +template <> struct PythonFormat<unsigned long long> { + static constexpr char format = 'K'; + static auto get(unsigned long long value) { return value; } +}; - if (Py_IsInitialized()) - Py_XDECREF(m_py_obj); +template <> struct PythonFormat<long long> { + static constexpr char format = 'L'; + static auto get(long long value) { return value; } +}; - m_py_obj = py_obj; +template <> struct PythonFormat<PyObject *> { + static constexpr char format = 'O'; + static auto get(PyObject *value) { return value; } +}; + +template <typename T> +struct PythonFormat< + T, typename std::enable_if<std::is_base_of<PythonObject, T>::value>::type> { + static constexpr char format = 'O'; + static auto get(const T &value) { return value.get(); } +}; + +class PythonObject { +public: + PythonObject() : m_py_obj(nullptr) {} + PythonObject(PyRefType type, PyObject *py_obj) { + m_py_obj = py_obj; // If this is a borrowed reference, we need to convert it to // an owned reference by incrementing it. If it is an owned // reference (for example the caller allocated it with PyDict_New() // then we must *not* increment it. - if (Py_IsInitialized() && type == PyRefType::Borrowed) + if (m_py_obj && Py_IsInitialized() && type == PyRefType::Borrowed) Py_XINCREF(m_py_obj); } + PythonObject(const PythonObject &rhs) + : PythonObject(PyRefType::Borrowed, rhs.m_py_obj) {} + + PythonObject(PythonObject &&rhs) { + m_py_obj = rhs.m_py_obj; + rhs.m_py_obj = nullptr; + } + + ~PythonObject() { Reset(); } + + void Reset() { + if (m_py_obj && Py_IsInitialized()) + Py_DECREF(m_py_obj); + m_py_obj = nullptr; + } + void Dump() const { if (m_py_obj) _PyObject_Dump(m_py_obj); @@ -144,8 +262,9 @@ public: return result; } - PythonObject &operator=(const PythonObject &other) { - Reset(PyRefType::Borrowed, other.get()); + PythonObject &operator=(PythonObject other) { + Reset(); + m_py_obj = std::exchange(other.m_py_obj, nullptr); return *this; } @@ -174,11 +293,13 @@ public: PythonObject GetAttributeValue(llvm::StringRef attribute) const; - bool IsValid() const; + bool IsNone() const { return m_py_obj == Py_None; } + + bool IsValid() const { return m_py_obj != nullptr; } - bool IsAllocated() const; + bool IsAllocated() const { return IsValid() && !IsNone(); } - bool IsNone() const; + explicit operator bool() const { return IsValid() && !IsNone(); } template <typename T> T AsType() const { if (!T::Check(m_py_obj)) @@ -189,24 +310,125 @@ public: StructuredData::ObjectSP CreateStructuredObject() const; protected: + +#if PY_MAJOR_VERSION < 3 + // The python 2 API declares some arguments as char* that should + // be const char *, but it doesn't actually modify them. + static char *py2_const_cast(const char *s) { return const_cast<char *>(s); } +#else + static const char *py2_const_cast(const char *s) { return s; } +#endif + +public: + template <typename... T> + llvm::Expected<PythonObject> CallMethod(const char *name, + const T &... t) const { + const char format[] = {'(', PythonFormat<T>::format..., ')', 0}; + PyObject *obj = + PyObject_CallMethod(m_py_obj, py2_const_cast(name), + py2_const_cast(format), PythonFormat<T>::get(t)...); + if (!obj) + return exception(); + return python::Take<PythonObject>(obj); + } + + template <typename... T> + llvm::Expected<PythonObject> Call(const T &... t) const { + const char format[] = {'(', PythonFormat<T>::format..., ')', 0}; + PyObject *obj = PyObject_CallFunction(m_py_obj, py2_const_cast(format), + PythonFormat<T>::get(t)...); + if (!obj) + return exception(); + return python::Take<PythonObject>(obj); + } + + llvm::Expected<PythonObject> GetAttribute(const llvm::Twine &name) const { + if (!m_py_obj) + return nullDeref(); + PyObject *obj = PyObject_GetAttrString(m_py_obj, NullTerminated(name)); + if (!obj) + return exception(); + return python::Take<PythonObject>(obj); + } + + llvm::Expected<bool> IsTrue() { + if (!m_py_obj) + return nullDeref(); + int r = PyObject_IsTrue(m_py_obj); + if (r < 0) + return exception(); + return !!r; + } + + llvm::Expected<long long> AsLongLong() { + if (!m_py_obj) + return nullDeref(); + assert(!PyErr_Occurred()); + long long r = PyLong_AsLongLong(m_py_obj); + if (PyErr_Occurred()) + return exception(); + return r; + } + + llvm::Expected<bool> IsInstance(const PythonObject &cls) { + if (!m_py_obj || !cls.IsValid()) + return nullDeref(); + int r = PyObject_IsInstance(m_py_obj, cls.get()); + if (r < 0) + return exception(); + return !!r; + } + +protected: PyObject *m_py_obj; }; -class PythonBytes : public PythonObject { + +// This is why C++ needs monads. +template <typename T> llvm::Expected<T> As(llvm::Expected<PythonObject> &&obj) { + if (!obj) + return obj.takeError(); + if (!T::Check(obj.get().get())) + return llvm::createStringError(llvm::inconvertibleErrorCode(), + "type error"); + return T(PyRefType::Borrowed, std::move(obj.get().get())); +} + +template <> llvm::Expected<bool> As<bool>(llvm::Expected<PythonObject> &&obj); + +template <> +llvm::Expected<long long> As<long long>(llvm::Expected<PythonObject> &&obj); + +template <> +llvm::Expected<std::string> As<std::string>(llvm::Expected<PythonObject> &&obj); + + +template <class T> class TypedPythonObject : public PythonObject { public: - PythonBytes(); - explicit PythonBytes(llvm::ArrayRef<uint8_t> bytes); - PythonBytes(const uint8_t *bytes, size_t length); - PythonBytes(PyRefType type, PyObject *o); + // override to perform implicit type conversions on Reset + // This can be eliminated once we drop python 2 support. + static void Convert(PyRefType &type, PyObject *&py_obj) {} - ~PythonBytes() override; + TypedPythonObject(PyRefType type, PyObject *py_obj) { + if (!py_obj) + return; + T::Convert(type, py_obj); + if (T::Check(py_obj)) + PythonObject::operator=(PythonObject(type, py_obj)); + else if (type == PyRefType::Owned) + Py_DECREF(py_obj); + } - static bool Check(PyObject *py_obj); + TypedPythonObject() {} +}; - // Bring in the no-argument base class version - using PythonObject::Reset; +class PythonBytes : public TypedPythonObject<PythonBytes> { +public: + using TypedPythonObject::TypedPythonObject; + explicit PythonBytes(llvm::ArrayRef<uint8_t> bytes); + PythonBytes(const uint8_t *bytes, size_t length); - void Reset(PyRefType type, PyObject *py_obj) override; + static bool Check(PyObject *py_obj); llvm::ArrayRef<uint8_t> GetBytes() const; @@ -217,23 +439,15 @@ public: StructuredData::StringSP CreateStructuredString() const; }; -class PythonByteArray : public PythonObject { +class PythonByteArray : public TypedPythonObject<PythonByteArray> { public: - PythonByteArray(); + using TypedPythonObject::TypedPythonObject; explicit PythonByteArray(llvm::ArrayRef<uint8_t> bytes); PythonByteArray(const uint8_t *bytes, size_t length); - PythonByteArray(PyRefType type, PyObject *o); PythonByteArray(const PythonBytes &object); - ~PythonByteArray() override; - static bool Check(PyObject *py_obj); - // Bring in the no-argument base class version - using PythonObject::Reset; - - void Reset(PyRefType type, PyObject *py_obj) override; - llvm::ArrayRef<uint8_t> GetBytes() const; size_t GetSize() const; @@ -243,45 +457,39 @@ public: StructuredData::StringSP CreateStructuredString() const; }; -class PythonString : public PythonObject { +class PythonString : public TypedPythonObject<PythonString> { public: - PythonString(); - explicit PythonString(llvm::StringRef string); - explicit PythonString(const char *string); - PythonString(PyRefType type, PyObject *o); + using TypedPythonObject::TypedPythonObject; + static llvm::Expected<PythonString> FromUTF8(llvm::StringRef string); - ~PythonString() override; + PythonString() : TypedPythonObject() {} // MSVC requires this for some reason - static bool Check(PyObject *py_obj); + explicit PythonString(llvm::StringRef string); // safe, null on error - // Bring in the no-argument base class version - using PythonObject::Reset; + static bool Check(PyObject *py_obj); + static void Convert(PyRefType &type, PyObject *&py_obj); - void Reset(PyRefType type, PyObject *py_obj) override; + llvm::StringRef GetString() const; // safe, empty string on error - llvm::StringRef GetString() const; + llvm::Expected<llvm::StringRef> AsUTF8() const; size_t GetSize() const; - void SetString(llvm::StringRef string); + void SetString(llvm::StringRef string); // safe, null on error StructuredData::StringSP CreateStructuredString() const; }; -class PythonInteger : public PythonObject { +class PythonInteger : public TypedPythonObject<PythonInteger> { public: - PythonInteger(); - explicit PythonInteger(int64_t value); - PythonInteger(PyRefType type, PyObject *o); - - ~PythonInteger() override; + using TypedPythonObject::TypedPythonObject; - static bool Check(PyObject *py_obj); + PythonInteger() : TypedPythonObject() {} // MSVC requires this for some reason - // Bring in the no-argument base class version - using PythonObject::Reset; + explicit PythonInteger(int64_t value); - void Reset(PyRefType type, PyObject *py_obj) override; + static bool Check(PyObject *py_obj); + static void Convert(PyRefType &type, PyObject *&py_obj); int64_t GetInteger() const; @@ -290,21 +498,14 @@ public: StructuredData::IntegerSP CreateStructuredInteger() const; }; -class PythonBoolean : public PythonObject { +class PythonBoolean : public TypedPythonObject<PythonBoolean> { public: - PythonBoolean() = default; - explicit PythonBoolean(bool value); - PythonBoolean(PyRefType type, PyObject *o); + using TypedPythonObject::TypedPythonObject; - ~PythonBoolean() override = default; + explicit PythonBoolean(bool value); static bool Check(PyObject *py_obj); - // Bring in the no-argument base class version - using PythonObject::Reset; - - void Reset(PyRefType type, PyObject *py_obj) override; - bool GetValue() const; void SetValue(bool value); @@ -312,22 +513,17 @@ public: StructuredData::BooleanSP CreateStructuredBoolean() const; }; -class PythonList : public PythonObject { +class PythonList : public TypedPythonObject<PythonList> { public: - PythonList() {} + using TypedPythonObject::TypedPythonObject; + + PythonList() : TypedPythonObject() {} // MSVC requires this for some reason + explicit PythonList(PyInitialValue value); explicit PythonList(int list_size); - PythonList(PyRefType type, PyObject *o); - - ~PythonList() override; static bool Check(PyObject *py_obj); - // Bring in the no-argument base class version - using PythonObject::Reset; - - void Reset(PyRefType type, PyObject *py_obj) override; - uint32_t GetSize() const; PythonObject GetItemAtIndex(uint32_t index) const; @@ -339,24 +535,17 @@ public: StructuredData::ArraySP CreateStructuredArray() const; }; -class PythonTuple : public PythonObject { +class PythonTuple : public TypedPythonObject<PythonTuple> { public: - PythonTuple() {} + using TypedPythonObject::TypedPythonObject; + explicit PythonTuple(PyInitialValue value); explicit PythonTuple(int tuple_size); - PythonTuple(PyRefType type, PyObject *o); PythonTuple(std::initializer_list<PythonObject> objects); PythonTuple(std::initializer_list<PyObject *> objects); - ~PythonTuple() override; - static bool Check(PyObject *py_obj); - // Bring in the no-argument base class version - using PythonObject::Reset; - - void Reset(PyRefType type, PyObject *py_obj) override; - uint32_t GetSize() const; PythonObject GetItemAtIndex(uint32_t index) const; @@ -366,37 +555,35 @@ public: StructuredData::ArraySP CreateStructuredArray() const; }; -class PythonDictionary : public PythonObject { +class PythonDictionary : public TypedPythonObject<PythonDictionary> { public: - PythonDictionary() {} - explicit PythonDictionary(PyInitialValue value); - PythonDictionary(PyRefType type, PyObject *o); + using TypedPythonObject::TypedPythonObject; - ~PythonDictionary() override; - - static bool Check(PyObject *py_obj); + PythonDictionary() : TypedPythonObject() {} // MSVC requires this for some reason - // Bring in the no-argument base class version - using PythonObject::Reset; + explicit PythonDictionary(PyInitialValue value); - void Reset(PyRefType type, PyObject *py_obj) override; + static bool Check(PyObject *py_obj); uint32_t GetSize() const; PythonList GetKeys() const; - PythonObject GetItemForKey(const PythonObject &key) const; - void SetItemForKey(const PythonObject &key, const PythonObject &value); + PythonObject GetItemForKey(const PythonObject &key) const; // DEPRECATED + void SetItemForKey(const PythonObject &key, + const PythonObject &value); // DEPRECATED + + llvm::Expected<PythonObject> GetItem(const PythonObject &key) const; + llvm::Expected<PythonObject> GetItem(const llvm::Twine &key) const; + llvm::Error SetItem(const PythonObject &key, const PythonObject &value) const; + llvm::Error SetItem(const llvm::Twine &key, const PythonObject &value) const; StructuredData::DictionarySP CreateStructuredDictionary() const; }; -class PythonModule : public PythonObject { +class PythonModule : public TypedPythonObject<PythonModule> { public: - PythonModule(); - PythonModule(PyRefType type, PyObject *o); - - ~PythonModule() override; + using TypedPythonObject::TypedPythonObject; static bool Check(PyObject *py_obj); @@ -406,38 +593,57 @@ public: static PythonModule AddModule(llvm::StringRef module); - static PythonModule ImportModule(llvm::StringRef module); + // safe, returns invalid on error; + static PythonModule ImportModule(llvm::StringRef name) { + std::string s = name; + auto mod = Import(s.c_str()); + if (!mod) { + llvm::consumeError(mod.takeError()); + return PythonModule(); + } + return std::move(mod.get()); + } - // Bring in the no-argument base class version - using PythonObject::Reset; + static llvm::Expected<PythonModule> Import(const llvm::Twine &name); - void Reset(PyRefType type, PyObject *py_obj) override; + llvm::Expected<PythonObject> Get(const llvm::Twine &name); PythonDictionary GetDictionary() const; }; -class PythonCallable : public PythonObject { +class PythonCallable : public TypedPythonObject<PythonCallable> { public: + using TypedPythonObject::TypedPythonObject; + struct ArgInfo { - size_t count; - bool is_bound_method : 1; - bool has_varargs : 1; - bool has_kwargs : 1; + /* the largest number of positional arguments this callable + * can accept, or UNBOUNDED, ie UINT_MAX if it's a varargs + * function and can accept an arbitrary number */ + unsigned max_positional_args; + static constexpr unsigned UNBOUNDED = UINT_MAX; // FIXME c++17 inline + /* the number of positional arguments, including optional ones, + * and excluding varargs. If this is a bound method, then the + * count will still include a +1 for self. + * + * FIXME. That's crazy. This should be replaced with + * an accurate min and max for positional args. + */ + int count; + /* does the callable have positional varargs? */ + bool has_varargs : 1; // FIXME delete this }; - PythonCallable(); - PythonCallable(PyRefType type, PyObject *o); - - ~PythonCallable() override; - static bool Check(PyObject *py_obj); - // Bring in the no-argument base class version - using PythonObject::Reset; + llvm::Expected<ArgInfo> GetArgInfo() const; - void Reset(PyRefType type, PyObject *py_obj) override; + llvm::Expected<ArgInfo> GetInitArgInfo() const; - ArgInfo GetNumArguments() const; + ArgInfo GetNumArguments() const; // DEPRECATED + + // If the callable is a Py_Class, then find the number of arguments + // of the __init__ method. + ArgInfo GetNumInitArguments() const; // DEPRECATED PythonObject operator()(); @@ -451,27 +657,123 @@ public: } }; -class PythonFile : public PythonObject { +class PythonFile : public TypedPythonObject<PythonFile> { public: - PythonFile(); - PythonFile(File &file, const char *mode); - PythonFile(const char *path, const char *mode); - PythonFile(PyRefType type, PyObject *o); + using TypedPythonObject::TypedPythonObject; - ~PythonFile() override; + PythonFile() : TypedPythonObject() {} // MSVC requires this for some reason static bool Check(PyObject *py_obj); - using PythonObject::Reset; + static llvm::Expected<PythonFile> FromFile(File &file, + const char *mode = nullptr); - void Reset(PyRefType type, PyObject *py_obj) override; - void Reset(File &file, const char *mode); + llvm::Expected<lldb::FileSP> ConvertToFile(bool borrowed = false); + llvm::Expected<lldb::FileSP> + ConvertToFileForcingUseOfScriptingIOMethods(bool borrowed = false); +}; - static uint32_t GetOptionsFromMode(llvm::StringRef mode); +class PythonException : public llvm::ErrorInfo<PythonException> { +private: + PyObject *m_exception_type, *m_exception, *m_traceback; + PyObject *m_repr_bytes; - bool GetUnderlyingFile(File &file) const; +public: + static char ID; + const char *toCString() const; + PythonException(const char *caller = nullptr); + void Restore(); + ~PythonException(); + void log(llvm::raw_ostream &OS) const override; + std::error_code convertToErrorCode() const override; + bool Matches(PyObject *exc) const; + std::string ReadBacktrace() const; +}; + +// This extracts the underlying T out of an Expected<T> and returns it. +// If the Expected is an Error instead of a T, that error will be converted +// into a python exception, and this will return a default-constructed T. +// +// This is appropriate for use right at the boundary of python calling into +// C++, such as in a SWIG typemap. In such a context you should simply +// check if the returned T is valid, and if it is, return a NULL back +// to python. This will result in the Error being raised as an exception +// from python code's point of view. +// +// For example: +// ``` +// Expected<Foo *> efoop = some_cpp_function(); +// Foo *foop = unwrapOrSetPythonException(efoop); +// if (!foop) +// return NULL; +// do_something(*foop); +// +// If the Error returned was itself created because a python exception was +// raised when C++ code called into python, then the original exception +// will be restored. Otherwise a simple string exception will be raised. +template <typename T> T unwrapOrSetPythonException(llvm::Expected<T> expected) { + if (expected) + return expected.get(); + llvm::handleAllErrors( + expected.takeError(), [](PythonException &E) { E.Restore(); }, + [](const llvm::ErrorInfoBase &E) { + PyErr_SetString(PyExc_Exception, E.message().c_str()); + }); + return T(); +} + +// This is only here to help incrementally migrate old, exception-unsafe +// code. +template <typename T> T unwrapIgnoringErrors(llvm::Expected<T> expected) { + if (expected) + return std::move(expected.get()); + llvm::consumeError(expected.takeError()); + return T(); +} + +llvm::Expected<PythonObject> runStringOneLine(const llvm::Twine &string, + const PythonDictionary &globals, + const PythonDictionary &locals); + +llvm::Expected<PythonObject> runStringMultiLine(const llvm::Twine &string, + const PythonDictionary &globals, + const PythonDictionary &locals); + +// Sometimes the best way to interact with a python interpreter is +// to run some python code. You construct a PythonScript with +// script string. The script assigns some function to `_function_` +// and you get a C++ callable object that calls the python function. +// +// Example: +// +// const char script[] = R"( +// def main(x, y): +// .... +// )"; +// +// Expected<PythonObject> cpp_foo_wrapper(PythonObject x, PythonObject y) { +// // no need to synchronize access to this global, we already have the GIL +// static PythonScript foo(script) +// return foo(x, y); +// } +class PythonScript { + const char *script; + PythonCallable function; + + llvm::Error Init(); + +public: + PythonScript(const char *script) : script(script), function() {} + + template <typename... Args> + llvm::Expected<PythonObject> operator()(Args &&... args) { + if (llvm::Error error = Init()) + return std::move(error); + return function.Call(std::forward<Args>(args)...); + } }; +} // namespace python } // namespace lldb_private #endif diff --git a/source/Plugins/ScriptInterpreter/Python/PythonExceptionState.cpp b/source/Plugins/ScriptInterpreter/Python/PythonExceptionState.cpp deleted file mode 100644 index c9d834ce6868..000000000000 --- a/source/Plugins/ScriptInterpreter/Python/PythonExceptionState.cpp +++ /dev/null @@ -1,169 +0,0 @@ -//===-- PythonExceptionState.cpp --------------------------------*- C++ -*-===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// - -#ifndef LLDB_DISABLE_PYTHON - -// LLDB Python header must be included first -#include "lldb-python.h" - -#include "PythonExceptionState.h" - -#include "llvm/ADT/StringRef.h" -#include "llvm/Support/raw_ostream.h" - -using namespace lldb_private; - -PythonExceptionState::PythonExceptionState(bool restore_on_exit) - : m_restore_on_exit(restore_on_exit) { - Acquire(restore_on_exit); -} - -PythonExceptionState::~PythonExceptionState() { - if (m_restore_on_exit) - Restore(); -} - -void PythonExceptionState::Acquire(bool restore_on_exit) { - // If a state is already acquired, the user needs to decide whether they want - // to discard or restore it. Don't allow the potential silent loss of a - // valid state. - assert(!IsError()); - - if (!HasErrorOccurred()) - return; - - PyObject *py_type = nullptr; - PyObject *py_value = nullptr; - PyObject *py_traceback = nullptr; - PyErr_Fetch(&py_type, &py_value, &py_traceback); - // PyErr_Fetch clears the error flag. - assert(!HasErrorOccurred()); - - // Ownership of the objects returned by `PyErr_Fetch` is transferred to us. - m_type.Reset(PyRefType::Owned, py_type); - m_value.Reset(PyRefType::Owned, py_value); - m_traceback.Reset(PyRefType::Owned, py_traceback); - m_restore_on_exit = restore_on_exit; -} - -void PythonExceptionState::Restore() { - if (m_type.IsValid()) { - // The documentation for PyErr_Restore says "Do not pass a null type and - // non-null value or traceback. So only restore if type was non-null to - // begin with. In this case we're passing ownership back to Python so - // release them all. - PyErr_Restore(m_type.release(), m_value.release(), m_traceback.release()); - } - - // After we restore, we should not hold onto the exception state. Demand - // that it be re-acquired. - Discard(); -} - -void PythonExceptionState::Discard() { - m_type.Reset(); - m_value.Reset(); - m_traceback.Reset(); -} - -void PythonExceptionState::Reset() { - if (m_restore_on_exit) - Restore(); - else - Discard(); -} - -bool PythonExceptionState::HasErrorOccurred() { return PyErr_Occurred(); } - -bool PythonExceptionState::IsError() const { - return m_type.IsValid() || m_value.IsValid() || m_traceback.IsValid(); -} - -PythonObject PythonExceptionState::GetType() const { return m_type; } - -PythonObject PythonExceptionState::GetValue() const { return m_value; } - -PythonObject PythonExceptionState::GetTraceback() const { return m_traceback; } - -std::string PythonExceptionState::Format() const { - // Don't allow this function to modify the error state. - PythonExceptionState state(true); - - std::string backtrace = ReadBacktrace(); - if (!IsError()) - return std::string(); - - // It's possible that ReadPythonBacktrace generated another exception. If - // this happens we have to clear the exception, because otherwise - // PyObject_Str() will assert below. That's why we needed to do the save / - // restore at the beginning of this function. - PythonExceptionState bt_error_state(false); - - std::string error_string; - llvm::raw_string_ostream error_stream(error_string); - error_stream << m_value.Str().GetString() << "\n"; - - if (!bt_error_state.IsError()) { - // If we were able to read the backtrace, just append it. - error_stream << backtrace << "\n"; - } else { - // Otherwise, append some information about why we were unable to obtain - // the backtrace. - PythonString bt_error = bt_error_state.GetValue().Str(); - error_stream << "An error occurred while retrieving the backtrace: " - << bt_error.GetString() << "\n"; - } - return error_stream.str(); -} - -std::string PythonExceptionState::ReadBacktrace() const { - std::string retval("backtrace unavailable"); - - auto traceback_module = PythonModule::ImportModule("traceback"); -#if PY_MAJOR_VERSION >= 3 - auto stringIO_module = PythonModule::ImportModule("io"); -#else - auto stringIO_module = PythonModule::ImportModule("StringIO"); -#endif - if (!m_traceback.IsAllocated()) - return retval; - - if (!traceback_module.IsAllocated() || !stringIO_module.IsAllocated()) - return retval; - - auto stringIO_builder = - stringIO_module.ResolveName<PythonCallable>("StringIO"); - if (!stringIO_builder.IsAllocated()) - return retval; - - auto stringIO_buffer = stringIO_builder(); - if (!stringIO_buffer.IsAllocated()) - return retval; - - auto printTB = traceback_module.ResolveName<PythonCallable>("print_tb"); - if (!printTB.IsAllocated()) - return retval; - - auto printTB_result = - printTB(m_traceback.get(), Py_None, stringIO_buffer.get()); - auto stringIO_getvalue = - stringIO_buffer.ResolveName<PythonCallable>("getvalue"); - if (!stringIO_getvalue.IsAllocated()) - return retval; - - auto printTB_string = stringIO_getvalue().AsType<PythonString>(); - if (!printTB_string.IsAllocated()) - return retval; - - llvm::StringRef string_data(printTB_string.GetString()); - retval.assign(string_data.data(), string_data.size()); - - return retval; -} - -#endif diff --git a/source/Plugins/ScriptInterpreter/Python/PythonExceptionState.h b/source/Plugins/ScriptInterpreter/Python/PythonExceptionState.h deleted file mode 100644 index 3a88aa037776..000000000000 --- a/source/Plugins/ScriptInterpreter/Python/PythonExceptionState.h +++ /dev/null @@ -1,56 +0,0 @@ -//===-- PythonExceptionState.h ----------------------------------*- C++ -*-===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// - -#ifndef LLDB_PLUGINS_SCRIPTINTERPRETER_PYTHON_PYTHONEXCEPTIONSTATE_H -#define LLDB_PLUGINS_SCRIPTINTERPRETER_PYTHON_PYTHONEXCEPTIONSTATE_H - -#ifndef LLDB_DISABLE_PYTHON - -#include "PythonDataObjects.h" - -namespace lldb_private { - -class PythonExceptionState { -public: - explicit PythonExceptionState(bool restore_on_exit); - ~PythonExceptionState(); - - void Acquire(bool restore_on_exit); - - void Restore(); - - void Discard(); - - void Reset(); - - static bool HasErrorOccurred(); - - bool IsError() const; - - PythonObject GetType() const; - - PythonObject GetValue() const; - - PythonObject GetTraceback() const; - - std::string Format() const; - -private: - std::string ReadBacktrace() const; - - bool m_restore_on_exit; - - PythonObject m_type; - PythonObject m_value; - PythonObject m_traceback; -}; -} - -#endif - -#endif diff --git a/source/Plugins/ScriptInterpreter/Python/ScriptInterpreterPython.cpp b/source/Plugins/ScriptInterpreter/Python/ScriptInterpreterPython.cpp index 2d2b68ceaaa6..3eee52184142 100644 --- a/source/Plugins/ScriptInterpreter/Python/ScriptInterpreterPython.cpp +++ b/source/Plugins/ScriptInterpreter/Python/ScriptInterpreterPython.cpp @@ -16,7 +16,6 @@ #include "lldb-python.h" #include "PythonDataObjects.h" -#include "PythonExceptionState.h" #include "ScriptInterpreterPythonImpl.h" #include "lldb/API/SBFrame.h" @@ -45,6 +44,7 @@ #include "llvm/ADT/STLExtras.h" #include "llvm/ADT/StringRef.h" #include "llvm/Support/FileSystem.h" +#include "llvm/Support/FormatAdapters.h" #include <memory> #include <mutex> @@ -54,6 +54,8 @@ using namespace lldb; using namespace lldb_private; +using namespace lldb_private::python; +using llvm::Expected; // Defined in the SWIG source file #if PY_MAJOR_VERSION >= 3 @@ -96,6 +98,8 @@ LLDBSwigPythonCreateCommandObject(const char *python_class_name, extern "C" void *LLDBSwigPythonCreateScriptedThreadPlan( const char *python_class_name, const char *session_dictionary_name, + StructuredDataImpl *args_data, + std::string &error_string, const lldb::ThreadPlanSP &thread_plan_sp); extern "C" bool LLDBSWIGPythonCallThreadPlan(void *implementor, @@ -302,39 +306,26 @@ void ScriptInterpreterPython::ComputePythonDirForApple( auto rend = llvm::sys::path::rend(path_ref); auto framework = std::find(rbegin, rend, "LLDB.framework"); if (framework == rend) { - ComputePythonDirForPosix(path); + ComputePythonDir(path); return; } path.resize(framework - rend); llvm::sys::path::append(path, style, "LLDB.framework", "Resources", "Python"); } -void ScriptInterpreterPython::ComputePythonDirForPosix( +void ScriptInterpreterPython::ComputePythonDir( llvm::SmallVectorImpl<char> &path) { - auto style = llvm::sys::path::Style::posix; -#if defined(LLDB_PYTHON_RELATIVE_LIBDIR) // Build the path by backing out of the lib dir, then building with whatever // the real python interpreter uses. (e.g. lib for most, lib64 on RHEL - // x86_64). - llvm::sys::path::remove_filename(path, style); - llvm::sys::path::append(path, style, LLDB_PYTHON_RELATIVE_LIBDIR); -#else - llvm::sys::path::append(path, style, - "python" + llvm::Twine(PY_MAJOR_VERSION) + "." + - llvm::Twine(PY_MINOR_VERSION), - "site-packages"); -#endif -} - -void ScriptInterpreterPython::ComputePythonDirForWindows( - llvm::SmallVectorImpl<char> &path) { - auto style = llvm::sys::path::Style::windows; - llvm::sys::path::remove_filename(path, style); - llvm::sys::path::append(path, style, "lib", "site-packages"); + // x86_64, or bin on Windows). + llvm::sys::path::remove_filename(path); + llvm::sys::path::append(path, LLDB_PYTHON_RELATIVE_LIBDIR); +#if defined(_WIN32) // This will be injected directly through FileSpec.GetDirectory().SetString(), // so we need to normalize manually. std::replace(path.begin(), path.end(), '\\', '/'); +#endif } FileSpec ScriptInterpreterPython::GetPythonDir() { @@ -347,10 +338,8 @@ FileSpec ScriptInterpreterPython::GetPythonDir() { #if defined(__APPLE__) ComputePythonDirForApple(path); -#elif defined(_WIN32) - ComputePythonDirForWindows(path); #else - ComputePythonDirForPosix(path); + ComputePythonDir(path); #endif spec.GetDirectory().SetString(path); return spec; @@ -382,7 +371,7 @@ void ScriptInterpreterPython::Terminate() {} ScriptInterpreterPythonImpl::Locker::Locker( ScriptInterpreterPythonImpl *py_interpreter, uint16_t on_entry, - uint16_t on_leave, FILE *in, FILE *out, FILE *err) + uint16_t on_leave, FileSP in, FileSP out, FileSP err) : ScriptInterpreterLocker(), m_teardown_session((on_leave & TearDownSession) == TearDownSession), m_python_interpreter(py_interpreter) { @@ -412,8 +401,8 @@ bool ScriptInterpreterPythonImpl::Locker::DoAcquireLock() { } bool ScriptInterpreterPythonImpl::Locker::DoInitSession(uint16_t on_entry_flags, - FILE *in, FILE *out, - FILE *err) { + FileSP in, FileSP out, + FileSP err) { if (!m_python_interpreter) return false; return m_python_interpreter->EnterSession(on_entry_flags, in, out, err); @@ -448,9 +437,9 @@ ScriptInterpreterPythonImpl::ScriptInterpreterPythonImpl(Debugger &debugger) m_sys_module_dict(PyInitialValue::Invalid), m_run_one_line_function(), m_run_one_line_str_global(), m_dictionary_name(m_debugger.GetInstanceName().AsCString()), - m_terminal_state(), m_active_io_handler(eIOHandlerNone), - m_session_is_active(false), m_pty_slave_is_open(false), - m_valid_session(true), m_lock_count(0), m_command_thread_state(nullptr) { + m_active_io_handler(eIOHandlerNone), m_session_is_active(false), + m_pty_slave_is_open(false), m_valid_session(true), m_lock_count(0), + m_command_thread_state(nullptr) { InitializePrivate(); m_dictionary_name.append("_dict"); @@ -535,7 +524,7 @@ def function (frame, bp_loc, internal_dict): } if (instructions) { - StreamFileSP output_sp(io_handler.GetOutputStreamFile()); + StreamFileSP output_sp(io_handler.GetOutputStreamFileSP()); if (output_sp && interactive) { output_sp->PutCString(instructions); output_sp->Flush(); @@ -558,7 +547,7 @@ void ScriptInterpreterPythonImpl::IOHandlerInputComplete(IOHandler &io_handler, if (!bp_options) continue; - auto data_up = llvm::make_unique<CommandDataPython>(); + auto data_up = std::make_unique<CommandDataPython>(); if (!data_up) break; data_up->user_source.SplitIntoLines(data); @@ -571,7 +560,7 @@ void ScriptInterpreterPythonImpl::IOHandlerInputComplete(IOHandler &io_handler, bp_options->SetCallback( ScriptInterpreterPythonImpl::BreakpointCallbackFunction, baton_sp); } else if (!batch_mode) { - StreamFileSP error_sp = io_handler.GetErrorStreamFile(); + StreamFileSP error_sp = io_handler.GetErrorStreamFileSP(); if (error_sp) { error_sp->Printf("Warning: No command attached to breakpoint.\n"); error_sp->Flush(); @@ -583,7 +572,7 @@ void ScriptInterpreterPythonImpl::IOHandlerInputComplete(IOHandler &io_handler, case eIOHandlerWatchpoint: { WatchpointOptions *wp_options = (WatchpointOptions *)io_handler.GetUserData(); - auto data_up = llvm::make_unique<WatchpointOptions::CommandData>(); + auto data_up = std::make_unique<WatchpointOptions::CommandData>(); data_up->user_source.SplitIntoLines(data); if (GenerateWatchpointCommandCallbackData(data_up->user_source, @@ -593,7 +582,7 @@ void ScriptInterpreterPythonImpl::IOHandlerInputComplete(IOHandler &io_handler, wp_options->SetCallback( ScriptInterpreterPythonImpl::WatchpointCallbackFunction, baton_sp); } else if (!batch_mode) { - StreamFileSP error_sp = io_handler.GetErrorStreamFile(); + StreamFileSP error_sp = io_handler.GetErrorStreamFileSP(); if (error_sp) { error_sp->Printf("Warning: No command attached to breakpoint.\n"); error_sp->Flush(); @@ -609,29 +598,15 @@ ScriptInterpreterPythonImpl::CreateInstance(Debugger &debugger) { return std::make_shared<ScriptInterpreterPythonImpl>(debugger); } -void ScriptInterpreterPythonImpl::ResetOutputFileHandle(FILE *fh) {} - -void ScriptInterpreterPythonImpl::SaveTerminalState(int fd) { - // Python mucks with the terminal state of STDIN. If we can possibly avoid - // this by setting the file handles up correctly prior to entering the - // interpreter we should. For now we save and restore the terminal state on - // the input file handle. - m_terminal_state.Save(fd, false); -} - -void ScriptInterpreterPythonImpl::RestoreTerminalState() { - // Python mucks with the terminal state of STDIN. If we can possibly avoid - // this by setting the file handles up correctly prior to entering the - // interpreter we should. For now we save and restore the terminal state on - // the input file handle. - m_terminal_state.Restore(); -} - void ScriptInterpreterPythonImpl::LeaveSession() { Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_SCRIPT)); if (log) log->PutCString("ScriptInterpreterPythonImpl::LeaveSession()"); + // Unset the LLDB global variables. + PyRun_SimpleString("lldb.debugger = None; lldb.target = None; lldb.process " + "= None; lldb.thread = None; lldb.frame = None"); + // checking that we have a valid thread state - since we use our own // threading and locking in some (rare) cases during cleanup Python may end // up believing we have no thread state and PyImport_AddModule will crash if @@ -662,45 +637,52 @@ void ScriptInterpreterPythonImpl::LeaveSession() { m_session_is_active = false; } -bool ScriptInterpreterPythonImpl::SetStdHandle(File &file, const char *py_name, - PythonFile &save_file, +bool ScriptInterpreterPythonImpl::SetStdHandle(FileSP file_sp, + const char *py_name, + PythonObject &save_file, const char *mode) { - if (file.IsValid()) { - // Flush the file before giving it to python to avoid interleaved output. - file.Flush(); + if (!file_sp || !*file_sp) { + save_file.Reset(); + return false; + } + File &file = *file_sp; - PythonDictionary &sys_module_dict = GetSysModuleDictionary(); + // Flush the file before giving it to python to avoid interleaved output. + file.Flush(); - save_file = sys_module_dict.GetItemForKey(PythonString(py_name)) - .AsType<PythonFile>(); + PythonDictionary &sys_module_dict = GetSysModuleDictionary(); - PythonFile new_file(file, mode); - sys_module_dict.SetItemForKey(PythonString(py_name), new_file); - return true; - } else - save_file.Reset(); - return false; + auto new_file = PythonFile::FromFile(file, mode); + if (!new_file) { + llvm::consumeError(new_file.takeError()); + return false; + } + + save_file = sys_module_dict.GetItemForKey(PythonString(py_name)); + + sys_module_dict.SetItemForKey(PythonString(py_name), new_file.get()); + return true; } bool ScriptInterpreterPythonImpl::EnterSession(uint16_t on_entry_flags, - FILE *in, FILE *out, FILE *err) { + FileSP in_sp, FileSP out_sp, + FileSP err_sp) { // If we have already entered the session, without having officially 'left' // it, then there is no need to 'enter' it again. Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_SCRIPT)); if (m_session_is_active) { - if (log) - log->Printf( - "ScriptInterpreterPythonImpl::EnterSession(on_entry_flags=0x%" PRIx16 - ") session is already active, returning without doing anything", - on_entry_flags); + LLDB_LOGF( + log, + "ScriptInterpreterPythonImpl::EnterSession(on_entry_flags=0x%" PRIx16 + ") session is already active, returning without doing anything", + on_entry_flags); return false; } - if (log) - log->Printf( - "ScriptInterpreterPythonImpl::EnterSession(on_entry_flags=0x%" PRIx16 - ")", - on_entry_flags); + LLDB_LOGF( + log, + "ScriptInterpreterPythonImpl::EnterSession(on_entry_flags=0x%" PRIx16 ")", + on_entry_flags); m_session_is_active = true; @@ -733,33 +715,29 @@ bool ScriptInterpreterPythonImpl::EnterSession(uint16_t on_entry_flags, PythonDictionary &sys_module_dict = GetSysModuleDictionary(); if (sys_module_dict.IsValid()) { - File in_file(in, false); - File out_file(out, false); - File err_file(err, false); - - lldb::StreamFileSP in_sp; - lldb::StreamFileSP out_sp; - lldb::StreamFileSP err_sp; - if (!in_file.IsValid() || !out_file.IsValid() || !err_file.IsValid()) - m_debugger.AdoptTopIOHandlerFilesIfInvalid(in_sp, out_sp, err_sp); + lldb::FileSP top_in_sp; + lldb::StreamFileSP top_out_sp, top_err_sp; + if (!in_sp || !out_sp || !err_sp || !*in_sp || !*out_sp || !*err_sp) + m_debugger.AdoptTopIOHandlerFilesIfInvalid(top_in_sp, top_out_sp, + top_err_sp); if (on_entry_flags & Locker::NoSTDIN) { m_saved_stdin.Reset(); } else { - if (!SetStdHandle(in_file, "stdin", m_saved_stdin, "r")) { - if (in_sp) - SetStdHandle(in_sp->GetFile(), "stdin", m_saved_stdin, "r"); + if (!SetStdHandle(in_sp, "stdin", m_saved_stdin, "r")) { + if (top_in_sp) + SetStdHandle(top_in_sp, "stdin", m_saved_stdin, "r"); } } - if (!SetStdHandle(out_file, "stdout", m_saved_stdout, "w")) { - if (out_sp) - SetStdHandle(out_sp->GetFile(), "stdout", m_saved_stdout, "w"); + if (!SetStdHandle(out_sp, "stdout", m_saved_stdout, "w")) { + if (top_out_sp) + SetStdHandle(top_out_sp->GetFileSP(), "stdout", m_saved_stdout, "w"); } - if (!SetStdHandle(err_file, "stderr", m_saved_stderr, "w")) { - if (err_sp) - SetStdHandle(err_sp->GetFile(), "stderr", m_saved_stderr, "w"); + if (!SetStdHandle(err_sp, "stderr", m_saved_stderr, "w")) { + if (top_err_sp) + SetStdHandle(top_err_sp->GetFileSP(), "stderr", m_saved_stderr, "w"); } } @@ -769,9 +747,9 @@ bool ScriptInterpreterPythonImpl::EnterSession(uint16_t on_entry_flags, return true; } -PythonObject &ScriptInterpreterPythonImpl::GetMainModule() { +PythonModule &ScriptInterpreterPythonImpl::GetMainModule() { if (!m_main_module.IsValid()) - m_main_module.Reset(PyRefType::Borrowed, PyImport_AddModule("__main__")); + m_main_module = unwrapIgnoringErrors(PythonModule::Import("__main__")); return m_main_module; } @@ -788,19 +766,16 @@ PythonDictionary &ScriptInterpreterPythonImpl::GetSessionDictionary() { if (!main_dict.IsValid()) return m_session_dict; - PythonObject item = main_dict.GetItemForKey(PythonString(m_dictionary_name)); - m_session_dict.Reset(PyRefType::Borrowed, item.get()); + m_session_dict = unwrapIgnoringErrors( + As<PythonDictionary>(main_dict.GetItem(m_dictionary_name))); return m_session_dict; } PythonDictionary &ScriptInterpreterPythonImpl::GetSysModuleDictionary() { if (m_sys_module_dict.IsValid()) return m_sys_module_dict; - - PythonObject sys_module(PyRefType::Borrowed, PyImport_AddModule("sys")); - if (sys_module.IsValid()) - m_sys_module_dict.Reset(PyRefType::Borrowed, - PyModule_GetDict(sys_module.get())); + PythonModule sys_module = unwrapIgnoringErrors(PythonModule::Import("sys")); + m_sys_module_dict = sys_module.GetDictionary(); return m_sys_module_dict; } @@ -867,7 +842,7 @@ bool ScriptInterpreterPythonImpl::ExecuteOneLine( // directly down to Python. Debugger &debugger = m_debugger; - StreamFileSP input_file_sp; + FileSP input_file_sp; StreamFileSP output_file_sp; StreamFileSP error_file_sp; Communication output_comm( @@ -875,7 +850,7 @@ bool ScriptInterpreterPythonImpl::ExecuteOneLine( bool join_read_thread = false; if (options.GetEnableIO()) { if (result) { - input_file_sp = debugger.GetInputFile(); + input_file_sp = debugger.GetInputFileSP(); // Set output to a temporary file so we can forward the results on to // the result object @@ -906,9 +881,9 @@ bool ScriptInterpreterPythonImpl::ExecuteOneLine( ::setbuf(outfile_handle, nullptr); result->SetImmediateOutputFile( - debugger.GetOutputFile()->GetFile().GetStream()); + debugger.GetOutputStream().GetFileSP()); result->SetImmediateErrorFile( - debugger.GetErrorFile()->GetFile().GetStream()); + debugger.GetErrorStream().GetFileSP()); } } } @@ -916,22 +891,26 @@ bool ScriptInterpreterPythonImpl::ExecuteOneLine( debugger.AdoptTopIOHandlerFilesIfInvalid(input_file_sp, output_file_sp, error_file_sp); } else { - input_file_sp = std::make_shared<StreamFile>(); - FileSystem::Instance().Open(input_file_sp->GetFile(), + auto nullin = FileSystem::Instance().Open( FileSpec(FileSystem::DEV_NULL), File::eOpenOptionRead); - - output_file_sp = std::make_shared<StreamFile>(); - FileSystem::Instance().Open(output_file_sp->GetFile(), + auto nullout = FileSystem::Instance().Open( FileSpec(FileSystem::DEV_NULL), File::eOpenOptionWrite); - - error_file_sp = output_file_sp; + if (!nullin) { + result->AppendErrorWithFormatv("failed to open /dev/null: {0}\n", + llvm::fmt_consume(nullin.takeError())); + return false; + } + if (!nullout) { + result->AppendErrorWithFormatv("failed to open /dev/null: {0}\n", + llvm::fmt_consume(nullout.takeError())); + return false; + } + input_file_sp = std::move(nullin.get()); + error_file_sp = output_file_sp = std::make_shared<StreamFile>(std::move(nullout.get())); } - FILE *in_file = input_file_sp->GetFile().GetStream(); - FILE *out_file = output_file_sp->GetFile().GetStream(); - FILE *err_file = error_file_sp->GetFile().GetStream(); bool success = false; { // WARNING! It's imperative that this RAII scope be as tight as @@ -947,8 +926,8 @@ bool ScriptInterpreterPythonImpl::ExecuteOneLine( Locker::AcquireLock | Locker::InitSession | (options.GetSetLLDBGlobals() ? Locker::InitGlobals : 0) | ((result && result->GetInteractive()) ? 0 : Locker::NoSTDIN), - Locker::FreeAcquiredLock | Locker::TearDownSession, in_file, out_file, - err_file); + Locker::FreeAcquiredLock | Locker::TearDownSession, input_file_sp, + output_file_sp->GetFileSP(), error_file_sp->GetFileSP()); // Find the correct script interpreter dictionary in the main module. PythonDictionary &session_dict = GetSessionDictionary(); @@ -975,9 +954,8 @@ bool ScriptInterpreterPythonImpl::ExecuteOneLine( } // Flush our output and error file handles - ::fflush(out_file); - if (out_file != err_file) - ::fflush(err_file); + output_file_sp->Flush(); + error_file_sp->Flush(); } if (join_read_thread) { @@ -1020,7 +998,7 @@ void ScriptInterpreterPythonImpl::ExecuteInterpreterLoop() { // a running interpreter loop inside the already running Python interpreter // loop, so we won't do it. - if (!debugger.GetInputFile()->GetFile().IsValid()) + if (!debugger.GetInputFile().IsValid()) return; IOHandlerSP io_handler_sp(new IOHandlerPythonInterpreter(debugger, this)); @@ -1040,19 +1018,19 @@ bool ScriptInterpreterPythonImpl::Interrupt() { long tid = state->thread_id; PyThreadState_Swap(state); int num_threads = PyThreadState_SetAsyncExc(tid, PyExc_KeyboardInterrupt); - if (log) - log->Printf("ScriptInterpreterPythonImpl::Interrupt() sending " - "PyExc_KeyboardInterrupt (tid = %li, num_threads = %i)...", - tid, num_threads); + LLDB_LOGF(log, + "ScriptInterpreterPythonImpl::Interrupt() sending " + "PyExc_KeyboardInterrupt (tid = %li, num_threads = %i)...", + tid, num_threads); return true; } } - if (log) - log->Printf( - "ScriptInterpreterPythonImpl::Interrupt() python code not running, " - "can't interrupt"); + LLDB_LOGF(log, + "ScriptInterpreterPythonImpl::Interrupt() python code not running, " + "can't interrupt"); return false; } + bool ScriptInterpreterPythonImpl::ExecuteOneLineWithReturn( llvm::StringRef in_string, ScriptInterpreter::ScriptReturnType return_type, void *ret_value, const ExecuteScriptOptions &options) { @@ -1063,152 +1041,111 @@ bool ScriptInterpreterPythonImpl::ExecuteOneLineWithReturn( Locker::NoSTDIN, Locker::FreeAcquiredLock | Locker::TearDownSession); - PythonObject py_return; - PythonObject &main_module = GetMainModule(); - PythonDictionary globals(PyRefType::Borrowed, - PyModule_GetDict(main_module.get())); - PythonObject py_error; - bool ret_success = false; - int success; + PythonModule &main_module = GetMainModule(); + PythonDictionary globals = main_module.GetDictionary(); PythonDictionary locals = GetSessionDictionary(); - - if (!locals.IsValid()) { - locals.Reset( - PyRefType::Owned, - PyObject_GetAttrString(globals.get(), m_dictionary_name.c_str())); - } - + if (!locals.IsValid()) + locals = unwrapIgnoringErrors( + As<PythonDictionary>(globals.GetAttribute(m_dictionary_name))); if (!locals.IsValid()) locals = globals; - py_error.Reset(PyRefType::Borrowed, PyErr_Occurred()); - if (py_error.IsValid()) - PyErr_Clear(); - - std::string as_string = in_string.str(); - { // scope for PythonInputReaderManager - // PythonInputReaderManager py_input(options.GetEnableIO() ? this : NULL); - py_return.Reset(PyRefType::Owned, - PyRun_String(as_string.c_str(), Py_eval_input, - globals.get(), locals.get())); - if (!py_return.IsValid()) { - py_error.Reset(PyRefType::Borrowed, PyErr_Occurred()); - if (py_error.IsValid()) - PyErr_Clear(); - - py_return.Reset(PyRefType::Owned, - PyRun_String(as_string.c_str(), Py_single_input, - globals.get(), locals.get())); - } + Expected<PythonObject> maybe_py_return = + runStringOneLine(in_string, globals, locals); + + if (!maybe_py_return) { + llvm::handleAllErrors( + maybe_py_return.takeError(), + [&](PythonException &E) { + E.Restore(); + if (options.GetMaskoutErrors()) { + if (E.Matches(PyExc_SyntaxError)) { + PyErr_Print(); + } + PyErr_Clear(); + } + }, + [](const llvm::ErrorInfoBase &E) {}); + return false; } - if (py_return.IsValid()) { - switch (return_type) { - case eScriptReturnTypeCharPtr: // "char *" - { - const char format[3] = "s#"; - success = PyArg_Parse(py_return.get(), format, (char **)ret_value); - break; - } - case eScriptReturnTypeCharStrOrNone: // char* or NULL if py_return == - // Py_None - { - const char format[3] = "z"; - success = PyArg_Parse(py_return.get(), format, (char **)ret_value); - break; - } - case eScriptReturnTypeBool: { - const char format[2] = "b"; - success = PyArg_Parse(py_return.get(), format, (bool *)ret_value); - break; - } - case eScriptReturnTypeShortInt: { - const char format[2] = "h"; - success = PyArg_Parse(py_return.get(), format, (short *)ret_value); - break; - } - case eScriptReturnTypeShortIntUnsigned: { - const char format[2] = "H"; - success = - PyArg_Parse(py_return.get(), format, (unsigned short *)ret_value); - break; - } - case eScriptReturnTypeInt: { - const char format[2] = "i"; - success = PyArg_Parse(py_return.get(), format, (int *)ret_value); - break; - } - case eScriptReturnTypeIntUnsigned: { - const char format[2] = "I"; - success = PyArg_Parse(py_return.get(), format, (unsigned int *)ret_value); - break; - } - case eScriptReturnTypeLongInt: { - const char format[2] = "l"; - success = PyArg_Parse(py_return.get(), format, (long *)ret_value); - break; - } - case eScriptReturnTypeLongIntUnsigned: { - const char format[2] = "k"; - success = - PyArg_Parse(py_return.get(), format, (unsigned long *)ret_value); - break; - } - case eScriptReturnTypeLongLong: { - const char format[2] = "L"; - success = PyArg_Parse(py_return.get(), format, (long long *)ret_value); - break; - } - case eScriptReturnTypeLongLongUnsigned: { - const char format[2] = "K"; - success = - PyArg_Parse(py_return.get(), format, (unsigned long long *)ret_value); - break; - } - case eScriptReturnTypeFloat: { - const char format[2] = "f"; - success = PyArg_Parse(py_return.get(), format, (float *)ret_value); - break; - } - case eScriptReturnTypeDouble: { - const char format[2] = "d"; - success = PyArg_Parse(py_return.get(), format, (double *)ret_value); - break; - } - case eScriptReturnTypeChar: { - const char format[2] = "c"; - success = PyArg_Parse(py_return.get(), format, (char *)ret_value); - break; - } - case eScriptReturnTypeOpaqueObject: { - success = true; - PyObject *saved_value = py_return.get(); - Py_XINCREF(saved_value); - *((PyObject **)ret_value) = saved_value; - break; - } - } + PythonObject py_return = std::move(maybe_py_return.get()); + assert(py_return.IsValid()); - ret_success = success; + switch (return_type) { + case eScriptReturnTypeCharPtr: // "char *" + { + const char format[3] = "s#"; + return PyArg_Parse(py_return.get(), format, (char **)ret_value); + } + case eScriptReturnTypeCharStrOrNone: // char* or NULL if py_return == + // Py_None + { + const char format[3] = "z"; + return PyArg_Parse(py_return.get(), format, (char **)ret_value); + } + case eScriptReturnTypeBool: { + const char format[2] = "b"; + return PyArg_Parse(py_return.get(), format, (bool *)ret_value); + } + case eScriptReturnTypeShortInt: { + const char format[2] = "h"; + return PyArg_Parse(py_return.get(), format, (short *)ret_value); + } + case eScriptReturnTypeShortIntUnsigned: { + const char format[2] = "H"; + return PyArg_Parse(py_return.get(), format, (unsigned short *)ret_value); + } + case eScriptReturnTypeInt: { + const char format[2] = "i"; + return PyArg_Parse(py_return.get(), format, (int *)ret_value); + } + case eScriptReturnTypeIntUnsigned: { + const char format[2] = "I"; + return PyArg_Parse(py_return.get(), format, (unsigned int *)ret_value); + } + case eScriptReturnTypeLongInt: { + const char format[2] = "l"; + return PyArg_Parse(py_return.get(), format, (long *)ret_value); + } + case eScriptReturnTypeLongIntUnsigned: { + const char format[2] = "k"; + return PyArg_Parse(py_return.get(), format, (unsigned long *)ret_value); + } + case eScriptReturnTypeLongLong: { + const char format[2] = "L"; + return PyArg_Parse(py_return.get(), format, (long long *)ret_value); + } + case eScriptReturnTypeLongLongUnsigned: { + const char format[2] = "K"; + return PyArg_Parse(py_return.get(), format, + (unsigned long long *)ret_value); + } + case eScriptReturnTypeFloat: { + const char format[2] = "f"; + return PyArg_Parse(py_return.get(), format, (float *)ret_value); + } + case eScriptReturnTypeDouble: { + const char format[2] = "d"; + return PyArg_Parse(py_return.get(), format, (double *)ret_value); + } + case eScriptReturnTypeChar: { + const char format[2] = "c"; + return PyArg_Parse(py_return.get(), format, (char *)ret_value); + } + case eScriptReturnTypeOpaqueObject: { + *((PyObject **)ret_value) = py_return.release(); + return true; } - - py_error.Reset(PyRefType::Borrowed, PyErr_Occurred()); - if (py_error.IsValid()) { - ret_success = false; - if (options.GetMaskoutErrors()) { - if (PyErr_GivenExceptionMatches(py_error.get(), PyExc_SyntaxError)) - PyErr_Print(); - PyErr_Clear(); - } } - - return ret_success; } Status ScriptInterpreterPythonImpl::ExecuteMultipleLines( const char *in_string, const ExecuteScriptOptions &options) { - Status error; + + if (in_string == nullptr) + return Status(); Locker locker(this, Locker::AcquireLock | Locker::InitSession | @@ -1216,52 +1153,32 @@ Status ScriptInterpreterPythonImpl::ExecuteMultipleLines( Locker::NoSTDIN, Locker::FreeAcquiredLock | Locker::TearDownSession); - PythonObject return_value; - PythonObject &main_module = GetMainModule(); - PythonDictionary globals(PyRefType::Borrowed, - PyModule_GetDict(main_module.get())); - PythonObject py_error; + PythonModule &main_module = GetMainModule(); + PythonDictionary globals = main_module.GetDictionary(); PythonDictionary locals = GetSessionDictionary(); - if (!locals.IsValid()) - locals.Reset( - PyRefType::Owned, - PyObject_GetAttrString(globals.get(), m_dictionary_name.c_str())); - + locals = unwrapIgnoringErrors( + As<PythonDictionary>(globals.GetAttribute(m_dictionary_name))); if (!locals.IsValid()) locals = globals; - py_error.Reset(PyRefType::Borrowed, PyErr_Occurred()); - if (py_error.IsValid()) - PyErr_Clear(); + Expected<PythonObject> return_value = + runStringMultiLine(in_string, globals, locals); - if (in_string != nullptr) { - PythonObject code_object; - code_object.Reset(PyRefType::Owned, - Py_CompileString(in_string, "temp.py", Py_file_input)); - - if (code_object.IsValid()) { -// In Python 2.x, PyEval_EvalCode takes a PyCodeObject, but in Python 3.x, it -// takes a PyObject. They are convertible (hence the function -// PyCode_Check(PyObject*), so we have to do the cast for Python 2.x -#if PY_MAJOR_VERSION >= 3 - PyObject *py_code_obj = code_object.get(); -#else - PyCodeObject *py_code_obj = - reinterpret_cast<PyCodeObject *>(code_object.get()); -#endif - return_value.Reset( - PyRefType::Owned, - PyEval_EvalCode(py_code_obj, globals.get(), locals.get())); - } + if (!return_value) { + llvm::Error error = + llvm::handleErrors(return_value.takeError(), [&](PythonException &E) { + llvm::Error error = llvm::createStringError( + llvm::inconvertibleErrorCode(), E.ReadBacktrace()); + if (!options.GetMaskoutErrors()) + E.Restore(); + return error; + }); + return Status(std::move(error)); } - PythonExceptionState exception_state(!options.GetMaskoutErrors()); - if (exception_state.IsError()) - error.SetErrorString(exception_state.Format().c_str()); - - return error; + return Status(); } void ScriptInterpreterPythonImpl::CollectDataForBreakpointCommandCallback( @@ -1308,7 +1225,7 @@ Status ScriptInterpreterPythonImpl::SetBreakpointCommandCallback( // Set a Python one-liner as the callback for the breakpoint. Status ScriptInterpreterPythonImpl::SetBreakpointCommandCallback( BreakpointOptions *bp_options, const char *command_body_text) { - auto data_up = llvm::make_unique<CommandDataPython>(); + auto data_up = std::make_unique<CommandDataPython>(); // Split the command_body_text into lines, and pass that to // GenerateBreakpointCommandCallbackData. That will wrap the body in an @@ -1331,7 +1248,7 @@ Status ScriptInterpreterPythonImpl::SetBreakpointCommandCallback( // Set a Python one-liner as the callback for the watchpoint. void ScriptInterpreterPythonImpl::SetWatchpointCommandCallback( WatchpointOptions *wp_options, const char *oneliner) { - auto data_up = llvm::make_unique<WatchpointOptions::CommandData>(); + auto data_up = std::make_unique<WatchpointOptions::CommandData>(); // It's necessary to set both user_source and script_source to the oneliner. // The former is used to generate callback description (as in watchpoint @@ -1853,12 +1770,14 @@ StructuredData::DictionarySP ScriptInterpreterPythonImpl::OSPlugin_CreateThread( } StructuredData::ObjectSP ScriptInterpreterPythonImpl::CreateScriptedThreadPlan( - const char *class_name, lldb::ThreadPlanSP thread_plan_sp) { + const char *class_name, StructuredDataImpl *args_data, + std::string &error_str, + lldb::ThreadPlanSP thread_plan_sp) { if (class_name == nullptr || class_name[0] == '\0') return StructuredData::ObjectSP(); if (!thread_plan_sp.get()) - return StructuredData::ObjectSP(); + return {}; Debugger &debugger = thread_plan_sp->GetTarget().GetDebugger(); ScriptInterpreter *script_interpreter = debugger.GetScriptInterpreter(); @@ -1866,17 +1785,18 @@ StructuredData::ObjectSP ScriptInterpreterPythonImpl::CreateScriptedThreadPlan( static_cast<ScriptInterpreterPythonImpl *>(script_interpreter); if (!script_interpreter) - return StructuredData::ObjectSP(); + return {}; void *ret_val; { Locker py_lock(this, Locker::AcquireLock | Locker::InitSession | Locker::NoSTDIN); - ret_val = LLDBSwigPythonCreateScriptedThreadPlan( class_name, python_interpreter->m_dictionary_name.c_str(), - thread_plan_sp); + args_data, error_str, thread_plan_sp); + if (!ret_val) + return {}; } return StructuredData::ObjectSP(new StructuredPythonObject(ret_val)); @@ -2052,15 +1972,22 @@ StructuredData::DictionarySP ScriptInterpreterPythonImpl::GetDynamicSettings( if (!generic) return StructuredData::DictionarySP(); - PythonObject reply_pyobj; Locker py_lock(this, Locker::AcquireLock | Locker::InitSession | Locker::NoSTDIN); TargetSP target_sp(target->shared_from_this()); - reply_pyobj.Reset(PyRefType::Owned, - (PyObject *)LLDBSWIGPython_GetDynamicSetting( - generic->GetValue(), setting_name, target_sp)); - PythonDictionary py_dict(PyRefType::Borrowed, reply_pyobj.get()); + auto setting = (PyObject *)LLDBSWIGPython_GetDynamicSetting( + generic->GetValue(), setting_name, target_sp); + + if (!setting) + return StructuredData::DictionarySP(); + + PythonDictionary py_dict = + unwrapIgnoringErrors(As<PythonDictionary>(Take<PythonObject>(setting))); + + if (!py_dict) + return StructuredData::DictionarySP(); + return py_dict.CreateStructuredDictionary(); } @@ -2230,18 +2157,6 @@ bool ScriptInterpreterPythonImpl::GetScriptedSummary( return ret_val; } -void ScriptInterpreterPythonImpl::Clear() { - // Release any global variables that might have strong references to - // LLDB objects when clearing the python script interpreter. - Locker locker(this, Locker::AcquireLock, Locker::FreeAcquiredLock); - - // This may be called as part of Py_Finalize. In that case the modules are - // destroyed in random order and we can't guarantee that we can access these. - if (Py_IsInitialized()) - PyRun_SimpleString("lldb.debugger = None; lldb.target = None; lldb.process " - "= None; lldb.thread = None; lldb.frame = None"); -} - bool ScriptInterpreterPythonImpl::BreakpointCallbackFunction( void *baton, StoppointCallbackContext *context, user_id_t break_id, user_id_t break_loc_id) { diff --git a/source/Plugins/ScriptInterpreter/Python/ScriptInterpreterPython.h b/source/Plugins/ScriptInterpreter/Python/ScriptInterpreterPython.h index 24941ec77452..33ae308041b2 100644 --- a/source/Plugins/ScriptInterpreter/Python/ScriptInterpreterPython.h +++ b/source/Plugins/ScriptInterpreter/Python/ScriptInterpreterPython.h @@ -48,8 +48,7 @@ public: protected: static void ComputePythonDirForApple(llvm::SmallVectorImpl<char> &path); - static void ComputePythonDirForPosix(llvm::SmallVectorImpl<char> &path); - static void ComputePythonDirForWindows(llvm::SmallVectorImpl<char> &path); + static void ComputePythonDir(llvm::SmallVectorImpl<char> &path); }; } // namespace lldb_private diff --git a/source/Plugins/ScriptInterpreter/Python/ScriptInterpreterPythonImpl.h b/source/Plugins/ScriptInterpreter/Python/ScriptInterpreterPythonImpl.h index a9993c4068a2..929567e579d8 100644 --- a/source/Plugins/ScriptInterpreter/Python/ScriptInterpreterPythonImpl.h +++ b/source/Plugins/ScriptInterpreter/Python/ScriptInterpreterPythonImpl.h @@ -78,6 +78,8 @@ public: StructuredData::ObjectSP CreateScriptedThreadPlan(const char *class_name, + StructuredDataImpl *args_data, + std::string &error_str, lldb::ThreadPlanSP thread_plan) override; bool ScriptedThreadPlanExplainsStop(StructuredData::ObjectSP implementor_sp, @@ -188,8 +190,6 @@ public: const TypeSummaryOptions &options, std::string &retval) override; - void Clear() override; - bool GetDocumentationForItem(const char *item, std::string &dest) override; bool GetShortHelpForCommandObject(StructuredData::GenericSP cmd_obj_sp, @@ -256,8 +256,6 @@ public: void SetWatchpointCommandCallback(WatchpointOptions *wp_options, const char *oneliner) override; - void ResetOutputFileHandle(FILE *new_fh) override; - const char *GetDictionaryName() { return m_dictionary_name.c_str(); } PyThreadState *GetThreadState() { return m_command_thread_state; } @@ -296,17 +294,19 @@ public: TearDownSession = 0x0004 }; - Locker(ScriptInterpreterPythonImpl *py_interpreter = nullptr, + Locker(ScriptInterpreterPythonImpl *py_interpreter, uint16_t on_entry = AcquireLock | InitSession, - uint16_t on_leave = FreeLock | TearDownSession, FILE *in = nullptr, - FILE *out = nullptr, FILE *err = nullptr); + uint16_t on_leave = FreeLock | TearDownSession, + lldb::FileSP in = nullptr, lldb::FileSP out = nullptr, + lldb::FileSP err = nullptr); ~Locker() override; private: bool DoAcquireLock(); - bool DoInitSession(uint16_t on_entry_flags, FILE *in, FILE *out, FILE *err); + bool DoInitSession(uint16_t on_entry_flags, lldb::FileSP in, + lldb::FileSP out, lldb::FileSP err); bool DoFreeLock(); @@ -314,7 +314,6 @@ public: bool m_teardown_session; ScriptInterpreterPythonImpl *m_python_interpreter; - // FILE* m_tmp_fh; PyGILState_STATE m_GILState; }; @@ -343,14 +342,11 @@ public: static void AddToSysPath(AddLocation location, std::string path); - bool EnterSession(uint16_t on_entry_flags, FILE *in, FILE *out, FILE *err); + bool EnterSession(uint16_t on_entry_flags, lldb::FileSP in, lldb::FileSP out, + lldb::FileSP err); void LeaveSession(); - void SaveTerminalState(int fd); - - void RestoreTerminalState(); - uint32_t IsExecutingPython() const { return m_lock_count > 0; } uint32_t IncrementLockCount() { return ++m_lock_count; } @@ -367,27 +363,26 @@ public: eIOHandlerWatchpoint }; - PythonObject &GetMainModule(); + python::PythonModule &GetMainModule(); - PythonDictionary &GetSessionDictionary(); + python::PythonDictionary &GetSessionDictionary(); - PythonDictionary &GetSysModuleDictionary(); + python::PythonDictionary &GetSysModuleDictionary(); bool GetEmbeddedInterpreterModuleObjects(); - bool SetStdHandle(File &file, const char *py_name, PythonFile &save_file, - const char *mode); - - PythonFile m_saved_stdin; - PythonFile m_saved_stdout; - PythonFile m_saved_stderr; - PythonObject m_main_module; - PythonDictionary m_session_dict; - PythonDictionary m_sys_module_dict; - PythonObject m_run_one_line_function; - PythonObject m_run_one_line_str_global; + bool SetStdHandle(lldb::FileSP file, const char *py_name, + python::PythonObject &save_file, const char *mode); + + python::PythonObject m_saved_stdin; + python::PythonObject m_saved_stdout; + python::PythonObject m_saved_stderr; + python::PythonModule m_main_module; + python::PythonDictionary m_session_dict; + python::PythonDictionary m_sys_module_dict; + python::PythonObject m_run_one_line_function; + python::PythonObject m_run_one_line_str_global; std::string m_dictionary_name; - TerminalState m_terminal_state; ActiveIOHandler m_active_io_handler; bool m_session_is_active; bool m_pty_slave_is_open; diff --git a/source/Plugins/StructuredData/DarwinLog/StructuredDataDarwinLog.cpp b/source/Plugins/StructuredData/DarwinLog/StructuredDataDarwinLog.cpp index 81a27125c036..c6b234baa8c8 100644 --- a/source/Plugins/StructuredData/DarwinLog/StructuredDataDarwinLog.cpp +++ b/source/Plugins/StructuredData/DarwinLog/StructuredDataDarwinLog.cpp @@ -104,30 +104,13 @@ void SetGlobalEnableOptions(const DebuggerSP &debugger_sp, /// Code to handle the StructuredDataDarwinLog settings -static constexpr PropertyDefinition g_properties[] = { - { - "enable-on-startup", // name - OptionValue::eTypeBoolean, // type - true, // global - false, // default uint value - nullptr, // default cstring value - {}, // enum values - "Enable Darwin os_log collection when debugged process is launched " - "or attached." // description - }, - { - "auto-enable-options", // name - OptionValue::eTypeString, // type - true, // global - 0, // default uint value - "", // default cstring value - {}, // enum values - "Specify the options to 'plugin structured-data darwin-log enable' " - "that should be applied when automatically enabling logging on " - "startup/attach." // description - }}; - -enum { ePropertyEnableOnStartup = 0, ePropertyAutoEnableOptions = 1 }; +#define LLDB_PROPERTIES_darwinlog +#include "StructuredDataDarwinLogProperties.inc" + +enum { +#define LLDB_PROPERTIES_darwinlog +#include "StructuredDataDarwinLogPropertiesEnum.inc" +}; class StructuredDataDarwinLogProperties : public Properties { public: @@ -138,7 +121,7 @@ public: StructuredDataDarwinLogProperties() : Properties() { m_collection_sp = std::make_shared<OptionValueProperties>(GetSettingName()); - m_collection_sp->Initialize(g_properties); + m_collection_sp->Initialize(g_darwinlog_properties); } ~StructuredDataDarwinLogProperties() override {} @@ -146,13 +129,13 @@ public: bool GetEnableOnStartup() const { const uint32_t idx = ePropertyEnableOnStartup; return m_collection_sp->GetPropertyAtIndexAsBoolean( - nullptr, idx, g_properties[idx].default_uint_value != 0); + nullptr, idx, g_darwinlog_properties[idx].default_uint_value != 0); } llvm::StringRef GetAutoEnableOptions() const { const uint32_t idx = ePropertyAutoEnableOptions; return m_collection_sp->GetPropertyAtIndexAsString( - nullptr, idx, g_properties[idx].default_cstr_value); + nullptr, idx, g_darwinlog_properties[idx].default_cstr_value); } const char *GetLoggingModuleName() const { return "libsystem_trace.dylib"; } @@ -305,11 +288,8 @@ private: // Instantiate the regex so we can report any errors. auto regex = RegularExpression(op_arg); - if (!regex.IsValid()) { - char error_text[256]; - error_text[0] = '\0'; - regex.GetErrorAsCString(error_text, sizeof(error_text)); - error.SetErrorString(error_text); + if (llvm::Error err = regex.GetError()) { + error.SetErrorString(llvm::toString(std::move(err))); return FilterRuleSP(); } @@ -807,15 +787,10 @@ protected: // Now check if we have a running process. If so, we should instruct the // process monitor to enable/disable DarwinLog support now. - Target *target = GetSelectedOrDummyTarget(); - if (!target) { - // No target, so there is nothing more to do right now. - result.SetStatus(eReturnStatusSuccessFinishNoResult); - return true; - } + Target &target = GetSelectedOrDummyTarget(); // Grab the active process. - auto process_sp = target->GetProcessSP(); + auto process_sp = target.GetProcessSP(); if (!process_sp) { // No active process, so there is nothing more to do right now. result.SetStatus(eReturnStatusSuccessFinishNoResult); @@ -897,9 +872,9 @@ protected: // Figure out if we've got a process. If so, we can tell if DarwinLog is // available for that process. - Target *target = GetSelectedOrDummyTarget(); - auto process_sp = target ? target->GetProcessSP() : ProcessSP(); - if (!target || !process_sp) { + Target &target = GetSelectedOrDummyTarget(); + auto process_sp = target.GetProcessSP(); + if (!process_sp) { stream.PutCString("Availability: unknown (requires process)\n"); stream.PutCString("Enabled: not applicable " "(requires process)\n"); @@ -1119,26 +1094,26 @@ void StructuredDataDarwinLog::HandleArrivalOfStructuredData( object_sp->Dump(json_stream); else json_stream.PutCString("<null>"); - log->Printf("StructuredDataDarwinLog::%s() called with json: %s", - __FUNCTION__, json_stream.GetData()); + LLDB_LOGF(log, "StructuredDataDarwinLog::%s() called with json: %s", + __FUNCTION__, json_stream.GetData()); } // Ignore empty structured data. if (!object_sp) { - if (log) - log->Printf("StructuredDataDarwinLog::%s() StructuredData object " - "is null", - __FUNCTION__); + LLDB_LOGF(log, + "StructuredDataDarwinLog::%s() StructuredData object " + "is null", + __FUNCTION__); return; } // Ignore any data that isn't for us. if (type_name != GetDarwinLogTypeName()) { - if (log) - log->Printf("StructuredDataDarwinLog::%s() StructuredData type " - "expected to be %s but was %s, ignoring", - __FUNCTION__, GetDarwinLogTypeName().AsCString(), - type_name.AsCString()); + LLDB_LOGF(log, + "StructuredDataDarwinLog::%s() StructuredData type " + "expected to be %s but was %s, ignoring", + __FUNCTION__, GetDarwinLogTypeName().AsCString(), + type_name.AsCString()); return; } @@ -1148,9 +1123,8 @@ void StructuredDataDarwinLog::HandleArrivalOfStructuredData( DebuggerSP debugger_sp = process.GetTarget().GetDebugger().shared_from_this(); auto options_sp = GetGlobalEnableOptions(debugger_sp); if (options_sp && options_sp->GetBroadcastEvents()) { - if (log) - log->Printf("StructuredDataDarwinLog::%s() broadcasting event", - __FUNCTION__); + LLDB_LOGF(log, "StructuredDataDarwinLog::%s() broadcasting event", + __FUNCTION__); process.BroadcastStructuredData(object_sp, shared_from_this()); } @@ -1263,19 +1237,18 @@ void StructuredDataDarwinLog::SetEnabled(bool enabled) { void StructuredDataDarwinLog::ModulesDidLoad(Process &process, ModuleList &module_list) { Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_PROCESS)); - if (log) - log->Printf("StructuredDataDarwinLog::%s called (process uid %u)", - __FUNCTION__, process.GetUniqueID()); + LLDB_LOGF(log, "StructuredDataDarwinLog::%s called (process uid %u)", + __FUNCTION__, process.GetUniqueID()); // Check if we should enable the darwin log support on startup/attach. if (!GetGlobalProperties()->GetEnableOnStartup() && !s_is_explicitly_enabled) { // We're neither auto-enabled or explicitly enabled, so we shouldn't try to // enable here. - if (log) - log->Printf("StructuredDataDarwinLog::%s not applicable, we're not " - "enabled (process uid %u)", - __FUNCTION__, process.GetUniqueID()); + LLDB_LOGF(log, + "StructuredDataDarwinLog::%s not applicable, we're not " + "enabled (process uid %u)", + __FUNCTION__, process.GetUniqueID()); return; } @@ -1283,10 +1256,10 @@ void StructuredDataDarwinLog::ModulesDidLoad(Process &process, { std::lock_guard<std::mutex> locker(m_added_breakpoint_mutex); if (m_added_breakpoint) { - if (log) - log->Printf("StructuredDataDarwinLog::%s process uid %u's " - "post-libtrace-init breakpoint is already set", - __FUNCTION__, process.GetUniqueID()); + LLDB_LOGF(log, + "StructuredDataDarwinLog::%s process uid %u's " + "post-libtrace-init breakpoint is already set", + __FUNCTION__, process.GetUniqueID()); return; } } @@ -1298,11 +1271,11 @@ void StructuredDataDarwinLog::ModulesDidLoad(Process &process, GetGlobalProperties()->GetLoggingModuleName(); if (!logging_module_cstr || (logging_module_cstr[0] == 0)) { // We need this. Bail. - if (log) - log->Printf("StructuredDataDarwinLog::%s no logging module name " - "specified, we don't know where to set a breakpoint " - "(process uid %u)", - __FUNCTION__, process.GetUniqueID()); + LLDB_LOGF(log, + "StructuredDataDarwinLog::%s no logging module name " + "specified, we don't know where to set a breakpoint " + "(process uid %u)", + __FUNCTION__, process.GetUniqueID()); return; } @@ -1324,23 +1297,23 @@ void StructuredDataDarwinLog::ModulesDidLoad(Process &process, } if (!found_logging_support_module) { - if (log) - log->Printf("StructuredDataDarwinLog::%s logging module %s " - "has not yet been loaded, can't set a breakpoint " - "yet (process uid %u)", - __FUNCTION__, logging_module_name.AsCString(), - process.GetUniqueID()); + LLDB_LOGF(log, + "StructuredDataDarwinLog::%s logging module %s " + "has not yet been loaded, can't set a breakpoint " + "yet (process uid %u)", + __FUNCTION__, logging_module_name.AsCString(), + process.GetUniqueID()); return; } // Time to enqueue the breakpoint so we can wait for logging support to be // initialized before we try to tap the libtrace stream. AddInitCompletionHook(process); - if (log) - log->Printf("StructuredDataDarwinLog::%s post-init hook breakpoint " - "set for logging module %s (process uid %u)", - __FUNCTION__, logging_module_name.AsCString(), - process.GetUniqueID()); + LLDB_LOGF(log, + "StructuredDataDarwinLog::%s post-init hook breakpoint " + "set for logging module %s (process uid %u)", + __FUNCTION__, logging_module_name.AsCString(), + process.GetUniqueID()); // We need to try the enable here as well, which will succeed in the event // that we're attaching to (rather than launching) the process and the @@ -1519,38 +1492,36 @@ bool StructuredDataDarwinLog::InitCompletionHookCallback( // we can execute our logic to enable the logging support. Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_PROCESS)); - if (log) - log->Printf("StructuredDataDarwinLog::%s() called", __FUNCTION__); + LLDB_LOGF(log, "StructuredDataDarwinLog::%s() called", __FUNCTION__); // Get the current thread. if (!context) { - if (log) - log->Printf("StructuredDataDarwinLog::%s() warning: no context, " - "ignoring", - __FUNCTION__); + LLDB_LOGF(log, + "StructuredDataDarwinLog::%s() warning: no context, " + "ignoring", + __FUNCTION__); return false; } // Get the plugin from the process. auto process_sp = context->exe_ctx_ref.GetProcessSP(); if (!process_sp) { - if (log) - log->Printf("StructuredDataDarwinLog::%s() warning: invalid " - "process in context, ignoring", - __FUNCTION__); + LLDB_LOGF(log, + "StructuredDataDarwinLog::%s() warning: invalid " + "process in context, ignoring", + __FUNCTION__); return false; } - if (log) - log->Printf("StructuredDataDarwinLog::%s() call is for process uid %d", - __FUNCTION__, process_sp->GetUniqueID()); + LLDB_LOGF(log, "StructuredDataDarwinLog::%s() call is for process uid %d", + __FUNCTION__, process_sp->GetUniqueID()); auto plugin_sp = process_sp->GetStructuredDataPlugin(GetDarwinLogTypeName()); if (!plugin_sp) { - if (log) - log->Printf("StructuredDataDarwinLog::%s() warning: no plugin for " - "feature %s in process uid %u", - __FUNCTION__, GetDarwinLogTypeName().AsCString(), - process_sp->GetUniqueID()); + LLDB_LOGF(log, + "StructuredDataDarwinLog::%s() warning: no plugin for " + "feature %s in process uid %u", + __FUNCTION__, GetDarwinLogTypeName().AsCString(), + process_sp->GetUniqueID()); return false; } @@ -1561,51 +1532,51 @@ bool StructuredDataDarwinLog::InitCompletionHookCallback( std::weak_ptr<StructuredDataPlugin> plugin_wp(plugin_sp); ThreadPlanCallOnFunctionExit::Callback callback = [plugin_wp, &called_enable_method, log, process_uid]() { - if (log) - log->Printf("StructuredDataDarwinLog::post-init callback: " - "called (process uid %u)", - process_uid); + LLDB_LOGF(log, + "StructuredDataDarwinLog::post-init callback: " + "called (process uid %u)", + process_uid); auto strong_plugin_sp = plugin_wp.lock(); if (!strong_plugin_sp) { - if (log) - log->Printf("StructuredDataDarwinLog::post-init callback: " - "plugin no longer exists, ignoring (process " - "uid %u)", - process_uid); + LLDB_LOGF(log, + "StructuredDataDarwinLog::post-init callback: " + "plugin no longer exists, ignoring (process " + "uid %u)", + process_uid); return; } // Make sure we only call it once, just in case the thread plan hits // the breakpoint twice. if (!called_enable_method) { - if (log) - log->Printf("StructuredDataDarwinLog::post-init callback: " - "calling EnableNow() (process uid %u)", - process_uid); + LLDB_LOGF(log, + "StructuredDataDarwinLog::post-init callback: " + "calling EnableNow() (process uid %u)", + process_uid); static_cast<StructuredDataDarwinLog *>(strong_plugin_sp.get()) ->EnableNow(); called_enable_method = true; } else { // Our breakpoint was hit more than once. Unexpected but no harm // done. Log it. - if (log) - log->Printf("StructuredDataDarwinLog::post-init callback: " - "skipping EnableNow(), already called by " - "callback [we hit this more than once] " - "(process uid %u)", - process_uid); + LLDB_LOGF(log, + "StructuredDataDarwinLog::post-init callback: " + "skipping EnableNow(), already called by " + "callback [we hit this more than once] " + "(process uid %u)", + process_uid); } }; // Grab the current thread. auto thread_sp = context->exe_ctx_ref.GetThreadSP(); if (!thread_sp) { - if (log) - log->Printf("StructuredDataDarwinLog::%s() warning: failed to " - "retrieve the current thread from the execution " - "context, nowhere to run the thread plan (process uid " - "%u)", - __FUNCTION__, process_sp->GetUniqueID()); + LLDB_LOGF(log, + "StructuredDataDarwinLog::%s() warning: failed to " + "retrieve the current thread from the execution " + "context, nowhere to run the thread plan (process uid " + "%u)", + __FUNCTION__, process_sp->GetUniqueID()); return false; } @@ -1614,10 +1585,10 @@ bool StructuredDataDarwinLog::InitCompletionHookCallback( ThreadPlanSP(new ThreadPlanCallOnFunctionExit(*thread_sp, callback)); const bool abort_other_plans = false; thread_sp->QueueThreadPlan(thread_plan_sp, abort_other_plans); - if (log) - log->Printf("StructuredDataDarwinLog::%s() queuing thread plan on " - "trace library init method entry (process uid %u)", - __FUNCTION__, process_sp->GetUniqueID()); + LLDB_LOGF(log, + "StructuredDataDarwinLog::%s() queuing thread plan on " + "trace library init method entry (process uid %u)", + __FUNCTION__, process_sp->GetUniqueID()); // We return false here to indicate that it isn't a public stop. return false; @@ -1625,18 +1596,17 @@ bool StructuredDataDarwinLog::InitCompletionHookCallback( void StructuredDataDarwinLog::AddInitCompletionHook(Process &process) { Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_PROCESS)); - if (log) - log->Printf("StructuredDataDarwinLog::%s() called (process uid %u)", - __FUNCTION__, process.GetUniqueID()); + LLDB_LOGF(log, "StructuredDataDarwinLog::%s() called (process uid %u)", + __FUNCTION__, process.GetUniqueID()); // Make sure we haven't already done this. { std::lock_guard<std::mutex> locker(m_added_breakpoint_mutex); if (m_added_breakpoint) { - if (log) - log->Printf("StructuredDataDarwinLog::%s() ignoring request, " - "breakpoint already set (process uid %u)", - __FUNCTION__, process.GetUniqueID()); + LLDB_LOGF(log, + "StructuredDataDarwinLog::%s() ignoring request, " + "breakpoint already set (process uid %u)", + __FUNCTION__, process.GetUniqueID()); return; } @@ -1669,22 +1639,22 @@ void StructuredDataDarwinLog::AddInitCompletionHook(Process &process) { eLanguageTypeC, offset, skip_prologue, internal, hardware); if (!breakpoint_sp) { // Huh? Bail here. - if (log) - log->Printf("StructuredDataDarwinLog::%s() failed to set " - "breakpoint in module %s, function %s (process uid %u)", - __FUNCTION__, GetGlobalProperties()->GetLoggingModuleName(), - func_name, process.GetUniqueID()); + LLDB_LOGF(log, + "StructuredDataDarwinLog::%s() failed to set " + "breakpoint in module %s, function %s (process uid %u)", + __FUNCTION__, GetGlobalProperties()->GetLoggingModuleName(), + func_name, process.GetUniqueID()); return; } // Set our callback. breakpoint_sp->SetCallback(InitCompletionHookCallback, nullptr); m_breakpoint_id = breakpoint_sp->GetID(); - if (log) - log->Printf("StructuredDataDarwinLog::%s() breakpoint set in module %s," - "function %s (process uid %u)", - __FUNCTION__, GetGlobalProperties()->GetLoggingModuleName(), - func_name, process.GetUniqueID()); + LLDB_LOGF(log, + "StructuredDataDarwinLog::%s() breakpoint set in module %s," + "function %s (process uid %u)", + __FUNCTION__, GetGlobalProperties()->GetLoggingModuleName(), + func_name, process.GetUniqueID()); } void StructuredDataDarwinLog::DumpTimestamp(Stream &stream, @@ -1825,22 +1795,20 @@ size_t StructuredDataDarwinLog::HandleDisplayOfEvent( void StructuredDataDarwinLog::EnableNow() { Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_PROCESS)); - if (log) - log->Printf("StructuredDataDarwinLog::%s() called", __FUNCTION__); + LLDB_LOGF(log, "StructuredDataDarwinLog::%s() called", __FUNCTION__); // Run the enable command. auto process_sp = GetProcess(); if (!process_sp) { // Nothing to do. - if (log) - log->Printf("StructuredDataDarwinLog::%s() warning: failed to get " - "valid process, skipping", - __FUNCTION__); + LLDB_LOGF(log, + "StructuredDataDarwinLog::%s() warning: failed to get " + "valid process, skipping", + __FUNCTION__); return; } - if (log) - log->Printf("StructuredDataDarwinLog::%s() call is for process uid %u", - __FUNCTION__, process_sp->GetUniqueID()); + LLDB_LOGF(log, "StructuredDataDarwinLog::%s() call is for process uid %u", + __FUNCTION__, process_sp->GetUniqueID()); // If we have configuration data, we can directly enable it now. Otherwise, // we need to run through the command interpreter to parse the auto-run @@ -1849,10 +1817,10 @@ void StructuredDataDarwinLog::EnableNow() { DebuggerSP debugger_sp = process_sp->GetTarget().GetDebugger().shared_from_this(); if (!debugger_sp) { - if (log) - log->Printf("StructuredDataDarwinLog::%s() warning: failed to get " - "debugger shared pointer, skipping (process uid %u)", - __FUNCTION__, process_sp->GetUniqueID()); + LLDB_LOGF(log, + "StructuredDataDarwinLog::%s() warning: failed to get " + "debugger shared pointer, skipping (process uid %u)", + __FUNCTION__, process_sp->GetUniqueID()); return; } @@ -1864,13 +1832,15 @@ void StructuredDataDarwinLog::EnableNow() { const bool success = RunEnableCommand(interpreter); if (log) { if (success) - log->Printf("StructuredDataDarwinLog::%s() ran enable command " - "successfully for (process uid %u)", - __FUNCTION__, process_sp->GetUniqueID()); + LLDB_LOGF(log, + "StructuredDataDarwinLog::%s() ran enable command " + "successfully for (process uid %u)", + __FUNCTION__, process_sp->GetUniqueID()); else - log->Printf("StructuredDataDarwinLog::%s() error: running " - "enable command failed (process uid %u)", - __FUNCTION__, process_sp->GetUniqueID()); + LLDB_LOGF(log, + "StructuredDataDarwinLog::%s() error: running " + "enable command failed (process uid %u)", + __FUNCTION__, process_sp->GetUniqueID()); } // Report failures to the debugger error stream. auto error_stream_sp = debugger_sp->GetAsyncErrorStream(); @@ -1886,11 +1856,11 @@ void StructuredDataDarwinLog::EnableNow() { // specified options. auto config_sp = options_sp->BuildConfigurationData(true); if (!config_sp) { - if (log) - log->Printf("StructuredDataDarwinLog::%s() warning: failed to " - "build configuration data for enable options, skipping " - "(process uid %u)", - __FUNCTION__, process_sp->GetUniqueID()); + LLDB_LOGF(log, + "StructuredDataDarwinLog::%s() warning: failed to " + "build configuration data for enable options, skipping " + "(process uid %u)", + __FUNCTION__, process_sp->GetUniqueID()); return; } @@ -1901,11 +1871,11 @@ void StructuredDataDarwinLog::EnableNow() { // Report results. if (!error.Success()) { - if (log) - log->Printf("StructuredDataDarwinLog::%s() " - "ConfigureStructuredData() call failed " - "(process uid %u): %s", - __FUNCTION__, process_sp->GetUniqueID(), error.AsCString()); + LLDB_LOGF(log, + "StructuredDataDarwinLog::%s() " + "ConfigureStructuredData() call failed " + "(process uid %u): %s", + __FUNCTION__, process_sp->GetUniqueID(), error.AsCString()); auto error_stream_sp = debugger_sp->GetAsyncErrorStream(); if (error_stream_sp) { error_stream_sp->Printf("failed to configure DarwinLog " @@ -1916,9 +1886,9 @@ void StructuredDataDarwinLog::EnableNow() { m_is_enabled = false; } else { m_is_enabled = true; - if (log) - log->Printf("StructuredDataDarwinLog::%s() success via direct " - "configuration (process uid %u)", - __FUNCTION__, process_sp->GetUniqueID()); + LLDB_LOGF(log, + "StructuredDataDarwinLog::%s() success via direct " + "configuration (process uid %u)", + __FUNCTION__, process_sp->GetUniqueID()); } } diff --git a/source/Plugins/StructuredData/DarwinLog/StructuredDataDarwinLogProperties.td b/source/Plugins/StructuredData/DarwinLog/StructuredDataDarwinLogProperties.td new file mode 100644 index 000000000000..5c22158542f9 --- /dev/null +++ b/source/Plugins/StructuredData/DarwinLog/StructuredDataDarwinLogProperties.td @@ -0,0 +1,12 @@ +include "../../../../include/lldb/Core/PropertiesBase.td" + +let Definition = "darwinlog" in { + def EnableOnStartup: Property<"enable-on-startup", "Boolean">, + Global, + DefaultFalse, + Desc<"Enable Darwin os_log collection when debugged process is launched or attached.">; + def AutoEnableOptions: Property<"auto-enable-options", "String">, + Global, + DefaultStringValue<"">, + Desc<"Specify the options to 'plugin structured-data darwin-log enable' that should be applied when automatically enabling logging on startup/attach.">; +} diff --git a/source/Plugins/SymbolFile/Breakpad/SymbolFileBreakpad.cpp b/source/Plugins/SymbolFile/Breakpad/SymbolFileBreakpad.cpp index d4258274a38c..f84cf0c5368d 100644 --- a/source/Plugins/SymbolFile/Breakpad/SymbolFileBreakpad.cpp +++ b/source/Plugins/SymbolFile/Breakpad/SymbolFileBreakpad.cpp @@ -15,7 +15,6 @@ #include "lldb/Host/FileSystem.h" #include "lldb/Symbol/CompileUnit.h" #include "lldb/Symbol/ObjectFile.h" -#include "lldb/Symbol/PostfixExpression.h" #include "lldb/Symbol/SymbolVendor.h" #include "lldb/Symbol/TypeMap.h" #include "lldb/Utility/Log.h" @@ -126,8 +125,8 @@ SymbolFileBreakpad::LineIterator::operator++() { llvm::iterator_range<SymbolFileBreakpad::LineIterator> SymbolFileBreakpad::lines(Record::Kind section_type) { - return llvm::make_range(LineIterator(*m_obj_file, section_type), - LineIterator(*m_obj_file)); + return llvm::make_range(LineIterator(*m_objfile_sp, section_type), + LineIterator(*m_objfile_sp)); } namespace { @@ -179,15 +178,13 @@ ConstString SymbolFileBreakpad::GetPluginNameStatic() { } uint32_t SymbolFileBreakpad::CalculateAbilities() { - if (!m_obj_file) - return 0; - if (m_obj_file->GetPluginName() != ObjectFileBreakpad::GetPluginNameStatic()) + if (!m_objfile_sp || !llvm::isa<ObjectFileBreakpad>(*m_objfile_sp)) return 0; return CompileUnits | Functions | LineTables; } -uint32_t SymbolFileBreakpad::GetNumCompileUnits() { +uint32_t SymbolFileBreakpad::CalculateNumCompileUnits() { ParseCUData(); return m_cu_data->GetSize(); } @@ -204,7 +201,8 @@ CompUnitSP SymbolFileBreakpad::ParseCompileUnitAtIndex(uint32_t index) { // The FileSpec of the compile unit will be the file corresponding to the // first LINE record. - LineIterator It(*m_obj_file, Record::Func, data.bookmark), End(*m_obj_file); + LineIterator It(*m_objfile_sp, Record::Func, data.bookmark), + End(*m_objfile_sp); assert(Record::classify(*It) == Record::Func); ++It; // Skip FUNC record. if (It != End) { @@ -213,12 +211,12 @@ CompUnitSP SymbolFileBreakpad::ParseCompileUnitAtIndex(uint32_t index) { spec = (*m_files)[record->FileNum]; } - auto cu_sp = std::make_shared<CompileUnit>(m_obj_file->GetModule(), + auto cu_sp = std::make_shared<CompileUnit>(m_objfile_sp->GetModule(), /*user_data*/ nullptr, spec, index, eLanguageTypeUnknown, /*is_optimized*/ eLazyBoolNo); - GetSymbolVendor().SetCompileUnitAtIndex(index, cu_sp); + SetCompileUnitAtIndex(index, cu_sp); return cu_sp; } @@ -228,6 +226,7 @@ size_t SymbolFileBreakpad::ParseFunctions(CompileUnit &comp_unit) { } bool SymbolFileBreakpad::ParseLineTable(CompileUnit &comp_unit) { + std::lock_guard<std::recursive_mutex> guard(GetModuleMutex()); CompUnitData &data = m_cu_data->GetEntryRef(comp_unit.GetID()).data; if (!data.line_table_up) @@ -239,6 +238,7 @@ bool SymbolFileBreakpad::ParseLineTable(CompileUnit &comp_unit) { bool SymbolFileBreakpad::ParseSupportFiles(CompileUnit &comp_unit, FileSpecList &support_files) { + std::lock_guard<std::recursive_mutex> guard(GetModuleMutex()); CompUnitData &data = m_cu_data->GetEntryRef(comp_unit.GetID()).data; if (!data.support_files) ParseLineTableAndSupportFiles(comp_unit, data); @@ -251,6 +251,7 @@ uint32_t SymbolFileBreakpad::ResolveSymbolContext(const Address &so_addr, SymbolContextItem resolve_scope, SymbolContext &sc) { + std::lock_guard<std::recursive_mutex> guard(GetModuleMutex()); if (!(resolve_scope & (eSymbolContextCompUnit | eSymbolContextLineEntry))) return 0; @@ -260,7 +261,7 @@ SymbolFileBreakpad::ResolveSymbolContext(const Address &so_addr, if (idx == UINT32_MAX) return 0; - sc.comp_unit = GetSymbolVendor().GetCompileUnitAtIndex(idx).get(); + sc.comp_unit = GetCompileUnitAtIndex(idx).get(); SymbolContextItem result = eSymbolContextCompUnit; if (resolve_scope & eSymbolContextLineEntry) { if (sc.comp_unit->GetLineTable()->FindLineEntryByAddress(so_addr, @@ -275,57 +276,43 @@ SymbolFileBreakpad::ResolveSymbolContext(const Address &so_addr, uint32_t SymbolFileBreakpad::ResolveSymbolContext( const FileSpec &file_spec, uint32_t line, bool check_inlines, lldb::SymbolContextItem resolve_scope, SymbolContextList &sc_list) { + std::lock_guard<std::recursive_mutex> guard(GetModuleMutex()); if (!(resolve_scope & eSymbolContextCompUnit)) return 0; uint32_t old_size = sc_list.GetSize(); for (size_t i = 0, size = GetNumCompileUnits(); i < size; ++i) { - CompileUnit &cu = *GetSymbolVendor().GetCompileUnitAtIndex(i); + CompileUnit &cu = *GetCompileUnitAtIndex(i); cu.ResolveSymbolContext(file_spec, line, check_inlines, /*exact*/ false, resolve_scope, sc_list); } return sc_list.GetSize() - old_size; } -uint32_t SymbolFileBreakpad::FindFunctions( +void SymbolFileBreakpad::FindFunctions( ConstString name, const CompilerDeclContext *parent_decl_ctx, - FunctionNameType name_type_mask, bool include_inlines, bool append, + FunctionNameType name_type_mask, bool include_inlines, SymbolContextList &sc_list) { // TODO - if (!append) - sc_list.Clear(); - return sc_list.GetSize(); } -uint32_t SymbolFileBreakpad::FindFunctions(const RegularExpression ®ex, - bool include_inlines, bool append, - SymbolContextList &sc_list) { +void SymbolFileBreakpad::FindFunctions(const RegularExpression ®ex, + bool include_inlines, + SymbolContextList &sc_list) { // TODO - if (!append) - sc_list.Clear(); - return sc_list.GetSize(); } -uint32_t SymbolFileBreakpad::FindTypes( +void SymbolFileBreakpad::FindTypes( ConstString name, const CompilerDeclContext *parent_decl_ctx, - bool append, uint32_t max_matches, - llvm::DenseSet<SymbolFile *> &searched_symbol_files, TypeMap &types) { - if (!append) - types.Clear(); - return types.GetSize(); -} + uint32_t max_matches, llvm::DenseSet<SymbolFile *> &searched_symbol_files, + TypeMap &types) {} -size_t -SymbolFileBreakpad::FindTypes(const std::vector<CompilerContext> &context, - bool append, TypeMap &types) { - if (!append) - types.Clear(); - return types.GetSize(); -} +void SymbolFileBreakpad::FindTypes(llvm::ArrayRef<CompilerContext> pattern, + LanguageSet languages, TypeMap &types) {} void SymbolFileBreakpad::AddSymbols(Symtab &symtab) { Log *log = GetLogIfAllCategoriesSet(LIBLLDB_LOG_SYMBOLS); - Module &module = *m_obj_file->GetModule(); + Module &module = *m_objfile_sp->GetModule(); addr_t base = GetBaseFileAddress(); if (base == LLDB_INVALID_ADDRESS) { LLDB_LOG(log, "Unable to fetch the base address of object file. Skipping " @@ -347,8 +334,8 @@ void SymbolFileBreakpad::AddSymbols(Symtab &symtab) { return; } symbols.try_emplace( - address, /*symID*/ 0, Mangled(name, /*is_mangled*/ false), - eSymbolTypeCode, /*is_global*/ true, /*is_debug*/ false, + address, /*symID*/ 0, Mangled(name), eSymbolTypeCode, + /*is_global*/ true, /*is_debug*/ false, /*is_trampoline*/ false, /*is_artificial*/ false, AddressRange(section_sp, address - section_sp->GetFileAddress(), size.getValueOr(0)), @@ -372,6 +359,20 @@ void SymbolFileBreakpad::AddSymbols(Symtab &symtab) { symtab.CalculateSymbolSizes(); } +llvm::Expected<lldb::addr_t> +SymbolFileBreakpad::GetParameterStackSize(Symbol &symbol) { + ParseUnwindData(); + if (auto *entry = m_unwind_data->win.FindEntryThatContains( + symbol.GetAddress().GetFileAddress())) { + auto record = StackWinRecord::parse( + *LineIterator(*m_objfile_sp, Record::StackWin, entry->data)); + assert(record.hasValue()); + return record->ParameterSize; + } + return llvm::createStringError(llvm::inconvertibleErrorCode(), + "Parameter size unknown."); +} + static llvm::Optional<std::pair<llvm::StringRef, llvm::StringRef>> GetRule(llvm::StringRef &unwind_rules) { // Unwind rules are of the form @@ -418,7 +419,17 @@ ResolveRegisterOrRA(const SymbolFile::RegisterInfoResolver &resolver, return ResolveRegister(resolver, name); } -bool SymbolFileBreakpad::ParseUnwindRow(llvm::StringRef unwind_rules, +llvm::ArrayRef<uint8_t> SymbolFileBreakpad::SaveAsDWARF(postfix::Node &node) { + ArchSpec arch = m_objfile_sp->GetArchitecture(); + StreamString dwarf(Stream::eBinary, arch.GetAddressByteSize(), + arch.GetByteOrder()); + ToDWARF(node, dwarf); + uint8_t *saved = m_allocator.Allocate<uint8_t>(dwarf.GetSize()); + std::memcpy(saved, dwarf.GetData(), dwarf.GetSize()); + return {saved, dwarf.GetSize()}; +} + +bool SymbolFileBreakpad::ParseCFIUnwindRow(llvm::StringRef unwind_rules, const RegisterInfoResolver &resolver, UnwindPlan::Row &row) { Log *log = GetLogIfAllCategoriesSet(LIBLLDB_LOG_SYMBOLS); @@ -427,7 +438,7 @@ bool SymbolFileBreakpad::ParseUnwindRow(llvm::StringRef unwind_rules, while (auto rule = GetRule(unwind_rules)) { node_alloc.Reset(); llvm::StringRef lhs = rule->first; - postfix::Node *rhs = postfix::Parse(rule->second, node_alloc); + postfix::Node *rhs = postfix::ParseOneExpression(rule->second, node_alloc); if (!rhs) { LLDB_LOG(log, "Could not parse `{0}` as unwind rhs.", rule->second); return false; @@ -451,18 +462,12 @@ bool SymbolFileBreakpad::ParseUnwindRow(llvm::StringRef unwind_rules, return false; } - ArchSpec arch = m_obj_file->GetArchitecture(); - StreamString dwarf(Stream::eBinary, arch.GetAddressByteSize(), - arch.GetByteOrder()); - ToDWARF(*rhs, dwarf); - uint8_t *saved = m_allocator.Allocate<uint8_t>(dwarf.GetSize()); - std::memcpy(saved, dwarf.GetData(), dwarf.GetSize()); - + llvm::ArrayRef<uint8_t> saved = SaveAsDWARF(*rhs); if (lhs == ".cfa") { - row.GetCFAValue().SetIsDWARFExpression(saved, dwarf.GetSize()); + row.GetCFAValue().SetIsDWARFExpression(saved.data(), saved.size()); } else if (const RegisterInfo *info = ResolveRegisterOrRA(resolver, lhs)) { UnwindPlan::Row::RegisterLocation loc; - loc.SetIsDWARFExpression(saved, dwarf.GetSize()); + loc.SetIsDWARFExpression(saved.data(), saved.size()); row.SetRegisterInfo(info->kinds[eRegisterKindLLDB], loc); } else LLDB_LOG(log, "Invalid register `{0}` in unwind rule.", lhs); @@ -478,31 +483,40 @@ UnwindPlanSP SymbolFileBreakpad::GetUnwindPlan(const Address &address, const RegisterInfoResolver &resolver) { ParseUnwindData(); - const UnwindMap::Entry *entry = - m_unwind_data->FindEntryThatContains(address.GetFileAddress()); - if (!entry) - return nullptr; + if (auto *entry = + m_unwind_data->cfi.FindEntryThatContains(address.GetFileAddress())) + return ParseCFIUnwindPlan(entry->data, resolver); + if (auto *entry = + m_unwind_data->win.FindEntryThatContains(address.GetFileAddress())) + return ParseWinUnwindPlan(entry->data, resolver); + return nullptr; +} +UnwindPlanSP +SymbolFileBreakpad::ParseCFIUnwindPlan(const Bookmark &bookmark, + const RegisterInfoResolver &resolver) { addr_t base = GetBaseFileAddress(); if (base == LLDB_INVALID_ADDRESS) return nullptr; - LineIterator It(*m_obj_file, Record::StackCFI, entry->data), End(*m_obj_file); + LineIterator It(*m_objfile_sp, Record::StackCFI, bookmark), + End(*m_objfile_sp); llvm::Optional<StackCFIRecord> init_record = StackCFIRecord::parse(*It); - assert(init_record.hasValue()); - assert(init_record->Size.hasValue()); + assert(init_record.hasValue() && init_record->Size.hasValue() && + "Record already parsed successfully in ParseUnwindData!"); auto plan_sp = std::make_shared<UnwindPlan>(lldb::eRegisterKindLLDB); plan_sp->SetSourceName("breakpad STACK CFI"); plan_sp->SetUnwindPlanValidAtAllInstructions(eLazyBoolNo); + plan_sp->SetUnwindPlanForSignalTrap(eLazyBoolNo); plan_sp->SetSourcedFromCompiler(eLazyBoolYes); plan_sp->SetPlanValidAddressRange( AddressRange(base + init_record->Address, *init_record->Size, - m_obj_file->GetModule()->GetSectionList())); + m_objfile_sp->GetModule()->GetSectionList())); auto row_sp = std::make_shared<UnwindPlan::Row>(); row_sp->SetOffset(0); - if (!ParseUnwindRow(init_record->UnwindRules, resolver, *row_sp)) + if (!ParseCFIUnwindRow(init_record->UnwindRules, resolver, *row_sp)) return nullptr; plan_sp->AppendRow(row_sp); for (++It; It != End; ++It) { @@ -514,19 +528,107 @@ SymbolFileBreakpad::GetUnwindPlan(const Address &address, row_sp = std::make_shared<UnwindPlan::Row>(*row_sp); row_sp->SetOffset(record->Address - init_record->Address); - if (!ParseUnwindRow(record->UnwindRules, resolver, *row_sp)) + if (!ParseCFIUnwindRow(record->UnwindRules, resolver, *row_sp)) return nullptr; plan_sp->AppendRow(row_sp); } return plan_sp; } -SymbolVendor &SymbolFileBreakpad::GetSymbolVendor() { - return *m_obj_file->GetModule()->GetSymbolVendor(); +UnwindPlanSP +SymbolFileBreakpad::ParseWinUnwindPlan(const Bookmark &bookmark, + const RegisterInfoResolver &resolver) { + Log *log = GetLogIfAllCategoriesSet(LIBLLDB_LOG_SYMBOLS); + addr_t base = GetBaseFileAddress(); + if (base == LLDB_INVALID_ADDRESS) + return nullptr; + + LineIterator It(*m_objfile_sp, Record::StackWin, bookmark); + llvm::Optional<StackWinRecord> record = StackWinRecord::parse(*It); + assert(record.hasValue() && + "Record already parsed successfully in ParseUnwindData!"); + + auto plan_sp = std::make_shared<UnwindPlan>(lldb::eRegisterKindLLDB); + plan_sp->SetSourceName("breakpad STACK WIN"); + plan_sp->SetUnwindPlanValidAtAllInstructions(eLazyBoolNo); + plan_sp->SetUnwindPlanForSignalTrap(eLazyBoolNo); + plan_sp->SetSourcedFromCompiler(eLazyBoolYes); + plan_sp->SetPlanValidAddressRange( + AddressRange(base + record->RVA, record->CodeSize, + m_objfile_sp->GetModule()->GetSectionList())); + + auto row_sp = std::make_shared<UnwindPlan::Row>(); + row_sp->SetOffset(0); + + llvm::BumpPtrAllocator node_alloc; + std::vector<std::pair<llvm::StringRef, postfix::Node *>> program = + postfix::ParseFPOProgram(record->ProgramString, node_alloc); + + if (program.empty()) { + LLDB_LOG(log, "Invalid unwind rule: {0}.", record->ProgramString); + return nullptr; + } + auto it = program.begin(); + const auto &symbol_resolver = + [&](postfix::SymbolNode &symbol) -> postfix::Node * { + llvm::StringRef name = symbol.GetName(); + for (const auto &rule : llvm::make_range(program.begin(), it)) { + if (rule.first == name) + return rule.second; + } + if (const RegisterInfo *info = ResolveRegister(resolver, name)) + return postfix::MakeNode<postfix::RegisterNode>( + node_alloc, info->kinds[eRegisterKindLLDB]); + return nullptr; + }; + + // We assume the first value will be the CFA. It is usually called T0, but + // clang will use T1, if it needs to realign the stack. + auto *symbol = llvm::dyn_cast<postfix::SymbolNode>(it->second); + if (symbol && symbol->GetName() == ".raSearch") { + row_sp->GetCFAValue().SetRaSearch(record->LocalSize + + record->SavedRegisterSize); + } else { + if (!postfix::ResolveSymbols(it->second, symbol_resolver)) { + LLDB_LOG(log, "Resolving symbols in `{0}` failed.", + record->ProgramString); + return nullptr; + } + llvm::ArrayRef<uint8_t> saved = SaveAsDWARF(*it->second); + row_sp->GetCFAValue().SetIsDWARFExpression(saved.data(), saved.size()); + } + + // Replace the node value with InitialValueNode, so that subsequent + // expressions refer to the CFA value instead of recomputing the whole + // expression. + it->second = postfix::MakeNode<postfix::InitialValueNode>(node_alloc); + + + // Now process the rest of the assignments. + for (++it; it != program.end(); ++it) { + const RegisterInfo *info = ResolveRegister(resolver, it->first); + // It is not an error if the resolution fails because the program may + // contain temporary variables. + if (!info) + continue; + if (!postfix::ResolveSymbols(it->second, symbol_resolver)) { + LLDB_LOG(log, "Resolving symbols in `{0}` failed.", + record->ProgramString); + return nullptr; + } + + llvm::ArrayRef<uint8_t> saved = SaveAsDWARF(*it->second); + UnwindPlan::Row::RegisterLocation loc; + loc.SetIsDWARFExpression(saved.data(), saved.size()); + row_sp->SetRegisterInfo(info->kinds[eRegisterKindLLDB], loc); + } + + plan_sp->AppendRow(row_sp); + return plan_sp; } addr_t SymbolFileBreakpad::GetBaseFileAddress() { - return m_obj_file->GetModule() + return m_objfile_sp->GetModule() ->GetObjectFile() ->GetBaseAddress() .GetFileAddress(); @@ -569,8 +671,8 @@ void SymbolFileBreakpad::ParseCUData() { // We shall create one compile unit for each FUNC record. So, count the number // of FUNC records, and store them in m_cu_data, together with their ranges. - for (LineIterator It(*m_obj_file, Record::Func), End(*m_obj_file); It != End; - ++It) { + for (LineIterator It(*m_objfile_sp, Record::Func), End(*m_objfile_sp); + It != End; ++It) { if (auto record = FuncRecord::parse(*It)) { m_cu_data->Append(CompUnitMap::Entry(base + record->Address, record->Size, CompUnitData(It.GetBookmark()))); @@ -589,7 +691,7 @@ void SymbolFileBreakpad::ParseLineTableAndSupportFiles(CompileUnit &cu, "How did we create compile units without a base address?"); SupportFileMap map; - data.line_table_up = llvm::make_unique<LineTable>(&cu); + data.line_table_up = std::make_unique<LineTable>(&cu); std::unique_ptr<LineSequence> line_seq_up( data.line_table_up->CreateLineSequenceContainer()); llvm::Optional<addr_t> next_addr; @@ -603,7 +705,8 @@ void SymbolFileBreakpad::ParseLineTableAndSupportFiles(CompileUnit &cu, line_seq_up->Clear(); }; - LineIterator It(*m_obj_file, Record::Func, data.bookmark), End(*m_obj_file); + LineIterator It(*m_objfile_sp, Record::Func, data.bookmark), + End(*m_objfile_sp); assert(Record::classify(*It) == Record::Func); for (++It; It != End; ++It) { auto record = LineRecord::parse(*It); @@ -631,8 +734,8 @@ void SymbolFileBreakpad::ParseLineTableAndSupportFiles(CompileUnit &cu, void SymbolFileBreakpad::ParseUnwindData() { if (m_unwind_data) return; - m_unwind_data.emplace(); + Log *log = GetLogIfAllCategoriesSet(LIBLLDB_LOG_SYMBOLS); addr_t base = GetBaseFileAddress(); if (base == LLDB_INVALID_ADDRESS) { @@ -640,14 +743,24 @@ void SymbolFileBreakpad::ParseUnwindData() { "of object file."); } - for (LineIterator It(*m_obj_file, Record::StackCFI), End(*m_obj_file); + for (LineIterator It(*m_objfile_sp, Record::StackCFI), End(*m_objfile_sp); It != End; ++It) { if (auto record = StackCFIRecord::parse(*It)) { if (record->Size) - m_unwind_data->Append(UnwindMap::Entry( + m_unwind_data->cfi.Append(UnwindMap::Entry( base + record->Address, *record->Size, It.GetBookmark())); } else LLDB_LOG(log, "Failed to parse: {0}. Skipping record.", *It); } - m_unwind_data->Sort(); + m_unwind_data->cfi.Sort(); + + for (LineIterator It(*m_objfile_sp, Record::StackWin), End(*m_objfile_sp); + It != End; ++It) { + if (auto record = StackWinRecord::parse(*It)) { + m_unwind_data->win.Append(UnwindMap::Entry( + base + record->RVA, record->CodeSize, It.GetBookmark())); + } else + LLDB_LOG(log, "Failed to parse: {0}. Skipping record.", *It); + } + m_unwind_data->win.Sort(); } diff --git a/source/Plugins/SymbolFile/Breakpad/SymbolFileBreakpad.h b/source/Plugins/SymbolFile/Breakpad/SymbolFileBreakpad.h index 8a0b7645fd0a..a10138cdf92f 100644 --- a/source/Plugins/SymbolFile/Breakpad/SymbolFileBreakpad.h +++ b/source/Plugins/SymbolFile/Breakpad/SymbolFileBreakpad.h @@ -12,6 +12,7 @@ #include "Plugins/ObjectFile/Breakpad/BreakpadRecords.h" #include "lldb/Core/FileSpecList.h" #include "lldb/Symbol/LineTable.h" +#include "lldb/Symbol/PostfixExpression.h" #include "lldb/Symbol/SymbolFile.h" #include "lldb/Symbol/UnwindPlan.h" @@ -31,12 +32,13 @@ public: return "Breakpad debug symbol file reader."; } - static SymbolFile *CreateInstance(ObjectFile *obj_file) { - return new SymbolFileBreakpad(obj_file); + static SymbolFile *CreateInstance(lldb::ObjectFileSP objfile_sp) { + return new SymbolFileBreakpad(std::move(objfile_sp)); } // Constructors and Destructors - SymbolFileBreakpad(ObjectFile *object_file) : SymbolFile(object_file) {} + SymbolFileBreakpad(lldb::ObjectFileSP objfile_sp) + : SymbolFile(std::move(objfile_sp)) {} ~SymbolFileBreakpad() override {} @@ -46,10 +48,6 @@ public: // Compile Unit function calls - uint32_t GetNumCompileUnits() override; - - lldb::CompUnitSP ParseCompileUnitAtIndex(uint32_t index) override; - lldb::LanguageType ParseLanguage(CompileUnit &comp_unit) override { return lldb::eLanguageTypeUnknown; } @@ -72,12 +70,10 @@ public: size_t ParseBlocksRecursive(Function &func) override { return 0; } - uint32_t FindGlobalVariables(ConstString name, - const CompilerDeclContext *parent_decl_ctx, - uint32_t max_matches, - VariableList &variables) override { - return 0; - } + void FindGlobalVariables(ConstString name, + const CompilerDeclContext *parent_decl_ctx, + uint32_t max_matches, + VariableList &variables) override {} size_t ParseVariablesForContext(const SymbolContext &sc) override { return 0; @@ -99,31 +95,30 @@ public: lldb::SymbolContextItem resolve_scope, SymbolContextList &sc_list) override; - size_t GetTypes(SymbolContextScope *sc_scope, lldb::TypeClass type_mask, - TypeList &type_list) override { - return 0; - } + void GetTypes(SymbolContextScope *sc_scope, lldb::TypeClass type_mask, + TypeList &type_list) override {} - uint32_t FindFunctions(ConstString name, - const CompilerDeclContext *parent_decl_ctx, - lldb::FunctionNameType name_type_mask, - bool include_inlines, bool append, - SymbolContextList &sc_list) override; + void FindFunctions(ConstString name, + const CompilerDeclContext *parent_decl_ctx, + lldb::FunctionNameType name_type_mask, + bool include_inlines, SymbolContextList &sc_list) override; - uint32_t FindFunctions(const RegularExpression ®ex, bool include_inlines, - bool append, SymbolContextList &sc_list) override; + void FindFunctions(const RegularExpression ®ex, bool include_inlines, + SymbolContextList &sc_list) override; - uint32_t FindTypes(ConstString name, - const CompilerDeclContext *parent_decl_ctx, bool append, - uint32_t max_matches, - llvm::DenseSet<SymbolFile *> &searched_symbol_files, - TypeMap &types) override; + void FindTypes(ConstString name, const CompilerDeclContext *parent_decl_ctx, + uint32_t max_matches, + llvm::DenseSet<SymbolFile *> &searched_symbol_files, + TypeMap &types) override; - size_t FindTypes(const std::vector<CompilerContext> &context, bool append, - TypeMap &types) override; + void FindTypes(llvm::ArrayRef<CompilerContext> pattern, LanguageSet languages, + TypeMap &types) override; - TypeSystem *GetTypeSystemForLanguage(lldb::LanguageType language) override { - return nullptr; + llvm::Expected<TypeSystem &> + GetTypeSystemForLanguage(lldb::LanguageType language) override { + return llvm::make_error<llvm::StringError>( + "SymbolFileBreakpad does not support GetTypeSystemForLanguage", + llvm::inconvertibleErrorCode()); } CompilerDeclContext @@ -134,6 +129,8 @@ public: void AddSymbols(Symtab &symtab) override; + llvm::Expected<lldb::addr_t> GetParameterStackSize(Symbol &symbol) override; + lldb::UnwindPlanSP GetUnwindPlan(const Address &address, const RegisterInfoResolver &resolver) override; @@ -196,15 +193,22 @@ private: }; - SymbolVendor &GetSymbolVendor(); + uint32_t CalculateNumCompileUnits() override; + lldb::CompUnitSP ParseCompileUnitAtIndex(uint32_t index) override; + lldb::addr_t GetBaseFileAddress(); void ParseFileRecords(); void ParseCUData(); void ParseLineTableAndSupportFiles(CompileUnit &cu, CompUnitData &data); void ParseUnwindData(); - bool ParseUnwindRow(llvm::StringRef unwind_rules, - const RegisterInfoResolver &resolver, - UnwindPlan::Row &row); + llvm::ArrayRef<uint8_t> SaveAsDWARF(postfix::Node &node); + lldb::UnwindPlanSP ParseCFIUnwindPlan(const Bookmark &bookmark, + const RegisterInfoResolver &resolver); + bool ParseCFIUnwindRow(llvm::StringRef unwind_rules, + const RegisterInfoResolver &resolver, + UnwindPlan::Row &row); + lldb::UnwindPlanSP ParseWinUnwindPlan(const Bookmark &bookmark, + const RegisterInfoResolver &resolver); using CompUnitMap = RangeDataVector<lldb::addr_t, lldb::addr_t, CompUnitData>; @@ -212,7 +216,11 @@ private: llvm::Optional<CompUnitMap> m_cu_data; using UnwindMap = RangeDataVector<lldb::addr_t, lldb::addr_t, Bookmark>; - llvm::Optional<UnwindMap> m_unwind_data; + struct UnwindData { + UnwindMap cfi; + UnwindMap win; + }; + llvm::Optional<UnwindData> m_unwind_data; llvm::BumpPtrAllocator m_allocator; }; diff --git a/source/Plugins/SymbolFile/DWARF/AppleDWARFIndex.cpp b/source/Plugins/SymbolFile/DWARF/AppleDWARFIndex.cpp index 9ae047da1325..0a5073b8cd9e 100644 --- a/source/Plugins/SymbolFile/DWARF/AppleDWARFIndex.cpp +++ b/source/Plugins/SymbolFile/DWARF/AppleDWARFIndex.cpp @@ -21,30 +21,30 @@ std::unique_ptr<AppleDWARFIndex> AppleDWARFIndex::Create( Module &module, DWARFDataExtractor apple_names, DWARFDataExtractor apple_namespaces, DWARFDataExtractor apple_types, DWARFDataExtractor apple_objc, DWARFDataExtractor debug_str) { - auto apple_names_table_up = llvm::make_unique<DWARFMappedHash::MemoryTable>( + auto apple_names_table_up = std::make_unique<DWARFMappedHash::MemoryTable>( apple_names, debug_str, ".apple_names"); if (!apple_names_table_up->IsValid()) apple_names_table_up.reset(); auto apple_namespaces_table_up = - llvm::make_unique<DWARFMappedHash::MemoryTable>( + std::make_unique<DWARFMappedHash::MemoryTable>( apple_namespaces, debug_str, ".apple_namespaces"); if (!apple_namespaces_table_up->IsValid()) apple_namespaces_table_up.reset(); - auto apple_types_table_up = llvm::make_unique<DWARFMappedHash::MemoryTable>( + auto apple_types_table_up = std::make_unique<DWARFMappedHash::MemoryTable>( apple_types, debug_str, ".apple_types"); if (!apple_types_table_up->IsValid()) apple_types_table_up.reset(); - auto apple_objc_table_up = llvm::make_unique<DWARFMappedHash::MemoryTable>( + auto apple_objc_table_up = std::make_unique<DWARFMappedHash::MemoryTable>( apple_objc, debug_str, ".apple_objc"); if (!apple_objc_table_up->IsValid()) apple_objc_table_up.reset(); if (apple_names_table_up || apple_names_table_up || apple_types_table_up || apple_objc_table_up) - return llvm::make_unique<AppleDWARFIndex>( + return std::make_unique<AppleDWARFIndex>( module, std::move(apple_names_table_up), std::move(apple_namespaces_table_up), std::move(apple_types_table_up), std::move(apple_objc_table_up)); @@ -110,6 +110,7 @@ void AppleDWARFIndex::GetTypes(const DWARFDeclContext &context, const bool has_qualified_name_hash = m_apple_types_up->GetHeader().header_data.ContainsAtom( DWARFMappedHash::eAtomTypeQualNameHash); + const ConstString type_name(context[0].name); const dw_tag_t tag = context[0].tag; if (has_tag && has_qualified_name_hash) { @@ -119,12 +120,32 @@ void AppleDWARFIndex::GetTypes(const DWARFDeclContext &context, m_module.LogMessage(log, "FindByNameAndTagAndQualifiedNameHash()"); m_apple_types_up->FindByNameAndTagAndQualifiedNameHash( type_name.GetStringRef(), tag, qualified_name_hash, offsets); - } else if (has_tag) { + return; + } + + if (has_tag) { + // When searching for a scoped type (for example, + // "std::vector<int>::const_iterator") searching for the innermost + // name alone ("const_iterator") could yield many false + // positives. By searching for the parent type ("vector<int>") + // first we can avoid extracting type DIEs from object files that + // would fail the filter anyway. + if (!has_qualified_name_hash && (context.GetSize() > 1) && + (context[1].tag == DW_TAG_class_type || + context[1].tag == DW_TAG_structure_type)) { + DIEArray class_matches; + m_apple_types_up->FindByName(context[1].name, class_matches); + if (class_matches.empty()) + return; + } + if (log) m_module.LogMessage(log, "FindByNameAndTag()"); m_apple_types_up->FindByNameAndTag(type_name.GetStringRef(), tag, offsets); - } else - m_apple_types_up->FindByName(type_name.GetStringRef(), offsets); + return; + } + + m_apple_types_up->FindByName(type_name.GetStringRef(), offsets); } void AppleDWARFIndex::GetNamespaces(ConstString name, DIEArray &offsets) { diff --git a/source/Plugins/SymbolFile/DWARF/DWARFASTParser.h b/source/Plugins/SymbolFile/DWARF/DWARFASTParser.h index e7927b31b9c3..7ee4727cde91 100644 --- a/source/Plugins/SymbolFile/DWARF/DWARFASTParser.h +++ b/source/Plugins/SymbolFile/DWARF/DWARFASTParser.h @@ -28,7 +28,6 @@ public: virtual lldb::TypeSP ParseTypeFromDWARF(const lldb_private::SymbolContext &sc, const DWARFDIE &die, - lldb_private::Log *log, bool *type_is_new_ptr) = 0; virtual lldb_private::Function * @@ -48,8 +47,8 @@ public: virtual lldb_private::CompilerDeclContext GetDeclContextContainingUIDFromDWARF(const DWARFDIE &die) = 0; - virtual std::vector<DWARFDIE> - GetDIEForDeclContext(lldb_private::CompilerDeclContext decl_context) = 0; + virtual void EnsureAllDIEsInDeclContextHaveBeenParsed( + lldb_private::CompilerDeclContext decl_context) = 0; static llvm::Optional<lldb_private::SymbolFile::ArrayInfo> ParseChildArrayInfo(const DWARFDIE &parent_die, diff --git a/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp b/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp index b85ab54a10d3..636e6032b877 100644 --- a/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp +++ b/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp @@ -9,7 +9,6 @@ #include <stdlib.h> #include "DWARFASTParserClang.h" -#include "DWARFDIE.h" #include "DWARFDebugInfo.h" #include "DWARFDeclContext.h" #include "DWARFDefines.h" @@ -28,7 +27,7 @@ #include "lldb/Symbol/CompileUnit.h" #include "lldb/Symbol/Function.h" #include "lldb/Symbol/ObjectFile.h" -#include "lldb/Symbol/SymbolVendor.h" +#include "lldb/Symbol/SymbolFile.h" #include "lldb/Symbol/TypeList.h" #include "lldb/Symbol/TypeMap.h" #include "lldb/Target/Language.h" @@ -144,23 +143,27 @@ TypeSP DWARFASTParserClang::ParseTypeFromDWO(const DWARFDIE &die, Log *log) { // If this type comes from a Clang module, look in the DWARF section // of the pcm file in the module cache. Clang generates DWO skeleton // units as breadcrumbs to find them. - std::vector<CompilerContext> decl_context; + llvm::SmallVector<CompilerContext, 4> decl_context; die.GetDeclContext(decl_context); TypeMap dwo_types; - if (!dwo_module_sp->GetSymbolVendor()->FindTypes(decl_context, true, - dwo_types)) { + // The type in the Clang module must have the same language as the current CU. + LanguageSet languages; + languages.Insert(die.GetCU()->GetLanguageType()); + dwo_module_sp->GetSymbolFile()->FindTypes(decl_context, languages, dwo_types); + if (dwo_types.Empty()) { if (!IsClangModuleFwdDecl(die)) return TypeSP(); - // Since this this type is defined in one of the Clang modules imported by - // this symbol file, search all of them. + // Since this type is defined in one of the Clang modules imported + // by this symbol file, search all of them. auto &sym_file = die.GetCU()->GetSymbolFileDWARF(); for (const auto &name_module : sym_file.getExternalTypeModules()) { if (!name_module.second) continue; - SymbolVendor *sym_vendor = name_module.second->GetSymbolVendor(); - if (sym_vendor->FindTypes(decl_context, true, dwo_types)) + name_module.second->GetSymbolFile()->FindTypes(decl_context, + languages, dwo_types); + if (dwo_types.GetSize()) break; } } @@ -188,7 +191,7 @@ TypeSP DWARFASTParserClang::ParseTypeFromDWO(const DWARFDIE &die, Log *log) { nullptr, LLDB_INVALID_UID, Type::eEncodingInvalid, &dwo_type_sp->GetDeclaration(), type, Type::eResolveStateForward)); - dwarf->GetTypeList()->Insert(type_sp); + dwarf->GetTypeList().Insert(type_sp); dwarf->GetDIEToType()[die.GetDIE()] = type_sp.get(); clang::TagDecl *tag_decl = ClangASTContext::GetAsTagDecl(type); if (tag_decl) @@ -228,42 +231,7 @@ static void CompleteExternalTagDeclType(ClangASTImporter &ast_importer, } } -namespace { -/// Parsed form of all attributes that are relevant for type reconstruction. -/// Some attributes are relevant for all kinds of types (declaration), while -/// others are only meaningful to a specific type (is_virtual) -struct ParsedTypeAttributes { - explicit ParsedTypeAttributes(const DWARFDIE &die); - - AccessType accessibility = eAccessNone; - bool is_artificial = false; - bool is_complete_objc_class = false; - bool is_explicit = false; - bool is_forward_declaration = false; - bool is_inline = false; - bool is_scoped_enum = false; - bool is_vector = false; - bool is_virtual = false; - clang::StorageClass storage = clang::SC_None; - const char *mangled_name = nullptr; - ConstString name; - Declaration decl; - DWARFDIE object_pointer; - DWARFFormValue abstract_origin; - DWARFFormValue containing_type; - DWARFFormValue signature; - DWARFFormValue specification; - DWARFFormValue type; - LanguageType class_language = eLanguageTypeUnknown; - llvm::Optional<uint64_t> byte_size; - size_t calling_convention = llvm::dwarf::DW_CC_normal; - uint32_t bit_stride = 0; - uint32_t byte_stride = 0; - uint32_t encoding = 0; -}; -} // namespace - -ParsedTypeAttributes::ParsedTypeAttributes(const DWARFDIE &die) { +ParsedDWARFTypeAttributes::ParsedDWARFTypeAttributes(const DWARFDIE &die) { DWARFAttributes attributes; size_t num_attributes = die.GetAttributes(attributes); for (size_t i = 0; i < num_attributes; ++i) { @@ -390,13 +358,17 @@ static std::string GetUnitName(const DWARFDIE &die) { } TypeSP DWARFASTParserClang::ParseTypeFromDWARF(const SymbolContext &sc, - const DWARFDIE &die, Log *log, + const DWARFDIE &die, bool *type_is_new_ptr) { if (type_is_new_ptr) *type_is_new_ptr = false; if (!die) return nullptr; + + Log *log(LogChannelDWARF::GetLogIfAny(DWARF_LOG_TYPE_COMPLETION | + DWARF_LOG_LOOKUPS)); + SymbolFileDWARF *dwarf = die.GetDWARF(); if (log) { DWARFDIE context_die; @@ -420,11 +392,11 @@ TypeSP DWARFASTParserClang::ParseTypeFromDWARF(const SymbolContext &sc, // Set a bit that lets us know that we are currently parsing this dwarf->GetDIEToType()[die.GetDIE()] = DIE_IS_BEING_PARSED; - ParsedTypeAttributes attrs(die); + ParsedDWARFTypeAttributes attrs(die); if (DWARFDIE signature_die = attrs.signature.Reference()) { if (TypeSP type_sp = - ParseTypeFromDWARF(sc, signature_die, log, type_is_new_ptr)) { + ParseTypeFromDWARF(sc, signature_die, type_is_new_ptr)) { dwarf->GetDIEToType()[die.GetDIE()] = type_sp.get(); if (clang::DeclContext *decl_ctx = GetCachedClangDeclContextForDIE(signature_die)) @@ -434,7 +406,6 @@ TypeSP DWARFASTParserClang::ParseTypeFromDWARF(const SymbolContext &sc, return nullptr; } - TypeList *type_list = dwarf->GetTypeList(); if (type_is_new_ptr) *type_is_new_ptr = true; @@ -562,7 +533,7 @@ TypeSP DWARFASTParserClang::ParseTypeFromDWARF(const SymbolContext &sc, bool function_type_is_new_pointer; TypeSP lldb_function_type_sp = ParseTypeFromDWARF( - sc, function_type, log, &function_type_is_new_pointer); + sc, function_type, &function_type_is_new_pointer); if (lldb_function_type_sp) { clang_type = m_ast.CreateBlockPointerType( @@ -660,370 +631,11 @@ TypeSP DWARFASTParserClang::ParseTypeFromDWARF(const SymbolContext &sc, case DW_TAG_structure_type: case DW_TAG_union_type: case DW_TAG_class_type: { - // UniqueDWARFASTType is large, so don't create a local variables on - // the stack, put it on the heap. This function is often called - // recursively and clang isn't good and sharing the stack space for - // variables in different blocks. - std::unique_ptr<UniqueDWARFASTType> unique_ast_entry_up( - new UniqueDWARFASTType()); - - ConstString unique_typename(attrs.name); - Declaration unique_decl(attrs.decl); - - if (attrs.name) { - if (Language::LanguageIsCPlusPlus(cu_language)) { - // For C++, we rely solely upon the one definition rule that says - // only one thing can exist at a given decl context. We ignore the - // file and line that things are declared on. - std::string qualified_name; - if (die.GetQualifiedName(qualified_name)) - unique_typename = ConstString(qualified_name); - unique_decl.Clear(); - } - - if (dwarf->GetUniqueDWARFASTTypeMap().Find( - unique_typename, die, unique_decl, attrs.byte_size.getValueOr(-1), - *unique_ast_entry_up)) { - type_sp = unique_ast_entry_up->m_type_sp; - if (type_sp) { - dwarf->GetDIEToType()[die.GetDIE()] = type_sp.get(); - return type_sp; - } - } - } - - DEBUG_PRINTF("0x%8.8" PRIx64 ": %s (\"%s\")\n", die.GetID(), - DW_TAG_value_to_name(tag), type_name_cstr); - - int tag_decl_kind = -1; - AccessType default_accessibility = eAccessNone; - if (tag == DW_TAG_structure_type) { - tag_decl_kind = clang::TTK_Struct; - default_accessibility = eAccessPublic; - } else if (tag == DW_TAG_union_type) { - tag_decl_kind = clang::TTK_Union; - default_accessibility = eAccessPublic; - } else if (tag == DW_TAG_class_type) { - tag_decl_kind = clang::TTK_Class; - default_accessibility = eAccessPrivate; - } - - if (attrs.byte_size && *attrs.byte_size == 0 && attrs.name && - !die.HasChildren() && cu_language == eLanguageTypeObjC) { - // Work around an issue with clang at the moment where forward - // declarations for objective C classes are emitted as: - // DW_TAG_structure_type [2] - // DW_AT_name( "ForwardObjcClass" ) - // DW_AT_byte_size( 0x00 ) - // DW_AT_decl_file( "..." ) - // DW_AT_decl_line( 1 ) - // - // Note that there is no DW_AT_declaration and there are no children, - // and the byte size is zero. - attrs.is_forward_declaration = true; - } - - if (attrs.class_language == eLanguageTypeObjC || - attrs.class_language == eLanguageTypeObjC_plus_plus) { - if (!attrs.is_complete_objc_class && - die.Supports_DW_AT_APPLE_objc_complete_type()) { - // We have a valid eSymbolTypeObjCClass class symbol whose name - // matches the current objective C class that we are trying to find - // and this DIE isn't the complete definition (we checked - // is_complete_objc_class above and know it is false), so the real - // definition is in here somewhere - type_sp = - dwarf->FindCompleteObjCDefinitionTypeForDIE(die, attrs.name, true); - - if (!type_sp) { - SymbolFileDWARFDebugMap *debug_map_symfile = - dwarf->GetDebugMapSymfile(); - if (debug_map_symfile) { - // We weren't able to find a full declaration in this DWARF, - // see if we have a declaration anywhere else... - type_sp = debug_map_symfile->FindCompleteObjCDefinitionTypeForDIE( - die, attrs.name, true); - } - } - - if (type_sp) { - if (log) { - dwarf->GetObjectFile()->GetModule()->LogMessage( - log, - "SymbolFileDWARF(%p) - 0x%8.8x: %s type \"%s\" is an " - "incomplete objc type, complete type is 0x%8.8" PRIx64, - static_cast<void *>(this), die.GetOffset(), - DW_TAG_value_to_name(tag), attrs.name.GetCString(), - type_sp->GetID()); - } - - // We found a real definition for this type elsewhere so lets use - // it and cache the fact that we found a complete type for this - // die - dwarf->GetDIEToType()[die.GetDIE()] = type_sp.get(); - return type_sp; - } - } - } - - if (attrs.is_forward_declaration) { - // We have a forward declaration to a type and we need to try and - // find a full declaration. We look in the current type index just in - // case we have a forward declaration followed by an actual - // declarations in the DWARF. If this fails, we need to look - // elsewhere... - if (log) { - dwarf->GetObjectFile()->GetModule()->LogMessage( - log, - "SymbolFileDWARF(%p) - 0x%8.8x: %s type \"%s\" is a " - "forward declaration, trying to find complete type", - static_cast<void *>(this), die.GetOffset(), - DW_TAG_value_to_name(tag), attrs.name.GetCString()); - } - - // See if the type comes from a DWO module and if so, track down that - // type. - type_sp = ParseTypeFromDWO(die, log); - if (type_sp) - return type_sp; - - DWARFDeclContext die_decl_ctx; - die.GetDWARFDeclContext(die_decl_ctx); - - // type_sp = FindDefinitionTypeForDIE (dwarf_cu, die, - // type_name_const_str); - type_sp = dwarf->FindDefinitionTypeForDWARFDeclContext(die_decl_ctx); - - if (!type_sp) { - SymbolFileDWARFDebugMap *debug_map_symfile = - dwarf->GetDebugMapSymfile(); - if (debug_map_symfile) { - // We weren't able to find a full declaration in this DWARF, see - // if we have a declaration anywhere else... - type_sp = debug_map_symfile->FindDefinitionTypeForDWARFDeclContext( - die_decl_ctx); - } - } - - if (type_sp) { - if (log) { - dwarf->GetObjectFile()->GetModule()->LogMessage( - log, - "SymbolFileDWARF(%p) - 0x%8.8x: %s type \"%s\" is a " - "forward declaration, complete type is 0x%8.8" PRIx64, - static_cast<void *>(this), die.GetOffset(), - DW_TAG_value_to_name(tag), attrs.name.GetCString(), - type_sp->GetID()); - } - - // We found a real definition for this type elsewhere so lets use - // it and cache the fact that we found a complete type for this die - dwarf->GetDIEToType()[die.GetDIE()] = type_sp.get(); - clang::DeclContext *defn_decl_ctx = - GetCachedClangDeclContextForDIE(dwarf->GetDIE(type_sp->GetID())); - if (defn_decl_ctx) - LinkDeclContextToDIE(defn_decl_ctx, die); - return type_sp; - } - } - assert(tag_decl_kind != -1); - bool clang_type_was_created = false; - clang_type.SetCompilerType( - &m_ast, dwarf->GetForwardDeclDieToClangType().lookup(die.GetDIE())); - if (!clang_type) { - clang::DeclContext *decl_ctx = - GetClangDeclContextContainingDIE(die, nullptr); - - // If your decl context is a record that was imported from another - // AST context (in the gmodules case), we need to make sure the type - // backing the Decl is complete before adding children to it. This is - // not an issue in the non-gmodules case because the debug info will - // always contain a full definition of parent types in that case. - CompleteExternalTagDeclType(GetClangASTImporter(), decl_ctx, die, - attrs.name.GetCString()); - - if (attrs.accessibility == eAccessNone && decl_ctx) { - // Check the decl context that contains this class/struct/union. If - // it is a class we must give it an accessibility. - const clang::Decl::Kind containing_decl_kind = decl_ctx->getDeclKind(); - if (DeclKindIsCXXClass(containing_decl_kind)) - attrs.accessibility = default_accessibility; - } - - ClangASTMetadata metadata; - metadata.SetUserID(die.GetID()); - metadata.SetIsDynamicCXXType(dwarf->ClassOrStructIsVirtual(die)); - - if (attrs.name.GetStringRef().contains('<')) { - ClangASTContext::TemplateParameterInfos template_param_infos; - if (ParseTemplateParameterInfos(die, template_param_infos)) { - clang::ClassTemplateDecl *class_template_decl = - m_ast.ParseClassTemplateDecl(decl_ctx, attrs.accessibility, - attrs.name.GetCString(), - tag_decl_kind, template_param_infos); - if (!class_template_decl) { - if (log) { - dwarf->GetObjectFile()->GetModule()->LogMessage( - log, - "SymbolFileDWARF(%p) - 0x%8.8x: %s type \"%s\" " - "clang::ClassTemplateDecl failed to return a decl.", - static_cast<void *>(this), die.GetOffset(), - DW_TAG_value_to_name(tag), attrs.name.GetCString()); - } - return TypeSP(); - } - - clang::ClassTemplateSpecializationDecl *class_specialization_decl = - m_ast.CreateClassTemplateSpecializationDecl( - decl_ctx, class_template_decl, tag_decl_kind, - template_param_infos); - clang_type = m_ast.CreateClassTemplateSpecializationType( - class_specialization_decl); - clang_type_was_created = true; - - m_ast.SetMetadata(class_template_decl, metadata); - m_ast.SetMetadata(class_specialization_decl, metadata); - } - } - - if (!clang_type_was_created) { - clang_type_was_created = true; - clang_type = m_ast.CreateRecordType( - decl_ctx, attrs.accessibility, attrs.name.GetCString(), - tag_decl_kind, attrs.class_language, &metadata); - } - } - - // Store a forward declaration to this class type in case any - // parameters in any class methods need it for the clang types for - // function prototypes. - LinkDeclContextToDIE(m_ast.GetDeclContextForType(clang_type), die); - type_sp = std::make_shared<Type>(die.GetID(), dwarf, attrs.name, - attrs.byte_size, nullptr, LLDB_INVALID_UID, - Type::eEncodingIsUID, &attrs.decl, clang_type, - Type::eResolveStateForward); - - type_sp->SetIsCompleteObjCClass(attrs.is_complete_objc_class); - - // Add our type to the unique type map so we don't end up creating many - // copies of the same type over and over in the ASTContext for our - // module - unique_ast_entry_up->m_type_sp = type_sp; - unique_ast_entry_up->m_die = die; - unique_ast_entry_up->m_declaration = unique_decl; - unique_ast_entry_up->m_byte_size = attrs.byte_size.getValueOr(0); - dwarf->GetUniqueDWARFASTTypeMap().Insert(unique_typename, - *unique_ast_entry_up); - - if (attrs.is_forward_declaration && die.HasChildren()) { - // Check to see if the DIE actually has a definition, some version of - // GCC will - // emit DIEs with DW_AT_declaration set to true, but yet still have - // subprogram, members, or inheritance, so we can't trust it - DWARFDIE child_die = die.GetFirstChild(); - while (child_die) { - switch (child_die.Tag()) { - case DW_TAG_inheritance: - case DW_TAG_subprogram: - case DW_TAG_member: - case DW_TAG_APPLE_property: - case DW_TAG_class_type: - case DW_TAG_structure_type: - case DW_TAG_enumeration_type: - case DW_TAG_typedef: - case DW_TAG_union_type: - child_die.Clear(); - attrs.is_forward_declaration = false; - break; - default: - child_die = child_die.GetSibling(); - break; - } - } - } - - if (!attrs.is_forward_declaration) { - // Always start the definition for a class type so that if the class - // has child classes or types that require the class to be created - // for use as their decl contexts the class will be ready to accept - // these child definitions. - if (!die.HasChildren()) { - // No children for this struct/union/class, lets finish it - if (ClangASTContext::StartTagDeclarationDefinition(clang_type)) { - ClangASTContext::CompleteTagDeclarationDefinition(clang_type); - } else { - dwarf->GetObjectFile()->GetModule()->ReportError( - "DWARF DIE at 0x%8.8x named \"%s\" was not able to start its " - "definition.\nPlease file a bug and attach the file at the " - "start of this error message", - die.GetOffset(), attrs.name.GetCString()); - } - - if (tag == DW_TAG_structure_type) // this only applies in C - { - clang::RecordDecl *record_decl = - ClangASTContext::GetAsRecordDecl(clang_type); - - if (record_decl) { - GetClangASTImporter().InsertRecordDecl( - record_decl, ClangASTImporter::LayoutInfo()); - } - } - } else if (clang_type_was_created) { - // Start the definition if the class is not objective C since the - // underlying decls respond to isCompleteDefinition(). Objective - // C decls don't respond to isCompleteDefinition() so we can't - // start the declaration definition right away. For C++ - // class/union/structs we want to start the definition in case the - // class is needed as the declaration context for a contained class - // or type without the need to complete that type.. - - if (attrs.class_language != eLanguageTypeObjC && - attrs.class_language != eLanguageTypeObjC_plus_plus) - ClangASTContext::StartTagDeclarationDefinition(clang_type); - - // Leave this as a forward declaration until we need to know the - // details of the type. lldb_private::Type will automatically call - // the SymbolFile virtual function - // "SymbolFileDWARF::CompleteType(Type *)" When the definition - // needs to be defined. - assert(!dwarf->GetForwardDeclClangTypeToDie().count( - ClangUtil::RemoveFastQualifiers(clang_type) - .GetOpaqueQualType()) && - "Type already in the forward declaration map!"); - // Can't assume m_ast.GetSymbolFile() is actually a - // SymbolFileDWARF, it can be a SymbolFileDWARFDebugMap for Apple - // binaries. - dwarf->GetForwardDeclDieToClangType()[die.GetDIE()] = - clang_type.GetOpaqueQualType(); - dwarf->GetForwardDeclClangTypeToDie() - [ClangUtil::RemoveFastQualifiers(clang_type).GetOpaqueQualType()] = - die.GetID(); - m_ast.SetHasExternalStorage(clang_type.GetOpaqueQualType(), true); - } - } - - // If we made a clang type, set the trivial abi if applicable: We only - // do this for pass by value - which implies the Trivial ABI. There - // isn't a way to assert that something that would normally be pass by - // value is pass by reference, so we ignore that attribute if set. - if (attrs.calling_convention == llvm::dwarf::DW_CC_pass_by_value) { - clang::CXXRecordDecl *record_decl = - m_ast.GetAsCXXRecordDecl(clang_type.GetOpaqueQualType()); - if (record_decl) { - record_decl->setHasTrivialSpecialMemberForCall(); - } - } - - if (attrs.calling_convention == llvm::dwarf::DW_CC_pass_by_reference) { - clang::CXXRecordDecl *record_decl = - m_ast.GetAsCXXRecordDecl(clang_type.GetOpaqueQualType()); - if (record_decl) - record_decl->setArgPassingRestrictions( - clang::RecordDecl::APK_CannotPassInRegs); - } - - } break; + assert((!type_sp && !clang_type) && + "Did not expect partially computed structure-like type"); + TypeSP struct_like_type_sp = ParseStructureLikeDIE(die, attrs); + return UpdateSymbolContextScopeForType(sc, die, struct_like_type_sp); + } case DW_TAG_enumeration_type: { if (attrs.is_forward_declaration) { @@ -1395,8 +1007,11 @@ TypeSP DWARFASTParserClang::ParseTypeFromDWARF(const SymbolContext &sc, is_attr_used, attrs.is_artificial); type_handled = cxx_method_decl != NULL; + // Artificial methods are always handled even when we + // don't create a new declaration for them. + type_handled |= attrs.is_artificial; - if (type_handled) { + if (cxx_method_decl) { LinkDeclContextToDIE( ClangASTContext::GetAsDeclContext(cxx_method_decl), die); @@ -1407,12 +1022,11 @@ TypeSP DWARFASTParserClang::ParseTypeFromDWARF(const SymbolContext &sc, if (!object_pointer_name.empty()) { metadata.SetObjectPtrName( object_pointer_name.c_str()); - if (log) - log->Printf( - "Setting object pointer name: %s on method " - "object %p.\n", - object_pointer_name.c_str(), - static_cast<void *>(cxx_method_decl)); + LLDB_LOGF(log, + "Setting object pointer name: %s on method " + "object %p.\n", + object_pointer_name.c_str(), + static_cast<void *>(cxx_method_decl)); } m_ast.SetMetadata(cxx_method_decl, metadata); } else { @@ -1520,11 +1134,11 @@ TypeSP DWARFASTParserClang::ParseTypeFromDWARF(const SymbolContext &sc, if (!object_pointer_name.empty()) { metadata.SetObjectPtrName(object_pointer_name.c_str()); - if (log) - log->Printf("Setting object pointer name: %s on function " - "object %p.", - object_pointer_name.c_str(), - static_cast<void *>(function_decl)); + LLDB_LOGF(log, + "Setting object pointer name: %s on function " + "object %p.", + object_pointer_name.c_str(), + static_cast<void *>(function_decl)); } m_ast.SetMetadata(function_decl, metadata); } @@ -1651,31 +1265,418 @@ TypeSP DWARFASTParserClang::ParseTypeFromDWARF(const SymbolContext &sc, break; } - if (type_sp.get()) { - DWARFDIE sc_parent_die = SymbolFileDWARF::GetParentSymbolContextDIE(die); - dw_tag_t sc_parent_tag = sc_parent_die.Tag(); + // TODO: We should consider making the switch above exhaustive to simplify + // control flow in ParseTypeFromDWARF. Then, we could simply replace this + // return statement with a call to llvm_unreachable. + return UpdateSymbolContextScopeForType(sc, die, type_sp); +} + +TypeSP DWARFASTParserClang::UpdateSymbolContextScopeForType( + const SymbolContext &sc, const DWARFDIE &die, TypeSP type_sp) { + if (!type_sp) + return type_sp; + + SymbolFileDWARF *dwarf = die.GetDWARF(); + TypeList &type_list = dwarf->GetTypeList(); + DWARFDIE sc_parent_die = SymbolFileDWARF::GetParentSymbolContextDIE(die); + dw_tag_t sc_parent_tag = sc_parent_die.Tag(); + + SymbolContextScope *symbol_context_scope = NULL; + if (sc_parent_tag == DW_TAG_compile_unit || + sc_parent_tag == DW_TAG_partial_unit) { + symbol_context_scope = sc.comp_unit; + } else if (sc.function != NULL && sc_parent_die) { + symbol_context_scope = + sc.function->GetBlock(true).FindBlockByID(sc_parent_die.GetID()); + if (symbol_context_scope == NULL) + symbol_context_scope = sc.function; + } else { + symbol_context_scope = sc.module_sp.get(); + } + + if (symbol_context_scope != NULL) + type_sp->SetSymbolContextScope(symbol_context_scope); - SymbolContextScope *symbol_context_scope = NULL; - if (sc_parent_tag == DW_TAG_compile_unit || - sc_parent_tag == DW_TAG_partial_unit) { - symbol_context_scope = sc.comp_unit; - } else if (sc.function != NULL && sc_parent_die) { - symbol_context_scope = - sc.function->GetBlock(true).FindBlockByID(sc_parent_die.GetID()); - if (symbol_context_scope == NULL) - symbol_context_scope = sc.function; - } else - symbol_context_scope = sc.module_sp.get(); + // We are ready to put this type into the uniqued list up at the module + // level. + type_list.Insert(type_sp); - if (symbol_context_scope != NULL) { - type_sp->SetSymbolContextScope(symbol_context_scope); + dwarf->GetDIEToType()[die.GetDIE()] = type_sp.get(); + return type_sp; +} + +TypeSP +DWARFASTParserClang::ParseStructureLikeDIE(const DWARFDIE &die, + ParsedDWARFTypeAttributes &attrs) { + TypeSP type_sp; + CompilerType clang_type; + const dw_tag_t tag = die.Tag(); + SymbolFileDWARF *dwarf = die.GetDWARF(); + LanguageType cu_language = die.GetLanguage(); + Log *log = LogChannelDWARF::GetLogIfAll(DWARF_LOG_TYPE_COMPLETION | + DWARF_LOG_LOOKUPS); + + // UniqueDWARFASTType is large, so don't create a local variables on the + // stack, put it on the heap. This function is often called recursively and + // clang isn't good at sharing the stack space for variables in different + // blocks. + auto unique_ast_entry_up = std::make_unique<UniqueDWARFASTType>(); + + ConstString unique_typename(attrs.name); + Declaration unique_decl(attrs.decl); + + if (attrs.name) { + if (Language::LanguageIsCPlusPlus(cu_language)) { + // For C++, we rely solely upon the one definition rule that says + // only one thing can exist at a given decl context. We ignore the + // file and line that things are declared on. + std::string qualified_name; + if (die.GetQualifiedName(qualified_name)) + unique_typename = ConstString(qualified_name); + unique_decl.Clear(); + } + + if (dwarf->GetUniqueDWARFASTTypeMap().Find( + unique_typename, die, unique_decl, attrs.byte_size.getValueOr(-1), + *unique_ast_entry_up)) { + type_sp = unique_ast_entry_up->m_type_sp; + if (type_sp) { + dwarf->GetDIEToType()[die.GetDIE()] = type_sp.get(); + LinkDeclContextToDIE( + GetCachedClangDeclContextForDIE(unique_ast_entry_up->m_die), die); + return type_sp; + } } + } - // We are ready to put this type into the uniqued list up at the module - // level - type_list->Insert(type_sp); + DEBUG_PRINTF("0x%8.8" PRIx64 ": %s (\"%s\")\n", die.GetID(), + DW_TAG_value_to_name(tag), type_name_cstr); + + int tag_decl_kind = -1; + AccessType default_accessibility = eAccessNone; + if (tag == DW_TAG_structure_type) { + tag_decl_kind = clang::TTK_Struct; + default_accessibility = eAccessPublic; + } else if (tag == DW_TAG_union_type) { + tag_decl_kind = clang::TTK_Union; + default_accessibility = eAccessPublic; + } else if (tag == DW_TAG_class_type) { + tag_decl_kind = clang::TTK_Class; + default_accessibility = eAccessPrivate; + } - dwarf->GetDIEToType()[die.GetDIE()] = type_sp.get(); + if (attrs.byte_size && *attrs.byte_size == 0 && attrs.name && + !die.HasChildren() && cu_language == eLanguageTypeObjC) { + // Work around an issue with clang at the moment where forward + // declarations for objective C classes are emitted as: + // DW_TAG_structure_type [2] + // DW_AT_name( "ForwardObjcClass" ) + // DW_AT_byte_size( 0x00 ) + // DW_AT_decl_file( "..." ) + // DW_AT_decl_line( 1 ) + // + // Note that there is no DW_AT_declaration and there are no children, + // and the byte size is zero. + attrs.is_forward_declaration = true; + } + + if (attrs.class_language == eLanguageTypeObjC || + attrs.class_language == eLanguageTypeObjC_plus_plus) { + if (!attrs.is_complete_objc_class && + die.Supports_DW_AT_APPLE_objc_complete_type()) { + // We have a valid eSymbolTypeObjCClass class symbol whose name + // matches the current objective C class that we are trying to find + // and this DIE isn't the complete definition (we checked + // is_complete_objc_class above and know it is false), so the real + // definition is in here somewhere + type_sp = + dwarf->FindCompleteObjCDefinitionTypeForDIE(die, attrs.name, true); + + if (!type_sp) { + SymbolFileDWARFDebugMap *debug_map_symfile = + dwarf->GetDebugMapSymfile(); + if (debug_map_symfile) { + // We weren't able to find a full declaration in this DWARF, + // see if we have a declaration anywhere else... + type_sp = debug_map_symfile->FindCompleteObjCDefinitionTypeForDIE( + die, attrs.name, true); + } + } + + if (type_sp) { + if (log) { + dwarf->GetObjectFile()->GetModule()->LogMessage( + log, + "SymbolFileDWARF(%p) - 0x%8.8x: %s type \"%s\" is an " + "incomplete objc type, complete type is 0x%8.8" PRIx64, + static_cast<void *>(this), die.GetOffset(), + DW_TAG_value_to_name(tag), attrs.name.GetCString(), + type_sp->GetID()); + } + + // We found a real definition for this type elsewhere so lets use + // it and cache the fact that we found a complete type for this + // die + dwarf->GetDIEToType()[die.GetDIE()] = type_sp.get(); + return type_sp; + } + } + } + + if (attrs.is_forward_declaration) { + // We have a forward declaration to a type and we need to try and + // find a full declaration. We look in the current type index just in + // case we have a forward declaration followed by an actual + // declarations in the DWARF. If this fails, we need to look + // elsewhere... + if (log) { + dwarf->GetObjectFile()->GetModule()->LogMessage( + log, + "SymbolFileDWARF(%p) - 0x%8.8x: %s type \"%s\" is a " + "forward declaration, trying to find complete type", + static_cast<void *>(this), die.GetOffset(), DW_TAG_value_to_name(tag), + attrs.name.GetCString()); + } + + // See if the type comes from a DWO module and if so, track down that + // type. + type_sp = ParseTypeFromDWO(die, log); + if (type_sp) + return type_sp; + + DWARFDeclContext die_decl_ctx; + die.GetDWARFDeclContext(die_decl_ctx); + + // type_sp = FindDefinitionTypeForDIE (dwarf_cu, die, + // type_name_const_str); + type_sp = dwarf->FindDefinitionTypeForDWARFDeclContext(die_decl_ctx); + + if (!type_sp) { + SymbolFileDWARFDebugMap *debug_map_symfile = dwarf->GetDebugMapSymfile(); + if (debug_map_symfile) { + // We weren't able to find a full declaration in this DWARF, see + // if we have a declaration anywhere else... + type_sp = debug_map_symfile->FindDefinitionTypeForDWARFDeclContext( + die_decl_ctx); + } + } + + if (type_sp) { + if (log) { + dwarf->GetObjectFile()->GetModule()->LogMessage( + log, + "SymbolFileDWARF(%p) - 0x%8.8x: %s type \"%s\" is a " + "forward declaration, complete type is 0x%8.8" PRIx64, + static_cast<void *>(this), die.GetOffset(), + DW_TAG_value_to_name(tag), attrs.name.GetCString(), + type_sp->GetID()); + } + + // We found a real definition for this type elsewhere so lets use + // it and cache the fact that we found a complete type for this die + dwarf->GetDIEToType()[die.GetDIE()] = type_sp.get(); + clang::DeclContext *defn_decl_ctx = + GetCachedClangDeclContextForDIE(dwarf->GetDIE(type_sp->GetID())); + if (defn_decl_ctx) + LinkDeclContextToDIE(defn_decl_ctx, die); + return type_sp; + } + } + assert(tag_decl_kind != -1); + bool clang_type_was_created = false; + clang_type.SetCompilerType( + &m_ast, dwarf->GetForwardDeclDieToClangType().lookup(die.GetDIE())); + if (!clang_type) { + clang::DeclContext *decl_ctx = + GetClangDeclContextContainingDIE(die, nullptr); + + // If your decl context is a record that was imported from another + // AST context (in the gmodules case), we need to make sure the type + // backing the Decl is complete before adding children to it. This is + // not an issue in the non-gmodules case because the debug info will + // always contain a full definition of parent types in that case. + CompleteExternalTagDeclType(GetClangASTImporter(), decl_ctx, die, + attrs.name.GetCString()); + + if (attrs.accessibility == eAccessNone && decl_ctx) { + // Check the decl context that contains this class/struct/union. If + // it is a class we must give it an accessibility. + const clang::Decl::Kind containing_decl_kind = decl_ctx->getDeclKind(); + if (DeclKindIsCXXClass(containing_decl_kind)) + attrs.accessibility = default_accessibility; + } + + ClangASTMetadata metadata; + metadata.SetUserID(die.GetID()); + metadata.SetIsDynamicCXXType(dwarf->ClassOrStructIsVirtual(die)); + + if (attrs.name.GetStringRef().contains('<')) { + ClangASTContext::TemplateParameterInfos template_param_infos; + if (ParseTemplateParameterInfos(die, template_param_infos)) { + clang::ClassTemplateDecl *class_template_decl = + m_ast.ParseClassTemplateDecl(decl_ctx, attrs.accessibility, + attrs.name.GetCString(), tag_decl_kind, + template_param_infos); + if (!class_template_decl) { + if (log) { + dwarf->GetObjectFile()->GetModule()->LogMessage( + log, + "SymbolFileDWARF(%p) - 0x%8.8x: %s type \"%s\" " + "clang::ClassTemplateDecl failed to return a decl.", + static_cast<void *>(this), die.GetOffset(), + DW_TAG_value_to_name(tag), attrs.name.GetCString()); + } + return TypeSP(); + } + + clang::ClassTemplateSpecializationDecl *class_specialization_decl = + m_ast.CreateClassTemplateSpecializationDecl( + decl_ctx, class_template_decl, tag_decl_kind, + template_param_infos); + clang_type = m_ast.CreateClassTemplateSpecializationType( + class_specialization_decl); + clang_type_was_created = true; + + m_ast.SetMetadata(class_template_decl, metadata); + m_ast.SetMetadata(class_specialization_decl, metadata); + } + } + + if (!clang_type_was_created) { + clang_type_was_created = true; + clang_type = m_ast.CreateRecordType( + decl_ctx, attrs.accessibility, attrs.name.GetCString(), tag_decl_kind, + attrs.class_language, &metadata); + } + } + + // Store a forward declaration to this class type in case any + // parameters in any class methods need it for the clang types for + // function prototypes. + LinkDeclContextToDIE(m_ast.GetDeclContextForType(clang_type), die); + type_sp = std::make_shared<Type>(die.GetID(), dwarf, attrs.name, + attrs.byte_size, nullptr, LLDB_INVALID_UID, + Type::eEncodingIsUID, &attrs.decl, + clang_type, Type::eResolveStateForward); + + type_sp->SetIsCompleteObjCClass(attrs.is_complete_objc_class); + + // Add our type to the unique type map so we don't end up creating many + // copies of the same type over and over in the ASTContext for our + // module + unique_ast_entry_up->m_type_sp = type_sp; + unique_ast_entry_up->m_die = die; + unique_ast_entry_up->m_declaration = unique_decl; + unique_ast_entry_up->m_byte_size = attrs.byte_size.getValueOr(0); + dwarf->GetUniqueDWARFASTTypeMap().Insert(unique_typename, + *unique_ast_entry_up); + + if (attrs.is_forward_declaration && die.HasChildren()) { + // Check to see if the DIE actually has a definition, some version of + // GCC will + // emit DIEs with DW_AT_declaration set to true, but yet still have + // subprogram, members, or inheritance, so we can't trust it + DWARFDIE child_die = die.GetFirstChild(); + while (child_die) { + switch (child_die.Tag()) { + case DW_TAG_inheritance: + case DW_TAG_subprogram: + case DW_TAG_member: + case DW_TAG_APPLE_property: + case DW_TAG_class_type: + case DW_TAG_structure_type: + case DW_TAG_enumeration_type: + case DW_TAG_typedef: + case DW_TAG_union_type: + child_die.Clear(); + attrs.is_forward_declaration = false; + break; + default: + child_die = child_die.GetSibling(); + break; + } + } + } + + if (!attrs.is_forward_declaration) { + // Always start the definition for a class type so that if the class + // has child classes or types that require the class to be created + // for use as their decl contexts the class will be ready to accept + // these child definitions. + if (!die.HasChildren()) { + // No children for this struct/union/class, lets finish it + if (ClangASTContext::StartTagDeclarationDefinition(clang_type)) { + ClangASTContext::CompleteTagDeclarationDefinition(clang_type); + } else { + dwarf->GetObjectFile()->GetModule()->ReportError( + "DWARF DIE at 0x%8.8x named \"%s\" was not able to start its " + "definition.\nPlease file a bug and attach the file at the " + "start of this error message", + die.GetOffset(), attrs.name.GetCString()); + } + + if (tag == DW_TAG_structure_type) // this only applies in C + { + clang::RecordDecl *record_decl = + ClangASTContext::GetAsRecordDecl(clang_type); + + if (record_decl) { + GetClangASTImporter().InsertRecordDecl( + record_decl, ClangASTImporter::LayoutInfo()); + } + } + } else if (clang_type_was_created) { + // Start the definition if the class is not objective C since the + // underlying decls respond to isCompleteDefinition(). Objective + // C decls don't respond to isCompleteDefinition() so we can't + // start the declaration definition right away. For C++ + // class/union/structs we want to start the definition in case the + // class is needed as the declaration context for a contained class + // or type without the need to complete that type.. + + if (attrs.class_language != eLanguageTypeObjC && + attrs.class_language != eLanguageTypeObjC_plus_plus) + ClangASTContext::StartTagDeclarationDefinition(clang_type); + + // Leave this as a forward declaration until we need to know the + // details of the type. lldb_private::Type will automatically call + // the SymbolFile virtual function + // "SymbolFileDWARF::CompleteType(Type *)" When the definition + // needs to be defined. + assert(!dwarf->GetForwardDeclClangTypeToDie().count( + ClangUtil::RemoveFastQualifiers(clang_type) + .GetOpaqueQualType()) && + "Type already in the forward declaration map!"); + // Can't assume m_ast.GetSymbolFile() is actually a + // SymbolFileDWARF, it can be a SymbolFileDWARFDebugMap for Apple + // binaries. + dwarf->GetForwardDeclDieToClangType()[die.GetDIE()] = + clang_type.GetOpaqueQualType(); + dwarf->GetForwardDeclClangTypeToDie() + [ClangUtil::RemoveFastQualifiers(clang_type).GetOpaqueQualType()] = + die.GetID(); + m_ast.SetHasExternalStorage(clang_type.GetOpaqueQualType(), true); + } + } + + // If we made a clang type, set the trivial abi if applicable: We only + // do this for pass by value - which implies the Trivial ABI. There + // isn't a way to assert that something that would normally be pass by + // value is pass by reference, so we ignore that attribute if set. + if (attrs.calling_convention == llvm::dwarf::DW_CC_pass_by_value) { + clang::CXXRecordDecl *record_decl = + m_ast.GetAsCXXRecordDecl(clang_type.GetOpaqueQualType()); + if (record_decl && record_decl->getDefinition()) { + record_decl->setHasTrivialSpecialMemberForCall(); + } + } + + if (attrs.calling_convention == llvm::dwarf::DW_CC_pass_by_reference) { + clang::CXXRecordDecl *record_decl = + m_ast.GetAsCXXRecordDecl(clang_type.GetOpaqueQualType()); + if (record_decl) + record_decl->setArgPassingRestrictions( + clang::RecordDecl::APK_CannotPassInRegs); } return type_sp; } @@ -2181,14 +2182,16 @@ bool DWARFASTParserClang::CompleteTypeFromDWARF(const DWARFDIE &die, return false; } -std::vector<DWARFDIE> DWARFASTParserClang::GetDIEForDeclContext( +void DWARFASTParserClang::EnsureAllDIEsInDeclContextHaveBeenParsed( lldb_private::CompilerDeclContext decl_context) { - std::vector<DWARFDIE> result; - for (auto it = m_decl_ctx_to_die.find( - (clang::DeclContext *)decl_context.GetOpaqueDeclContext()); - it != m_decl_ctx_to_die.end(); it++) - result.push_back(it->second); - return result; + auto opaque_decl_ctx = + (clang::DeclContext *)decl_context.GetOpaqueDeclContext(); + for (auto it = m_decl_ctx_to_die.find(opaque_decl_ctx); + it != m_decl_ctx_to_die.end() && it->first == opaque_decl_ctx; + it = m_decl_ctx_to_die.erase(it)) + for (DWARFDIE decl = it->second.GetFirstChild(); decl; + decl = decl.GetSibling()) + GetClangDeclForDIE(decl); } CompilerDecl DWARFASTParserClang::GetDeclForUIDFromDWARF(const DWARFDIE &die) { @@ -2530,9 +2533,11 @@ bool DWARFASTParserClang::ParseChildMembers( if (DWARFExpression::Evaluate( nullptr, // ExecutionContext * nullptr, // RegisterContext * - module_sp, debug_info_data, die.GetCU(), block_offset, - block_length, eRegisterKindDWARF, &initialValue, - nullptr, memberOffset, nullptr)) { + module_sp, + DataExtractor(debug_info_data, block_offset, + block_length), + die.GetCU(), eRegisterKindDWARF, &initialValue, nullptr, + memberOffset, nullptr)) { member_byte_offset = memberOffset.ResolveValue(nullptr).UInt(); } @@ -2965,11 +2970,12 @@ bool DWARFASTParserClang::ParseChildMembers( uint32_t block_length = form_value.Unsigned(); uint32_t block_offset = form_value.BlockData() - debug_info_data.GetDataStart(); - if (DWARFExpression::Evaluate(nullptr, nullptr, module_sp, - debug_info_data, die.GetCU(), - block_offset, block_length, - eRegisterKindDWARF, &initialValue, - nullptr, memberOffset, nullptr)) { + if (DWARFExpression::Evaluate( + nullptr, nullptr, module_sp, + DataExtractor(debug_info_data, block_offset, + block_length), + die.GetCU(), eRegisterKindDWARF, &initialValue, nullptr, + memberOffset, nullptr)) { member_byte_offset = memberOffset.ResolveValue(nullptr).UInt(); } @@ -3270,6 +3276,8 @@ DWARFASTParser::ParseChildArrayInfo(const DWARFDIE &parent_die, array_info.element_orders.push_back(num_elements); } } break; + default: + break; } } return array_info; @@ -3672,11 +3680,11 @@ bool DWARFASTParserClang::CopyUniqueClassMethodTypes( if (src_size != dst_size) { if (src_size != 0 && dst_size != 0) { - if (log) - log->Printf("warning: trying to unique class DIE 0x%8.8x to 0x%8.8x, " - "but they didn't have the same size (src=%d, dst=%d)", - src_class_die.GetOffset(), dst_class_die.GetOffset(), - src_size, dst_size); + LLDB_LOGF(log, + "warning: trying to unique class DIE 0x%8.8x to 0x%8.8x, " + "but they didn't have the same size (src=%d, dst=%d)", + src_class_die.GetOffset(), dst_class_die.GetOffset(), src_size, + dst_size); } fast_path = false; @@ -3690,12 +3698,12 @@ bool DWARFASTParserClang::CopyUniqueClassMethodTypes( dst_die = dst_name_to_die.GetValueAtIndexUnchecked(idx); if (src_die.Tag() != dst_die.Tag()) { - if (log) - log->Printf("warning: tried to unique class DIE 0x%8.8x to 0x%8.8x, " - "but 0x%8.8x (%s) tags didn't match 0x%8.8x (%s)", - src_class_die.GetOffset(), dst_class_die.GetOffset(), - src_die.GetOffset(), src_die.GetTagAsCString(), - dst_die.GetOffset(), dst_die.GetTagAsCString()); + LLDB_LOGF(log, + "warning: tried to unique class DIE 0x%8.8x to 0x%8.8x, " + "but 0x%8.8x (%s) tags didn't match 0x%8.8x (%s)", + src_class_die.GetOffset(), dst_class_die.GetOffset(), + src_die.GetOffset(), src_die.GetTagAsCString(), + dst_die.GetOffset(), dst_die.GetTagAsCString()); fast_path = false; } @@ -3706,12 +3714,11 @@ bool DWARFASTParserClang::CopyUniqueClassMethodTypes( if (src_name == dst_name || (strcmp(src_name, dst_name) == 0)) continue; - if (log) - log->Printf("warning: tried to unique class DIE 0x%8.8x to 0x%8.8x, " - "but 0x%8.8x (%s) names didn't match 0x%8.8x (%s)", - src_class_die.GetOffset(), dst_class_die.GetOffset(), - src_die.GetOffset(), src_name, dst_die.GetOffset(), - dst_name); + LLDB_LOGF(log, + "warning: tried to unique class DIE 0x%8.8x to 0x%8.8x, " + "but 0x%8.8x (%s) names didn't match 0x%8.8x (%s)", + src_class_die.GetOffset(), dst_class_die.GetOffset(), + src_die.GetOffset(), src_name, dst_die.GetOffset(), dst_name); fast_path = false; } @@ -3733,32 +3740,31 @@ bool DWARFASTParserClang::CopyUniqueClassMethodTypes( clang::DeclContext *src_decl_ctx = src_dwarf_ast_parser->m_die_to_decl_ctx[src_die.GetDIE()]; if (src_decl_ctx) { - if (log) - log->Printf("uniquing decl context %p from 0x%8.8x for 0x%8.8x", - static_cast<void *>(src_decl_ctx), src_die.GetOffset(), - dst_die.GetOffset()); + LLDB_LOGF(log, "uniquing decl context %p from 0x%8.8x for 0x%8.8x", + static_cast<void *>(src_decl_ctx), src_die.GetOffset(), + dst_die.GetOffset()); dst_dwarf_ast_parser->LinkDeclContextToDIE(src_decl_ctx, dst_die); } else { - if (log) - log->Printf("warning: tried to unique decl context from 0x%8.8x for " - "0x%8.8x, but none was found", - src_die.GetOffset(), dst_die.GetOffset()); + LLDB_LOGF(log, + "warning: tried to unique decl context from 0x%8.8x for " + "0x%8.8x, but none was found", + src_die.GetOffset(), dst_die.GetOffset()); } Type *src_child_type = dst_die.GetDWARF()->GetDIEToType()[src_die.GetDIE()]; if (src_child_type) { - if (log) - log->Printf( - "uniquing type %p (uid=0x%" PRIx64 ") from 0x%8.8x for 0x%8.8x", - static_cast<void *>(src_child_type), src_child_type->GetID(), - src_die.GetOffset(), dst_die.GetOffset()); + LLDB_LOGF(log, + "uniquing type %p (uid=0x%" PRIx64 + ") from 0x%8.8x for 0x%8.8x", + static_cast<void *>(src_child_type), src_child_type->GetID(), + src_die.GetOffset(), dst_die.GetOffset()); dst_die.GetDWARF()->GetDIEToType()[dst_die.GetDIE()] = src_child_type; } else { - if (log) - log->Printf("warning: tried to unique lldb_private::Type from " - "0x%8.8x for 0x%8.8x, but none was found", - src_die.GetOffset(), dst_die.GetOffset()); + LLDB_LOGF(log, + "warning: tried to unique lldb_private::Type from " + "0x%8.8x for 0x%8.8x, but none was found", + src_die.GetOffset(), dst_die.GetOffset()); } } } else { @@ -3778,39 +3784,36 @@ bool DWARFASTParserClang::CopyUniqueClassMethodTypes( clang::DeclContext *src_decl_ctx = src_dwarf_ast_parser->m_die_to_decl_ctx[src_die.GetDIE()]; if (src_decl_ctx) { - if (log) - log->Printf("uniquing decl context %p from 0x%8.8x for 0x%8.8x", - static_cast<void *>(src_decl_ctx), - src_die.GetOffset(), dst_die.GetOffset()); + LLDB_LOGF(log, "uniquing decl context %p from 0x%8.8x for 0x%8.8x", + static_cast<void *>(src_decl_ctx), src_die.GetOffset(), + dst_die.GetOffset()); dst_dwarf_ast_parser->LinkDeclContextToDIE(src_decl_ctx, dst_die); } else { - if (log) - log->Printf("warning: tried to unique decl context from 0x%8.8x " - "for 0x%8.8x, but none was found", - src_die.GetOffset(), dst_die.GetOffset()); + LLDB_LOGF(log, + "warning: tried to unique decl context from 0x%8.8x " + "for 0x%8.8x, but none was found", + src_die.GetOffset(), dst_die.GetOffset()); } Type *src_child_type = dst_die.GetDWARF()->GetDIEToType()[src_die.GetDIE()]; if (src_child_type) { - if (log) - log->Printf("uniquing type %p (uid=0x%" PRIx64 - ") from 0x%8.8x for 0x%8.8x", - static_cast<void *>(src_child_type), - src_child_type->GetID(), src_die.GetOffset(), - dst_die.GetOffset()); + LLDB_LOGF( + log, + "uniquing type %p (uid=0x%" PRIx64 ") from 0x%8.8x for 0x%8.8x", + static_cast<void *>(src_child_type), src_child_type->GetID(), + src_die.GetOffset(), dst_die.GetOffset()); dst_die.GetDWARF()->GetDIEToType()[dst_die.GetDIE()] = src_child_type; } else { - if (log) - log->Printf("warning: tried to unique lldb_private::Type from " - "0x%8.8x for 0x%8.8x, but none was found", - src_die.GetOffset(), dst_die.GetOffset()); + LLDB_LOGF(log, + "warning: tried to unique lldb_private::Type from " + "0x%8.8x for 0x%8.8x, but none was found", + src_die.GetOffset(), dst_die.GetOffset()); } } else { - if (log) - log->Printf("warning: couldn't find a match for 0x%8.8x", - dst_die.GetOffset()); + LLDB_LOGF(log, "warning: couldn't find a match for 0x%8.8x", + dst_die.GetOffset()); failures.push_back(dst_die); } @@ -3836,32 +3839,31 @@ bool DWARFASTParserClang::CopyUniqueClassMethodTypes( clang::DeclContext *src_decl_ctx = src_dwarf_ast_parser->m_die_to_decl_ctx[src_die.GetDIE()]; if (src_decl_ctx) { - if (log) - log->Printf("uniquing decl context %p from 0x%8.8x for 0x%8.8x", - static_cast<void *>(src_decl_ctx), src_die.GetOffset(), - dst_die.GetOffset()); + LLDB_LOGF(log, "uniquing decl context %p from 0x%8.8x for 0x%8.8x", + static_cast<void *>(src_decl_ctx), src_die.GetOffset(), + dst_die.GetOffset()); dst_dwarf_ast_parser->LinkDeclContextToDIE(src_decl_ctx, dst_die); } else { - if (log) - log->Printf("warning: tried to unique decl context from 0x%8.8x " - "for 0x%8.8x, but none was found", - src_die.GetOffset(), dst_die.GetOffset()); + LLDB_LOGF(log, + "warning: tried to unique decl context from 0x%8.8x " + "for 0x%8.8x, but none was found", + src_die.GetOffset(), dst_die.GetOffset()); } Type *src_child_type = dst_die.GetDWARF()->GetDIEToType()[src_die.GetDIE()]; if (src_child_type) { - if (log) - log->Printf( - "uniquing type %p (uid=0x%" PRIx64 ") from 0x%8.8x for 0x%8.8x", - static_cast<void *>(src_child_type), src_child_type->GetID(), - src_die.GetOffset(), dst_die.GetOffset()); + LLDB_LOGF( + log, + "uniquing type %p (uid=0x%" PRIx64 ") from 0x%8.8x for 0x%8.8x", + static_cast<void *>(src_child_type), src_child_type->GetID(), + src_die.GetOffset(), dst_die.GetOffset()); dst_die.GetDWARF()->GetDIEToType()[dst_die.GetDIE()] = src_child_type; } else { - if (log) - log->Printf("warning: tried to unique lldb_private::Type from " - "0x%8.8x for 0x%8.8x, but none was found", - src_die.GetOffset(), dst_die.GetOffset()); + LLDB_LOGF(log, + "warning: tried to unique lldb_private::Type from " + "0x%8.8x for 0x%8.8x, but none was found", + src_die.GetOffset(), dst_die.GetOffset()); } } } @@ -3872,10 +3874,10 @@ bool DWARFASTParserClang::CopyUniqueClassMethodTypes( ConstString dst_name_artificial = dst_name_to_die_artificial.GetCStringAtIndex(idx); dst_die = dst_name_to_die_artificial.GetValueAtIndexUnchecked(idx); - if (log) - log->Printf("warning: need to create artificial method for 0x%8.8x for " - "method '%s'", - dst_die.GetOffset(), dst_name_artificial.GetCString()); + LLDB_LOGF(log, + "warning: need to create artificial method for 0x%8.8x for " + "method '%s'", + dst_die.GetOffset(), dst_name_artificial.GetCString()); failures.push_back(dst_die); } diff --git a/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.h b/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.h index 5b5d83d65932..106f9254a449 100644 --- a/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.h +++ b/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.h @@ -15,7 +15,10 @@ #include "llvm/ADT/SmallVector.h" #include "DWARFASTParser.h" +#include "DWARFDIE.h" #include "DWARFDefines.h" +#include "DWARFFormValue.h" +#include "LogChannelDWARF.h" #include "lldb/Core/ClangForward.h" #include "lldb/Core/PluginInterface.h" #include "lldb/Symbol/ClangASTContext.h" @@ -29,6 +32,8 @@ class CompileUnit; class DWARFDebugInfoEntry; class SymbolFileDWARF; +struct ParsedDWARFTypeAttributes; + class DWARFASTParserClang : public DWARFASTParser { public: DWARFASTParserClang(lldb_private::ClangASTContext &ast); @@ -37,7 +42,7 @@ public: // DWARFASTParser interface. lldb::TypeSP ParseTypeFromDWARF(const lldb_private::SymbolContext &sc, - const DWARFDIE &die, lldb_private::Log *log, + const DWARFDIE &die, bool *type_is_new_ptr) override; lldb_private::Function * @@ -51,8 +56,8 @@ public: lldb_private::CompilerDecl GetDeclForUIDFromDWARF(const DWARFDIE &die) override; - std::vector<DWARFDIE> - GetDIEForDeclContext(lldb_private::CompilerDeclContext decl_context) override; + void EnsureAllDIEsInDeclContextHaveBeenParsed( + lldb_private::CompilerDeclContext decl_context) override; lldb_private::CompilerDeclContext GetDeclContextForUIDFromDWARF(const DWARFDIE &die) override; @@ -63,9 +68,28 @@ public: lldb_private::ClangASTImporter &GetClangASTImporter(); protected: + /// Protected typedefs and members. + /// @{ class DelayedAddObjCClassProperty; typedef std::vector<DelayedAddObjCClassProperty> DelayedPropertyList; + typedef llvm::SmallPtrSet<const DWARFDebugInfoEntry *, 4> DIEPointerSet; + typedef llvm::DenseMap<const DWARFDebugInfoEntry *, clang::DeclContext *> + DIEToDeclContextMap; + typedef std::multimap<const clang::DeclContext *, const DWARFDIE> + DeclContextToDIEMap; + typedef llvm::DenseMap<const DWARFDebugInfoEntry *, clang::Decl *> + DIEToDeclMap; + typedef llvm::DenseMap<const clang::Decl *, DIEPointerSet> DeclToDIEMap; + + lldb_private::ClangASTContext &m_ast; + DIEToDeclMap m_die_to_decl; + DeclToDIEMap m_decl_to_die; + DIEToDeclContextMap m_die_to_decl_ctx; + DeclContextToDIEMap m_decl_ctx_to_die; + std::unique_ptr<lldb_private::ClangASTImporter> m_clang_ast_importer_up; + /// @} + clang::DeclContext *GetDeclContextForBlock(const DWARFDIE &die); clang::BlockDecl *ResolveBlockDIE(const DWARFDIE &die); @@ -103,6 +127,10 @@ protected: bool is_signed, uint32_t enumerator_byte_size, const DWARFDIE &parent_die); + /// Parse a structure, class, or union type DIE. + lldb::TypeSP ParseStructureLikeDIE(const DWARFDIE &die, + ParsedDWARFTypeAttributes &attrs); + lldb_private::Type *GetTypeForDIE(const DWARFDIE &die); clang::Decl *GetClangDeclForDIE(const DWARFDIE &die); @@ -123,29 +151,52 @@ protected: void LinkDeclToDIE(clang::Decl *decl, const DWARFDIE &die); + /// If \p type_sp is valid, calculate and set its symbol context scope, and + /// update the type list for its backing symbol file. + /// + /// Returns \p type_sp. + lldb::TypeSP + UpdateSymbolContextScopeForType(const lldb_private::SymbolContext &sc, + const DWARFDIE &die, lldb::TypeSP type_sp); + lldb::TypeSP ParseTypeFromDWO(const DWARFDIE &die, lldb_private::Log *log); // Return true if this type is a declaration to a type in an external // module. lldb::ModuleSP GetModuleForType(const DWARFDIE &die); +}; - typedef llvm::SmallPtrSet<const DWARFDebugInfoEntry *, 4> DIEPointerSet; - typedef llvm::DenseMap<const DWARFDebugInfoEntry *, clang::DeclContext *> - DIEToDeclContextMap; - // typedef llvm::DenseMap<const clang::DeclContext *, DIEPointerSet> - // DeclContextToDIEMap; - typedef std::multimap<const clang::DeclContext *, const DWARFDIE> - DeclContextToDIEMap; - typedef llvm::DenseMap<const DWARFDebugInfoEntry *, clang::Decl *> - DIEToDeclMap; - typedef llvm::DenseMap<const clang::Decl *, DIEPointerSet> DeclToDIEMap; - - lldb_private::ClangASTContext &m_ast; - DIEToDeclMap m_die_to_decl; - DeclToDIEMap m_decl_to_die; - DIEToDeclContextMap m_die_to_decl_ctx; - DeclContextToDIEMap m_decl_ctx_to_die; - std::unique_ptr<lldb_private::ClangASTImporter> m_clang_ast_importer_up; +/// Parsed form of all attributes that are relevant for type reconstruction. +/// Some attributes are relevant for all kinds of types (declaration), while +/// others are only meaningful to a specific type (is_virtual) +struct ParsedDWARFTypeAttributes { + explicit ParsedDWARFTypeAttributes(const DWARFDIE &die); + + lldb::AccessType accessibility = lldb::eAccessNone; + bool is_artificial = false; + bool is_complete_objc_class = false; + bool is_explicit = false; + bool is_forward_declaration = false; + bool is_inline = false; + bool is_scoped_enum = false; + bool is_vector = false; + bool is_virtual = false; + clang::StorageClass storage = clang::SC_None; + const char *mangled_name = nullptr; + lldb_private::ConstString name; + lldb_private::Declaration decl; + DWARFDIE object_pointer; + DWARFFormValue abstract_origin; + DWARFFormValue containing_type; + DWARFFormValue signature; + DWARFFormValue specification; + DWARFFormValue type; + lldb::LanguageType class_language = lldb::eLanguageTypeUnknown; + llvm::Optional<uint64_t> byte_size; + size_t calling_convention = llvm::dwarf::DW_CC_normal; + uint32_t bit_stride = 0; + uint32_t byte_stride = 0; + uint32_t encoding = 0; }; #endif // SymbolFileDWARF_DWARFASTParserClang_h_ diff --git a/source/Plugins/SymbolFile/DWARF/DWARFAbbreviationDeclaration.cpp b/source/Plugins/SymbolFile/DWARF/DWARFAbbreviationDeclaration.cpp index 6128163a2926..741669b05754 100644 --- a/source/Plugins/SymbolFile/DWARF/DWARFAbbreviationDeclaration.cpp +++ b/source/Plugins/SymbolFile/DWARF/DWARFAbbreviationDeclaration.cpp @@ -18,7 +18,8 @@ using namespace lldb_private; DWARFAbbreviationDeclaration::DWARFAbbreviationDeclaration() - : m_code(InvalidCode), m_tag(0), m_has_children(0), m_attributes() {} + : m_code(InvalidCode), m_tag(llvm::dwarf::DW_TAG_null), m_has_children(0), + m_attributes() {} DWARFAbbreviationDeclaration::DWARFAbbreviationDeclaration(dw_tag_t tag, uint8_t has_children) @@ -33,7 +34,7 @@ DWARFAbbreviationDeclaration::extract(const DWARFDataExtractor &data, return DWARFEnumState::Complete; m_attributes.clear(); - m_tag = data.GetULEB128(offset_ptr); + m_tag = static_cast<dw_tag_t>(data.GetULEB128(offset_ptr)); if (m_tag == DW_TAG_null) return llvm::make_error<llvm::object::GenericBinaryError>( "abbrev decl requires non-null tag."); @@ -68,7 +69,7 @@ DWARFAbbreviationDeclaration::extract(const DWARFDataExtractor &data, } bool DWARFAbbreviationDeclaration::IsValid() { - return m_code != 0 && m_tag != 0; + return m_code != 0 && m_tag != llvm::dwarf::DW_TAG_null; } uint32_t diff --git a/source/Plugins/SymbolFile/DWARF/DWARFBaseDIE.cpp b/source/Plugins/SymbolFile/DWARF/DWARFBaseDIE.cpp index 96adb72c9532..033105efdc53 100644 --- a/source/Plugins/SymbolFile/DWARF/DWARFBaseDIE.cpp +++ b/source/Plugins/SymbolFile/DWARF/DWARFBaseDIE.cpp @@ -14,6 +14,7 @@ #include "lldb/Core/Module.h" #include "lldb/Symbol/ObjectFile.h" +#include "lldb/Utility/Log.h" using namespace lldb_private; @@ -29,7 +30,7 @@ dw_tag_t DWARFBaseDIE::Tag() const { if (m_die) return m_die->Tag(); else - return 0; + return llvm::dwarf::DW_TAG_null; } const char *DWARFBaseDIE::GetTagAsCString() const { @@ -102,19 +103,22 @@ SymbolFileDWARF *DWARFBaseDIE::GetDWARF() const { return nullptr; } -lldb_private::TypeSystem *DWARFBaseDIE::GetTypeSystem() const { - if (m_cu) - return m_cu->GetTypeSystem(); - else - return nullptr; +llvm::Expected<lldb_private::TypeSystem &> DWARFBaseDIE::GetTypeSystem() const { + if (!m_cu) + return llvm::make_error<llvm::StringError>( + "Unable to get TypeSystem, no compilation unit available", + llvm::inconvertibleErrorCode()); + return m_cu->GetTypeSystem(); } DWARFASTParser *DWARFBaseDIE::GetDWARFParser() const { - lldb_private::TypeSystem *type_system = GetTypeSystem(); - if (type_system) - return type_system->GetDWARFParser(); - else + auto type_system_or_err = GetTypeSystem(); + if (auto err = type_system_or_err.takeError()) { + LLDB_LOG_ERROR(lldb_private::GetLogIfAnyCategoriesSet(LIBLLDB_LOG_SYMBOLS), + std::move(err), "Unable to get DWARFASTParser"); return nullptr; + } + return type_system_or_err->GetDWARFParser(); } bool DWARFBaseDIE::HasChildren() const { diff --git a/source/Plugins/SymbolFile/DWARF/DWARFBaseDIE.h b/source/Plugins/SymbolFile/DWARF/DWARFBaseDIE.h index 0058043017cd..9652d7946e87 100644 --- a/source/Plugins/SymbolFile/DWARF/DWARFBaseDIE.h +++ b/source/Plugins/SymbolFile/DWARF/DWARFBaseDIE.h @@ -12,6 +12,8 @@ #include "lldb/Core/dwarf.h" #include "lldb/lldb-types.h" +#include "llvm/Support/Error.h" + class DIERef; class DWARFASTParser; class DWARFAttributes; @@ -55,7 +57,7 @@ public: llvm::Optional<DIERef> GetDIERef() const; - lldb_private::TypeSystem *GetTypeSystem() const; + llvm::Expected<lldb_private::TypeSystem &> GetTypeSystem() const; DWARFASTParser *GetDWARFParser() const; diff --git a/source/Plugins/SymbolFile/DWARF/DWARFDIE.cpp b/source/Plugins/SymbolFile/DWARF/DWARFDIE.cpp index 9d97ca15a252..5ee0687995a1 100644 --- a/source/Plugins/SymbolFile/DWARF/DWARFDIE.cpp +++ b/source/Plugins/SymbolFile/DWARF/DWARFDIE.cpp @@ -342,7 +342,8 @@ void DWARFDIE::GetDWARFDeclContext(DWARFDeclContext &dwarf_decl_ctx) const { } } -void DWARFDIE::GetDeclContext(std::vector<CompilerContext> &context) const { +void DWARFDIE::GetDeclContext( + llvm::SmallVectorImpl<lldb_private::CompilerContext> &context) const { const dw_tag_t tag = Tag(); if (tag == DW_TAG_compile_unit || tag == DW_TAG_partial_unit) return; @@ -351,40 +352,33 @@ void DWARFDIE::GetDeclContext(std::vector<CompilerContext> &context) const { parent.GetDeclContext(context); switch (tag) { case DW_TAG_module: - context.push_back( - CompilerContext(CompilerContextKind::Module, ConstString(GetName()))); + context.push_back({CompilerContextKind::Module, ConstString(GetName())}); break; case DW_TAG_namespace: - context.push_back(CompilerContext(CompilerContextKind::Namespace, - ConstString(GetName()))); + context.push_back({CompilerContextKind::Namespace, ConstString(GetName())}); break; case DW_TAG_structure_type: - context.push_back(CompilerContext(CompilerContextKind::Structure, - ConstString(GetName()))); + context.push_back({CompilerContextKind::Struct, ConstString(GetName())}); break; case DW_TAG_union_type: - context.push_back( - CompilerContext(CompilerContextKind::Union, ConstString(GetName()))); + context.push_back({CompilerContextKind::Union, ConstString(GetName())}); break; case DW_TAG_class_type: - context.push_back( - CompilerContext(CompilerContextKind::Class, ConstString(GetName()))); + context.push_back({CompilerContextKind::Class, ConstString(GetName())}); break; case DW_TAG_enumeration_type: - context.push_back(CompilerContext(CompilerContextKind::Enumeration, - ConstString(GetName()))); + context.push_back({CompilerContextKind::Enum, ConstString(GetName())}); break; case DW_TAG_subprogram: - context.push_back(CompilerContext(CompilerContextKind::Function, - ConstString(GetPubname()))); + context.push_back( + {CompilerContextKind::Function, ConstString(GetPubname())}); break; case DW_TAG_variable: - context.push_back(CompilerContext(CompilerContextKind::Variable, - ConstString(GetPubname()))); + context.push_back( + {CompilerContextKind::Variable, ConstString(GetPubname())}); break; case DW_TAG_typedef: - context.push_back( - CompilerContext(CompilerContextKind::Typedef, ConstString(GetName()))); + context.push_back({CompilerContextKind::Typedef, ConstString(GetName())}); break; default: break; diff --git a/source/Plugins/SymbolFile/DWARF/DWARFDIE.h b/source/Plugins/SymbolFile/DWARF/DWARFDIE.h index 7753ec9008cb..a779c589611a 100644 --- a/source/Plugins/SymbolFile/DWARF/DWARFDIE.h +++ b/source/Plugins/SymbolFile/DWARF/DWARFDIE.h @@ -78,8 +78,8 @@ public: /// Return this DIE's decl context as it is needed to look up types /// in Clang's -gmodules debug info format. - void - GetDeclContext(std::vector<lldb_private::CompilerContext> &context) const; + void GetDeclContext( + llvm::SmallVectorImpl<lldb_private::CompilerContext> &context) const; // Getting attribute values from the DIE. // diff --git a/source/Plugins/SymbolFile/DWARF/DWARFDebugAranges.cpp b/source/Plugins/SymbolFile/DWARF/DWARFDebugAranges.cpp index ccf33e6dc341..c8da2381353e 100644 --- a/source/Plugins/SymbolFile/DWARF/DWARFDebugAranges.cpp +++ b/source/Plugins/SymbolFile/DWARF/DWARFDebugAranges.cpp @@ -66,8 +66,8 @@ void DWARFDebugAranges::Dump(Log *log) const { for (size_t i = 0; i < num_entries; ++i) { const RangeToDIE::Entry *entry = m_aranges.GetEntryAtIndex(i); if (entry) - log->Printf("0x%8.8x: [0x%" PRIx64 " - 0x%" PRIx64 ")", entry->data, - entry->GetRangeBase(), entry->GetRangeEnd()); + LLDB_LOGF(log, "0x%8.8x: [0x%" PRIx64 " - 0x%" PRIx64 ")", entry->data, + entry->GetRangeBase(), entry->GetRangeEnd()); } } diff --git a/source/Plugins/SymbolFile/DWARF/DWARFDebugInfo.cpp b/source/Plugins/SymbolFile/DWARF/DWARFDebugInfo.cpp index 100f35f8c6b0..1e04baca2c58 100644 --- a/source/Plugins/SymbolFile/DWARF/DWARFDebugInfo.cpp +++ b/source/Plugins/SymbolFile/DWARF/DWARFDebugInfo.cpp @@ -38,7 +38,7 @@ llvm::Expected<DWARFDebugAranges &> DWARFDebugInfo::GetCompileUnitAranges() { if (m_cu_aranges_up) return *m_cu_aranges_up; - m_cu_aranges_up = llvm::make_unique<DWARFDebugAranges>(); + m_cu_aranges_up = std::make_unique<DWARFDebugAranges>(); const DWARFDataExtractor &debug_aranges_data = m_context.getOrLoadArangesData(); if (llvm::Error error = m_cu_aranges_up->extract(debug_aranges_data)) diff --git a/source/Plugins/SymbolFile/DWARF/DWARFDebugInfoEntry.cpp b/source/Plugins/SymbolFile/DWARF/DWARFDebugInfoEntry.cpp index 2f55b7d40ed9..8c0fbeb4b717 100644 --- a/source/Plugins/SymbolFile/DWARF/DWARFDebugInfoEntry.cpp +++ b/source/Plugins/SymbolFile/DWARF/DWARFDebugInfoEntry.cpp @@ -192,7 +192,7 @@ bool DWARFDebugInfoEntry::Extract(const DWARFDataExtractor &data, *offset_ptr = offset; return true; } else { - m_tag = 0; + m_tag = llvm::dwarf::DW_TAG_null; m_has_children = false; return true; // NULL debug tag entry } @@ -340,18 +340,14 @@ bool DWARFDebugInfoEntry::GetDIENamesAndRanges( uint32_t block_offset = form_value.BlockData() - data.GetDataStart(); uint32_t block_length = form_value.Unsigned(); - *frame_base = DWARFExpression(module, data, cu, - block_offset, block_length); + *frame_base = DWARFExpression( + module, DataExtractor(data, block_offset, block_length), cu); } else { - const DWARFDataExtractor &debug_loc_data = dwarf.DebugLocData(); - const dw_offset_t debug_loc_offset = form_value.Unsigned(); - - size_t loc_list_length = DWARFExpression::LocationListSize( - cu, debug_loc_data, debug_loc_offset); - if (loc_list_length > 0) { - *frame_base = - DWARFExpression(module, debug_loc_data, cu, - debug_loc_offset, loc_list_length); + DataExtractor data = dwarf.DebugLocData(); + const dw_offset_t offset = form_value.Unsigned(); + if (data.ValidOffset(offset)) { + data = DataExtractor(data, offset, data.GetByteSize() - offset); + *frame_base = DWARFExpression(module, data, cu); if (lo_pc != LLDB_INVALID_ADDRESS) { assert(lo_pc >= cu->GetBaseAddress()); frame_base->SetLocationListSlide(lo_pc - diff --git a/source/Plugins/SymbolFile/DWARF/DWARFDebugInfoEntry.h b/source/Plugins/SymbolFile/DWARF/DWARFDebugInfoEntry.h index 1e7b5f27642d..25c885608d85 100644 --- a/source/Plugins/SymbolFile/DWARF/DWARFDebugInfoEntry.h +++ b/source/Plugins/SymbolFile/DWARF/DWARFDebugInfoEntry.h @@ -31,7 +31,7 @@ public: DWARFDebugInfoEntry() : m_offset(DW_INVALID_OFFSET), m_parent_idx(0), m_sibling_idx(0), - m_has_children(false), m_abbr_idx(0), m_tag(0) {} + m_has_children(false), m_abbr_idx(0), m_tag(llvm::dwarf::DW_TAG_null) {} explicit operator bool() const { return m_offset != DW_INVALID_OFFSET; } bool operator==(const DWARFDebugInfoEntry &rhs) const; @@ -178,8 +178,9 @@ protected: // a single NULL terminating child. m_has_children : 1; uint16_t m_abbr_idx; - uint16_t m_tag; // A copy of the DW_TAG value so we don't have to go through - // the compile unit abbrev table + /// A copy of the DW_TAG value so we don't have to go through the compile + /// unit abbrev table + dw_tag_t m_tag = llvm::dwarf::DW_TAG_null; }; #endif // SymbolFileDWARF_DWARFDebugInfoEntry_h_ diff --git a/source/Plugins/SymbolFile/DWARF/DWARFDebugLine.cpp b/source/Plugins/SymbolFile/DWARF/DWARFDebugLine.cpp deleted file mode 100644 index 953089fee22b..000000000000 --- a/source/Plugins/SymbolFile/DWARF/DWARFDebugLine.cpp +++ /dev/null @@ -1,1038 +0,0 @@ -//===-- DWARFDebugLine.cpp --------------------------------------*- C++ -*-===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// - -#include "DWARFDebugLine.h" - -//#define ENABLE_DEBUG_PRINTF // DO NOT LEAVE THIS DEFINED: DEBUG ONLY!!! -#include <assert.h> - -#include <memory> - -#include "lldb/Core/FileSpecList.h" -#include "lldb/Core/Module.h" -#include "lldb/Host/Host.h" -#include "lldb/Utility/Log.h" -#include "lldb/Utility/Timer.h" - -#include "DWARFUnit.h" -#include "LogChannelDWARF.h" -#include "SymbolFileDWARF.h" - -using namespace lldb; -using namespace lldb_private; -using namespace std; - -// Parse -// -// Parse all information in the debug_line_data into an internal -// representation. -void DWARFDebugLine::Parse(const DWARFDataExtractor &debug_line_data) { - m_lineTableMap.clear(); - lldb::offset_t offset = 0; - LineTable::shared_ptr line_table_sp(new LineTable); - while (debug_line_data.ValidOffset(offset)) { - const lldb::offset_t debug_line_offset = offset; - - if (line_table_sp.get() == nullptr) - break; - - if (ParseStatementTable(debug_line_data, &offset, line_table_sp.get(), nullptr)) { - // Make sure we don't don't loop infinitely - if (offset <= debug_line_offset) - break; - // DEBUG_PRINTF("m_lineTableMap[0x%8.8x] = line_table_sp\n", - // debug_line_offset); - m_lineTableMap[debug_line_offset] = line_table_sp; - line_table_sp = std::make_shared<LineTable>(); - } else - ++offset; // Try next byte in line table - } -} - -void DWARFDebugLine::ParseIfNeeded(const DWARFDataExtractor &debug_line_data) { - if (m_lineTableMap.empty()) - Parse(debug_line_data); -} - -// DWARFDebugLine::GetLineTable -DWARFDebugLine::LineTable::shared_ptr -DWARFDebugLine::GetLineTable(const dw_offset_t offset) const { - DWARFDebugLine::LineTable::shared_ptr line_table_shared_ptr; - LineTableConstIter pos = m_lineTableMap.find(offset); - if (pos != m_lineTableMap.end()) - line_table_shared_ptr = pos->second; - return line_table_shared_ptr; -} - -// Parse -// -// Parse the entire line table contents calling callback each time a new -// prologue is parsed and every time a new row is to be added to the line -// table. -void DWARFDebugLine::Parse(const DWARFDataExtractor &debug_line_data, - DWARFDebugLine::State::Callback callback, - void *userData) { - lldb::offset_t offset = 0; - if (debug_line_data.ValidOffset(offset)) { - if (!ParseStatementTable(debug_line_data, &offset, callback, userData, nullptr)) - ++offset; // Skip to next byte in .debug_line section - } -} - -namespace { -struct EntryDescriptor { - dw_sleb128_t code; - dw_sleb128_t form; -}; - -static std::vector<EntryDescriptor> -ReadDescriptors(const DWARFDataExtractor &debug_line_data, - lldb::offset_t *offset_ptr) { - std::vector<EntryDescriptor> ret; - uint8_t n = debug_line_data.GetU8(offset_ptr); - for (uint8_t i = 0; i < n; ++i) { - EntryDescriptor ent; - ent.code = debug_line_data.GetULEB128(offset_ptr); - ent.form = debug_line_data.GetULEB128(offset_ptr); - ret.push_back(ent); - } - return ret; -} -} // namespace - -// DWARFDebugLine::ParsePrologue -bool DWARFDebugLine::ParsePrologue(const DWARFDataExtractor &debug_line_data, - lldb::offset_t *offset_ptr, - Prologue *prologue, DWARFUnit *dwarf_cu) { - const lldb::offset_t prologue_offset = *offset_ptr; - - // DEBUG_PRINTF("0x%8.8x: ParsePrologue()\n", *offset_ptr); - - prologue->Clear(); - uint32_t i; - const char *s; - prologue->total_length = debug_line_data.GetDWARFInitialLength(offset_ptr); - prologue->version = debug_line_data.GetU16(offset_ptr); - if (prologue->version < 2 || prologue->version > 5) - return false; - - if (prologue->version >= 5) { - prologue->address_size = debug_line_data.GetU8(offset_ptr); - prologue->segment_selector_size = debug_line_data.GetU8(offset_ptr); - } - - prologue->prologue_length = debug_line_data.GetDWARFOffset(offset_ptr); - const lldb::offset_t end_prologue_offset = - prologue->prologue_length + *offset_ptr; - prologue->min_inst_length = debug_line_data.GetU8(offset_ptr); - if (prologue->version >= 4) - prologue->maximum_operations_per_instruction = - debug_line_data.GetU8(offset_ptr); - else - prologue->maximum_operations_per_instruction = 1; - prologue->default_is_stmt = debug_line_data.GetU8(offset_ptr); - prologue->line_base = debug_line_data.GetU8(offset_ptr); - prologue->line_range = debug_line_data.GetU8(offset_ptr); - prologue->opcode_base = debug_line_data.GetU8(offset_ptr); - - prologue->standard_opcode_lengths.reserve(prologue->opcode_base - 1); - - for (i = 1; i < prologue->opcode_base; ++i) { - uint8_t op_len = debug_line_data.GetU8(offset_ptr); - prologue->standard_opcode_lengths.push_back(op_len); - } - - if (prologue->version >= 5) { - std::vector<EntryDescriptor> dirEntryFormatV = - ReadDescriptors(debug_line_data, offset_ptr); - uint8_t dirCount = debug_line_data.GetULEB128(offset_ptr); - for (int i = 0; i < dirCount; ++i) { - for (EntryDescriptor &ent : dirEntryFormatV) { - DWARFFormValue value(dwarf_cu, ent.form); - if (ent.code != DW_LNCT_path) { - if (!value.SkipValue(debug_line_data, offset_ptr)) - return false; - continue; - } - - if (!value.ExtractValue(debug_line_data, offset_ptr)) - return false; - prologue->include_directories.push_back(value.AsCString()); - } - } - - std::vector<EntryDescriptor> filesEntryFormatV = - ReadDescriptors(debug_line_data, offset_ptr); - llvm::DenseSet<std::pair<uint64_t, uint64_t>> seen; - uint8_t n = debug_line_data.GetULEB128(offset_ptr); - for (int i = 0; i < n; ++i) { - FileNameEntry entry; - for (EntryDescriptor &ent : filesEntryFormatV) { - DWARFFormValue value(dwarf_cu, ent.form); - if (!value.ExtractValue(debug_line_data, offset_ptr)) - return false; - - switch (ent.code) { - case DW_LNCT_path: - entry.name = value.AsCString(); - break; - case DW_LNCT_directory_index: - entry.dir_idx = value.Unsigned(); - break; - case DW_LNCT_timestamp: - entry.mod_time = value.Unsigned(); - break; - case DW_LNCT_size: - entry.length = value.Unsigned(); - break; - case DW_LNCT_MD5: - assert(value.Unsigned() == 16); - std::uninitialized_copy_n(value.BlockData(), 16, - entry.checksum.Bytes.begin()); - break; - default: - break; - } - } - - if (seen.insert(entry.checksum.words()).second) - prologue->file_names.push_back(entry); - } - } else { - while (*offset_ptr < end_prologue_offset) { - s = debug_line_data.GetCStr(offset_ptr); - if (s && s[0]) - prologue->include_directories.push_back(s); - else - break; - } - - while (*offset_ptr < end_prologue_offset) { - const char *name = debug_line_data.GetCStr(offset_ptr); - if (name && name[0]) { - FileNameEntry fileEntry; - fileEntry.name = name; - fileEntry.dir_idx = debug_line_data.GetULEB128(offset_ptr); - fileEntry.mod_time = debug_line_data.GetULEB128(offset_ptr); - fileEntry.length = debug_line_data.GetULEB128(offset_ptr); - prologue->file_names.push_back(fileEntry); - } else - break; - } - } - - // XXX GNU as is broken for 64-Bit DWARF - if (*offset_ptr != end_prologue_offset) { - Host::SystemLog(Host::eSystemLogWarning, - "warning: parsing line table prologue at 0x%8.8" PRIx64 - " should have ended at 0x%8.8" PRIx64 - " but it ended at 0x%8.8" PRIx64 "\n", - prologue_offset, end_prologue_offset, *offset_ptr); - } - return end_prologue_offset; -} - -bool DWARFDebugLine::ParseSupportFiles( - const lldb::ModuleSP &module_sp, const DWARFDataExtractor &debug_line_data, - dw_offset_t stmt_list, FileSpecList &support_files, DWARFUnit *dwarf_cu) { - lldb::offset_t offset = stmt_list; - - Prologue prologue; - if (!ParsePrologue(debug_line_data, &offset, &prologue, dwarf_cu)) { - Host::SystemLog(Host::eSystemLogError, "error: parsing line table prologue " - "at 0x%8.8x (parsing ended around " - "0x%8.8" PRIx64 "\n", - stmt_list, offset); - return false; - } - - FileSpec file_spec; - std::string remapped_file; - - for (uint32_t file_idx = 1; - prologue.GetFile(file_idx, dwarf_cu->GetCompilationDirectory(), - dwarf_cu->GetPathStyle(), file_spec); - ++file_idx) { - if (module_sp->RemapSourceFile(file_spec.GetPath(), remapped_file)) - file_spec.SetFile(remapped_file, FileSpec::Style::native); - support_files.Append(file_spec); - } - return true; -} - -// ParseStatementTable -// -// Parse a single line table (prologue and all rows) and call the callback -// function once for the prologue (row in state will be zero) and each time a -// row is to be added to the line table. -bool DWARFDebugLine::ParseStatementTable( - const DWARFDataExtractor &debug_line_data, lldb::offset_t *offset_ptr, - DWARFDebugLine::State::Callback callback, void *userData, DWARFUnit *dwarf_cu) { - Log *log(LogChannelDWARF::GetLogIfAll(DWARF_LOG_DEBUG_LINE)); - Prologue::shared_ptr prologue(new Prologue()); - - const dw_offset_t debug_line_offset = *offset_ptr; - - static Timer::Category func_cat(LLVM_PRETTY_FUNCTION); - Timer scoped_timer( - func_cat, "DWARFDebugLine::ParseStatementTable (.debug_line[0x%8.8x])", - debug_line_offset); - - if (!ParsePrologue(debug_line_data, offset_ptr, prologue.get(), dwarf_cu)) { - if (log) - log->Error("failed to parse DWARF line table prologue"); - // Restore our offset and return false to indicate failure! - *offset_ptr = debug_line_offset; - return false; - } - - if (log) - prologue->Dump(log); - - const dw_offset_t end_offset = - debug_line_offset + prologue->total_length + - (debug_line_data.GetDWARFSizeofInitialLength()); - - State state(prologue, log, callback, userData); - - while (*offset_ptr < end_offset) { - // DEBUG_PRINTF("0x%8.8x: ", *offset_ptr); - uint8_t opcode = debug_line_data.GetU8(offset_ptr); - - if (opcode == 0) { - // Extended Opcodes always start with a zero opcode followed by a uleb128 - // length so you can skip ones you don't know about - lldb::offset_t ext_offset = *offset_ptr; - dw_uleb128_t len = debug_line_data.GetULEB128(offset_ptr); - dw_offset_t arg_size = len - (*offset_ptr - ext_offset); - - // DEBUG_PRINTF("Extended: <%2u> ", len); - uint8_t sub_opcode = debug_line_data.GetU8(offset_ptr); - switch (sub_opcode) { - case DW_LNE_end_sequence: - // Set the end_sequence register of the state machine to true and - // append a row to the matrix using the current values of the state- - // machine registers. Then reset the registers to the initial values - // specified above. Every statement program sequence must end with a - // DW_LNE_end_sequence instruction which creates a row whose address is - // that of the byte after the last target machine instruction of the - // sequence. - state.end_sequence = true; - state.AppendRowToMatrix(*offset_ptr); - state.Reset(); - break; - - case DW_LNE_set_address: - // Takes a single relocatable address as an operand. The size of the - // operand is the size appropriate to hold an address on the target - // machine. Set the address register to the value given by the - // relocatable address. All of the other statement program opcodes that - // affect the address register add a delta to it. This instruction - // stores a relocatable value into it instead. - if (arg_size == 4) - state.address = debug_line_data.GetU32(offset_ptr); - else // arg_size == 8 - state.address = debug_line_data.GetU64(offset_ptr); - break; - - case DW_LNE_define_file: - // Takes 4 arguments. The first is a null terminated string containing - // a source file name. The second is an unsigned LEB128 number - // representing the directory index of the directory in which the file - // was found. The third is an unsigned LEB128 number representing the - // time of last modification of the file. The fourth is an unsigned - // LEB128 number representing the length in bytes of the file. The time - // and length fields may contain LEB128(0) if the information is not - // available. - // - // The directory index represents an entry in the include_directories - // section of the statement program prologue. The index is LEB128(0) if - // the file was found in the current directory of the compilation, - // LEB128(1) if it was found in the first directory in the - // include_directories section, and so on. The directory index is - // ignored for file names that represent full path names. - // - // The files are numbered, starting at 1, in the order in which they - // appear; the names in the prologue come before names defined by the - // DW_LNE_define_file instruction. These numbers are used in the file - // register of the state machine. - { - FileNameEntry fileEntry; - fileEntry.name = debug_line_data.GetCStr(offset_ptr); - fileEntry.dir_idx = debug_line_data.GetULEB128(offset_ptr); - fileEntry.mod_time = debug_line_data.GetULEB128(offset_ptr); - fileEntry.length = debug_line_data.GetULEB128(offset_ptr); - state.prologue->file_names.push_back(fileEntry); - } - break; - - default: - // Length doesn't include the zero opcode byte or the length itself, - // but it does include the sub_opcode, so we have to adjust for that - // below - (*offset_ptr) += arg_size; - break; - } - } else if (opcode < prologue->opcode_base) { - switch (opcode) { - // Standard Opcodes - case DW_LNS_copy: - // Takes no arguments. Append a row to the matrix using the current - // values of the state-machine registers. Then set the basic_block - // register to false. - state.AppendRowToMatrix(*offset_ptr); - break; - - case DW_LNS_advance_pc: - // Takes a single unsigned LEB128 operand, multiplies it by the - // min_inst_length field of the prologue, and adds the result to the - // address register of the state machine. - state.address += - debug_line_data.GetULEB128(offset_ptr) * prologue->min_inst_length; - break; - - case DW_LNS_advance_line: - // Takes a single signed LEB128 operand and adds that value to the line - // register of the state machine. - state.line += debug_line_data.GetSLEB128(offset_ptr); - break; - - case DW_LNS_set_file: - // Takes a single unsigned LEB128 operand and stores it in the file - // register of the state machine. - state.file = debug_line_data.GetULEB128(offset_ptr); - break; - - case DW_LNS_set_column: - // Takes a single unsigned LEB128 operand and stores it in the column - // register of the state machine. - state.column = debug_line_data.GetULEB128(offset_ptr); - break; - - case DW_LNS_negate_stmt: - // Takes no arguments. Set the is_stmt register of the state machine to - // the logical negation of its current value. - state.is_stmt = !state.is_stmt; - break; - - case DW_LNS_set_basic_block: - // Takes no arguments. Set the basic_block register of the state - // machine to true - state.basic_block = true; - break; - - case DW_LNS_const_add_pc: - // Takes no arguments. Add to the address register of the state machine - // the address increment value corresponding to special opcode 255. The - // motivation for DW_LNS_const_add_pc is this: when the statement - // program needs to advance the address by a small amount, it can use a - // single special opcode, which occupies a single byte. When it needs - // to advance the address by up to twice the range of the last special - // opcode, it can use DW_LNS_const_add_pc followed by a special opcode, - // for a total of two bytes. Only if it needs to advance the address by - // more than twice that range will it need to use both - // DW_LNS_advance_pc and a special opcode, requiring three or more - // bytes. - { - uint8_t adjust_opcode = 255 - prologue->opcode_base; - dw_addr_t addr_offset = (adjust_opcode / prologue->line_range) * - prologue->min_inst_length; - state.address += addr_offset; - } - break; - - case DW_LNS_fixed_advance_pc: - // Takes a single uhalf operand. Add to the address register of the - // state machine the value of the (unencoded) operand. This is the only - // extended opcode that takes an argument that is not a variable length - // number. The motivation for DW_LNS_fixed_advance_pc is this: existing - // assemblers cannot emit DW_LNS_advance_pc or special opcodes because - // they cannot encode LEB128 numbers or judge when the computation of a - // special opcode overflows and requires the use of DW_LNS_advance_pc. - // Such assemblers, however, can use DW_LNS_fixed_advance_pc instead, - // sacrificing compression. - state.address += debug_line_data.GetU16(offset_ptr); - break; - - case DW_LNS_set_prologue_end: - // Takes no arguments. Set the prologue_end register of the state - // machine to true - state.prologue_end = true; - break; - - case DW_LNS_set_epilogue_begin: - // Takes no arguments. Set the basic_block register of the state - // machine to true - state.epilogue_begin = true; - break; - - case DW_LNS_set_isa: - // Takes a single unsigned LEB128 operand and stores it in the column - // register of the state machine. - state.isa = debug_line_data.GetULEB128(offset_ptr); - break; - - default: - // Handle any unknown standard opcodes here. We know the lengths of - // such opcodes because they are specified in the prologue as a - // multiple of LEB128 operands for each opcode. - { - uint8_t i; - assert(static_cast<size_t>(opcode - 1) < - prologue->standard_opcode_lengths.size()); - const uint8_t opcode_length = - prologue->standard_opcode_lengths[opcode - 1]; - for (i = 0; i < opcode_length; ++i) - debug_line_data.Skip_LEB128(offset_ptr); - } - break; - } - } else { - // Special Opcodes - - // A special opcode value is chosen based on the amount that needs - // to be added to the line and address registers. The maximum line - // increment for a special opcode is the value of the line_base field in - // the header, plus the value of the line_range field, minus 1 (line base - // + line range - 1). If the desired line increment is greater than the - // maximum line increment, a standard opcode must be used instead of a - // special opcode. The "address advance" is calculated by dividing the - // desired address increment by the minimum_instruction_length field from - // the header. The special opcode is then calculated using the following - // formula: - // - // opcode = (desired line increment - line_base) + (line_range * address - // advance) + opcode_base - // - // If the resulting opcode is greater than 255, a standard opcode must be - // used instead. - // - // To decode a special opcode, subtract the opcode_base from the opcode - // itself to give the adjusted opcode. The amount to increment the - // address register is the result of the adjusted opcode divided by the - // line_range multiplied by the minimum_instruction_length field from the - // header. That is: - // - // address increment = (adjusted opcode / line_range) * - // minimum_instruction_length - // - // The amount to increment the line register is the line_base plus the - // result of the adjusted opcode modulo the line_range. That is: - // - // line increment = line_base + (adjusted opcode % line_range) - - uint8_t adjust_opcode = opcode - prologue->opcode_base; - dw_addr_t addr_offset = - (adjust_opcode / prologue->line_range) * prologue->min_inst_length; - int32_t line_offset = - prologue->line_base + (adjust_opcode % prologue->line_range); - state.line += line_offset; - state.address += addr_offset; - state.AppendRowToMatrix(*offset_ptr); - } - } - - state.Finalize(*offset_ptr); - - return end_offset; -} - -// ParseStatementTableCallback -static void ParseStatementTableCallback(dw_offset_t offset, - const DWARFDebugLine::State &state, - void *userData) { - DWARFDebugLine::LineTable *line_table = (DWARFDebugLine::LineTable *)userData; - if (state.row == DWARFDebugLine::State::StartParsingLineTable) { - // Just started parsing the line table, so lets keep a reference to the - // prologue using the supplied shared pointer - line_table->prologue = state.prologue; - } else if (state.row == DWARFDebugLine::State::DoneParsingLineTable) { - // Done parsing line table, nothing to do for the cleanup - } else { - // We have a new row, lets append it - line_table->AppendRow(state); - } -} - -// ParseStatementTable -// -// Parse a line table at offset and populate the LineTable class with the -// prologue and all rows. -bool DWARFDebugLine::ParseStatementTable( - const DWARFDataExtractor &debug_line_data, lldb::offset_t *offset_ptr, - LineTable *line_table, DWARFUnit *dwarf_cu) { - return ParseStatementTable(debug_line_data, offset_ptr, - ParseStatementTableCallback, line_table, dwarf_cu); -} - -inline bool DWARFDebugLine::Prologue::IsValid() const { - return SymbolFileDWARF::SupportedVersion(version); -} - -// DWARFDebugLine::Prologue::Dump -void DWARFDebugLine::Prologue::Dump(Log *log) { - uint32_t i; - - log->Printf("Line table prologue:"); - log->Printf(" total_length: 0x%8.8x", total_length); - log->Printf(" version: %u", version); - log->Printf("prologue_length: 0x%8.8x", prologue_length); - log->Printf("min_inst_length: %u", min_inst_length); - log->Printf("default_is_stmt: %u", default_is_stmt); - log->Printf(" line_base: %i", line_base); - log->Printf(" line_range: %u", line_range); - log->Printf(" opcode_base: %u", opcode_base); - - for (i = 0; i < standard_opcode_lengths.size(); ++i) { - log->Printf("standard_opcode_lengths[%s] = %u", DW_LNS_value_to_name(i + 1), - standard_opcode_lengths[i]); - } - - if (!include_directories.empty()) { - for (i = 0; i < include_directories.size(); ++i) { - log->Printf("include_directories[%3u] = '%s'", i + 1, - include_directories[i]); - } - } - - if (!file_names.empty()) { - log->PutCString(" Dir Mod Time File Len File Name"); - log->PutCString(" ---- ---------- ---------- " - "---------------------------"); - for (i = 0; i < file_names.size(); ++i) { - const FileNameEntry &fileEntry = file_names[i]; - log->Printf("file_names[%3u] %4u 0x%8.8x 0x%8.8x %s", i + 1, - fileEntry.dir_idx, fileEntry.mod_time, fileEntry.length, - fileEntry.name); - } - } -} - -// DWARFDebugLine::ParsePrologue::Append -// -// Append the contents of the prologue to the binary stream buffer -// void -// DWARFDebugLine::Prologue::Append(BinaryStreamBuf& buff) const -//{ -// uint32_t i; -// -// buff.Append32(total_length); -// buff.Append16(version); -// buff.Append32(prologue_length); -// buff.Append8(min_inst_length); -// buff.Append8(default_is_stmt); -// buff.Append8(line_base); -// buff.Append8(line_range); -// buff.Append8(opcode_base); -// -// for (i=0; i<standard_opcode_lengths.size(); ++i) -// buff.Append8(standard_opcode_lengths[i]); -// -// for (i=0; i<include_directories.size(); ++i) -// buff.AppendCStr(include_directories[i].c_str()); -// buff.Append8(0); // Terminate the include directory section with empty -// string -// -// for (i=0; i<file_names.size(); ++i) -// { -// buff.AppendCStr(file_names[i].name.c_str()); -// buff.Append32_as_ULEB128(file_names[i].dir_idx); -// buff.Append32_as_ULEB128(file_names[i].mod_time); -// buff.Append32_as_ULEB128(file_names[i].length); -// } -// buff.Append8(0); // Terminate the file names section with empty string -//} - -bool DWARFDebugLine::Prologue::GetFile(uint32_t file_idx, - const FileSpec &comp_dir, - FileSpec::Style style, - FileSpec &file) const { - uint32_t idx = file_idx - 1; // File indexes are 1 based... - if (idx < file_names.size()) { - file.SetFile(file_names[idx].name, style); - if (file.IsRelative()) { - if (file_names[idx].dir_idx > 0) { - const uint32_t dir_idx = file_names[idx].dir_idx - 1; - if (dir_idx < include_directories.size()) { - file.PrependPathComponent(include_directories[dir_idx]); - if (!file.IsRelative()) - return true; - } - } - - if (comp_dir) - file.PrependPathComponent(comp_dir); - } - return true; - } - return false; -} - -void DWARFDebugLine::LineTable::AppendRow(const DWARFDebugLine::Row &state) { - rows.push_back(state); -} - -// Compare function for the binary search in -// DWARFDebugLine::LineTable::LookupAddress() -static bool FindMatchingAddress(const DWARFDebugLine::Row &row1, - const DWARFDebugLine::Row &row2) { - return row1.address < row2.address; -} - -// DWARFDebugLine::LineTable::LookupAddress -uint32_t DWARFDebugLine::LineTable::LookupAddress(dw_addr_t address, - dw_addr_t cu_high_pc) const { - uint32_t index = UINT32_MAX; - if (!rows.empty()) { - // Use the lower_bound algorithm to perform a binary search since we know - // that our line table data is ordered by address. - DWARFDebugLine::Row row; - row.address = address; - Row::const_iterator begin_pos = rows.begin(); - Row::const_iterator end_pos = rows.end(); - Row::const_iterator pos = - lower_bound(begin_pos, end_pos, row, FindMatchingAddress); - if (pos == end_pos) { - if (address < cu_high_pc) - return rows.size() - 1; - } else { - // Rely on fact that we are using a std::vector and we can do pointer - // arithmetic to find the row index (which will be one less that what we - // found since it will find the first position after the current address) - // since std::vector iterators are just pointers to the container type. - index = pos - begin_pos; - if (pos->address > address) { - if (index > 0) - --index; - else - index = UINT32_MAX; - } - } - } - return index; // Failed to find address -} - -// DWARFDebugLine::Row::Row -DWARFDebugLine::Row::Row(bool default_is_stmt) - : address(0), line(1), column(0), file(1), is_stmt(default_is_stmt), - basic_block(false), end_sequence(false), prologue_end(false), - epilogue_begin(false), isa(0) {} - -// Called after a row is appended to the matrix -void DWARFDebugLine::Row::PostAppend() { - basic_block = false; - prologue_end = false; - epilogue_begin = false; -} - -// DWARFDebugLine::Row::Reset -void DWARFDebugLine::Row::Reset(bool default_is_stmt) { - address = 0; - line = 1; - column = 0; - file = 1; - is_stmt = default_is_stmt; - basic_block = false; - end_sequence = false; - prologue_end = false; - epilogue_begin = false; - isa = 0; -} -// DWARFDebugLine::Row::Dump -void DWARFDebugLine::Row::Dump(Log *log) const { - log->Printf("0x%16.16" PRIx64 " %6u %6u %6u %3u %s%s%s%s%s", address, line, - column, file, isa, is_stmt ? " is_stmt" : "", - basic_block ? " basic_block" : "", - prologue_end ? " prologue_end" : "", - epilogue_begin ? " epilogue_begin" : "", - end_sequence ? " end_sequence" : ""); -} - -// Compare function LineTable structures -static bool AddressLessThan(const DWARFDebugLine::Row &a, - const DWARFDebugLine::Row &b) { - return a.address < b.address; -} - -// Insert a row at the correct address if the addresses can be out of order -// which can only happen when we are linking a line table that may have had -// it's contents rearranged. -void DWARFDebugLine::Row::Insert(Row::collection &state_coll, - const Row &state) { - // If we don't have anything yet, or if the address of the last state in our - // line table is less than the current one, just append the current state - if (state_coll.empty() || AddressLessThan(state_coll.back(), state)) { - state_coll.push_back(state); - } else { - // Do a binary search for the correct entry - pair<Row::iterator, Row::iterator> range(equal_range( - state_coll.begin(), state_coll.end(), state, AddressLessThan)); - - // If the addresses are equal, we can safely replace the previous entry - // with the current one if the one it is replacing is an end_sequence - // entry. We currently always place an extra end sequence when ever we exit - // a valid address range for a function in case the functions get - // rearranged by optimizations or by order specifications. These extra end - // sequences will disappear by getting replaced with valid consecutive - // entries within a compile unit if there are no gaps. - if (range.first == range.second) { - state_coll.insert(range.first, state); - } else { - if ((distance(range.first, range.second) == 1) && - range.first->end_sequence == true) { - *range.first = state; - } else { - state_coll.insert(range.second, state); - } - } - } -} - -// DWARFDebugLine::State::State -DWARFDebugLine::State::State(Prologue::shared_ptr &p, Log *l, - DWARFDebugLine::State::Callback cb, void *userData) - : Row(p->default_is_stmt), prologue(p), log(l), callback(cb), - callbackUserData(userData), row(StartParsingLineTable) { - // Call the callback with the initial row state of zero for the prologue - if (callback) - callback(0, *this, callbackUserData); -} - -// DWARFDebugLine::State::Reset -void DWARFDebugLine::State::Reset() { Row::Reset(prologue->default_is_stmt); } - -// DWARFDebugLine::State::AppendRowToMatrix -void DWARFDebugLine::State::AppendRowToMatrix(dw_offset_t offset) { - // Each time we are to add an entry into the line table matrix call the - // callback function so that someone can do something with the current state - // of the state machine (like build a line table or dump the line table!) - if (log) { - if (row == 0) { - log->PutCString("Address Line Column File ISA Flags"); - log->PutCString( - "------------------ ------ ------ ------ --- -------------"); - } - Dump(log); - } - - ++row; // Increase the row number before we call our callback for a real row - if (callback) - callback(offset, *this, callbackUserData); - PostAppend(); -} - -// DWARFDebugLine::State::Finalize -void DWARFDebugLine::State::Finalize(dw_offset_t offset) { - // Call the callback with a special row state when we are done parsing a line - // table - row = DoneParsingLineTable; - if (callback) - callback(offset, *this, callbackUserData); -} - -// void -// DWARFDebugLine::AppendLineTableData -//( -// const DWARFDebugLine::Prologue* prologue, -// const DWARFDebugLine::Row::collection& state_coll, -// const uint32_t addr_size, -// BinaryStreamBuf &debug_line_data -//) -//{ -// if (state_coll.empty()) -// { -// // We have no entries, just make an empty line table -// debug_line_data.Append8(0); -// debug_line_data.Append8(1); -// debug_line_data.Append8(DW_LNE_end_sequence); -// } -// else -// { -// DWARFDebugLine::Row::const_iterator pos; -// Row::const_iterator end = state_coll.end(); -// bool default_is_stmt = prologue->default_is_stmt; -// const DWARFDebugLine::Row reset_state(default_is_stmt); -// const DWARFDebugLine::Row* prev_state = &reset_state; -// const int32_t max_line_increment_for_special_opcode = -// prologue->MaxLineIncrementForSpecialOpcode(); -// for (pos = state_coll.begin(); pos != end; ++pos) -// { -// const DWARFDebugLine::Row& curr_state = *pos; -// int32_t line_increment = 0; -// dw_addr_t addr_offset = curr_state.address - prev_state->address; -// dw_addr_t addr_advance = (addr_offset) / prologue->min_inst_length; -// line_increment = (int32_t)(curr_state.line - prev_state->line); -// -// // If our previous state was the reset state, then let's emit the -// // address to keep GDB's DWARF parser happy. If we don't start each -// // sequence with a DW_LNE_set_address opcode, the line table won't -// // get slid properly in GDB. -// -// if (prev_state == &reset_state) -// { -// debug_line_data.Append8(0); // Extended opcode -// debug_line_data.Append32_as_ULEB128(addr_size + 1); // Length of -// opcode bytes -// debug_line_data.Append8(DW_LNE_set_address); -// debug_line_data.AppendMax64(curr_state.address, addr_size); -// addr_advance = 0; -// } -// -// if (prev_state->file != curr_state.file) -// { -// debug_line_data.Append8(DW_LNS_set_file); -// debug_line_data.Append32_as_ULEB128(curr_state.file); -// } -// -// if (prev_state->column != curr_state.column) -// { -// debug_line_data.Append8(DW_LNS_set_column); -// debug_line_data.Append32_as_ULEB128(curr_state.column); -// } -// -// // Don't do anything fancy if we are at the end of a sequence -// // as we don't want to push any extra rows since the -// DW_LNE_end_sequence -// // will push a row itself! -// if (curr_state.end_sequence) -// { -// if (line_increment != 0) -// { -// debug_line_data.Append8(DW_LNS_advance_line); -// debug_line_data.Append32_as_SLEB128(line_increment); -// } -// -// if (addr_advance > 0) -// { -// debug_line_data.Append8(DW_LNS_advance_pc); -// debug_line_data.Append32_as_ULEB128(addr_advance); -// } -// -// // Now push the end sequence on! -// debug_line_data.Append8(0); -// debug_line_data.Append8(1); -// debug_line_data.Append8(DW_LNE_end_sequence); -// -// prev_state = &reset_state; -// } -// else -// { -// if (line_increment || addr_advance) -// { -// if (line_increment > max_line_increment_for_special_opcode) -// { -// debug_line_data.Append8(DW_LNS_advance_line); -// debug_line_data.Append32_as_SLEB128(line_increment); -// line_increment = 0; -// } -// -// uint32_t special_opcode = (line_increment >= -// prologue->line_base) ? ((line_increment - -// prologue->line_base) + (prologue->line_range * addr_advance) -// + prologue->opcode_base) : 256; -// if (special_opcode > 255) -// { -// // Both the address and line won't fit in one special -// opcode -// // check to see if just the line advance will? -// uint32_t special_opcode_line = ((line_increment >= -// prologue->line_base) && (line_increment != 0)) ? -// ((line_increment - prologue->line_base) + -// prologue->opcode_base) : 256; -// -// -// if (special_opcode_line > 255) -// { -// // Nope, the line advance won't fit by itself, check -// the address increment by itself -// uint32_t special_opcode_addr = addr_advance ? -// ((0 - prologue->line_base) + -// (prologue->line_range * addr_advance) + -// prologue->opcode_base) : 256; -// -// if (special_opcode_addr > 255) -// { -// // Neither the address nor the line will fit in -// a -// // special opcode, we must manually enter both -// then -// // do a DW_LNS_copy to push a row (special -// opcode -// // automatically imply a new row is pushed) -// if (line_increment != 0) -// { -// debug_line_data.Append8(DW_LNS_advance_line); -// debug_line_data.Append32_as_SLEB128(line_increment); -// } -// -// if (addr_advance > 0) -// { -// debug_line_data.Append8(DW_LNS_advance_pc); -// debug_line_data.Append32_as_ULEB128(addr_advance); -// } -// -// // Now push a row onto the line table manually -// debug_line_data.Append8(DW_LNS_copy); -// -// } -// else -// { -// // The address increment alone will fit into a -// special opcode -// // so modify our line change, then issue a -// special opcode -// // for the address increment and it will push a -// row into the -// // line table -// if (line_increment != 0) -// { -// debug_line_data.Append8(DW_LNS_advance_line); -// debug_line_data.Append32_as_SLEB128(line_increment); -// } -// -// // Advance of line and address will fit into a -// single byte special opcode -// // and this will also push a row onto the line -// table -// debug_line_data.Append8(special_opcode_addr); -// } -// } -// else -// { -// // The line change alone will fit into a special -// opcode -// // so modify our address increment first, then issue -// a -// // special opcode for the line change and it will -// push -// // a row into the line table -// if (addr_advance > 0) -// { -// debug_line_data.Append8(DW_LNS_advance_pc); -// debug_line_data.Append32_as_ULEB128(addr_advance); -// } -// -// // Advance of line and address will fit into a -// single byte special opcode -// // and this will also push a row onto the line table -// debug_line_data.Append8(special_opcode_line); -// } -// } -// else -// { -// // Advance of line and address will fit into a single -// byte special opcode -// // and this will also push a row onto the line table -// debug_line_data.Append8(special_opcode); -// } -// } -// prev_state = &curr_state; -// } -// } -// } -//} diff --git a/source/Plugins/SymbolFile/DWARF/DWARFDebugLine.h b/source/Plugins/SymbolFile/DWARF/DWARFDebugLine.h deleted file mode 100644 index 0d236ca686b5..000000000000 --- a/source/Plugins/SymbolFile/DWARF/DWARFDebugLine.h +++ /dev/null @@ -1,227 +0,0 @@ -//===-- DWARFDebugLine.h ----------------------------------------*- C++ -*-===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// - -#ifndef SymbolFileDWARF_DWARFDebugLine_h_ -#define SymbolFileDWARF_DWARFDebugLine_h_ - -#include <map> -#include <string> -#include <vector> - -#include "lldb/Utility/FileSpec.h" -#include "lldb/lldb-private.h" - -#include "DWARFDataExtractor.h" -#include "DWARFDefines.h" - -#include "llvm/Support/MD5.h" - -class DWARFUnit; -class SymbolFileDWARF; - -// DWARFDebugLine -class DWARFDebugLine { -public: - // FileNameEntry - struct FileNameEntry { - FileNameEntry() - : name(nullptr), dir_idx(0), mod_time(0), length(0), checksum() {} - - const char *name; - dw_sleb128_t dir_idx; - dw_sleb128_t mod_time; - dw_sleb128_t length; - llvm::MD5::MD5Result checksum; - }; - - // Prologue - struct Prologue { - - Prologue() - : total_length(0), version(0), prologue_length(0), min_inst_length(0), - default_is_stmt(0), line_base(0), line_range(0), opcode_base(0), - standard_opcode_lengths(), include_directories(), file_names() {} - - typedef std::shared_ptr<Prologue> shared_ptr; - - uint32_t total_length; // The size in bytes of the statement information for - // this compilation unit (not including the - // total_length field itself). - uint16_t - version; // Version identifier for the statement information format. - - uint8_t address_size; - uint8_t segment_selector_size; - - uint32_t prologue_length; // The number of bytes following the - // prologue_length field to the beginning of the - // first byte of the statement program itself. - uint8_t min_inst_length; // The size in bytes of the smallest target machine - // instruction. Statement program opcodes that - // alter the address register first multiply their - // operands by this value. - uint8_t maximum_operations_per_instruction; // New in DWARF4. The maximum - // number of individual - // operations that may be - // encoded in an instruction. - uint8_t default_is_stmt; // The initial value of theis_stmtregister. - int8_t line_base; // This parameter affects the meaning of the special - // opcodes. See below. - uint8_t line_range; // This parameter affects the meaning of the special - // opcodes. See below. - uint8_t opcode_base; // The number assigned to the first special opcode. - std::vector<uint8_t> standard_opcode_lengths; - std::vector<const char *> include_directories; - std::vector<FileNameEntry> file_names; - - int32_t MaxLineIncrementForSpecialOpcode() const { - return line_base + (int8_t)line_range - 1; - } - bool IsValid() const; - // void Append(BinaryStreamBuf& buff) const; - void Dump(lldb_private::Log *log); - void Clear() { - total_length = version = prologue_length = min_inst_length = line_base = - line_range = opcode_base = 0; - line_base = 0; - standard_opcode_lengths.clear(); - include_directories.clear(); - file_names.clear(); - } - bool GetFile(uint32_t file_idx, const lldb_private::FileSpec &cu_comp_dir, - lldb_private::FileSpec::Style style, - lldb_private::FileSpec &file) const; - }; - - // Standard .debug_line state machine structure - struct Row { - typedef std::vector<Row> collection; - typedef collection::iterator iterator; - typedef collection::const_iterator const_iterator; - - Row(bool default_is_stmt = false); - virtual ~Row() {} - void PostAppend(); - void Reset(bool default_is_stmt); - void Dump(lldb_private::Log *log) const; - static void Insert(Row::collection &state_coll, const Row &state); - - dw_addr_t address; // The program-counter value corresponding to a machine - // instruction generated by the compiler. - uint32_t line; // An unsigned integer indicating a source line number. Lines - // are numbered beginning at 1. The compiler may emit the - // value 0 in cases where an instruction cannot be attributed - // to any source line. - uint16_t column; // An unsigned integer indicating a column number within a - // source line. Columns are numbered beginning at 1. The - // value 0 is reserved to indicate that a statement begins - // at the 'left edge' of the line. - uint16_t file; // An unsigned integer indicating the identity of the source - // file corresponding to a machine instruction. - uint8_t is_stmt : 1, // A boolean indicating that the current instruction is - // the beginning of a statement. - basic_block : 1, // A boolean indicating that the current instruction is - // the beginning of a basic block. - end_sequence : 1, // A boolean indicating that the current address is - // that of the first byte after the end of a sequence - // of target machine instructions. - prologue_end : 1, // A boolean indicating that the current address is - // one (of possibly many) where execution should be - // suspended for an entry breakpoint of a function. - epilogue_begin : 1; // A boolean indicating that the current address is - // one (of possibly many) where execution should be - // suspended for an exit breakpoint of a function. - uint32_t isa; // An unsigned integer whose value encodes the applicable - // instruction set architecture for the current instruction. - }; - - // LineTable - struct LineTable { - typedef std::shared_ptr<LineTable> shared_ptr; - - LineTable() : prologue(), rows() {} - - void AppendRow(const DWARFDebugLine::Row &state); - void Clear() { - prologue.reset(); - rows.clear(); - } - - uint32_t LookupAddress(dw_addr_t address, dw_addr_t cu_high_pc) const; - - Prologue::shared_ptr prologue; - Row::collection rows; - }; - - // State - struct State : public Row { - typedef void (*Callback)(dw_offset_t offset, const State &state, - void *userData); - - // Special row codes used when calling the callback - enum { StartParsingLineTable = 0, DoneParsingLineTable = -1 }; - - State(Prologue::shared_ptr &prologue_sp, lldb_private::Log *log, - Callback callback, void *userData); - - void AppendRowToMatrix(dw_offset_t offset); - - void Finalize(dw_offset_t offset); - - void Reset(); - - Prologue::shared_ptr prologue; - lldb_private::Log *log; - Callback callback; // Callback function that gets called each time an entry - // is to be added to the matrix - void *callbackUserData; - int row; // The row number that starts at zero for the prologue, and - // increases for each row added to the matrix - private: - DISALLOW_COPY_AND_ASSIGN(State); - }; - - static bool - ParseSupportFiles(const lldb::ModuleSP &module_sp, - const lldb_private::DWARFDataExtractor &debug_line_data, - dw_offset_t stmt_list, - lldb_private::FileSpecList &support_files, - DWARFUnit *dwarf_cu); - static bool - ParsePrologue(const lldb_private::DWARFDataExtractor &debug_line_data, - lldb::offset_t *offset_ptr, Prologue *prologue, - DWARFUnit *dwarf_cu = nullptr); - static bool - ParseStatementTable(const lldb_private::DWARFDataExtractor &debug_line_data, - lldb::offset_t *offset_ptr, State::Callback callback, - void *userData, DWARFUnit *dwarf_cu); - static bool - ParseStatementTable(const lldb_private::DWARFDataExtractor &debug_line_data, - lldb::offset_t *offset_ptr, LineTable *line_table, - DWARFUnit *dwarf_cu); - static void Parse(const lldb_private::DWARFDataExtractor &debug_line_data, - DWARFDebugLine::State::Callback callback, void *userData); - // static void AppendLineTableData(const DWARFDebugLine::Prologue* prologue, - // const DWARFDebugLine::Row::collection& state_coll, const uint32_t - // addr_size, BinaryStreamBuf &debug_line_data); - - DWARFDebugLine() : m_lineTableMap() {} - - void Parse(const lldb_private::DWARFDataExtractor &debug_line_data); - void ParseIfNeeded(const lldb_private::DWARFDataExtractor &debug_line_data); - LineTable::shared_ptr GetLineTable(const dw_offset_t offset) const; - -protected: - typedef std::map<dw_offset_t, LineTable::shared_ptr> LineTableMap; - typedef LineTableMap::iterator LineTableIter; - typedef LineTableMap::const_iterator LineTableConstIter; - - LineTableMap m_lineTableMap; -}; - -#endif // SymbolFileDWARF_DWARFDebugLine_h_ diff --git a/source/Plugins/SymbolFile/DWARF/DWARFDebugRanges.cpp b/source/Plugins/SymbolFile/DWARF/DWARFDebugRanges.cpp index 207c71211c9a..0b08fa09f906 100644 --- a/source/Plugins/SymbolFile/DWARF/DWARFDebugRanges.cpp +++ b/source/Plugins/SymbolFile/DWARF/DWARFDebugRanges.cpp @@ -123,11 +123,6 @@ bool DWARFDebugRanges::FindRanges(const DWARFUnit *cu, return false; } -uint64_t DWARFDebugRanges::GetOffset(size_t Index) const { - lldbassert(false && "DW_FORM_rnglistx is not present before DWARF5"); - return 0; -} - bool DWARFDebugRngLists::ExtractRangeList( const DWARFDataExtractor &data, uint8_t addrSize, lldb::offset_t *offset_ptr, std::vector<RngListEntry> &rangeList) { diff --git a/source/Plugins/SymbolFile/DWARF/DWARFDebugRanges.h b/source/Plugins/SymbolFile/DWARF/DWARFDebugRanges.h index baf2667f0afe..c398259056b3 100644 --- a/source/Plugins/SymbolFile/DWARF/DWARFDebugRanges.h +++ b/source/Plugins/SymbolFile/DWARF/DWARFDebugRanges.h @@ -24,7 +24,6 @@ public: virtual void Extract(lldb_private::DWARFContext &context) = 0; virtual bool FindRanges(const DWARFUnit *cu, dw_offset_t debug_ranges_offset, DWARFRangeList &range_list) const = 0; - virtual uint64_t GetOffset(size_t Index) const = 0; }; class DWARFDebugRanges final : public DWARFDebugRangesBase { @@ -34,7 +33,6 @@ public: void Extract(lldb_private::DWARFContext &context) override; bool FindRanges(const DWARFUnit *cu, dw_offset_t debug_ranges_offset, DWARFRangeList &range_list) const override; - uint64_t GetOffset(size_t Index) const override; static void Dump(lldb_private::Stream &s, const lldb_private::DWARFDataExtractor &debug_ranges_data, @@ -62,7 +60,7 @@ public: void Extract(lldb_private::DWARFContext &context) override; bool FindRanges(const DWARFUnit *cu, dw_offset_t debug_ranges_offset, DWARFRangeList &range_list) const override; - uint64_t GetOffset(size_t Index) const override; + uint64_t GetOffset(size_t Index) const; protected: bool ExtractRangeList(const lldb_private::DWARFDataExtractor &data, diff --git a/source/Plugins/SymbolFile/DWARF/DWARFDeclContext.h b/source/Plugins/SymbolFile/DWARF/DWARFDeclContext.h index d0d70dd5123e..6501ac27f27d 100644 --- a/source/Plugins/SymbolFile/DWARF/DWARFDeclContext.h +++ b/source/Plugins/SymbolFile/DWARF/DWARFDeclContext.h @@ -23,7 +23,7 @@ class DWARFDeclContext { public: struct Entry { - Entry() : tag(0), name(nullptr) {} + Entry() : tag(llvm::dwarf::DW_TAG_null), name(nullptr) {} Entry(dw_tag_t t, const char *n) : tag(t), name(n) {} bool NameMatches(const Entry &rhs) const { diff --git a/source/Plugins/SymbolFile/DWARF/DWARFDefines.cpp b/source/Plugins/SymbolFile/DWARF/DWARFDefines.cpp index 3bf0bb088227..2ae1bbc9f507 100644 --- a/source/Plugins/SymbolFile/DWARF/DWARFDefines.cpp +++ b/source/Plugins/SymbolFile/DWARF/DWARFDefines.cpp @@ -59,6 +59,8 @@ const char *DW_OP_value_to_name(uint32_t val) { } DRC_class DW_OP_value_to_class(uint32_t val) { + // FIXME: If we just used llvm's DWARFExpression printer, we could delete + // all this code (and more in lldb's DWARFExpression.cpp). switch (val) { case 0x03: return DRC_ONEOPERAND; @@ -358,6 +360,8 @@ DRC_class DW_OP_value_to_class(uint32_t val) { return DRC_DWARFv3 | DRC_ONEOPERAND; case 0x9a: return DRC_DWARFv3 | DRC_ONEOPERAND; + case 0xa3: /* DW_OP_entry_value */ + return DRC_TWOOPERANDS; case 0xf0: return DRC_ZEROOPERANDS; /* DW_OP_APPLE_uninit */ case 0xe0: diff --git a/source/Plugins/SymbolFile/DWARF/DWARFUnit.cpp b/source/Plugins/SymbolFile/DWARF/DWARFUnit.cpp index 33e83d1fe57f..9964cf4b893c 100644 --- a/source/Plugins/SymbolFile/DWARF/DWARFUnit.cpp +++ b/source/Plugins/SymbolFile/DWARF/DWARFUnit.cpp @@ -438,7 +438,7 @@ lldb::ByteOrder DWARFUnit::GetByteOrder() const { return m_dwarf.GetObjectFile()->GetByteOrder(); } -TypeSystem *DWARFUnit::GetTypeSystem() { +llvm::Expected<TypeSystem &> DWARFUnit::GetTypeSystem() { return m_dwarf.GetTypeSystemForLanguage(GetLanguageType()); } @@ -540,19 +540,15 @@ void DWARFUnit::ParseProducerInfo() { } else if (strstr(producer_cstr, "clang")) { static RegularExpression g_clang_version_regex( llvm::StringRef("clang-([0-9]+)\\.([0-9]+)\\.([0-9]+)")); - RegularExpression::Match regex_match(3); + llvm::SmallVector<llvm::StringRef, 4> matches; if (g_clang_version_regex.Execute(llvm::StringRef(producer_cstr), - ®ex_match)) { - std::string str; - if (regex_match.GetMatchAtIndex(producer_cstr, 1, str)) - m_producer_version_major = - StringConvert::ToUInt32(str.c_str(), UINT32_MAX, 10); - if (regex_match.GetMatchAtIndex(producer_cstr, 2, str)) - m_producer_version_minor = - StringConvert::ToUInt32(str.c_str(), UINT32_MAX, 10); - if (regex_match.GetMatchAtIndex(producer_cstr, 3, str)) - m_producer_version_update = - StringConvert::ToUInt32(str.c_str(), UINT32_MAX, 10); + &matches)) { + m_producer_version_major = + StringConvert::ToUInt32(matches[1].str().c_str(), UINT32_MAX, 10); + m_producer_version_minor = + StringConvert::ToUInt32(matches[2].str().c_str(), UINT32_MAX, 10); + m_producer_version_update = + StringConvert::ToUInt32(matches[3].str().c_str(), UINT32_MAX, 10); } m_producer = eProducerClang; } else if (strstr(producer_cstr, "GNU")) @@ -870,7 +866,7 @@ DWARFUnit::FindRnglistFromOffset(dw_offset_t offset) const { llvm::Expected<DWARFRangeList> DWARFUnit::FindRnglistFromIndex(uint32_t index) const { - const DWARFDebugRangesBase *debug_rnglists = m_dwarf.GetDebugRngLists(); + const DWARFDebugRngLists *debug_rnglists = m_dwarf.GetDebugRngLists(); if (!debug_rnglists) return llvm::make_error<llvm::object::GenericBinaryError>( "No debug_rnglists section"); diff --git a/source/Plugins/SymbolFile/DWARF/DWARFUnit.h b/source/Plugins/SymbolFile/DWARF/DWARFUnit.h index 8aa1e449f3ed..87e0de283de4 100644 --- a/source/Plugins/SymbolFile/DWARF/DWARFUnit.h +++ b/source/Plugins/SymbolFile/DWARF/DWARFUnit.h @@ -153,7 +153,7 @@ public: lldb::ByteOrder GetByteOrder() const; - lldb_private::TypeSystem *GetTypeSystem(); + llvm::Expected<lldb_private::TypeSystem &> GetTypeSystem(); const DWARFDebugAranges &GetFunctionAranges(); diff --git a/source/Plugins/SymbolFile/DWARF/DebugNamesDWARFIndex.cpp b/source/Plugins/SymbolFile/DWARF/DebugNamesDWARFIndex.cpp index 9746ad76c930..007ef2e05e59 100644 --- a/source/Plugins/SymbolFile/DWARF/DebugNamesDWARFIndex.cpp +++ b/source/Plugins/SymbolFile/DWARF/DebugNamesDWARFIndex.cpp @@ -24,7 +24,7 @@ DebugNamesDWARFIndex::Create(Module &module, DWARFDataExtractor debug_names, return llvm::make_error<llvm::StringError>("debug info null", llvm::inconvertibleErrorCode()); } - auto index_up = llvm::make_unique<DebugNames>(debug_names.GetAsLLVM(), + auto index_up = std::make_unique<DebugNames>(debug_names.GetAsLLVM(), debug_str.GetAsLLVM()); if (llvm::Error E = index_up->extract()) return std::move(E); @@ -105,7 +105,7 @@ void DebugNamesDWARFIndex::GetGlobalVariables(const RegularExpression ®ex, if (!regex.Execute(nte.getString())) continue; - uint32_t entry_offset = nte.getEntryOffset(); + uint64_t entry_offset = nte.getEntryOffset(); llvm::Expected<DebugNames::Entry> entry_or = ni.getEntry(&entry_offset); for (; entry_or; entry_or = ni.getEntry(&entry_offset)) { if (entry_or->tag() != DW_TAG_variable) @@ -125,7 +125,7 @@ void DebugNamesDWARFIndex::GetGlobalVariables(const DWARFUnit &cu, uint64_t cu_offset = cu.GetOffset(); for (const DebugNames::NameIndex &ni: *m_debug_names_up) { for (DebugNames::NameTableEntry nte: ni) { - uint32_t entry_offset = nte.getEntryOffset(); + uint64_t entry_offset = nte.getEntryOffset(); llvm::Expected<DebugNames::Entry> entry_or = ni.getEntry(&entry_offset); for (; entry_or; entry_or = ni.getEntry(&entry_offset)) { if (entry_or->tag() != DW_TAG_variable) @@ -248,7 +248,7 @@ void DebugNamesDWARFIndex::GetFunctions(const RegularExpression ®ex, if (!regex.Execute(nte.getString())) continue; - uint32_t entry_offset = nte.getEntryOffset(); + uint64_t entry_offset = nte.getEntryOffset(); llvm::Expected<DebugNames::Entry> entry_or = ni.getEntry(&entry_offset); for (; entry_or; entry_or = ni.getEntry(&entry_offset)) { Tag tag = entry_or->tag(); diff --git a/source/Plugins/SymbolFile/DWARF/HashedNameToDIE.cpp b/source/Plugins/SymbolFile/DWARF/HashedNameToDIE.cpp index 62b0ad37a9fc..88a29f4a2672 100644 --- a/source/Plugins/SymbolFile/DWARF/HashedNameToDIE.cpp +++ b/source/Plugins/SymbolFile/DWARF/HashedNameToDIE.cpp @@ -125,7 +125,7 @@ DWARFMappedHash::Prologue::Prologue(dw_offset_t _die_base_offset) : die_base_offset(_die_base_offset), atoms(), atom_mask(0), min_hash_data_byte_size(0), hash_data_has_fixed_byte_size(true) { // Define an array of DIE offsets by first defining an array, and then define - // the atom type for the array, in this case we have an array of DIE offsets + // the atom type for the array, in this case we have an array of DIE offsets. AppendAtom(eAtomTypeDIEOffset, DW_FORM_data4); } @@ -208,9 +208,10 @@ DWARFMappedHash::Prologue::Read(const lldb_private::DataExtractor &data, const uint32_t atom_count = data.GetU32(&offset); if (atom_count == 0x00060003u) { - // Old format, deal with contents of old pre-release format - while (data.GetU32(&offset)) + // Old format, deal with contents of old pre-release format. + while (data.GetU32(&offset)) { /* do nothing */; + } // Hardcode to the only known value for now. AppendAtom(eAtomTypeDIEOffset, DW_FORM_data4); @@ -226,7 +227,7 @@ DWARFMappedHash::Prologue::Read(const lldb_private::DataExtractor &data, size_t DWARFMappedHash::Prologue::GetByteSize() const { // Add an extra count to the atoms size for the zero termination Atom that - // gets written to disk + // gets written to disk. return sizeof(die_base_offset) + sizeof(uint32_t) + atoms.size() * sizeof(Atom); } @@ -286,7 +287,7 @@ bool DWARFMappedHash::Header::Read(const lldb_private::DWARFDataExtractor &data, break; default: - // We can always skip atoms we don't know about + // We can always skip atoms we don't know about. break; } } @@ -308,8 +309,8 @@ DWARFMappedHash::MemoryTable::GetStringForKeyType(KeyType key) const { bool DWARFMappedHash::MemoryTable::ReadHashData(uint32_t hash_data_offset, HashData &hash_data) const { lldb::offset_t offset = hash_data_offset; - offset += 4; // Skip string table offset that contains offset of hash name in - // .debug_str + // Skip string table offset that contains offset of hash name in .debug_str. + offset += 4; const uint32_t count = m_data.GetU32(&offset); if (count > 0) { hash_data.resize(count); @@ -335,7 +336,7 @@ DWARFMappedHash::MemoryTable::GetHashDataForName( return eResultEndOfHashData; // There definitely should be a string for this string offset, if there - // isn't, there is something wrong, return and error + // isn't, there is something wrong, return and error. const char *strp_cstr = m_string_table.PeekCStr(pair.key); if (strp_cstr == nullptr) { *hash_data_offset_ptr = UINT32_MAX; @@ -345,9 +346,8 @@ DWARFMappedHash::MemoryTable::GetHashDataForName( const uint32_t count = m_data.GetU32(hash_data_offset_ptr); const size_t min_total_hash_data_size = count * m_header.header_data.GetMinimumHashDataByteSize(); - if (count > 0 && - m_data.ValidOffsetForDataOfSize(*hash_data_offset_ptr, - min_total_hash_data_size)) { + if (count > 0 && m_data.ValidOffsetForDataOfSize(*hash_data_offset_ptr, + min_total_hash_data_size)) { // We have at least one HashData entry, and we have enough data to parse at // least "count" HashData entries. @@ -370,21 +370,22 @@ DWARFMappedHash::MemoryTable::GetHashDataForName( if (match) pair.value.push_back(die_info); } else { - // Something went wrong while reading the data + // Something went wrong while reading the data. *hash_data_offset_ptr = UINT32_MAX; return eResultError; } } } // Return the correct response depending on if the string matched or not... - if (match) - return eResultKeyMatch; // The key (cstring) matches and we have lookup - // results! - else - return eResultKeyMismatch; // The key doesn't match, this function will - // get called - // again for the next key/value or the key terminator which in our case is - // a zero .debug_str offset. + if (match) { + // The key (cstring) matches and we have lookup results! + return eResultKeyMatch; + } else { + // The key doesn't match, this function will get called again for the + // next key/value or the key terminator which in our case is a zero + // .debug_str offset. + return eResultKeyMismatch; + } } else { *hash_data_offset_ptr = UINT32_MAX; return eResultError; @@ -402,7 +403,7 @@ DWARFMappedHash::MemoryTable::AppendHashDataForRegularExpression( return eResultEndOfHashData; // There definitely should be a string for this string offset, if there - // isn't, there is something wrong, return and error + // isn't, there is something wrong, return and error. const char *strp_cstr = m_string_table.PeekCStr(pair.key); if (strp_cstr == nullptr) return eResultError; @@ -410,9 +411,8 @@ DWARFMappedHash::MemoryTable::AppendHashDataForRegularExpression( const uint32_t count = m_data.GetU32(hash_data_offset_ptr); const size_t min_total_hash_data_size = count * m_header.header_data.GetMinimumHashDataByteSize(); - if (count > 0 && - m_data.ValidOffsetForDataOfSize(*hash_data_offset_ptr, - min_total_hash_data_size)) { + if (count > 0 && m_data.ValidOffsetForDataOfSize(*hash_data_offset_ptr, + min_total_hash_data_size)) { const bool match = regex.Execute(llvm::StringRef(strp_cstr)); if (!match && m_header.header_data.HashDataHasFixedByteSize()) { @@ -438,14 +438,15 @@ DWARFMappedHash::MemoryTable::AppendHashDataForRegularExpression( } } // Return the correct response depending on if the string matched or not... - if (match) - return eResultKeyMatch; // The key (cstring) matches and we have lookup - // results! - else - return eResultKeyMismatch; // The key doesn't match, this function will - // get called - // again for the next key/value or the key terminator which in our case is - // a zero .debug_str offset. + if (match) { + // The key (cstring) matches and we have lookup results! + return eResultKeyMatch; + } else { + // The key doesn't match, this function will get called again for the + // next key/value or the key terminator which in our case is a zero + // .debug_str offset. + return eResultKeyMismatch; + } } else { *hash_data_offset_ptr = UINT32_MAX; return eResultError; @@ -466,7 +467,7 @@ size_t DWARFMappedHash::MemoryTable::AppendAllDIEsThatMatchingRegex( if (prev_hash_data_offset == hash_data_offset) break; - // Check the result of getting our hash data + // Check the result of getting our hash data. switch (hash_result) { case eResultKeyMatch: case eResultKeyMismatch: diff --git a/source/Plugins/SymbolFile/DWARF/HashedNameToDIE.h b/source/Plugins/SymbolFile/DWARF/HashedNameToDIE.h index a01612b59528..56d9bc548877 100644 --- a/source/Plugins/SymbolFile/DWARF/HashedNameToDIE.h +++ b/source/Plugins/SymbolFile/DWARF/HashedNameToDIE.h @@ -24,37 +24,41 @@ class DWARFMappedHash { public: enum AtomType : uint16_t { eAtomTypeNULL = 0u, - eAtomTypeDIEOffset = 1u, // DIE offset, check form for encoding - eAtomTypeCUOffset = 2u, // DIE offset of the compiler unit header that - // contains the item in question - eAtomTypeTag = 3u, // DW_TAG_xxx value, should be encoded as DW_FORM_data1 - // (if no tags exceed 255) or DW_FORM_data2 - eAtomTypeNameFlags = 4u, // Flags from enum NameFlags - eAtomTypeTypeFlags = 5u, // Flags from enum TypeFlags, - eAtomTypeQualNameHash = 6u // A 32 bit hash of the full qualified name - // (since all hash entries are basename only) - // For example a type like "std::vector<int>::iterator" would have a name of - // "iterator" - // and a 32 bit hash for "std::vector<int>::iterator" to allow us to not - // have to pull - // in debug info for a type when we know the fully qualified name. + /// DIE offset, check form for encoding. + eAtomTypeDIEOffset = 1u, + /// DIE offset of the compiler unit header that contains the item in + /// question. + eAtomTypeCUOffset = 2u, + /// DW_TAG_xxx value, should be encoded as DW_FORM_data1 (if no tags exceed + /// 255) or DW_FORM_data2. + eAtomTypeTag = 3u, + // Flags from enum NameFlags. + eAtomTypeNameFlags = 4u, + // Flags from enum TypeFlags. + eAtomTypeTypeFlags = 5u, + /// A 32 bit hash of the full qualified name (since all hash entries are + /// basename only) For example a type like "std::vector<int>::iterator" + /// would have a name of "iterator" and a 32 bit hash for + /// "std::vector<int>::iterator" to allow us to not have to pull in debug + /// info for a type when we know the fully qualified name. + eAtomTypeQualNameHash = 6u }; - // Bit definitions for the eAtomTypeTypeFlags flags + /// Bit definitions for the eAtomTypeTypeFlags flags. enum TypeFlags { - // Always set for C++, only set for ObjC if this is the - // @implementation for class + /// Always set for C++, only set for ObjC if this is the + /// @implementation for class. eTypeFlagClassIsImplementation = (1u << 1) }; struct DIEInfo { dw_offset_t die_offset = DW_INVALID_OFFSET; - dw_tag_t tag = 0; + dw_tag_t tag = llvm::dwarf::DW_TAG_null; - /// Any flags for this DIEInfo + /// Any flags for this DIEInfo. uint32_t type_flags = 0; - /// A 32 bit hash of the fully qualified name + /// A 32 bit hash of the fully qualified name. uint32_t qualified_name_hash = 0; DIEInfo() = default; @@ -94,7 +98,7 @@ public: bool HashDataHasFixedByteSize() const; - // DIE offset base so die offsets in hash_data can be CU relative + /// DIE offset base so die offsets in hash_data can be CU relative. dw_offset_t die_base_offset; AtomArray atoms; uint32_t atom_mask; @@ -113,8 +117,8 @@ public: lldb::offset_t *offset_ptr, DIEInfo &hash_data) const; }; - // A class for reading and using a saved hash table from a block of data - // in memory + /// A class for reading and using a saved hash table from a block of data in + /// memory. class MemoryTable : public MappedHash::MemoryTable<uint32_t, DWARFMappedHash::Header, DIEInfoArray> { diff --git a/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp b/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp index e2ddcfc5d64b..c982d59c2830 100644 --- a/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp +++ b/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp @@ -8,6 +8,7 @@ #include "SymbolFileDWARF.h" +#include "llvm/ADT/Optional.h" #include "llvm/Support/Casting.h" #include "llvm/Support/Threading.h" @@ -43,7 +44,7 @@ #include "lldb/Symbol/LineTable.h" #include "lldb/Symbol/LocateSymbolFile.h" #include "lldb/Symbol/ObjectFile.h" -#include "lldb/Symbol/SymbolVendor.h" +#include "lldb/Symbol/SymbolFile.h" #include "lldb/Symbol/TypeMap.h" #include "lldb/Symbol/TypeSystem.h" #include "lldb/Symbol/VariableList.h" @@ -58,7 +59,6 @@ #include "DWARFDebugAbbrev.h" #include "DWARFDebugAranges.h" #include "DWARFDebugInfo.h" -#include "DWARFDebugLine.h" #include "DWARFDebugMacro.h" #include "DWARFDebugRanges.h" #include "DWARFDeclContext.h" @@ -72,6 +72,7 @@ #include "SymbolFileDWARFDwo.h" #include "SymbolFileDWARFDwp.h" +#include "llvm/DebugInfo/DWARF/DWARFContext.h" #include "llvm/Support/FileSystem.h" #include <algorithm> @@ -113,18 +114,12 @@ using namespace lldb_private; namespace { -static constexpr PropertyDefinition g_properties[] = { - {"comp-dir-symlink-paths", OptionValue::eTypeFileSpecList, true, 0, nullptr, - {}, - "If the DW_AT_comp_dir matches any of these paths the symbolic " - "links will be resolved at DWARF parse time."}, - {"ignore-file-indexes", OptionValue::eTypeBoolean, true, 0, nullptr, {}, - "Ignore indexes present in the object files and always index DWARF " - "manually."}}; +#define LLDB_PROPERTIES_symbolfiledwarf +#include "SymbolFileDWARFProperties.inc" enum { - ePropertySymLinkPaths, - ePropertyIgnoreIndexes, +#define LLDB_PROPERTIES_symbolfiledwarf +#include "SymbolFileDWARFPropertiesEnum.inc" }; class PluginProperties : public Properties { @@ -135,7 +130,7 @@ public: PluginProperties() { m_collection_sp = std::make_shared<OptionValueProperties>(GetSettingName()); - m_collection_sp->Initialize(g_properties); + m_collection_sp->Initialize(g_symbolfiledwarf_properties); } FileSpecList GetSymLinkPaths() { @@ -159,7 +154,66 @@ static const SymbolFileDWARFPropertiesSP &GetGlobalPluginProperties() { return g_settings_sp; } -} // anonymous namespace end +} // namespace + +static const llvm::DWARFDebugLine::LineTable * +ParseLLVMLineTable(lldb_private::DWARFContext &context, + llvm::DWARFDebugLine &line, dw_offset_t line_offset, + dw_offset_t unit_offset) { + Log *log = LogChannelDWARF::GetLogIfAll(DWARF_LOG_DEBUG_INFO); + + llvm::DWARFDataExtractor data = context.getOrLoadLineData().GetAsLLVM(); + llvm::DWARFContext &ctx = context.GetAsLLVM(); + llvm::Expected<const llvm::DWARFDebugLine::LineTable *> line_table = + line.getOrParseLineTable( + data, line_offset, ctx, nullptr, [&](llvm::Error e) { + LLDB_LOG_ERROR(log, std::move(e), + "SymbolFileDWARF::ParseLineTable failed to parse"); + }); + + if (!line_table) { + LLDB_LOG_ERROR(log, line_table.takeError(), + "SymbolFileDWARF::ParseLineTable failed to parse"); + return nullptr; + } + return *line_table; +} + +static FileSpecList ParseSupportFilesFromPrologue( + const lldb::ModuleSP &module, + const llvm::DWARFDebugLine::Prologue &prologue, FileSpec::Style style, + llvm::StringRef compile_dir = {}, FileSpec first_file = {}) { + FileSpecList support_files; + support_files.Append(first_file); + + const size_t number_of_files = prologue.FileNames.size(); + for (size_t idx = 1; idx <= number_of_files; ++idx) { + std::string original_file; + if (!prologue.getFileNameByIndex( + idx, compile_dir, + llvm::DILineInfoSpecifier::FileLineInfoKind::Default, original_file, + style)) { + // Always add an entry so the indexes remain correct. + support_files.EmplaceBack(); + continue; + } + + std::string remapped_file; + if (!prologue.getFileNameByIndex( + idx, compile_dir, + llvm::DILineInfoSpecifier::FileLineInfoKind::AbsoluteFilePath, + remapped_file, style)) { + // Always add an entry so the indexes remain correct. + support_files.EmplaceBack(original_file, style); + continue; + } + + module->RemapSourceFile(llvm::StringRef(original_file), remapped_file); + support_files.EmplaceBack(remapped_file, style); + } + + return support_files; +} FileSpecList SymbolFileDWARF::GetSymlinkPaths() { return GetGlobalPluginProperties()->GetSymLinkPaths(); @@ -197,20 +251,16 @@ const char *SymbolFileDWARF::GetPluginDescriptionStatic() { return "DWARF and DWARF3 debug symbol file reader."; } -SymbolFile *SymbolFileDWARF::CreateInstance(ObjectFile *obj_file) { - return new SymbolFileDWARF(obj_file, +SymbolFile *SymbolFileDWARF::CreateInstance(ObjectFileSP objfile_sp) { + return new SymbolFileDWARF(std::move(objfile_sp), /*dwo_section_list*/ nullptr); } -TypeList *SymbolFileDWARF::GetTypeList() { - // This method can be called without going through the symbol vendor so we - // need to lock the module. +TypeList &SymbolFileDWARF::GetTypeList() { std::lock_guard<std::recursive_mutex> guard(GetModuleMutex()); - SymbolFileDWARFDebugMap *debug_map_symfile = GetDebugMapSymfile(); - if (debug_map_symfile) + if (SymbolFileDWARFDebugMap *debug_map_symfile = GetDebugMapSymfile()) return debug_map_symfile->GetTypeList(); - else - return m_obj_file->GetModule()->GetTypeList(); + return SymbolFile::GetTypeList(); } void SymbolFileDWARF::GetTypes(const DWARFDIE &die, dw_offset_t min_die_offset, dw_offset_t max_die_offset, uint32_t type_mask, @@ -264,6 +314,8 @@ void SymbolFileDWARF::GetTypes(const DWARFDIE &die, dw_offset_t min_die_offset, case DW_TAG_ptr_to_member_type: add_type = (type_mask & eTypeClassMemberPointer) != 0; break; + default: + break; } if (add_type) { @@ -283,11 +335,11 @@ void SymbolFileDWARF::GetTypes(const DWARFDIE &die, dw_offset_t min_die_offset, } } -size_t SymbolFileDWARF::GetTypes(SymbolContextScope *sc_scope, - TypeClass type_mask, TypeList &type_list) +void SymbolFileDWARF::GetTypes(SymbolContextScope *sc_scope, + TypeClass type_mask, TypeList &type_list) { - ASSERT_MODULE_LOCK(this); + std::lock_guard<std::recursive_mutex> guard(GetModuleMutex()); TypeSet type_set; CompileUnit *comp_unit = nullptr; @@ -297,8 +349,8 @@ size_t SymbolFileDWARF::GetTypes(SymbolContextScope *sc_scope, if (comp_unit) { dwarf_cu = GetDWARFCompileUnit(comp_unit); - if (dwarf_cu == nullptr) - return 0; + if (!dwarf_cu) + return; GetTypes(dwarf_cu->DIE(), dwarf_cu->GetOffset(), dwarf_cu->GetNextUnitOffset(), type_mask, type_set); } else { @@ -315,16 +367,13 @@ size_t SymbolFileDWARF::GetTypes(SymbolContextScope *sc_scope, } std::set<CompilerType> compiler_type_set; - size_t num_types_added = 0; for (Type *type : type_set) { CompilerType compiler_type = type->GetForwardCompilerType(); if (compiler_type_set.find(compiler_type) == compiler_type_set.end()) { compiler_type_set.insert(compiler_type); type_list.Insert(type->shared_from_this()); - ++num_types_added; } } - return num_types_added; } // Gets the first parent that is a lexical block, function or inlined @@ -342,19 +391,21 @@ SymbolFileDWARF::GetParentSymbolContextDIE(const DWARFDIE &child_die) { case DW_TAG_inlined_subroutine: case DW_TAG_lexical_block: return die; + default: + break; } } return DWARFDIE(); } -SymbolFileDWARF::SymbolFileDWARF(ObjectFile *objfile, +SymbolFileDWARF::SymbolFileDWARF(ObjectFileSP objfile_sp, SectionList *dwo_section_list) - : SymbolFile(objfile), + : SymbolFile(std::move(objfile_sp)), UserID(0x7fffffff00000000), // Used by SymbolFileDWARFDebugMap to // when this class parses .o files to // contain the .o file index/ID m_debug_map_module_wp(), m_debug_map_symfile(nullptr), - m_context(objfile->GetModule()->GetSectionList(), dwo_section_list), + m_context(m_objfile_sp->GetModule()->GetSectionList(), dwo_section_list), m_data_debug_loc(), m_abbr(), m_info(), m_fetched_external_modules(false), m_supports_DW_AT_APPLE_objc_complete_type(eLazyBoolCalculate), m_unique_ast_type_map() {} @@ -374,17 +425,17 @@ UniqueDWARFASTTypeMap &SymbolFileDWARF::GetUniqueDWARFASTTypeMap() { return m_unique_ast_type_map; } -TypeSystem *SymbolFileDWARF::GetTypeSystemForLanguage(LanguageType language) { - SymbolFileDWARFDebugMap *debug_map_symfile = GetDebugMapSymfile(); - TypeSystem *type_system; - if (debug_map_symfile) { - type_system = debug_map_symfile->GetTypeSystemForLanguage(language); - } else { - type_system = m_obj_file->GetModule()->GetTypeSystemForLanguage(language); - if (type_system) - type_system->SetSymbolFile(this); +llvm::Expected<TypeSystem &> +SymbolFileDWARF::GetTypeSystemForLanguage(LanguageType language) { + if (SymbolFileDWARFDebugMap *debug_map_symfile = GetDebugMapSymfile()) + return debug_map_symfile->GetTypeSystemForLanguage(language); + + auto type_system_or_err = + m_objfile_sp->GetModule()->GetTypeSystemForLanguage(language); + if (type_system_or_err) { + type_system_or_err->SetSymbolFile(this); } - return type_system; + return type_system_or_err; } void SymbolFileDWARF::InitializeObject() { @@ -420,7 +471,7 @@ void SymbolFileDWARF::InitializeObject() { } } - m_index = llvm::make_unique<ManualDWARFIndex>(*GetObjectFile()->GetModule(), + m_index = std::make_unique<ManualDWARFIndex>(*GetObjectFile()->GetModule(), DebugInfo()); } @@ -430,9 +481,9 @@ bool SymbolFileDWARF::SupportedVersion(uint16_t version) { uint32_t SymbolFileDWARF::CalculateAbilities() { uint32_t abilities = 0; - if (m_obj_file != nullptr) { + if (m_objfile_sp != nullptr) { const Section *section = nullptr; - const SectionList *section_list = m_obj_file->GetSectionList(); + const SectionList *section_list = m_objfile_sp->GetSectionList(); if (section_list == nullptr) return 0; @@ -462,10 +513,12 @@ uint32_t SymbolFileDWARF::CalculateAbilities() { abbrev->GetUnsupportedForms(invalid_forms); if (!invalid_forms.empty()) { StreamString error; - error.Printf("unsupported DW_FORM value%s:", invalid_forms.size() > 1 ? "s" : ""); + error.Printf("unsupported DW_FORM value%s:", + invalid_forms.size() > 1 ? "s" : ""); for (auto form : invalid_forms) error.Printf(" %#x", form); - m_obj_file->GetModule()->ReportWarning("%s", error.GetString().str().c_str()); + m_objfile_sp->GetModule()->ReportWarning( + "%s", error.GetString().str().c_str()); return 0; } } @@ -477,10 +530,10 @@ uint32_t SymbolFileDWARF::CalculateAbilities() { debug_line_file_size = section->GetFileSize(); } else { const char *symfile_dir_cstr = - m_obj_file->GetFileSpec().GetDirectory().GetCString(); + m_objfile_sp->GetFileSpec().GetDirectory().GetCString(); if (symfile_dir_cstr) { if (strcasestr(symfile_dir_cstr, ".dsym")) { - if (m_obj_file->GetType() == ObjectFile::eTypeDebugInfo) { + if (m_objfile_sp->GetType() == ObjectFile::eTypeDebugInfo) { // We have a dSYM file that didn't have a any debug info. If the // string table has a size of 1, then it was made from an // executable with no debug info, or from an executable that was @@ -489,7 +542,7 @@ uint32_t SymbolFileDWARF::CalculateAbilities() { section_list->FindSectionByType(eSectionTypeDWARFDebugStr, true) .get(); if (section && section->GetFileSize() == 1) { - m_obj_file->GetModule()->ReportWarning( + m_objfile_sp->GetModule()->ReportWarning( "empty dSYM file detected, dSYM was created with an " "executable with no debug info."); } @@ -519,7 +572,7 @@ SymbolFileDWARF::GetCachedSectionData(lldb::SectionType sect_type, void SymbolFileDWARF::LoadSectionData(lldb::SectionType sect_type, DWARFDataExtractor &data) { - ModuleSP module_sp(m_obj_file->GetModule()); + ModuleSP module_sp(m_objfile_sp->GetModule()); const SectionList *section_list = module_sp->GetSectionList(); if (!section_list) return; @@ -529,7 +582,7 @@ void SymbolFileDWARF::LoadSectionData(lldb::SectionType sect_type, return; data.Clear(); - m_obj_file->ReadSectionData(section_sp.get(), data); + m_objfile_sp->ReadSectionData(section_sp.get(), data); } const DWARFDataExtractor &SymbolFileDWARF::DebugLocData() { @@ -556,7 +609,7 @@ DWARFDebugAbbrev *SymbolFileDWARF::DebugAbbrev() { if (debug_abbrev_data.GetByteSize() == 0) return nullptr; - auto abbr = llvm::make_unique<DWARFDebugAbbrev>(); + auto abbr = std::make_unique<DWARFDebugAbbrev>(); llvm::Error error = abbr->parse(debug_abbrev_data); if (error) { Log *log = LogChannelDWARF::GetLogIfAll(DWARF_LOG_DEBUG_INFO); @@ -579,7 +632,7 @@ DWARFDebugInfo *SymbolFileDWARF::DebugInfo() { Timer scoped_timer(func_cat, "%s this = %p", LLVM_PRETTY_FUNCTION, static_cast<void *>(this)); if (m_context.getOrLoadDebugInfoData().GetByteSize() > 0) - m_info = llvm::make_unique<DWARFDebugInfo>(*this, m_context); + m_info = std::make_unique<DWARFDebugInfo>(*this, m_context); } return m_info.get(); } @@ -604,7 +657,7 @@ SymbolFileDWARF::GetDWARFCompileUnit(lldb_private::CompileUnit *comp_unit) { return nullptr; } -DWARFDebugRangesBase *SymbolFileDWARF::GetDebugRanges() { +DWARFDebugRanges *SymbolFileDWARF::GetDebugRanges() { if (!m_ranges) { static Timer::Category func_cat(LLVM_PRETTY_FUNCTION); Timer scoped_timer(func_cat, "%s this = %p", LLVM_PRETTY_FUNCTION, @@ -619,7 +672,7 @@ DWARFDebugRangesBase *SymbolFileDWARF::GetDebugRanges() { return m_ranges.get(); } -DWARFDebugRangesBase *SymbolFileDWARF::GetDebugRngLists() { +DWARFDebugRngLists *SymbolFileDWARF::GetDebugRngLists() { if (!m_rnglists) { static Timer::Category func_cat(LLVM_PRETTY_FUNCTION); Timer scoped_timer(func_cat, "%s this = %p", LLVM_PRETTY_FUNCTION, @@ -648,7 +701,7 @@ lldb::CompUnitSP SymbolFileDWARF::ParseCompileUnit(DWARFCompileUnit &dwarf_cu) { cu_sp = m_debug_map_symfile->GetCompileUnit(this); dwarf_cu.SetUserData(cu_sp.get()); } else { - ModuleSP module_sp(m_obj_file->GetModule()); + ModuleSP module_sp(m_objfile_sp->GetModule()); if (module_sp) { const DWARFDIE cu_die = dwarf_cu.DIE(); if (cu_die) { @@ -677,8 +730,7 @@ lldb::CompUnitSP SymbolFileDWARF::ParseCompileUnit(DWARFCompileUnit &dwarf_cu) { dwarf_cu.SetUserData(cu_sp.get()); - m_obj_file->GetModule()->GetSymbolVendor()->SetCompileUnitAtIndex( - dwarf_cu.GetID(), cu_sp); + SetCompileUnitAtIndex(dwarf_cu.GetID(), cu_sp); } } } @@ -715,7 +767,7 @@ llvm::Optional<uint32_t> SymbolFileDWARF::GetDWARFUnitIndex(uint32_t cu_idx) { return m_lldb_cu_to_dwarf_unit[cu_idx]; } -uint32_t SymbolFileDWARF::GetNumCompileUnits() { +uint32_t SymbolFileDWARF::CalculateNumCompileUnits() { DWARFDebugInfo *info = DebugInfo(); if (!info) return 0; @@ -741,17 +793,21 @@ CompUnitSP SymbolFileDWARF::ParseCompileUnitAtIndex(uint32_t cu_idx) { Function *SymbolFileDWARF::ParseFunction(CompileUnit &comp_unit, const DWARFDIE &die) { ASSERT_MODULE_LOCK(this); - if (die.IsValid()) { - TypeSystem *type_system = - GetTypeSystemForLanguage(die.GetCU()->GetLanguageType()); - - if (type_system) { - DWARFASTParser *dwarf_ast = type_system->GetDWARFParser(); - if (dwarf_ast) - return dwarf_ast->ParseFunctionFromDWARF(comp_unit, die); - } + if (!die.IsValid()) + return nullptr; + + auto type_system_or_err = + GetTypeSystemForLanguage(die.GetCU()->GetLanguageType()); + if (auto err = type_system_or_err.takeError()) { + LLDB_LOG_ERROR(lldb_private::GetLogIfAnyCategoriesSet(LIBLLDB_LOG_SYMBOLS), + std::move(err), "Unable to parse function"); + return nullptr; } - return nullptr; + DWARFASTParser *dwarf_ast = type_system_or_err->GetDWARFParser(); + if (!dwarf_ast) + return nullptr; + + return dwarf_ast->ParseFunctionFromDWARF(comp_unit, die); } bool SymbolFileDWARF::FixupAddress(Address &addr) { @@ -763,7 +819,7 @@ bool SymbolFileDWARF::FixupAddress(Address &addr) { return true; } lldb::LanguageType SymbolFileDWARF::ParseLanguage(CompileUnit &comp_unit) { - ASSERT_MODULE_LOCK(this); + std::lock_guard<std::recursive_mutex> guard(GetModuleMutex()); DWARFUnit *dwarf_cu = GetDWARFCompileUnit(&comp_unit); if (dwarf_cu) return dwarf_cu->GetLanguageType(); @@ -772,7 +828,7 @@ lldb::LanguageType SymbolFileDWARF::ParseLanguage(CompileUnit &comp_unit) { } size_t SymbolFileDWARF::ParseFunctions(CompileUnit &comp_unit) { - ASSERT_MODULE_LOCK(this); + std::lock_guard<std::recursive_mutex> guard(GetModuleMutex()); DWARFUnit *dwarf_cu = GetDWARFCompileUnit(&comp_unit); if (!dwarf_cu) return 0; @@ -790,21 +846,23 @@ size_t SymbolFileDWARF::ParseFunctions(CompileUnit &comp_unit) { return functions_added; } +void SymbolFileDWARF::ForEachExternalModule( + CompileUnit &comp_unit, llvm::function_ref<void(ModuleSP)> f) { + UpdateExternalModuleListIfNeeded(); + + for (auto &p : m_external_type_modules) { + ModuleSP module = p.second; + f(module); + for (std::size_t i = 0; i < module->GetNumCompileUnits(); ++i) + module->GetCompileUnitAtIndex(i)->ForEachExternalModule(f); + } +} + bool SymbolFileDWARF::ParseSupportFiles(CompileUnit &comp_unit, FileSpecList &support_files) { - ASSERT_MODULE_LOCK(this); - if (DWARFUnit *unit = GetDWARFCompileUnit(&comp_unit)) { - const dw_offset_t stmt_list = unit->GetLineTableOffset(); - if (stmt_list != DW_INVALID_OFFSET) { - // All file indexes in DWARF are one based and a file of index zero is - // supposed to be the compile unit itself. - support_files.Append(comp_unit); - return DWARFDebugLine::ParseSupportFiles(comp_unit.GetModule(), - m_context.getOrLoadLineData(), - stmt_list, support_files, unit); - } - } - return false; + if (!comp_unit.GetLineTable()) + ParseLineTable(comp_unit); + return true; } FileSpec SymbolFileDWARF::GetFile(DWARFUnit &unit, size_t file_idx) { @@ -833,16 +891,26 @@ SymbolFileDWARF::GetTypeUnitSupportFiles(DWARFTypeUnit &tu) { auto iter_bool = m_type_unit_support_files.try_emplace(offset); FileSpecList &list = iter_bool.first->second; if (iter_bool.second) { - list.Append(FileSpec()); - DWARFDebugLine::ParseSupportFiles(GetObjectFile()->GetModule(), - m_context.getOrLoadLineData(), offset, - list, &tu); + uint64_t line_table_offset = offset; + llvm::DWARFDataExtractor data = m_context.getOrLoadLineData().GetAsLLVM(); + llvm::DWARFContext &ctx = m_context.GetAsLLVM(); + llvm::DWARFDebugLine::Prologue prologue; + llvm::Error error = prologue.parse(data, &line_table_offset, ctx); + if (error) { + Log *log = LogChannelDWARF::GetLogIfAll(DWARF_LOG_DEBUG_INFO); + LLDB_LOG_ERROR(log, std::move(error), + "SymbolFileDWARF::GetTypeUnitSupportFiles failed to parse " + "the line table prologue"); + } else { + list = ParseSupportFilesFromPrologue(GetObjectFile()->GetModule(), + prologue, tu.GetPathStyle()); + } } return list; } bool SymbolFileDWARF::ParseIsOptimized(CompileUnit &comp_unit) { - ASSERT_MODULE_LOCK(this); + std::lock_guard<std::recursive_mutex> guard(GetModuleMutex()); DWARFUnit *dwarf_cu = GetDWARFCompileUnit(&comp_unit); if (dwarf_cu) return dwarf_cu->GetIsOptimized(); @@ -852,7 +920,7 @@ bool SymbolFileDWARF::ParseIsOptimized(CompileUnit &comp_unit) { bool SymbolFileDWARF::ParseImportedModules( const lldb_private::SymbolContext &sc, std::vector<SourceModule> &imported_modules) { - ASSERT_MODULE_LOCK(this); + std::lock_guard<std::recursive_mutex> guard(GetModuleMutex()); assert(sc.comp_unit); DWARFUnit *dwarf_cu = GetDWARFCompileUnit(sc.comp_unit); if (!dwarf_cu) @@ -901,102 +969,63 @@ bool SymbolFileDWARF::ParseImportedModules( return true; } -struct ParseDWARFLineTableCallbackInfo { - LineTable *line_table; - std::unique_ptr<LineSequence> sequence_up; - lldb::addr_t addr_mask; -}; - -// ParseStatementTableCallback -static void ParseDWARFLineTableCallback(dw_offset_t offset, - const DWARFDebugLine::State &state, - void *userData) { - if (state.row == DWARFDebugLine::State::StartParsingLineTable) { - // Just started parsing the line table - } else if (state.row == DWARFDebugLine::State::DoneParsingLineTable) { - // Done parsing line table, nothing to do for the cleanup - } else { - ParseDWARFLineTableCallbackInfo *info = - (ParseDWARFLineTableCallbackInfo *)userData; - LineTable *line_table = info->line_table; - - // If this is our first time here, we need to create a sequence container. - if (!info->sequence_up) { - info->sequence_up.reset(line_table->CreateLineSequenceContainer()); - assert(info->sequence_up.get()); - } - line_table->AppendLineEntryToSequence( - info->sequence_up.get(), state.address & info->addr_mask, state.line, - state.column, state.file, state.is_stmt, state.basic_block, - state.prologue_end, state.epilogue_begin, state.end_sequence); - if (state.end_sequence) { - // First, put the current sequence into the line table. - line_table->InsertSequence(info->sequence_up.get()); - // Then, empty it to prepare for the next sequence. - info->sequence_up->Clear(); - } - } -} - bool SymbolFileDWARF::ParseLineTable(CompileUnit &comp_unit) { - ASSERT_MODULE_LOCK(this); + std::lock_guard<std::recursive_mutex> guard(GetModuleMutex()); if (comp_unit.GetLineTable() != nullptr) return true; DWARFUnit *dwarf_cu = GetDWARFCompileUnit(&comp_unit); - if (dwarf_cu) { - const DWARFBaseDIE dwarf_cu_die = dwarf_cu->GetUnitDIEOnly(); - if (dwarf_cu_die) { - const dw_offset_t cu_line_offset = - dwarf_cu_die.GetAttributeValueAsUnsigned(DW_AT_stmt_list, - DW_INVALID_OFFSET); - if (cu_line_offset != DW_INVALID_OFFSET) { - std::unique_ptr<LineTable> line_table_up(new LineTable(&comp_unit)); - if (line_table_up) { - ParseDWARFLineTableCallbackInfo info; - info.line_table = line_table_up.get(); - - /* - * MIPS: - * The SymbolContext may not have a valid target, thus we may not be - * able - * to call Address::GetOpcodeLoadAddress() which would clear the bit - * #0 - * for MIPS. Use ArchSpec to clear the bit #0. - */ - switch (GetObjectFile()->GetArchitecture().GetMachine()) { - case llvm::Triple::mips: - case llvm::Triple::mipsel: - case llvm::Triple::mips64: - case llvm::Triple::mips64el: - info.addr_mask = ~((lldb::addr_t)1); - break; - default: - info.addr_mask = ~((lldb::addr_t)0); - break; - } + if (!dwarf_cu) + return false; - lldb::offset_t offset = cu_line_offset; - DWARFDebugLine::ParseStatementTable( - m_context.getOrLoadLineData(), &offset, - ParseDWARFLineTableCallback, &info, dwarf_cu); - SymbolFileDWARFDebugMap *debug_map_symfile = GetDebugMapSymfile(); - if (debug_map_symfile) { - // We have an object file that has a line table with addresses that - // are not linked. We need to link the line table and convert the - // addresses that are relative to the .o file into addresses for - // the main executable. - comp_unit.SetLineTable( - debug_map_symfile->LinkOSOLineTable(this, line_table_up.get())); - } else { - comp_unit.SetLineTable(line_table_up.release()); - return true; - } - } - } + const DWARFBaseDIE dwarf_cu_die = dwarf_cu->GetUnitDIEOnly(); + if (!dwarf_cu_die) + return false; + + const dw_offset_t cu_line_offset = dwarf_cu_die.GetAttributeValueAsUnsigned( + DW_AT_stmt_list, DW_INVALID_OFFSET); + if (cu_line_offset == DW_INVALID_OFFSET) + return false; + + llvm::DWARFDebugLine line; + const llvm::DWARFDebugLine::LineTable *line_table = ParseLLVMLineTable( + m_context, line, cu_line_offset, dwarf_cu->GetOffset()); + + if (!line_table) + return false; + + // FIXME: Rather than parsing the whole line table and then copying it over + // into LLDB, we should explore using a callback to populate the line table + // while we parse to reduce memory usage. + std::unique_ptr<LineTable> line_table_up = + std::make_unique<LineTable>(&comp_unit); + LineSequence *sequence = line_table_up->CreateLineSequenceContainer(); + for (auto &row : line_table->Rows) { + line_table_up->AppendLineEntryToSequence( + sequence, row.Address.Address, row.Line, row.Column, row.File, + row.IsStmt, row.BasicBlock, row.PrologueEnd, row.EpilogueBegin, + row.EndSequence); + if (row.EndSequence) { + line_table_up->InsertSequence(sequence); + sequence = line_table_up->CreateLineSequenceContainer(); } } - return false; + + if (SymbolFileDWARFDebugMap *debug_map_symfile = GetDebugMapSymfile()) { + // We have an object file that has a line table with addresses that are not + // linked. We need to link the line table and convert the addresses that + // are relative to the .o file into addresses for the main executable. + comp_unit.SetLineTable( + debug_map_symfile->LinkOSOLineTable(this, line_table_up.get())); + } else { + comp_unit.SetLineTable(line_table_up.release()); + } + + comp_unit.SetSupportFiles(ParseSupportFilesFromPrologue( + comp_unit.GetModule(), line_table->Prologue, dwarf_cu->GetPathStyle(), + dwarf_cu->GetCompilationDirectory().GetCString(), FileSpec(comp_unit))); + + return true; } lldb_private::DebugMacrosSP @@ -1022,7 +1051,7 @@ SymbolFileDWARF::ParseDebugMacros(lldb::offset_t *offset) { } bool SymbolFileDWARF::ParseDebugMacros(CompileUnit &comp_unit) { - ASSERT_MODULE_LOCK(this); + std::lock_guard<std::recursive_mutex> guard(GetModuleMutex()); DWARFUnit *dwarf_cu = GetDWARFCompileUnit(&comp_unit); if (dwarf_cu == nullptr) @@ -1114,7 +1143,7 @@ size_t SymbolFileDWARF::ParseBlocksRecursive( "0x%8.8" PRIx64 ": adding range [0x%" PRIx64 "-0x%" PRIx64 ") which has a base that is less than the function's low PC " "0x%" PRIx64 ". Please file a bug and attach the file at the " - "start of this error message", + "start of this error message", block->GetID(), range_base, range.GetRangeEnd(), subprogram_low_pc); } @@ -1188,15 +1217,10 @@ bool SymbolFileDWARF::ClassOrStructIsVirtual(const DWARFDIE &parent_die) { } void SymbolFileDWARF::ParseDeclsForContext(CompilerDeclContext decl_ctx) { - TypeSystem *type_system = decl_ctx.GetTypeSystem(); - DWARFASTParser *ast_parser = type_system->GetDWARFParser(); - std::vector<DWARFDIE> decl_ctx_die_list = - ast_parser->GetDIEForDeclContext(decl_ctx); - - for (DWARFDIE decl_ctx_die : decl_ctx_die_list) - for (DWARFDIE decl = decl_ctx_die.GetFirstChild(); decl; - decl = decl.GetSibling()) - ast_parser->GetDeclForUIDFromDWARF(decl); + auto *type_system = decl_ctx.GetTypeSystem(); + if (type_system != nullptr) + type_system->GetDWARFParser()->EnsureAllDIEsInDeclContextHaveBeenParsed( + decl_ctx); } user_id_t SymbolFileDWARF::GetUID(DIERef ref) { @@ -1281,8 +1305,6 @@ SymbolFileDWARF::GetDeclContextForUID(lldb::user_id_t type_uid) { CompilerDeclContext SymbolFileDWARF::GetDeclContextContainingUID(lldb::user_id_t type_uid) { - // This method can be called without going through the symbol vendor so we - // need to lock the module. std::lock_guard<std::recursive_mutex> guard(GetModuleMutex()); // Anytime we have a lldb::user_id_t, we must get the DIE by calling // SymbolFileDWARF::GetDIE(). See comments inside the @@ -1293,8 +1315,6 @@ SymbolFileDWARF::GetDeclContextContainingUID(lldb::user_id_t type_uid) { } Type *SymbolFileDWARF::ResolveTypeUID(lldb::user_id_t type_uid) { - // This method can be called without going through the symbol vendor so we - // need to lock the module. std::lock_guard<std::recursive_mutex> guard(GetModuleMutex()); // Anytime we have a lldb::user_id_t, we must get the DIE by calling // SymbolFileDWARF::GetDIE(). See comments inside the @@ -1341,8 +1361,9 @@ Type *SymbolFileDWARF::ResolveTypeUID(const DWARFDIE &die, // Get the type, which could be a forward declaration if (log) GetObjectFile()->GetModule()->LogMessage( - log, "SymbolFileDWARF::ResolveTypeUID (die = 0x%8.8x) %s '%s' " - "resolve parent forward type for 0x%8.8x", + log, + "SymbolFileDWARF::ResolveTypeUID (die = 0x%8.8x) %s '%s' " + "resolve parent forward type for 0x%8.8x", die.GetOffset(), die.GetTagAsCString(), die.GetName(), decl_ctx_die.GetOffset()); } break; @@ -1504,7 +1525,6 @@ SymbolFileDWARF::GetDIE(const DIERef &die_ref) { ->GetDIE(die_ref); } - DWARFDebugInfo *debug_info = DebugInfo(); if (debug_info) return debug_info->GetDIE(die_ref); @@ -1567,7 +1587,7 @@ SymbolFileDWARF::GetDwoSymbolFileForCompileUnit( if (dwo_obj_file == nullptr) return nullptr; - return llvm::make_unique<SymbolFileDWARFDwo>(dwo_obj_file, *dwarf_cu); + return std::make_unique<SymbolFileDWARFDwo>(dwo_obj_file, *dwarf_cu); } void SymbolFileDWARF::UpdateExternalModuleListIfNeeded() { @@ -1607,7 +1627,7 @@ void SymbolFileDWARF::UpdateExternalModuleListIfNeeded() { } } dwo_module_spec.GetArchitecture() = - m_obj_file->GetModule()->GetArchitecture(); + m_objfile_sp->GetModule()->GetArchitecture(); // When LLDB loads "external" modules it looks at the presence of // DW_AT_GNU_dwo_name. However, when the already created module @@ -1621,8 +1641,8 @@ void SymbolFileDWARF::UpdateExternalModuleListIfNeeded() { // printed. However, as one can notice in this case we don't // actually need to try to load the already loaded module // (corresponding to .dwo) so we simply skip it. - if (m_obj_file->GetFileSpec().GetFileNameExtension() == ".dwo" && - llvm::StringRef(m_obj_file->GetFileSpec().GetPath()) + if (m_objfile_sp->GetFileSpec().GetFileNameExtension() == ".dwo" && + llvm::StringRef(m_objfile_sp->GetFileSpec().GetPath()) .endswith(dwo_module_spec.GetFileSpec().GetPath())) { continue; } @@ -1694,6 +1714,7 @@ SymbolFileDWARF::GlobalVariableMap &SymbolFileDWARF::GetGlobalAranges() { uint32_t SymbolFileDWARF::ResolveSymbolContext(const Address &so_addr, SymbolContextItem resolve_scope, SymbolContext &sc) { + std::lock_guard<std::recursive_mutex> guard(GetModuleMutex()); static Timer::Category func_cat(LLVM_PRETTY_FUNCTION); Timer scoped_timer(func_cat, "SymbolFileDWARF::" @@ -1837,6 +1858,7 @@ uint32_t SymbolFileDWARF::ResolveSymbolContext(const FileSpec &file_spec, bool check_inlines, SymbolContextItem resolve_scope, SymbolContextList &sc_list) { + std::lock_guard<std::recursive_mutex> guard(GetModuleMutex()); const uint32_t prev_size = sc_list.GetSize(); if (resolve_scope & eSymbolContextCompUnit) { for (uint32_t cu_idx = 0, num_cus = GetNumCompileUnits(); cu_idx < num_cus; @@ -1849,7 +1871,7 @@ uint32_t SymbolFileDWARF::ResolveSymbolContext(const FileSpec &file_spec, bool file_spec_matches_cu_file_spec = FileSpec::Equal(file_spec, *dc_cu, full_match); if (check_inlines || file_spec_matches_cu_file_spec) { - SymbolContext sc(m_obj_file->GetModule()); + SymbolContext sc(m_objfile_sp->GetModule()); sc.comp_unit = dc_cu; uint32_t file_idx = UINT32_MAX; @@ -1961,9 +1983,16 @@ bool SymbolFileDWARF::DeclContextMatchesThisSymbolFile( } TypeSystem *decl_ctx_type_system = decl_ctx->GetTypeSystem(); - TypeSystem *type_system = GetTypeSystemForLanguage( + auto type_system_or_err = GetTypeSystemForLanguage( decl_ctx_type_system->GetMinimumLanguage(nullptr)); - if (decl_ctx_type_system == type_system) + if (auto err = type_system_or_err.takeError()) { + LLDB_LOG_ERROR(lldb_private::GetLogIfAnyCategoriesSet(LIBLLDB_LOG_SYMBOLS), + std::move(err), + "Unable to match namespace decl using TypeSystem"); + return false; + } + + if (decl_ctx_type_system == &type_system_or_err.get()) return true; // The type systems match, return true // The namespace AST was valid, and it does not match... @@ -1976,9 +2005,10 @@ bool SymbolFileDWARF::DeclContextMatchesThisSymbolFile( return false; } -uint32_t SymbolFileDWARF::FindGlobalVariables( +void SymbolFileDWARF::FindGlobalVariables( ConstString name, const CompilerDeclContext *parent_decl_ctx, uint32_t max_matches, VariableList &variables) { + std::lock_guard<std::recursive_mutex> guard(GetModuleMutex()); Log *log(LogChannelDWARF::GetLogIfAll(DWARF_LOG_LOOKUPS)); if (log) @@ -1990,11 +2020,11 @@ uint32_t SymbolFileDWARF::FindGlobalVariables( max_matches); if (!DeclContextMatchesThisSymbolFile(parent_decl_ctx)) - return 0; + return; DWARFDebugInfo *info = DebugInfo(); - if (info == nullptr) - return 0; + if (!info) + return; // Remember how many variables are in the list before we search. const uint32_t original_size = variables.GetSize(); @@ -2012,7 +2042,7 @@ uint32_t SymbolFileDWARF::FindGlobalVariables( const size_t num_die_matches = die_offsets.size(); if (num_die_matches) { SymbolContext sc; - sc.module_sp = m_obj_file->GetModule(); + sc.module_sp = m_objfile_sp->GetModule(); assert(sc.module_sp); // Loop invariant: Variables up to this index have been checked for context @@ -2081,12 +2111,12 @@ uint32_t SymbolFileDWARF::FindGlobalVariables( name.GetCString(), static_cast<const void *>(parent_decl_ctx), max_matches, num_matches); } - return num_matches; } -uint32_t SymbolFileDWARF::FindGlobalVariables(const RegularExpression ®ex, - uint32_t max_matches, - VariableList &variables) { +void SymbolFileDWARF::FindGlobalVariables(const RegularExpression ®ex, + uint32_t max_matches, + VariableList &variables) { + std::lock_guard<std::recursive_mutex> guard(GetModuleMutex()); Log *log(LogChannelDWARF::GetLogIfAll(DWARF_LOG_LOOKUPS)); if (log) { @@ -2098,8 +2128,8 @@ uint32_t SymbolFileDWARF::FindGlobalVariables(const RegularExpression ®ex, } DWARFDebugInfo *info = DebugInfo(); - if (info == nullptr) - return 0; + if (!info) + return; // Remember how many variables are in the list before we search. const uint32_t original_size = variables.GetSize(); @@ -2108,7 +2138,7 @@ uint32_t SymbolFileDWARF::FindGlobalVariables(const RegularExpression ®ex, m_index->GetGlobalVariables(regex, die_offsets); SymbolContext sc; - sc.module_sp = m_obj_file->GetModule(); + sc.module_sp = m_objfile_sp->GetModule(); assert(sc.module_sp); const size_t num_matches = die_offsets.size(); @@ -2132,9 +2162,6 @@ uint32_t SymbolFileDWARF::FindGlobalVariables(const RegularExpression ®ex, m_index->ReportInvalidDIERef(die_ref, regex.GetText()); } } - - // Return the number of variable that were appended to the list - return variables.GetSize() - original_size; } bool SymbolFileDWARF::ResolveFunction(const DWARFDIE &orig_die, @@ -2210,10 +2237,12 @@ bool SymbolFileDWARF::DIEInDeclContext(const CompilerDeclContext *decl_ctx, return false; } -uint32_t SymbolFileDWARF::FindFunctions( - ConstString name, const CompilerDeclContext *parent_decl_ctx, - FunctionNameType name_type_mask, bool include_inlines, bool append, - SymbolContextList &sc_list) { +void SymbolFileDWARF::FindFunctions(ConstString name, + const CompilerDeclContext *parent_decl_ctx, + FunctionNameType name_type_mask, + bool include_inlines, + SymbolContextList &sc_list) { + std::lock_guard<std::recursive_mutex> guard(GetModuleMutex()); static Timer::Category func_cat(LLVM_PRETTY_FUNCTION); Timer scoped_timer(func_cat, "SymbolFileDWARF::FindFunctions (name = '%s')", name.AsCString()); @@ -2226,21 +2255,17 @@ uint32_t SymbolFileDWARF::FindFunctions( if (log) { GetObjectFile()->GetModule()->LogMessage( - log, "SymbolFileDWARF::FindFunctions (name=\"%s\", " - "name_type_mask=0x%x, append=%u, sc_list)", - name.GetCString(), name_type_mask, append); + log, + "SymbolFileDWARF::FindFunctions (name=\"%s\", name_type_mask=0x%x, sc_list)", + name.GetCString(), name_type_mask); } - // If we aren't appending the results to this list, then clear the list - if (!append) - sc_list.Clear(); - if (!DeclContextMatchesThisSymbolFile(parent_decl_ctx)) - return 0; + return; // If name is empty then we won't find anything. if (name.IsEmpty()) - return 0; + return; // Remember how many sc_list are in the list before we search in case we are // appending the results to a variable list. @@ -2255,7 +2280,7 @@ uint32_t SymbolFileDWARF::FindFunctions( std::vector<DWARFDIE> dies; m_index->GetFunctions(name, *this, *parent_decl_ctx, name_type_mask, dies); - for (const DWARFDIE &die: dies) { + for (const DWARFDIE &die : dies) { if (resolved_dies.insert(die.GetDIE()).second) ResolveFunction(die, include_inlines, sc_list); } @@ -2265,18 +2290,18 @@ uint32_t SymbolFileDWARF::FindFunctions( if (log && num_matches > 0) { GetObjectFile()->GetModule()->LogMessage( - log, "SymbolFileDWARF::FindFunctions (name=\"%s\", " - "name_type_mask=0x%x, include_inlines=%d, append=%u, sc_list) => " - "%u", - name.GetCString(), name_type_mask, include_inlines, append, + log, + "SymbolFileDWARF::FindFunctions (name=\"%s\", " + "name_type_mask=0x%x, include_inlines=%d, sc_list) => %u", + name.GetCString(), name_type_mask, include_inlines, num_matches); } - return num_matches; } -uint32_t SymbolFileDWARF::FindFunctions(const RegularExpression ®ex, - bool include_inlines, bool append, - SymbolContextList &sc_list) { +void SymbolFileDWARF::FindFunctions(const RegularExpression ®ex, + bool include_inlines, + SymbolContextList &sc_list) { + std::lock_guard<std::recursive_mutex> guard(GetModuleMutex()); static Timer::Category func_cat(LLVM_PRETTY_FUNCTION); Timer scoped_timer(func_cat, "SymbolFileDWARF::FindFunctions (regex = '%s')", regex.GetText().str().c_str()); @@ -2285,22 +2310,13 @@ uint32_t SymbolFileDWARF::FindFunctions(const RegularExpression ®ex, if (log) { GetObjectFile()->GetModule()->LogMessage( - log, - "SymbolFileDWARF::FindFunctions (regex=\"%s\", append=%u, sc_list)", - regex.GetText().str().c_str(), append); + log, "SymbolFileDWARF::FindFunctions (regex=\"%s\", sc_list)", + regex.GetText().str().c_str()); } - // If we aren't appending the results to this list, then clear the list - if (!append) - sc_list.Clear(); - DWARFDebugInfo *info = DebugInfo(); if (!info) - return 0; - - // Remember how many sc_list are in the list before we search in case we are - // appending the results to a variable list. - uint32_t original_size = sc_list.GetSize(); + return; DIEArray offsets; m_index->GetFunctions(regex, offsets); @@ -2315,9 +2331,6 @@ uint32_t SymbolFileDWARF::FindFunctions(const RegularExpression ®ex, if (resolved_dies.insert(die.GetDIE()).second) ResolveFunction(die, include_inlines, sc_list); } - - // Return the number of variable that were appended to the list - return sc_list.GetSize() - original_size; } void SymbolFileDWARF::GetMangledNamesForFunction( @@ -2345,156 +2358,141 @@ void SymbolFileDWARF::GetMangledNamesForFunction( } } -uint32_t SymbolFileDWARF::FindTypes( +void SymbolFileDWARF::FindTypes( ConstString name, const CompilerDeclContext *parent_decl_ctx, - bool append, uint32_t max_matches, + uint32_t max_matches, llvm::DenseSet<lldb_private::SymbolFile *> &searched_symbol_files, TypeMap &types) { - // If we aren't appending the results to this list, then clear the list - if (!append) - types.Clear(); - + std::lock_guard<std::recursive_mutex> guard(GetModuleMutex()); // Make sure we haven't already searched this SymbolFile before... if (searched_symbol_files.count(this)) - return 0; - else - searched_symbol_files.insert(this); + return; + + searched_symbol_files.insert(this); DWARFDebugInfo *info = DebugInfo(); - if (info == nullptr) - return 0; + if (!info) + return; Log *log(LogChannelDWARF::GetLogIfAll(DWARF_LOG_LOOKUPS)); if (log) { if (parent_decl_ctx) GetObjectFile()->GetModule()->LogMessage( - log, "SymbolFileDWARF::FindTypes (sc, name=\"%s\", parent_decl_ctx = " - "%p (\"%s\"), append=%u, max_matches=%u, type_list)", + log, + "SymbolFileDWARF::FindTypes (sc, name=\"%s\", parent_decl_ctx = " + "%p (\"%s\"), max_matches=%u, type_list)", name.GetCString(), static_cast<const void *>(parent_decl_ctx), - parent_decl_ctx->GetName().AsCString("<NULL>"), append, max_matches); + parent_decl_ctx->GetName().AsCString("<NULL>"), max_matches); else GetObjectFile()->GetModule()->LogMessage( - log, "SymbolFileDWARF::FindTypes (sc, name=\"%s\", parent_decl_ctx = " - "NULL, append=%u, max_matches=%u, type_list)", - name.GetCString(), append, max_matches); + log, + "SymbolFileDWARF::FindTypes (sc, name=\"%s\", parent_decl_ctx = " + "NULL, max_matches=%u, type_list)", + name.GetCString(), max_matches); } if (!DeclContextMatchesThisSymbolFile(parent_decl_ctx)) - return 0; + return; DIEArray die_offsets; m_index->GetTypes(name, die_offsets); const size_t num_die_matches = die_offsets.size(); - if (num_die_matches) { - const uint32_t initial_types_size = types.GetSize(); - for (size_t i = 0; i < num_die_matches; ++i) { - const DIERef &die_ref = die_offsets[i]; - DWARFDIE die = GetDIE(die_ref); - - if (die) { - if (!DIEInDeclContext(parent_decl_ctx, die)) - continue; // The containing decl contexts don't match - - Type *matching_type = ResolveType(die, true, true); - if (matching_type) { - // We found a type pointer, now find the shared pointer form our type - // list - types.InsertUnique(matching_type->shared_from_this()); - if (types.GetSize() >= max_matches) - break; - } - } else { - m_index->ReportInvalidDIERef(die_ref, name.GetStringRef()); - } - } - const uint32_t num_matches = types.GetSize() - initial_types_size; - if (log && num_matches) { - if (parent_decl_ctx) { - GetObjectFile()->GetModule()->LogMessage( - log, "SymbolFileDWARF::FindTypes (sc, name=\"%s\", parent_decl_ctx " - "= %p (\"%s\"), append=%u, max_matches=%u, type_list) => %u", - name.GetCString(), static_cast<const void *>(parent_decl_ctx), - parent_decl_ctx->GetName().AsCString("<NULL>"), append, max_matches, - num_matches); - } else { - GetObjectFile()->GetModule()->LogMessage( - log, "SymbolFileDWARF::FindTypes (sc, name=\"%s\", parent_decl_ctx " - "= NULL, append=%u, max_matches=%u, type_list) => %u", - name.GetCString(), append, max_matches, num_matches); + for (size_t i = 0; i < num_die_matches; ++i) { + const DIERef &die_ref = die_offsets[i]; + DWARFDIE die = GetDIE(die_ref); + if (die) { + if (!DIEInDeclContext(parent_decl_ctx, die)) + continue; // The containing decl contexts don't match + + Type *matching_type = ResolveType(die, true, true); + if (matching_type) { + // We found a type pointer, now find the shared pointer form our type + // list + types.InsertUnique(matching_type->shared_from_this()); + if (types.GetSize() >= max_matches) + break; } + } else { + m_index->ReportInvalidDIERef(die_ref, name.GetStringRef()); } - return num_matches; - } else { + } + + // Next search through the reachable Clang modules. This only applies for + // DWARF objects compiled with -gmodules that haven't been processed by + // dsymutil. + if (num_die_matches < max_matches) { UpdateExternalModuleListIfNeeded(); - for (const auto &pair : m_external_type_modules) { - ModuleSP external_module_sp = pair.second; - if (external_module_sp) { - SymbolVendor *sym_vendor = external_module_sp->GetSymbolVendor(); - if (sym_vendor) { - const uint32_t num_external_matches = - sym_vendor->FindTypes(name, parent_decl_ctx, append, max_matches, - searched_symbol_files, types); - if (num_external_matches) - return num_external_matches; - } - } - } + for (const auto &pair : m_external_type_modules) + if (ModuleSP external_module_sp = pair.second) + if (SymbolFile *sym_file = external_module_sp->GetSymbolFile()) + sym_file->FindTypes(name, parent_decl_ctx, max_matches, + searched_symbol_files, types); } - return 0; + if (log && types.GetSize()) { + if (parent_decl_ctx) { + GetObjectFile()->GetModule()->LogMessage( + log, + "SymbolFileDWARF::FindTypes (sc, name=\"%s\", parent_decl_ctx " + "= %p (\"%s\"), max_matches=%u, type_list) => %u", + name.GetCString(), static_cast<const void *>(parent_decl_ctx), + parent_decl_ctx->GetName().AsCString("<NULL>"), max_matches, + types.GetSize()); + } else { + GetObjectFile()->GetModule()->LogMessage( + log, + "SymbolFileDWARF::FindTypes (sc, name=\"%s\", parent_decl_ctx " + "= NULL, max_matches=%u, type_list) => %u", + name.GetCString(), max_matches, types.GetSize()); + } + } } -size_t SymbolFileDWARF::FindTypes(const std::vector<CompilerContext> &context, - bool append, TypeMap &types) { - if (!append) - types.Clear(); - - if (context.empty()) - return 0; +void SymbolFileDWARF::FindTypes(llvm::ArrayRef<CompilerContext> pattern, + LanguageSet languages, TypeMap &types) { + std::lock_guard<std::recursive_mutex> guard(GetModuleMutex()); + if (pattern.empty()) + return; - ConstString name = context.back().name; + ConstString name = pattern.back().name; if (!name) - return 0; + return; DIEArray die_offsets; m_index->GetTypes(name, die_offsets); const size_t num_die_matches = die_offsets.size(); - if (num_die_matches) { - size_t num_matches = 0; - for (size_t i = 0; i < num_die_matches; ++i) { - const DIERef &die_ref = die_offsets[i]; - DWARFDIE die = GetDIE(die_ref); + for (size_t i = 0; i < num_die_matches; ++i) { + const DIERef &die_ref = die_offsets[i]; + DWARFDIE die = GetDIE(die_ref); - if (die) { - std::vector<CompilerContext> die_context; - die.GetDeclContext(die_context); - if (die_context != context) - continue; - - Type *matching_type = ResolveType(die, true, true); - if (matching_type) { - // We found a type pointer, now find the shared pointer form our type - // list - types.InsertUnique(matching_type->shared_from_this()); - ++num_matches; - } - } else { - m_index->ReportInvalidDIERef(die_ref, name.GetStringRef()); - } + if (!die) { + m_index->ReportInvalidDIERef(die_ref, name.GetStringRef()); + continue; } - return num_matches; + if (!languages[die.GetCU()->GetLanguageType()]) + continue; + + llvm::SmallVector<CompilerContext, 4> die_context; + die.GetDeclContext(die_context); + if (!contextMatches(die_context, pattern)) + continue; + + if (Type *matching_type = ResolveType(die, true, true)) + // We found a type pointer, now find the shared pointer form our type + // list. + types.InsertUnique(matching_type->shared_from_this()); } - return 0; } CompilerDeclContext SymbolFileDWARF::FindNamespace(ConstString name, const CompilerDeclContext *parent_decl_ctx) { + std::lock_guard<std::recursive_mutex> guard(GetModuleMutex()); Log *log(LogChannelDWARF::GetLogIfAll(DWARF_LOG_LOOKUPS)); if (log) { @@ -2536,8 +2534,9 @@ SymbolFileDWARF::FindNamespace(ConstString name, } if (log && namespace_decl_ctx) { GetObjectFile()->GetModule()->LogMessage( - log, "SymbolFileDWARF::FindNamespace (sc, name=\"%s\") => " - "CompilerDeclContext(%p/%p) \"%s\"", + log, + "SymbolFileDWARF::FindNamespace (sc, name=\"%s\") => " + "CompilerDeclContext(%p/%p) \"%s\"", name.GetCString(), static_cast<const void *>(namespace_decl_ctx.GetTypeSystem()), static_cast<const void *>(namespace_decl_ctx.GetOpaqueDeclContext()), @@ -2632,11 +2631,10 @@ SymbolFileDWARF::GetDeclContextDIEContainingDIE(const DWARFDIE &orig_die) { return DWARFDIE(); } -Symbol * -SymbolFileDWARF::GetObjCClassSymbol(ConstString objc_class_name) { +Symbol *SymbolFileDWARF::GetObjCClassSymbol(ConstString objc_class_name) { Symbol *objc_class_symbol = nullptr; - if (m_obj_file) { - Symtab *symtab = m_obj_file->GetSymtab(); + if (m_objfile_sp) { + Symtab *symtab = m_objfile_sp->GetSymtab(); if (symtab) { objc_class_symbol = symtab->FindFirstSymbolWithNameAndType( objc_class_name, eSymbolTypeObjCClass, Symtab::eDebugNo, @@ -2653,8 +2651,7 @@ SymbolFileDWARF::GetObjCClassSymbol(ConstString objc_class_name) { // worry about the debug map // DWARF file // if we are doing darwin DWARF in .o file debugging. -bool SymbolFileDWARF::Supports_DW_AT_APPLE_objc_complete_type( - DWARFUnit *cu) { +bool SymbolFileDWARF::Supports_DW_AT_APPLE_objc_complete_type(DWARFUnit *cu) { if (m_supports_DW_AT_APPLE_objc_complete_type == eLazyBoolCalculate) { m_supports_DW_AT_APPLE_objc_complete_type = eLazyBoolNo; if (cu && cu->Supports_DW_AT_APPLE_objc_complete_type()) @@ -2681,8 +2678,7 @@ bool SymbolFileDWARF::Supports_DW_AT_APPLE_objc_complete_type( // This function can be used when a DIE is found that is a forward declaration // DIE and we want to try and find a type that has the complete definition. TypeSP SymbolFileDWARF::FindCompleteObjCDefinitionTypeForDIE( - const DWARFDIE &die, ConstString type_name, - bool must_be_implementation) { + const DWARFDIE &die, ConstString type_name, bool must_be_implementation) { TypeSP type_sp; @@ -2727,7 +2723,7 @@ TypeSP SymbolFileDWARF::FindCompleteObjCDefinitionTypeForDIE( DEBUG_PRINTF("resolved 0x%8.8" PRIx64 " from %s to 0x%8.8" PRIx64 " (cu 0x%8.8" PRIx64 ")\n", die.GetID(), - m_obj_file->GetFileSpec().GetFilename().AsCString( + m_objfile_sp->GetFileSpec().GetFilename().AsCString( "<Unknown>"), type_die.GetID(), type_cu->GetID()); @@ -2849,8 +2845,9 @@ TypeSP SymbolFileDWARF::FindDefinitionTypeForDWARFDeclContext( DWARF_LOG_LOOKUPS)); if (log) { GetObjectFile()->GetModule()->LogMessage( - log, "SymbolFileDWARF::FindDefinitionTypeForDWARFDeclContext(tag=%" - "s, qualified-name='%s')", + log, + "SymbolFileDWARF::FindDefinitionTypeForDWARFDeclContext(tag=%" + "s, qualified-name='%s')", DW_TAG_value_to_name(dwarf_decl_ctx[0].tag), dwarf_decl_ctx.GetQualifiedName()); } @@ -2863,10 +2860,18 @@ TypeSP SymbolFileDWARF::FindDefinitionTypeForDWARFDeclContext( // use this to ensure any matches we find are in a language that this // type system supports const LanguageType language = dwarf_decl_ctx.GetLanguage(); - TypeSystem *type_system = (language == eLanguageTypeUnknown) - ? nullptr - : GetTypeSystemForLanguage(language); - + TypeSystem *type_system = nullptr; + if (language != eLanguageTypeUnknown) { + auto type_system_or_err = GetTypeSystemForLanguage(language); + if (auto err = type_system_or_err.takeError()) { + LLDB_LOG_ERROR( + lldb_private::GetLogIfAnyCategoriesSet(LIBLLDB_LOG_SYMBOLS), + std::move(err), "Cannot get TypeSystem for language {}", + Language::GetNameForLanguageType(language)); + } else { + type_system = &type_system_or_err.get(); + } + } if (num_matches) { for (size_t i = 0; i < num_matches; ++i) { const DIERef &die_ref = die_offsets[i]; @@ -2916,9 +2921,10 @@ TypeSP SymbolFileDWARF::FindDefinitionTypeForDWARFDeclContext( if (log) { GetObjectFile()->GetModule()->LogMessage( - log, "SymbolFileDWARF::" - "FindDefinitionTypeForDWARFDeclContext(tag=%s, " - "qualified-name='%s') trying die=0x%8.8x (%s)", + log, + "SymbolFileDWARF::" + "FindDefinitionTypeForDWARFDeclContext(tag=%s, " + "qualified-name='%s') trying die=0x%8.8x (%s)", DW_TAG_value_to_name(dwarf_decl_ctx[0].tag), dwarf_decl_ctx.GetQualifiedName(), type_die.GetOffset(), type_dwarf_decl_ctx.GetQualifiedName()); @@ -2937,9 +2943,10 @@ TypeSP SymbolFileDWARF::FindDefinitionTypeForDWARFDeclContext( std::string qualified_name; type_die.GetQualifiedName(qualified_name); GetObjectFile()->GetModule()->LogMessage( - log, "SymbolFileDWARF::" - "FindDefinitionTypeForDWARFDeclContext(tag=%s, " - "qualified-name='%s') ignoring die=0x%8.8x (%s)", + log, + "SymbolFileDWARF::" + "FindDefinitionTypeForDWARFDeclContext(tag=%s, " + "qualified-name='%s') ignoring die=0x%8.8x (%s)", DW_TAG_value_to_name(dwarf_decl_ctx[0].tag), dwarf_decl_ctx.GetQualifiedName(), type_die.GetOffset(), qualified_name.c_str()); @@ -2960,21 +2967,21 @@ TypeSP SymbolFileDWARF::ParseType(const SymbolContext &sc, const DWARFDIE &die, if (!die) return {}; - TypeSystem *type_system = + auto type_system_or_err = GetTypeSystemForLanguage(die.GetCU()->GetLanguageType()); - if (!type_system) + if (auto err = type_system_or_err.takeError()) { + LLDB_LOG_ERROR(lldb_private::GetLogIfAnyCategoriesSet(LIBLLDB_LOG_SYMBOLS), + std::move(err), "Unable to parse type"); return {}; + } - DWARFASTParser *dwarf_ast = type_system->GetDWARFParser(); + DWARFASTParser *dwarf_ast = type_system_or_err->GetDWARFParser(); if (!dwarf_ast) return {}; - Log *log = LogChannelDWARF::GetLogIfAll(DWARF_LOG_DEBUG_INFO); - TypeSP type_sp = dwarf_ast->ParseTypeFromDWARF(sc, die, log, type_is_new_ptr); + TypeSP type_sp = dwarf_ast->ParseTypeFromDWARF(sc, die, type_is_new_ptr); if (type_sp) { - TypeList *type_list = GetTypeList(); - if (type_list) - type_list->Insert(type_sp); + GetTypeList().Insert(type_sp); if (die.Tag() == DW_TAG_subprogram) { std::string scope_qualified_name(GetDeclContextForUID(die.GetID()) @@ -2995,12 +3002,21 @@ size_t SymbolFileDWARF::ParseTypes(const SymbolContext &sc, bool parse_siblings, bool parse_children) { size_t types_added = 0; DWARFDIE die = orig_die; + while (die) { + const dw_tag_t tag = die.Tag(); bool type_is_new = false; - if (ParseType(sc, die, &type_is_new).get()) { - if (type_is_new) - ++types_added; - } + + Tag dwarf_tag = static_cast<Tag>(tag); + + // TODO: Currently ParseTypeFromDWARF(...) which is called by ParseType(...) + // does not handle DW_TAG_subrange_type. It is not clear if this is a bug or + // not. + if (isType(dwarf_tag) && tag != DW_TAG_subrange_type) + ParseType(sc, die, &type_is_new); + + if (type_is_new) + ++types_added; if (parse_children && die.HasChildren()) { if (die.Tag() == DW_TAG_subprogram) { @@ -3020,7 +3036,7 @@ size_t SymbolFileDWARF::ParseTypes(const SymbolContext &sc, } size_t SymbolFileDWARF::ParseBlocksRecursive(Function &func) { - ASSERT_MODULE_LOCK(this); + std::lock_guard<std::recursive_mutex> guard(GetModuleMutex()); CompileUnit *comp_unit = func.GetCompileUnit(); lldbassert(comp_unit); @@ -3040,7 +3056,7 @@ size_t SymbolFileDWARF::ParseBlocksRecursive(Function &func) { } size_t SymbolFileDWARF::ParseTypes(CompileUnit &comp_unit) { - ASSERT_MODULE_LOCK(this); + std::lock_guard<std::recursive_mutex> guard(GetModuleMutex()); size_t types_added = 0; DWARFUnit *dwarf_cu = GetDWARFCompileUnit(&comp_unit); if (dwarf_cu) { @@ -3056,7 +3072,7 @@ size_t SymbolFileDWARF::ParseTypes(CompileUnit &comp_unit) { } size_t SymbolFileDWARF::ParseVariablesForContext(const SymbolContext &sc) { - ASSERT_MODULE_LOCK(this); + std::lock_guard<std::recursive_mutex> guard(GetModuleMutex()); if (sc.comp_unit != nullptr) { DWARFDebugInfo *info = DebugInfo(); if (info == nullptr) @@ -3193,15 +3209,18 @@ VariableSP SymbolFileDWARF::ParseVariableDIE(const SymbolContext &sc, uint32_t block_offset = form_value.BlockData() - debug_info_data.GetDataStart(); uint32_t block_length = form_value.Unsigned(); - location = DWARFExpression(module, debug_info_data, die.GetCU(), - block_offset, block_length); + location = DWARFExpression( + module, + DataExtractor(debug_info_data, block_offset, block_length), + die.GetCU()); } else if (DWARFFormValue::IsDataForm(form_value.Form())) { // Retrieve the value as a data expression. uint32_t data_offset = attributes.DIEOffsetAtIndex(i); if (auto data_length = form_value.GetFixedSize()) - location = - DWARFExpression(module, debug_info_data, die.GetCU(), - data_offset, *data_length); + location = DWARFExpression( + module, + DataExtractor(debug_info_data, data_offset, *data_length), + die.GetCU()); else { const uint8_t *data_pointer = form_value.BlockData(); if (data_pointer) { @@ -3217,17 +3236,21 @@ VariableSP SymbolFileDWARF::ParseVariableDIE(const SymbolContext &sc, if (form_value.Form() == DW_FORM_strp) { uint32_t data_offset = attributes.DIEOffsetAtIndex(i); if (auto data_length = form_value.GetFixedSize()) - location = - DWARFExpression(module, debug_info_data, die.GetCU(), - data_offset, *data_length); + location = DWARFExpression(module, + DataExtractor(debug_info_data, + data_offset, + *data_length), + die.GetCU()); } else { const char *str = form_value.AsCString(); uint32_t string_offset = str - (const char *)debug_info_data.GetDataStart(); uint32_t string_length = strlen(str) + 1; - location = - DWARFExpression(module, debug_info_data, die.GetCU(), - string_offset, string_length); + location = DWARFExpression(module, + DataExtractor(debug_info_data, + string_offset, + string_length), + die.GetCU()); } } } @@ -3241,17 +3264,15 @@ VariableSP SymbolFileDWARF::ParseVariableDIE(const SymbolContext &sc, uint32_t block_offset = form_value.BlockData() - data.GetDataStart(); uint32_t block_length = form_value.Unsigned(); - location = DWARFExpression(module, data, die.GetCU(), - block_offset, block_length); + location = DWARFExpression( + module, DataExtractor(data, block_offset, block_length), + die.GetCU()); } else { - const DWARFDataExtractor &debug_loc_data = DebugLocData(); - const dw_offset_t debug_loc_offset = form_value.Unsigned(); - - size_t loc_list_length = DWARFExpression::LocationListSize( - die.GetCU(), debug_loc_data, debug_loc_offset); - if (loc_list_length > 0) { - location = DWARFExpression(module, debug_loc_data, die.GetCU(), - debug_loc_offset, loc_list_length); + DataExtractor data = DebugLocData(); + const dw_offset_t offset = form_value.Unsigned(); + if (data.ValidOffset(offset)) { + data = DataExtractor(data, offset, data.GetByteSize() - offset); + location = DWARFExpression(module, data, die.GetCU()); assert(func_low_pc != LLDB_INVALID_ADDRESS); location.SetLocationListSlide( func_low_pc - @@ -3522,6 +3543,8 @@ SymbolFileDWARF::FindBlockContainingSpecification( spec_block_die_offset) return die; } break; + default: + break; } // Give the concrete function die specified by "func_die_offset", find the @@ -3577,8 +3600,7 @@ size_t SymbolFileDWARF::ParseVariables(const SymbolContext &sc, } else { GetObjectFile()->GetModule()->ReportError( "parent 0x%8.8" PRIx64 " %s with no valid compile unit in " - "symbol context for 0x%8.8" PRIx64 - " %s.\n", + "symbol context for 0x%8.8" PRIx64 " %s.\n", sc_parent_die.GetID(), sc_parent_die.GetTagAsCString(), orig_die.GetID(), orig_die.GetTagAsCString()); } @@ -3654,9 +3676,57 @@ size_t SymbolFileDWARF::ParseVariables(const SymbolContext &sc, return vars_added; } +/// Collect call site parameters in a DW_TAG_call_site DIE. +static CallSiteParameterArray +CollectCallSiteParameters(ModuleSP module, DWARFDIE call_site_die) { + CallSiteParameterArray parameters; + for (DWARFDIE child = call_site_die.GetFirstChild(); child.IsValid(); + child = child.GetSibling()) { + if (child.Tag() != DW_TAG_call_site_parameter) + continue; + + llvm::Optional<DWARFExpression> LocationInCallee = {}; + llvm::Optional<DWARFExpression> LocationInCaller = {}; + + DWARFAttributes attributes; + const size_t num_attributes = child.GetAttributes(attributes); + + // Parse the location at index \p attr_index within this call site parameter + // DIE, or return None on failure. + auto parse_simple_location = + [&](int attr_index) -> llvm::Optional<DWARFExpression> { + DWARFFormValue form_value; + if (!attributes.ExtractFormValueAtIndex(attr_index, form_value)) + return {}; + if (!DWARFFormValue::IsBlockForm(form_value.Form())) + return {}; + auto data = child.GetData(); + uint32_t block_offset = form_value.BlockData() - data.GetDataStart(); + uint32_t block_length = form_value.Unsigned(); + return DWARFExpression(module, + DataExtractor(data, block_offset, block_length), + child.GetCU()); + }; + + for (size_t i = 0; i < num_attributes; ++i) { + dw_attr_t attr = attributes.AttributeAtIndex(i); + if (attr == DW_AT_location) + LocationInCallee = parse_simple_location(i); + if (attr == DW_AT_call_value) + LocationInCaller = parse_simple_location(i); + } + + if (LocationInCallee && LocationInCaller) { + CallSiteParameter param = {*LocationInCallee, *LocationInCaller}; + parameters.push_back(param); + } + } + return parameters; +} + /// Collect call graph edges present in a function DIE. static std::vector<lldb_private::CallEdge> -CollectCallEdges(DWARFDIE function_die) { +CollectCallEdges(ModuleSP module, DWARFDIE function_die) { // Check if the function has a supported call site-related attribute. // TODO: In the future it may be worthwhile to support call_all_source_calls. uint64_t has_call_edges = @@ -3693,9 +3763,28 @@ CollectCallEdges(DWARFDIE function_die) { addr_t return_pc = child.GetAttributeValueAsAddress(DW_AT_call_return_pc, LLDB_INVALID_ADDRESS); + // Extract call site parameters. + CallSiteParameterArray parameters = + CollectCallSiteParameters(module, child); + LLDB_LOG(log, "CollectCallEdges: Found call origin: {0} (retn-PC: {1:x})", call_origin.GetPubname(), return_pc); - call_edges.emplace_back(call_origin.GetMangledName(), return_pc); + if (log && parameters.size()) { + for (const CallSiteParameter ¶m : parameters) { + StreamString callee_loc_desc, caller_loc_desc; + param.LocationInCallee.GetDescription(&callee_loc_desc, + eDescriptionLevelBrief, + LLDB_INVALID_ADDRESS, nullptr); + param.LocationInCaller.GetDescription(&caller_loc_desc, + eDescriptionLevelBrief, + LLDB_INVALID_ADDRESS, nullptr); + LLDB_LOG(log, "CollectCallEdges: \tparam: {0} => {1}", + callee_loc_desc.GetString(), caller_loc_desc.GetString()); + } + } + + call_edges.emplace_back(call_origin.GetMangledName(), return_pc, + std::move(parameters)); } return call_edges; } @@ -3704,7 +3793,7 @@ std::vector<lldb_private::CallEdge> SymbolFileDWARF::ParseCallEdgesInFunction(UserID func_id) { DWARFDIE func_die = GetDIE(func_id.GetID()); if (func_die.IsValid()) - return CollectCallEdges(func_die); + return CollectCallEdges(GetObjectFile()->GetModule(), func_die); return {}; } @@ -3713,11 +3802,17 @@ ConstString SymbolFileDWARF::GetPluginName() { return GetPluginNameStatic(); } uint32_t SymbolFileDWARF::GetPluginVersion() { return 1; } -void SymbolFileDWARF::Dump(lldb_private::Stream &s) { m_index->Dump(s); } +void SymbolFileDWARF::Dump(lldb_private::Stream &s) { + SymbolFile::Dump(s); + m_index->Dump(s); +} void SymbolFileDWARF::DumpClangAST(Stream &s) { - TypeSystem *ts = GetTypeSystemForLanguage(eLanguageTypeC_plus_plus); - ClangASTContext *clang = llvm::dyn_cast_or_null<ClangASTContext>(ts); + auto ts_or_err = GetTypeSystemForLanguage(eLanguageTypeC_plus_plus); + if (!ts_or_err) + return; + ClangASTContext *clang = + llvm::dyn_cast_or_null<ClangASTContext>(&ts_or_err.get()); if (!clang) return; clang->Dump(s); @@ -3727,10 +3822,8 @@ SymbolFileDWARFDebugMap *SymbolFileDWARF::GetDebugMapSymfile() { if (m_debug_map_symfile == nullptr && !m_debug_map_module_wp.expired()) { lldb::ModuleSP module_sp(m_debug_map_module_wp.lock()); if (module_sp) { - SymbolVendor *sym_vendor = module_sp->GetSymbolVendor(); - if (sym_vendor) - m_debug_map_symfile = - (SymbolFileDWARFDebugMap *)sym_vendor->GetSymbolFile(); + m_debug_map_symfile = + (SymbolFileDWARFDebugMap *)module_sp->GetSymbolFile(); } } return m_debug_map_symfile; @@ -3746,9 +3839,9 @@ SymbolFileDWARF::GetLocationListFormat() const { SymbolFileDWARFDwp *SymbolFileDWARF::GetDwpSymbolFile() { llvm::call_once(m_dwp_symfile_once_flag, [this]() { ModuleSpec module_spec; - module_spec.GetFileSpec() = m_obj_file->GetFileSpec(); + module_spec.GetFileSpec() = m_objfile_sp->GetFileSpec(); module_spec.GetSymbolFileSpec() = - FileSpec(m_obj_file->GetFileSpec().GetPath() + ".dwp"); + FileSpec(m_objfile_sp->GetFileSpec().GetPath() + ".dwp"); FileSpecList search_paths = Target::GetDefaultDebugFileSearchPaths(); FileSpec dwp_filespec = diff --git a/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.h b/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.h index 018af47305f4..04cb11d426be 100644 --- a/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.h +++ b/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.h @@ -46,7 +46,8 @@ class DWARFDebugAranges; class DWARFDebugInfo; class DWARFDebugInfoEntry; class DWARFDebugLine; -class DWARFDebugRangesBase; +class DWARFDebugRanges; +class DWARFDebugRngLists; class DWARFDeclContext; class DWARFFormValue; class DWARFTypeUnit; @@ -78,13 +79,13 @@ public: static const char *GetPluginDescriptionStatic(); static lldb_private::SymbolFile * - CreateInstance(lldb_private::ObjectFile *obj_file); + CreateInstance(lldb::ObjectFileSP objfile_sp); static lldb_private::FileSpecList GetSymlinkPaths(); // Constructors and Destructors - SymbolFileDWARF(lldb_private::ObjectFile *ofile, + SymbolFileDWARF(lldb::ObjectFileSP objfile_sp, lldb_private::SectionList *dwo_section_list); ~SymbolFileDWARF() override; @@ -95,10 +96,6 @@ public: // Compile Unit function calls - uint32_t GetNumCompileUnits() override; - - lldb::CompUnitSP ParseCompileUnitAtIndex(uint32_t index) override; - lldb::LanguageType ParseLanguage(lldb_private::CompileUnit &comp_unit) override; @@ -108,6 +105,10 @@ public: bool ParseDebugMacros(lldb_private::CompileUnit &comp_unit) override; + void + ForEachExternalModule(lldb_private::CompileUnit &comp_unit, + llvm::function_ref<void(lldb::ModuleSP)> f) override; + bool ParseSupportFiles(lldb_private::CompileUnit &comp_unit, lldb_private::FileSpecList &support_files) override; @@ -156,47 +157,46 @@ public: lldb::SymbolContextItem resolve_scope, lldb_private::SymbolContextList &sc_list) override; - uint32_t + void FindGlobalVariables(lldb_private::ConstString name, const lldb_private::CompilerDeclContext *parent_decl_ctx, uint32_t max_matches, lldb_private::VariableList &variables) override; - uint32_t FindGlobalVariables(const lldb_private::RegularExpression ®ex, - uint32_t max_matches, - lldb_private::VariableList &variables) override; + void FindGlobalVariables(const lldb_private::RegularExpression ®ex, + uint32_t max_matches, + lldb_private::VariableList &variables) override; - uint32_t - FindFunctions(lldb_private::ConstString name, - const lldb_private::CompilerDeclContext *parent_decl_ctx, - lldb::FunctionNameType name_type_mask, bool include_inlines, - bool append, lldb_private::SymbolContextList &sc_list) override; + void FindFunctions(lldb_private::ConstString name, + const lldb_private::CompilerDeclContext *parent_decl_ctx, + lldb::FunctionNameType name_type_mask, + bool include_inlines, + lldb_private::SymbolContextList &sc_list) override; - uint32_t FindFunctions(const lldb_private::RegularExpression ®ex, - bool include_inlines, bool append, - lldb_private::SymbolContextList &sc_list) override; + void FindFunctions(const lldb_private::RegularExpression ®ex, + bool include_inlines, + lldb_private::SymbolContextList &sc_list) override; void GetMangledNamesForFunction( const std::string &scope_qualified_name, std::vector<lldb_private::ConstString> &mangled_names) override; - uint32_t + void FindTypes(lldb_private::ConstString name, const lldb_private::CompilerDeclContext *parent_decl_ctx, - bool append, uint32_t max_matches, + uint32_t max_matches, llvm::DenseSet<lldb_private::SymbolFile *> &searched_symbol_files, lldb_private::TypeMap &types) override; - size_t FindTypes(const std::vector<lldb_private::CompilerContext> &context, - bool append, lldb_private::TypeMap &types) override; + void FindTypes(llvm::ArrayRef<lldb_private::CompilerContext> pattern, + lldb_private::LanguageSet languages, + lldb_private::TypeMap &types) override; - lldb_private::TypeList *GetTypeList() override; + void GetTypes(lldb_private::SymbolContextScope *sc_scope, + lldb::TypeClass type_mask, + lldb_private::TypeList &type_list) override; - size_t GetTypes(lldb_private::SymbolContextScope *sc_scope, - lldb::TypeClass type_mask, - lldb_private::TypeList &type_list) override; - - lldb_private::TypeSystem * + llvm::Expected<lldb_private::TypeSystem &> GetTypeSystemForLanguage(lldb::LanguageType language) override; lldb_private::CompilerDeclContext FindNamespace( @@ -223,8 +223,8 @@ public: const DWARFDebugInfo *DebugInfo() const; - DWARFDebugRangesBase *GetDebugRanges(); - DWARFDebugRangesBase *GetDebugRngLists(); + DWARFDebugRanges *GetDebugRanges(); + DWARFDebugRngLists *GetDebugRngLists(); const lldb_private::DWARFDataExtractor &DebugLocData(); @@ -331,6 +331,12 @@ protected: bool DeclContextMatchesThisSymbolFile( const lldb_private::CompilerDeclContext *decl_ctx); + uint32_t CalculateNumCompileUnits() override; + + lldb::CompUnitSP ParseCompileUnitAtIndex(uint32_t index) override; + + lldb_private::TypeList &GetTypeList() override; + virtual DWARFUnit * GetDWARFCompileUnit(lldb_private::CompileUnit *comp_unit); @@ -477,8 +483,8 @@ protected: typedef std::set<lldb::user_id_t> DIERefSet; typedef llvm::StringMap<DIERefSet> NameToOffsetMap; NameToOffsetMap m_function_scope_qualified_name_map; - std::unique_ptr<DWARFDebugRangesBase> m_ranges; - std::unique_ptr<DWARFDebugRangesBase> m_rnglists; + std::unique_ptr<DWARFDebugRanges> m_ranges; + std::unique_ptr<DWARFDebugRngLists> m_rnglists; UniqueDWARFASTTypeMap m_unique_ast_type_map; DIEToTypePtr m_die_to_type; DIEToVariableSP m_die_to_variable_sp; diff --git a/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDebugMap.cpp b/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDebugMap.cpp index 8ec64dbaf764..a50d4e460bae 100644 --- a/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDebugMap.cpp +++ b/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDebugMap.cpp @@ -41,7 +41,7 @@ using namespace lldb_private; // Subclass lldb_private::Module so we can intercept the // "Module::GetObjectFile()" (so we can fixup the object file sections) and -// also for "Module::GetSymbolVendor()" (so we can fixup the symbol file id. +// also for "Module::GetSymbolFile()" (so we can fixup the symbol file id. const SymbolFileDWARFDebugMap::FileRangeMap & SymbolFileDWARFDebugMap::CompileUnitInfo::GetFileRangeMap( @@ -60,11 +60,11 @@ SymbolFileDWARFDebugMap::CompileUnitInfo::GetFileRangeMap( return file_range_map; Log *log(LogChannelDWARF::GetLogIfAll(DWARF_LOG_DEBUG_MAP)); - if (log) - log->Printf( - "%p: SymbolFileDWARFDebugMap::CompileUnitInfo::GetFileRangeMap ('%s')", - static_cast<void *>(this), - oso_module->GetSpecificationDescription().c_str()); + LLDB_LOGF( + log, + "%p: SymbolFileDWARFDebugMap::CompileUnitInfo::GetFileRangeMap ('%s')", + static_cast<void *>(this), + oso_module->GetSpecificationDescription().c_str()); std::vector<SymbolFileDWARFDebugMap::CompileUnitInfo *> cu_infos; if (exe_symfile->GetCompUnitInfosForModule(oso_module, cu_infos)) { @@ -173,12 +173,12 @@ public: ~DebugMapModule() override = default; - SymbolVendor * - GetSymbolVendor(bool can_create = true, - lldb_private::Stream *feedback_strm = nullptr) override { + SymbolFile * + GetSymbolFile(bool can_create = true, + lldb_private::Stream *feedback_strm = nullptr) override { // Scope for locker if (m_symfile_up.get() || !can_create) - return m_symfile_up.get(); + return m_symfile_up ? m_symfile_up->GetSymbolFile() : nullptr; ModuleSP exe_module_sp(m_exe_module_wp.lock()); if (exe_module_sp) { @@ -186,30 +186,28 @@ public: ObjectFile *oso_objfile = GetObjectFile(); if (oso_objfile) { std::lock_guard<std::recursive_mutex> guard(m_mutex); - SymbolVendor *symbol_vendor = - Module::GetSymbolVendor(can_create, feedback_strm); - if (symbol_vendor) { + if (SymbolFile *symfile = + Module::GetSymbolFile(can_create, feedback_strm)) { // Set a pointer to this class to set our OSO DWARF file know that // the DWARF is being used along with a debug map and that it will // have the remapped sections that we do below. SymbolFileDWARF *oso_symfile = - SymbolFileDWARFDebugMap::GetSymbolFileAsSymbolFileDWARF( - symbol_vendor->GetSymbolFile()); + SymbolFileDWARFDebugMap::GetSymbolFileAsSymbolFileDWARF(symfile); if (!oso_symfile) return nullptr; ObjectFile *exe_objfile = exe_module_sp->GetObjectFile(); - SymbolVendor *exe_sym_vendor = exe_module_sp->GetSymbolVendor(); + SymbolFile *exe_symfile = exe_module_sp->GetSymbolFile(); - if (exe_objfile && exe_sym_vendor) { + if (exe_objfile && exe_symfile) { oso_symfile->SetDebugMapModule(exe_module_sp); // Set the ID of the symbol file DWARF to the index of the OSO // shifted left by 32 bits to provide a unique prefix for any // UserID's that get created in the symbol file. oso_symfile->SetID(((uint64_t)m_cu_idx + 1ull) << 32ull); } - return symbol_vendor; + return symfile; } } } @@ -239,13 +237,13 @@ const char *SymbolFileDWARFDebugMap::GetPluginDescriptionStatic() { return "DWARF and DWARF3 debug symbol file reader (debug map)."; } -SymbolFile *SymbolFileDWARFDebugMap::CreateInstance(ObjectFile *obj_file) { - return new SymbolFileDWARFDebugMap(obj_file); +SymbolFile *SymbolFileDWARFDebugMap::CreateInstance(ObjectFileSP objfile_sp) { + return new SymbolFileDWARFDebugMap(std::move(objfile_sp)); } -SymbolFileDWARFDebugMap::SymbolFileDWARFDebugMap(ObjectFile *ofile) - : SymbolFile(ofile), m_flags(), m_compile_unit_infos(), m_func_indexes(), - m_glob_indexes(), +SymbolFileDWARFDebugMap::SymbolFileDWARFDebugMap(ObjectFileSP objfile_sp) + : SymbolFile(std::move(objfile_sp)), m_flags(), m_compile_unit_infos(), + m_func_indexes(), m_glob_indexes(), m_supports_DW_AT_APPLE_objc_complete_type(eLazyBoolCalculate) {} SymbolFileDWARFDebugMap::~SymbolFileDWARFDebugMap() {} @@ -260,12 +258,12 @@ void SymbolFileDWARFDebugMap::InitOSO() { // If the object file has been stripped, there is no sense in looking further // as all of the debug symbols for the debug map will not be available - if (m_obj_file->IsStripped()) + if (m_objfile_sp->IsStripped()) return; // Also make sure the file type is some sort of executable. Core files, debug // info files (dSYM), object files (.o files), and stub libraries all can - switch (m_obj_file->GetType()) { + switch (m_objfile_sp->GetType()) { case ObjectFile::eTypeInvalid: case ObjectFile::eTypeCoreFile: case ObjectFile::eTypeDebugInfo: @@ -286,7 +284,7 @@ void SymbolFileDWARFDebugMap::InitOSO() { // these files exist and also contain valid DWARF. If we get any of that then // we return the abilities of the first N_OSO's DWARF. - Symtab *symtab = m_obj_file->GetSymtab(); + Symtab *symtab = m_objfile_sp->GetSymtab(); if (symtab) { Log *log(LogChannelDWARF::GetLogIfAll(DWARF_LOG_DEBUG_MAP)); @@ -352,7 +350,7 @@ void SymbolFileDWARFDebugMap::InitOSO() { // The sibling index can't be less that or equal to the current index // "i" if (sibling_idx == UINT32_MAX) { - m_obj_file->GetModule()->ReportError( + m_objfile_sp->GetModule()->ReportError( "N_SO in symbol with UID %u has invalid sibling in debug map, " "please file a bug and attach the binary listed in this error", so_symbol->GetID()); @@ -363,28 +361,27 @@ void SymbolFileDWARFDebugMap::InitOSO() { m_compile_unit_infos[i].first_symbol_id = so_symbol->GetID(); m_compile_unit_infos[i].last_symbol_id = last_symbol->GetID(); - if (log) - log->Printf("Initialized OSO 0x%8.8x: file=%s", i, - oso_symbol->GetName().GetCString()); + LLDB_LOGF(log, "Initialized OSO 0x%8.8x: file=%s", i, + oso_symbol->GetName().GetCString()); } } else { if (oso_symbol == nullptr) - m_obj_file->GetModule()->ReportError( + m_objfile_sp->GetModule()->ReportError( "N_OSO symbol[%u] can't be found, please file a bug and attach " "the binary listed in this error", oso_idx); else if (so_symbol == nullptr) - m_obj_file->GetModule()->ReportError( + m_objfile_sp->GetModule()->ReportError( "N_SO not found for N_OSO symbol[%u], please file a bug and " "attach the binary listed in this error", oso_idx); else if (so_symbol->GetType() != eSymbolTypeSourceFile) - m_obj_file->GetModule()->ReportError( + m_objfile_sp->GetModule()->ReportError( "N_SO has incorrect symbol type (%u) for N_OSO symbol[%u], " "please file a bug and attach the binary listed in this error", so_symbol->GetType(), oso_idx); else if (oso_symbol->GetType() != eSymbolTypeSourceFile) - m_obj_file->GetModule()->ReportError( + m_objfile_sp->GetModule()->ReportError( "N_OSO has incorrect symbol type (%u) for N_OSO symbol[%u], " "please file a bug and attach the binary listed in this error", oso_symbol->GetType(), oso_idx); @@ -421,7 +418,11 @@ Module *SymbolFileDWARFDebugMap::GetModuleByCompUnitInfo( // than the one from the CU. auto oso_mod_time = std::chrono::time_point_cast<std::chrono::seconds>( FileSystem::Instance().GetModificationTime(oso_file)); - if (oso_mod_time != comp_unit_info->oso_mod_time) { + // A timestamp of 0 means that the linker was in deterministic mode. In + // that case, we should skip the check against the filesystem last + // modification timestamp, since it will never match. + if (comp_unit_info->oso_mod_time != llvm::sys::TimePoint<>() && + oso_mod_time != comp_unit_info->oso_mod_time) { obj_file->GetModule()->ReportError( "debug map object file '%s' has changed (actual time is " "%s, debug map time is %s" @@ -448,7 +449,7 @@ Module *SymbolFileDWARFDebugMap::GetModuleByCompUnitInfo( // since .o files for "i386-apple-ios" will historically show up as "i386 // -apple-macosx" due to the lack of a LC_VERSION_MIN_MACOSX or // LC_VERSION_MIN_IPHONEOS load command... - oso_arch.SetTriple(m_obj_file->GetModule() + oso_arch.SetTriple(m_objfile_sp->GetModule() ->GetArchitecture() .GetTriple() .getArchName() @@ -534,12 +535,8 @@ SymbolFileDWARFDebugMap::GetSymbolFileAsSymbolFileDWARF(SymbolFile *sym_file) { SymbolFileDWARF *SymbolFileDWARFDebugMap::GetSymbolFileByCompUnitInfo( CompileUnitInfo *comp_unit_info) { - Module *oso_module = GetModuleByCompUnitInfo(comp_unit_info); - if (oso_module) { - SymbolVendor *sym_vendor = oso_module->GetSymbolVendor(); - if (sym_vendor) - return GetSymbolFileAsSymbolFileDWARF(sym_vendor->GetSymbolFile()); - } + if (Module *oso_module = GetModuleByCompUnitInfo(comp_unit_info)) + return GetSymbolFileAsSymbolFileDWARF(oso_module->GetSymbolFile()); return nullptr; } @@ -562,7 +559,7 @@ uint32_t SymbolFileDWARFDebugMap::CalculateAbilities() { return 0; } -uint32_t SymbolFileDWARFDebugMap::GetNumCompileUnits() { +uint32_t SymbolFileDWARFDebugMap::CalculateNumCompileUnits() { InitOSO(); return m_compile_unit_infos.size(); } @@ -581,13 +578,12 @@ CompUnitSP SymbolFileDWARFDebugMap::ParseCompileUnitAtIndex(uint32_t cu_idx) { lldb::user_id_t cu_id = 0; m_compile_unit_infos[cu_idx].compile_unit_sp = std::make_shared<CompileUnit>( - m_obj_file->GetModule(), nullptr, so_file_spec, cu_id, + m_objfile_sp->GetModule(), nullptr, so_file_spec, cu_id, eLanguageTypeUnknown, eLazyBoolCalculate); if (m_compile_unit_infos[cu_idx].compile_unit_sp) { - // Let our symbol vendor know about this compile unit - m_obj_file->GetModule()->GetSymbolVendor()->SetCompileUnitAtIndex( - cu_idx, m_compile_unit_infos[cu_idx].compile_unit_sp); + SetCompileUnitAtIndex(cu_idx, + m_compile_unit_infos[cu_idx].compile_unit_sp); } } } @@ -625,6 +621,7 @@ size_t SymbolFileDWARFDebugMap::GetCompUnitInfosForModule( lldb::LanguageType SymbolFileDWARFDebugMap::ParseLanguage(CompileUnit &comp_unit) { + std::lock_guard<std::recursive_mutex> guard(GetModuleMutex()); SymbolFileDWARF *oso_dwarf = GetSymbolFile(comp_unit); if (oso_dwarf) return oso_dwarf->ParseLanguage(comp_unit); @@ -632,6 +629,7 @@ SymbolFileDWARFDebugMap::ParseLanguage(CompileUnit &comp_unit) { } size_t SymbolFileDWARFDebugMap::ParseFunctions(CompileUnit &comp_unit) { + std::lock_guard<std::recursive_mutex> guard(GetModuleMutex()); SymbolFileDWARF *oso_dwarf = GetSymbolFile(comp_unit); if (oso_dwarf) return oso_dwarf->ParseFunctions(comp_unit); @@ -639,6 +637,7 @@ size_t SymbolFileDWARFDebugMap::ParseFunctions(CompileUnit &comp_unit) { } bool SymbolFileDWARFDebugMap::ParseLineTable(CompileUnit &comp_unit) { + std::lock_guard<std::recursive_mutex> guard(GetModuleMutex()); SymbolFileDWARF *oso_dwarf = GetSymbolFile(comp_unit); if (oso_dwarf) return oso_dwarf->ParseLineTable(comp_unit); @@ -646,14 +645,24 @@ bool SymbolFileDWARFDebugMap::ParseLineTable(CompileUnit &comp_unit) { } bool SymbolFileDWARFDebugMap::ParseDebugMacros(CompileUnit &comp_unit) { + std::lock_guard<std::recursive_mutex> guard(GetModuleMutex()); SymbolFileDWARF *oso_dwarf = GetSymbolFile(comp_unit); if (oso_dwarf) return oso_dwarf->ParseDebugMacros(comp_unit); return false; } +void SymbolFileDWARFDebugMap::ForEachExternalModule( + CompileUnit &comp_unit, llvm::function_ref<void(ModuleSP)> f) { + std::lock_guard<std::recursive_mutex> guard(GetModuleMutex()); + SymbolFileDWARF *oso_dwarf = GetSymbolFile(comp_unit); + if (oso_dwarf) + oso_dwarf->ForEachExternalModule(comp_unit, f); +} + bool SymbolFileDWARFDebugMap::ParseSupportFiles(CompileUnit &comp_unit, FileSpecList &support_files) { + std::lock_guard<std::recursive_mutex> guard(GetModuleMutex()); SymbolFileDWARF *oso_dwarf = GetSymbolFile(comp_unit); if (oso_dwarf) return oso_dwarf->ParseSupportFiles(comp_unit, support_files); @@ -661,6 +670,7 @@ bool SymbolFileDWARFDebugMap::ParseSupportFiles(CompileUnit &comp_unit, } bool SymbolFileDWARFDebugMap::ParseIsOptimized(CompileUnit &comp_unit) { + std::lock_guard<std::recursive_mutex> guard(GetModuleMutex()); SymbolFileDWARF *oso_dwarf = GetSymbolFile(comp_unit); if (oso_dwarf) return oso_dwarf->ParseIsOptimized(comp_unit); @@ -669,6 +679,7 @@ bool SymbolFileDWARFDebugMap::ParseIsOptimized(CompileUnit &comp_unit) { bool SymbolFileDWARFDebugMap::ParseImportedModules( const SymbolContext &sc, std::vector<SourceModule> &imported_modules) { + std::lock_guard<std::recursive_mutex> guard(GetModuleMutex()); SymbolFileDWARF *oso_dwarf = GetSymbolFile(sc); if (oso_dwarf) return oso_dwarf->ParseImportedModules(sc, imported_modules); @@ -676,6 +687,7 @@ bool SymbolFileDWARFDebugMap::ParseImportedModules( } size_t SymbolFileDWARFDebugMap::ParseBlocksRecursive(Function &func) { + std::lock_guard<std::recursive_mutex> guard(GetModuleMutex()); CompileUnit *comp_unit = func.GetCompileUnit(); if (!comp_unit) return 0; @@ -687,6 +699,7 @@ size_t SymbolFileDWARFDebugMap::ParseBlocksRecursive(Function &func) { } size_t SymbolFileDWARFDebugMap::ParseTypes(CompileUnit &comp_unit) { + std::lock_guard<std::recursive_mutex> guard(GetModuleMutex()); SymbolFileDWARF *oso_dwarf = GetSymbolFile(comp_unit); if (oso_dwarf) return oso_dwarf->ParseTypes(comp_unit); @@ -695,6 +708,7 @@ size_t SymbolFileDWARFDebugMap::ParseTypes(CompileUnit &comp_unit) { size_t SymbolFileDWARFDebugMap::ParseVariablesForContext(const SymbolContext &sc) { + std::lock_guard<std::recursive_mutex> guard(GetModuleMutex()); SymbolFileDWARF *oso_dwarf = GetSymbolFile(sc); if (oso_dwarf) return oso_dwarf->ParseVariablesForContext(sc); @@ -702,6 +716,7 @@ SymbolFileDWARFDebugMap::ParseVariablesForContext(const SymbolContext &sc) { } Type *SymbolFileDWARFDebugMap::ResolveTypeUID(lldb::user_id_t type_uid) { + std::lock_guard<std::recursive_mutex> guard(GetModuleMutex()); const uint64_t oso_idx = GetOSOIndexFromUserID(type_uid); SymbolFileDWARF *oso_dwarf = GetSymbolFileByOSOIndex(oso_idx); if (oso_dwarf) @@ -738,8 +753,9 @@ uint32_t SymbolFileDWARFDebugMap::ResolveSymbolContext(const Address &exe_so_addr, SymbolContextItem resolve_scope, SymbolContext &sc) { + std::lock_guard<std::recursive_mutex> guard(GetModuleMutex()); uint32_t resolved_flags = 0; - Symtab *symtab = m_obj_file->GetSymtab(); + Symtab *symtab = m_objfile_sp->GetSymtab(); if (symtab) { const addr_t exe_file_addr = exe_so_addr.GetFileAddress(); @@ -766,7 +782,7 @@ SymbolFileDWARFDebugMap::ResolveSymbolContext(const Address &exe_so_addr, Address oso_so_addr; if (oso_module->ResolveFileAddress(oso_file_addr, oso_so_addr)) { resolved_flags |= - oso_module->GetSymbolVendor()->ResolveSymbolContext( + oso_module->GetSymbolFile()->ResolveSymbolContext( oso_so_addr, resolve_scope, sc); } } @@ -780,6 +796,7 @@ SymbolFileDWARFDebugMap::ResolveSymbolContext(const Address &exe_so_addr, uint32_t SymbolFileDWARFDebugMap::ResolveSymbolContext( const FileSpec &file_spec, uint32_t line, bool check_inlines, SymbolContextItem resolve_scope, SymbolContextList &sc_list) { + std::lock_guard<std::recursive_mutex> guard(GetModuleMutex()); const uint32_t initial = sc_list.GetSize(); const uint32_t cu_count = GetNumCompileUnits(); @@ -807,12 +824,11 @@ uint32_t SymbolFileDWARFDebugMap::ResolveSymbolContext( return sc_list.GetSize() - initial; } -uint32_t SymbolFileDWARFDebugMap::PrivateFindGlobalVariables( +void SymbolFileDWARFDebugMap::PrivateFindGlobalVariables( ConstString name, const CompilerDeclContext *parent_decl_ctx, const std::vector<uint32_t> &indexes, // Indexes into the symbol table that match "name" uint32_t max_matches, VariableList &variables) { - const uint32_t original_size = variables.GetSize(); const size_t match_count = indexes.size(); for (size_t i = 0; i < match_count; ++i) { uint32_t oso_idx; @@ -821,28 +837,26 @@ uint32_t SymbolFileDWARFDebugMap::PrivateFindGlobalVariables( if (comp_unit_info) { SymbolFileDWARF *oso_dwarf = GetSymbolFileByOSOIndex(oso_idx); if (oso_dwarf) { - if (oso_dwarf->FindGlobalVariables(name, parent_decl_ctx, max_matches, - variables)) - if (variables.GetSize() > max_matches) - break; + oso_dwarf->FindGlobalVariables(name, parent_decl_ctx, max_matches, + variables); + if (variables.GetSize() > max_matches) + break; } } } - return variables.GetSize() - original_size; } -uint32_t SymbolFileDWARFDebugMap::FindGlobalVariables( +void SymbolFileDWARFDebugMap::FindGlobalVariables( ConstString name, const CompilerDeclContext *parent_decl_ctx, uint32_t max_matches, VariableList &variables) { - - // Remember how many variables are in the list before we search. - const uint32_t original_size = variables.GetSize(); - + std::lock_guard<std::recursive_mutex> guard(GetModuleMutex()); uint32_t total_matches = 0; ForEachSymbolFile([&](SymbolFileDWARF *oso_dwarf) -> bool { - const uint32_t oso_matches = oso_dwarf->FindGlobalVariables( - name, parent_decl_ctx, max_matches, variables); + const uint32_t old_size = variables.GetSize(); + oso_dwarf->FindGlobalVariables(name, parent_decl_ctx, max_matches, + variables); + const uint32_t oso_matches = variables.GetSize() - old_size; if (oso_matches > 0) { total_matches += oso_matches; @@ -861,22 +875,18 @@ uint32_t SymbolFileDWARFDebugMap::FindGlobalVariables( return false; }); - - // Return the number of variable that were appended to the list - return variables.GetSize() - original_size; } -uint32_t -SymbolFileDWARFDebugMap::FindGlobalVariables(const RegularExpression ®ex, - uint32_t max_matches, - VariableList &variables) { - // Remember how many variables are in the list before we search. - const uint32_t original_size = variables.GetSize(); - +void SymbolFileDWARFDebugMap::FindGlobalVariables( + const RegularExpression ®ex, uint32_t max_matches, + VariableList &variables) { + std::lock_guard<std::recursive_mutex> guard(GetModuleMutex()); uint32_t total_matches = 0; ForEachSymbolFile([&](SymbolFileDWARF *oso_dwarf) -> bool { - const uint32_t oso_matches = - oso_dwarf->FindGlobalVariables(regex, max_matches, variables); + const uint32_t old_size = variables.GetSize(); + oso_dwarf->FindGlobalVariables(regex, max_matches, variables); + + const uint32_t oso_matches = variables.GetSize() - old_size; if (oso_matches > 0) { total_matches += oso_matches; @@ -895,9 +905,6 @@ SymbolFileDWARFDebugMap::FindGlobalVariables(const RegularExpression ®ex, return false; }); - - // Return the number of variable that were appended to the list - return variables.GetSize() - original_size; } int SymbolFileDWARFDebugMap::SymbolContainsSymbolWithIndex( @@ -993,71 +1000,58 @@ static void RemoveFunctionsWithModuleNotEqualTo(const ModuleSP &module_sp, } } -uint32_t SymbolFileDWARFDebugMap::FindFunctions( +void SymbolFileDWARFDebugMap::FindFunctions( ConstString name, const CompilerDeclContext *parent_decl_ctx, - FunctionNameType name_type_mask, bool include_inlines, bool append, + FunctionNameType name_type_mask, bool include_inlines, SymbolContextList &sc_list) { + std::lock_guard<std::recursive_mutex> guard(GetModuleMutex()); static Timer::Category func_cat(LLVM_PRETTY_FUNCTION); Timer scoped_timer(func_cat, "SymbolFileDWARFDebugMap::FindFunctions (name = %s)", name.GetCString()); - uint32_t initial_size = 0; - if (append) - initial_size = sc_list.GetSize(); - else - sc_list.Clear(); - ForEachSymbolFile([&](SymbolFileDWARF *oso_dwarf) -> bool { uint32_t sc_idx = sc_list.GetSize(); - if (oso_dwarf->FindFunctions(name, parent_decl_ctx, name_type_mask, - include_inlines, true, sc_list)) { - RemoveFunctionsWithModuleNotEqualTo(m_obj_file->GetModule(), sc_list, + oso_dwarf->FindFunctions(name, parent_decl_ctx, name_type_mask, + include_inlines, sc_list); + if (!sc_list.IsEmpty()) { + RemoveFunctionsWithModuleNotEqualTo(m_objfile_sp->GetModule(), sc_list, sc_idx); } return false; }); - - return sc_list.GetSize() - initial_size; } -uint32_t SymbolFileDWARFDebugMap::FindFunctions(const RegularExpression ®ex, - bool include_inlines, - bool append, - SymbolContextList &sc_list) { +void SymbolFileDWARFDebugMap::FindFunctions(const RegularExpression ®ex, + bool include_inlines, + SymbolContextList &sc_list) { + std::lock_guard<std::recursive_mutex> guard(GetModuleMutex()); static Timer::Category func_cat(LLVM_PRETTY_FUNCTION); Timer scoped_timer(func_cat, "SymbolFileDWARFDebugMap::FindFunctions (regex = '%s')", regex.GetText().str().c_str()); - uint32_t initial_size = 0; - if (append) - initial_size = sc_list.GetSize(); - else - sc_list.Clear(); - ForEachSymbolFile([&](SymbolFileDWARF *oso_dwarf) -> bool { uint32_t sc_idx = sc_list.GetSize(); - if (oso_dwarf->FindFunctions(regex, include_inlines, true, sc_list)) { - RemoveFunctionsWithModuleNotEqualTo(m_obj_file->GetModule(), sc_list, + oso_dwarf->FindFunctions(regex, include_inlines, sc_list); + if (!sc_list.IsEmpty()) { + RemoveFunctionsWithModuleNotEqualTo(m_objfile_sp->GetModule(), sc_list, sc_idx); } return false; }); - - return sc_list.GetSize() - initial_size; } -size_t SymbolFileDWARFDebugMap::GetTypes(SymbolContextScope *sc_scope, - lldb::TypeClass type_mask, - TypeList &type_list) { +void SymbolFileDWARFDebugMap::GetTypes(SymbolContextScope *sc_scope, + lldb::TypeClass type_mask, + TypeList &type_list) { + std::lock_guard<std::recursive_mutex> guard(GetModuleMutex()); static Timer::Category func_cat(LLVM_PRETTY_FUNCTION); Timer scoped_timer(func_cat, "SymbolFileDWARFDebugMap::GetTypes (type_mask = 0x%8.8x)", type_mask); - uint32_t initial_size = type_list.GetSize(); SymbolFileDWARF *oso_dwarf = nullptr; if (sc_scope) { SymbolContext sc; @@ -1075,7 +1069,6 @@ size_t SymbolFileDWARFDebugMap::GetTypes(SymbolContextScope *sc_scope, return false; }); } - return type_list.GetSize() - initial_size; } std::vector<lldb_private::CallEdge> @@ -1124,7 +1117,7 @@ TypeSP SymbolFileDWARFDebugMap::FindCompleteObjCDefinitionTypeForDIE( // N_SO. SymbolFileDWARF *oso_dwarf = nullptr; TypeSP type_sp; - ObjectFile *module_objfile = m_obj_file->GetModule()->GetObjectFile(); + ObjectFile *module_objfile = m_objfile_sp->GetModule()->GetObjectFile(); if (module_objfile) { Symtab *symtab = module_objfile->GetSymtab(); if (symtab) { @@ -1177,23 +1170,17 @@ TypeSP SymbolFileDWARFDebugMap::FindCompleteObjCDefinitionTypeForDIE( return TypeSP(); } -uint32_t SymbolFileDWARFDebugMap::FindTypes( +void SymbolFileDWARFDebugMap::FindTypes( ConstString name, const CompilerDeclContext *parent_decl_ctx, - bool append, uint32_t max_matches, + uint32_t max_matches, llvm::DenseSet<lldb_private::SymbolFile *> &searched_symbol_files, TypeMap &types) { - if (!append) - types.Clear(); - - const uint32_t initial_types_size = types.GetSize(); - + std::lock_guard<std::recursive_mutex> guard(GetModuleMutex()); ForEachSymbolFile([&](SymbolFileDWARF *oso_dwarf) -> bool { - oso_dwarf->FindTypes(name, parent_decl_ctx, append, max_matches, + oso_dwarf->FindTypes(name, parent_decl_ctx, max_matches, searched_symbol_files, types); return types.GetSize() >= max_matches; }); - - return types.GetSize() - initial_types_size; } // @@ -1212,6 +1199,7 @@ uint32_t SymbolFileDWARFDebugMap::FindTypes( CompilerDeclContext SymbolFileDWARFDebugMap::FindNamespace( lldb_private::ConstString name, const CompilerDeclContext *parent_decl_ctx) { + std::lock_guard<std::recursive_mutex> guard(GetModuleMutex()); CompilerDeclContext matching_namespace; ForEachSymbolFile([&](SymbolFileDWARF *oso_dwarf) -> bool { @@ -1284,8 +1272,7 @@ void SymbolFileDWARFDebugMap::SetCompileUnit(SymbolFileDWARF *oso_dwarf, cu_sp.get()); } else { m_compile_unit_infos[cu_idx].compile_unit_sp = cu_sp; - m_obj_file->GetModule()->GetSymbolVendor()->SetCompileUnitAtIndex( - cu_idx, cu_sp); + SetCompileUnitAtIndex(cu_idx, cu_sp); } } } @@ -1388,8 +1375,8 @@ bool SymbolFileDWARFDebugMap::LinkOSOAddress(Address &addr) { if (addr_module == exe_module) return true; // Address is already in terms of the main executable module - CompileUnitInfo *cu_info = GetCompileUnitInfo(GetSymbolFileAsSymbolFileDWARF( - addr_module->GetSymbolVendor()->GetSymbolFile())); + CompileUnitInfo *cu_info = GetCompileUnitInfo( + GetSymbolFileAsSymbolFileDWARF(addr_module->GetSymbolFile())); if (cu_info) { const lldb::addr_t oso_file_addr = addr.GetFileAddress(); const FileRangeMap::Entry *oso_range_entry = diff --git a/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDebugMap.h b/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDebugMap.h index afc6142e8231..7adee1b356ce 100644 --- a/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDebugMap.h +++ b/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDebugMap.h @@ -34,19 +34,16 @@ public: static const char *GetPluginDescriptionStatic(); static lldb_private::SymbolFile * - CreateInstance(lldb_private::ObjectFile *obj_file); + CreateInstance(lldb::ObjectFileSP objfile_sp); // Constructors and Destructors - SymbolFileDWARFDebugMap(lldb_private::ObjectFile *ofile); + SymbolFileDWARFDebugMap(lldb::ObjectFileSP objfile_sp); ~SymbolFileDWARFDebugMap() override; uint32_t CalculateAbilities() override; void InitializeObject() override; // Compile Unit function calls - uint32_t GetNumCompileUnits() override; - lldb::CompUnitSP ParseCompileUnitAtIndex(uint32_t index) override; - lldb::LanguageType ParseLanguage(lldb_private::CompileUnit &comp_unit) override; @@ -56,6 +53,10 @@ public: bool ParseDebugMacros(lldb_private::CompileUnit &comp_unit) override; + void + ForEachExternalModule(lldb_private::CompileUnit &comp_unit, + llvm::function_ref<void(lldb::ModuleSP)> f) override; + bool ParseSupportFiles(lldb_private::CompileUnit &comp_unit, lldb_private::FileSpecList &support_files) override; @@ -91,34 +92,34 @@ public: bool check_inlines, lldb::SymbolContextItem resolve_scope, lldb_private::SymbolContextList &sc_list) override; - uint32_t + void FindGlobalVariables(lldb_private::ConstString name, const lldb_private::CompilerDeclContext *parent_decl_ctx, uint32_t max_matches, lldb_private::VariableList &variables) override; - uint32_t FindGlobalVariables(const lldb_private::RegularExpression ®ex, - uint32_t max_matches, - lldb_private::VariableList &variables) override; - uint32_t - FindFunctions(lldb_private::ConstString name, - const lldb_private::CompilerDeclContext *parent_decl_ctx, - lldb::FunctionNameType name_type_mask, bool include_inlines, - bool append, lldb_private::SymbolContextList &sc_list) override; - uint32_t FindFunctions(const lldb_private::RegularExpression ®ex, - bool include_inlines, bool append, - lldb_private::SymbolContextList &sc_list) override; - uint32_t + void FindGlobalVariables(const lldb_private::RegularExpression ®ex, + uint32_t max_matches, + lldb_private::VariableList &variables) override; + void FindFunctions(lldb_private::ConstString name, + const lldb_private::CompilerDeclContext *parent_decl_ctx, + lldb::FunctionNameType name_type_mask, + bool include_inlines, + lldb_private::SymbolContextList &sc_list) override; + void FindFunctions(const lldb_private::RegularExpression ®ex, + bool include_inlines, + lldb_private::SymbolContextList &sc_list) override; + void FindTypes(lldb_private::ConstString name, const lldb_private::CompilerDeclContext *parent_decl_ctx, - bool append, uint32_t max_matches, + uint32_t max_matches, llvm::DenseSet<lldb_private::SymbolFile *> &searched_symbol_files, lldb_private::TypeMap &types) override; lldb_private::CompilerDeclContext FindNamespace( lldb_private::ConstString name, const lldb_private::CompilerDeclContext *parent_decl_ctx) override; - size_t GetTypes(lldb_private::SymbolContextScope *sc_scope, - lldb::TypeClass type_mask, - lldb_private::TypeList &type_list) override; + void GetTypes(lldb_private::SymbolContextScope *sc_scope, + lldb::TypeClass type_mask, + lldb_private::TypeList &type_list) override; std::vector<lldb_private::CallEdge> ParseCallEdgesInFunction(lldb_private::UserID func_id) override; @@ -174,6 +175,9 @@ protected: // Protected Member Functions void InitOSO(); + uint32_t CalculateNumCompileUnits() override; + lldb::CompUnitSP ParseCompileUnitAtIndex(uint32_t index) override; + static uint32_t GetOSOIndexFromUserID(lldb::user_id_t uid) { return (uint32_t)((uid >> 32ull) - 1ull); } @@ -232,7 +236,7 @@ protected: static int SymbolContainsSymbolWithID(lldb::user_id_t *symbol_idx_ptr, const CompileUnitInfo *comp_unit_info); - uint32_t PrivateFindGlobalVariables( + void PrivateFindGlobalVariables( lldb_private::ConstString name, const lldb_private::CompilerDeclContext *parent_decl_ctx, const std::vector<uint32_t> &name_symbol_indexes, uint32_t max_matches, diff --git a/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDwo.cpp b/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDwo.cpp index c5b54b65ea29..b0f7e813d4f8 100644 --- a/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDwo.cpp +++ b/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDwo.cpp @@ -23,21 +23,21 @@ using namespace lldb_private; SymbolFileDWARFDwo::SymbolFileDWARFDwo(ObjectFileSP objfile, DWARFCompileUnit &dwarf_cu) - : SymbolFileDWARF(objfile.get(), objfile->GetSectionList( - /*update_module_section_list*/ false)), - m_obj_file_sp(objfile), m_base_dwarf_cu(dwarf_cu) { + : SymbolFileDWARF(objfile, objfile->GetSectionList( + /*update_module_section_list*/ false)), + m_base_dwarf_cu(dwarf_cu) { SetID(((lldb::user_id_t)dwarf_cu.GetID()) << 32); } void SymbolFileDWARFDwo::LoadSectionData(lldb::SectionType sect_type, DWARFDataExtractor &data) { const SectionList *section_list = - m_obj_file->GetSectionList(false /* update_module_section_list */); + m_objfile_sp->GetSectionList(false /* update_module_section_list */); if (section_list) { SectionSP section_sp(section_list->FindSectionByType(sect_type, true)); if (section_sp) { - if (m_obj_file->ReadSectionData(section_sp.get(), data) != 0) + if (m_objfile_sp->ReadSectionData(section_sp.get(), data) != 0) return; data.Clear(); @@ -140,7 +140,7 @@ SymbolFileDWARFDwo::GetLocationListFormat() const { return DWARFExpression::SplitDwarfLocationList; } -TypeSystem * +llvm::Expected<TypeSystem &> SymbolFileDWARFDwo::GetTypeSystemForLanguage(LanguageType language) { return GetBaseSymbolFile().GetTypeSystemForLanguage(language); } diff --git a/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDwo.h b/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDwo.h index 9b2f3bb84c4f..ad290cdcf65e 100644 --- a/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDwo.h +++ b/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDwo.h @@ -30,7 +30,7 @@ public: size_t GetObjCMethodDIEOffsets(lldb_private::ConstString class_name, DIEArray &method_die_offsets) override; - lldb_private::TypeSystem * + llvm::Expected<lldb_private::TypeSystem &> GetTypeSystemForLanguage(lldb::LanguageType language) override; DWARFDIE @@ -71,7 +71,6 @@ protected: DWARFCompileUnit *ComputeCompileUnit(); - lldb::ObjectFileSP m_obj_file_sp; DWARFCompileUnit &m_base_dwarf_cu; DWARFCompileUnit *m_cu = nullptr; }; diff --git a/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFProperties.td b/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFProperties.td new file mode 100644 index 000000000000..ef6ae3498588 --- /dev/null +++ b/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFProperties.td @@ -0,0 +1,12 @@ +include "../../../../include/lldb/Core/PropertiesBase.td" + +let Definition = "symbolfiledwarf" in { + def SymLinkPaths: Property<"comp-dir-symlink-paths", "FileSpecList">, + Global, + DefaultStringValue<"">, + Desc<"If the DW_AT_comp_dir matches any of these paths the symbolic links will be resolved at DWARF parse time.">; + def IgnoreIndexes: Property<"ignore-file-indexes", "Boolean">, + Global, + DefaultFalse, + Desc<"Ignore indexes present in the object files and always index DWARF manually.">; +} diff --git a/source/Plugins/SymbolFile/DWARF/UniqueDWARFASTType.cpp b/source/Plugins/SymbolFile/DWARF/UniqueDWARFASTType.cpp index 8da7e2226266..4862fea8d079 100644 --- a/source/Plugins/SymbolFile/DWARF/UniqueDWARFASTType.cpp +++ b/source/Plugins/SymbolFile/DWARF/UniqueDWARFASTType.cpp @@ -55,6 +55,8 @@ bool UniqueDWARFASTTypeList::Find(const DWARFDIE &die, case DW_TAG_partial_unit: done = true; break; + default: + break; } } parent_arg_die = parent_arg_die.GetParent(); diff --git a/source/Plugins/SymbolFile/NativePDB/CompileUnitIndex.cpp b/source/Plugins/SymbolFile/NativePDB/CompileUnitIndex.cpp index 1838204e4ca6..830d78f81679 100644 --- a/source/Plugins/SymbolFile/NativePDB/CompileUnitIndex.cpp +++ b/source/Plugins/SymbolFile/NativePDB/CompileUnitIndex.cpp @@ -130,7 +130,7 @@ CompilandIndexItem &CompileUnitIndex::GetOrCreateCompiland(uint16_t modi) { if (!stream_data) { llvm::pdb::ModuleDebugStreamRef debug_stream(descriptor, nullptr); - cci = llvm::make_unique<CompilandIndexItem>(PdbCompilandId{ modi }, debug_stream, std::move(descriptor)); + cci = std::make_unique<CompilandIndexItem>(PdbCompilandId{ modi }, debug_stream, std::move(descriptor)); return *cci; } @@ -139,7 +139,7 @@ CompilandIndexItem &CompileUnitIndex::GetOrCreateCompiland(uint16_t modi) { cantFail(debug_stream.reload()); - cci = llvm::make_unique<CompilandIndexItem>( + cci = std::make_unique<CompilandIndexItem>( PdbCompilandId{modi}, std::move(debug_stream), std::move(descriptor)); ParseExtendedInfo(m_index, *cci); diff --git a/source/Plugins/SymbolFile/NativePDB/DWARFLocationExpression.cpp b/source/Plugins/SymbolFile/NativePDB/DWARFLocationExpression.cpp index 3d8bfb058721..6aaff06cc134 100644 --- a/source/Plugins/SymbolFile/NativePDB/DWARFLocationExpression.cpp +++ b/source/Plugins/SymbolFile/NativePDB/DWARFLocationExpression.cpp @@ -122,7 +122,7 @@ static DWARFExpression MakeLocationExpressionInternal(lldb::ModuleSP module, DataBufferSP buffer = std::make_shared<DataBufferHeap>(stream.GetData(), stream.GetSize()); DataExtractor extractor(buffer, byte_order, address_size, byte_size); - DWARFExpression result(module, extractor, nullptr, 0, buffer->GetByteSize()); + DWARFExpression result(module, extractor, nullptr); result.SetRegisterKind(register_kind); return result; @@ -247,6 +247,6 @@ DWARFExpression lldb_private::npdb::MakeConstantLocationExpression( .take_front(size); buffer->CopyData(bytes.data(), size); DataExtractor extractor(buffer, lldb::eByteOrderLittle, address_size); - DWARFExpression result(nullptr, extractor, nullptr, 0, size); + DWARFExpression result(nullptr, extractor, nullptr); return result; } diff --git a/source/Plugins/SymbolFile/NativePDB/PdbAstBuilder.cpp b/source/Plugins/SymbolFile/NativePDB/PdbAstBuilder.cpp index 4991be8e70ce..986b0b785d87 100644 --- a/source/Plugins/SymbolFile/NativePDB/PdbAstBuilder.cpp +++ b/source/Plugins/SymbolFile/NativePDB/PdbAstBuilder.cpp @@ -121,13 +121,6 @@ AnyScopesHaveTemplateParams(llvm::ArrayRef<llvm::ms_demangle::Node *> scopes) { return false; } -static ClangASTContext &GetClangASTContext(ObjectFile &obj) { - TypeSystem *ts = - obj.GetModule()->GetTypeSystemForLanguage(lldb::eLanguageTypeC_plus_plus); - lldbassert(ts); - return static_cast<ClangASTContext &>(*ts); -} - static llvm::Optional<clang::CallingConv> TranslateCallingConvention(llvm::codeview::CallingConvention conv) { using CC = llvm::codeview::CallingConvention; @@ -209,8 +202,8 @@ static bool IsAnonymousNamespaceName(llvm::StringRef name) { return name == "`anonymous namespace'" || name == "`anonymous-namespace'"; } -PdbAstBuilder::PdbAstBuilder(ObjectFile &obj, PdbIndex &index) - : m_index(index), m_clang(GetClangASTContext(obj)) { +PdbAstBuilder::PdbAstBuilder(ObjectFile &obj, PdbIndex &index, ClangASTContext &clang) + : m_index(index), m_clang(clang) { BuildParentMap(); } @@ -465,9 +458,9 @@ clang::Decl *PdbAstBuilder::GetOrCreateSymbolForId(PdbCompilandSymId id) { } } -clang::Decl *PdbAstBuilder::GetOrCreateDeclForUid(PdbSymUid uid) { +llvm::Optional<CompilerDecl> PdbAstBuilder::GetOrCreateDeclForUid(PdbSymUid uid) { if (clang::Decl *result = TryGetDecl(uid)) - return result; + return ToCompilerDecl(*result); clang::Decl *result = nullptr; switch (uid.kind()) { @@ -480,13 +473,13 @@ clang::Decl *PdbAstBuilder::GetOrCreateDeclForUid(PdbSymUid uid) { result = tag; break; } - return nullptr; + return llvm::None; } default: - return nullptr; + return llvm::None; } m_uid_to_decl[toOpaqueUid(uid)] = result; - return result; + return ToCompilerDecl(*result); } clang::DeclContext *PdbAstBuilder::GetOrCreateDeclContextForUid(PdbSymUid uid) { @@ -494,8 +487,10 @@ clang::DeclContext *PdbAstBuilder::GetOrCreateDeclContextForUid(PdbSymUid uid) { if (uid.asCompilandSym().offset == 0) return FromCompilerDeclContext(GetTranslationUnitDecl()); } - - clang::Decl *decl = GetOrCreateDeclForUid(uid); + auto option = GetOrCreateDeclForUid(uid); + if (!option) + return nullptr; + clang::Decl *decl = FromCompilerDecl(option.getValue()); if (!decl) return nullptr; @@ -1089,7 +1084,7 @@ void PdbAstBuilder::CreateFunctionParameters(PdbCompilandSymId func_id, CompilerType param_type_ct(&m_clang, qt.getAsOpaquePtr()); clang::ParmVarDecl *param = m_clang.CreateParameterDeclaration( &function_decl, param_name.str().c_str(), param_type_ct, - clang::SC_None); + clang::SC_None, true); lldbassert(m_uid_to_decl.count(toOpaqueUid(param_uid)) == 0); m_uid_to_decl[toOpaqueUid(param_uid)] = param; diff --git a/source/Plugins/SymbolFile/NativePDB/PdbAstBuilder.h b/source/Plugins/SymbolFile/NativePDB/PdbAstBuilder.h index 67d024741e0d..a4242e90810d 100644 --- a/source/Plugins/SymbolFile/NativePDB/PdbAstBuilder.h +++ b/source/Plugins/SymbolFile/NativePDB/PdbAstBuilder.h @@ -51,11 +51,12 @@ struct DeclStatus { class PdbAstBuilder { public: // Constructors and Destructors - PdbAstBuilder(ObjectFile &obj, PdbIndex &index); + PdbAstBuilder(ObjectFile &obj, PdbIndex &index, ClangASTContext &clang); lldb_private::CompilerDeclContext GetTranslationUnitDecl(); - clang::Decl *GetOrCreateDeclForUid(PdbSymUid uid); + llvm::Optional<lldb_private::CompilerDecl> + GetOrCreateDeclForUid(PdbSymUid uid); clang::DeclContext *GetOrCreateDeclContextForUid(PdbSymUid uid); clang::DeclContext *GetParentDeclContext(PdbSymUid uid); @@ -76,7 +77,7 @@ public: CompilerDecl ToCompilerDecl(clang::Decl &decl); CompilerType ToCompilerType(clang::QualType qt); CompilerDeclContext ToCompilerDeclContext(clang::DeclContext &context); - clang::Decl * FromCompilerDecl(CompilerDecl decl); + clang::Decl *FromCompilerDecl(CompilerDecl decl); clang::DeclContext *FromCompilerDeclContext(CompilerDeclContext context); ClangASTContext &clang() { return m_clang; } diff --git a/source/Plugins/SymbolFile/NativePDB/PdbFPOProgramToDWARFExpression.cpp b/source/Plugins/SymbolFile/NativePDB/PdbFPOProgramToDWARFExpression.cpp index 79dd010ff311..a7bc23519710 100644 --- a/source/Plugins/SymbolFile/NativePDB/PdbFPOProgramToDWARFExpression.cpp +++ b/source/Plugins/SymbolFile/NativePDB/PdbFPOProgramToDWARFExpression.cpp @@ -51,54 +51,23 @@ static uint32_t ResolveLLDBRegisterNum(llvm::StringRef reg_name, llvm::Triple::A return npdb::GetLLDBRegisterNumber(arch_type, reg_id); } -static bool ParseFPOSingleAssignmentProgram(llvm::StringRef program, - llvm::BumpPtrAllocator &alloc, - llvm::StringRef ®ister_name, - Node *&ast) { - // lvalue of assignment is always first token - // rvalue program goes next - std::tie(register_name, program) = getToken(program); - if (register_name.empty()) - return false; - - ast = Parse(program, alloc); - return ast != nullptr; -} - -static Node *ParseFPOProgram(llvm::StringRef program, +static Node *ResolveFPOProgram(llvm::StringRef program, llvm::StringRef register_name, llvm::Triple::ArchType arch_type, llvm::BumpPtrAllocator &alloc) { - llvm::DenseMap<llvm::StringRef, Node *> dependent_programs; - - size_t cur = 0; - while (true) { - size_t assign_index = program.find('=', cur); - if (assign_index == llvm::StringRef::npos) { - llvm::StringRef tail = program.slice(cur, llvm::StringRef::npos); - if (!tail.trim().empty()) { - // missing assign operator - return nullptr; - } - break; - } - llvm::StringRef assignment_program = program.slice(cur, assign_index); - - llvm::StringRef lvalue_name; - Node *rvalue_ast = nullptr; - if (!ParseFPOSingleAssignmentProgram(assignment_program, alloc, lvalue_name, - rvalue_ast)) { - return nullptr; - } - - lldbassert(rvalue_ast); + std::vector<std::pair<llvm::StringRef, Node *>> parsed = + postfix::ParseFPOProgram(program, alloc); + for (auto it = parsed.begin(), end = parsed.end(); it != end; ++it) { // Emplace valid dependent subtrees to make target assignment independent // from predecessors. Resolve all other SymbolNodes as registers. bool success = - ResolveSymbols(rvalue_ast, [&](SymbolNode &symbol) -> Node * { - if (Node *node = dependent_programs.lookup(symbol.GetName())) - return node; + ResolveSymbols(it->second, [&](SymbolNode &symbol) -> Node * { + for (const auto &pair : llvm::make_range(parsed.begin(), it)) { + if (pair.first == symbol.GetName()) + return pair.second; + } + uint32_t reg_num = ResolveLLDBRegisterNum(symbol.GetName().drop_front(1), arch_type); @@ -110,13 +79,10 @@ static Node *ParseFPOProgram(llvm::StringRef program, if (!success) return nullptr; - if (lvalue_name == register_name) { + if (it->first == register_name) { // found target assignment program - no need to parse further - return rvalue_ast; + return it->second; } - - dependent_programs[lvalue_name] = rvalue_ast; - cur = assign_index + 1; } return nullptr; @@ -127,7 +93,7 @@ bool lldb_private::npdb::TranslateFPOProgramToDWARFExpression( llvm::Triple::ArchType arch_type, Stream &stream) { llvm::BumpPtrAllocator node_alloc; Node *target_program = - ParseFPOProgram(program, register_name, arch_type, node_alloc); + ResolveFPOProgram(program, register_name, arch_type, node_alloc); if (target_program == nullptr) { return false; } diff --git a/source/Plugins/SymbolFile/NativePDB/PdbUtil.cpp b/source/Plugins/SymbolFile/NativePDB/PdbUtil.cpp index 1f5c97da81cf..fc047e25a2f4 100644 --- a/source/Plugins/SymbolFile/NativePDB/PdbUtil.cpp +++ b/source/Plugins/SymbolFile/NativePDB/PdbUtil.cpp @@ -641,14 +641,14 @@ VariableInfo lldb_private::npdb::GetVariableLocationInfo( llvm::StringRef program; if (GetFrameDataProgram(index, ranges, program)) { result.location = - MakeVFrameRelLocationExpression(program, loc.Offset, module); + MakeVFrameRelLocationExpression(program, loc.Hdr.Offset, module); result.ranges = std::move(ranges); } else { // invalid variable } } else { result.location = - MakeRegRelLocationExpression(base_reg, loc.Offset, module); + MakeRegRelLocationExpression(base_reg, loc.Hdr.Offset, module); result.ranges = std::move(ranges); } } else if (loc_specifier_cvs.kind() == S_DEFRANGE_REGISTER_REL) { diff --git a/source/Plugins/SymbolFile/NativePDB/SymbolFileNativePDB.cpp b/source/Plugins/SymbolFile/NativePDB/SymbolFileNativePDB.cpp index e27d4699ae2f..33b8da3b543b 100644 --- a/source/Plugins/SymbolFile/NativePDB/SymbolFileNativePDB.cpp +++ b/source/Plugins/SymbolFile/NativePDB/SymbolFileNativePDB.cpp @@ -20,7 +20,6 @@ #include "lldb/Core/StreamBuffer.h" #include "lldb/Core/StreamFile.h" #include "lldb/Symbol/ClangASTContext.h" -#include "lldb/Symbol/ClangASTImporter.h" #include "lldb/Symbol/ClangExternalASTSourceCommon.h" #include "lldb/Symbol/ClangUtil.h" #include "lldb/Symbol/CompileUnit.h" @@ -30,6 +29,7 @@ #include "lldb/Symbol/SymbolVendor.h" #include "lldb/Symbol/Variable.h" #include "lldb/Symbol/VariableList.h" +#include "lldb/Utility/Log.h" #include "llvm/DebugInfo/CodeView/CVRecord.h" #include "llvm/DebugInfo/CodeView/CVTypeVisitor.h" @@ -90,10 +90,10 @@ static std::unique_ptr<PDBFile> loadPDBFile(std::string PdbPath, std::unique_ptr<llvm::MemoryBuffer> Buffer = std::move(*ErrorOrBuffer); llvm::StringRef Path = Buffer->getBufferIdentifier(); - auto Stream = llvm::make_unique<llvm::MemoryBufferByteStream>( + auto Stream = std::make_unique<llvm::MemoryBufferByteStream>( std::move(Buffer), llvm::support::little); - auto File = llvm::make_unique<PDBFile>(Path, std::move(Stream), Allocator); + auto File = std::make_unique<PDBFile>(Path, std::move(Stream), Allocator); if (auto EC = File->parseFileHeaders()) { llvm::consumeError(std::move(EC)); return nullptr; @@ -119,6 +119,8 @@ loadMatchingPDBFile(std::string exe_path, llvm::BumpPtrAllocator &allocator) { } OwningBinary<Binary> binary = std::move(*expected_binary); + // TODO: Avoid opening the PE/COFF binary twice by reading this information + // directly from the lldb_private::ObjectFile. auto *obj = llvm::dyn_cast<llvm::object::COFFObjectFile>(binary.getBinary()); if (!obj) return nullptr; @@ -264,27 +266,27 @@ const char *SymbolFileNativePDB::GetPluginDescriptionStatic() { return "Microsoft PDB debug symbol cross-platform file reader."; } -SymbolFile *SymbolFileNativePDB::CreateInstance(ObjectFile *obj_file) { - return new SymbolFileNativePDB(obj_file); +SymbolFile *SymbolFileNativePDB::CreateInstance(ObjectFileSP objfile_sp) { + return new SymbolFileNativePDB(std::move(objfile_sp)); } -SymbolFileNativePDB::SymbolFileNativePDB(ObjectFile *object_file) - : SymbolFile(object_file) {} +SymbolFileNativePDB::SymbolFileNativePDB(ObjectFileSP objfile_sp) + : SymbolFile(std::move(objfile_sp)) {} SymbolFileNativePDB::~SymbolFileNativePDB() {} uint32_t SymbolFileNativePDB::CalculateAbilities() { uint32_t abilities = 0; - if (!m_obj_file) + if (!m_objfile_sp) return 0; if (!m_index) { // Lazily load and match the PDB file, but only do this once. std::unique_ptr<PDBFile> file_up = - loadMatchingPDBFile(m_obj_file->GetFileSpec().GetPath(), m_allocator); + loadMatchingPDBFile(m_objfile_sp->GetFileSpec().GetPath(), m_allocator); if (!file_up) { - auto module_sp = m_obj_file->GetModule(); + auto module_sp = m_objfile_sp->GetModule(); if (!module_sp) return 0; // See if any symbol file is specified through `--symfile` option. @@ -317,19 +319,24 @@ uint32_t SymbolFileNativePDB::CalculateAbilities() { } void SymbolFileNativePDB::InitializeObject() { - m_obj_load_address = m_obj_file->GetBaseAddress().GetFileAddress(); + m_obj_load_address = m_objfile_sp->GetBaseAddress().GetFileAddress(); m_index->SetLoadAddress(m_obj_load_address); m_index->ParseSectionContribs(); - TypeSystem *ts = m_obj_file->GetModule()->GetTypeSystemForLanguage( + auto ts_or_err = m_objfile_sp->GetModule()->GetTypeSystemForLanguage( lldb::eLanguageTypeC_plus_plus); - if (ts) - ts->SetSymbolFile(this); - - m_ast = llvm::make_unique<PdbAstBuilder>(*m_obj_file, *m_index); + if (auto err = ts_or_err.takeError()) { + LLDB_LOG_ERROR(lldb_private::GetLogIfAnyCategoriesSet(LIBLLDB_LOG_SYMBOLS), + std::move(err), "Failed to initialize"); + } else { + ts_or_err->SetSymbolFile(this); + auto *clang = llvm::cast_or_null<ClangASTContext>(&ts_or_err.get()); + lldbassert(clang); + m_ast = std::make_unique<PdbAstBuilder>(*m_objfile_sp, *m_index, *clang); + } } -uint32_t SymbolFileNativePDB::GetNumCompileUnits() { +uint32_t SymbolFileNativePDB::CalculateNumCompileUnits() { const DbiModuleList &modules = m_index->dbi().modules(); uint32_t count = modules.getModuleCount(); if (count == 0) @@ -430,11 +437,10 @@ SymbolFileNativePDB::CreateCompileUnit(const CompilandIndexItem &cci) { FileSpec fs(source_file_name); CompUnitSP cu_sp = - std::make_shared<CompileUnit>(m_obj_file->GetModule(), nullptr, fs, + std::make_shared<CompileUnit>(m_objfile_sp->GetModule(), nullptr, fs, toOpaqueUid(cci.m_id), lang, optimized); - m_obj_file->GetModule()->GetSymbolVendor()->SetCompileUnitAtIndex( - cci.m_id.modi, cu_sp); + SetCompileUnitAtIndex(cci.m_id.modi, cu_sp); return cu_sp; } @@ -730,7 +736,7 @@ TypeSP SymbolFileNativePDB::GetOrCreateType(PdbTypeSymId type_id) { TypeSP type = CreateAndCacheType(type_id); if (type) - m_obj_file->GetModule()->GetTypeList()->Insert(type); + GetTypeList().Insert(type); return type; } @@ -900,6 +906,7 @@ lldb::CompUnitSP SymbolFileNativePDB::ParseCompileUnitAtIndex(uint32_t index) { } lldb::LanguageType SymbolFileNativePDB::ParseLanguage(CompileUnit &comp_unit) { + std::lock_guard<std::recursive_mutex> guard(GetModuleMutex()); PdbSymUid uid(comp_unit.GetID()); lldbassert(uid.kind() == PdbSymUidKind::Compiland); @@ -915,6 +922,7 @@ lldb::LanguageType SymbolFileNativePDB::ParseLanguage(CompileUnit &comp_unit) { void SymbolFileNativePDB::AddSymbols(Symtab &symtab) { return; } size_t SymbolFileNativePDB::ParseFunctions(CompileUnit &comp_unit) { + std::lock_guard<std::recursive_mutex> guard(GetModuleMutex()); PdbSymUid uid{comp_unit.GetID()}; lldbassert(uid.kind() == PdbSymUidKind::Compiland); uint16_t modi = uid.asCompiland().modi; @@ -948,6 +956,7 @@ static bool NeedsResolvedCompileUnit(uint32_t resolve_scope) { uint32_t SymbolFileNativePDB::ResolveSymbolContext( const Address &addr, SymbolContextItem resolve_scope, SymbolContext &sc) { + std::lock_guard<std::recursive_mutex> guard(GetModuleMutex()); uint32_t resolved_flags = 0; lldb::addr_t file_addr = addr.GetFileAddress(); @@ -1052,12 +1061,13 @@ bool SymbolFileNativePDB::ParseLineTable(CompileUnit &comp_unit) { // all at once, even if all it really needs is line info for a specific // function. In the future it would be nice if it could set the sc.m_function // member, and we could only get the line info for the function in question. + std::lock_guard<std::recursive_mutex> guard(GetModuleMutex()); PdbSymUid cu_id(comp_unit.GetID()); lldbassert(cu_id.kind() == PdbSymUidKind::Compiland); CompilandIndexItem *cci = m_index->compilands().GetCompiland(cu_id.asCompiland().modi); lldbassert(cci); - auto line_table = llvm::make_unique<LineTable>(&comp_unit); + auto line_table = std::make_unique<LineTable>(&comp_unit); // This is basically a copy of the .debug$S subsections from all original COFF // object files merged together with address relocations applied. We are @@ -1130,6 +1140,7 @@ bool SymbolFileNativePDB::ParseDebugMacros(CompileUnit &comp_unit) { bool SymbolFileNativePDB::ParseSupportFiles(CompileUnit &comp_unit, FileSpecList &support_files) { + std::lock_guard<std::recursive_mutex> guard(GetModuleMutex()); PdbSymUid cu_id(comp_unit.GetID()); lldbassert(cu_id.kind() == PdbSymUidKind::Compiland); CompilandIndexItem *cci = @@ -1160,6 +1171,7 @@ bool SymbolFileNativePDB::ParseImportedModules( } size_t SymbolFileNativePDB::ParseBlocksRecursive(Function &func) { + std::lock_guard<std::recursive_mutex> guard(GetModuleMutex()); GetOrCreateBlock(PdbSymUid(func.GetID()).asCompilandSym()); // FIXME: Parse child blocks return 1; @@ -1167,9 +1179,10 @@ size_t SymbolFileNativePDB::ParseBlocksRecursive(Function &func) { void SymbolFileNativePDB::DumpClangAST(Stream &s) { m_ast->Dump(s); } -uint32_t SymbolFileNativePDB::FindGlobalVariables( +void SymbolFileNativePDB::FindGlobalVariables( ConstString name, const CompilerDeclContext *parent_decl_ctx, uint32_t max_matches, VariableList &variables) { + std::lock_guard<std::recursive_mutex> guard(GetModuleMutex()); using SymbolAndOffset = std::pair<uint32_t, llvm::codeview::CVSymbol>; std::vector<SymbolAndOffset> results = m_index->globals().findRecordsByName( @@ -1191,16 +1204,16 @@ uint32_t SymbolFileNativePDB::FindGlobalVariables( continue; } } - return variables.GetSize(); } -uint32_t SymbolFileNativePDB::FindFunctions( +void SymbolFileNativePDB::FindFunctions( ConstString name, const CompilerDeclContext *parent_decl_ctx, - FunctionNameType name_type_mask, bool include_inlines, bool append, + FunctionNameType name_type_mask, bool include_inlines, SymbolContextList &sc_list) { + std::lock_guard<std::recursive_mutex> guard(GetModuleMutex()); // For now we only support lookup by method name. if (!(name_type_mask & eFunctionNameTypeMethod)) - return 0; + return; using SymbolAndOffset = std::pair<uint32_t, llvm::codeview::CVSymbol>; @@ -1225,45 +1238,34 @@ uint32_t SymbolFileNativePDB::FindFunctions( sc_list.Append(sc); } - - return sc_list.GetSize(); } -uint32_t SymbolFileNativePDB::FindFunctions(const RegularExpression ®ex, - bool include_inlines, bool append, - SymbolContextList &sc_list) { - return 0; -} +void SymbolFileNativePDB::FindFunctions(const RegularExpression ®ex, + bool include_inlines, + SymbolContextList &sc_list) {} -uint32_t SymbolFileNativePDB::FindTypes( +void SymbolFileNativePDB::FindTypes( ConstString name, const CompilerDeclContext *parent_decl_ctx, - bool append, uint32_t max_matches, - llvm::DenseSet<SymbolFile *> &searched_symbol_files, TypeMap &types) { - if (!append) - types.Clear(); + uint32_t max_matches, llvm::DenseSet<SymbolFile *> &searched_symbol_files, + TypeMap &types) { + std::lock_guard<std::recursive_mutex> guard(GetModuleMutex()); if (!name) - return 0; + return; searched_symbol_files.clear(); searched_symbol_files.insert(this); // There is an assumption 'name' is not a regex - size_t match_count = FindTypesByName(name.GetStringRef(), max_matches, types); - - return match_count; + FindTypesByName(name.GetStringRef(), max_matches, types); } -size_t -SymbolFileNativePDB::FindTypes(const std::vector<CompilerContext> &context, - bool append, TypeMap &types) { - return 0; -} +void SymbolFileNativePDB::FindTypes(llvm::ArrayRef<CompilerContext> pattern, + LanguageSet languages, TypeMap &types) {} -size_t SymbolFileNativePDB::FindTypesByName(llvm::StringRef name, - uint32_t max_matches, - TypeMap &types) { +void SymbolFileNativePDB::FindTypesByName(llvm::StringRef name, + uint32_t max_matches, + TypeMap &types) { - size_t match_count = 0; std::vector<TypeIndex> matches = m_index->tpi().findRecordsByName(name); if (max_matches > 0 && max_matches < matches.size()) matches.resize(max_matches); @@ -1274,17 +1276,16 @@ size_t SymbolFileNativePDB::FindTypesByName(llvm::StringRef name, continue; types.Insert(type); - ++match_count; } - return match_count; } size_t SymbolFileNativePDB::ParseTypes(CompileUnit &comp_unit) { + std::lock_guard<std::recursive_mutex> guard(GetModuleMutex()); // Only do the full type scan the first time. if (m_done_full_type_scan) return 0; - size_t old_count = m_obj_file->GetModule()->GetTypeList()->GetSize(); + const size_t old_count = GetTypeList().GetSize(); LazyRandomTypeCollection &types = m_index->tpi().typeCollection(); // First process the entire TPI stream. @@ -1314,7 +1315,7 @@ size_t SymbolFileNativePDB::ParseTypes(CompileUnit &comp_unit) { GetOrCreateTypedef(global); } - size_t new_count = m_obj_file->GetModule()->GetTypeList()->GetSize(); + const size_t new_count = GetTypeList().GetSize(); m_done_full_type_scan = true; @@ -1476,6 +1477,7 @@ size_t SymbolFileNativePDB::ParseVariablesForBlock(PdbCompilandSymId block_id) { } size_t SymbolFileNativePDB::ParseVariablesForContext(const SymbolContext &sc) { + std::lock_guard<std::recursive_mutex> guard(GetModuleMutex()); lldbassert(sc.function || sc.comp_unit); VariableListSP variables; @@ -1506,9 +1508,10 @@ size_t SymbolFileNativePDB::ParseVariablesForContext(const SymbolContext &sc) { } CompilerDecl SymbolFileNativePDB::GetDeclForUID(lldb::user_id_t uid) { - clang::Decl *decl = m_ast->GetOrCreateDeclForUid(PdbSymUid(uid)); - - return m_ast->ToCompilerDecl(*decl); + if (auto decl = m_ast->GetOrCreateDeclForUid(uid)) + return decl.getValue(); + else + return CompilerDecl(); } CompilerDeclContext @@ -1528,6 +1531,7 @@ SymbolFileNativePDB::GetDeclContextContainingUID(lldb::user_id_t uid) { } Type *SymbolFileNativePDB::ResolveTypeUID(lldb::user_id_t type_uid) { + std::lock_guard<std::recursive_mutex> guard(GetModuleMutex()); auto iter = m_types.find(type_uid); // lldb should not be passing us non-sensical type uids. the only way it // could have a type uid in the first place is if we handed it out, in which @@ -1561,11 +1565,9 @@ bool SymbolFileNativePDB::CompleteType(CompilerType &compiler_type) { return m_ast->CompleteType(qt); } -size_t SymbolFileNativePDB::GetTypes(lldb_private::SymbolContextScope *sc_scope, - TypeClass type_mask, - lldb_private::TypeList &type_list) { - return 0; -} +void SymbolFileNativePDB::GetTypes(lldb_private::SymbolContextScope *sc_scope, + TypeClass type_mask, + lldb_private::TypeList &type_list) {} CompilerDeclContext SymbolFileNativePDB::FindNamespace(ConstString name, @@ -1573,13 +1575,14 @@ SymbolFileNativePDB::FindNamespace(ConstString name, return {}; } -TypeSystem * +llvm::Expected<TypeSystem &> SymbolFileNativePDB::GetTypeSystemForLanguage(lldb::LanguageType language) { - auto type_system = - m_obj_file->GetModule()->GetTypeSystemForLanguage(language); - if (type_system) - type_system->SetSymbolFile(this); - return type_system; + auto type_system_or_err = + m_objfile_sp->GetModule()->GetTypeSystemForLanguage(language); + if (type_system_or_err) { + type_system_or_err->SetSymbolFile(this); + } + return type_system_or_err; } ConstString SymbolFileNativePDB::GetPluginName() { diff --git a/source/Plugins/SymbolFile/NativePDB/SymbolFileNativePDB.h b/source/Plugins/SymbolFile/NativePDB/SymbolFileNativePDB.h index 20daff219a0a..ca7de0e7d1ed 100644 --- a/source/Plugins/SymbolFile/NativePDB/SymbolFileNativePDB.h +++ b/source/Plugins/SymbolFile/NativePDB/SymbolFileNativePDB.h @@ -9,7 +9,6 @@ #ifndef LLDB_PLUGINS_SYMBOLFILE_NATIVEPDB_SYMBOLFILENATIVEPDB_H #define LLDB_PLUGINS_SYMBOLFILE_NATIVEPDB_SYMBOLFILENATIVEPDB_H -#include "lldb/Symbol/ClangASTImporter.h" #include "lldb/Symbol/SymbolFile.h" #include "llvm/ADT/DenseMap.h" @@ -35,7 +34,6 @@ struct UnionRecord; } // namespace llvm namespace lldb_private { -class ClangASTImporter; namespace npdb { class PdbAstBuilder; @@ -55,10 +53,10 @@ public: static const char *GetPluginDescriptionStatic(); - static SymbolFile *CreateInstance(ObjectFile *obj_file); + static SymbolFile *CreateInstance(lldb::ObjectFileSP objfile_sp); // Constructors and Destructors - SymbolFileNativePDB(ObjectFile *ofile); + SymbolFileNativePDB(lldb::ObjectFileSP objfile_sp); ~SymbolFileNativePDB() override; @@ -68,13 +66,9 @@ public: // Compile Unit function calls - uint32_t GetNumCompileUnits() override; - void ParseDeclsForContext(lldb_private::CompilerDeclContext decl_ctx) override; - lldb::CompUnitSP ParseCompileUnitAtIndex(uint32_t index) override; - lldb::LanguageType ParseLanguage(lldb_private::CompileUnit &comp_unit) override; @@ -94,10 +88,10 @@ public: size_t ParseBlocksRecursive(Function &func) override; - uint32_t FindGlobalVariables(ConstString name, - const CompilerDeclContext *parent_decl_ctx, - uint32_t max_matches, - VariableList &variables) override; + void FindGlobalVariables(ConstString name, + const CompilerDeclContext *parent_decl_ctx, + uint32_t max_matches, + VariableList &variables) override; size_t ParseVariablesForContext(const SymbolContext &sc) override; @@ -120,28 +114,27 @@ public: lldb::SymbolContextItem resolve_scope, SymbolContextList &sc_list) override; - size_t GetTypes(SymbolContextScope *sc_scope, lldb::TypeClass type_mask, - TypeList &type_list) override; + void GetTypes(SymbolContextScope *sc_scope, lldb::TypeClass type_mask, + TypeList &type_list) override; - uint32_t FindFunctions(ConstString name, - const CompilerDeclContext *parent_decl_ctx, - lldb::FunctionNameType name_type_mask, - bool include_inlines, bool append, - SymbolContextList &sc_list) override; + void FindFunctions(ConstString name, + const CompilerDeclContext *parent_decl_ctx, + lldb::FunctionNameType name_type_mask, + bool include_inlines, SymbolContextList &sc_list) override; - uint32_t FindFunctions(const RegularExpression ®ex, bool include_inlines, - bool append, SymbolContextList &sc_list) override; + void FindFunctions(const RegularExpression ®ex, bool include_inlines, + SymbolContextList &sc_list) override; - uint32_t FindTypes(ConstString name, - const CompilerDeclContext *parent_decl_ctx, bool append, - uint32_t max_matches, - llvm::DenseSet<SymbolFile *> &searched_symbol_files, - TypeMap &types) override; + void FindTypes(ConstString name, const CompilerDeclContext *parent_decl_ctx, + uint32_t max_matches, + llvm::DenseSet<SymbolFile *> &searched_symbol_files, + TypeMap &types) override; - size_t FindTypes(const std::vector<CompilerContext> &context, bool append, - TypeMap &types) override; + void FindTypes(llvm::ArrayRef<CompilerContext> pattern, LanguageSet languages, + TypeMap &types) override; - TypeSystem *GetTypeSystemForLanguage(lldb::LanguageType language) override; + llvm::Expected<TypeSystem &> + GetTypeSystemForLanguage(lldb::LanguageType language) override; CompilerDeclContext FindNamespace(ConstString name, @@ -157,9 +150,12 @@ public: void DumpClangAST(Stream &s) override; private: + uint32_t CalculateNumCompileUnits() override; + + lldb::CompUnitSP ParseCompileUnitAtIndex(uint32_t index) override; - size_t FindTypesByName(llvm::StringRef name, uint32_t max_matches, - TypeMap &types); + void FindTypesByName(llvm::StringRef name, uint32_t max_matches, + TypeMap &types); lldb::TypeSP CreateModifierType(PdbTypeSymId type_id, const llvm::codeview::ModifierRecord &mr, diff --git a/source/Plugins/SymbolFile/PDB/PDBASTParser.cpp b/source/Plugins/SymbolFile/PDB/PDBASTParser.cpp index 82cfcfbb040f..47c4ad088494 100644 --- a/source/Plugins/SymbolFile/PDB/PDBASTParser.cpp +++ b/source/Plugins/SymbolFile/PDB/PDBASTParser.cpp @@ -120,24 +120,31 @@ GetBuiltinTypeForPDBEncodingAndBitSize(ClangASTContext &clang_ast, return clang_ast.GetBasicType(eBasicTypeBool); case PDB_BuiltinType::Long: if (width == ast->getTypeSize(ast->LongTy)) - return CompilerType(ast, ast->LongTy); + return CompilerType(ClangASTContext::GetASTContext(ast), + ast->LongTy.getAsOpaquePtr()); if (width == ast->getTypeSize(ast->LongLongTy)) - return CompilerType(ast, ast->LongLongTy); + return CompilerType(ClangASTContext::GetASTContext(ast), + ast->LongLongTy.getAsOpaquePtr()); break; case PDB_BuiltinType::ULong: if (width == ast->getTypeSize(ast->UnsignedLongTy)) - return CompilerType(ast, ast->UnsignedLongTy); + return CompilerType(ClangASTContext::GetASTContext(ast), + ast->UnsignedLongTy.getAsOpaquePtr()); if (width == ast->getTypeSize(ast->UnsignedLongLongTy)) - return CompilerType(ast, ast->UnsignedLongLongTy); + return CompilerType(ClangASTContext::GetASTContext(ast), + ast->UnsignedLongLongTy.getAsOpaquePtr()); break; case PDB_BuiltinType::WCharT: if (width == ast->getTypeSize(ast->WCharTy)) - return CompilerType(ast, ast->WCharTy); + return CompilerType(ClangASTContext::GetASTContext(ast), + ast->WCharTy.getAsOpaquePtr()); break; case PDB_BuiltinType::Char16: - return CompilerType(ast, ast->Char16Ty); + return CompilerType(ClangASTContext::GetASTContext(ast), + ast->Char16Ty.getAsOpaquePtr()); case PDB_BuiltinType::Char32: - return CompilerType(ast, ast->Char32Ty); + return CompilerType(ClangASTContext::GetASTContext(ast), + ast->Char32Ty.getAsOpaquePtr()); case PDB_BuiltinType::Float: // Note: types `long double` and `double` have same bit size in MSVC and // there is no information in the PDB to distinguish them. So when falling @@ -940,7 +947,7 @@ PDBASTParser::GetDeclForSymbol(const llvm::pdb::PDBSymbol &symbol) { clang::ParmVarDecl *param = m_ast.CreateParameterDeclaration( decl, nullptr, arg_type->GetForwardCompilerType(), - clang::SC_None); + clang::SC_None, true); if (param) params.push_back(param); } diff --git a/source/Plugins/SymbolFile/PDB/PDBLocationToDWARFExpression.cpp b/source/Plugins/SymbolFile/PDB/PDBLocationToDWARFExpression.cpp index 1c17bf6563b3..42bf1b34c956 100644 --- a/source/Plugins/SymbolFile/PDB/PDBLocationToDWARFExpression.cpp +++ b/source/Plugins/SymbolFile/PDB/PDBLocationToDWARFExpression.cpp @@ -174,7 +174,7 @@ DWARFExpression ConvertPDBLocationToDWARFExpression( DataBufferSP buffer = std::make_shared<DataBufferHeap>(stream.GetData(), stream.GetSize()); DataExtractor extractor(buffer, byte_order, address_size, byte_size); - DWARFExpression result(module, extractor, nullptr, 0, buffer->GetByteSize()); + DWARFExpression result(module, extractor, nullptr); result.SetRegisterKind(register_kind); return result; diff --git a/source/Plugins/SymbolFile/PDB/SymbolFilePDB.cpp b/source/Plugins/SymbolFile/PDB/SymbolFilePDB.cpp index 17dfcdaceb9c..854e735b5f83 100644 --- a/source/Plugins/SymbolFile/PDB/SymbolFilePDB.cpp +++ b/source/Plugins/SymbolFile/PDB/SymbolFilePDB.cpp @@ -24,6 +24,7 @@ #include "lldb/Symbol/TypeList.h" #include "lldb/Symbol/TypeMap.h" #include "lldb/Symbol/Variable.h" +#include "lldb/Utility/Log.h" #include "lldb/Utility/RegularExpression.h" #include "llvm/DebugInfo/PDB/GenericError.h" @@ -118,29 +119,28 @@ const char *SymbolFilePDB::GetPluginDescriptionStatic() { } lldb_private::SymbolFile * -SymbolFilePDB::CreateInstance(lldb_private::ObjectFile *obj_file) { - return new SymbolFilePDB(obj_file); +SymbolFilePDB::CreateInstance(ObjectFileSP objfile_sp) { + return new SymbolFilePDB(std::move(objfile_sp)); } -SymbolFilePDB::SymbolFilePDB(lldb_private::ObjectFile *object_file) - : SymbolFile(object_file), m_session_up(), m_global_scope_up(), - m_cached_compile_unit_count(0) {} +SymbolFilePDB::SymbolFilePDB(lldb::ObjectFileSP objfile_sp) + : SymbolFile(std::move(objfile_sp)), m_session_up(), m_global_scope_up() {} SymbolFilePDB::~SymbolFilePDB() {} uint32_t SymbolFilePDB::CalculateAbilities() { uint32_t abilities = 0; - if (!m_obj_file) + if (!m_objfile_sp) return 0; if (!m_session_up) { // Lazily load and match the PDB file, but only do this once. - std::string exePath = m_obj_file->GetFileSpec().GetPath(); + std::string exePath = m_objfile_sp->GetFileSpec().GetPath(); auto error = loadDataForEXE(PDB_ReaderType::DIA, llvm::StringRef(exePath), m_session_up); if (error) { llvm::consumeError(std::move(error)); - auto module_sp = m_obj_file->GetModule(); + auto module_sp = m_objfile_sp->GetModule(); if (!module_sp) return 0; // See if any symbol file is specified through `--symfile` option. @@ -183,7 +183,8 @@ uint32_t SymbolFilePDB::CalculateAbilities() { } void SymbolFilePDB::InitializeObject() { - lldb::addr_t obj_load_address = m_obj_file->GetBaseAddress().GetFileAddress(); + lldb::addr_t obj_load_address = + m_objfile_sp->GetBaseAddress().GetFileAddress(); lldbassert(obj_load_address && obj_load_address != LLDB_INVALID_ADDRESS); m_session_up->setLoadAddress(obj_load_address); if (!m_global_scope_up) @@ -191,33 +192,30 @@ void SymbolFilePDB::InitializeObject() { lldbassert(m_global_scope_up.get()); } -uint32_t SymbolFilePDB::GetNumCompileUnits() { - if (m_cached_compile_unit_count == 0) { - auto compilands = m_global_scope_up->findAllChildren<PDBSymbolCompiland>(); - if (!compilands) - return 0; +uint32_t SymbolFilePDB::CalculateNumCompileUnits() { + auto compilands = m_global_scope_up->findAllChildren<PDBSymbolCompiland>(); + if (!compilands) + return 0; - // The linker could link *.dll (compiland language = LINK), or import - // *.dll. For example, a compiland with name `Import:KERNEL32.dll` could be - // found as a child of the global scope (PDB executable). Usually, such - // compilands contain `thunk` symbols in which we are not interested for - // now. However we still count them in the compiland list. If we perform - // any compiland related activity, like finding symbols through - // llvm::pdb::IPDBSession methods, such compilands will all be searched - // automatically no matter whether we include them or not. - m_cached_compile_unit_count = compilands->getChildCount(); - - // The linker can inject an additional "dummy" compilation unit into the - // PDB. Ignore this special compile unit for our purposes, if it is there. - // It is always the last one. - auto last_compiland_up = - compilands->getChildAtIndex(m_cached_compile_unit_count - 1); - lldbassert(last_compiland_up.get()); - std::string name = last_compiland_up->getName(); - if (name == "* Linker *") - --m_cached_compile_unit_count; - } - return m_cached_compile_unit_count; + // The linker could link *.dll (compiland language = LINK), or import + // *.dll. For example, a compiland with name `Import:KERNEL32.dll` could be + // found as a child of the global scope (PDB executable). Usually, such + // compilands contain `thunk` symbols in which we are not interested for + // now. However we still count them in the compiland list. If we perform + // any compiland related activity, like finding symbols through + // llvm::pdb::IPDBSession methods, such compilands will all be searched + // automatically no matter whether we include them or not. + uint32_t compile_unit_count = compilands->getChildCount(); + + // The linker can inject an additional "dummy" compilation unit into the + // PDB. Ignore this special compile unit for our purposes, if it is there. + // It is always the last one. + auto last_compiland_up = compilands->getChildAtIndex(compile_unit_count - 1); + lldbassert(last_compiland_up.get()); + std::string name = last_compiland_up->getName(); + if (name == "* Linker *") + --compile_unit_count; + return compile_unit_count; } void SymbolFilePDB::GetCompileUnitIndex( @@ -261,6 +259,7 @@ lldb::CompUnitSP SymbolFilePDB::ParseCompileUnitAtIndex(uint32_t index) { } lldb::LanguageType SymbolFilePDB::ParseLanguage(CompileUnit &comp_unit) { + std::lock_guard<std::recursive_mutex> guard(GetModuleMutex()); auto compiland_up = GetPDBCompilandByUID(comp_unit.GetID()); if (!compiland_up) return lldb::eLanguageTypeUnknown; @@ -302,11 +301,15 @@ SymbolFilePDB::ParseCompileUnitFunctionForPDBFunc(const PDBSymbolFunc &pdb_func, comp_unit.AddFunction(func_sp); LanguageType lang = ParseLanguage(comp_unit); - TypeSystem *type_system = GetTypeSystemForLanguage(lang); - if (!type_system) + auto type_system_or_err = GetTypeSystemForLanguage(lang); + if (auto err = type_system_or_err.takeError()) { + LLDB_LOG_ERROR(lldb_private::GetLogIfAnyCategoriesSet(LIBLLDB_LOG_SYMBOLS), + std::move(err), "Unable to parse PDBFunc"); return nullptr; + } + ClangASTContext *clang_type_system = - llvm::dyn_cast_or_null<ClangASTContext>(type_system); + llvm::dyn_cast_or_null<ClangASTContext>(&type_system_or_err.get()); if (!clang_type_system) return nullptr; clang_type_system->GetPDBParser()->GetDeclForSymbol(pdb_func); @@ -315,6 +318,7 @@ SymbolFilePDB::ParseCompileUnitFunctionForPDBFunc(const PDBSymbolFunc &pdb_func, } size_t SymbolFilePDB::ParseFunctions(CompileUnit &comp_unit) { + std::lock_guard<std::recursive_mutex> guard(GetModuleMutex()); size_t func_added = 0; auto compiland_up = GetPDBCompilandByUID(comp_unit.GetID()); if (!compiland_up) @@ -333,6 +337,7 @@ size_t SymbolFilePDB::ParseFunctions(CompileUnit &comp_unit) { } bool SymbolFilePDB::ParseLineTable(CompileUnit &comp_unit) { + std::lock_guard<std::recursive_mutex> guard(GetModuleMutex()); if (comp_unit.GetLineTable()) return true; return ParseCompileUnitLineTable(comp_unit, 0); @@ -351,6 +356,7 @@ bool SymbolFilePDB::ParseSupportFiles( // second time seems like a waste. Unfortunately, there's no good way around // this short of a moderate refactor since SymbolVendor depends on being able // to cache this list. + std::lock_guard<std::recursive_mutex> guard(GetModuleMutex()); auto compiland_up = GetPDBCompilandByUID(comp_unit.GetID()); if (!compiland_up) return false; @@ -428,6 +434,7 @@ static size_t ParseFunctionBlocksForPDBSymbol( } size_t SymbolFilePDB::ParseBlocksRecursive(Function &func) { + std::lock_guard<std::recursive_mutex> guard(GetModuleMutex()); size_t num_added = 0; auto uid = func.GetID(); auto pdb_func_up = m_session_up->getConcreteSymbolById<PDBSymbolFunc>(uid); @@ -440,6 +447,7 @@ size_t SymbolFilePDB::ParseBlocksRecursive(Function &func) { } size_t SymbolFilePDB::ParseTypes(CompileUnit &comp_unit) { + std::lock_guard<std::recursive_mutex> guard(GetModuleMutex()); size_t num_added = 0; auto compiland = GetPDBCompilandByUID(comp_unit.GetID()); @@ -492,6 +500,7 @@ size_t SymbolFilePDB::ParseTypes(CompileUnit &comp_unit) { size_t SymbolFilePDB::ParseVariablesForContext(const lldb_private::SymbolContext &sc) { + std::lock_guard<std::recursive_mutex> guard(GetModuleMutex()); if (!sc.comp_unit) return 0; @@ -540,14 +549,21 @@ SymbolFilePDB::ParseVariablesForContext(const lldb_private::SymbolContext &sc) { } lldb_private::Type *SymbolFilePDB::ResolveTypeUID(lldb::user_id_t type_uid) { + std::lock_guard<std::recursive_mutex> guard(GetModuleMutex()); auto find_result = m_types.find(type_uid); if (find_result != m_types.end()) return find_result->second.get(); - TypeSystem *type_system = + auto type_system_or_err = GetTypeSystemForLanguage(lldb::eLanguageTypeC_plus_plus); + if (auto err = type_system_or_err.takeError()) { + LLDB_LOG_ERROR(lldb_private::GetLogIfAnyCategoriesSet(LIBLLDB_LOG_SYMBOLS), + std::move(err), "Unable to ResolveTypeUID"); + return nullptr; + } + ClangASTContext *clang_type_system = - llvm::dyn_cast_or_null<ClangASTContext>(type_system); + llvm::dyn_cast_or_null<ClangASTContext>(&type_system_or_err.get()); if (!clang_type_system) return nullptr; PDBASTParser *pdb = clang_type_system->GetPDBParser(); @@ -561,9 +577,7 @@ lldb_private::Type *SymbolFilePDB::ResolveTypeUID(lldb::user_id_t type_uid) { lldb::TypeSP result = pdb->CreateLLDBTypeFromPDBType(*pdb_type); if (result) { m_types.insert(std::make_pair(type_uid, result)); - auto type_list = GetTypeList(); - if (type_list) - type_list->Insert(result); + GetTypeList().Insert(result); } return result.get(); } @@ -577,8 +591,17 @@ bool SymbolFilePDB::CompleteType(lldb_private::CompilerType &compiler_type) { std::lock_guard<std::recursive_mutex> guard( GetObjectFile()->GetModule()->GetMutex()); - ClangASTContext *clang_ast_ctx = llvm::dyn_cast_or_null<ClangASTContext>( - GetTypeSystemForLanguage(lldb::eLanguageTypeC_plus_plus)); + auto type_system_or_err = + GetTypeSystemForLanguage(lldb::eLanguageTypeC_plus_plus); + if (auto err = type_system_or_err.takeError()) { + LLDB_LOG_ERROR(lldb_private::GetLogIfAnyCategoriesSet(LIBLLDB_LOG_SYMBOLS), + std::move(err), "Unable to get dynamic array info for UID"); + return false; + } + + ClangASTContext *clang_ast_ctx = + llvm::dyn_cast_or_null<ClangASTContext>(&type_system_or_err.get()); + if (!clang_ast_ctx) return false; @@ -590,8 +613,16 @@ bool SymbolFilePDB::CompleteType(lldb_private::CompilerType &compiler_type) { } lldb_private::CompilerDecl SymbolFilePDB::GetDeclForUID(lldb::user_id_t uid) { - ClangASTContext *clang_ast_ctx = llvm::dyn_cast_or_null<ClangASTContext>( - GetTypeSystemForLanguage(lldb::eLanguageTypeC_plus_plus)); + auto type_system_or_err = + GetTypeSystemForLanguage(lldb::eLanguageTypeC_plus_plus); + if (auto err = type_system_or_err.takeError()) { + LLDB_LOG_ERROR(lldb_private::GetLogIfAnyCategoriesSet(LIBLLDB_LOG_SYMBOLS), + std::move(err), "Unable to get decl for UID"); + return CompilerDecl(); + } + + ClangASTContext *clang_ast_ctx = + llvm::dyn_cast_or_null<ClangASTContext>(&type_system_or_err.get()); if (!clang_ast_ctx) return CompilerDecl(); @@ -612,8 +643,16 @@ lldb_private::CompilerDecl SymbolFilePDB::GetDeclForUID(lldb::user_id_t uid) { lldb_private::CompilerDeclContext SymbolFilePDB::GetDeclContextForUID(lldb::user_id_t uid) { - ClangASTContext *clang_ast_ctx = llvm::dyn_cast_or_null<ClangASTContext>( - GetTypeSystemForLanguage(lldb::eLanguageTypeC_plus_plus)); + auto type_system_or_err = + GetTypeSystemForLanguage(lldb::eLanguageTypeC_plus_plus); + if (auto err = type_system_or_err.takeError()) { + LLDB_LOG_ERROR(lldb_private::GetLogIfAnyCategoriesSet(LIBLLDB_LOG_SYMBOLS), + std::move(err), "Unable to get DeclContext for UID"); + return CompilerDeclContext(); + } + + ClangASTContext *clang_ast_ctx = + llvm::dyn_cast_or_null<ClangASTContext>(&type_system_or_err.get()); if (!clang_ast_ctx) return CompilerDeclContext(); @@ -634,8 +673,16 @@ SymbolFilePDB::GetDeclContextForUID(lldb::user_id_t uid) { lldb_private::CompilerDeclContext SymbolFilePDB::GetDeclContextContainingUID(lldb::user_id_t uid) { - ClangASTContext *clang_ast_ctx = llvm::dyn_cast_or_null<ClangASTContext>( - GetTypeSystemForLanguage(lldb::eLanguageTypeC_plus_plus)); + auto type_system_or_err = + GetTypeSystemForLanguage(lldb::eLanguageTypeC_plus_plus); + if (auto err = type_system_or_err.takeError()) { + LLDB_LOG_ERROR(lldb_private::GetLogIfAnyCategoriesSet(LIBLLDB_LOG_SYMBOLS), + std::move(err), "Unable to get DeclContext containing UID"); + return CompilerDeclContext(); + } + + ClangASTContext *clang_ast_ctx = + llvm::dyn_cast_or_null<ClangASTContext>(&type_system_or_err.get()); if (!clang_ast_ctx) return CompilerDeclContext(); @@ -655,8 +702,16 @@ SymbolFilePDB::GetDeclContextContainingUID(lldb::user_id_t uid) { void SymbolFilePDB::ParseDeclsForContext( lldb_private::CompilerDeclContext decl_ctx) { - ClangASTContext *clang_ast_ctx = llvm::dyn_cast_or_null<ClangASTContext>( - GetTypeSystemForLanguage(lldb::eLanguageTypeC_plus_plus)); + auto type_system_or_err = + GetTypeSystemForLanguage(lldb::eLanguageTypeC_plus_plus); + if (auto err = type_system_or_err.takeError()) { + LLDB_LOG_ERROR(lldb_private::GetLogIfAnyCategoriesSet(LIBLLDB_LOG_SYMBOLS), + std::move(err), "Unable to parse decls for context"); + return; + } + + ClangASTContext *clang_ast_ctx = + llvm::dyn_cast_or_null<ClangASTContext>(&type_system_or_err.get()); if (!clang_ast_ctx) return; @@ -672,6 +727,7 @@ uint32_t SymbolFilePDB::ResolveSymbolContext(const lldb_private::Address &so_addr, SymbolContextItem resolve_scope, lldb_private::SymbolContext &sc) { + std::lock_guard<std::recursive_mutex> guard(GetModuleMutex()); uint32_t resolved_flags = 0; if (resolve_scope & eSymbolContextCompUnit || resolve_scope & eSymbolContextVariable || @@ -680,7 +736,7 @@ SymbolFilePDB::ResolveSymbolContext(const lldb_private::Address &so_addr, resolve_scope & eSymbolContextLineEntry) { auto cu_sp = GetCompileUnitContainsAddress(so_addr); if (!cu_sp) { - if (resolved_flags | eSymbolContextVariable) { + if (resolved_flags & eSymbolContextVariable) { // TODO: Resolve variables } return 0; @@ -732,6 +788,7 @@ SymbolFilePDB::ResolveSymbolContext(const lldb_private::Address &so_addr, uint32_t SymbolFilePDB::ResolveSymbolContext( const lldb_private::FileSpec &file_spec, uint32_t line, bool check_inlines, SymbolContextItem resolve_scope, lldb_private::SymbolContextList &sc_list) { + std::lock_guard<std::recursive_mutex> guard(GetModuleMutex()); const size_t old_size = sc_list.GetSize(); if (resolve_scope & lldb::eSymbolContextCompUnit) { // Locate all compilation units with line numbers referencing the specified @@ -1040,18 +1097,19 @@ SymbolFilePDB::ParseVariables(const lldb_private::SymbolContext &sc, return num_added; } -uint32_t SymbolFilePDB::FindGlobalVariables( +void SymbolFilePDB::FindGlobalVariables( lldb_private::ConstString name, const lldb_private::CompilerDeclContext *parent_decl_ctx, uint32_t max_matches, lldb_private::VariableList &variables) { + std::lock_guard<std::recursive_mutex> guard(GetModuleMutex()); if (!DeclContextMatchesThisSymbolFile(parent_decl_ctx)) - return 0; + return; if (name.IsEmpty()) - return 0; + return; auto results = m_global_scope_up->findAllChildren<PDBSymbolData>(); if (!results) - return 0; + return; uint32_t matches = 0; size_t old_size = variables.GetSize(); @@ -1061,7 +1119,7 @@ uint32_t SymbolFilePDB::FindGlobalVariables( break; SymbolContext sc; - sc.module_sp = m_obj_file->GetModule(); + sc.module_sp = m_objfile_sp->GetModule(); lldbassert(sc.module_sp.get()); if (!name.GetStringRef().equals( @@ -1080,19 +1138,17 @@ uint32_t SymbolFilePDB::FindGlobalVariables( ParseVariables(sc, *pdb_data, &variables); matches = variables.GetSize() - old_size; } - - return matches; } -uint32_t -SymbolFilePDB::FindGlobalVariables(const lldb_private::RegularExpression ®ex, - uint32_t max_matches, - lldb_private::VariableList &variables) { +void SymbolFilePDB::FindGlobalVariables( + const lldb_private::RegularExpression ®ex, uint32_t max_matches, + lldb_private::VariableList &variables) { + std::lock_guard<std::recursive_mutex> guard(GetModuleMutex()); if (!regex.IsValid()) - return 0; + return; auto results = m_global_scope_up->findAllChildren<PDBSymbolData>(); if (!results) - return 0; + return; uint32_t matches = 0; size_t old_size = variables.GetSize(); @@ -1106,7 +1162,7 @@ SymbolFilePDB::FindGlobalVariables(const lldb_private::RegularExpression ®ex, if (!regex.Execute(var_name)) continue; SymbolContext sc; - sc.module_sp = m_obj_file->GetModule(); + sc.module_sp = m_objfile_sp->GetModule(); lldbassert(sc.module_sp.get()); sc.comp_unit = ParseCompileUnitForUID(GetCompilandId(*pdb_data)).get(); @@ -1117,8 +1173,6 @@ SymbolFilePDB::FindGlobalVariables(const lldb_private::RegularExpression ®ex, ParseVariables(sc, *pdb_data, &variables); matches = variables.GetSize() - old_size; } - - return matches; } bool SymbolFilePDB::ResolveFunction(const llvm::pdb::PDBSymbolFunc &pdb_func, @@ -1240,23 +1294,21 @@ void SymbolFilePDB::CacheFunctionNames() { m_func_base_names.SizeToFit(); } -uint32_t SymbolFilePDB::FindFunctions( +void SymbolFilePDB::FindFunctions( lldb_private::ConstString name, const lldb_private::CompilerDeclContext *parent_decl_ctx, - FunctionNameType name_type_mask, bool include_inlines, bool append, + FunctionNameType name_type_mask, bool include_inlines, lldb_private::SymbolContextList &sc_list) { - if (!append) - sc_list.Clear(); + std::lock_guard<std::recursive_mutex> guard(GetModuleMutex()); lldbassert((name_type_mask & eFunctionNameTypeAuto) == 0); if (name_type_mask == eFunctionNameTypeNone) - return 0; + return; if (!DeclContextMatchesThisSymbolFile(parent_decl_ctx)) - return 0; + return; if (name.IsEmpty()) - return 0; + return; - auto old_size = sc_list.GetSize(); if (name_type_mask & eFunctionNameTypeFull || name_type_mask & eFunctionNameTypeBase || name_type_mask & eFunctionNameTypeMethod) { @@ -1286,26 +1338,20 @@ uint32_t SymbolFilePDB::FindFunctions( ResolveFn(m_func_base_names); ResolveFn(m_func_method_names); } - if (name_type_mask & eFunctionNameTypeBase) { + if (name_type_mask & eFunctionNameTypeBase) ResolveFn(m_func_base_names); - } - if (name_type_mask & eFunctionNameTypeMethod) { + if (name_type_mask & eFunctionNameTypeMethod) ResolveFn(m_func_method_names); - } } - return sc_list.GetSize() - old_size; } -uint32_t -SymbolFilePDB::FindFunctions(const lldb_private::RegularExpression ®ex, - bool include_inlines, bool append, - lldb_private::SymbolContextList &sc_list) { - if (!append) - sc_list.Clear(); +void SymbolFilePDB::FindFunctions(const lldb_private::RegularExpression ®ex, + bool include_inlines, + lldb_private::SymbolContextList &sc_list) { + std::lock_guard<std::recursive_mutex> guard(GetModuleMutex()); if (!regex.IsValid()) - return 0; + return; - auto old_size = sc_list.GetSize(); CacheFunctionNames(); std::set<uint32_t> resolved_ids; @@ -1322,8 +1368,6 @@ SymbolFilePDB::FindFunctions(const lldb_private::RegularExpression ®ex, }; ResolveFn(m_func_full_names); ResolveFn(m_func_base_names); - - return sc_list.GetSize() - old_size; } void SymbolFilePDB::GetMangledNamesForFunction( @@ -1339,7 +1383,7 @@ void SymbolFilePDB::AddSymbols(lldb_private::Symtab &symtab) { if (!results) return; - auto section_list = m_obj_file->GetSectionList(); + auto section_list = m_objfile_sp->GetSectionList(); if (!section_list) return; @@ -1361,7 +1405,6 @@ void SymbolFilePDB::AddSymbols(lldb_private::Symtab &symtab) { symtab.AddSymbol( Symbol(pub_symbol->getSymIndexId(), // symID pub_symbol->getName().c_str(), // name - true, // name_is_mangled pub_symbol->isCode() ? eSymbolTypeCode : eSymbolTypeData, // type true, // external false, // is_debug @@ -1380,34 +1423,39 @@ void SymbolFilePDB::AddSymbols(lldb_private::Symtab &symtab) { symtab.Finalize(); } -uint32_t SymbolFilePDB::FindTypes( +void SymbolFilePDB::FindTypes( lldb_private::ConstString name, - const lldb_private::CompilerDeclContext *parent_decl_ctx, bool append, + const lldb_private::CompilerDeclContext *parent_decl_ctx, uint32_t max_matches, llvm::DenseSet<lldb_private::SymbolFile *> &searched_symbol_files, lldb_private::TypeMap &types) { - if (!append) - types.Clear(); + std::lock_guard<std::recursive_mutex> guard(GetModuleMutex()); if (!name) - return 0; + return; if (!DeclContextMatchesThisSymbolFile(parent_decl_ctx)) - return 0; + return; searched_symbol_files.clear(); searched_symbol_files.insert(this); // There is an assumption 'name' is not a regex FindTypesByName(name.GetStringRef(), parent_decl_ctx, max_matches, types); - - return types.GetSize(); } void SymbolFilePDB::DumpClangAST(Stream &s) { - auto type_system = GetTypeSystemForLanguage(lldb::eLanguageTypeC_plus_plus); - auto clang = llvm::dyn_cast_or_null<ClangASTContext>(type_system); - if (!clang) + auto type_system_or_err = + GetTypeSystemForLanguage(lldb::eLanguageTypeC_plus_plus); + if (auto err = type_system_or_err.takeError()) { + LLDB_LOG_ERROR(lldb_private::GetLogIfAnyCategoriesSet(LIBLLDB_LOG_SYMBOLS), + std::move(err), "Unable to dump ClangAST"); + return; + } + + auto *clang_type_system = + llvm::dyn_cast_or_null<ClangASTContext>(&type_system_or_err.get()); + if (!clang_type_system) return; - clang->Dump(s); + clang_type_system->Dump(s); } void SymbolFilePDB::FindTypesByRegex( @@ -1514,15 +1562,9 @@ void SymbolFilePDB::FindTypesByName( } } -size_t SymbolFilePDB::FindTypes( - const std::vector<lldb_private::CompilerContext> &contexts, bool append, - lldb_private::TypeMap &types) { - return 0; -} - -lldb_private::TypeList *SymbolFilePDB::GetTypeList() { - return m_obj_file->GetModule()->GetTypeList(); -} +void SymbolFilePDB::FindTypes(llvm::ArrayRef<CompilerContext> pattern, + LanguageSet languages, + lldb_private::TypeMap &types) {} void SymbolFilePDB::GetTypesForPDBSymbol(const llvm::pdb::PDBSymbol &pdb_symbol, uint32_t type_mask, @@ -1574,17 +1616,17 @@ void SymbolFilePDB::GetTypesForPDBSymbol(const llvm::pdb::PDBSymbol &pdb_symbol, GetTypesForPDBSymbol(*symbol_up, type_mask, type_collection); } -size_t SymbolFilePDB::GetTypes(lldb_private::SymbolContextScope *sc_scope, - TypeClass type_mask, - lldb_private::TypeList &type_list) { +void SymbolFilePDB::GetTypes(lldb_private::SymbolContextScope *sc_scope, + TypeClass type_mask, + lldb_private::TypeList &type_list) { + std::lock_guard<std::recursive_mutex> guard(GetModuleMutex()); TypeCollection type_collection; - uint32_t old_size = type_list.GetSize(); CompileUnit *cu = sc_scope ? sc_scope->CalculateSymbolContextCompileUnit() : nullptr; if (cu) { auto compiland_up = GetPDBCompilandByUID(cu->GetID()); if (!compiland_up) - return 0; + return; GetTypesForPDBSymbol(*compiland_up, type_mask, type_collection); } else { for (uint32_t cu_idx = 0; cu_idx < GetNumCompileUnits(); ++cu_idx) { @@ -1600,21 +1642,29 @@ size_t SymbolFilePDB::GetTypes(lldb_private::SymbolContextScope *sc_scope, type->GetForwardCompilerType(); type_list.Insert(type->shared_from_this()); } - return type_list.GetSize() - old_size; } -lldb_private::TypeSystem * +llvm::Expected<lldb_private::TypeSystem &> SymbolFilePDB::GetTypeSystemForLanguage(lldb::LanguageType language) { - auto type_system = - m_obj_file->GetModule()->GetTypeSystemForLanguage(language); - if (type_system) - type_system->SetSymbolFile(this); - return type_system; + auto type_system_or_err = + m_objfile_sp->GetModule()->GetTypeSystemForLanguage(language); + if (type_system_or_err) { + type_system_or_err->SetSymbolFile(this); + } + return type_system_or_err; } PDBASTParser *SymbolFilePDB::GetPDBAstParser() { - auto type_system = GetTypeSystemForLanguage(lldb::eLanguageTypeC_plus_plus); - auto clang_type_system = llvm::dyn_cast_or_null<ClangASTContext>(type_system); + auto type_system_or_err = + GetTypeSystemForLanguage(lldb::eLanguageTypeC_plus_plus); + if (auto err = type_system_or_err.takeError()) { + LLDB_LOG_ERROR(lldb_private::GetLogIfAnyCategoriesSet(LIBLLDB_LOG_SYMBOLS), + std::move(err), "Unable to get PDB AST parser"); + return nullptr; + } + + auto *clang_type_system = + llvm::dyn_cast_or_null<ClangASTContext>(&type_system_or_err.get()); if (!clang_type_system) return nullptr; @@ -1625,8 +1675,18 @@ PDBASTParser *SymbolFilePDB::GetPDBAstParser() { lldb_private::CompilerDeclContext SymbolFilePDB::FindNamespace( lldb_private::ConstString name, const lldb_private::CompilerDeclContext *parent_decl_ctx) { - auto type_system = GetTypeSystemForLanguage(lldb::eLanguageTypeC_plus_plus); - auto clang_type_system = llvm::dyn_cast_or_null<ClangASTContext>(type_system); + std::lock_guard<std::recursive_mutex> guard(GetModuleMutex()); + auto type_system_or_err = + GetTypeSystemForLanguage(lldb::eLanguageTypeC_plus_plus); + if (auto err = type_system_or_err.takeError()) { + LLDB_LOG_ERROR(lldb_private::GetLogIfAnyCategoriesSet(LIBLLDB_LOG_SYMBOLS), + std::move(err), "Unable to find namespace {}", + name.AsCString()); + return CompilerDeclContext(); + } + + auto *clang_type_system = + llvm::dyn_cast_or_null<ClangASTContext>(&type_system_or_err.get()); if (!clang_type_system) return CompilerDeclContext(); @@ -1644,7 +1704,7 @@ lldb_private::CompilerDeclContext SymbolFilePDB::FindNamespace( if (!namespace_decl) return CompilerDeclContext(); - return CompilerDeclContext(type_system, + return CompilerDeclContext(clang_type_system, static_cast<clang::DeclContext *>(namespace_decl)); } @@ -1688,7 +1748,7 @@ lldb::CompUnitSP SymbolFilePDB::ParseCompileUnitForUID(uint32_t id, // Don't support optimized code for now, DebugInfoPDB does not return this // information. LazyBool optimized = eLazyBoolNo; - auto cu_sp = std::make_shared<CompileUnit>(m_obj_file->GetModule(), nullptr, + auto cu_sp = std::make_shared<CompileUnit>(m_objfile_sp->GetModule(), nullptr, path.c_str(), id, lang, optimized); if (!cu_sp) @@ -1698,8 +1758,7 @@ lldb::CompUnitSP SymbolFilePDB::ParseCompileUnitForUID(uint32_t id, if (index == UINT32_MAX) GetCompileUnitIndex(*compiland_up, index); lldbassert(index != UINT32_MAX); - m_obj_file->GetModule()->GetSymbolVendor()->SetCompileUnitAtIndex(index, - cu_sp); + SetCompileUnitAtIndex(index, cu_sp); return cu_sp; } @@ -1715,7 +1774,7 @@ bool SymbolFilePDB::ParseCompileUnitLineTable(CompileUnit &comp_unit, // to do a mapping so that we can hand out indices. llvm::DenseMap<uint32_t, uint32_t> index_map; BuildSupportFileIdToSupportFileIndexMap(*compiland_up, index_map); - auto line_table = llvm::make_unique<LineTable>(&comp_unit); + auto line_table = std::make_unique<LineTable>(&comp_unit); // Find contributions to `compiland` from all source and header files. std::string path = comp_unit.GetPath(); @@ -1925,9 +1984,17 @@ bool SymbolFilePDB::DeclContextMatchesThisSymbolFile( TypeSystem *decl_ctx_type_system = decl_ctx->GetTypeSystem(); if (!decl_ctx_type_system) return false; - TypeSystem *type_system = GetTypeSystemForLanguage( + auto type_system_or_err = GetTypeSystemForLanguage( decl_ctx_type_system->GetMinimumLanguage(nullptr)); - if (decl_ctx_type_system == type_system) + if (auto err = type_system_or_err.takeError()) { + LLDB_LOG_ERROR( + lldb_private::GetLogIfAnyCategoriesSet(LIBLLDB_LOG_SYMBOLS), + std::move(err), + "Unable to determine if DeclContext matches this symbol file"); + return false; + } + + if (decl_ctx_type_system == &type_system_or_err.get()) return true; // The type systems match, return true return false; diff --git a/source/Plugins/SymbolFile/PDB/SymbolFilePDB.h b/source/Plugins/SymbolFile/PDB/SymbolFilePDB.h index ba3099aaec4d..df717bbbbdb0 100644 --- a/source/Plugins/SymbolFile/PDB/SymbolFilePDB.h +++ b/source/Plugins/SymbolFile/PDB/SymbolFilePDB.h @@ -35,10 +35,10 @@ public: static const char *GetPluginDescriptionStatic(); static lldb_private::SymbolFile * - CreateInstance(lldb_private::ObjectFile *obj_file); + CreateInstance(lldb::ObjectFileSP objfile_sp); // Constructors and Destructors - SymbolFilePDB(lldb_private::ObjectFile *ofile); + SymbolFilePDB(lldb::ObjectFileSP objfile_sp); ~SymbolFilePDB() override; @@ -48,10 +48,6 @@ public: // Compile Unit function calls - uint32_t GetNumCompileUnits() override; - - lldb::CompUnitSP ParseCompileUnitAtIndex(uint32_t index) override; - lldb::LanguageType ParseLanguage(lldb_private::CompileUnit &comp_unit) override; @@ -103,25 +99,25 @@ public: lldb::SymbolContextItem resolve_scope, lldb_private::SymbolContextList &sc_list) override; - uint32_t + void FindGlobalVariables(lldb_private::ConstString name, const lldb_private::CompilerDeclContext *parent_decl_ctx, uint32_t max_matches, lldb_private::VariableList &variables) override; - uint32_t FindGlobalVariables(const lldb_private::RegularExpression ®ex, - uint32_t max_matches, - lldb_private::VariableList &variables) override; + void FindGlobalVariables(const lldb_private::RegularExpression ®ex, + uint32_t max_matches, + lldb_private::VariableList &variables) override; - uint32_t - FindFunctions(lldb_private::ConstString name, - const lldb_private::CompilerDeclContext *parent_decl_ctx, - lldb::FunctionNameType name_type_mask, bool include_inlines, - bool append, lldb_private::SymbolContextList &sc_list) override; + void FindFunctions(lldb_private::ConstString name, + const lldb_private::CompilerDeclContext *parent_decl_ctx, + lldb::FunctionNameType name_type_mask, + bool include_inlines, + lldb_private::SymbolContextList &sc_list) override; - uint32_t FindFunctions(const lldb_private::RegularExpression ®ex, - bool include_inlines, bool append, - lldb_private::SymbolContextList &sc_list) override; + void FindFunctions(const lldb_private::RegularExpression ®ex, + bool include_inlines, + lldb_private::SymbolContextList &sc_list) override; void GetMangledNamesForFunction( const std::string &scope_qualified_name, @@ -129,26 +125,25 @@ public: void AddSymbols(lldb_private::Symtab &symtab) override; - uint32_t + void FindTypes(lldb_private::ConstString name, const lldb_private::CompilerDeclContext *parent_decl_ctx, - bool append, uint32_t max_matches, + uint32_t max_matches, llvm::DenseSet<lldb_private::SymbolFile *> &searched_symbol_files, lldb_private::TypeMap &types) override; - size_t FindTypes(const std::vector<lldb_private::CompilerContext> &context, - bool append, lldb_private::TypeMap &types) override; + void FindTypes(llvm::ArrayRef<lldb_private::CompilerContext> pattern, + lldb_private::LanguageSet languages, + lldb_private::TypeMap &types) override; void FindTypesByRegex(const lldb_private::RegularExpression ®ex, uint32_t max_matches, lldb_private::TypeMap &types); - lldb_private::TypeList *GetTypeList() override; - - size_t GetTypes(lldb_private::SymbolContextScope *sc_scope, - lldb::TypeClass type_mask, - lldb_private::TypeList &type_list) override; + void GetTypes(lldb_private::SymbolContextScope *sc_scope, + lldb::TypeClass type_mask, + lldb_private::TypeList &type_list) override; - lldb_private::TypeSystem * + llvm::Expected<lldb_private::TypeSystem &> GetTypeSystemForLanguage(lldb::LanguageType language) override; lldb_private::CompilerDeclContext FindNamespace( @@ -173,6 +168,10 @@ private: }; using SecContribsMap = std::map<uint32_t, std::vector<SecContribInfo>>; + uint32_t CalculateNumCompileUnits() override; + + lldb::CompUnitSP ParseCompileUnitAtIndex(uint32_t index) override; + lldb::CompUnitSP ParseCompileUnitForUID(uint32_t id, uint32_t index = UINT32_MAX); @@ -245,7 +244,6 @@ private: std::vector<lldb::TypeSP> m_builtin_types; std::unique_ptr<llvm::pdb::IPDBSession> m_session_up; std::unique_ptr<llvm::pdb::PDBSymbolExe> m_global_scope_up; - uint32_t m_cached_compile_unit_count; lldb_private::UniqueCStringMap<uint32_t> m_func_full_names; lldb_private::UniqueCStringMap<uint32_t> m_func_base_names; diff --git a/source/Plugins/SymbolFile/Symtab/SymbolFileSymtab.cpp b/source/Plugins/SymbolFile/Symtab/SymbolFileSymtab.cpp index a1b21e51b0fe..62da76581c3e 100644 --- a/source/Plugins/SymbolFile/Symtab/SymbolFileSymtab.cpp +++ b/source/Plugins/SymbolFile/Symtab/SymbolFileSymtab.cpp @@ -43,26 +43,24 @@ const char *SymbolFileSymtab::GetPluginDescriptionStatic() { return "Reads debug symbols from an object file's symbol table."; } -SymbolFile *SymbolFileSymtab::CreateInstance(ObjectFile *obj_file) { - return new SymbolFileSymtab(obj_file); +SymbolFile *SymbolFileSymtab::CreateInstance(ObjectFileSP objfile_sp) { + return new SymbolFileSymtab(std::move(objfile_sp)); } -size_t SymbolFileSymtab::GetTypes(SymbolContextScope *sc_scope, - TypeClass type_mask, - lldb_private::TypeList &type_list) { - return 0; -} +void SymbolFileSymtab::GetTypes(SymbolContextScope *sc_scope, + TypeClass type_mask, + lldb_private::TypeList &type_list) {} -SymbolFileSymtab::SymbolFileSymtab(ObjectFile *obj_file) - : SymbolFile(obj_file), m_source_indexes(), m_func_indexes(), +SymbolFileSymtab::SymbolFileSymtab(ObjectFileSP objfile_sp) + : SymbolFile(std::move(objfile_sp)), m_source_indexes(), m_func_indexes(), m_code_indexes(), m_objc_class_name_to_index() {} SymbolFileSymtab::~SymbolFileSymtab() {} uint32_t SymbolFileSymtab::CalculateAbilities() { uint32_t abilities = 0; - if (m_obj_file) { - const Symtab *symtab = m_obj_file->GetSymtab(); + if (m_objfile_sp) { + const Symtab *symtab = m_objfile_sp->GetSymtab(); if (symtab) { // The snippet of code below will get the indexes the module symbol table // entries that are code, data, or function related (debug info), sort @@ -104,7 +102,7 @@ uint32_t SymbolFileSymtab::CalculateAbilities() { return abilities; } -uint32_t SymbolFileSymtab::GetNumCompileUnits() { +uint32_t SymbolFileSymtab::CalculateNumCompileUnits() { // If we don't have any source file symbols we will just have one compile // unit for the entire object file if (m_source_indexes.empty()) @@ -122,10 +120,10 @@ CompUnitSP SymbolFileSymtab::ParseCompileUnitAtIndex(uint32_t idx) { // unit for the entire object file if (idx < m_source_indexes.size()) { const Symbol *cu_symbol = - m_obj_file->GetSymtab()->SymbolAtIndex(m_source_indexes[idx]); + m_objfile_sp->GetSymtab()->SymbolAtIndex(m_source_indexes[idx]); if (cu_symbol) - cu_sp = std::make_shared<CompileUnit>(m_obj_file->GetModule(), nullptr, - cu_symbol->GetName().AsCString(), 0, + cu_sp = std::make_shared<CompileUnit>(m_objfile_sp->GetModule(), nullptr, + cu_symbol->GetName().AsCString(), 0, eLanguageTypeUnknown, eLazyBoolNo); } return cu_sp; @@ -136,12 +134,13 @@ lldb::LanguageType SymbolFileSymtab::ParseLanguage(CompileUnit &comp_unit) { } size_t SymbolFileSymtab::ParseFunctions(CompileUnit &comp_unit) { + std::lock_guard<std::recursive_mutex> guard(GetModuleMutex()); size_t num_added = 0; // We must at least have a valid compile unit - const Symtab *symtab = m_obj_file->GetSymtab(); + const Symtab *symtab = m_objfile_sp->GetSymtab(); const Symbol *curr_symbol = nullptr; const Symbol *next_symbol = nullptr; - // const char *prefix = m_obj_file->SymbolPrefix(); + // const char *prefix = m_objfile_sp->SymbolPrefix(); // if (prefix == NULL) // prefix == ""; // @@ -246,12 +245,13 @@ bool SymbolFileSymtab::CompleteType(lldb_private::CompilerType &compiler_type) { uint32_t SymbolFileSymtab::ResolveSymbolContext(const Address &so_addr, SymbolContextItem resolve_scope, SymbolContext &sc) { - if (m_obj_file->GetSymtab() == nullptr) + std::lock_guard<std::recursive_mutex> guard(GetModuleMutex()); + if (m_objfile_sp->GetSymtab() == nullptr) return 0; uint32_t resolved_flags = 0; if (resolve_scope & eSymbolContextSymbol) { - sc.symbol = m_obj_file->GetSymtab()->FindSymbolContainingFileAddress( + sc.symbol = m_objfile_sp->GetSymtab()->FindSymbolContainingFileAddress( so_addr.GetFileAddress()); if (sc.symbol) resolved_flags |= eSymbolContextSymbol; diff --git a/source/Plugins/SymbolFile/Symtab/SymbolFileSymtab.h b/source/Plugins/SymbolFile/Symtab/SymbolFileSymtab.h index bc9a531419ae..2ac4660f0125 100644 --- a/source/Plugins/SymbolFile/Symtab/SymbolFileSymtab.h +++ b/source/Plugins/SymbolFile/Symtab/SymbolFileSymtab.h @@ -18,7 +18,7 @@ class SymbolFileSymtab : public lldb_private::SymbolFile { public: // Constructors and Destructors - SymbolFileSymtab(lldb_private::ObjectFile *obj_file); + SymbolFileSymtab(lldb::ObjectFileSP objfile_sp); ~SymbolFileSymtab() override; @@ -32,15 +32,11 @@ public: static const char *GetPluginDescriptionStatic(); static lldb_private::SymbolFile * - CreateInstance(lldb_private::ObjectFile *obj_file); + CreateInstance(lldb::ObjectFileSP objfile_sp); uint32_t CalculateAbilities() override; // Compile Unit function calls - uint32_t GetNumCompileUnits() override; - - lldb::CompUnitSP ParseCompileUnitAtIndex(uint32_t index) override; - lldb::LanguageType ParseLanguage(lldb_private::CompileUnit &comp_unit) override; @@ -75,9 +71,9 @@ public: lldb::SymbolContextItem resolve_scope, lldb_private::SymbolContext &sc) override; - size_t GetTypes(lldb_private::SymbolContextScope *sc_scope, - lldb::TypeClass type_mask, - lldb_private::TypeList &type_list) override; + void GetTypes(lldb_private::SymbolContextScope *sc_scope, + lldb::TypeClass type_mask, + lldb_private::TypeList &type_list) override; // PluginInterface protocol lldb_private::ConstString GetPluginName() override; @@ -85,6 +81,10 @@ public: uint32_t GetPluginVersion() override; protected: + uint32_t CalculateNumCompileUnits() override; + + lldb::CompUnitSP ParseCompileUnitAtIndex(uint32_t index) override; + typedef std::map<lldb_private::ConstString, lldb::TypeSP> TypeMap; lldb_private::Symtab::IndexCollection m_source_indexes; diff --git a/source/Plugins/SymbolVendor/ELF/SymbolVendorELF.cpp b/source/Plugins/SymbolVendor/ELF/SymbolVendorELF.cpp index f279af61a131..e61e5763fabb 100644 --- a/source/Plugins/SymbolVendor/ELF/SymbolVendorELF.cpp +++ b/source/Plugins/SymbolVendor/ELF/SymbolVendorELF.cpp @@ -10,6 +10,7 @@ #include <string.h> +#include "Plugins/ObjectFile/ELF/ObjectFileELF.h" #include "lldb/Core/Module.h" #include "lldb/Core/ModuleSpec.h" #include "lldb/Core/PluginManager.h" @@ -61,99 +62,86 @@ SymbolVendorELF::CreateInstance(const lldb::ModuleSP &module_sp, if (!module_sp) return nullptr; - ObjectFile *obj_file = module_sp->GetObjectFile(); + ObjectFileELF *obj_file = + llvm::dyn_cast_or_null<ObjectFileELF>(module_sp->GetObjectFile()); if (!obj_file) return nullptr; - static ConstString obj_file_elf("elf"); - ConstString obj_name = obj_file->GetPluginName(); - if (obj_name != obj_file_elf) - return nullptr; - lldb_private::UUID uuid = obj_file->GetUUID(); if (!uuid) return nullptr; - // Get the .gnu_debuglink file (if specified). - FileSpecList file_spec_list = obj_file->GetDebugSymbolFilePaths(); - - // If the module specified a filespec, use it first. - FileSpec debug_symbol_fspec(module_sp->GetSymbolFileFileSpec()); - if (debug_symbol_fspec) - file_spec_list.Insert(0, debug_symbol_fspec); - - // If we have no debug symbol files, then nothing to do. - if (file_spec_list.IsEmpty()) + // If the main object file already contains debug info, then we are done. + if (obj_file->GetSectionList()->FindSectionByType( + lldb::eSectionTypeDWARFDebugInfo, true)) return nullptr; + // If the module specified a filespec, use that. + FileSpec fspec = module_sp->GetSymbolFileFileSpec(); + // Otherwise, try gnu_debuglink, if one exists. + if (!fspec) + fspec = obj_file->GetDebugLink().getValueOr(FileSpec()); + static Timer::Category func_cat(LLVM_PRETTY_FUNCTION); Timer scoped_timer(func_cat, "SymbolVendorELF::CreateInstance (module = %s)", module_sp->GetFileSpec().GetPath().c_str()); - for (size_t idx = 0; idx < file_spec_list.GetSize(); ++idx) { - ModuleSpec module_spec; - const FileSpec fspec = file_spec_list.GetFileSpecAtIndex(idx); - - module_spec.GetFileSpec() = obj_file->GetFileSpec(); - FileSystem::Instance().Resolve(module_spec.GetFileSpec()); - module_spec.GetSymbolFileSpec() = fspec; - module_spec.GetUUID() = uuid; - FileSpecList search_paths = Target::GetDefaultDebugFileSearchPaths(); - FileSpec dsym_fspec = - Symbols::LocateExecutableSymbolFile(module_spec, search_paths); - if (dsym_fspec) { - DataBufferSP dsym_file_data_sp; - lldb::offset_t dsym_file_data_offset = 0; - ObjectFileSP dsym_objfile_sp = - ObjectFile::FindPlugin(module_sp, &dsym_fspec, 0, - FileSystem::Instance().GetByteSize(dsym_fspec), - dsym_file_data_sp, dsym_file_data_offset); - if (dsym_objfile_sp) { - // This objfile is for debugging purposes. Sadly, ObjectFileELF won't - // be able to figure this out consistently as the symbol file may not - // have stripped the code sections, etc. - dsym_objfile_sp->SetType(ObjectFile::eTypeDebugInfo); - - SymbolVendorELF *symbol_vendor = new SymbolVendorELF(module_sp); - if (symbol_vendor) { - // Get the module unified section list and add our debug sections to - // that. - SectionList *module_section_list = module_sp->GetSectionList(); - SectionList *objfile_section_list = dsym_objfile_sp->GetSectionList(); - - static const SectionType g_sections[] = { - eSectionTypeDWARFDebugAbbrev, eSectionTypeDWARFDebugAddr, - eSectionTypeDWARFDebugAranges, eSectionTypeDWARFDebugCuIndex, - eSectionTypeDWARFDebugFrame, eSectionTypeDWARFDebugInfo, - eSectionTypeDWARFDebugLine, eSectionTypeDWARFDebugLoc, - eSectionTypeDWARFDebugMacInfo, eSectionTypeDWARFDebugPubNames, - eSectionTypeDWARFDebugPubTypes, eSectionTypeDWARFDebugRanges, - eSectionTypeDWARFDebugStr, eSectionTypeDWARFDebugStrOffsets, - eSectionTypeELFSymbolTable, eSectionTypeDWARFGNUDebugAltLink, - }; - for (size_t idx = 0; idx < sizeof(g_sections) / sizeof(g_sections[0]); - ++idx) { - SectionType section_type = g_sections[idx]; - SectionSP section_sp( - objfile_section_list->FindSectionByType(section_type, true)); - if (section_sp) { - SectionSP module_section_sp( - module_section_list->FindSectionByType(section_type, true)); - if (module_section_sp) - module_section_list->ReplaceSection(module_section_sp->GetID(), - section_sp); - else - module_section_list->AddSection(section_sp); - } - } - - symbol_vendor->AddSymbolFileRepresentation(dsym_objfile_sp); - return symbol_vendor; - } - } + ModuleSpec module_spec; + + module_spec.GetFileSpec() = obj_file->GetFileSpec(); + FileSystem::Instance().Resolve(module_spec.GetFileSpec()); + module_spec.GetSymbolFileSpec() = fspec; + module_spec.GetUUID() = uuid; + FileSpecList search_paths = Target::GetDefaultDebugFileSearchPaths(); + FileSpec dsym_fspec = + Symbols::LocateExecutableSymbolFile(module_spec, search_paths); + if (!dsym_fspec) + return nullptr; + + DataBufferSP dsym_file_data_sp; + lldb::offset_t dsym_file_data_offset = 0; + ObjectFileSP dsym_objfile_sp = ObjectFile::FindPlugin( + module_sp, &dsym_fspec, 0, FileSystem::Instance().GetByteSize(dsym_fspec), + dsym_file_data_sp, dsym_file_data_offset); + if (!dsym_objfile_sp) + return nullptr; + + // This objfile is for debugging purposes. Sadly, ObjectFileELF won't + // be able to figure this out consistently as the symbol file may not + // have stripped the code sections, etc. + dsym_objfile_sp->SetType(ObjectFile::eTypeDebugInfo); + + SymbolVendorELF *symbol_vendor = new SymbolVendorELF(module_sp); + + // Get the module unified section list and add our debug sections to + // that. + SectionList *module_section_list = module_sp->GetSectionList(); + SectionList *objfile_section_list = dsym_objfile_sp->GetSectionList(); + + static const SectionType g_sections[] = { + eSectionTypeDWARFDebugAbbrev, eSectionTypeDWARFDebugAddr, + eSectionTypeDWARFDebugAranges, eSectionTypeDWARFDebugCuIndex, + eSectionTypeDWARFDebugFrame, eSectionTypeDWARFDebugInfo, + eSectionTypeDWARFDebugLine, eSectionTypeDWARFDebugLoc, + eSectionTypeDWARFDebugMacInfo, eSectionTypeDWARFDebugPubNames, + eSectionTypeDWARFDebugPubTypes, eSectionTypeDWARFDebugRanges, + eSectionTypeDWARFDebugStr, eSectionTypeDWARFDebugStrOffsets, + eSectionTypeELFSymbolTable, eSectionTypeDWARFGNUDebugAltLink, + }; + for (SectionType section_type : g_sections) { + if (SectionSP section_sp = + objfile_section_list->FindSectionByType(section_type, true)) { + if (SectionSP module_section_sp = + module_section_list->FindSectionByType(section_type, true)) + module_section_list->ReplaceSection(module_section_sp->GetID(), + section_sp); + else + module_section_list->AddSection(section_sp); } } - return nullptr; + + symbol_vendor->AddSymbolFileRepresentation(dsym_objfile_sp); + return symbol_vendor; } // PluginInterface protocol diff --git a/source/Plugins/UnwindAssembly/x86/x86AssemblyInspectionEngine.cpp b/source/Plugins/UnwindAssembly/x86/x86AssemblyInspectionEngine.cpp index 43041ca1bb2f..bf6f60a2d26c 100644 --- a/source/Plugins/UnwindAssembly/x86/x86AssemblyInspectionEngine.cpp +++ b/source/Plugins/UnwindAssembly/x86/x86AssemblyInspectionEngine.cpp @@ -1328,6 +1328,7 @@ bool x86AssemblyInspectionEngine::GetNonCallSiteUnwindPlanFromAssembly( unwind_plan.SetSourceName("assembly insn profiling"); unwind_plan.SetSourcedFromCompiler(eLazyBoolNo); unwind_plan.SetUnwindPlanValidAtAllInstructions(eLazyBoolYes); + unwind_plan.SetUnwindPlanForSignalTrap(eLazyBoolNo); return true; } @@ -1370,7 +1371,6 @@ bool x86AssemblyInspectionEngine::AugmentUnwindPlanFromCallSite( int row_id = 1; bool unwind_plan_updated = false; UnwindPlan::RowSP row(new UnwindPlan::Row(*first_row)); - m_cur_insn = data + offset; // After a mid-function epilogue we will need to re-insert the original // unwind rules so unwinds work for the remainder of the function. These @@ -1380,19 +1380,17 @@ bool x86AssemblyInspectionEngine::AugmentUnwindPlanFromCallSite( while (offset < size) { m_cur_insn = data + offset; int insn_len; - if (!instruction_length(m_cur_insn, insn_len, size - offset) - || insn_len == 0 - || insn_len > kMaxInstructionByteSize) { + if (!instruction_length(m_cur_insn, insn_len, size - offset) || + insn_len == 0 || insn_len > kMaxInstructionByteSize) { // An unrecognized/junk instruction. break; } // Advance offsets. offset += insn_len; - m_cur_insn = data + offset; // offset is pointing beyond the bounds of the function; stop looping. - if (offset >= size) + if (offset >= size) continue; if (reinstate_unwind_state) { @@ -1546,16 +1544,18 @@ bool x86AssemblyInspectionEngine::AugmentUnwindPlanFromCallSite( // [0x5d] pop %rbp/%ebp // => [0xc3] ret if (pop_rbp_pattern_p() || leave_pattern_p()) { - offset += 1; - row->SetOffset(offset); - row->GetCFAValue().SetIsRegisterPlusOffset( - first_row->GetCFAValue().GetRegisterNumber(), m_wordsize); - - UnwindPlan::RowSP new_row(new UnwindPlan::Row(*row)); - unwind_plan.InsertRow(new_row); - unwind_plan_updated = true; - reinstate_unwind_state = true; - continue; + m_cur_insn++; + if (ret_pattern_p()) { + row->SetOffset(offset); + row->GetCFAValue().SetIsRegisterPlusOffset( + first_row->GetCFAValue().GetRegisterNumber(), m_wordsize); + + UnwindPlan::RowSP new_row(new UnwindPlan::Row(*row)); + unwind_plan.InsertRow(new_row); + unwind_plan_updated = true; + reinstate_unwind_state = true; + continue; + } } } else { // CFA register is not sp or fp. diff --git a/source/Symbol/ArmUnwindInfo.cpp b/source/Symbol/ArmUnwindInfo.cpp index b9fd84b1e706..fdf4e30b2db5 100644 --- a/source/Symbol/ArmUnwindInfo.cpp +++ b/source/Symbol/ArmUnwindInfo.cpp @@ -344,6 +344,7 @@ bool ArmUnwindInfo::GetUnwindPlan(Target &target, const Address &addr, unwind_plan.SetSourceName("ARM.exidx unwind info"); unwind_plan.SetSourcedFromCompiler(eLazyBoolYes); unwind_plan.SetUnwindPlanValidAtAllInstructions(eLazyBoolNo); + unwind_plan.SetUnwindPlanForSignalTrap(eLazyBoolNo); unwind_plan.SetRegisterKind(eRegisterKindDWARF); return true; diff --git a/source/Symbol/Block.cpp b/source/Symbol/Block.cpp index 6fe617080f96..77a4830dea7c 100644 --- a/source/Symbol/Block.cpp +++ b/source/Symbol/Block.cpp @@ -12,7 +12,6 @@ #include "lldb/Core/Section.h" #include "lldb/Symbol/Function.h" #include "lldb/Symbol/SymbolFile.h" -#include "lldb/Symbol/SymbolVendor.h" #include "lldb/Symbol/VariableList.h" #include "lldb/Utility/Log.h" @@ -337,22 +336,24 @@ void Block::AddRange(const Range &range) { const Declaration &func_decl = func_type->GetDeclaration(); if (func_decl.GetLine()) { - log->Printf("warning: %s:%u block {0x%8.8" PRIx64 - "} has range[%u] [0x%" PRIx64 " - 0x%" PRIx64 - ") which is not contained in parent block {0x%8.8" PRIx64 - "} in function {0x%8.8" PRIx64 "} from %s", - func_decl.GetFile().GetPath().c_str(), func_decl.GetLine(), - GetID(), (uint32_t)m_ranges.GetSize(), block_start_addr, - block_end_addr, parent_block->GetID(), function->GetID(), - module_sp->GetFileSpec().GetPath().c_str()); + LLDB_LOGF(log, + "warning: %s:%u block {0x%8.8" PRIx64 + "} has range[%u] [0x%" PRIx64 " - 0x%" PRIx64 + ") which is not contained in parent block {0x%8.8" PRIx64 + "} in function {0x%8.8" PRIx64 "} from %s", + func_decl.GetFile().GetPath().c_str(), func_decl.GetLine(), + GetID(), (uint32_t)m_ranges.GetSize(), block_start_addr, + block_end_addr, parent_block->GetID(), function->GetID(), + module_sp->GetFileSpec().GetPath().c_str()); } else { - log->Printf("warning: block {0x%8.8" PRIx64 - "} has range[%u] [0x%" PRIx64 " - 0x%" PRIx64 - ") which is not contained in parent block {0x%8.8" PRIx64 - "} in function {0x%8.8" PRIx64 "} from %s", - GetID(), (uint32_t)m_ranges.GetSize(), block_start_addr, - block_end_addr, parent_block->GetID(), function->GetID(), - module_sp->GetFileSpec().GetPath().c_str()); + LLDB_LOGF(log, + "warning: block {0x%8.8" PRIx64 "} has range[%u] [0x%" PRIx64 + " - 0x%" PRIx64 + ") which is not contained in parent block {0x%8.8" PRIx64 + "} in function {0x%8.8" PRIx64 "} from %s", + GetID(), (uint32_t)m_ranges.GetSize(), block_start_addr, + block_end_addr, parent_block->GetID(), function->GetID(), + module_sp->GetFileSpec().GetPath().c_str()); } } parent_block->AddRange(range); @@ -391,7 +392,7 @@ VariableListSP Block::GetBlockVariableList(bool can_create) { SymbolContext sc; CalculateSymbolContext(&sc); assert(sc.module_sp); - sc.module_sp->GetSymbolVendor()->ParseVariablesForContext(sc); + sc.module_sp->GetSymbolFile()->ParseVariablesForContext(sc); } } return m_variable_list_sp; @@ -462,8 +463,7 @@ uint32_t Block::AppendVariables(bool can_create, bool get_parent_variables, SymbolFile *Block::GetSymbolFile() { if (ModuleSP module_sp = CalculateSymbolContextModule()) - if (SymbolVendor *sym_vendor = module_sp->GetSymbolVendor()) - return sym_vendor->GetSymbolFile(); + return module_sp->GetSymbolFile(); return nullptr; } diff --git a/source/Symbol/ClangASTContext.cpp b/source/Symbol/ClangASTContext.cpp index 205523355ce0..565b15a007da 100644 --- a/source/Symbol/ClangASTContext.cpp +++ b/source/Symbol/ClangASTContext.cpp @@ -47,11 +47,11 @@ #include "clang/Basic/Diagnostic.h" #include "clang/Basic/FileManager.h" #include "clang/Basic/FileSystemOptions.h" +#include "clang/Basic/LangStandard.h" #include "clang/Basic/SourceManager.h" #include "clang/Basic/TargetInfo.h" #include "clang/Basic/TargetOptions.h" #include "clang/Frontend/FrontendOptions.h" -#include "clang/Frontend/LangStandard.h" #include "clang/Sema/Sema.h" #ifdef LLDB_DEFINED_NDEBUG_FOR_CLANG @@ -65,6 +65,7 @@ #include "llvm/Support/Threading.h" #include "Plugins/ExpressionParser/Clang/ClangFunctionCaller.h" +#include "Plugins/ExpressionParser/Clang/ClangPersistentVariables.h" #include "Plugins/ExpressionParser/Clang/ClangUserExpression.h" #include "Plugins/ExpressionParser/Clang/ClangUtilityFunction.h" #include "lldb/Utility/ArchSpec.h" @@ -76,14 +77,12 @@ #include "lldb/Core/StreamFile.h" #include "lldb/Core/ThreadSafeDenseMap.h" #include "lldb/Core/UniqueCStringMap.h" -#include "lldb/Symbol/ClangASTContext.h" #include "lldb/Symbol/ClangASTImporter.h" #include "lldb/Symbol/ClangExternalASTSourceCallbacks.h" #include "lldb/Symbol/ClangExternalASTSourceCommon.h" #include "lldb/Symbol/ClangUtil.h" #include "lldb/Symbol/ObjectFile.h" #include "lldb/Symbol/SymbolFile.h" -#include "lldb/Symbol/VerifyDecl.h" #include "lldb/Target/ExecutionContext.h" #include "lldb/Target/Language.h" #include "lldb/Target/Process.h" @@ -104,17 +103,24 @@ using namespace lldb; using namespace lldb_private; -using namespace llvm; using namespace clang; +using llvm::StringSwitch; namespace { +#ifdef LLDB_CONFIGURATION_DEBUG +static void VerifyDecl(clang::Decl *decl) { + assert(decl && "VerifyDecl called with nullptr?"); + decl->getAccess(); +} +#endif + static inline bool ClangASTContextSupportsLanguage(lldb::LanguageType language) { return language == eLanguageTypeUnknown || // Clang is the default type system - Language::LanguageIsC(language) || - Language::LanguageIsCPlusPlus(language) || - Language::LanguageIsObjC(language) || - Language::LanguageIsPascal(language) || + lldb_private::Language::LanguageIsC(language) || + lldb_private::Language::LanguageIsCPlusPlus(language) || + lldb_private::Language::LanguageIsObjC(language) || + lldb_private::Language::LanguageIsPascal(language) || // Use Clang for Rust until there is a proper language plugin for it language == eLanguageTypeRust || language == eLanguageTypeExtRenderScript || @@ -331,219 +337,82 @@ static ClangASTMap &GetASTMap() { return *g_map_ptr; } -bool ClangASTContext::IsOperator(const char *name, +bool ClangASTContext::IsOperator(llvm::StringRef name, clang::OverloadedOperatorKind &op_kind) { - if (name == nullptr || name[0] == '\0') - return false; - -#define OPERATOR_PREFIX "operator" -#define OPERATOR_PREFIX_LENGTH (sizeof(OPERATOR_PREFIX) - 1) - - const char *post_op_name = nullptr; - - bool no_space = true; - - if (::strncmp(name, OPERATOR_PREFIX, OPERATOR_PREFIX_LENGTH)) + // All operators have to start with "operator". + if (!name.consume_front("operator")) return false; - post_op_name = name + OPERATOR_PREFIX_LENGTH; - - if (post_op_name[0] == ' ') { - post_op_name++; - no_space = false; - } - -#undef OPERATOR_PREFIX -#undef OPERATOR_PREFIX_LENGTH - - // This is an operator, set the overloaded operator kind to invalid in case - // this is a conversion operator... - op_kind = clang::NUM_OVERLOADED_OPERATORS; - - switch (post_op_name[0]) { - default: - if (no_space) - return false; - break; - case 'n': - if (no_space) - return false; - if (strcmp(post_op_name, "new") == 0) - op_kind = clang::OO_New; - else if (strcmp(post_op_name, "new[]") == 0) - op_kind = clang::OO_Array_New; - break; - - case 'd': - if (no_space) - return false; - if (strcmp(post_op_name, "delete") == 0) - op_kind = clang::OO_Delete; - else if (strcmp(post_op_name, "delete[]") == 0) - op_kind = clang::OO_Array_Delete; - break; - - case '+': - if (post_op_name[1] == '\0') - op_kind = clang::OO_Plus; - else if (post_op_name[2] == '\0') { - if (post_op_name[1] == '=') - op_kind = clang::OO_PlusEqual; - else if (post_op_name[1] == '+') - op_kind = clang::OO_PlusPlus; - } - break; - - case '-': - if (post_op_name[1] == '\0') - op_kind = clang::OO_Minus; - else if (post_op_name[2] == '\0') { - switch (post_op_name[1]) { - case '=': - op_kind = clang::OO_MinusEqual; - break; - case '-': - op_kind = clang::OO_MinusMinus; - break; - case '>': - op_kind = clang::OO_Arrow; - break; - } - } else if (post_op_name[3] == '\0') { - if (post_op_name[2] == '*') - op_kind = clang::OO_ArrowStar; - break; - } - break; - - case '*': - if (post_op_name[1] == '\0') - op_kind = clang::OO_Star; - else if (post_op_name[1] == '=' && post_op_name[2] == '\0') - op_kind = clang::OO_StarEqual; - break; - - case '/': - if (post_op_name[1] == '\0') - op_kind = clang::OO_Slash; - else if (post_op_name[1] == '=' && post_op_name[2] == '\0') - op_kind = clang::OO_SlashEqual; - break; - - case '%': - if (post_op_name[1] == '\0') - op_kind = clang::OO_Percent; - else if (post_op_name[1] == '=' && post_op_name[2] == '\0') - op_kind = clang::OO_PercentEqual; - break; - - case '^': - if (post_op_name[1] == '\0') - op_kind = clang::OO_Caret; - else if (post_op_name[1] == '=' && post_op_name[2] == '\0') - op_kind = clang::OO_CaretEqual; - break; - - case '&': - if (post_op_name[1] == '\0') - op_kind = clang::OO_Amp; - else if (post_op_name[2] == '\0') { - switch (post_op_name[1]) { - case '=': - op_kind = clang::OO_AmpEqual; - break; - case '&': - op_kind = clang::OO_AmpAmp; - break; - } - } - break; - - case '|': - if (post_op_name[1] == '\0') - op_kind = clang::OO_Pipe; - else if (post_op_name[2] == '\0') { - switch (post_op_name[1]) { - case '=': - op_kind = clang::OO_PipeEqual; - break; - case '|': - op_kind = clang::OO_PipePipe; - break; - } - } - break; - - case '~': - if (post_op_name[1] == '\0') - op_kind = clang::OO_Tilde; - break; - - case '!': - if (post_op_name[1] == '\0') - op_kind = clang::OO_Exclaim; - else if (post_op_name[1] == '=' && post_op_name[2] == '\0') - op_kind = clang::OO_ExclaimEqual; - break; - - case '=': - if (post_op_name[1] == '\0') - op_kind = clang::OO_Equal; - else if (post_op_name[1] == '=' && post_op_name[2] == '\0') - op_kind = clang::OO_EqualEqual; - break; - - case '<': - if (post_op_name[1] == '\0') - op_kind = clang::OO_Less; - else if (post_op_name[2] == '\0') { - switch (post_op_name[1]) { - case '<': - op_kind = clang::OO_LessLess; - break; - case '=': - op_kind = clang::OO_LessEqual; - break; - } - } else if (post_op_name[3] == '\0') { - if (post_op_name[2] == '=') - op_kind = clang::OO_LessLessEqual; - } - break; - - case '>': - if (post_op_name[1] == '\0') - op_kind = clang::OO_Greater; - else if (post_op_name[2] == '\0') { - switch (post_op_name[1]) { - case '>': - op_kind = clang::OO_GreaterGreater; - break; - case '=': - op_kind = clang::OO_GreaterEqual; - break; - } - } else if (post_op_name[1] == '>' && post_op_name[2] == '=' && - post_op_name[3] == '\0') { - op_kind = clang::OO_GreaterGreaterEqual; - } - break; - - case ',': - if (post_op_name[1] == '\0') - op_kind = clang::OO_Comma; - break; - - case '(': - if (post_op_name[1] == ')' && post_op_name[2] == '\0') - op_kind = clang::OO_Call; - break; + // Remember if there was a space after "operator". This is necessary to + // check for collisions with strangely named functions like "operatorint()". + bool space_after_operator = name.consume_front(" "); + + op_kind = StringSwitch<clang::OverloadedOperatorKind>(name) + .Case("+", clang::OO_Plus) + .Case("+=", clang::OO_PlusEqual) + .Case("++", clang::OO_PlusPlus) + .Case("-", clang::OO_Minus) + .Case("-=", clang::OO_MinusEqual) + .Case("--", clang::OO_MinusMinus) + .Case("->", clang::OO_Arrow) + .Case("->*", clang::OO_ArrowStar) + .Case("*", clang::OO_Star) + .Case("*=", clang::OO_StarEqual) + .Case("/", clang::OO_Slash) + .Case("/=", clang::OO_SlashEqual) + .Case("%", clang::OO_Percent) + .Case("%=", clang::OO_PercentEqual) + .Case("^", clang::OO_Caret) + .Case("^=", clang::OO_CaretEqual) + .Case("&", clang::OO_Amp) + .Case("&=", clang::OO_AmpEqual) + .Case("&&", clang::OO_AmpAmp) + .Case("|", clang::OO_Pipe) + .Case("|=", clang::OO_PipeEqual) + .Case("||", clang::OO_PipePipe) + .Case("~", clang::OO_Tilde) + .Case("!", clang::OO_Exclaim) + .Case("!=", clang::OO_ExclaimEqual) + .Case("=", clang::OO_Equal) + .Case("==", clang::OO_EqualEqual) + .Case("<", clang::OO_Less) + .Case("<<", clang::OO_LessLess) + .Case("<<=", clang::OO_LessLessEqual) + .Case("<=", clang::OO_LessEqual) + .Case(">", clang::OO_Greater) + .Case(">>", clang::OO_GreaterGreater) + .Case(">>=", clang::OO_GreaterGreaterEqual) + .Case(">=", clang::OO_GreaterEqual) + .Case("()", clang::OO_Call) + .Case("[]", clang::OO_Subscript) + .Case(",", clang::OO_Comma) + .Default(clang::NUM_OVERLOADED_OPERATORS); + + // We found a fitting operator, so we can exit now. + if (op_kind != clang::NUM_OVERLOADED_OPERATORS) + return true; - case '[': - if (post_op_name[1] == ']' && post_op_name[2] == '\0') - op_kind = clang::OO_Subscript; - break; - } + // After the "operator " or "operator" part is something unknown. This means + // it's either one of the named operators (new/delete), a conversion operator + // (e.g. operator bool) or a function which name starts with "operator" + // (e.g. void operatorbool). + + // If it's a function that starts with operator it can't have a space after + // "operator" because identifiers can't contain spaces. + // E.g. "operator int" (conversion operator) + // vs. "operatorint" (function with colliding name). + if (!space_after_operator) + return false; // not an operator. + + // Now the operator is either one of the named operators or a conversion + // operator. + op_kind = StringSwitch<clang::OverloadedOperatorKind>(name) + .Case("new", clang::OO_New) + .Case("new[]", clang::OO_Array_New) + .Case("delete", clang::OO_Delete) + .Case("delete[]", clang::OO_Array_Delete) + // conversion operators hit this case. + .Default(clang::NUM_OVERLOADED_OPERATORS); return true; } @@ -571,7 +440,7 @@ static void ParseLangArgs(LangOptions &Opts, InputKind IK, const char *triple) { // Set some properties which depend solely on the input kind; it would be // nice to move these to the language standard, and have the driver resolve // the input kind + language standard. - if (IK.getLanguage() == InputKind::Asm) { + if (IK.getLanguage() == clang::Language::Asm) { Opts.AsmPreprocessor = 1; } else if (IK.isObjectiveC()) { Opts.ObjC = 1; @@ -582,26 +451,26 @@ static void ParseLangArgs(LangOptions &Opts, InputKind IK, const char *triple) { if (LangStd == LangStandard::lang_unspecified) { // Based on the base language, pick one. switch (IK.getLanguage()) { - case InputKind::Unknown: - case InputKind::LLVM_IR: - case InputKind::RenderScript: + case clang::Language::Unknown: + case clang::Language::LLVM_IR: + case clang::Language::RenderScript: llvm_unreachable("Invalid input kind!"); - case InputKind::OpenCL: + case clang::Language::OpenCL: LangStd = LangStandard::lang_opencl10; break; - case InputKind::CUDA: + case clang::Language::CUDA: LangStd = LangStandard::lang_cuda; break; - case InputKind::Asm: - case InputKind::C: - case InputKind::ObjC: + case clang::Language::Asm: + case clang::Language::C: + case clang::Language::ObjC: LangStd = LangStandard::lang_gnu99; break; - case InputKind::CXX: - case InputKind::ObjCXX: + case clang::Language::CXX: + case clang::Language::ObjCXX: LangStd = LangStandard::lang_gnucxx98; break; - case InputKind::HIP: + case clang::Language::HIP: LangStd = LangStandard::lang_hip; break; } @@ -625,7 +494,7 @@ static void ParseLangArgs(LangOptions &Opts, InputKind IK, const char *triple) { Opts.OpenCL = 1; Opts.AltiVec = 1; Opts.CXXOperatorNames = 1; - Opts.LaxVectorConversions = 1; + Opts.setLaxVectorConversions(LangOptions::LaxVectorConversionKind::All); } // OpenCL and C++ both have bool, true, false keywords. @@ -653,15 +522,29 @@ static void ParseLangArgs(LangOptions &Opts, InputKind IK, const char *triple) { Opts.NoInlineDefine = !Opt; } -ClangASTContext::ClangASTContext(const char *target_triple) - : TypeSystem(TypeSystem::eKindClang), m_target_triple(), m_ast_up(), - m_language_options_up(), m_source_manager_up(), m_diagnostics_engine_up(), - m_target_options_rp(), m_target_info_up(), m_identifier_table_up(), - m_selector_table_up(), m_builtins_up(), m_callback_tag_decl(nullptr), - m_callback_objc_decl(nullptr), m_callback_baton(nullptr), - m_pointer_byte_size(0), m_ast_owned(false) { - if (target_triple && target_triple[0]) +ClangASTContext::ClangASTContext(llvm::StringRef target_triple) + : TypeSystem(TypeSystem::eKindClang) { + if (!target_triple.empty()) SetTargetTriple(target_triple); + // The caller didn't pass an ASTContext so create a new one for this + // ClangASTContext. + CreateASTContext(); +} + +ClangASTContext::ClangASTContext(ArchSpec arch) + : TypeSystem(TypeSystem::eKindClang) { + SetTargetTriple(arch.GetTriple().str()); + // The caller didn't pass an ASTContext so create a new one for this + // ClangASTContext. + CreateASTContext(); +} + +ClangASTContext::ClangASTContext(ASTContext &existing_ctxt) + : TypeSystem(TypeSystem::eKindClang) { + SetTargetTriple(existing_ctxt.getTargetInfo().getTriple().str()); + + m_ast_up.reset(&existing_ctxt); + GetASTMap().Insert(&existing_ctxt, this); } // Destructor @@ -695,6 +578,7 @@ lldb::TypeSystemSP ClangASTContext::CreateInstance(lldb::LanguageType language, fixed_arch.GetTriple().getOS() == llvm::Triple::UnknownOS) { if (fixed_arch.GetTriple().getArch() == llvm::Triple::arm || fixed_arch.GetTriple().getArch() == llvm::Triple::aarch64 || + fixed_arch.GetTriple().getArch() == llvm::Triple::aarch64_32 || fixed_arch.GetTriple().getArch() == llvm::Triple::thumb) { fixed_arch.GetTriple().setOS(llvm::Triple::IOS); } else { @@ -703,58 +587,57 @@ lldb::TypeSystemSP ClangASTContext::CreateInstance(lldb::LanguageType language, } if (module) { - std::shared_ptr<ClangASTContext> ast_sp(new ClangASTContext); - if (ast_sp) { - ast_sp->SetArchitecture(fixed_arch); - } + std::shared_ptr<ClangASTContext> ast_sp( + new ClangASTContext(fixed_arch)); return ast_sp; } else if (target && target->IsValid()) { std::shared_ptr<ClangASTContextForExpressions> ast_sp( - new ClangASTContextForExpressions(*target)); - if (ast_sp) { - ast_sp->SetArchitecture(fixed_arch); - ast_sp->m_scratch_ast_source_up.reset( - new ClangASTSource(target->shared_from_this())); - lldbassert(ast_sp->getFileManager()); - ast_sp->m_scratch_ast_source_up->InstallASTContext( - *ast_sp->getASTContext(), *ast_sp->getFileManager(), true); - llvm::IntrusiveRefCntPtr<clang::ExternalASTSource> proxy_ast_source( - ast_sp->m_scratch_ast_source_up->CreateProxy()); - ast_sp->SetExternalSource(proxy_ast_source); - return ast_sp; - } + new ClangASTContextForExpressions(*target, fixed_arch)); + ast_sp->m_scratch_ast_source_up.reset( + new ClangASTSource(target->shared_from_this())); + lldbassert(ast_sp->getFileManager()); + ast_sp->m_scratch_ast_source_up->InstallASTContext( + *ast_sp->getASTContext(), *ast_sp->getFileManager(), true); + llvm::IntrusiveRefCntPtr<clang::ExternalASTSource> proxy_ast_source( + ast_sp->m_scratch_ast_source_up->CreateProxy()); + ast_sp->SetExternalSource(proxy_ast_source); + return ast_sp; } } } return lldb::TypeSystemSP(); } -void ClangASTContext::EnumerateSupportedLanguages( - std::set<lldb::LanguageType> &languages_for_types, - std::set<lldb::LanguageType> &languages_for_expressions) { - static std::vector<lldb::LanguageType> s_supported_languages_for_types( - {lldb::eLanguageTypeC89, lldb::eLanguageTypeC, lldb::eLanguageTypeC11, - lldb::eLanguageTypeC_plus_plus, lldb::eLanguageTypeC99, - lldb::eLanguageTypeObjC, lldb::eLanguageTypeObjC_plus_plus, - lldb::eLanguageTypeC_plus_plus_03, lldb::eLanguageTypeC_plus_plus_11, - lldb::eLanguageTypeC11, lldb::eLanguageTypeC_plus_plus_14}); - - static std::vector<lldb::LanguageType> s_supported_languages_for_expressions( - {lldb::eLanguageTypeC_plus_plus, lldb::eLanguageTypeObjC_plus_plus, - lldb::eLanguageTypeC_plus_plus_03, lldb::eLanguageTypeC_plus_plus_11, - lldb::eLanguageTypeC_plus_plus_14}); - - languages_for_types.insert(s_supported_languages_for_types.begin(), - s_supported_languages_for_types.end()); - languages_for_expressions.insert( - s_supported_languages_for_expressions.begin(), - s_supported_languages_for_expressions.end()); +LanguageSet ClangASTContext::GetSupportedLanguagesForTypes() { + LanguageSet languages; + languages.Insert(lldb::eLanguageTypeC89); + languages.Insert(lldb::eLanguageTypeC); + languages.Insert(lldb::eLanguageTypeC11); + languages.Insert(lldb::eLanguageTypeC_plus_plus); + languages.Insert(lldb::eLanguageTypeC99); + languages.Insert(lldb::eLanguageTypeObjC); + languages.Insert(lldb::eLanguageTypeObjC_plus_plus); + languages.Insert(lldb::eLanguageTypeC_plus_plus_03); + languages.Insert(lldb::eLanguageTypeC_plus_plus_11); + languages.Insert(lldb::eLanguageTypeC11); + languages.Insert(lldb::eLanguageTypeC_plus_plus_14); + return languages; +} + +LanguageSet ClangASTContext::GetSupportedLanguagesForExpressions() { + LanguageSet languages; + languages.Insert(lldb::eLanguageTypeC_plus_plus); + languages.Insert(lldb::eLanguageTypeObjC_plus_plus); + languages.Insert(lldb::eLanguageTypeC_plus_plus_03); + languages.Insert(lldb::eLanguageTypeC_plus_plus_11); + languages.Insert(lldb::eLanguageTypeC_plus_plus_14); + return languages; } void ClangASTContext::Initialize() { - PluginManager::RegisterPlugin(GetPluginNameStatic(), - "clang base AST context plug-in", - CreateInstance, EnumerateSupportedLanguages); + PluginManager::RegisterPlugin( + GetPluginNameStatic(), "clang base AST context plug-in", CreateInstance, + GetSupportedLanguagesForTypes(), GetSupportedLanguagesForExpressions()); } void ClangASTContext::Terminate() { @@ -762,11 +645,10 @@ void ClangASTContext::Terminate() { } void ClangASTContext::Finalize() { - if (m_ast_up) { - GetASTMap().Erase(m_ast_up.get()); - if (!m_ast_owned) - m_ast_up.release(); - } + assert(m_ast_up); + GetASTMap().Erase(m_ast_up.get()); + if (!m_ast_owned) + m_ast_up.release(); m_builtins_up.reset(); m_selector_table_up.reset(); @@ -776,23 +658,9 @@ void ClangASTContext::Finalize() { m_diagnostics_engine_up.reset(); m_source_manager_up.reset(); m_language_options_up.reset(); - m_ast_up.reset(); m_scratch_ast_source_up.reset(); } -void ClangASTContext::Clear() { - m_ast_up.reset(); - m_language_options_up.reset(); - m_source_manager_up.reset(); - m_diagnostics_engine_up.reset(); - m_target_options_rp.reset(); - m_target_info_up.reset(); - m_identifier_table_up.reset(); - m_selector_table_up.reset(); - m_builtins_up.reset(); - m_pointer_byte_size = 0; -} - void ClangASTContext::setSema(Sema *s) { // Ensure that the new sema actually belongs to our ASTContext. assert(s == nullptr || &s->getASTContext() == m_ast_up.get()); @@ -803,20 +671,8 @@ const char *ClangASTContext::GetTargetTriple() { return m_target_triple.c_str(); } -void ClangASTContext::SetTargetTriple(const char *target_triple) { - Clear(); - m_target_triple.assign(target_triple); -} - -void ClangASTContext::SetArchitecture(const ArchSpec &arch) { - SetTargetTriple(arch.GetTriple().str().c_str()); -} - -bool ClangASTContext::HasExternalSource() { - ASTContext *ast = getASTContext(); - if (ast) - return ast->getExternalSource() != nullptr; - return false; +void ClangASTContext::SetTargetTriple(llvm::StringRef target_triple) { + m_target_triple = target_triple.str(); } void ClangASTContext::SetExternalSource( @@ -828,56 +684,40 @@ void ClangASTContext::SetExternalSource( } } -void ClangASTContext::RemoveExternalSource() { - ASTContext *ast = getASTContext(); - - if (ast) { - llvm::IntrusiveRefCntPtr<ExternalASTSource> empty_ast_source_up; - ast->setExternalSource(empty_ast_source_up); - ast->getTranslationUnitDecl()->setHasExternalLexicalStorage(false); - } -} - -void ClangASTContext::setASTContext(clang::ASTContext *ast_ctx) { - if (!m_ast_owned) { - m_ast_up.release(); - } - m_ast_owned = false; - m_ast_up.reset(ast_ctx); - GetASTMap().Insert(ast_ctx, this); +ASTContext *ClangASTContext::getASTContext() { + assert(m_ast_up); + return m_ast_up.get(); } -ASTContext *ClangASTContext::getASTContext() { - if (m_ast_up == nullptr) { - m_ast_owned = true; - m_ast_up.reset(new ASTContext(*getLanguageOptions(), *getSourceManager(), - *getIdentifierTable(), *getSelectorTable(), - *getBuiltinContext())); +void ClangASTContext::CreateASTContext() { + assert(!m_ast_up); + m_ast_owned = true; + m_ast_up.reset(new ASTContext(*getLanguageOptions(), *getSourceManager(), + *getIdentifierTable(), *getSelectorTable(), + *getBuiltinContext())); - m_ast_up->getDiagnostics().setClient(getDiagnosticConsumer(), false); + m_ast_up->getDiagnostics().setClient(getDiagnosticConsumer(), false); - // This can be NULL if we don't know anything about the architecture or if - // the target for an architecture isn't enabled in the llvm/clang that we - // built - TargetInfo *target_info = getTargetInfo(); - if (target_info) - m_ast_up->InitBuiltinTypes(*target_info); + // This can be NULL if we don't know anything about the architecture or if + // the target for an architecture isn't enabled in the llvm/clang that we + // built + TargetInfo *target_info = getTargetInfo(); + if (target_info) + m_ast_up->InitBuiltinTypes(*target_info); - if ((m_callback_tag_decl || m_callback_objc_decl) && m_callback_baton) { - m_ast_up->getTranslationUnitDecl()->setHasExternalLexicalStorage(); - // m_ast_up->getTranslationUnitDecl()->setHasExternalVisibleStorage(); - } + if ((m_callback_tag_decl || m_callback_objc_decl) && m_callback_baton) { + m_ast_up->getTranslationUnitDecl()->setHasExternalLexicalStorage(); + // m_ast_up->getTranslationUnitDecl()->setHasExternalVisibleStorage(); + } - GetASTMap().Insert(m_ast_up.get(), this); + GetASTMap().Insert(m_ast_up.get(), this); - llvm::IntrusiveRefCntPtr<clang::ExternalASTSource> ast_source_up( - new ClangExternalASTSourceCallbacks( - ClangASTContext::CompleteTagDecl, - ClangASTContext::CompleteObjCInterfaceDecl, nullptr, - ClangASTContext::LayoutRecordType, this)); - SetExternalSource(ast_source_up); - } - return m_ast_up.get(); + llvm::IntrusiveRefCntPtr<clang::ExternalASTSource> ast_source_up( + new ClangExternalASTSourceCallbacks( + ClangASTContext::CompleteTagDecl, + ClangASTContext::CompleteObjCInterfaceDecl, nullptr, + ClangASTContext::LayoutRecordType, this)); + SetExternalSource(ast_source_up); } ClangASTContext *ClangASTContext::GetASTContext(clang::ASTContext *ast) { @@ -901,8 +741,9 @@ IdentifierTable *ClangASTContext::getIdentifierTable() { LangOptions *ClangASTContext::getLanguageOptions() { if (m_language_options_up == nullptr) { m_language_options_up.reset(new LangOptions()); - ParseLangArgs(*m_language_options_up, InputKind::ObjCXX, GetTargetTriple()); - // InitializeLangOptions(*m_language_options_up, InputKind::ObjCXX); + ParseLangArgs(*m_language_options_up, clang::Language::ObjCXX, + GetTargetTriple()); + // InitializeLangOptions(*m_language_options_up, Language::ObjCXX); } return m_language_options_up.get(); } @@ -956,7 +797,7 @@ public: llvm::SmallVector<char, 32> diag_str(10); info.FormatDiagnostic(diag_str); diag_str.push_back('\0'); - m_log->Printf("Compiler diagnostic: %s\n", diag_str.data()); + LLDB_LOGF(m_log, "Compiler diagnostic: %s\n", diag_str.data()); } } @@ -1009,60 +850,71 @@ ClangASTContext::GetBuiltinTypeForEncodingAndBitSize(Encoding encoding, CompilerType ClangASTContext::GetBuiltinTypeForEncodingAndBitSize( ASTContext *ast, Encoding encoding, uint32_t bit_size) { + auto *clang_ast_context = ClangASTContext::GetASTContext(ast); if (!ast) return CompilerType(); switch (encoding) { case eEncodingInvalid: if (QualTypeMatchesBitSize(bit_size, ast, ast->VoidPtrTy)) - return CompilerType(ast, ast->VoidPtrTy); + return CompilerType(clang_ast_context, ast->VoidPtrTy.getAsOpaquePtr()); break; case eEncodingUint: if (QualTypeMatchesBitSize(bit_size, ast, ast->UnsignedCharTy)) - return CompilerType(ast, ast->UnsignedCharTy); + return CompilerType(clang_ast_context, + ast->UnsignedCharTy.getAsOpaquePtr()); if (QualTypeMatchesBitSize(bit_size, ast, ast->UnsignedShortTy)) - return CompilerType(ast, ast->UnsignedShortTy); + return CompilerType(clang_ast_context, + ast->UnsignedShortTy.getAsOpaquePtr()); if (QualTypeMatchesBitSize(bit_size, ast, ast->UnsignedIntTy)) - return CompilerType(ast, ast->UnsignedIntTy); + return CompilerType(clang_ast_context, + ast->UnsignedIntTy.getAsOpaquePtr()); if (QualTypeMatchesBitSize(bit_size, ast, ast->UnsignedLongTy)) - return CompilerType(ast, ast->UnsignedLongTy); + return CompilerType(clang_ast_context, + ast->UnsignedLongTy.getAsOpaquePtr()); if (QualTypeMatchesBitSize(bit_size, ast, ast->UnsignedLongLongTy)) - return CompilerType(ast, ast->UnsignedLongLongTy); + return CompilerType(clang_ast_context, + ast->UnsignedLongLongTy.getAsOpaquePtr()); if (QualTypeMatchesBitSize(bit_size, ast, ast->UnsignedInt128Ty)) - return CompilerType(ast, ast->UnsignedInt128Ty); + return CompilerType(clang_ast_context, + ast->UnsignedInt128Ty.getAsOpaquePtr()); break; case eEncodingSint: if (QualTypeMatchesBitSize(bit_size, ast, ast->SignedCharTy)) - return CompilerType(ast, ast->SignedCharTy); + return CompilerType(clang_ast_context, + ast->SignedCharTy.getAsOpaquePtr()); if (QualTypeMatchesBitSize(bit_size, ast, ast->ShortTy)) - return CompilerType(ast, ast->ShortTy); + return CompilerType(clang_ast_context, ast->ShortTy.getAsOpaquePtr()); if (QualTypeMatchesBitSize(bit_size, ast, ast->IntTy)) - return CompilerType(ast, ast->IntTy); + return CompilerType(clang_ast_context, ast->IntTy.getAsOpaquePtr()); if (QualTypeMatchesBitSize(bit_size, ast, ast->LongTy)) - return CompilerType(ast, ast->LongTy); + return CompilerType(clang_ast_context, ast->LongTy.getAsOpaquePtr()); if (QualTypeMatchesBitSize(bit_size, ast, ast->LongLongTy)) - return CompilerType(ast, ast->LongLongTy); + return CompilerType(clang_ast_context, ast->LongLongTy.getAsOpaquePtr()); if (QualTypeMatchesBitSize(bit_size, ast, ast->Int128Ty)) - return CompilerType(ast, ast->Int128Ty); + return CompilerType(clang_ast_context, ast->Int128Ty.getAsOpaquePtr()); break; case eEncodingIEEE754: if (QualTypeMatchesBitSize(bit_size, ast, ast->FloatTy)) - return CompilerType(ast, ast->FloatTy); + return CompilerType(clang_ast_context, ast->FloatTy.getAsOpaquePtr()); if (QualTypeMatchesBitSize(bit_size, ast, ast->DoubleTy)) - return CompilerType(ast, ast->DoubleTy); + return CompilerType(clang_ast_context, ast->DoubleTy.getAsOpaquePtr()); if (QualTypeMatchesBitSize(bit_size, ast, ast->LongDoubleTy)) - return CompilerType(ast, ast->LongDoubleTy); + return CompilerType(clang_ast_context, + ast->LongDoubleTy.getAsOpaquePtr()); if (QualTypeMatchesBitSize(bit_size, ast, ast->HalfTy)) - return CompilerType(ast, ast->HalfTy); + return CompilerType(clang_ast_context, ast->HalfTy.getAsOpaquePtr()); break; case eEncodingVector: // Sanity check that bit_size is a multiple of 8's. if (bit_size && !(bit_size & 0x7u)) return CompilerType( - ast, ast->getExtVectorType(ast->UnsignedCharTy, bit_size / 8)); + clang_ast_context, + ast->getExtVectorType(ast->UnsignedCharTy, bit_size / 8) + .getAsOpaquePtr()); break; } @@ -1182,18 +1034,18 @@ CompilerType ClangASTContext::GetBuiltinTypeForDWARFEncodingAndBitSize( case DW_ATE_address: if (QualTypeMatchesBitSize(bit_size, ast, ast->VoidPtrTy)) - return CompilerType(ast, ast->VoidPtrTy); + return CompilerType(this, ast->VoidPtrTy.getAsOpaquePtr()); break; case DW_ATE_boolean: if (QualTypeMatchesBitSize(bit_size, ast, ast->BoolTy)) - return CompilerType(ast, ast->BoolTy); + return CompilerType(this, ast->BoolTy.getAsOpaquePtr()); if (QualTypeMatchesBitSize(bit_size, ast, ast->UnsignedCharTy)) - return CompilerType(ast, ast->UnsignedCharTy); + return CompilerType(this, ast->UnsignedCharTy.getAsOpaquePtr()); if (QualTypeMatchesBitSize(bit_size, ast, ast->UnsignedShortTy)) - return CompilerType(ast, ast->UnsignedShortTy); + return CompilerType(this, ast->UnsignedShortTy.getAsOpaquePtr()); if (QualTypeMatchesBitSize(bit_size, ast, ast->UnsignedIntTy)) - return CompilerType(ast, ast->UnsignedIntTy); + return CompilerType(this, ast->UnsignedIntTy.getAsOpaquePtr()); break; case DW_ATE_lo_user: @@ -1203,47 +1055,51 @@ CompilerType ClangASTContext::GetBuiltinTypeForDWARFEncodingAndBitSize( CompilerType complex_int_clang_type = GetBuiltinTypeForDWARFEncodingAndBitSize("int", DW_ATE_signed, bit_size / 2); - return CompilerType(ast, ast->getComplexType(ClangUtil::GetQualType( - complex_int_clang_type))); + return CompilerType( + this, ast->getComplexType( + ClangUtil::GetQualType(complex_int_clang_type)) + .getAsOpaquePtr()); } } break; case DW_ATE_complex_float: if (QualTypeMatchesBitSize(bit_size, ast, ast->FloatComplexTy)) - return CompilerType(ast, ast->FloatComplexTy); + return CompilerType(this, ast->FloatComplexTy.getAsOpaquePtr()); else if (QualTypeMatchesBitSize(bit_size, ast, ast->DoubleComplexTy)) - return CompilerType(ast, ast->DoubleComplexTy); + return CompilerType(this, ast->DoubleComplexTy.getAsOpaquePtr()); else if (QualTypeMatchesBitSize(bit_size, ast, ast->LongDoubleComplexTy)) - return CompilerType(ast, ast->LongDoubleComplexTy); + return CompilerType(this, ast->LongDoubleComplexTy.getAsOpaquePtr()); else { CompilerType complex_float_clang_type = GetBuiltinTypeForDWARFEncodingAndBitSize("float", DW_ATE_float, bit_size / 2); - return CompilerType(ast, ast->getComplexType(ClangUtil::GetQualType( - complex_float_clang_type))); + return CompilerType( + this, ast->getComplexType( + ClangUtil::GetQualType(complex_float_clang_type)) + .getAsOpaquePtr()); } break; case DW_ATE_float: if (streq(type_name, "float") && QualTypeMatchesBitSize(bit_size, ast, ast->FloatTy)) - return CompilerType(ast, ast->FloatTy); + return CompilerType(this, ast->FloatTy.getAsOpaquePtr()); if (streq(type_name, "double") && QualTypeMatchesBitSize(bit_size, ast, ast->DoubleTy)) - return CompilerType(ast, ast->DoubleTy); + return CompilerType(this, ast->DoubleTy.getAsOpaquePtr()); if (streq(type_name, "long double") && QualTypeMatchesBitSize(bit_size, ast, ast->LongDoubleTy)) - return CompilerType(ast, ast->LongDoubleTy); + return CompilerType(this, ast->LongDoubleTy.getAsOpaquePtr()); // Fall back to not requiring a name match if (QualTypeMatchesBitSize(bit_size, ast, ast->FloatTy)) - return CompilerType(ast, ast->FloatTy); + return CompilerType(this, ast->FloatTy.getAsOpaquePtr()); if (QualTypeMatchesBitSize(bit_size, ast, ast->DoubleTy)) - return CompilerType(ast, ast->DoubleTy); + return CompilerType(this, ast->DoubleTy.getAsOpaquePtr()); if (QualTypeMatchesBitSize(bit_size, ast, ast->LongDoubleTy)) - return CompilerType(ast, ast->LongDoubleTy); + return CompilerType(this, ast->LongDoubleTy.getAsOpaquePtr()); if (QualTypeMatchesBitSize(bit_size, ast, ast->HalfTy)) - return CompilerType(ast, ast->HalfTy); + return CompilerType(this, ast->HalfTy.getAsOpaquePtr()); break; case DW_ATE_signed: @@ -1252,55 +1108,55 @@ CompilerType ClangASTContext::GetBuiltinTypeForDWARFEncodingAndBitSize( QualTypeMatchesBitSize(bit_size, ast, ast->WCharTy) && (getTargetInfo() && TargetInfo::isTypeSigned(getTargetInfo()->getWCharType()))) - return CompilerType(ast, ast->WCharTy); + return CompilerType(this, ast->WCharTy.getAsOpaquePtr()); if (streq(type_name, "void") && QualTypeMatchesBitSize(bit_size, ast, ast->VoidTy)) - return CompilerType(ast, ast->VoidTy); + return CompilerType(this, ast->VoidTy.getAsOpaquePtr()); if (strstr(type_name, "long long") && QualTypeMatchesBitSize(bit_size, ast, ast->LongLongTy)) - return CompilerType(ast, ast->LongLongTy); + return CompilerType(this, ast->LongLongTy.getAsOpaquePtr()); if (strstr(type_name, "long") && QualTypeMatchesBitSize(bit_size, ast, ast->LongTy)) - return CompilerType(ast, ast->LongTy); + return CompilerType(this, ast->LongTy.getAsOpaquePtr()); if (strstr(type_name, "short") && QualTypeMatchesBitSize(bit_size, ast, ast->ShortTy)) - return CompilerType(ast, ast->ShortTy); + return CompilerType(this, ast->ShortTy.getAsOpaquePtr()); if (strstr(type_name, "char")) { if (QualTypeMatchesBitSize(bit_size, ast, ast->CharTy)) - return CompilerType(ast, ast->CharTy); + return CompilerType(this, ast->CharTy.getAsOpaquePtr()); if (QualTypeMatchesBitSize(bit_size, ast, ast->SignedCharTy)) - return CompilerType(ast, ast->SignedCharTy); + return CompilerType(this, ast->SignedCharTy.getAsOpaquePtr()); } if (strstr(type_name, "int")) { if (QualTypeMatchesBitSize(bit_size, ast, ast->IntTy)) - return CompilerType(ast, ast->IntTy); + return CompilerType(this, ast->IntTy.getAsOpaquePtr()); if (QualTypeMatchesBitSize(bit_size, ast, ast->Int128Ty)) - return CompilerType(ast, ast->Int128Ty); + return CompilerType(this, ast->Int128Ty.getAsOpaquePtr()); } } // We weren't able to match up a type name, just search by size if (QualTypeMatchesBitSize(bit_size, ast, ast->CharTy)) - return CompilerType(ast, ast->CharTy); + return CompilerType(this, ast->CharTy.getAsOpaquePtr()); if (QualTypeMatchesBitSize(bit_size, ast, ast->ShortTy)) - return CompilerType(ast, ast->ShortTy); + return CompilerType(this, ast->ShortTy.getAsOpaquePtr()); if (QualTypeMatchesBitSize(bit_size, ast, ast->IntTy)) - return CompilerType(ast, ast->IntTy); + return CompilerType(this, ast->IntTy.getAsOpaquePtr()); if (QualTypeMatchesBitSize(bit_size, ast, ast->LongTy)) - return CompilerType(ast, ast->LongTy); + return CompilerType(this, ast->LongTy.getAsOpaquePtr()); if (QualTypeMatchesBitSize(bit_size, ast, ast->LongLongTy)) - return CompilerType(ast, ast->LongLongTy); + return CompilerType(this, ast->LongLongTy.getAsOpaquePtr()); if (QualTypeMatchesBitSize(bit_size, ast, ast->Int128Ty)) - return CompilerType(ast, ast->Int128Ty); + return CompilerType(this, ast->Int128Ty.getAsOpaquePtr()); break; case DW_ATE_signed_char: if (ast->getLangOpts().CharIsSigned && type_name && streq(type_name, "char")) { if (QualTypeMatchesBitSize(bit_size, ast, ast->CharTy)) - return CompilerType(ast, ast->CharTy); + return CompilerType(this, ast->CharTy.getAsOpaquePtr()); } if (QualTypeMatchesBitSize(bit_size, ast, ast->SignedCharTy)) - return CompilerType(ast, ast->SignedCharTy); + return CompilerType(this, ast->SignedCharTy.getAsOpaquePtr()); break; case DW_ATE_unsigned: @@ -1309,53 +1165,53 @@ CompilerType ClangASTContext::GetBuiltinTypeForDWARFEncodingAndBitSize( if (QualTypeMatchesBitSize(bit_size, ast, ast->WCharTy)) { if (!(getTargetInfo() && TargetInfo::isTypeSigned(getTargetInfo()->getWCharType()))) - return CompilerType(ast, ast->WCharTy); + return CompilerType(this, ast->WCharTy.getAsOpaquePtr()); } } if (strstr(type_name, "long long")) { if (QualTypeMatchesBitSize(bit_size, ast, ast->UnsignedLongLongTy)) - return CompilerType(ast, ast->UnsignedLongLongTy); + return CompilerType(this, ast->UnsignedLongLongTy.getAsOpaquePtr()); } else if (strstr(type_name, "long")) { if (QualTypeMatchesBitSize(bit_size, ast, ast->UnsignedLongTy)) - return CompilerType(ast, ast->UnsignedLongTy); + return CompilerType(this, ast->UnsignedLongTy.getAsOpaquePtr()); } else if (strstr(type_name, "short")) { if (QualTypeMatchesBitSize(bit_size, ast, ast->UnsignedShortTy)) - return CompilerType(ast, ast->UnsignedShortTy); + return CompilerType(this, ast->UnsignedShortTy.getAsOpaquePtr()); } else if (strstr(type_name, "char")) { if (QualTypeMatchesBitSize(bit_size, ast, ast->UnsignedCharTy)) - return CompilerType(ast, ast->UnsignedCharTy); + return CompilerType(this, ast->UnsignedCharTy.getAsOpaquePtr()); } else if (strstr(type_name, "int")) { if (QualTypeMatchesBitSize(bit_size, ast, ast->UnsignedIntTy)) - return CompilerType(ast, ast->UnsignedIntTy); + return CompilerType(this, ast->UnsignedIntTy.getAsOpaquePtr()); if (QualTypeMatchesBitSize(bit_size, ast, ast->UnsignedInt128Ty)) - return CompilerType(ast, ast->UnsignedInt128Ty); + return CompilerType(this, ast->UnsignedInt128Ty.getAsOpaquePtr()); } } // We weren't able to match up a type name, just search by size if (QualTypeMatchesBitSize(bit_size, ast, ast->UnsignedCharTy)) - return CompilerType(ast, ast->UnsignedCharTy); + return CompilerType(this, ast->UnsignedCharTy.getAsOpaquePtr()); if (QualTypeMatchesBitSize(bit_size, ast, ast->UnsignedShortTy)) - return CompilerType(ast, ast->UnsignedShortTy); + return CompilerType(this, ast->UnsignedShortTy.getAsOpaquePtr()); if (QualTypeMatchesBitSize(bit_size, ast, ast->UnsignedIntTy)) - return CompilerType(ast, ast->UnsignedIntTy); + return CompilerType(this, ast->UnsignedIntTy.getAsOpaquePtr()); if (QualTypeMatchesBitSize(bit_size, ast, ast->UnsignedLongTy)) - return CompilerType(ast, ast->UnsignedLongTy); + return CompilerType(this, ast->UnsignedLongTy.getAsOpaquePtr()); if (QualTypeMatchesBitSize(bit_size, ast, ast->UnsignedLongLongTy)) - return CompilerType(ast, ast->UnsignedLongLongTy); + return CompilerType(this, ast->UnsignedLongLongTy.getAsOpaquePtr()); if (QualTypeMatchesBitSize(bit_size, ast, ast->UnsignedInt128Ty)) - return CompilerType(ast, ast->UnsignedInt128Ty); + return CompilerType(this, ast->UnsignedInt128Ty.getAsOpaquePtr()); break; case DW_ATE_unsigned_char: if (!ast->getLangOpts().CharIsSigned && type_name && streq(type_name, "char")) { if (QualTypeMatchesBitSize(bit_size, ast, ast->CharTy)) - return CompilerType(ast, ast->CharTy); + return CompilerType(this, ast->CharTy.getAsOpaquePtr()); } if (QualTypeMatchesBitSize(bit_size, ast, ast->UnsignedCharTy)) - return CompilerType(ast, ast->UnsignedCharTy); + return CompilerType(this, ast->UnsignedCharTy.getAsOpaquePtr()); if (QualTypeMatchesBitSize(bit_size, ast, ast->UnsignedShortTy)) - return CompilerType(ast, ast->UnsignedShortTy); + return CompilerType(this, ast->UnsignedShortTy.getAsOpaquePtr()); break; case DW_ATE_imaginary_float: @@ -1363,11 +1219,12 @@ CompilerType ClangASTContext::GetBuiltinTypeForDWARFEncodingAndBitSize( case DW_ATE_UTF: if (type_name) { - if (streq(type_name, "char16_t")) { - return CompilerType(ast, ast->Char16Ty); - } else if (streq(type_name, "char32_t")) { - return CompilerType(ast, ast->Char32Ty); - } + if (streq(type_name, "char16_t")) + return CompilerType(this, ast->Char16Ty.getAsOpaquePtr()); + if (streq(type_name, "char32_t")) + return CompilerType(this, ast->Char32Ty.getAsOpaquePtr()); + if (streq(type_name, "char8_t")) + return CompilerType(this, ast->Char8Ty.getAsOpaquePtr()); } break; } @@ -1390,7 +1247,8 @@ CompilerType ClangASTContext::GetBuiltinTypeForDWARFEncodingAndBitSize( CompilerType ClangASTContext::GetUnknownAnyType(clang::ASTContext *ast) { if (ast) - return CompilerType(ast, ast->UnknownAnyTy); + return CompilerType(ClangASTContext::GetASTContext(ast), + ast->UnknownAnyTy.getAsOpaquePtr()); return CompilerType(); } @@ -1401,7 +1259,7 @@ CompilerType ClangASTContext::GetCStringType(bool is_const) { if (is_const) char_type.addConst(); - return CompilerType(ast, ast->getPointerType(char_type)); + return CompilerType(this, ast->getPointerType(char_type).getAsOpaquePtr()); } clang::DeclContext * @@ -1446,6 +1304,16 @@ bool ClangASTContext::AreTypesSame(CompilerType type1, CompilerType type2, return ast->getASTContext()->hasSameType(type1_qual, type2_qual); } +CompilerType ClangASTContext::GetTypeForDecl(void *opaque_decl) { + if (!opaque_decl) + return CompilerType(); + + clang::Decl *decl = static_cast<clang::Decl *>(opaque_decl); + if (auto *named_decl = llvm::dyn_cast<clang::NamedDecl>(decl)) + return GetTypeForDecl(named_decl); + return CompilerType(); +} + CompilerType ClangASTContext::GetTypeForDecl(clang::NamedDecl *decl) { if (clang::ObjCInterfaceDecl *interface_decl = llvm::dyn_cast<clang::ObjCInterfaceDecl>(decl)) @@ -1461,7 +1329,8 @@ CompilerType ClangASTContext::GetTypeForDecl(TagDecl *decl) { // AST if our AST didn't already exist... ASTContext *ast = &decl->getASTContext(); if (ast) - return CompilerType(ast, ast->getTagDeclType(decl)); + return CompilerType(ClangASTContext::GetASTContext(ast), + ast->getTagDeclType(decl).getAsOpaquePtr()); return CompilerType(); } @@ -1471,7 +1340,8 @@ CompilerType ClangASTContext::GetTypeForDecl(ObjCInterfaceDecl *decl) { // AST if our AST didn't already exist... ASTContext *ast = &decl->getASTContext(); if (ast) - return CompilerType(ast, ast->getObjCInterfaceType(decl)); + return CompilerType(ClangASTContext::GetASTContext(ast), + ast->getObjCInterfaceType(decl).getAsOpaquePtr()); return CompilerType(); } @@ -1501,14 +1371,43 @@ CompilerType ClangASTContext::CreateRecordType(DeclContext *decl_ctx, // something is struct or a class, so we default to always use the more // complete definition just in case. - bool is_anonymous = (!name) || (!name[0]); + bool has_name = name && name[0]; CXXRecordDecl *decl = CXXRecordDecl::Create( *ast, (TagDecl::TagKind)kind, decl_ctx, SourceLocation(), - SourceLocation(), is_anonymous ? nullptr : &ast->Idents.get(name)); + SourceLocation(), has_name ? &ast->Idents.get(name) : nullptr); - if (is_anonymous) - decl->setAnonymousStructOrUnion(true); + if (!has_name) { + // In C++ a lambda is also represented as an unnamed class. This is + // different from an *anonymous class* that the user wrote: + // + // struct A { + // // anonymous class (GNU/MSVC extension) + // struct { + // int x; + // }; + // // unnamed class within a class + // struct { + // int y; + // } B; + // }; + // + // void f() { + // // unammed class outside of a class + // struct { + // int z; + // } C; + // } + // + // Anonymous classes is a GNU/MSVC extension that clang supports. It + // requires the anonymous class be embedded within a class. So the new + // heuristic verifies this condition. + // + // FIXME: An unnamed class within a class is also wrongly recognized as an + // anonymous struct. + if (isa<CXXRecordDecl>(decl_ctx)) + decl->setAnonymousStructOrUnion(true); + } if (decl) { if (metadata) @@ -1520,7 +1419,7 @@ CompilerType ClangASTContext::CreateRecordType(DeclContext *decl_ctx, if (decl_ctx) decl_ctx->addDecl(decl); - return CompilerType(ast, ast->getTagDeclType(decl)); + return CompilerType(this, ast->getTagDeclType(decl).getAsOpaquePtr()); } return CompilerType(); } @@ -1743,7 +1642,8 @@ CompilerType ClangASTContext::CreateClassTemplateSpecializationType( ASTContext *ast = getASTContext(); if (ast) return CompilerType( - ast, ast->getTagDeclType(class_template_specialization_decl)); + this, ast->getTagDeclType(class_template_specialization_decl) + .getAsOpaquePtr()); } return CompilerType(); } @@ -1874,7 +1774,7 @@ CompilerType ClangASTContext::CreateObjCClass(const char *name, if (decl && metadata) SetMetadata(ast, decl, *metadata); - return CompilerType(ast, ast->getObjCInterfaceType(decl)); + return CompilerType(this, ast->getObjCInterfaceType(decl).getAsOpaquePtr()); } static inline bool BaseSpecifierIsEmpty(const CXXBaseSpecifier *b) { @@ -2220,14 +2120,14 @@ CompilerType ClangASTContext::CreateFunctionType( proto_info.TypeQuals = clang::Qualifiers::fromFastMask(type_quals); proto_info.RefQualifier = RQ_None; - return CompilerType(ast, + return CompilerType(ClangASTContext::GetASTContext(ast), ast->getFunctionType(ClangUtil::GetQualType(result_type), - qual_type_args, proto_info)); + qual_type_args, proto_info).getAsOpaquePtr()); } ParmVarDecl *ClangASTContext::CreateParameterDeclaration( clang::DeclContext *decl_ctx, const char *name, - const CompilerType ¶m_type, int storage) { + const CompilerType ¶m_type, int storage, bool add_decl) { ASTContext *ast = getASTContext(); assert(ast != nullptr); auto *decl = @@ -2235,7 +2135,9 @@ ParmVarDecl *ClangASTContext::CreateParameterDeclaration( name && name[0] ? &ast->Idents.get(name) : nullptr, ClangUtil::GetQualType(param_type), nullptr, (clang::StorageClass)storage, nullptr); - decl_ctx->addDecl(decl); + if (add_decl) + decl_ctx->addDecl(decl); + return decl; } @@ -2265,20 +2167,23 @@ CompilerType ClangASTContext::CreateArrayType(const CompilerType &element_type, if (is_vector) { return CompilerType( - ast, ast->getExtVectorType(ClangUtil::GetQualType(element_type), - element_count)); + this, ast->getExtVectorType(ClangUtil::GetQualType(element_type), + element_count) + .getAsOpaquePtr()); } else { llvm::APInt ap_element_count(64, element_count); if (element_count == 0) { - return CompilerType(ast, ast->getIncompleteArrayType( - ClangUtil::GetQualType(element_type), - clang::ArrayType::Normal, 0)); + return CompilerType(this, ast->getIncompleteArrayType( + ClangUtil::GetQualType(element_type), + clang::ArrayType::Normal, 0) + .getAsOpaquePtr()); } else { - return CompilerType( - ast, ast->getConstantArrayType(ClangUtil::GetQualType(element_type), - ap_element_count, - clang::ArrayType::Normal, 0)); + return CompilerType(this, ast->getConstantArrayType( + ClangUtil::GetQualType(element_type), + ap_element_count, nullptr, + clang::ArrayType::Normal, 0) + .getAsOpaquePtr()); } } } @@ -2352,7 +2257,7 @@ ClangASTContext::CreateEnumerationType(const char *name, DeclContext *decl_ctx, enum_decl->setAccess(AS_public); // TODO respect what's in the debug info - return CompilerType(ast, ast->getTagDeclType(enum_decl)); + return CompilerType(this, ast->getTagDeclType(enum_decl).getAsOpaquePtr()); } return CompilerType(); } @@ -2361,42 +2266,51 @@ CompilerType ClangASTContext::GetIntTypeFromBitSize(clang::ASTContext *ast, size_t bit_size, bool is_signed) { if (ast) { + auto *clang_ast_context = ClangASTContext::GetASTContext(ast); if (is_signed) { if (bit_size == ast->getTypeSize(ast->SignedCharTy)) - return CompilerType(ast, ast->SignedCharTy); + return CompilerType(clang_ast_context, + ast->SignedCharTy.getAsOpaquePtr()); if (bit_size == ast->getTypeSize(ast->ShortTy)) - return CompilerType(ast, ast->ShortTy); + return CompilerType(clang_ast_context, ast->ShortTy.getAsOpaquePtr()); if (bit_size == ast->getTypeSize(ast->IntTy)) - return CompilerType(ast, ast->IntTy); + return CompilerType(clang_ast_context, ast->IntTy.getAsOpaquePtr()); if (bit_size == ast->getTypeSize(ast->LongTy)) - return CompilerType(ast, ast->LongTy); + return CompilerType(clang_ast_context, ast->LongTy.getAsOpaquePtr()); if (bit_size == ast->getTypeSize(ast->LongLongTy)) - return CompilerType(ast, ast->LongLongTy); + return CompilerType(clang_ast_context, + ast->LongLongTy.getAsOpaquePtr()); if (bit_size == ast->getTypeSize(ast->Int128Ty)) - return CompilerType(ast, ast->Int128Ty); + return CompilerType(clang_ast_context, ast->Int128Ty.getAsOpaquePtr()); } else { if (bit_size == ast->getTypeSize(ast->UnsignedCharTy)) - return CompilerType(ast, ast->UnsignedCharTy); + return CompilerType(clang_ast_context, + ast->UnsignedCharTy.getAsOpaquePtr()); if (bit_size == ast->getTypeSize(ast->UnsignedShortTy)) - return CompilerType(ast, ast->UnsignedShortTy); + return CompilerType(clang_ast_context, + ast->UnsignedShortTy.getAsOpaquePtr()); if (bit_size == ast->getTypeSize(ast->UnsignedIntTy)) - return CompilerType(ast, ast->UnsignedIntTy); + return CompilerType(clang_ast_context, + ast->UnsignedIntTy.getAsOpaquePtr()); if (bit_size == ast->getTypeSize(ast->UnsignedLongTy)) - return CompilerType(ast, ast->UnsignedLongTy); + return CompilerType(clang_ast_context, + ast->UnsignedLongTy.getAsOpaquePtr()); if (bit_size == ast->getTypeSize(ast->UnsignedLongLongTy)) - return CompilerType(ast, ast->UnsignedLongLongTy); + return CompilerType(clang_ast_context, + ast->UnsignedLongLongTy.getAsOpaquePtr()); if (bit_size == ast->getTypeSize(ast->UnsignedInt128Ty)) - return CompilerType(ast, ast->UnsignedInt128Ty); + return CompilerType(clang_ast_context, + ast->UnsignedInt128Ty.getAsOpaquePtr()); } } return CompilerType(); @@ -2926,8 +2840,9 @@ bool ClangASTContext::IsArrayType(lldb::opaque_compiler_type_t type, case clang::Type::ConstantArray: if (element_type_ptr) element_type_ptr->SetCompilerType( - getASTContext(), - llvm::cast<clang::ConstantArrayType>(qual_type)->getElementType()); + this, llvm::cast<clang::ConstantArrayType>(qual_type) + ->getElementType() + .getAsOpaquePtr()); if (size) *size = llvm::cast<clang::ConstantArrayType>(qual_type) ->getSize() @@ -2939,8 +2854,9 @@ bool ClangASTContext::IsArrayType(lldb::opaque_compiler_type_t type, case clang::Type::IncompleteArray: if (element_type_ptr) element_type_ptr->SetCompilerType( - getASTContext(), - llvm::cast<clang::IncompleteArrayType>(qual_type)->getElementType()); + this, llvm::cast<clang::IncompleteArrayType>(qual_type) + ->getElementType() + .getAsOpaquePtr()); if (size) *size = 0; if (is_incomplete) @@ -2950,8 +2866,9 @@ bool ClangASTContext::IsArrayType(lldb::opaque_compiler_type_t type, case clang::Type::VariableArray: if (element_type_ptr) element_type_ptr->SetCompilerType( - getASTContext(), - llvm::cast<clang::VariableArrayType>(qual_type)->getElementType()); + this, llvm::cast<clang::VariableArrayType>(qual_type) + ->getElementType() + .getAsOpaquePtr()); if (size) *size = 0; if (is_incomplete) @@ -2961,8 +2878,9 @@ bool ClangASTContext::IsArrayType(lldb::opaque_compiler_type_t type, case clang::Type::DependentSizedArray: if (element_type_ptr) element_type_ptr->SetCompilerType( - getASTContext(), llvm::cast<clang::DependentSizedArrayType>(qual_type) - ->getElementType()); + this, llvm::cast<clang::DependentSizedArrayType>(qual_type) + ->getElementType() + .getAsOpaquePtr()); if (size) *size = 0; if (is_incomplete) @@ -3013,7 +2931,7 @@ bool ClangASTContext::IsVectorType(lldb::opaque_compiler_type_t type, *size = vector_type->getNumElements(); if (element_type) *element_type = - CompilerType(getASTContext(), vector_type->getElementType()); + CompilerType(this, vector_type->getElementType().getAsOpaquePtr()); } return true; } break; @@ -3025,7 +2943,7 @@ bool ClangASTContext::IsVectorType(lldb::opaque_compiler_type_t type, *size = ext_vector_type->getNumElements(); if (element_type) *element_type = - CompilerType(getASTContext(), ext_vector_type->getElementType()); + CompilerType(this, ext_vector_type->getElementType().getAsOpaquePtr()); } return true; } @@ -3218,7 +3136,7 @@ ClangASTContext::IsHomogeneousAggregate(lldb::opaque_compiler_type_t type, ++num_fields; } if (base_type_ptr) - *base_type_ptr = CompilerType(getASTContext(), base_qual_type); + *base_type_ptr = CompilerType(this, base_qual_type.getAsOpaquePtr()); return num_fields; } } @@ -3270,7 +3188,7 @@ ClangASTContext::GetFunctionArgumentAtIndex(lldb::opaque_compiler_type_t type, llvm::dyn_cast<clang::FunctionProtoType>(qual_type.getTypePtr()); if (func) { if (index < func->getNumParams()) - return CompilerType(getASTContext(), func->getParamType(index)); + return CompilerType(this, func->getParamType(index).getAsOpaquePtr()); } } return CompilerType(); @@ -3330,7 +3248,7 @@ bool ClangASTContext::IsBlockPointerType( QualType pointee_type = block_pointer_type->getPointeeType(); QualType function_pointer_type = m_ast_up->getPointerType(pointee_type); *function_pointer_type_ptr = - CompilerType(getASTContext(), function_pointer_type); + CompilerType(this, function_pointer_type.getAsOpaquePtr()); } return true; } @@ -3427,26 +3345,30 @@ bool ClangASTContext::IsPointerType(lldb::opaque_compiler_type_t type, case clang::Type::ObjCObjectPointer: if (pointee_type) pointee_type->SetCompilerType( - getASTContext(), llvm::cast<clang::ObjCObjectPointerType>(qual_type) - ->getPointeeType()); + this, llvm::cast<clang::ObjCObjectPointerType>(qual_type) + ->getPointeeType() + .getAsOpaquePtr()); return true; case clang::Type::BlockPointer: if (pointee_type) pointee_type->SetCompilerType( - getASTContext(), - llvm::cast<clang::BlockPointerType>(qual_type)->getPointeeType()); + this, llvm::cast<clang::BlockPointerType>(qual_type) + ->getPointeeType() + .getAsOpaquePtr()); return true; case clang::Type::Pointer: if (pointee_type) - pointee_type->SetCompilerType( - getASTContext(), - llvm::cast<clang::PointerType>(qual_type)->getPointeeType()); + pointee_type->SetCompilerType(this, + llvm::cast<clang::PointerType>(qual_type) + ->getPointeeType() + .getAsOpaquePtr()); return true; case clang::Type::MemberPointer: if (pointee_type) pointee_type->SetCompilerType( - getASTContext(), - llvm::cast<clang::MemberPointerType>(qual_type)->getPointeeType()); + this, llvm::cast<clang::MemberPointerType>(qual_type) + ->getPointeeType() + .getAsOpaquePtr()); return true; case clang::Type::Typedef: return IsPointerType(llvm::cast<clang::TypedefType>(qual_type) @@ -3495,38 +3417,43 @@ bool ClangASTContext::IsPointerOrReferenceType( case clang::Type::ObjCObjectPointer: if (pointee_type) pointee_type->SetCompilerType( - getASTContext(), llvm::cast<clang::ObjCObjectPointerType>(qual_type) - ->getPointeeType()); + this, llvm::cast<clang::ObjCObjectPointerType>(qual_type) + ->getPointeeType().getAsOpaquePtr()); return true; case clang::Type::BlockPointer: if (pointee_type) pointee_type->SetCompilerType( - getASTContext(), - llvm::cast<clang::BlockPointerType>(qual_type)->getPointeeType()); + this, llvm::cast<clang::BlockPointerType>(qual_type) + ->getPointeeType() + .getAsOpaquePtr()); return true; case clang::Type::Pointer: if (pointee_type) - pointee_type->SetCompilerType( - getASTContext(), - llvm::cast<clang::PointerType>(qual_type)->getPointeeType()); + pointee_type->SetCompilerType(this, + llvm::cast<clang::PointerType>(qual_type) + ->getPointeeType() + .getAsOpaquePtr()); return true; case clang::Type::MemberPointer: if (pointee_type) pointee_type->SetCompilerType( - getASTContext(), - llvm::cast<clang::MemberPointerType>(qual_type)->getPointeeType()); + this, llvm::cast<clang::MemberPointerType>(qual_type) + ->getPointeeType() + .getAsOpaquePtr()); return true; case clang::Type::LValueReference: if (pointee_type) pointee_type->SetCompilerType( - getASTContext(), - llvm::cast<clang::LValueReferenceType>(qual_type)->desugar()); + this, llvm::cast<clang::LValueReferenceType>(qual_type) + ->desugar() + .getAsOpaquePtr()); return true; case clang::Type::RValueReference: if (pointee_type) pointee_type->SetCompilerType( - getASTContext(), - llvm::cast<clang::RValueReferenceType>(qual_type)->desugar()); + this, llvm::cast<clang::RValueReferenceType>(qual_type) + ->desugar() + .getAsOpaquePtr()); return true; case clang::Type::Typedef: return IsPointerOrReferenceType(llvm::cast<clang::TypedefType>(qual_type) @@ -3569,16 +3496,18 @@ bool ClangASTContext::IsReferenceType(lldb::opaque_compiler_type_t type, case clang::Type::LValueReference: if (pointee_type) pointee_type->SetCompilerType( - getASTContext(), - llvm::cast<clang::LValueReferenceType>(qual_type)->desugar()); + this, llvm::cast<clang::LValueReferenceType>(qual_type) + ->desugar() + .getAsOpaquePtr()); if (is_rvalue) *is_rvalue = false; return true; case clang::Type::RValueReference: if (pointee_type) pointee_type->SetCompilerType( - getASTContext(), - llvm::cast<clang::RValueReferenceType>(qual_type)->desugar()); + this, llvm::cast<clang::RValueReferenceType>(qual_type) + ->desugar() + .getAsOpaquePtr()); if (is_rvalue) *is_rvalue = true; return true; @@ -3770,9 +3699,9 @@ bool ClangASTContext::IsPossibleDynamicType(lldb::opaque_compiler_type_t type, } if (dynamic_pointee_type) dynamic_pointee_type->SetCompilerType( - getASTContext(), - llvm::cast<clang::ObjCObjectPointerType>(qual_type) - ->getPointeeType()); + this, llvm::cast<clang::ObjCObjectPointerType>(qual_type) + ->getPointeeType() + .getAsOpaquePtr()); return true; } break; @@ -3832,8 +3761,8 @@ bool ClangASTContext::IsPossibleDynamicType(lldb::opaque_compiler_type_t type, case clang::BuiltinType::UnknownAny: case clang::BuiltinType::Void: if (dynamic_pointee_type) - dynamic_pointee_type->SetCompilerType(getASTContext(), - pointee_qual_type); + dynamic_pointee_type->SetCompilerType( + this, pointee_qual_type.getAsOpaquePtr()); return true; default: break; @@ -3855,8 +3784,9 @@ bool ClangASTContext::IsPossibleDynamicType(lldb::opaque_compiler_type_t type, if (metadata) success = metadata->GetIsDynamicCXXType(); else { - is_complete = CompilerType(getASTContext(), pointee_qual_type) - .GetCompleteType(); + is_complete = + CompilerType(this, pointee_qual_type.getAsOpaquePtr()) + .GetCompleteType(); if (is_complete) success = cxx_record_decl->isDynamicClass(); else @@ -3866,8 +3796,8 @@ bool ClangASTContext::IsPossibleDynamicType(lldb::opaque_compiler_type_t type, if (success) { if (dynamic_pointee_type) - dynamic_pointee_type->SetCompilerType(getASTContext(), - pointee_qual_type); + dynamic_pointee_type->SetCompilerType( + this, pointee_qual_type.getAsOpaquePtr()); return true; } } @@ -3878,8 +3808,8 @@ bool ClangASTContext::IsPossibleDynamicType(lldb::opaque_compiler_type_t type, case clang::Type::ObjCInterface: if (check_objc) { if (dynamic_pointee_type) - dynamic_pointee_type->SetCompilerType(getASTContext(), - pointee_qual_type); + dynamic_pointee_type->SetCompilerType( + this, pointee_qual_type.getAsOpaquePtr()); return true; } break; @@ -3987,25 +3917,6 @@ bool ClangASTContext::IsObjCObjectPointerType(const CompilerType &type, return false; } -bool ClangASTContext::GetObjCClassName(const CompilerType &type, - std::string &class_name) { - if (!type) - return false; - - clang::QualType qual_type(ClangUtil::GetCanonicalQualType(type)); - - const clang::ObjCObjectType *object_type = - llvm::dyn_cast<clang::ObjCObjectType>(qual_type); - if (object_type) { - const clang::ObjCInterfaceDecl *interface = object_type->getInterface(); - if (interface) { - class_name = interface->getNameAsString(); - return true; - } - } - return false; -} - // Type Completion bool ClangASTContext::GetCompleteType(lldb::opaque_compiler_type_t type) { @@ -4062,14 +3973,14 @@ ClangASTContext::GetTypeInfo(lldb::opaque_compiler_type_t type, case clang::BuiltinType::ObjCClass: if (pointee_or_element_clang_type) pointee_or_element_clang_type->SetCompilerType( - getASTContext(), getASTContext()->ObjCBuiltinClassTy); + this, getASTContext()->ObjCBuiltinClassTy.getAsOpaquePtr()); builtin_type_flags |= eTypeIsPointer | eTypeIsObjC; break; case clang::BuiltinType::ObjCSel: if (pointee_or_element_clang_type) - pointee_or_element_clang_type->SetCompilerType(getASTContext(), - getASTContext()->CharTy); + pointee_or_element_clang_type->SetCompilerType( + this, getASTContext()->CharTy.getAsOpaquePtr()); builtin_type_flags |= eTypeIsPointer | eTypeIsObjC; break; @@ -4112,7 +4023,7 @@ ClangASTContext::GetTypeInfo(lldb::opaque_compiler_type_t type, case clang::Type::BlockPointer: if (pointee_or_element_clang_type) pointee_or_element_clang_type->SetCompilerType( - getASTContext(), qual_type->getPointeeType()); + this, qual_type->getPointeeType().getAsOpaquePtr()); return eTypeIsPointer | eTypeHasChildren | eTypeIsBlock; case clang::Type::Complex: { @@ -4136,8 +4047,9 @@ ClangASTContext::GetTypeInfo(lldb::opaque_compiler_type_t type, case clang::Type::VariableArray: if (pointee_or_element_clang_type) pointee_or_element_clang_type->SetCompilerType( - getASTContext(), llvm::cast<clang::ArrayType>(qual_type.getTypePtr()) - ->getElementType()); + this, llvm::cast<clang::ArrayType>(qual_type.getTypePtr()) + ->getElementType() + .getAsOpaquePtr()); return eTypeHasChildren | eTypeIsArray; case clang::Type::DependentName: @@ -4147,31 +4059,34 @@ ClangASTContext::GetTypeInfo(lldb::opaque_compiler_type_t type, case clang::Type::DependentTemplateSpecialization: return eTypeIsTemplate; case clang::Type::Decltype: - return CompilerType( - getASTContext(), - llvm::cast<clang::DecltypeType>(qual_type)->getUnderlyingType()) + return CompilerType(this, llvm::cast<clang::DecltypeType>(qual_type) + ->getUnderlyingType() + .getAsOpaquePtr()) .GetTypeInfo(pointee_or_element_clang_type); case clang::Type::Enum: if (pointee_or_element_clang_type) pointee_or_element_clang_type->SetCompilerType( - getASTContext(), - llvm::cast<clang::EnumType>(qual_type)->getDecl()->getIntegerType()); + this, llvm::cast<clang::EnumType>(qual_type) + ->getDecl() + ->getIntegerType() + .getAsOpaquePtr()); return eTypeIsEnumeration | eTypeHasValue; case clang::Type::Auto: - return CompilerType( - getASTContext(), - llvm::cast<clang::AutoType>(qual_type)->getDeducedType()) + return CompilerType(this, llvm::cast<clang::AutoType>(qual_type) + ->getDeducedType() + .getAsOpaquePtr()) .GetTypeInfo(pointee_or_element_clang_type); case clang::Type::Elaborated: - return CompilerType( - getASTContext(), - llvm::cast<clang::ElaboratedType>(qual_type)->getNamedType()) + return CompilerType(this, llvm::cast<clang::ElaboratedType>(qual_type) + ->getNamedType() + .getAsOpaquePtr()) .GetTypeInfo(pointee_or_element_clang_type); case clang::Type::Paren: - return CompilerType(getASTContext(), - llvm::cast<clang::ParenType>(qual_type)->desugar()) + return CompilerType(this, llvm::cast<clang::ParenType>(qual_type) + ->desugar() + .getAsOpaquePtr()) .GetTypeInfo(pointee_or_element_clang_type); case clang::Type::FunctionProto: @@ -4185,9 +4100,9 @@ ClangASTContext::GetTypeInfo(lldb::opaque_compiler_type_t type, case clang::Type::RValueReference: if (pointee_or_element_clang_type) pointee_or_element_clang_type->SetCompilerType( - getASTContext(), - llvm::cast<clang::ReferenceType>(qual_type.getTypePtr()) - ->getPointeeType()); + this, llvm::cast<clang::ReferenceType>(qual_type.getTypePtr()) + ->getPointeeType() + .getAsOpaquePtr()); return eTypeHasChildren | eTypeIsReference | eTypeHasValue; case clang::Type::MemberPointer: @@ -4196,7 +4111,7 @@ ClangASTContext::GetTypeInfo(lldb::opaque_compiler_type_t type, case clang::Type::ObjCObjectPointer: if (pointee_or_element_clang_type) pointee_or_element_clang_type->SetCompilerType( - getASTContext(), qual_type->getPointeeType()); + this, qual_type->getPointeeType().getAsOpaquePtr()); return eTypeHasChildren | eTypeIsObjC | eTypeIsClass | eTypeIsPointer | eTypeHasValue; @@ -4208,7 +4123,7 @@ ClangASTContext::GetTypeInfo(lldb::opaque_compiler_type_t type, case clang::Type::Pointer: if (pointee_or_element_clang_type) pointee_or_element_clang_type->SetCompilerType( - getASTContext(), qual_type->getPointeeType()); + this, qual_type->getPointeeType().getAsOpaquePtr()); return eTypeHasChildren | eTypeIsPointer | eTypeHasValue; case clang::Type::Record: @@ -4226,21 +4141,21 @@ ClangASTContext::GetTypeInfo(lldb::opaque_compiler_type_t type, case clang::Type::Typedef: return eTypeIsTypedef | - CompilerType(getASTContext(), - llvm::cast<clang::TypedefType>(qual_type) - ->getDecl() - ->getUnderlyingType()) + CompilerType(this, llvm::cast<clang::TypedefType>(qual_type) + ->getDecl() + ->getUnderlyingType() + .getAsOpaquePtr()) .GetTypeInfo(pointee_or_element_clang_type); case clang::Type::TypeOfExpr: - return CompilerType(getASTContext(), - llvm::cast<clang::TypeOfExprType>(qual_type) - ->getUnderlyingExpr() - ->getType()) + return CompilerType(this, llvm::cast<clang::TypeOfExprType>(qual_type) + ->getUnderlyingExpr() + ->getType() + .getAsOpaquePtr()) .GetTypeInfo(pointee_or_element_clang_type); case clang::Type::TypeOf: - return CompilerType( - getASTContext(), - llvm::cast<clang::TypeOfType>(qual_type)->getUnderlyingType()) + return CompilerType(this, llvm::cast<clang::TypeOfType>(qual_type) + ->getUnderlyingType() + .getAsOpaquePtr()) .GetTypeInfo(pointee_or_element_clang_type); case clang::Type::UnresolvedUsing: return 0; @@ -4339,10 +4254,10 @@ ClangASTContext::GetMinimumLanguage(lldb::opaque_compiler_type_t type) { } break; case clang::Type::Typedef: - return CompilerType(getASTContext(), - llvm::cast<clang::TypedefType>(qual_type) - ->getDecl() - ->getUnderlyingType()) + return CompilerType(this, llvm::cast<clang::TypedefType>(qual_type) + ->getDecl() + ->getUnderlyingType() + .getAsOpaquePtr()) .GetMinimumLanguage(); } } @@ -4420,18 +4335,19 @@ ClangASTContext::GetTypeClass(lldb::opaque_compiler_type_t type) { case clang::Type::UnresolvedUsing: break; case clang::Type::Paren: - return CompilerType(getASTContext(), - llvm::cast<clang::ParenType>(qual_type)->desugar()) + return CompilerType(this, llvm::cast<clang::ParenType>(qual_type) + ->desugar() + .getAsOpaquePtr()) .GetTypeClass(); case clang::Type::Auto: - return CompilerType( - getASTContext(), - llvm::cast<clang::AutoType>(qual_type)->getDeducedType()) + return CompilerType(this, llvm::cast<clang::AutoType>(qual_type) + ->getDeducedType() + .getAsOpaquePtr()) .GetTypeClass(); case clang::Type::Elaborated: - return CompilerType( - getASTContext(), - llvm::cast<clang::ElaboratedType>(qual_type)->getNamedType()) + return CompilerType(this, llvm::cast<clang::ElaboratedType>(qual_type) + ->getNamedType() + .getAsOpaquePtr()) .GetTypeClass(); case clang::Type::Attributed: @@ -4452,20 +4368,20 @@ ClangASTContext::GetTypeClass(lldb::opaque_compiler_type_t type) { break; case clang::Type::TypeOfExpr: - return CompilerType(getASTContext(), - llvm::cast<clang::TypeOfExprType>(qual_type) - ->getUnderlyingExpr() - ->getType()) + return CompilerType(this, llvm::cast<clang::TypeOfExprType>(qual_type) + ->getUnderlyingExpr() + ->getType() + .getAsOpaquePtr()) .GetTypeClass(); case clang::Type::TypeOf: - return CompilerType( - getASTContext(), - llvm::cast<clang::TypeOfType>(qual_type)->getUnderlyingType()) + return CompilerType(this, llvm::cast<clang::TypeOfType>(qual_type) + ->getUnderlyingType() + .getAsOpaquePtr()) .GetTypeClass(); case clang::Type::Decltype: - return CompilerType( - getASTContext(), - llvm::cast<clang::TypeOfType>(qual_type)->getUnderlyingType()) + return CompilerType(this, llvm::cast<clang::TypeOfType>(qual_type) + ->getUnderlyingType() + .getAsOpaquePtr()) .GetTypeClass(); case clang::Type::TemplateSpecialization: break; @@ -4513,8 +4429,8 @@ ClangASTContext::GetArrayElementType(lldb::opaque_compiler_type_t type, if (!array_eletype) return CompilerType(); - CompilerType element_type(getASTContext(), - array_eletype->getCanonicalTypeUnqualified()); + CompilerType element_type( + this, array_eletype->getCanonicalTypeUnqualified().getAsOpaquePtr()); // TODO: the real stride will be >= this value.. find the real one! if (stride) @@ -4533,14 +4449,18 @@ CompilerType ClangASTContext::GetArrayType(lldb::opaque_compiler_type_t type, if (clang::ASTContext *ast_ctx = getASTContext()) { if (size != 0) return CompilerType( - ast_ctx, ast_ctx->getConstantArrayType( - qual_type, llvm::APInt(64, size), - clang::ArrayType::ArraySizeModifier::Normal, 0)); + this, ast_ctx + ->getConstantArrayType( + qual_type, llvm::APInt(64, size), nullptr, + clang::ArrayType::ArraySizeModifier::Normal, 0) + .getAsOpaquePtr()); else return CompilerType( - ast_ctx, - ast_ctx->getIncompleteArrayType( - qual_type, clang::ArrayType::ArraySizeModifier::Normal, 0)); + this, + ast_ctx + ->getIncompleteArrayType( + qual_type, clang::ArrayType::ArraySizeModifier::Normal, 0) + .getAsOpaquePtr()); } } @@ -4550,7 +4470,7 @@ CompilerType ClangASTContext::GetArrayType(lldb::opaque_compiler_type_t type, CompilerType ClangASTContext::GetCanonicalType(lldb::opaque_compiler_type_t type) { if (type) - return CompilerType(getASTContext(), GetCanonicalQualType(type)); + return CompilerType(this, GetCanonicalQualType(type).getAsOpaquePtr()); return CompilerType(); } @@ -4571,8 +4491,8 @@ CompilerType ClangASTContext::GetFullyUnqualifiedType(lldb::opaque_compiler_type_t type) { if (type) return CompilerType( - getASTContext(), - GetFullyUnqualifiedType_Impl(getASTContext(), GetQualType(type))); + this, + GetFullyUnqualifiedType_Impl(getASTContext(), GetQualType(type)).getAsOpaquePtr()); return CompilerType(); } @@ -4595,7 +4515,7 @@ CompilerType ClangASTContext::GetFunctionArgumentTypeAtIndex( if (func) { const uint32_t num_args = func->getNumParams(); if (idx < num_args) - return CompilerType(getASTContext(), func->getParamType(idx)); + return CompilerType(this, func->getParamType(idx).getAsOpaquePtr()); } } return CompilerType(); @@ -4608,7 +4528,7 @@ ClangASTContext::GetFunctionReturnType(lldb::opaque_compiler_type_t type) { const clang::FunctionProtoType *func = llvm::dyn_cast<clang::FunctionProtoType>(qual_type.getTypePtr()); if (func) - return CompilerType(getASTContext(), func->getReturnType()); + return CompilerType(this, func->getReturnType().getAsOpaquePtr()); } return CompilerType(); } @@ -4667,27 +4587,28 @@ ClangASTContext::GetNumMemberFunctions(lldb::opaque_compiler_type_t type) { break; case clang::Type::Typedef: - return CompilerType(getASTContext(), - llvm::cast<clang::TypedefType>(qual_type) - ->getDecl() - ->getUnderlyingType()) + return CompilerType(this, llvm::cast<clang::TypedefType>(qual_type) + ->getDecl() + ->getUnderlyingType() + .getAsOpaquePtr()) .GetNumMemberFunctions(); case clang::Type::Auto: - return CompilerType( - getASTContext(), - llvm::cast<clang::AutoType>(qual_type)->getDeducedType()) + return CompilerType(this, llvm::cast<clang::AutoType>(qual_type) + ->getDeducedType() + .getAsOpaquePtr()) .GetNumMemberFunctions(); case clang::Type::Elaborated: - return CompilerType( - getASTContext(), - llvm::cast<clang::ElaboratedType>(qual_type)->getNamedType()) + return CompilerType(this, llvm::cast<clang::ElaboratedType>(qual_type) + ->getNamedType() + .getAsOpaquePtr()) .GetNumMemberFunctions(); case clang::Type::Paren: - return CompilerType(getASTContext(), - llvm::cast<clang::ParenType>(qual_type)->desugar()) + return CompilerType(this, llvm::cast<clang::ParenType>(qual_type) + ->desugar() + .getAsOpaquePtr()) .GetNumMemberFunctions(); default: @@ -4843,8 +4764,8 @@ ClangASTContext::GetMemberFunctionAtIndex(lldb::opaque_compiler_type_t type, CompilerType ClangASTContext::GetNonReferenceType(lldb::opaque_compiler_type_t type) { if (type) - return CompilerType(getASTContext(), - GetQualType(type).getNonReferenceType()); + return CompilerType( + this, GetQualType(type).getNonReferenceType().getAsOpaquePtr()); return CompilerType(); } @@ -4874,7 +4795,7 @@ CompilerType ClangASTContext::CreateTypedefType( decl_ctx->addDecl(decl); // Get a uniqued clang::QualType for the typedef decl type - return CompilerType(clang_ast, clang_ast->getTypedefType(decl)); + return CompilerType(ast, clang_ast->getTypedefType(decl).getAsOpaquePtr()); } return CompilerType(); } @@ -4883,8 +4804,8 @@ CompilerType ClangASTContext::GetPointeeType(lldb::opaque_compiler_type_t type) { if (type) { clang::QualType qual_type(GetQualType(type)); - return CompilerType(getASTContext(), - qual_type.getTypePtr()->getPointeeType()); + return CompilerType( + this, qual_type.getTypePtr()->getPointeeType().getAsOpaquePtr()); } return CompilerType(); } @@ -4898,12 +4819,13 @@ ClangASTContext::GetPointerType(lldb::opaque_compiler_type_t type) { switch (type_class) { case clang::Type::ObjCObject: case clang::Type::ObjCInterface: - return CompilerType(getASTContext(), - getASTContext()->getObjCObjectPointerType(qual_type)); + return CompilerType(this, getASTContext() + ->getObjCObjectPointerType(qual_type) + .getAsOpaquePtr()); default: - return CompilerType(getASTContext(), - getASTContext()->getPointerType(qual_type)); + return CompilerType( + this, getASTContext()->getPointerType(qual_type).getAsOpaquePtr()); } } return CompilerType(); @@ -5005,8 +4927,8 @@ ClangASTContext::GetTypedefedType(lldb::opaque_compiler_type_t type) { const clang::TypedefType *typedef_type = llvm::dyn_cast<clang::TypedefType>(GetQualType(type)); if (typedef_type) - return CompilerType(getASTContext(), - typedef_type->getDecl()->getUnderlyingType()); + return CompilerType( + this, typedef_type->getDecl()->getUnderlyingType().getAsOpaquePtr()); } return CompilerType(); } @@ -5018,6 +4940,22 @@ CompilerType ClangASTContext::GetBasicTypeFromAST(lldb::BasicType basic_type) { } // Exploring the type +const llvm::fltSemantics & +ClangASTContext::GetFloatTypeSemantics(size_t byte_size) { + if (auto *ast = getASTContext()) { + const size_t bit_size = byte_size * 8; + if (bit_size == ast->getTypeSize(ast->FloatTy)) + return ast->getFloatTypeSemantics(ast->FloatTy); + else if (bit_size == ast->getTypeSize(ast->DoubleTy)) + return ast->getFloatTypeSemantics(ast->DoubleTy); + else if (bit_size == ast->getTypeSize(ast->LongDoubleTy)) + return ast->getFloatTypeSemantics(ast->LongDoubleTy); + else if (bit_size == ast->getTypeSize(ast->HalfTy)) + return ast->getFloatTypeSemantics(ast->HalfTy); + } + return llvm::APFloatBase::Bogus(); +} + Optional<uint64_t> ClangASTContext::GetBitSize(lldb::opaque_compiler_type_t type, ExecutionContextScope *exe_scope) { @@ -5041,7 +4979,7 @@ ClangASTContext::GetBitSize(lldb::opaque_compiler_type_t type, if (objc_runtime) { uint64_t bit_size = 0; if (objc_runtime->GetTypeBitSize( - CompilerType(getASTContext(), qual_type), bit_size)) + CompilerType(this, qual_type.getAsOpaquePtr()), bit_size)) return bit_size; } } else { @@ -5084,10 +5022,12 @@ ClangASTContext::GetBitSize(lldb::opaque_compiler_type_t type, return None; } -size_t ClangASTContext::GetTypeBitAlign(lldb::opaque_compiler_type_t type) { +llvm::Optional<size_t> +ClangASTContext::GetTypeBitAlign(lldb::opaque_compiler_type_t type, + ExecutionContextScope *exe_scope) { if (GetCompleteType(type)) return getASTContext()->getTypeAlign(GetQualType(type)); - return 0; + return {}; } lldb::Encoding ClangASTContext::GetEncoding(lldb::opaque_compiler_type_t type, @@ -5255,6 +5195,20 @@ lldb::Encoding ClangASTContext::GetEncoding(lldb::opaque_compiler_type_t type, case clang::BuiltinType::OCLIntelSubgroupAVCImeSingleRefStreamin: case clang::BuiltinType::OCLIntelSubgroupAVCImeDualRefStreamin: break; + + case clang::BuiltinType::SveBool: + case clang::BuiltinType::SveInt8: + case clang::BuiltinType::SveInt16: + case clang::BuiltinType::SveInt32: + case clang::BuiltinType::SveInt64: + case clang::BuiltinType::SveUint8: + case clang::BuiltinType::SveUint16: + case clang::BuiltinType::SveUint32: + case clang::BuiltinType::SveUint64: + case clang::BuiltinType::SveFloat16: + case clang::BuiltinType::SveFloat32: + case clang::BuiltinType::SveFloat64: + break; } break; // All pointer types are represented as unsigned integer encodings. We may @@ -5274,8 +5228,9 @@ lldb::Encoding ClangASTContext::GetEncoding(lldb::opaque_compiler_type_t type, const clang::ComplexType *complex_type = qual_type->getAsComplexIntegerType(); if (complex_type) - encoding = CompilerType(getASTContext(), complex_type->getElementType()) - .GetEncoding(count); + encoding = + CompilerType(this, complex_type->getElementType().getAsOpaquePtr()) + .GetEncoding(count); else encoding = lldb::eEncodingSint; } @@ -5290,43 +5245,44 @@ lldb::Encoding ClangASTContext::GetEncoding(lldb::opaque_compiler_type_t type, case clang::Type::Enum: return lldb::eEncodingSint; case clang::Type::Typedef: - return CompilerType(getASTContext(), - llvm::cast<clang::TypedefType>(qual_type) - ->getDecl() - ->getUnderlyingType()) + return CompilerType(this, llvm::cast<clang::TypedefType>(qual_type) + ->getDecl() + ->getUnderlyingType() + .getAsOpaquePtr()) .GetEncoding(count); case clang::Type::Auto: - return CompilerType( - getASTContext(), - llvm::cast<clang::AutoType>(qual_type)->getDeducedType()) + return CompilerType(this, llvm::cast<clang::AutoType>(qual_type) + ->getDeducedType() + .getAsOpaquePtr()) .GetEncoding(count); case clang::Type::Elaborated: - return CompilerType( - getASTContext(), - llvm::cast<clang::ElaboratedType>(qual_type)->getNamedType()) + return CompilerType(this, llvm::cast<clang::ElaboratedType>(qual_type) + ->getNamedType() + .getAsOpaquePtr()) .GetEncoding(count); case clang::Type::Paren: - return CompilerType(getASTContext(), - llvm::cast<clang::ParenType>(qual_type)->desugar()) + return CompilerType(this, llvm::cast<clang::ParenType>(qual_type) + ->desugar() + .getAsOpaquePtr()) .GetEncoding(count); case clang::Type::TypeOfExpr: - return CompilerType(getASTContext(), - llvm::cast<clang::TypeOfExprType>(qual_type) - ->getUnderlyingExpr() - ->getType()) + return CompilerType(this, llvm::cast<clang::TypeOfExprType>(qual_type) + ->getUnderlyingExpr() + ->getType() + .getAsOpaquePtr()) .GetEncoding(count); case clang::Type::TypeOf: - return CompilerType( - getASTContext(), - llvm::cast<clang::TypeOfType>(qual_type)->getUnderlyingType()) + return CompilerType(this, llvm::cast<clang::TypeOfType>(qual_type) + ->getUnderlyingType() + .getAsOpaquePtr()) .GetEncoding(count); case clang::Type::Decltype: - return CompilerType( - getASTContext(), - llvm::cast<clang::DecltypeType>(qual_type)->getUnderlyingType()) + return CompilerType(this, llvm::cast<clang::DecltypeType>(qual_type) + ->getUnderlyingType() + .getAsOpaquePtr()) .GetEncoding(count); case clang::Type::DependentSizedArray: case clang::Type::DependentSizedExtVector: @@ -5463,39 +5419,41 @@ lldb::Format ClangASTContext::GetFormat(lldb::opaque_compiler_type_t type) { case clang::Type::Enum: return lldb::eFormatEnum; case clang::Type::Typedef: - return CompilerType(getASTContext(), - llvm::cast<clang::TypedefType>(qual_type) - ->getDecl() - ->getUnderlyingType()) + return CompilerType(this, llvm::cast<clang::TypedefType>(qual_type) + ->getDecl() + ->getUnderlyingType() + .getAsOpaquePtr()) .GetFormat(); case clang::Type::Auto: - return CompilerType(getASTContext(), - llvm::cast<clang::AutoType>(qual_type)->desugar()) + return CompilerType(this, llvm::cast<clang::AutoType>(qual_type) + ->desugar() + .getAsOpaquePtr()) .GetFormat(); case clang::Type::Paren: - return CompilerType(getASTContext(), - llvm::cast<clang::ParenType>(qual_type)->desugar()) + return CompilerType(this, llvm::cast<clang::ParenType>(qual_type) + ->desugar() + .getAsOpaquePtr()) .GetFormat(); case clang::Type::Elaborated: - return CompilerType( - getASTContext(), - llvm::cast<clang::ElaboratedType>(qual_type)->getNamedType()) + return CompilerType(this, llvm::cast<clang::ElaboratedType>(qual_type) + ->getNamedType() + .getAsOpaquePtr()) .GetFormat(); case clang::Type::TypeOfExpr: - return CompilerType(getASTContext(), - llvm::cast<clang::TypeOfExprType>(qual_type) - ->getUnderlyingExpr() - ->getType()) + return CompilerType(this, llvm::cast<clang::TypeOfExprType>(qual_type) + ->getUnderlyingExpr() + ->getType() + .getAsOpaquePtr()) .GetFormat(); case clang::Type::TypeOf: - return CompilerType( - getASTContext(), - llvm::cast<clang::TypeOfType>(qual_type)->getUnderlyingType()) + return CompilerType(this, llvm::cast<clang::TypeOfType>(qual_type) + ->getUnderlyingType() + .getAsOpaquePtr()) .GetFormat(); case clang::Type::Decltype: - return CompilerType( - getASTContext(), - llvm::cast<clang::DecltypeType>(qual_type)->getUnderlyingType()) + return CompilerType(this, llvm::cast<clang::DecltypeType>(qual_type) + ->getUnderlyingType() + .getAsOpaquePtr()) .GetFormat(); case clang::Type::DependentSizedArray: case clang::Type::DependentSizedExtVector: @@ -5657,7 +5615,7 @@ uint32_t ClangASTContext::GetNumChildren(lldb::opaque_compiler_type_t type, llvm::cast<clang::ObjCObjectPointerType>(qual_type.getTypePtr()); clang::QualType pointee_type = pointer_type->getPointeeType(); uint32_t num_pointee_children = - CompilerType(getASTContext(), pointee_type) + CompilerType(this, pointee_type.getAsOpaquePtr()) .GetNumChildren(omit_empty_base_classes, exe_ctx); // If this type points to a simple type, then it has 1 child if (num_pointee_children == 0) @@ -5691,7 +5649,7 @@ uint32_t ClangASTContext::GetNumChildren(lldb::opaque_compiler_type_t type, llvm::cast<clang::PointerType>(qual_type.getTypePtr()); clang::QualType pointee_type(pointer_type->getPointeeType()); uint32_t num_pointee_children = - CompilerType(getASTContext(), pointee_type) + CompilerType(this, pointee_type.getAsOpaquePtr()) .GetNumChildren(omit_empty_base_classes, exe_ctx); if (num_pointee_children == 0) { // We have a pointer to a pointee type that claims it has no children. We @@ -5707,7 +5665,7 @@ uint32_t ClangASTContext::GetNumChildren(lldb::opaque_compiler_type_t type, llvm::cast<clang::ReferenceType>(qual_type.getTypePtr()); clang::QualType pointee_type = reference_type->getPointeeType(); uint32_t num_pointee_children = - CompilerType(getASTContext(), pointee_type) + CompilerType(this, pointee_type.getAsOpaquePtr()) .GetNumChildren(omit_empty_base_classes, exe_ctx); // If this type points to a simple type, then it has 1 child if (num_pointee_children == 0) @@ -5717,32 +5675,33 @@ uint32_t ClangASTContext::GetNumChildren(lldb::opaque_compiler_type_t type, } break; case clang::Type::Typedef: - num_children = - CompilerType(getASTContext(), llvm::cast<clang::TypedefType>(qual_type) + num_children = CompilerType(this, llvm::cast<clang::TypedefType>(qual_type) ->getDecl() - ->getUnderlyingType()) - .GetNumChildren(omit_empty_base_classes, exe_ctx); + ->getUnderlyingType() + .getAsOpaquePtr()) + .GetNumChildren(omit_empty_base_classes, exe_ctx); break; case clang::Type::Auto: - num_children = - CompilerType(getASTContext(), - llvm::cast<clang::AutoType>(qual_type)->getDeducedType()) - .GetNumChildren(omit_empty_base_classes, exe_ctx); + num_children = CompilerType(this, llvm::cast<clang::AutoType>(qual_type) + ->getDeducedType() + .getAsOpaquePtr()) + .GetNumChildren(omit_empty_base_classes, exe_ctx); break; case clang::Type::Elaborated: num_children = - CompilerType( - getASTContext(), - llvm::cast<clang::ElaboratedType>(qual_type)->getNamedType()) + CompilerType(this, llvm::cast<clang::ElaboratedType>(qual_type) + ->getNamedType() + .getAsOpaquePtr()) .GetNumChildren(omit_empty_base_classes, exe_ctx); break; case clang::Type::Paren: num_children = - CompilerType(getASTContext(), - llvm::cast<clang::ParenType>(qual_type)->desugar()) + CompilerType( + this, + llvm::cast<clang::ParenType>(qual_type)->desugar().getAsOpaquePtr()) .GetNumChildren(omit_empty_base_classes, exe_ctx); break; default: @@ -5883,31 +5842,33 @@ uint32_t ClangASTContext::GetNumFields(lldb::opaque_compiler_type_t type) { break; case clang::Type::Typedef: - count = - CompilerType(getASTContext(), llvm::cast<clang::TypedefType>(qual_type) - ->getDecl() - ->getUnderlyingType()) - .GetNumFields(); + count = CompilerType(this, llvm::cast<clang::TypedefType>(qual_type) + ->getDecl() + ->getUnderlyingType() + .getAsOpaquePtr()) + .GetNumFields(); break; case clang::Type::Auto: - count = - CompilerType(getASTContext(), - llvm::cast<clang::AutoType>(qual_type)->getDeducedType()) - .GetNumFields(); + count = CompilerType(this, llvm::cast<clang::AutoType>(qual_type) + ->getDeducedType() + .getAsOpaquePtr()) + .GetNumFields(); break; case clang::Type::Elaborated: - count = CompilerType( - getASTContext(), - llvm::cast<clang::ElaboratedType>(qual_type)->getNamedType()) + count = CompilerType(this, llvm::cast<clang::ElaboratedType>(qual_type) + ->getNamedType() + .getAsOpaquePtr()) .GetNumFields(); break; case clang::Type::Paren: - count = CompilerType(getASTContext(), - llvm::cast<clang::ParenType>(qual_type)->desugar()) - .GetNumFields(); + count = + CompilerType( + this, + llvm::cast<clang::ParenType>(qual_type)->desugar().getAsOpaquePtr()) + .GetNumFields(); break; case clang::Type::ObjCObjectPointer: { @@ -6053,7 +6014,7 @@ CompilerType ClangASTContext::GetFieldAtIndex(lldb::opaque_compiler_type_t type, if (is_bitfield_ptr) *is_bitfield_ptr = is_bitfield; - return CompilerType(getASTContext(), field->getType()); + return CompilerType(this, field->getType().getAsOpaquePtr()); } } } @@ -6097,30 +6058,31 @@ CompilerType ClangASTContext::GetFieldAtIndex(lldb::opaque_compiler_type_t type, break; case clang::Type::Typedef: - return CompilerType(getASTContext(), - llvm::cast<clang::TypedefType>(qual_type) - ->getDecl() - ->getUnderlyingType()) + return CompilerType(this, llvm::cast<clang::TypedefType>(qual_type) + ->getDecl() + ->getUnderlyingType() + .getAsOpaquePtr()) .GetFieldAtIndex(idx, name, bit_offset_ptr, bitfield_bit_size_ptr, is_bitfield_ptr); case clang::Type::Auto: - return CompilerType( - getASTContext(), - llvm::cast<clang::AutoType>(qual_type)->getDeducedType()) + return CompilerType(this, llvm::cast<clang::AutoType>(qual_type) + ->getDeducedType() + .getAsOpaquePtr()) .GetFieldAtIndex(idx, name, bit_offset_ptr, bitfield_bit_size_ptr, is_bitfield_ptr); case clang::Type::Elaborated: - return CompilerType( - getASTContext(), - llvm::cast<clang::ElaboratedType>(qual_type)->getNamedType()) + return CompilerType(this, llvm::cast<clang::ElaboratedType>(qual_type) + ->getNamedType() + .getAsOpaquePtr()) .GetFieldAtIndex(idx, name, bit_offset_ptr, bitfield_bit_size_ptr, is_bitfield_ptr); case clang::Type::Paren: - return CompilerType(getASTContext(), - llvm::cast<clang::ParenType>(qual_type)->desugar()) + return CompilerType(this, llvm::cast<clang::ParenType>(qual_type) + ->desugar() + .getAsOpaquePtr()) .GetFieldAtIndex(idx, name, bit_offset_ptr, bitfield_bit_size_ptr, is_bitfield_ptr); @@ -6311,9 +6273,9 @@ CompilerType ClangASTContext::GetDirectBaseClassAtIndex( if (superclass_interface_decl) { if (bit_offset_ptr) *bit_offset_ptr = 0; - return CompilerType(getASTContext(), + return CompilerType(this, getASTContext()->getObjCInterfaceType( - superclass_interface_decl)); + superclass_interface_decl).getAsOpaquePtr()); } } } @@ -6333,9 +6295,10 @@ CompilerType ClangASTContext::GetDirectBaseClassAtIndex( if (superclass_interface_decl) { if (bit_offset_ptr) *bit_offset_ptr = 0; - return CompilerType(getASTContext(), - getASTContext()->getObjCInterfaceType( - superclass_interface_decl)); + return CompilerType( + this, getASTContext() + ->getObjCInterfaceType(superclass_interface_decl) + .getAsOpaquePtr()); } } } @@ -6638,8 +6601,8 @@ CompilerType ClangASTContext::GetChildCompilerTypeAtIndex( child_byte_size = getASTContext()->getTypeSize(getASTContext()->ObjCBuiltinClassTy) / CHAR_BIT; - return CompilerType(getASTContext(), - getASTContext()->ObjCBuiltinClassTy); + return CompilerType( + this, getASTContext()->ObjCBuiltinClassTy.getAsOpaquePtr()); default: break; @@ -6702,8 +6665,8 @@ CompilerType ClangASTContext::GetChildCompilerTypeAtIndex( // Base classes should be a multiple of 8 bits in size child_byte_offset = bit_offset / 8; - CompilerType base_class_clang_type(getASTContext(), - base_class->getType()); + CompilerType base_class_clang_type( + this, base_class->getType().getAsOpaquePtr()); child_name = base_class_clang_type.GetTypeName().AsCString(""); Optional<uint64_t> size = base_class_clang_type.GetBitSize(get_exe_scope()); @@ -6735,7 +6698,8 @@ CompilerType ClangASTContext::GetChildCompilerTypeAtIndex( // Figure out the type byte size (field_type_info.first) and // alignment (field_type_info.second) from the AST context. - CompilerType field_clang_type(getASTContext(), field->getType()); + CompilerType field_clang_type(this, + field->getType().getAsOpaquePtr()); assert(field_idx < record_layout.getFieldCount()); Optional<uint64_t> size = field_clang_type.GetByteSize(get_exe_scope()); @@ -6783,8 +6747,9 @@ CompilerType ClangASTContext::GetChildCompilerTypeAtIndex( if (superclass_interface_decl) { if (omit_empty_base_classes) { CompilerType base_class_clang_type( - getASTContext(), getASTContext()->getObjCInterfaceType( - superclass_interface_decl)); + this, getASTContext() + ->getObjCInterfaceType(superclass_interface_decl) + .getAsOpaquePtr()); if (base_class_clang_type.GetNumChildren(omit_empty_base_classes, exe_ctx) > 0) { if (idx == 0) { @@ -6802,7 +6767,7 @@ CompilerType ClangASTContext::GetChildCompilerTypeAtIndex( child_byte_offset = 0; child_is_base_class = true; - return CompilerType(getASTContext(), ivar_qual_type); + return CompilerType(this, ivar_qual_type.getAsOpaquePtr()); } ++child_idx; @@ -6846,8 +6811,8 @@ CompilerType ClangASTContext::GetChildCompilerTypeAtIndex( ObjCLanguageRuntime *objc_runtime = ObjCLanguageRuntime::Get(*process); if (objc_runtime != nullptr) { - CompilerType parent_ast_type(getASTContext(), - parent_qual_type); + CompilerType parent_ast_type( + this, parent_qual_type.getAsOpaquePtr()); child_byte_offset = objc_runtime->GetByteOffsetForIvar( parent_ast_type, ivar_decl->getNameAsString().c_str()); } @@ -6878,7 +6843,7 @@ CompilerType ClangASTContext::GetChildCompilerTypeAtIndex( child_bitfield_bit_offset = bit_offset % 8; } - return CompilerType(getASTContext(), ivar_qual_type); + return CompilerType(this, ivar_qual_type.getAsOpaquePtr()); } ++child_idx; } @@ -6929,7 +6894,8 @@ CompilerType ClangASTContext::GetChildCompilerTypeAtIndex( const clang::VectorType *array = llvm::cast<clang::VectorType>(parent_qual_type.getTypePtr()); if (array) { - CompilerType element_type(getASTContext(), array->getElementType()); + CompilerType element_type(this, + array->getElementType().getAsOpaquePtr()); if (element_type.GetCompleteType()) { char element_name[64]; ::snprintf(element_name, sizeof(element_name), "[%" PRIu64 "]", @@ -6951,7 +6917,8 @@ CompilerType ClangASTContext::GetChildCompilerTypeAtIndex( if (ignore_array_bounds || idx_is_valid) { const clang::ArrayType *array = GetQualType(type)->getAsArrayTypeUnsafe(); if (array) { - CompilerType element_type(getASTContext(), array->getElementType()); + CompilerType element_type(this, + array->getElementType().getAsOpaquePtr()); if (element_type.GetCompleteType()) { child_name = llvm::formatv("[{0}]", idx); if (Optional<uint64_t> size = @@ -7009,8 +6976,8 @@ CompilerType ClangASTContext::GetChildCompilerTypeAtIndex( if (idx_is_valid) { const clang::ReferenceType *reference_type = llvm::cast<clang::ReferenceType>(parent_qual_type.getTypePtr()); - CompilerType pointee_clang_type(getASTContext(), - reference_type->getPointeeType()); + CompilerType pointee_clang_type( + this, reference_type->getPointeeType().getAsOpaquePtr()); if (transparent_pointers && pointee_clang_type.IsAggregateType()) { child_is_deref_of_parent = false; bool tmp_child_is_deref_of_parent = false; @@ -7043,9 +7010,10 @@ CompilerType ClangASTContext::GetChildCompilerTypeAtIndex( case clang::Type::Typedef: { CompilerType typedefed_clang_type( - getASTContext(), llvm::cast<clang::TypedefType>(parent_qual_type) - ->getDecl() - ->getUnderlyingType()); + this, llvm::cast<clang::TypedefType>(parent_qual_type) + ->getDecl() + ->getUnderlyingType() + .getAsOpaquePtr()); return typedefed_clang_type.GetChildCompilerTypeAtIndex( exe_ctx, idx, transparent_pointers, omit_empty_base_classes, ignore_array_bounds, child_name, child_byte_size, child_byte_offset, @@ -7055,8 +7023,9 @@ CompilerType ClangASTContext::GetChildCompilerTypeAtIndex( case clang::Type::Auto: { CompilerType elaborated_clang_type( - getASTContext(), - llvm::cast<clang::AutoType>(parent_qual_type)->getDeducedType()); + this, llvm::cast<clang::AutoType>(parent_qual_type) + ->getDeducedType() + .getAsOpaquePtr()); return elaborated_clang_type.GetChildCompilerTypeAtIndex( exe_ctx, idx, transparent_pointers, omit_empty_base_classes, ignore_array_bounds, child_name, child_byte_size, child_byte_offset, @@ -7066,8 +7035,9 @@ CompilerType ClangASTContext::GetChildCompilerTypeAtIndex( case clang::Type::Elaborated: { CompilerType elaborated_clang_type( - getASTContext(), - llvm::cast<clang::ElaboratedType>(parent_qual_type)->getNamedType()); + this, llvm::cast<clang::ElaboratedType>(parent_qual_type) + ->getNamedType() + .getAsOpaquePtr()); return elaborated_clang_type.GetChildCompilerTypeAtIndex( exe_ctx, idx, transparent_pointers, omit_empty_base_classes, ignore_array_bounds, child_name, child_byte_size, child_byte_offset, @@ -7076,9 +7046,10 @@ CompilerType ClangASTContext::GetChildCompilerTypeAtIndex( } case clang::Type::Paren: { - CompilerType paren_clang_type( - getASTContext(), - llvm::cast<clang::ParenType>(parent_qual_type)->desugar()); + CompilerType paren_clang_type(this, + llvm::cast<clang::ParenType>(parent_qual_type) + ->desugar() + .getAsOpaquePtr()); return paren_clang_type.GetChildCompilerTypeAtIndex( exe_ctx, idx, transparent_pointers, omit_empty_base_classes, ignore_array_bounds, child_name, child_byte_size, child_byte_offset, @@ -7207,7 +7178,7 @@ size_t ClangASTContext::GetIndexOfChildMemberWithName( field != field_end; ++field, ++child_idx) { llvm::StringRef field_name = field->getName(); if (field_name.empty()) { - CompilerType field_type(getASTContext(), field->getType()); + CompilerType field_type(this, field->getType().getAsOpaquePtr()); child_indexes.push_back(child_idx); if (field_type.GetIndexOfChildMemberWithName( name, omit_empty_base_classes, child_indexes)) @@ -7319,8 +7290,9 @@ size_t ClangASTContext::GetIndexOfChildMemberWithName( child_indexes.push_back(0); CompilerType superclass_clang_type( - getASTContext(), getASTContext()->getObjCInterfaceType( - superclass_interface_decl)); + this, getASTContext() + ->getObjCInterfaceType(superclass_interface_decl) + .getAsOpaquePtr()); if (superclass_clang_type.GetIndexOfChildMemberWithName( name, omit_empty_base_classes, child_indexes)) { // We did find an ivar in a superclass so just return the @@ -7339,9 +7311,9 @@ size_t ClangASTContext::GetIndexOfChildMemberWithName( case clang::Type::ObjCObjectPointer: { CompilerType objc_object_clang_type( - getASTContext(), - llvm::cast<clang::ObjCObjectPointerType>(qual_type.getTypePtr()) - ->getPointeeType()); + this, llvm::cast<clang::ObjCObjectPointerType>(qual_type.getTypePtr()) + ->getPointeeType() + .getAsOpaquePtr()); return objc_object_clang_type.GetIndexOfChildMemberWithName( name, omit_empty_base_classes, child_indexes); } break; @@ -7391,7 +7363,7 @@ size_t ClangASTContext::GetIndexOfChildMemberWithName( const clang::ReferenceType *reference_type = llvm::cast<clang::ReferenceType>(qual_type.getTypePtr()); clang::QualType pointee_type(reference_type->getPointeeType()); - CompilerType pointee_clang_type(getASTContext(), pointee_type); + CompilerType pointee_clang_type(this, pointee_type.getAsOpaquePtr()); if (pointee_clang_type.IsAggregateType()) { return pointee_clang_type.GetIndexOfChildMemberWithName( @@ -7409,30 +7381,31 @@ size_t ClangASTContext::GetIndexOfChildMemberWithName( } break; case clang::Type::Typedef: - return CompilerType(getASTContext(), - llvm::cast<clang::TypedefType>(qual_type) - ->getDecl() - ->getUnderlyingType()) + return CompilerType(this, llvm::cast<clang::TypedefType>(qual_type) + ->getDecl() + ->getUnderlyingType() + .getAsOpaquePtr()) .GetIndexOfChildMemberWithName(name, omit_empty_base_classes, child_indexes); case clang::Type::Auto: - return CompilerType( - getASTContext(), - llvm::cast<clang::AutoType>(qual_type)->getDeducedType()) + return CompilerType(this, llvm::cast<clang::AutoType>(qual_type) + ->getDeducedType() + .getAsOpaquePtr()) .GetIndexOfChildMemberWithName(name, omit_empty_base_classes, child_indexes); case clang::Type::Elaborated: - return CompilerType( - getASTContext(), - llvm::cast<clang::ElaboratedType>(qual_type)->getNamedType()) + return CompilerType(this, llvm::cast<clang::ElaboratedType>(qual_type) + ->getNamedType() + .getAsOpaquePtr()) .GetIndexOfChildMemberWithName(name, omit_empty_base_classes, child_indexes); case clang::Type::Paren: - return CompilerType(getASTContext(), - llvm::cast<clang::ParenType>(qual_type)->desugar()) + return CompilerType(this, llvm::cast<clang::ParenType>(qual_type) + ->desugar() + .getAsOpaquePtr()) .GetIndexOfChildMemberWithName(name, omit_empty_base_classes, child_indexes); @@ -7485,8 +7458,8 @@ ClangASTContext::GetIndexOfChildWithName(lldb::opaque_compiler_type_t type, !ClangASTContext::RecordHasFields(base_class_decl)) continue; - CompilerType base_class_clang_type(getASTContext(), - base_class->getType()); + CompilerType base_class_clang_type( + this, base_class->getType().getAsOpaquePtr()); std::string base_class_type_name( base_class_clang_type.GetTypeName().AsCString("")); if (base_class_type_name == name) @@ -7550,9 +7523,9 @@ ClangASTContext::GetIndexOfChildWithName(lldb::opaque_compiler_type_t type, case clang::Type::ObjCObjectPointer: { CompilerType pointee_clang_type( - getASTContext(), - llvm::cast<clang::ObjCObjectPointerType>(qual_type.getTypePtr()) - ->getPointeeType()); + this, llvm::cast<clang::ObjCObjectPointerType>(qual_type.getTypePtr()) + ->getPointeeType() + .getAsOpaquePtr()); return pointee_clang_type.GetIndexOfChildWithName( name, omit_empty_base_classes); } break; @@ -7601,8 +7574,8 @@ ClangASTContext::GetIndexOfChildWithName(lldb::opaque_compiler_type_t type, case clang::Type::RValueReference: { const clang::ReferenceType *reference_type = llvm::cast<clang::ReferenceType>(qual_type.getTypePtr()); - CompilerType pointee_type(getASTContext(), - reference_type->getPointeeType()); + CompilerType pointee_type( + this, reference_type->getPointeeType().getAsOpaquePtr()); if (pointee_type.IsAggregateType()) { return pointee_type.GetIndexOfChildWithName(name, @@ -7613,8 +7586,8 @@ ClangASTContext::GetIndexOfChildWithName(lldb::opaque_compiler_type_t type, case clang::Type::Pointer: { const clang::PointerType *pointer_type = llvm::cast<clang::PointerType>(qual_type.getTypePtr()); - CompilerType pointee_type(getASTContext(), - pointer_type->getPointeeType()); + CompilerType pointee_type( + this, pointer_type->getPointeeType().getAsOpaquePtr()); if (pointee_type.IsAggregateType()) { return pointee_type.GetIndexOfChildWithName(name, @@ -7640,27 +7613,28 @@ ClangASTContext::GetIndexOfChildWithName(lldb::opaque_compiler_type_t type, } break; case clang::Type::Auto: - return CompilerType( - getASTContext(), - llvm::cast<clang::AutoType>(qual_type)->getDeducedType()) + return CompilerType(this, llvm::cast<clang::AutoType>(qual_type) + ->getDeducedType() + .getAsOpaquePtr()) .GetIndexOfChildWithName(name, omit_empty_base_classes); case clang::Type::Elaborated: - return CompilerType( - getASTContext(), - llvm::cast<clang::ElaboratedType>(qual_type)->getNamedType()) + return CompilerType(this, llvm::cast<clang::ElaboratedType>(qual_type) + ->getNamedType() + .getAsOpaquePtr()) .GetIndexOfChildWithName(name, omit_empty_base_classes); case clang::Type::Paren: - return CompilerType(getASTContext(), - llvm::cast<clang::ParenType>(qual_type)->desugar()) + return CompilerType(this, llvm::cast<clang::ParenType>(qual_type) + ->desugar() + .getAsOpaquePtr()) .GetIndexOfChildWithName(name, omit_empty_base_classes); case clang::Type::Typedef: - return CompilerType(getASTContext(), - llvm::cast<clang::TypedefType>(qual_type) - ->getDecl() - ->getUnderlyingType()) + return CompilerType(this, llvm::cast<clang::TypedefType>(qual_type) + ->getDecl() + ->getUnderlyingType() + .getAsOpaquePtr()) .GetIndexOfChildWithName(name, omit_empty_base_classes); default: @@ -7693,27 +7667,28 @@ ClangASTContext::GetNumTemplateArguments(lldb::opaque_compiler_type_t type) { break; case clang::Type::Typedef: - return (CompilerType(getASTContext(), - llvm::cast<clang::TypedefType>(qual_type) - ->getDecl() - ->getUnderlyingType())) + return CompilerType(this, llvm::cast<clang::TypedefType>(qual_type) + ->getDecl() + ->getUnderlyingType() + .getAsOpaquePtr()) .GetNumTemplateArguments(); case clang::Type::Auto: - return (CompilerType( - getASTContext(), - llvm::cast<clang::AutoType>(qual_type)->getDeducedType())) + return CompilerType(this, llvm::cast<clang::AutoType>(qual_type) + ->getDeducedType() + .getAsOpaquePtr()) .GetNumTemplateArguments(); case clang::Type::Elaborated: - return (CompilerType( - getASTContext(), - llvm::cast<clang::ElaboratedType>(qual_type)->getNamedType())) + return CompilerType(this, llvm::cast<clang::ElaboratedType>(qual_type) + ->getNamedType() + .getAsOpaquePtr()) .GetNumTemplateArguments(); case clang::Type::Paren: - return (CompilerType(getASTContext(), - llvm::cast<clang::ParenType>(qual_type)->desugar())) + return CompilerType(this, llvm::cast<clang::ParenType>(qual_type) + ->desugar() + .getAsOpaquePtr()) .GetNumTemplateArguments(); default: @@ -7821,7 +7796,7 @@ ClangASTContext::GetTypeTemplateArgument(lldb::opaque_compiler_type_t type, if (template_arg.getKind() != clang::TemplateArgument::Type) return CompilerType(); - return CompilerType(getASTContext(), template_arg.getAsType()); + return CompilerType(this, template_arg.getAsType().getAsOpaquePtr()); } Optional<CompilerType::IntegralTemplateArgument> @@ -7837,8 +7812,9 @@ ClangASTContext::GetIntegralTemplateArgument(lldb::opaque_compiler_type_t type, if (template_arg.getKind() != clang::TemplateArgument::Integral) return llvm::None; - return {{template_arg.getAsIntegral(), - CompilerType(getASTContext(), template_arg.getIntegralType())}}; + return { + {template_arg.getAsIntegral(), + CompilerType(this, template_arg.getIntegralType().getAsOpaquePtr())}}; } CompilerType ClangASTContext::GetTypeForFormatters(void *type) { @@ -8201,7 +8177,8 @@ clang::CXXMethodDecl *ClangASTContext::AddMethodToCXXRecordType( getASTContext()->DeclarationNames.getCXXDestructorName( getASTContext()->getCanonicalType(record_qual_type)), clang::SourceLocation()), - method_qual_type, nullptr, is_inline, is_artificial); + method_qual_type, nullptr, is_inline, is_artificial, + ConstexprSpecKind::CSK_unspecified); cxx_method_decl = cxx_dtor_decl; } else if (decl_name == cxx_record_decl->getDeclName()) { cxx_ctor_decl = clang::CXXConstructorDecl::Create( @@ -8272,8 +8249,8 @@ clang::CXXMethodDecl *ClangASTContext::AddMethodToCXXRecordType( cxx_method_decl->addAttr(clang::UsedAttr::CreateImplicit(*getASTContext())); if (mangled_name != nullptr) { - cxx_method_decl->addAttr( - clang::AsmLabelAttr::CreateImplicit(*getASTContext(), mangled_name)); + cxx_method_decl->addAttr(clang::AsmLabelAttr::CreateImplicit( + *getASTContext(), mangled_name, /*literal=*/false)); } // Populate the method decl with parameter decls @@ -8327,24 +8304,6 @@ clang::CXXMethodDecl *ClangASTContext::AddMethodToCXXRecordType( VerifyDecl(cxx_method_decl); #endif - // printf ("decl->isPolymorphic() = %i\n", - // cxx_record_decl->isPolymorphic()); - // printf ("decl->isAggregate() = %i\n", - // cxx_record_decl->isAggregate()); - // printf ("decl->isPOD() = %i\n", - // cxx_record_decl->isPOD()); - // printf ("decl->isEmpty() = %i\n", - // cxx_record_decl->isEmpty()); - // printf ("decl->isAbstract() = %i\n", - // cxx_record_decl->isAbstract()); - // printf ("decl->hasTrivialConstructor() = %i\n", - // cxx_record_decl->hasTrivialConstructor()); - // printf ("decl->hasTrivialCopyConstructor() = %i\n", - // cxx_record_decl->hasTrivialCopyConstructor()); - // printf ("decl->hasTrivialCopyAssignment() = %i\n", - // cxx_record_decl->hasTrivialCopyAssignment()); - // printf ("decl->hasTrivialDestructor() = %i\n", - // cxx_record_decl->hasTrivialDestructor()); return cxx_method_decl; } @@ -8364,7 +8323,7 @@ ClangASTContext::CreateBaseClassSpecifier(lldb::opaque_compiler_type_t type, if (!type) return nullptr; - return llvm::make_unique<clang::CXXBaseSpecifier>( + return std::make_unique<clang::CXXBaseSpecifier>( clang::SourceRange(), is_virtual, base_of_class, ClangASTContext::ConvertAccessTypeToAccessSpecifier(access), getASTContext()->getTrivialTypeSourceInfo(GetQualType(type)), @@ -8435,7 +8394,7 @@ bool ClangASTContext::AddObjCClassProperty( property_clang_type_to_access = property_clang_type; else if (ivar_decl) property_clang_type_to_access = - CompilerType(clang_ast, ivar_decl->getType()); + CompilerType(ast, ivar_decl->getType().getAsOpaquePtr()); if (class_interface_decl && property_clang_type_to_access.IsValid()) { clang::TypeSourceInfo *prop_type_source; @@ -8733,74 +8692,6 @@ clang::ObjCMethodDecl *ClangASTContext::AddMethodToObjCObjectType( return objc_method_decl; } -bool ClangASTContext::GetHasExternalStorage(const CompilerType &type) { - if (ClangUtil::IsClangType(type)) - return false; - - clang::QualType qual_type(ClangUtil::GetCanonicalQualType(type)); - - const clang::Type::TypeClass type_class = qual_type->getTypeClass(); - switch (type_class) { - case clang::Type::Record: { - clang::CXXRecordDecl *cxx_record_decl = qual_type->getAsCXXRecordDecl(); - if (cxx_record_decl) - return cxx_record_decl->hasExternalLexicalStorage() || - cxx_record_decl->hasExternalVisibleStorage(); - } break; - - case clang::Type::Enum: { - clang::EnumDecl *enum_decl = - llvm::cast<clang::EnumType>(qual_type)->getDecl(); - if (enum_decl) - return enum_decl->hasExternalLexicalStorage() || - enum_decl->hasExternalVisibleStorage(); - } break; - - case clang::Type::ObjCObject: - case clang::Type::ObjCInterface: { - const clang::ObjCObjectType *objc_class_type = - llvm::dyn_cast<clang::ObjCObjectType>(qual_type.getTypePtr()); - assert(objc_class_type); - if (objc_class_type) { - clang::ObjCInterfaceDecl *class_interface_decl = - objc_class_type->getInterface(); - - if (class_interface_decl) - return class_interface_decl->hasExternalLexicalStorage() || - class_interface_decl->hasExternalVisibleStorage(); - } - } break; - - case clang::Type::Typedef: - return GetHasExternalStorage(CompilerType( - type.GetTypeSystem(), llvm::cast<clang::TypedefType>(qual_type) - ->getDecl() - ->getUnderlyingType() - .getAsOpaquePtr())); - - case clang::Type::Auto: - return GetHasExternalStorage(CompilerType( - type.GetTypeSystem(), llvm::cast<clang::AutoType>(qual_type) - ->getDeducedType() - .getAsOpaquePtr())); - - case clang::Type::Elaborated: - return GetHasExternalStorage(CompilerType( - type.GetTypeSystem(), llvm::cast<clang::ElaboratedType>(qual_type) - ->getNamedType() - .getAsOpaquePtr())); - - case clang::Type::Paren: - return GetHasExternalStorage(CompilerType( - type.GetTypeSystem(), - llvm::cast<clang::ParenType>(qual_type)->desugar().getAsOpaquePtr())); - - default: - break; - } - return false; -} - bool ClangASTContext::SetHasExternalStorage(lldb::opaque_compiler_type_t type, bool has_extern) { if (!type) @@ -9041,7 +8932,7 @@ ClangASTContext::GetEnumerationIntegerType(lldb::opaque_compiler_type_t type) { if (enutype) { clang::EnumDecl *enum_decl = enutype->getDecl(); if (enum_decl) - return CompilerType(getASTContext(), enum_decl->getIntegerType()); + return CompilerType(this, enum_decl->getIntegerType().getAsOpaquePtr()); } } return CompilerType(); @@ -9056,47 +8947,15 @@ ClangASTContext::CreateMemberPointerType(const CompilerType &type, llvm::dyn_cast<ClangASTContext>(type.GetTypeSystem()); if (!ast) return CompilerType(); - return CompilerType(ast->getASTContext(), - ast->getASTContext()->getMemberPointerType( - ClangUtil::GetQualType(pointee_type), - ClangUtil::GetQualType(type).getTypePtr())); + return CompilerType(ast, ast->getASTContext() + ->getMemberPointerType( + ClangUtil::GetQualType(pointee_type), + ClangUtil::GetQualType(type).getTypePtr()) + .getAsOpaquePtr()); } return CompilerType(); } -size_t -ClangASTContext::ConvertStringToFloatValue(lldb::opaque_compiler_type_t type, - const char *s, uint8_t *dst, - size_t dst_size) { - if (type) { - clang::QualType qual_type(GetCanonicalQualType(type)); - uint32_t count = 0; - bool is_complex = false; - if (IsFloatingPointType(type, count, is_complex)) { - // TODO: handle complex and vector types - if (count != 1) - return false; - - llvm::StringRef s_sref(s); - llvm::APFloat ap_float(getASTContext()->getFloatTypeSemantics(qual_type), - s_sref); - - const uint64_t bit_size = getASTContext()->getTypeSize(qual_type); - const uint64_t byte_size = bit_size / 8; - if (dst_size >= byte_size) { - Scalar scalar = ap_float.bitcastToAPInt().zextOrTrunc( - llvm::NextPowerOf2(byte_size) * 8); - lldb_private::Status get_data_error; - if (scalar.GetAsMemoryData(dst, byte_size, - lldb_private::endian::InlHostByteOrder(), - get_data_error)) - return byte_size; - } - } - } - return 0; -} - // Dumping types #define DEPTH_INCREMENT 2 @@ -9115,6 +8974,39 @@ void ClangASTContext::Dump(Stream &s) { tu->dump(s.AsRawOstream()); } +void ClangASTContext::DumpFromSymbolFile(Stream &s, + llvm::StringRef symbol_name) { + SymbolFile *symfile = GetSymbolFile(); + + if (!symfile) + return; + + lldb_private::TypeList type_list; + symfile->GetTypes(nullptr, eTypeClassAny, type_list); + size_t ntypes = type_list.GetSize(); + + for (size_t i = 0; i < ntypes; ++i) { + TypeSP type = type_list.GetTypeAtIndex(i); + + if (!symbol_name.empty()) + if (symbol_name.compare(type->GetName().GetStringRef()) != 0) + continue; + + s << type->GetName().AsCString() << "\n"; + + if (clang::TagDecl *tag_decl = + GetAsTagDecl(type->GetFullCompilerType())) + tag_decl->dump(s.AsRawOstream()); + else if (clang::TypedefNameDecl *typedef_decl = + GetAsTypedefDecl(type->GetFullCompilerType())) + typedef_decl->dump(s.AsRawOstream()); + else { + GetCanonicalQualType(type->GetFullCompilerType().GetOpaqueQualType()) + .dump(s.AsRawOstream()); + } + } +} + void ClangASTContext::DumpValue( lldb::opaque_compiler_type_t type, ExecutionContext *exe_ctx, Stream *s, lldb::Format format, const DataExtractor &data, @@ -9182,7 +9074,8 @@ void ClangASTContext::DumpValue( getASTContext()->getTypeInfo(base_class_qual_type); // Dump the value of the member - CompilerType base_clang_type(getASTContext(), base_class_qual_type); + CompilerType base_clang_type(this, + base_class_qual_type.getAsOpaquePtr()); base_clang_type.DumpValue( exe_ctx, s, // Stream to dump to @@ -9249,7 +9142,7 @@ void ClangASTContext::DumpValue( s->Printf("%s = ", field->getNameAsString().c_str()); // Dump the value of the member - CompilerType field_clang_type(getASTContext(), field_type); + CompilerType field_clang_type(this, field_type.getAsOpaquePtr()); field_clang_type.DumpValue( exe_ctx, s, // Stream to dump to @@ -9329,7 +9222,7 @@ void ClangASTContext::DumpValue( s->PutChar('"'); return; } else { - CompilerType element_clang_type(getASTContext(), element_qual_type); + CompilerType element_clang_type(this, element_qual_type.getAsOpaquePtr()); lldb::Format element_format = element_clang_type.GetFormat(); for (element_idx = 0; element_idx < element_count; ++element_idx) { @@ -9380,7 +9273,7 @@ void ClangASTContext::DumpValue( ->getDecl() ->getUnderlyingType(); - CompilerType typedef_clang_type(getASTContext(), typedef_qual_type); + CompilerType typedef_clang_type(this, typedef_qual_type.getAsOpaquePtr()); lldb::Format typedef_format = typedef_clang_type.GetFormat(); clang::TypeInfo typedef_type_info = getASTContext()->getTypeInfo(typedef_qual_type); @@ -9405,7 +9298,8 @@ void ClangASTContext::DumpValue( case clang::Type::Auto: { clang::QualType elaborated_qual_type = llvm::cast<clang::AutoType>(qual_type)->getDeducedType(); - CompilerType elaborated_clang_type(getASTContext(), elaborated_qual_type); + CompilerType elaborated_clang_type(this, + elaborated_qual_type.getAsOpaquePtr()); lldb::Format elaborated_format = elaborated_clang_type.GetFormat(); clang::TypeInfo elaborated_type_info = getASTContext()->getTypeInfo(elaborated_qual_type); @@ -9430,7 +9324,8 @@ void ClangASTContext::DumpValue( case clang::Type::Elaborated: { clang::QualType elaborated_qual_type = llvm::cast<clang::ElaboratedType>(qual_type)->getNamedType(); - CompilerType elaborated_clang_type(getASTContext(), elaborated_qual_type); + CompilerType elaborated_clang_type(this, + elaborated_qual_type.getAsOpaquePtr()); lldb::Format elaborated_format = elaborated_clang_type.GetFormat(); clang::TypeInfo elaborated_type_info = getASTContext()->getTypeInfo(elaborated_qual_type); @@ -9455,7 +9350,7 @@ void ClangASTContext::DumpValue( case clang::Type::Paren: { clang::QualType desugar_qual_type = llvm::cast<clang::ParenType>(qual_type)->desugar(); - CompilerType desugar_clang_type(getASTContext(), desugar_qual_type); + CompilerType desugar_clang_type(this, desugar_qual_type.getAsOpaquePtr()); lldb::Format desugar_format = desugar_clang_type.GetFormat(); clang::TypeInfo desugar_type_info = @@ -9490,6 +9385,86 @@ void ClangASTContext::DumpValue( } } +static bool DumpEnumValue(const clang::QualType &qual_type, Stream *s, + const DataExtractor &data, lldb::offset_t byte_offset, + size_t byte_size, uint32_t bitfield_bit_offset, + uint32_t bitfield_bit_size) { + const clang::EnumType *enutype = + llvm::cast<clang::EnumType>(qual_type.getTypePtr()); + const clang::EnumDecl *enum_decl = enutype->getDecl(); + assert(enum_decl); + lldb::offset_t offset = byte_offset; + const uint64_t enum_svalue = data.GetMaxS64Bitfield( + &offset, byte_size, bitfield_bit_size, bitfield_bit_offset); + bool can_be_bitfield = true; + uint64_t covered_bits = 0; + int num_enumerators = 0; + + // Try to find an exact match for the value. + // At the same time, we're applying a heuristic to determine whether we want + // to print this enum as a bitfield. We're likely dealing with a bitfield if + // every enumrator is either a one bit value or a superset of the previous + // enumerators. Also 0 doesn't make sense when the enumerators are used as + // flags. + for (auto enumerator : enum_decl->enumerators()) { + uint64_t val = enumerator->getInitVal().getSExtValue(); + val = llvm::SignExtend64(val, 8*byte_size); + if (llvm::countPopulation(val) != 1 && (val & ~covered_bits) != 0) + can_be_bitfield = false; + covered_bits |= val; + ++num_enumerators; + if (val == enum_svalue) { + // Found an exact match, that's all we need to do. + s->PutCString(enumerator->getNameAsString()); + return true; + } + } + + // Unsigned values make more sense for flags. + offset = byte_offset; + const uint64_t enum_uvalue = data.GetMaxU64Bitfield( + &offset, byte_size, bitfield_bit_size, bitfield_bit_offset); + + // No exact match, but we don't think this is a bitfield. Print the value as + // decimal. + if (!can_be_bitfield) { + if (qual_type->isSignedIntegerOrEnumerationType()) + s->Printf("%" PRIi64, enum_svalue); + else + s->Printf("%" PRIu64, enum_uvalue); + return true; + } + + uint64_t remaining_value = enum_uvalue; + std::vector<std::pair<uint64_t, llvm::StringRef>> values; + values.reserve(num_enumerators); + for (auto enumerator : enum_decl->enumerators()) + if (auto val = enumerator->getInitVal().getZExtValue()) + values.emplace_back(val, enumerator->getName()); + + // Sort in reverse order of the number of the population count, so that in + // `enum {A, B, ALL = A|B }` we visit ALL first. Use a stable sort so that + // A | C where A is declared before C is displayed in this order. + std::stable_sort(values.begin(), values.end(), [](const auto &a, const auto &b) { + return llvm::countPopulation(a.first) > llvm::countPopulation(b.first); + }); + + for (const auto &val : values) { + if ((remaining_value & val.first) != val.first) + continue; + remaining_value &= ~val.first; + s->PutCString(val.second); + if (remaining_value) + s->PutCString(" | "); + } + + // If there is a remainder that is not covered by the value, print it as hex. + if (remaining_value) + s->Printf("0x%" PRIx64, remaining_value); + + return true; +} + bool ClangASTContext::DumpTypeValue( lldb::opaque_compiler_type_t type, Stream *s, lldb::Format format, const DataExtractor &data, lldb::offset_t byte_offset, size_t byte_size, @@ -9503,13 +9478,20 @@ bool ClangASTContext::DumpTypeValue( clang::QualType qual_type(GetQualType(type)); const clang::Type::TypeClass type_class = qual_type->getTypeClass(); + + if (type_class == clang::Type::Elaborated) { + qual_type = llvm::cast<clang::ElaboratedType>(qual_type)->getNamedType(); + return DumpTypeValue(qual_type.getAsOpaquePtr(), s, format, data, byte_offset, byte_size, + bitfield_bit_size, bitfield_bit_offset, exe_scope); + } + switch (type_class) { case clang::Type::Typedef: { clang::QualType typedef_qual_type = llvm::cast<clang::TypedefType>(qual_type) ->getDecl() ->getUnderlyingType(); - CompilerType typedef_clang_type(getASTContext(), typedef_qual_type); + CompilerType typedef_clang_type(this, typedef_qual_type.getAsOpaquePtr()); if (format == eFormatDefault) format = typedef_clang_type.GetFormat(); clang::TypeInfo typedef_type_info = @@ -9533,45 +9515,9 @@ bool ClangASTContext::DumpTypeValue( // If our format is enum or default, show the enumeration value as its // enumeration string value, else just display it as requested. if ((format == eFormatEnum || format == eFormatDefault) && - GetCompleteType(type)) { - const clang::EnumType *enutype = - llvm::cast<clang::EnumType>(qual_type.getTypePtr()); - const clang::EnumDecl *enum_decl = enutype->getDecl(); - assert(enum_decl); - clang::EnumDecl::enumerator_iterator enum_pos, enum_end_pos; - const bool is_signed = qual_type->isSignedIntegerOrEnumerationType(); - lldb::offset_t offset = byte_offset; - if (is_signed) { - const int64_t enum_svalue = data.GetMaxS64Bitfield( - &offset, byte_size, bitfield_bit_size, bitfield_bit_offset); - for (enum_pos = enum_decl->enumerator_begin(), - enum_end_pos = enum_decl->enumerator_end(); - enum_pos != enum_end_pos; ++enum_pos) { - if (enum_pos->getInitVal().getSExtValue() == enum_svalue) { - s->PutCString(enum_pos->getNameAsString()); - return true; - } - } - // If we have gotten here we didn't get find the enumerator in the - // enum decl, so just print the integer. - s->Printf("%" PRIi64, enum_svalue); - } else { - const uint64_t enum_uvalue = data.GetMaxU64Bitfield( - &offset, byte_size, bitfield_bit_size, bitfield_bit_offset); - for (enum_pos = enum_decl->enumerator_begin(), - enum_end_pos = enum_decl->enumerator_end(); - enum_pos != enum_end_pos; ++enum_pos) { - if (enum_pos->getInitVal().getZExtValue() == enum_uvalue) { - s->PutCString(enum_pos->getNameAsString()); - return true; - } - } - // If we have gotten here we didn't get find the enumerator in the - // enum decl, so just print the integer. - s->Printf("%" PRIu64, enum_uvalue); - } - return true; - } + GetCompleteType(type)) + return DumpEnumValue(qual_type, s, data, byte_offset, byte_size, + bitfield_bit_offset, bitfield_bit_size); // format was not enum, just fall through and dump the value as // requested.... LLVM_FALLTHROUGH; @@ -9739,20 +9685,23 @@ void ClangASTContext::DumpTypeDescription(lldb::opaque_compiler_type_t type, } break; case clang::Type::Auto: - CompilerType(getASTContext(), - llvm::cast<clang::AutoType>(qual_type)->getDeducedType()) + CompilerType(this, llvm::cast<clang::AutoType>(qual_type) + ->getDeducedType() + .getAsOpaquePtr()) .DumpTypeDescription(s); return; case clang::Type::Elaborated: - CompilerType(getASTContext(), - llvm::cast<clang::ElaboratedType>(qual_type)->getNamedType()) + CompilerType(this, llvm::cast<clang::ElaboratedType>(qual_type) + ->getNamedType() + .getAsOpaquePtr()) .DumpTypeDescription(s); return; case clang::Type::Paren: - CompilerType(getASTContext(), - llvm::cast<clang::ParenType>(qual_type)->desugar()) + CompilerType( + this, + llvm::cast<clang::ParenType>(qual_type)->desugar().getAsOpaquePtr()) .DumpTypeDescription(s); return; @@ -10348,9 +10297,9 @@ ClangASTContext::DeclContextGetClangASTContext(const CompilerDeclContext &dc) { return nullptr; } -ClangASTContextForExpressions::ClangASTContextForExpressions(Target &target) - : ClangASTContext(target.GetArchitecture().GetTriple().getTriple().c_str()), - m_target_wp(target.shared_from_this()), +ClangASTContextForExpressions::ClangASTContextForExpressions(Target &target, + ArchSpec arch) + : ClangASTContext(arch), m_target_wp(target.shared_from_this()), m_persistent_variables(new ClangPersistentVariables) {} UserExpression *ClangASTContextForExpressions::GetUserExpression( diff --git a/source/Symbol/ClangASTImporter.cpp b/source/Symbol/ClangASTImporter.cpp index 32d0c47693b0..92d51f79a007 100644 --- a/source/Symbol/ClangASTImporter.cpp +++ b/source/Symbol/ClangASTImporter.cpp @@ -30,28 +30,28 @@ ClangASTMetrics::Counters ClangASTMetrics::local_counters = {0, 0, 0, 0, 0, 0}; void ClangASTMetrics::DumpCounters(Log *log, ClangASTMetrics::Counters &counters) { - log->Printf(" Number of visible Decl queries by name : %" PRIu64, - counters.m_visible_query_count); - log->Printf(" Number of lexical Decl queries : %" PRIu64, - counters.m_lexical_query_count); - log->Printf(" Number of imports initiated by LLDB : %" PRIu64, - counters.m_lldb_import_count); - log->Printf(" Number of imports conducted by Clang : %" PRIu64, - counters.m_clang_import_count); - log->Printf(" Number of Decls completed : %" PRIu64, - counters.m_decls_completed_count); - log->Printf(" Number of records laid out : %" PRIu64, - counters.m_record_layout_count); + LLDB_LOGF(log, " Number of visible Decl queries by name : %" PRIu64, + counters.m_visible_query_count); + LLDB_LOGF(log, " Number of lexical Decl queries : %" PRIu64, + counters.m_lexical_query_count); + LLDB_LOGF(log, " Number of imports initiated by LLDB : %" PRIu64, + counters.m_lldb_import_count); + LLDB_LOGF(log, " Number of imports conducted by Clang : %" PRIu64, + counters.m_clang_import_count); + LLDB_LOGF(log, " Number of Decls completed : %" PRIu64, + counters.m_decls_completed_count); + LLDB_LOGF(log, " Number of records laid out : %" PRIu64, + counters.m_record_layout_count); } void ClangASTMetrics::DumpCounters(Log *log) { if (!log) return; - log->Printf("== ClangASTMetrics output =="); - log->Printf("-- Global metrics --"); + LLDB_LOGF(log, "== ClangASTMetrics output =="); + LLDB_LOGF(log, "-- Global metrics --"); DumpCounters(log, global_counters); - log->Printf("-- Local metrics --"); + LLDB_LOGF(log, "-- Local metrics --"); DumpCounters(log, local_counters); } @@ -127,14 +127,16 @@ clang::Decl *ClangASTImporter::CopyDecl(clang::ASTContext *dst_ast, user_id = metadata->GetUserID(); if (NamedDecl *named_decl = dyn_cast<NamedDecl>(decl)) - log->Printf(" [ClangASTImporter] WARNING: Failed to import a %s " - "'%s', metadata 0x%" PRIx64, - decl->getDeclKindName(), - named_decl->getNameAsString().c_str(), user_id); + LLDB_LOGF(log, + " [ClangASTImporter] WARNING: Failed to import a %s " + "'%s', metadata 0x%" PRIx64, + decl->getDeclKindName(), + named_decl->getNameAsString().c_str(), user_id); else - log->Printf(" [ClangASTImporter] WARNING: Failed to import a %s, " - "metadata 0x%" PRIx64, - decl->getDeclKindName(), user_id); + LLDB_LOGF(log, + " [ClangASTImporter] WARNING: Failed to import a %s, " + "metadata 0x%" PRIx64, + decl->getDeclKindName(), user_id); } return nullptr; } @@ -211,12 +213,12 @@ private: if (clang::Decl *escaped_child = GetEscapedChild(decl)) { Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_EXPRESSIONS)); - if (log) - log->Printf(" [ClangASTImporter] DeclContextOverride couldn't " - "override (%sDecl*)%p - its child (%sDecl*)%p escapes", - decl->getDeclKindName(), static_cast<void *>(decl), - escaped_child->getDeclKindName(), - static_cast<void *>(escaped_child)); + LLDB_LOGF(log, + " [ClangASTImporter] DeclContextOverride couldn't " + "override (%sDecl*)%p - its child (%sDecl*)%p escapes", + decl->getDeclKindName(), static_cast<void *>(decl), + escaped_child->getDeclKindName(), + static_cast<void *>(escaped_child)); lldbassert(0 && "Couldn't override!"); } @@ -248,40 +250,117 @@ public: } }; -lldb::opaque_compiler_type_t -ClangASTImporter::DeportType(clang::ASTContext *dst_ctx, - clang::ASTContext *src_ctx, - lldb::opaque_compiler_type_t type) { - Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_EXPRESSIONS)); +namespace { +/// Completes all imported TagDecls at the end of the scope. +/// +/// While in a CompleteTagDeclsScope, every decl that could be completed will +/// be completed at the end of the scope (including all Decls that are +/// imported while completing the original Decls). +class CompleteTagDeclsScope : public ClangASTImporter::NewDeclListener { + ClangASTImporter::ImporterDelegateSP m_delegate; + // FIXME: Investigate how many decls we usually have in these sets and + // see if we can use SmallPtrSet instead here. + std::set<NamedDecl *> m_decls_to_complete; + std::set<NamedDecl *> m_decls_already_completed; + clang::ASTContext *m_dst_ctx; + clang::ASTContext *m_src_ctx; + ClangASTImporter &importer; - if (log) - log->Printf(" [ClangASTImporter] DeportType called on (%sType*)0x%llx " - "from (ASTContext*)%p to (ASTContext*)%p", - QualType::getFromOpaquePtr(type)->getTypeClassName(), - (unsigned long long)type, static_cast<void *>(src_ctx), - static_cast<void *>(dst_ctx)); +public: + /// Constructs a CompleteTagDeclsScope. + /// \param importer The ClangASTImporter that we should observe. + /// \param dst_ctx The ASTContext to which Decls are imported. + /// \param src_ctx The ASTContext from which Decls are imported. + explicit CompleteTagDeclsScope(ClangASTImporter &importer, + clang::ASTContext *dst_ctx, + clang::ASTContext *src_ctx) + : m_delegate(importer.GetDelegate(dst_ctx, src_ctx)), m_dst_ctx(dst_ctx), + m_src_ctx(src_ctx), importer(importer) { + m_delegate->SetImportListener(this); + } - ImporterDelegateSP delegate_sp(GetDelegate(dst_ctx, src_ctx)); + virtual ~CompleteTagDeclsScope() { + ClangASTImporter::ASTContextMetadataSP to_context_md = + importer.GetContextMetadata(m_dst_ctx); - if (!delegate_sp) - return nullptr; + // Complete all decls we collected until now. + while (!m_decls_to_complete.empty()) { + NamedDecl *decl = *m_decls_to_complete.begin(); - std::set<NamedDecl *> decls_to_deport; - std::set<NamedDecl *> decls_already_deported; + m_decls_already_completed.insert(decl); + m_decls_to_complete.erase(decl); - DeclContextOverride decl_context_override; + // We should only complete decls coming from the source context. + assert(to_context_md->m_origins[decl].ctx == m_src_ctx); + + Decl *original_decl = to_context_md->m_origins[decl].decl; + + // Complete the decl now. + ClangASTContext::GetCompleteDecl(m_src_ctx, original_decl); + if (auto *tag_decl = dyn_cast<TagDecl>(decl)) { + if (auto *original_tag_decl = dyn_cast<TagDecl>(original_decl)) { + if (original_tag_decl->isCompleteDefinition()) { + m_delegate->ImportDefinitionTo(tag_decl, original_tag_decl); + tag_decl->setCompleteDefinition(true); + } + } + + tag_decl->setHasExternalLexicalStorage(false); + tag_decl->setHasExternalVisibleStorage(false); + } else if (auto *container_decl = dyn_cast<ObjCContainerDecl>(decl)) { + container_decl->setHasExternalLexicalStorage(false); + container_decl->setHasExternalVisibleStorage(false); + } - if (const clang::TagType *tag_type = - clang::QualType::getFromOpaquePtr(type)->getAs<TagType>()) { - decl_context_override.OverrideAllDeclsFromContainingFunction( - tag_type->getDecl()); + to_context_md->m_origins.erase(decl); + } + + // Stop listening to imported decls. We do this after clearing the + // Decls we needed to import to catch all Decls they might have pulled in. + m_delegate->RemoveImportListener(); } - delegate_sp->InitDeportWorkQueues(&decls_to_deport, &decls_already_deported); + void NewDeclImported(clang::Decl *from, clang::Decl *to) override { + // Filter out decls that we can't complete later. + if (!isa<TagDecl>(to) && !isa<ObjCInterfaceDecl>(to)) + return; + RecordDecl *from_record_decl = dyn_cast<RecordDecl>(from); + // We don't need to complete injected class name decls. + if (from_record_decl && from_record_decl->isInjectedClassName()) + return; + + NamedDecl *to_named_decl = dyn_cast<NamedDecl>(to); + // Check if we already completed this type. + if (m_decls_already_completed.count(to_named_decl) != 0) + return; + m_decls_to_complete.insert(to_named_decl); + } +}; +} // namespace + +lldb::opaque_compiler_type_t +ClangASTImporter::DeportType(clang::ASTContext *dst_ctx, + clang::ASTContext *src_ctx, + lldb::opaque_compiler_type_t type) { + Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_EXPRESSIONS)); + + LLDB_LOGF(log, + " [ClangASTImporter] DeportType called on (%sType*)0x%llx " + "from (ASTContext*)%p to (ASTContext*)%p", + QualType::getFromOpaquePtr(type)->getTypeClassName(), + (unsigned long long)type, static_cast<void *>(src_ctx), + static_cast<void *>(dst_ctx)); + + DeclContextOverride decl_context_override; - lldb::opaque_compiler_type_t result = CopyType(dst_ctx, src_ctx, type); + if (auto *t = QualType::getFromOpaquePtr(type)->getAs<TagType>()) + decl_context_override.OverrideAllDeclsFromContainingFunction(t->getDecl()); - delegate_sp->ExecuteDeportWorkQueues(); + lldb::opaque_compiler_type_t result; + { + CompleteTagDeclsScope complete_scope(*this, dst_ctx, src_ctx); + result = CopyType(dst_ctx, src_ctx, type); + } if (!result) return nullptr; @@ -294,38 +373,30 @@ clang::Decl *ClangASTImporter::DeportDecl(clang::ASTContext *dst_ctx, clang::Decl *decl) { Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_EXPRESSIONS)); - if (log) - log->Printf(" [ClangASTImporter] DeportDecl called on (%sDecl*)%p from " - "(ASTContext*)%p to (ASTContext*)%p", - decl->getDeclKindName(), static_cast<void *>(decl), - static_cast<void *>(src_ctx), static_cast<void *>(dst_ctx)); - - ImporterDelegateSP delegate_sp(GetDelegate(dst_ctx, src_ctx)); - - if (!delegate_sp) - return nullptr; - - std::set<NamedDecl *> decls_to_deport; - std::set<NamedDecl *> decls_already_deported; + LLDB_LOGF(log, + " [ClangASTImporter] DeportDecl called on (%sDecl*)%p from " + "(ASTContext*)%p to (ASTContext*)%p", + decl->getDeclKindName(), static_cast<void *>(decl), + static_cast<void *>(src_ctx), static_cast<void *>(dst_ctx)); DeclContextOverride decl_context_override; decl_context_override.OverrideAllDeclsFromContainingFunction(decl); - delegate_sp->InitDeportWorkQueues(&decls_to_deport, &decls_already_deported); - - clang::Decl *result = CopyDecl(dst_ctx, src_ctx, decl); - - delegate_sp->ExecuteDeportWorkQueues(); + clang::Decl *result; + { + CompleteTagDeclsScope complete_scope(*this, dst_ctx, src_ctx); + result = CopyDecl(dst_ctx, src_ctx, decl); + } if (!result) return nullptr; - if (log) - log->Printf( - " [ClangASTImporter] DeportDecl deported (%sDecl*)%p to (%sDecl*)%p", - decl->getDeclKindName(), static_cast<void *>(decl), - result->getDeclKindName(), static_cast<void *>(result)); + LLDB_LOGF( + log, + " [ClangASTImporter] DeportDecl deported (%sDecl*)%p to (%sDecl*)%p", + decl->getDeclKindName(), static_cast<void *>(decl), + result->getDeclKindName(), static_cast<void *>(result)); return result; } @@ -533,9 +604,8 @@ void ClangASTImporter::InsertRecordDecl(clang::RecordDecl *decl, void ClangASTImporter::CompleteDecl(clang::Decl *decl) { Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_EXPRESSIONS)); - if (log) - log->Printf(" [ClangASTImporter] CompleteDecl called on (%sDecl*)%p", - decl->getDeclKindName(), static_cast<void *>(decl)); + LLDB_LOGF(log, " [ClangASTImporter] CompleteDecl called on (%sDecl*)%p", + decl->getDeclKindName(), static_cast<void *>(decl)); if (ObjCInterfaceDecl *interface_decl = dyn_cast<ObjCInterfaceDecl>(decl)) { if (!interface_decl->getDefinition()) { @@ -817,9 +887,9 @@ void ClangASTImporter::BuildNamespaceMap(const clang::NamespaceDecl *decl) { void ClangASTImporter::ForgetDestination(clang::ASTContext *dst_ast) { Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_EXPRESSIONS)); - if (log) - log->Printf(" [ClangASTImporter] Forgetting destination (ASTContext*)%p", - static_cast<void *>(dst_ast)); + LLDB_LOGF(log, + " [ClangASTImporter] Forgetting destination (ASTContext*)%p", + static_cast<void *>(dst_ast)); m_metadata_map.erase(dst_ast); } @@ -830,10 +900,10 @@ void ClangASTImporter::ForgetSource(clang::ASTContext *dst_ast, Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_EXPRESSIONS)); - if (log) - log->Printf(" [ClangASTImporter] Forgetting source->dest " - "(ASTContext*)%p->(ASTContext*)%p", - static_cast<void *>(src_ast), static_cast<void *>(dst_ast)); + LLDB_LOGF(log, + " [ClangASTImporter] Forgetting source->dest " + "(ASTContext*)%p->(ASTContext*)%p", + static_cast<void *>(src_ast), static_cast<void *>(dst_ast)); if (!md) return; @@ -869,63 +939,6 @@ ClangASTImporter::ASTImporterDelegate::ImportImpl(Decl *From) { return ASTImporter::ImportImpl(From); } -void ClangASTImporter::ASTImporterDelegate::InitDeportWorkQueues( - std::set<clang::NamedDecl *> *decls_to_deport, - std::set<clang::NamedDecl *> *decls_already_deported) { - assert(!m_decls_to_deport); - assert(!m_decls_already_deported); - - m_decls_to_deport = decls_to_deport; - m_decls_already_deported = decls_already_deported; -} - -void ClangASTImporter::ASTImporterDelegate::ExecuteDeportWorkQueues() { - assert(m_decls_to_deport); - assert(m_decls_already_deported); - - ASTContextMetadataSP to_context_md = - m_master.GetContextMetadata(&getToContext()); - - while (!m_decls_to_deport->empty()) { - NamedDecl *decl = *m_decls_to_deport->begin(); - - m_decls_already_deported->insert(decl); - m_decls_to_deport->erase(decl); - - DeclOrigin &origin = to_context_md->m_origins[decl]; - UNUSED_IF_ASSERT_DISABLED(origin); - - assert(origin.ctx == - m_source_ctx); // otherwise we should never have added this - // because it doesn't need to be deported - - Decl *original_decl = to_context_md->m_origins[decl].decl; - - ClangASTContext::GetCompleteDecl(m_source_ctx, original_decl); - - if (TagDecl *tag_decl = dyn_cast<TagDecl>(decl)) { - if (TagDecl *original_tag_decl = dyn_cast<TagDecl>(original_decl)) { - if (original_tag_decl->isCompleteDefinition()) { - ImportDefinitionTo(tag_decl, original_tag_decl); - tag_decl->setCompleteDefinition(true); - } - } - - tag_decl->setHasExternalLexicalStorage(false); - tag_decl->setHasExternalVisibleStorage(false); - } else if (ObjCContainerDecl *container_decl = - dyn_cast<ObjCContainerDecl>(decl)) { - container_decl->setHasExternalLexicalStorage(false); - container_decl->setHasExternalVisibleStorage(false); - } - - to_context_md->m_origins.erase(decl); - } - - m_decls_to_deport = nullptr; - m_decls_already_deported = nullptr; -} - void ClangASTImporter::ASTImporterDelegate::ImportDefinitionTo( clang::Decl *to, clang::Decl *from) { ASTImporter::Imported(from, to); @@ -1045,15 +1058,17 @@ void ClangASTImporter::ASTImporterDelegate::Imported(clang::Decl *from, from_named_decl->printName(name_stream); name_stream.flush(); - log->Printf(" [ClangASTImporter] Imported (%sDecl*)%p, named %s (from " - "(Decl*)%p), metadata 0x%" PRIx64, - from->getDeclKindName(), static_cast<void *>(to), - name_string.c_str(), static_cast<void *>(from), user_id); + LLDB_LOGF(log, + " [ClangASTImporter] Imported (%sDecl*)%p, named %s (from " + "(Decl*)%p), metadata 0x%" PRIx64, + from->getDeclKindName(), static_cast<void *>(to), + name_string.c_str(), static_cast<void *>(from), user_id); } else { - log->Printf(" [ClangASTImporter] Imported (%sDecl*)%p (from " - "(Decl*)%p), metadata 0x%" PRIx64, - from->getDeclKindName(), static_cast<void *>(to), - static_cast<void *>(from), user_id); + LLDB_LOGF(log, + " [ClangASTImporter] Imported (%sDecl*)%p (from " + "(Decl*)%p), metadata 0x%" PRIx64, + from->getDeclKindName(), static_cast<void *>(to), + static_cast<void *>(from), user_id); } } @@ -1080,37 +1095,27 @@ void ClangASTImporter::ASTImporterDelegate::Imported(clang::Decl *from, if (direct_completer.get() != this) direct_completer->ASTImporter::Imported(origin_iter->second.decl, to); - if (log) - log->Printf(" [ClangASTImporter] Propagated origin " - "(Decl*)%p/(ASTContext*)%p from (ASTContext*)%p to " - "(ASTContext*)%p", - static_cast<void *>(origin_iter->second.decl), - static_cast<void *>(origin_iter->second.ctx), - static_cast<void *>(&from->getASTContext()), - static_cast<void *>(&to->getASTContext())); + LLDB_LOGF(log, + " [ClangASTImporter] Propagated origin " + "(Decl*)%p/(ASTContext*)%p from (ASTContext*)%p to " + "(ASTContext*)%p", + static_cast<void *>(origin_iter->second.decl), + static_cast<void *>(origin_iter->second.ctx), + static_cast<void *>(&from->getASTContext()), + static_cast<void *>(&to->getASTContext())); } else { - if (m_decls_to_deport && m_decls_already_deported) { - if (isa<TagDecl>(to) || isa<ObjCInterfaceDecl>(to)) { - RecordDecl *from_record_decl = dyn_cast<RecordDecl>(from); - if (from_record_decl == nullptr || - !from_record_decl->isInjectedClassName()) { - NamedDecl *to_named_decl = dyn_cast<NamedDecl>(to); - - if (!m_decls_already_deported->count(to_named_decl)) - m_decls_to_deport->insert(to_named_decl); - } - } - } + if (m_new_decl_listener) + m_new_decl_listener->NewDeclImported(from, to); if (to_context_md->m_origins.find(to) == to_context_md->m_origins.end() || user_id != LLDB_INVALID_UID) { to_context_md->m_origins[to] = DeclOrigin(m_source_ctx, from); } - if (log) - log->Printf(" [ClangASTImporter] Decl has no origin information in " - "(ASTContext*)%p", - static_cast<void *>(&from->getASTContext())); + LLDB_LOGF(log, + " [ClangASTImporter] Decl has no origin information in " + "(ASTContext*)%p", + static_cast<void *>(&from->getASTContext())); } if (clang::NamespaceDecl *to_namespace = @@ -1130,11 +1135,11 @@ void ClangASTImporter::ASTImporterDelegate::Imported(clang::Decl *from, } else { to_context_md->m_origins[to] = DeclOrigin(m_source_ctx, from); - if (log) - log->Printf(" [ClangASTImporter] Sourced origin " - "(Decl*)%p/(ASTContext*)%p into (ASTContext*)%p", - static_cast<void *>(from), static_cast<void *>(m_source_ctx), - static_cast<void *>(&to->getASTContext())); + LLDB_LOGF(log, + " [ClangASTImporter] Sourced origin " + "(Decl*)%p/(ASTContext*)%p into (ASTContext*)%p", + static_cast<void *>(from), static_cast<void *>(m_source_ctx), + static_cast<void *>(&to->getASTContext())); } if (TagDecl *from_tag_decl = dyn_cast<TagDecl>(from)) { @@ -1143,13 +1148,13 @@ void ClangASTImporter::ASTImporterDelegate::Imported(clang::Decl *from, to_tag_decl->setHasExternalLexicalStorage(); to_tag_decl->getPrimaryContext()->setMustBuildLookupTable(); - if (log) - log->Printf( - " [ClangASTImporter] To is a TagDecl - attributes %s%s [%s->%s]", - (to_tag_decl->hasExternalLexicalStorage() ? " Lexical" : ""), - (to_tag_decl->hasExternalVisibleStorage() ? " Visible" : ""), - (from_tag_decl->isCompleteDefinition() ? "complete" : "incomplete"), - (to_tag_decl->isCompleteDefinition() ? "complete" : "incomplete")); + LLDB_LOGF( + log, + " [ClangASTImporter] To is a TagDecl - attributes %s%s [%s->%s]", + (to_tag_decl->hasExternalLexicalStorage() ? " Lexical" : ""), + (to_tag_decl->hasExternalVisibleStorage() ? " Visible" : ""), + (from_tag_decl->isCompleteDefinition() ? "complete" : "incomplete"), + (to_tag_decl->isCompleteDefinition() ? "complete" : "incomplete")); } if (isa<NamespaceDecl>(from)) { @@ -1171,15 +1176,16 @@ void ClangASTImporter::ASTImporterDelegate::Imported(clang::Decl *from, if (log) { if (ObjCInterfaceDecl *to_interface_decl = llvm::dyn_cast<ObjCInterfaceDecl>(to_container_decl)) { - log->Printf( + LLDB_LOGF( + log, " [ClangASTImporter] To is an ObjCInterfaceDecl - attributes " "%s%s%s", (to_interface_decl->hasExternalLexicalStorage() ? " Lexical" : ""), (to_interface_decl->hasExternalVisibleStorage() ? " Visible" : ""), (to_interface_decl->hasDefinition() ? " HasDefinition" : "")); } else { - log->Printf( - " [ClangASTImporter] To is an %sDecl - attributes %s%s", + LLDB_LOGF( + log, " [ClangASTImporter] To is an %sDecl - attributes %s%s", ((Decl *)to_container_decl)->getDeclKindName(), (to_container_decl->hasExternalLexicalStorage() ? " Lexical" : ""), (to_container_decl->hasExternalVisibleStorage() ? " Visible" : "")); diff --git a/source/Symbol/CompactUnwindInfo.cpp b/source/Symbol/CompactUnwindInfo.cpp index 3a2a4d3a09e6..3eee7f785f36 100644 --- a/source/Symbol/CompactUnwindInfo.cpp +++ b/source/Symbol/CompactUnwindInfo.cpp @@ -190,8 +190,8 @@ bool CompactUnwindInfo::GetUnwindPlan(Target &target, Address addr, Address::DumpStyle::DumpStyleResolvedDescriptionNoFunctionArguments, Address::DumpStyle::DumpStyleFileAddress, arch.GetAddressByteSize()); - log->Printf("Got compact unwind encoding 0x%x for function %s", - function_info.encoding, strm.GetData()); + LLDB_LOGF(log, "Got compact unwind encoding 0x%x for function %s", + function_info.encoding, strm.GetData()); } if (function_info.valid_range_offset_start != 0 && @@ -213,7 +213,8 @@ bool CompactUnwindInfo::GetUnwindPlan(Target &target, Address addr, return CreateUnwindPlan_x86_64(target, function_info, unwind_plan, addr); } - if (arch.GetTriple().getArch() == llvm::Triple::aarch64) { + if (arch.GetTriple().getArch() == llvm::Triple::aarch64 || + arch.GetTriple().getArch() == llvm::Triple::aarch64_32) { return CreateUnwindPlan_arm64(target, function_info, unwind_plan, addr); } if (arch.GetTriple().getArch() == llvm::Triple::x86) { @@ -737,6 +738,7 @@ bool CompactUnwindInfo::CreateUnwindPlan_x86_64(Target &target, unwind_plan.SetSourceName("compact unwind info"); unwind_plan.SetSourcedFromCompiler(eLazyBoolYes); unwind_plan.SetUnwindPlanValidAtAllInstructions(eLazyBoolNo); + unwind_plan.SetUnwindPlanForSignalTrap(eLazyBoolNo); unwind_plan.SetRegisterKind(eRegisterKindEHFrame); unwind_plan.SetLSDAAddress(function_info.lsda_address); @@ -1008,6 +1010,7 @@ bool CompactUnwindInfo::CreateUnwindPlan_i386(Target &target, unwind_plan.SetSourceName("compact unwind info"); unwind_plan.SetSourcedFromCompiler(eLazyBoolYes); unwind_plan.SetUnwindPlanValidAtAllInstructions(eLazyBoolNo); + unwind_plan.SetUnwindPlanForSignalTrap(eLazyBoolNo); unwind_plan.SetRegisterKind(eRegisterKindEHFrame); unwind_plan.SetLSDAAddress(function_info.lsda_address); @@ -1304,6 +1307,7 @@ bool CompactUnwindInfo::CreateUnwindPlan_arm64(Target &target, unwind_plan.SetSourceName("compact unwind info"); unwind_plan.SetSourcedFromCompiler(eLazyBoolYes); unwind_plan.SetUnwindPlanValidAtAllInstructions(eLazyBoolNo); + unwind_plan.SetUnwindPlanForSignalTrap(eLazyBoolNo); unwind_plan.SetRegisterKind(eRegisterKindEHFrame); unwind_plan.SetLSDAAddress(function_info.lsda_address); @@ -1437,6 +1441,7 @@ bool CompactUnwindInfo::CreateUnwindPlan_armv7(Target &target, unwind_plan.SetSourceName("compact unwind info"); unwind_plan.SetSourcedFromCompiler(eLazyBoolYes); unwind_plan.SetUnwindPlanValidAtAllInstructions(eLazyBoolNo); + unwind_plan.SetUnwindPlanForSignalTrap(eLazyBoolNo); unwind_plan.SetRegisterKind(eRegisterKindEHFrame); unwind_plan.SetLSDAAddress(function_info.lsda_address); diff --git a/source/Symbol/CompileUnit.cpp b/source/Symbol/CompileUnit.cpp index 5fb9b6b9f729..41086d2df3df 100644 --- a/source/Symbol/CompileUnit.cpp +++ b/source/Symbol/CompileUnit.cpp @@ -9,7 +9,7 @@ #include "lldb/Symbol/CompileUnit.h" #include "lldb/Core/Module.h" #include "lldb/Symbol/LineTable.h" -#include "lldb/Symbol/SymbolVendor.h" +#include "lldb/Symbol/SymbolFile.h" #include "lldb/Symbol/VariableList.h" #include "lldb/Target/Language.h" @@ -119,49 +119,6 @@ void CompileUnit::AddFunction(FunctionSP &funcSP) { m_functions_by_uid[funcSP->GetID()] = funcSP; } -// Find functions using the Mangled::Tokens token list. This function currently -// implements an interactive approach designed to find all instances of certain -// functions. It isn't designed to the quickest way to lookup functions as it -// will need to iterate through all functions and see if they match, though it -// does provide a powerful and context sensitive way to search for all -// functions with a certain name, all functions in a namespace, or all -// functions of a template type. See Mangled::Tokens::Parse() comments for more -// information. -// -// The function prototype will need to change to return a list of results. It -// was originally used to help debug the Mangled class and the -// Mangled::Tokens::MatchesQuery() function and it currently will print out a -// list of matching results for the functions that are currently in this -// compile unit. -// -// A FindFunctions method should be called prior to this that takes -// a regular function name (const char * or ConstString as a parameter) before -// resorting to this slower but more complete function. The other FindFunctions -// method should be able to take advantage of any accelerator tables available -// in the debug information (which is parsed by the SymbolFile parser plug-ins -// and registered with each Module). -// void -// CompileUnit::FindFunctions(const Mangled::Tokens& tokens) -//{ -// if (!m_functions.empty()) -// { -// Stream s(stdout); -// std::vector<FunctionSP>::const_iterator pos; -// std::vector<FunctionSP>::const_iterator end = m_functions.end(); -// for (pos = m_functions.begin(); pos != end; ++pos) -// { -// const ConstString& demangled = (*pos)->Mangled().Demangled(); -// if (demangled) -// { -// const Mangled::Tokens& func_tokens = -// (*pos)->Mangled().GetTokens(); -// if (func_tokens.MatchesQuery (tokens)) -// s << "demangled MATCH found: " << demangled << "\n"; -// } -// } -// } -//} - FunctionSP CompileUnit::FindFunctionByUID(lldb::user_id_t func_uid) { auto it = m_functions_by_uid.find(func_uid); if (it == m_functions_by_uid.end()) @@ -173,10 +130,8 @@ lldb::LanguageType CompileUnit::GetLanguage() { if (m_language == eLanguageTypeUnknown) { if (m_flags.IsClear(flagsParsedLanguage)) { m_flags.Set(flagsParsedLanguage); - SymbolVendor *symbol_vendor = GetModule()->GetSymbolVendor(); - if (symbol_vendor) { - m_language = symbol_vendor->ParseLanguage(*this); - } + if (SymbolFile *symfile = GetModule()->GetSymbolFile()) + m_language = symfile->ParseLanguage(*this); } } return m_language; @@ -186,9 +141,8 @@ LineTable *CompileUnit::GetLineTable() { if (m_line_table_up == nullptr) { if (m_flags.IsClear(flagsParsedLineTable)) { m_flags.Set(flagsParsedLineTable); - SymbolVendor *symbol_vendor = GetModule()->GetSymbolVendor(); - if (symbol_vendor) - symbol_vendor->ParseLineTable(*this); + if (SymbolFile *symfile = GetModule()->GetSymbolFile()) + symfile->ParseLineTable(*this); } } return m_line_table_up.get(); @@ -202,14 +156,16 @@ void CompileUnit::SetLineTable(LineTable *line_table) { m_line_table_up.reset(line_table); } +void CompileUnit::SetSupportFiles(const FileSpecList &support_files) { + m_support_files = support_files; +} + DebugMacros *CompileUnit::GetDebugMacros() { if (m_debug_macros_sp.get() == nullptr) { if (m_flags.IsClear(flagsParsedDebugMacros)) { m_flags.Set(flagsParsedDebugMacros); - SymbolVendor *symbol_vendor = GetModule()->GetSymbolVendor(); - if (symbol_vendor) { - symbol_vendor->ParseDebugMacros(*this); - } + if (SymbolFile *symfile = GetModule()->GetSymbolFile()) + symfile->ParseDebugMacros(*this); } } @@ -229,7 +185,7 @@ VariableListSP CompileUnit::GetVariableList(bool can_create) { SymbolContext sc; CalculateSymbolContext(&sc); assert(sc.module_sp); - sc.module_sp->GetSymbolVendor()->ParseVariablesForContext(sc); + sc.module_sp->GetSymbolFile()->ParseVariablesForContext(sc); } return m_variables; @@ -372,8 +328,8 @@ uint32_t CompileUnit::ResolveSymbolContext(const FileSpec &file_spec, bool CompileUnit::GetIsOptimized() { if (m_is_optimized == eLazyBoolCalculate) { m_is_optimized = eLazyBoolNo; - if (SymbolVendor *symbol_vendor = GetModule()->GetSymbolVendor()) { - if (symbol_vendor->ParseIsOptimized(*this)) + if (SymbolFile *symfile = GetModule()->GetSymbolFile()) { + if (symfile->ParseIsOptimized(*this)) m_is_optimized = eLazyBoolYes; } } @@ -388,23 +344,26 @@ const std::vector<SourceModule> &CompileUnit::GetImportedModules() { if (m_imported_modules.empty() && m_flags.IsClear(flagsParsedImportedModules)) { m_flags.Set(flagsParsedImportedModules); - if (SymbolVendor *symbol_vendor = GetModule()->GetSymbolVendor()) { + if (SymbolFile *symfile = GetModule()->GetSymbolFile()) { SymbolContext sc; CalculateSymbolContext(&sc); - symbol_vendor->ParseImportedModules(sc, m_imported_modules); + symfile->ParseImportedModules(sc, m_imported_modules); } } return m_imported_modules; } +void CompileUnit::ForEachExternalModule(llvm::function_ref<void(ModuleSP)> f) { + if (SymbolFile *symfile = GetModule()->GetSymbolFile()) + symfile->ForEachExternalModule(*this, f); +} + const FileSpecList &CompileUnit::GetSupportFiles() { if (m_support_files.GetSize() == 0) { if (m_flags.IsClear(flagsParsedSupportFiles)) { m_flags.Set(flagsParsedSupportFiles); - SymbolVendor *symbol_vendor = GetModule()->GetSymbolVendor(); - if (symbol_vendor) { - symbol_vendor->ParseSupportFiles(*this, m_support_files); - } + if (SymbolFile *symfile = GetModule()->GetSymbolFile()) + symfile->ParseSupportFiles(*this, m_support_files); } } return m_support_files; diff --git a/source/Symbol/CompilerType.cpp b/source/Symbol/CompilerType.cpp index bb9a1a642e42..571a8570a43b 100644 --- a/source/Symbol/CompilerType.cpp +++ b/source/Symbol/CompilerType.cpp @@ -10,8 +10,6 @@ #include "lldb/Core/Debugger.h" #include "lldb/Core/StreamFile.h" -#include "lldb/Symbol/ClangASTContext.h" -#include "lldb/Symbol/ClangExternalASTSourceCommon.h" #include "lldb/Symbol/Type.h" #include "lldb/Target/ExecutionContext.h" #include "lldb/Target/Process.h" @@ -32,13 +30,6 @@ CompilerType::CompilerType(TypeSystem *type_system, lldb::opaque_compiler_type_t type) : m_type(type), m_type_system(type_system) {} -CompilerType::CompilerType(clang::ASTContext *ast, clang::QualType qual_type) - : m_type(qual_type.getAsOpaquePtr()), - m_type_system(ClangASTContext::GetASTContext(ast)) { - if (m_type) - assert(m_type_system != nullptr); -} - CompilerType::~CompilerType() {} // Tests @@ -333,12 +324,6 @@ void CompilerType::SetCompilerType(TypeSystem *type_system, m_type = type; } -void CompilerType::SetCompilerType(clang::ASTContext *ast, - clang::QualType qual_type) { - m_type_system = ClangASTContext::GetASTContext(ast); - m_type = qual_type.getAsOpaquePtr(); -} - unsigned CompilerType::GetTypeQualifiers() const { if (IsValid()) return m_type_system->GetTypeQualifiers(m_type); @@ -503,10 +488,10 @@ CompilerType::GetByteSize(ExecutionContextScope *exe_scope) const { return {}; } -size_t CompilerType::GetTypeBitAlign() const { +llvm::Optional<size_t> CompilerType::GetTypeBitAlign(ExecutionContextScope *exe_scope) const { if (IsValid()) - return m_type_system->GetTypeBitAlign(m_type); - return 0; + return m_type_system->GetTypeBitAlign(m_type, exe_scope); + return {}; } lldb::Encoding CompilerType::GetEncoding(uint64_t &count) const { @@ -729,13 +714,6 @@ CompilerType::GetIndexOfChildWithName(const char *name, return UINT32_MAX; } -size_t CompilerType::ConvertStringToFloatValue(const char *s, uint8_t *dst, - size_t dst_size) const { - if (IsValid()) - return m_type_system->ConvertStringToFloatValue(m_type, s, dst, dst_size); - return 0; -} - // Dumping types #define DEPTH_INCREMENT 2 diff --git a/source/Symbol/CxxModuleHandler.cpp b/source/Symbol/CxxModuleHandler.cpp index 68a2aab80bd6..19e80e5036bc 100644 --- a/source/Symbol/CxxModuleHandler.cpp +++ b/source/Symbol/CxxModuleHandler.cpp @@ -175,6 +175,8 @@ T *createDecl(ASTImporter &importer, Decl *from_d, Args &&... args) { } llvm::Optional<Decl *> CxxModuleHandler::tryInstantiateStdTemplate(Decl *d) { + Log *log = lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_EXPRESSIONS); + // If we don't have a template to instiantiate, then there is nothing to do. auto td = dyn_cast<ClassTemplateSpecializationDecl>(d); if (!td) @@ -196,9 +198,15 @@ llvm::Optional<Decl *> CxxModuleHandler::tryInstantiateStdTemplate(Decl *d) { // Find the local DeclContext that corresponds to the DeclContext of our // decl we want to import. - auto to_context = getEqualLocalDeclContext(*m_sema, td->getDeclContext()); - if (!to_context) + llvm::Expected<DeclContext *> to_context = + getEqualLocalDeclContext(*m_sema, td->getDeclContext()); + if (!to_context) { + LLDB_LOG_ERROR(log, to_context.takeError(), + "Got error while searching equal local DeclContext for decl " + "'{1}':\n{0}", + td->getName()); return {}; + } // Look up the template in our local context. std::unique_ptr<LookupResult> lookup = @@ -215,8 +223,6 @@ llvm::Optional<Decl *> CxxModuleHandler::tryInstantiateStdTemplate(Decl *d) { // Import the foreign template arguments. llvm::SmallVector<TemplateArgument, 4> imported_args; - Log *log = lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_EXPRESSIONS); - // If this logic is changed, also update templateArgsAreSupported. for (const TemplateArgument &arg : foreign_args.asArray()) { switch (arg.getKind()) { diff --git a/source/Symbol/DWARFCallFrameInfo.cpp b/source/Symbol/DWARFCallFrameInfo.cpp index 0ab9fa4b7bbd..b4e74e9a2898 100644 --- a/source/Symbol/DWARFCallFrameInfo.cpp +++ b/source/Symbol/DWARFCallFrameInfo.cpp @@ -19,6 +19,7 @@ #include "lldb/Utility/Log.h" #include "lldb/Utility/Timer.h" #include <list> +#include <cstring> using namespace lldb; using namespace lldb_private; @@ -601,6 +602,9 @@ bool DWARFCallFrameInfo::FDEToUnwindPlan(dw_offset_t dwarf_offset, } offset += aug_data_len; } + unwind_plan.SetUnwindPlanForSignalTrap( + strchr(cie->augmentation, 'S') ? eLazyBoolYes : eLazyBoolNo); + Address lsda_data; Address personality_function_ptr; @@ -769,13 +773,12 @@ bool DWARFCallFrameInfo::FDEToUnwindPlan(dw_offset_t dwarf_offset, // useful for compilers that move epilogue code into the body of a // function.) if (stack.empty()) { - if (log) - log->Printf("DWARFCallFrameInfo::%s(dwarf_offset: %" PRIx32 - ", startaddr: %" PRIx64 - " encountered DW_CFA_restore_state but state stack " - "is empty. Corrupt unwind info?", - __FUNCTION__, dwarf_offset, - startaddr.GetFileAddress()); + LLDB_LOGF(log, + "DWARFCallFrameInfo::%s(dwarf_offset: %" PRIx32 + ", startaddr: %" PRIx64 + " encountered DW_CFA_restore_state but state stack " + "is empty. Corrupt unwind info?", + __FUNCTION__, dwarf_offset, startaddr.GetFileAddress()); break; } lldb::addr_t offset = row->GetOffset(); diff --git a/source/Symbol/DeclVendor.cpp b/source/Symbol/DeclVendor.cpp index 0a912a2fd214..9ccf422e3bea 100644 --- a/source/Symbol/DeclVendor.cpp +++ b/source/Symbol/DeclVendor.cpp @@ -7,8 +7,8 @@ //===----------------------------------------------------------------------===// #include "lldb/Symbol/DeclVendor.h" - -#include "lldb/Symbol/ClangASTContext.h" +#include "lldb/Symbol/CompilerDecl.h" +#include "lldb/Symbol/TypeSystem.h" #include <vector> @@ -20,10 +20,11 @@ std::vector<CompilerType> DeclVendor::FindTypes(ConstString name, // FIXME: This depends on clang, but should be able to support any // TypeSystem. std::vector<CompilerType> ret; - std::vector<clang::NamedDecl *> decls; + std::vector<CompilerDecl> decls; if (FindDecls(name, /*append*/ true, max_matches, decls)) - for (auto *decl : decls) - if (auto type = ClangASTContext::GetTypeForDecl(decl)) + for (auto decl : decls) + if (auto type = + decl.GetTypeSystem()->GetTypeForDecl(decl.GetOpaqueDecl())) ret.push_back(type); return ret; } diff --git a/source/Symbol/FuncUnwinders.cpp b/source/Symbol/FuncUnwinders.cpp index 09cb9b00aaf3..f609bf7821e1 100644 --- a/source/Symbol/FuncUnwinders.cpp +++ b/source/Symbol/FuncUnwinders.cpp @@ -10,6 +10,7 @@ #include "lldb/Core/Address.h" #include "lldb/Core/AddressRange.h" #include "lldb/Symbol/ArmUnwindInfo.h" +#include "lldb/Symbol/CallFrameInfo.h" #include "lldb/Symbol/CompactUnwindInfo.h" #include "lldb/Symbol/DWARFCallFrameInfo.h" #include "lldb/Symbol/ObjectFile.h" @@ -58,6 +59,8 @@ UnwindPlanSP FuncUnwinders::GetUnwindPlanAtCallSite(Target &target, Thread &thread) { std::lock_guard<std::recursive_mutex> guard(m_mutex); + if (UnwindPlanSP plan_sp = GetObjectFileUnwindPlan(target)) + return plan_sp; if (UnwindPlanSP plan_sp = GetSymbolFileUnwindPlan(thread)) return plan_sp; if (UnwindPlanSP plan_sp = GetDebugFrameUnwindPlan(target)) @@ -97,6 +100,26 @@ UnwindPlanSP FuncUnwinders::GetCompactUnwindUnwindPlan(Target &target) { return UnwindPlanSP(); } +lldb::UnwindPlanSP FuncUnwinders::GetObjectFileUnwindPlan(Target &target) { + std::lock_guard<std::recursive_mutex> guard(m_mutex); + if (m_unwind_plan_object_file_sp.get() || + m_tried_unwind_plan_object_file) + return m_unwind_plan_object_file_sp; + + m_tried_unwind_plan_object_file = true; + if (m_range.GetBaseAddress().IsValid()) { + CallFrameInfo *object_file_frame = m_unwind_table.GetObjectFileUnwindInfo(); + if (object_file_frame) { + m_unwind_plan_object_file_sp = + std::make_shared<UnwindPlan>(lldb::eRegisterKindGeneric); + if (!object_file_frame->GetUnwindPlan(m_range, + *m_unwind_plan_object_file_sp)) + m_unwind_plan_object_file_sp.reset(); + } + } + return m_unwind_plan_object_file_sp; +} + UnwindPlanSP FuncUnwinders::GetEHFrameUnwindPlan(Target &target) { std::lock_guard<std::recursive_mutex> guard(m_mutex); if (m_unwind_plan_eh_frame_sp.get() || m_tried_unwind_plan_eh_frame) @@ -185,6 +208,38 @@ UnwindPlanSP FuncUnwinders::GetSymbolFileUnwindPlan(Thread &thread) { return m_unwind_plan_symbol_file_sp; } +UnwindPlanSP +FuncUnwinders::GetObjectFileAugmentedUnwindPlan(Target &target, + Thread &thread) { + std::lock_guard<std::recursive_mutex> guard(m_mutex); + if (m_unwind_plan_object_file_augmented_sp.get() || + m_tried_unwind_plan_object_file_augmented) + return m_unwind_plan_object_file_augmented_sp; + + m_tried_unwind_plan_object_file_augmented = true; + + UnwindPlanSP object_file_unwind_plan = GetObjectFileUnwindPlan(target); + if (!object_file_unwind_plan) + return m_unwind_plan_object_file_augmented_sp; + + m_unwind_plan_object_file_augmented_sp = + std::make_shared<UnwindPlan>(*object_file_unwind_plan); + + // Augment the instructions with epilogue descriptions if necessary + // so the UnwindPlan can be used at any instruction in the function. + + UnwindAssemblySP assembly_profiler_sp(GetUnwindAssemblyProfiler(target)); + if (assembly_profiler_sp) { + if (!assembly_profiler_sp->AugmentUnwindPlanFromCallSite( + m_range, thread, *m_unwind_plan_object_file_augmented_sp)) { + m_unwind_plan_object_file_augmented_sp.reset(); + } + } else { + m_unwind_plan_object_file_augmented_sp.reset(); + } + return m_unwind_plan_object_file_augmented_sp; +} + UnwindPlanSP FuncUnwinders::GetEHFrameAugmentedUnwindPlan(Target &target, Thread &thread) { std::lock_guard<std::recursive_mutex> guard(m_mutex); @@ -328,6 +383,8 @@ UnwindPlanSP FuncUnwinders::GetUnwindPlanAtNonCallSite(Target &target, UnwindPlanSP eh_frame_sp = GetEHFrameUnwindPlan(target); if (!eh_frame_sp) eh_frame_sp = GetDebugFrameUnwindPlan(target); + if (!eh_frame_sp) + eh_frame_sp = GetObjectFileUnwindPlan(target); UnwindPlanSP arch_default_at_entry_sp = GetUnwindPlanArchitectureDefaultAtFunctionEntry(thread); UnwindPlanSP arch_default_sp = GetUnwindPlanArchitectureDefault(thread); @@ -366,6 +423,8 @@ UnwindPlanSP FuncUnwinders::GetUnwindPlanAtNonCallSite(Target &target, return plan_sp; if (UnwindPlanSP plan_sp = GetEHFrameAugmentedUnwindPlan(target, thread)) return plan_sp; + if (UnwindPlanSP plan_sp = GetObjectFileAugmentedUnwindPlan(target, thread)) + return plan_sp; return assembly_sp; } @@ -473,6 +532,9 @@ Address FuncUnwinders::GetLSDAAddress(Target &target) { if (unwind_plan_sp.get() == nullptr) { unwind_plan_sp = GetCompactUnwindUnwindPlan(target); } + if (unwind_plan_sp.get() == nullptr) { + unwind_plan_sp = GetObjectFileUnwindPlan(target); + } if (unwind_plan_sp.get() && unwind_plan_sp->GetLSDAAddress().IsValid()) { lsda_addr = unwind_plan_sp->GetLSDAAddress(); } @@ -486,6 +548,9 @@ Address FuncUnwinders::GetPersonalityRoutinePtrAddress(Target &target) { if (unwind_plan_sp.get() == nullptr) { unwind_plan_sp = GetCompactUnwindUnwindPlan(target); } + if (unwind_plan_sp.get() == nullptr) { + unwind_plan_sp = GetObjectFileUnwindPlan(target); + } if (unwind_plan_sp.get() && unwind_plan_sp->GetPersonalityFunctionPtr().IsValid()) { personality_addr = unwind_plan_sp->GetPersonalityFunctionPtr(); diff --git a/source/Symbol/Function.cpp b/source/Symbol/Function.cpp index 951392c1f1bf..a4c2d3b4b44a 100644 --- a/source/Symbol/Function.cpp +++ b/source/Symbol/Function.cpp @@ -16,7 +16,6 @@ #include "lldb/Symbol/CompilerType.h" #include "lldb/Symbol/LineTable.h" #include "lldb/Symbol/SymbolFile.h" -#include "lldb/Symbol/SymbolVendor.h" #include "lldb/Target/Language.h" #include "lldb/Utility/Log.h" #include "llvm/Support/Casting.h" @@ -60,10 +59,11 @@ size_t FunctionInfo::MemorySize() const { return m_name.MemorySize() + m_declaration.MemorySize(); } -InlineFunctionInfo::InlineFunctionInfo(const char *name, const char *mangled, +InlineFunctionInfo::InlineFunctionInfo(const char *name, + llvm::StringRef mangled, const Declaration *decl_ptr, const Declaration *call_decl_ptr) - : FunctionInfo(name, decl_ptr), m_mangled(ConstString(mangled), true), + : FunctionInfo(name, decl_ptr), m_mangled(mangled), m_call_decl(call_decl_ptr) {} InlineFunctionInfo::InlineFunctionInfo(ConstString name, @@ -128,11 +128,16 @@ size_t InlineFunctionInfo::MemorySize() const { } // -CallEdge::CallEdge(const char *symbol_name, lldb::addr_t return_pc) - : return_pc(return_pc), resolved(false) { +CallEdge::CallEdge(const char *symbol_name, lldb::addr_t return_pc, + CallSiteParameterArray parameters) + : return_pc(return_pc), parameters(std::move(parameters)), resolved(false) { lazy_callee.symbol_name = symbol_name; } +llvm::ArrayRef<CallSiteParameter> CallEdge::GetCallSiteParameters() const { + return parameters; +} + void CallEdge::ParseSymbolFileAndResolve(ModuleList &images) { if (resolved) return; @@ -144,8 +149,8 @@ void CallEdge::ParseSymbolFileAndResolve(ModuleList &images) { auto resolve_lazy_callee = [&]() -> Function * { ConstString callee_name{lazy_callee.symbol_name}; SymbolContextList sc_list; - size_t num_matches = - images.FindFunctionSymbols(callee_name, eFunctionNameTypeAuto, sc_list); + images.FindFunctionSymbols(callee_name, eFunctionNameTypeAuto, sc_list); + size_t num_matches = sc_list.GetSize(); if (num_matches == 0 || !sc_list[0].symbol) { LLDB_LOG(log, "CallEdge: Found no symbols for {0}, cannot resolve it", callee_name); @@ -169,6 +174,7 @@ void CallEdge::ParseSymbolFileAndResolve(ModuleList &images) { Function *CallEdge::GetCallee(ModuleList &images) { ParseSymbolFileAndResolve(images); + assert(resolved && "Did not resolve lazy callee"); return lazy_callee.def; } @@ -277,11 +283,25 @@ llvm::MutableArrayRef<CallEdge> Function::GetTailCallingEdges() { }); } +CallEdge *Function::GetCallEdgeForReturnAddress(addr_t return_pc, + Target &target) { + auto edges = GetCallEdges(); + auto edge_it = + std::lower_bound(edges.begin(), edges.end(), return_pc, + [&](const CallEdge &edge, addr_t pc) { + return edge.GetReturnPCAddress(*this, target) < pc; + }); + if (edge_it == edges.end() || + edge_it->GetReturnPCAddress(*this, target) != return_pc) + return nullptr; + return &const_cast<CallEdge &>(*edge_it); +} + Block &Function::GetBlock(bool can_create) { if (!m_block.BlockInfoHasBeenParsed() && can_create) { ModuleSP module_sp = CalculateSymbolContextModule(); if (module_sp) { - module_sp->GetSymbolVendor()->ParseBlocksRecursive(*this); + module_sp->GetSymbolFile()->ParseBlocksRecursive(*this); } else { Host::SystemLog(Host::eSystemLogError, "error: unable to find module " @@ -428,14 +448,8 @@ CompilerDeclContext Function::GetDeclContext() { ModuleSP module_sp = CalculateSymbolContextModule(); if (module_sp) { - SymbolVendor *sym_vendor = module_sp->GetSymbolVendor(); - - if (sym_vendor) { - SymbolFile *sym_file = sym_vendor->GetSymbolFile(); - - if (sym_file) - return sym_file->GetDeclContextForUID(GetID()); - } + if (SymbolFile *sym_file = module_sp->GetSymbolFile()) + return sym_file->GetDeclContextForUID(GetID()); } return CompilerDeclContext(); } @@ -449,12 +463,7 @@ Type *Function::GetType() { if (!sc.module_sp) return nullptr; - SymbolVendor *sym_vendor = sc.module_sp->GetSymbolVendor(); - - if (sym_vendor == nullptr) - return nullptr; - - SymbolFile *sym_file = sym_vendor->GetSymbolFile(); + SymbolFile *sym_file = sc.module_sp->GetSymbolFile(); if (sym_file == nullptr) return nullptr; diff --git a/source/Symbol/LineTable.cpp b/source/Symbol/LineTable.cpp index 8d4d72c9a2a2..1433dc156d91 100644 --- a/source/Symbol/LineTable.cpp +++ b/source/Symbol/LineTable.cpp @@ -241,33 +241,47 @@ bool LineTable::FindLineEntryByAddress(const Address &so_addr, bool LineTable::ConvertEntryAtIndexToLineEntry(uint32_t idx, LineEntry &line_entry) { - if (idx < m_entries.size()) { - const Entry &entry = m_entries[idx]; - ModuleSP module_sp(m_comp_unit->GetModule()); - if (module_sp && - module_sp->ResolveFileAddress(entry.file_addr, - line_entry.range.GetBaseAddress())) { - if (!entry.is_terminal_entry && idx + 1 < m_entries.size()) - line_entry.range.SetByteSize(m_entries[idx + 1].file_addr - - entry.file_addr); - else - line_entry.range.SetByteSize(0); - - line_entry.file = - m_comp_unit->GetSupportFiles().GetFileSpecAtIndex(entry.file_idx); - line_entry.original_file = - m_comp_unit->GetSupportFiles().GetFileSpecAtIndex(entry.file_idx); - line_entry.line = entry.line; - line_entry.column = entry.column; - line_entry.is_start_of_statement = entry.is_start_of_statement; - line_entry.is_start_of_basic_block = entry.is_start_of_basic_block; - line_entry.is_prologue_end = entry.is_prologue_end; - line_entry.is_epilogue_begin = entry.is_epilogue_begin; - line_entry.is_terminal_entry = entry.is_terminal_entry; - return true; - } - } - return false; + if (idx >= m_entries.size()) + return false; + + const Entry &entry = m_entries[idx]; + ModuleSP module_sp(m_comp_unit->GetModule()); + if (!module_sp) + return false; + + addr_t file_addr = entry.file_addr; + + // A terminal entry can point outside of a module or a section. Decrement the + // address to ensure it resolves correctly. + if (entry.is_terminal_entry) + --file_addr; + + if (!module_sp->ResolveFileAddress(file_addr, + line_entry.range.GetBaseAddress())) + return false; + + // Now undo the decrement above. + if (entry.is_terminal_entry) + line_entry.range.GetBaseAddress().Slide(1); + + if (!entry.is_terminal_entry && idx + 1 < m_entries.size()) + line_entry.range.SetByteSize(m_entries[idx + 1].file_addr - + entry.file_addr); + else + line_entry.range.SetByteSize(0); + + line_entry.file = + m_comp_unit->GetSupportFiles().GetFileSpecAtIndex(entry.file_idx); + line_entry.original_file = + m_comp_unit->GetSupportFiles().GetFileSpecAtIndex(entry.file_idx); + line_entry.line = entry.line; + line_entry.column = entry.column; + line_entry.is_start_of_statement = entry.is_start_of_statement; + line_entry.is_start_of_basic_block = entry.is_start_of_basic_block; + line_entry.is_prologue_end = entry.is_prologue_end; + line_entry.is_epilogue_begin = entry.is_epilogue_begin; + line_entry.is_terminal_entry = entry.is_terminal_entry; + return true; } uint32_t LineTable::FindLineEntryIndexByFileIndex( diff --git a/source/Symbol/LocateSymbolFile.cpp b/source/Symbol/LocateSymbolFile.cpp index bfdb6e705f4a..0d0e5300668f 100644 --- a/source/Symbol/LocateSymbolFile.cpp +++ b/source/Symbol/LocateSymbolFile.cpp @@ -157,8 +157,8 @@ static bool LocateDSYMInVincinityOfExecutable(const ModuleSpec &module_spec, if (::LookForDsymNextToExecutablePath(module_spec, exec_fspec, dsym_fspec)) { if (log) { - log->Printf("dSYM with matching UUID & arch found at %s", - dsym_fspec.GetPath().c_str()); + LLDB_LOGF(log, "dSYM with matching UUID & arch found at %s", + dsym_fspec.GetPath().c_str()); } return true; } else { @@ -189,8 +189,8 @@ static bool LocateDSYMInVincinityOfExecutable(const ModuleSpec &module_spec, if (::LookForDsymNextToExecutablePath(module_spec, parent_dirs, dsym_fspec)) { if (log) { - log->Printf("dSYM with matching UUID & arch found at %s", - dsym_fspec.GetPath().c_str()); + LLDB_LOGF(log, "dSYM with matching UUID & arch found at %s", + dsym_fspec.GetPath().c_str()); } return true; } @@ -261,107 +261,110 @@ Symbols::LocateExecutableSymbolFile(const ModuleSpec &module_spec, FileSystem::Instance().Exists(symbol_file_spec)) return symbol_file_spec; - const char *symbol_filename = symbol_file_spec.GetFilename().AsCString(); - if (symbol_filename && symbol_filename[0]) { - FileSpecList debug_file_search_paths = default_search_paths; + FileSpecList debug_file_search_paths = default_search_paths; - // Add module directory. - FileSpec module_file_spec = module_spec.GetFileSpec(); - // We keep the unresolved pathname if it fails. - FileSystem::Instance().ResolveSymbolicLink(module_file_spec, - module_file_spec); + // Add module directory. + FileSpec module_file_spec = module_spec.GetFileSpec(); + // We keep the unresolved pathname if it fails. + FileSystem::Instance().ResolveSymbolicLink(module_file_spec, + module_file_spec); - ConstString file_dir = module_file_spec.GetDirectory(); + ConstString file_dir = module_file_spec.GetDirectory(); + { + FileSpec file_spec(file_dir.AsCString(".")); + FileSystem::Instance().Resolve(file_spec); + debug_file_search_paths.AppendIfUnique(file_spec); + } + + if (ModuleList::GetGlobalModuleListProperties().GetEnableExternalLookup()) { + + // Add current working directory. { - FileSpec file_spec(file_dir.AsCString(".")); + FileSpec file_spec("."); FileSystem::Instance().Resolve(file_spec); debug_file_search_paths.AppendIfUnique(file_spec); } - if (ModuleList::GetGlobalModuleListProperties().GetEnableExternalLookup()) { - - // Add current working directory. - { - FileSpec file_spec("."); - FileSystem::Instance().Resolve(file_spec); - debug_file_search_paths.AppendIfUnique(file_spec); - } - #ifndef _WIN32 #if defined(__NetBSD__) - // Add /usr/libdata/debug directory. - { - FileSpec file_spec("/usr/libdata/debug"); - FileSystem::Instance().Resolve(file_spec); - debug_file_search_paths.AppendIfUnique(file_spec); - } + // Add /usr/libdata/debug directory. + { + FileSpec file_spec("/usr/libdata/debug"); + FileSystem::Instance().Resolve(file_spec); + debug_file_search_paths.AppendIfUnique(file_spec); + } #else - // Add /usr/lib/debug directory. - { - FileSpec file_spec("/usr/lib/debug"); - FileSystem::Instance().Resolve(file_spec); - debug_file_search_paths.AppendIfUnique(file_spec); - } + // Add /usr/lib/debug directory. + { + FileSpec file_spec("/usr/lib/debug"); + FileSystem::Instance().Resolve(file_spec); + debug_file_search_paths.AppendIfUnique(file_spec); + } #endif #endif // _WIN32 - } + } - std::string uuid_str; - const UUID &module_uuid = module_spec.GetUUID(); - if (module_uuid.IsValid()) { - // Some debug files are stored in the .build-id directory like this: - // /usr/lib/debug/.build-id/ff/e7fe727889ad82bb153de2ad065b2189693315.debug - uuid_str = module_uuid.GetAsString(""); - std::transform(uuid_str.begin(), uuid_str.end(), uuid_str.begin(), - ::tolower); - uuid_str.insert(2, 1, '/'); - uuid_str = uuid_str + ".debug"; - } + std::string uuid_str; + const UUID &module_uuid = module_spec.GetUUID(); + if (module_uuid.IsValid()) { + // Some debug files are stored in the .build-id directory like this: + // /usr/lib/debug/.build-id/ff/e7fe727889ad82bb153de2ad065b2189693315.debug + uuid_str = module_uuid.GetAsString(""); + std::transform(uuid_str.begin(), uuid_str.end(), uuid_str.begin(), + ::tolower); + uuid_str.insert(2, 1, '/'); + uuid_str = uuid_str + ".debug"; + } - size_t num_directories = debug_file_search_paths.GetSize(); - for (size_t idx = 0; idx < num_directories; ++idx) { - FileSpec dirspec = debug_file_search_paths.GetFileSpecAtIndex(idx); - FileSystem::Instance().Resolve(dirspec); - if (!FileSystem::Instance().IsDirectory(dirspec)) - continue; + size_t num_directories = debug_file_search_paths.GetSize(); + for (size_t idx = 0; idx < num_directories; ++idx) { + FileSpec dirspec = debug_file_search_paths.GetFileSpecAtIndex(idx); + FileSystem::Instance().Resolve(dirspec); + if (!FileSystem::Instance().IsDirectory(dirspec)) + continue; - std::vector<std::string> files; - std::string dirname = dirspec.GetPath(); + std::vector<std::string> files; + std::string dirname = dirspec.GetPath(); - files.push_back(dirname + "/" + symbol_filename); - files.push_back(dirname + "/.debug/" + symbol_filename); + if (!uuid_str.empty()) files.push_back(dirname + "/.build-id/" + uuid_str); + if (symbol_file_spec.GetFilename()) { + files.push_back(dirname + "/" + + symbol_file_spec.GetFilename().GetCString()); + files.push_back(dirname + "/.debug/" + + symbol_file_spec.GetFilename().GetCString()); // Some debug files may stored in the module directory like this: // /usr/lib/debug/usr/lib/library.so.debug if (!file_dir.IsEmpty()) - files.push_back(dirname + file_dir.AsCString() + "/" + symbol_filename); - - const uint32_t num_files = files.size(); - for (size_t idx_file = 0; idx_file < num_files; ++idx_file) { - const std::string &filename = files[idx_file]; - FileSpec file_spec(filename); - FileSystem::Instance().Resolve(file_spec); - - if (llvm::sys::fs::equivalent(file_spec.GetPath(), - module_file_spec.GetPath())) - continue; - - if (FileSystem::Instance().Exists(file_spec)) { - lldb_private::ModuleSpecList specs; - const size_t num_specs = - ObjectFile::GetModuleSpecifications(file_spec, 0, 0, specs); - assert(num_specs <= 1 && - "Symbol Vendor supports only a single architecture"); - if (num_specs == 1) { - ModuleSpec mspec; - if (specs.GetModuleSpecAtIndex(0, mspec)) { - // Skip the uuids check if module_uuid is invalid. For example, - // this happens for *.dwp files since at the moment llvm-dwp - // doesn't output build ids, nor does binutils dwp. - if (!module_uuid.IsValid() || module_uuid == mspec.GetUUID()) - return file_spec; - } + files.push_back(dirname + file_dir.AsCString() + "/" + + symbol_file_spec.GetFilename().GetCString()); + } + + const uint32_t num_files = files.size(); + for (size_t idx_file = 0; idx_file < num_files; ++idx_file) { + const std::string &filename = files[idx_file]; + FileSpec file_spec(filename); + FileSystem::Instance().Resolve(file_spec); + + if (llvm::sys::fs::equivalent(file_spec.GetPath(), + module_file_spec.GetPath())) + continue; + + if (FileSystem::Instance().Exists(file_spec)) { + lldb_private::ModuleSpecList specs; + const size_t num_specs = + ObjectFile::GetModuleSpecifications(file_spec, 0, 0, specs); + assert(num_specs <= 1 && + "Symbol Vendor supports only a single architecture"); + if (num_specs == 1) { + ModuleSpec mspec; + if (specs.GetModuleSpecAtIndex(0, mspec)) { + // Skip the uuids check if module_uuid is invalid. For example, + // this happens for *.dwp files since at the moment llvm-dwp + // doesn't output build ids, nor does binutils dwp. + if (!module_uuid.IsValid() || module_uuid == mspec.GetUUID()) + return file_spec; } } } diff --git a/source/Symbol/LocateSymbolFileMacOSX.cpp b/source/Symbol/LocateSymbolFileMacOSX.cpp index 4e16382d53e7..74718a8c5e30 100644 --- a/source/Symbol/LocateSymbolFileMacOSX.cpp +++ b/source/Symbol/LocateSymbolFileMacOSX.cpp @@ -23,7 +23,6 @@ #include "lldb/Host/Host.h" #include "lldb/Symbol/ObjectFile.h" #include "lldb/Utility/ArchSpec.h" -#include "lldb/Utility/CleanUp.h" #include "lldb/Utility/DataBuffer.h" #include "lldb/Utility/DataExtractor.h" #include "lldb/Utility/Endian.h" @@ -33,6 +32,7 @@ #include "lldb/Utility/UUID.h" #include "mach/machine.h" +#include "llvm/ADT/ScopeExit.h" #include "llvm/Support/FileSystem.h" using namespace lldb; @@ -45,8 +45,7 @@ int LocateMacOSXFilesUsingDebugSymbols(const ModuleSpec &module_spec, ModuleSpec &return_module_spec) { Log *log = lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_HOST); if (!ModuleList::GetGlobalModuleListProperties().GetEnableExternalLookup()) { - if (log) - log->Printf("Spotlight lookup for .dSYM bundles is disabled."); + LLDB_LOGF(log, "Spotlight lookup for .dSYM bundles is disabled."); return 0; } @@ -102,9 +101,10 @@ int LocateMacOSXFilesUsingDebugSymbols(const ModuleSpec &module_spec, if (::CFURLGetFileSystemRepresentation( dsym_url.get(), true, (UInt8 *)path, sizeof(path) - 1)) { if (log) { - log->Printf("DebugSymbols framework returned dSYM path of %s for " - "UUID %s -- looking for the dSYM", - path, uuid->GetAsString().c_str()); + LLDB_LOGF(log, + "DebugSymbols framework returned dSYM path of %s for " + "UUID %s -- looking for the dSYM", + path, uuid->GetAsString().c_str()); } FileSpec dsym_filespec(path); if (path[0] == '~') @@ -124,9 +124,10 @@ int LocateMacOSXFilesUsingDebugSymbols(const ModuleSpec &module_spec, if (log) { if (::CFURLGetFileSystemRepresentation( dsym_url.get(), true, (UInt8 *)path, sizeof(path) - 1)) { - log->Printf("DebugSymbols framework returned dSYM path of %s for " - "UUID %s -- looking for an exec file", - path, uuid->GetAsString().c_str()); + LLDB_LOGF(log, + "DebugSymbols framework returned dSYM path of %s for " + "UUID %s -- looking for an exec file", + path, uuid->GetAsString().c_str()); } } @@ -145,8 +146,8 @@ int LocateMacOSXFilesUsingDebugSymbols(const ModuleSpec &module_spec, if (exec_cf_path && ::CFStringGetFileSystemRepresentation( exec_cf_path, path, sizeof(path))) { if (log) { - log->Printf("plist bundle has exec path of %s for UUID %s", - path, uuid->GetAsString().c_str()); + LLDB_LOGF(log, "plist bundle has exec path of %s for UUID %s", + path, uuid->GetAsString().c_str()); } ++items_found; FileSpec exec_filespec(path); @@ -168,9 +169,10 @@ int LocateMacOSXFilesUsingDebugSymbols(const ModuleSpec &module_spec, if (dsym_extension_pos) { *dsym_extension_pos = '\0'; if (log) { - log->Printf("Looking for executable binary next to dSYM " - "bundle with name with name %s", - path); + LLDB_LOGF(log, + "Looking for executable binary next to dSYM " + "bundle with name with name %s", + path); } FileSpec file_spec(path); FileSystem::Instance().Resolve(file_spec); @@ -199,9 +201,10 @@ int LocateMacOSXFilesUsingDebugSymbols(const ModuleSpec &module_spec, ++items_found; return_module_spec.GetFileSpec() = bundle_exe_file_spec; if (log) { - log->Printf("Executable binary %s next to dSYM is " - "compatible; using", - path); + LLDB_LOGF(log, + "Executable binary %s next to dSYM is " + "compatible; using", + path); } } } @@ -228,9 +231,10 @@ int LocateMacOSXFilesUsingDebugSymbols(const ModuleSpec &module_spec, ++items_found; return_module_spec.GetFileSpec() = file_spec; if (log) { - log->Printf("Executable binary %s next to dSYM is " - "compatible; using", - path); + LLDB_LOGF(log, + "Executable binary %s next to dSYM is " + "compatible; using", + path); } } break; @@ -260,7 +264,7 @@ FileSpec Symbols::FindSymbolFileInBundle(const FileSpec &dsym_bundle_fspec, return {}; // Make sure we close the directory before exiting this scope. - CleanUp cleanup_dir(closedir, dirp); + auto cleanup_dir = llvm::make_scope_exit([&]() { closedir(dirp); }); FileSpec dsym_fspec; dsym_fspec.GetDirectory().SetCString(path); @@ -315,9 +319,9 @@ static bool GetModuleSpecInfoFromUUIDDictionary(CFDictionaryRef uuid_dict, module_spec.GetFileSpec().SetFile(str.c_str(), FileSpec::Style::native); FileSystem::Instance().Resolve(module_spec.GetFileSpec()); if (log) { - log->Printf( - "From dsymForUUID plist: Symbol rich executable is at '%s'", - str.c_str()); + LLDB_LOGF(log, + "From dsymForUUID plist: Symbol rich executable is at '%s'", + str.c_str()); } } } @@ -331,7 +335,8 @@ static bool GetModuleSpecInfoFromUUIDDictionary(CFDictionaryRef uuid_dict, FileSystem::Instance().Resolve(module_spec.GetFileSpec()); success = true; if (log) { - log->Printf("From dsymForUUID plist: dSYM is at '%s'", str.c_str()); + LLDB_LOGF(log, "From dsymForUUID plist: dSYM is at '%s'", + str.c_str()); } } } @@ -582,11 +587,11 @@ bool Symbols::DownloadObjectAndSymbolFile(ModuleSpec &module_spec, std::string command_output; if (log) { if (!uuid_str.empty()) - log->Printf("Calling %s with UUID %s to find dSYM", - g_dsym_for_uuid_exe_path, uuid_str.c_str()); + LLDB_LOGF(log, "Calling %s with UUID %s to find dSYM", + g_dsym_for_uuid_exe_path, uuid_str.c_str()); else if (file_path[0] != '\0') - log->Printf("Calling %s with file %s to find dSYM", - g_dsym_for_uuid_exe_path, file_path); + LLDB_LOGF(log, "Calling %s with file %s to find dSYM", + g_dsym_for_uuid_exe_path, file_path); } Status error = Host::RunShellCommand( command.GetData(), @@ -643,11 +648,11 @@ bool Symbols::DownloadObjectAndSymbolFile(ModuleSpec &module_spec, } else { if (log) { if (!uuid_str.empty()) - log->Printf("Called %s on %s, no matches", - g_dsym_for_uuid_exe_path, uuid_str.c_str()); + LLDB_LOGF(log, "Called %s on %s, no matches", + g_dsym_for_uuid_exe_path, uuid_str.c_str()); else if (file_path[0] != '\0') - log->Printf("Called %s on %s, no matches", - g_dsym_for_uuid_exe_path, file_path); + LLDB_LOGF(log, "Called %s on %s, no matches", + g_dsym_for_uuid_exe_path, file_path); } } } diff --git a/source/Symbol/ObjectFile.cpp b/source/Symbol/ObjectFile.cpp index 172d2b3f01e3..38bc7722d0d0 100644 --- a/source/Symbol/ObjectFile.cpp +++ b/source/Symbol/ObjectFile.cpp @@ -11,6 +11,7 @@ #include "lldb/Core/ModuleSpec.h" #include "lldb/Core/PluginManager.h" #include "lldb/Core/Section.h" +#include "lldb/Symbol/CallFrameInfo.h" #include "lldb/Symbol/ObjectContainer.h" #include "lldb/Symbol/SymbolFile.h" #include "lldb/Target/Process.h" @@ -19,13 +20,14 @@ #include "lldb/Utility/DataBuffer.h" #include "lldb/Utility/DataBufferHeap.h" #include "lldb/Utility/Log.h" -#include "lldb/Utility/RegularExpression.h" #include "lldb/Utility/Timer.h" #include "lldb/lldb-private.h" using namespace lldb; using namespace lldb_private; +char ObjectFile::ID; + ObjectFileSP ObjectFile::FindPlugin(const lldb::ModuleSP &module_sp, const FileSpec *file, lldb::offset_t file_offset, lldb::offset_t file_size, @@ -81,9 +83,8 @@ ObjectFile::FindPlugin(const lldb::ModuleSP &module_sp, const FileSpec *file, if (!data_sp || data_sp->GetByteSize() == 0) { // Check for archive file with format "/path/to/archive.a(object.o)" - char path_with_object[PATH_MAX * 2]; - module_sp->GetFileSpec().GetPath(path_with_object, - sizeof(path_with_object)); + llvm::SmallString<256> path_with_object; + module_sp->GetFileSpec().GetPath(path_with_object); ConstString archive_object; const bool must_exist = true; @@ -271,13 +272,13 @@ ObjectFile::ObjectFile(const lldb::ModuleSP &module_sp, if (data_sp) m_data.SetData(data_sp, data_offset, length); Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_OBJECT)); - if (log) - log->Printf("%p ObjectFile::ObjectFile() module = %p (%s), file = %s, " - "file_offset = 0x%8.8" PRIx64 ", size = %" PRIu64, - static_cast<void *>(this), static_cast<void *>(module_sp.get()), - module_sp->GetSpecificationDescription().c_str(), - m_file ? m_file.GetPath().c_str() : "<NULL>", m_file_offset, - m_length); + LLDB_LOGF(log, + "%p ObjectFile::ObjectFile() module = %p (%s), file = %s, " + "file_offset = 0x%8.8" PRIx64 ", size = %" PRIu64, + static_cast<void *>(this), static_cast<void *>(module_sp.get()), + module_sp->GetSpecificationDescription().c_str(), + m_file ? m_file.GetPath().c_str() : "<NULL>", m_file_offset, + m_length); } ObjectFile::ObjectFile(const lldb::ModuleSP &module_sp, @@ -290,18 +291,17 @@ ObjectFile::ObjectFile(const lldb::ModuleSP &module_sp, if (header_data_sp) m_data.SetData(header_data_sp, 0, header_data_sp->GetByteSize()); Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_OBJECT)); - if (log) - log->Printf("%p ObjectFile::ObjectFile() module = %p (%s), process = %p, " - "header_addr = 0x%" PRIx64, - static_cast<void *>(this), static_cast<void *>(module_sp.get()), - module_sp->GetSpecificationDescription().c_str(), - static_cast<void *>(process_sp.get()), m_memory_addr); + LLDB_LOGF(log, + "%p ObjectFile::ObjectFile() module = %p (%s), process = %p, " + "header_addr = 0x%" PRIx64, + static_cast<void *>(this), static_cast<void *>(module_sp.get()), + module_sp->GetSpecificationDescription().c_str(), + static_cast<void *>(process_sp.get()), m_memory_addr); } ObjectFile::~ObjectFile() { Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_OBJECT)); - if (log) - log->Printf("%p ObjectFile::~ObjectFile ()\n", static_cast<void *>(this)); + LLDB_LOGF(log, "%p ObjectFile::~ObjectFile ()\n", static_cast<void *>(this)); } bool ObjectFile::SetModulesArchitecture(const ArchSpec &new_arch) { @@ -570,24 +570,22 @@ size_t ObjectFile::ReadSectionData(Section *section, } } -bool ObjectFile::SplitArchivePathWithObject(const char *path_with_object, +bool ObjectFile::SplitArchivePathWithObject(llvm::StringRef path_with_object, FileSpec &archive_file, ConstString &archive_object, bool must_exist) { - RegularExpression g_object_regex(llvm::StringRef("(.*)\\(([^\\)]+)\\)$")); - RegularExpression::Match regex_match(2); - if (g_object_regex.Execute(llvm::StringRef::withNullAsEmpty(path_with_object), - ®ex_match)) { - std::string path; - std::string obj; - if (regex_match.GetMatchAtIndex(path_with_object, 1, path) && - regex_match.GetMatchAtIndex(path_with_object, 2, obj)) { - archive_file.SetFile(path, FileSpec::Style::native); - archive_object.SetCString(obj.c_str()); - return !(must_exist && !FileSystem::Instance().Exists(archive_file)); - } - } - return false; + size_t len = path_with_object.size(); + if (len < 2 || path_with_object.back() != ')') + return false; + llvm::StringRef archive = path_with_object.substr(0, path_with_object.rfind('(')); + if (archive.empty()) + return false; + llvm::StringRef object = path_with_object.substr(archive.size() + 1).drop_back(); + archive_file.SetFile(archive, FileSpec::Style::native); + if (must_exist && !FileSystem::Instance().Exists(archive_file)) + return false; + archive_object.SetString(object); + return true; } void ObjectFile::ClearSymtab() { @@ -595,10 +593,9 @@ void ObjectFile::ClearSymtab() { if (module_sp) { std::lock_guard<std::recursive_mutex> guard(module_sp->GetMutex()); Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_OBJECT)); - if (log) - log->Printf("%p ObjectFile::ClearSymtab () symtab = %p", - static_cast<void *>(this), - static_cast<void *>(m_symtab_up.get())); + LLDB_LOGF(log, "%p ObjectFile::ClearSymtab () symtab = %p", + static_cast<void *>(this), + static_cast<void *>(m_symtab_up.get())); m_symtab_up.reset(); } } @@ -674,6 +671,10 @@ ObjectFile::GetLoadableData(Target &target) { return loadables; } +std::unique_ptr<CallFrameInfo> ObjectFile::CreateCallFrameInfo() { + return {}; +} + void ObjectFile::RelocateSection(lldb_private::Section *section) { } diff --git a/source/Symbol/PostfixExpression.cpp b/source/Symbol/PostfixExpression.cpp index 148653561a4e..8ecd571ed929 100644 --- a/source/Symbol/PostfixExpression.cpp +++ b/source/Symbol/PostfixExpression.cpp @@ -41,7 +41,8 @@ GetUnaryOpType(llvm::StringRef token) { return llvm::None; } -Node *postfix::Parse(llvm::StringRef expr, llvm::BumpPtrAllocator &alloc) { +Node *postfix::ParseOneExpression(llvm::StringRef expr, + llvm::BumpPtrAllocator &alloc) { llvm::SmallVector<Node *, 4> stack; llvm::StringRef token; @@ -83,6 +84,26 @@ Node *postfix::Parse(llvm::StringRef expr, llvm::BumpPtrAllocator &alloc) { return stack.back(); } +std::vector<std::pair<llvm::StringRef, Node *>> +postfix::ParseFPOProgram(llvm::StringRef prog, llvm::BumpPtrAllocator &alloc) { + llvm::SmallVector<llvm::StringRef, 4> exprs; + prog.split(exprs, '='); + if (exprs.empty() || !exprs.back().trim().empty()) + return {}; + exprs.pop_back(); + + std::vector<std::pair<llvm::StringRef, Node *>> result; + for (llvm::StringRef expr : exprs) { + llvm::StringRef lhs; + std::tie(lhs, expr) = getToken(expr); + Node *rhs = ParseOneExpression(expr, alloc); + if (!rhs) + return {}; + result.emplace_back(lhs, rhs); + } + return result; +} + namespace { class SymbolResolver : public Visitor<bool> { public: diff --git a/source/Symbol/Symbol.cpp b/source/Symbol/Symbol.cpp index 589f69244a48..3f2414335813 100644 --- a/source/Symbol/Symbol.cpp +++ b/source/Symbol/Symbol.cpp @@ -31,9 +31,8 @@ Symbol::Symbol() m_is_weak(false), m_type(eSymbolTypeInvalid), m_mangled(), m_addr_range(), m_flags() {} -Symbol::Symbol(uint32_t symID, const char *name, bool name_is_mangled, - SymbolType type, bool external, bool is_debug, - bool is_trampoline, bool is_artificial, +Symbol::Symbol(uint32_t symID, llvm::StringRef name, SymbolType type, bool external, + bool is_debug, bool is_trampoline, bool is_artificial, const lldb::SectionSP §ion_sp, addr_t offset, addr_t size, bool size_is_valid, bool contains_linker_annotations, uint32_t flags) @@ -42,9 +41,9 @@ Symbol::Symbol(uint32_t symID, const char *name, bool name_is_mangled, m_is_debug(is_debug), m_is_external(external), m_size_is_sibling(false), m_size_is_synthesized(false), m_size_is_valid(size_is_valid || size > 0), m_demangled_is_synthesized(false), - m_contains_linker_annotations(contains_linker_annotations), + m_contains_linker_annotations(contains_linker_annotations), m_is_weak(false), m_type(type), - m_mangled(ConstString(name), name_is_mangled), + m_mangled(name), m_addr_range(section_sp, offset, size), m_flags(flags) {} Symbol::Symbol(uint32_t symID, const Mangled &mangled, SymbolType type, diff --git a/source/Symbol/SymbolContext.cpp b/source/Symbol/SymbolContext.cpp index a0b35cf3d0b9..31e0c89eed94 100644 --- a/source/Symbol/SymbolContext.cpp +++ b/source/Symbol/SymbolContext.cpp @@ -13,7 +13,6 @@ #include "lldb/Host/Host.h" #include "lldb/Host/StringConvert.h" #include "lldb/Symbol/Block.h" -#include "lldb/Symbol/ClangASTContext.h" #include "lldb/Symbol/CompileUnit.h" #include "lldb/Symbol/ObjectFile.h" #include "lldb/Symbol/Symbol.h" @@ -22,6 +21,7 @@ #include "lldb/Symbol/Variable.h" #include "lldb/Target/Target.h" #include "lldb/Utility/Log.h" +#include "lldb/Utility/StreamString.h" using namespace lldb; using namespace lldb_private; @@ -494,7 +494,8 @@ bool SymbolContext::GetParentOfInlinedScope(const Address &curr_frame_pc, Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_SYMBOLS)); if (log) { - log->Printf( + LLDB_LOGF( + log, "warning: inlined block 0x%8.8" PRIx64 " doesn't have a range that contains file address 0x%" PRIx64, curr_inlined_block->GetID(), curr_frame_pc.GetFileAddress()); @@ -503,12 +504,8 @@ bool SymbolContext::GetParentOfInlinedScope(const Address &curr_frame_pc, else { ObjectFile *objfile = nullptr; if (module_sp) { - SymbolVendor *symbol_vendor = module_sp->GetSymbolVendor(); - if (symbol_vendor) { - SymbolFile *symbol_file = symbol_vendor->GetSymbolFile(); - if (symbol_file) - objfile = symbol_file->GetObjectFile(); - } + if (SymbolFile *symbol_file = module_sp->GetSymbolFile()) + objfile = symbol_file->GetObjectFile(); } if (objfile) { Host::SystemLog( @@ -762,9 +759,8 @@ bool SymbolContext::GetAddressRangeFromHereToEndLine(uint32_t end_line, } Block *func_block = GetFunctionBlock(); - if (func_block && - func_block->GetRangeIndexContainingAddress( - end_entry.range.GetBaseAddress()) == UINT32_MAX) { + if (func_block && func_block->GetRangeIndexContainingAddress( + end_entry.range.GetBaseAddress()) == UINT32_MAX) { error.SetErrorStringWithFormat( "end line number %d is not contained within the current function.", end_line); @@ -777,8 +773,8 @@ bool SymbolContext::GetAddressRangeFromHereToEndLine(uint32_t end_line, return true; } -const Symbol * -SymbolContext::FindBestGlobalDataSymbol(ConstString name, Status &error) { +const Symbol *SymbolContext::FindBestGlobalDataSymbol(ConstString name, + Status &error) { error.Clear(); if (!target_sp) { @@ -788,8 +784,9 @@ SymbolContext::FindBestGlobalDataSymbol(ConstString name, Status &error) { Target &target = *target_sp; Module *module = module_sp.get(); - auto ProcessMatches = [this, &name, &target, module] - (SymbolContextList &sc_list, Status &error) -> const Symbol* { + auto ProcessMatches = [this, &name, &target, + module](SymbolContextList &sc_list, + Status &error) -> const Symbol * { llvm::SmallVector<const Symbol *, 1> external_symbols; llvm::SmallVector<const Symbol *, 1> internal_symbols; const uint32_t matches = sc_list.GetSize(); @@ -802,77 +799,77 @@ SymbolContext::FindBestGlobalDataSymbol(ConstString name, Status &error) { if (sym_address.IsValid()) { switch (symbol->GetType()) { - case eSymbolTypeData: - case eSymbolTypeRuntime: - case eSymbolTypeAbsolute: - case eSymbolTypeObjCClass: - case eSymbolTypeObjCMetaClass: - case eSymbolTypeObjCIVar: - if (symbol->GetDemangledNameIsSynthesized()) { - // If the demangled name was synthesized, then don't use it for - // expressions. Only let the symbol match if the mangled named - // matches for these symbols. - if (symbol->GetMangled().GetMangledName() != name) - break; - } - if (symbol->IsExternal()) { - external_symbols.push_back(symbol); - } else { - internal_symbols.push_back(symbol); - } - break; - case eSymbolTypeReExported: { - ConstString reexport_name = symbol->GetReExportedSymbolName(); - if (reexport_name) { - ModuleSP reexport_module_sp; - ModuleSpec reexport_module_spec; - reexport_module_spec.GetPlatformFileSpec() = - 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 = + case eSymbolTypeData: + case eSymbolTypeRuntime: + case eSymbolTypeAbsolute: + case eSymbolTypeObjCClass: + case eSymbolTypeObjCMetaClass: + case eSymbolTypeObjCIVar: + if (symbol->GetDemangledNameIsSynthesized()) { + // If the demangled name was synthesized, then don't use it for + // expressions. Only let the symbol match if the mangled named + // matches for these symbols. + if (symbol->GetMangled().GetMangledName() != name) + break; + } + if (symbol->IsExternal()) { + external_symbols.push_back(symbol); + } else { + internal_symbols.push_back(symbol); + } + break; + case eSymbolTypeReExported: { + ConstString reexport_name = symbol->GetReExportedSymbolName(); + if (reexport_name) { + ModuleSP reexport_module_sp; + ModuleSpec reexport_module_spec; + reexport_module_spec.GetPlatformFileSpec() = + 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); } - // Don't allow us to try and resolve a re-exported symbol if it - // is the same as the current symbol - if (name == symbol->GetReExportedSymbolName() && - module == reexport_module_sp.get()) - return nullptr; - - return FindBestGlobalDataSymbol( - symbol->GetReExportedSymbolName(), error); } - } break; - - case eSymbolTypeCode: // We already lookup functions elsewhere - case eSymbolTypeVariable: - case eSymbolTypeLocal: - case eSymbolTypeParam: - case eSymbolTypeTrampoline: - case eSymbolTypeInvalid: - 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 eSymbolTypeResolver: - break; + // Don't allow us to try and resolve a re-exported symbol if it + // is the same as the current symbol + if (name == symbol->GetReExportedSymbolName() && + module == reexport_module_sp.get()) + return nullptr; + + return FindBestGlobalDataSymbol(symbol->GetReExportedSymbolName(), + error); + } + } break; + + case eSymbolTypeCode: // We already lookup functions elsewhere + case eSymbolTypeVariable: + case eSymbolTypeLocal: + case eSymbolTypeParam: + case eSymbolTypeTrampoline: + case eSymbolTypeInvalid: + 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 eSymbolTypeResolver: + break; } } } @@ -933,7 +930,6 @@ SymbolContext::FindBestGlobalDataSymbol(ConstString name, Status &error) { return nullptr; // no error; we just didn't find anything } - // // SymbolContextSpecifier // @@ -1296,6 +1292,8 @@ bool SymbolContextList::RemoveContextAtIndex(size_t idx) { uint32_t SymbolContextList::GetSize() const { return m_symbol_contexts.size(); } +bool SymbolContextList::IsEmpty() const { return m_symbol_contexts.empty(); } + uint32_t SymbolContextList::NumLineEntriesWithLine(uint32_t line) const { uint32_t match_count = 0; const size_t size = m_symbol_contexts.size(); diff --git a/source/Symbol/SymbolFile.cpp b/source/Symbol/SymbolFile.cpp index 77ab2223ec07..c4f3a9c1a8c8 100644 --- a/source/Symbol/SymbolFile.cpp +++ b/source/Symbol/SymbolFile.cpp @@ -10,6 +10,7 @@ #include "lldb/Core/Module.h" #include "lldb/Core/PluginManager.h" +#include "lldb/Symbol/CompileUnit.h" #include "lldb/Symbol/ObjectFile.h" #include "lldb/Symbol/TypeMap.h" #include "lldb/Symbol/TypeSystem.h" @@ -21,6 +22,7 @@ #include <future> using namespace lldb_private; +using namespace lldb; void SymbolFile::PreloadSymbols() { // No-op for most implementations. @@ -29,21 +31,24 @@ void SymbolFile::PreloadSymbols() { std::recursive_mutex &SymbolFile::GetModuleMutex() const { return GetObjectFile()->GetModule()->GetMutex(); } +ObjectFile *SymbolFile::GetMainObjectFile() { + return m_objfile_sp->GetModule()->GetObjectFile(); +} -SymbolFile *SymbolFile::FindPlugin(ObjectFile *obj_file) { +SymbolFile *SymbolFile::FindPlugin(ObjectFileSP objfile_sp) { std::unique_ptr<SymbolFile> best_symfile_up; - if (obj_file != nullptr) { + if (objfile_sp != nullptr) { // We need to test the abilities of this section list. So create what it - // would be with this new obj_file. - lldb::ModuleSP module_sp(obj_file->GetModule()); + // would be with this new objfile_sp. + lldb::ModuleSP module_sp(objfile_sp->GetModule()); if (module_sp) { // Default to the main module section list. ObjectFile *module_obj_file = module_sp->GetObjectFile(); - if (module_obj_file != obj_file) { + if (module_obj_file != objfile_sp.get()) { // Make sure the main object file's sections are created module_obj_file->GetSectionList(); - obj_file->CreateSections(*module_sp->GetUnifiedSectionList()); + objfile_sp->CreateSections(*module_sp->GetUnifiedSectionList()); } } @@ -57,7 +62,7 @@ SymbolFile *SymbolFile::FindPlugin(ObjectFile *obj_file) { (create_callback = PluginManager::GetSymbolFileCreateCallbackAtIndex( idx)) != nullptr; ++idx) { - std::unique_ptr<SymbolFile> curr_symfile_up(create_callback(obj_file)); + std::unique_ptr<SymbolFile> curr_symfile_up(create_callback(objfile_sp)); if (curr_symfile_up) { const uint32_t sym_file_abilities = curr_symfile_up->GetAbilities(); @@ -80,18 +85,14 @@ SymbolFile *SymbolFile::FindPlugin(ObjectFile *obj_file) { return best_symfile_up.release(); } -TypeList *SymbolFile::GetTypeList() { - if (m_obj_file) - return m_obj_file->GetModule()->GetTypeList(); - return nullptr; -} - -TypeSystem *SymbolFile::GetTypeSystemForLanguage(lldb::LanguageType language) { - TypeSystem *type_system = - m_obj_file->GetModule()->GetTypeSystemForLanguage(language); - if (type_system) - type_system->SetSymbolFile(this); - return type_system; +llvm::Expected<TypeSystem &> +SymbolFile::GetTypeSystemForLanguage(lldb::LanguageType language) { + auto type_system_or_err = + m_objfile_sp->GetModule()->GetTypeSystemForLanguage(language); + if (type_system_or_err) { + type_system_or_err->SetSymbolFile(this); + } + return type_system_or_err; } uint32_t SymbolFile::ResolveSymbolContext(const FileSpec &file_spec, @@ -101,36 +102,24 @@ uint32_t SymbolFile::ResolveSymbolContext(const FileSpec &file_spec, return 0; } -uint32_t -SymbolFile::FindGlobalVariables(ConstString name, - const CompilerDeclContext *parent_decl_ctx, - uint32_t max_matches, VariableList &variables) { - return 0; -} +void SymbolFile::FindGlobalVariables(ConstString name, + const CompilerDeclContext *parent_decl_ctx, + uint32_t max_matches, + VariableList &variables) {} -uint32_t SymbolFile::FindGlobalVariables(const RegularExpression ®ex, - uint32_t max_matches, - VariableList &variables) { - return 0; -} +void SymbolFile::FindGlobalVariables(const RegularExpression ®ex, + uint32_t max_matches, + VariableList &variables) {} -uint32_t SymbolFile::FindFunctions(ConstString name, - const CompilerDeclContext *parent_decl_ctx, - lldb::FunctionNameType name_type_mask, - bool include_inlines, bool append, - SymbolContextList &sc_list) { - if (!append) - sc_list.Clear(); - return 0; -} +void SymbolFile::FindFunctions(ConstString name, + const CompilerDeclContext *parent_decl_ctx, + lldb::FunctionNameType name_type_mask, + bool include_inlines, + SymbolContextList &sc_list) {} -uint32_t SymbolFile::FindFunctions(const RegularExpression ®ex, - bool include_inlines, bool append, - SymbolContextList &sc_list) { - if (!append) - sc_list.Clear(); - return 0; -} +void SymbolFile::FindFunctions(const RegularExpression ®ex, + bool include_inlines, + SymbolContextList &sc_list) {} void SymbolFile::GetMangledNamesForFunction( const std::string &scope_qualified_name, @@ -138,22 +127,14 @@ void SymbolFile::GetMangledNamesForFunction( return; } -uint32_t SymbolFile::FindTypes( +void SymbolFile::FindTypes( ConstString name, const CompilerDeclContext *parent_decl_ctx, - bool append, uint32_t max_matches, + uint32_t max_matches, llvm::DenseSet<lldb_private::SymbolFile *> &searched_symbol_files, - TypeMap &types) { - if (!append) - types.Clear(); - return 0; -} + TypeMap &types) {} -size_t SymbolFile::FindTypes(const std::vector<CompilerContext> &context, - bool append, TypeMap &types) { - if (!append) - types.Clear(); - return 0; -} +void SymbolFile::FindTypes(llvm::ArrayRef<CompilerContext> pattern, + LanguageSet languages, TypeMap &types) {} void SymbolFile::AssertModuleLock() { // The code below is too expensive to leave enabled in release builds. It's @@ -169,4 +150,85 @@ void SymbolFile::AssertModuleLock() { #endif } +uint32_t SymbolFile::GetNumCompileUnits() { + std::lock_guard<std::recursive_mutex> guard(GetModuleMutex()); + if (!m_compile_units) { + // Create an array of compile unit shared pointers -- which will each + // remain NULL until someone asks for the actual compile unit information. + m_compile_units.emplace(CalculateNumCompileUnits()); + } + return m_compile_units->size(); +} + +CompUnitSP SymbolFile::GetCompileUnitAtIndex(uint32_t idx) { + std::lock_guard<std::recursive_mutex> guard(GetModuleMutex()); + uint32_t num = GetNumCompileUnits(); + if (idx >= num) + return nullptr; + lldb::CompUnitSP &cu_sp = (*m_compile_units)[idx]; + if (!cu_sp) + cu_sp = ParseCompileUnitAtIndex(idx); + return cu_sp; +} + +void SymbolFile::SetCompileUnitAtIndex(uint32_t idx, const CompUnitSP &cu_sp) { + std::lock_guard<std::recursive_mutex> guard(GetModuleMutex()); + const size_t num_compile_units = GetNumCompileUnits(); + assert(idx < num_compile_units); + (void)num_compile_units; + + // Fire off an assertion if this compile unit already exists for now. The + // partial parsing should take care of only setting the compile unit + // once, so if this assertion fails, we need to make sure that we don't + // have a race condition, or have a second parse of the same compile + // unit. + assert((*m_compile_units)[idx] == nullptr); + (*m_compile_units)[idx] = cu_sp; +} + +Symtab *SymbolFile::GetSymtab() { + std::lock_guard<std::recursive_mutex> guard(GetModuleMutex()); + if (m_symtab) + return m_symtab; + + // Fetch the symtab from the main object file. + m_symtab = GetMainObjectFile()->GetSymtab(); + + // Then add our symbols to it. + if (m_symtab) + AddSymbols(*m_symtab); + + return m_symtab; +} + +void SymbolFile::SectionFileAddressesChanged() { + ObjectFile *module_objfile = GetMainObjectFile(); + ObjectFile *symfile_objfile = GetObjectFile(); + if (symfile_objfile != module_objfile) + symfile_objfile->SectionFileAddressesChanged(); + if (m_symtab) + m_symtab->SectionFileAddressesChanged(); +} + +void SymbolFile::Dump(Stream &s) { + s.Format("SymbolFile {0} ({1})\n", GetPluginName(), + GetMainObjectFile()->GetFileSpec()); + s.PutCString("Types:\n"); + m_type_list.Dump(&s, /*show_context*/ false); + s.PutChar('\n'); + + s.PutCString("Compile units:\n"); + if (m_compile_units) { + for (const CompUnitSP &cu_sp : *m_compile_units) { + // We currently only dump the compile units that have been parsed + if (cu_sp) + cu_sp->Dump(&s, /*show_context*/ false); + } + } + s.PutChar('\n'); + + if (Symtab *symtab = GetSymtab()) + symtab->Dump(&s, nullptr, eSortOrderNone); +} + SymbolFile::RegisterInfoResolver::~RegisterInfoResolver() = default; diff --git a/source/Symbol/SymbolVendor.cpp b/source/Symbol/SymbolVendor.cpp index b9f3a5fe3926..1e1dea71d7f3 100644 --- a/source/Symbol/SymbolVendor.cpp +++ b/source/Symbol/SymbolVendor.cpp @@ -58,8 +58,7 @@ SymbolVendor *SymbolVendor::FindPlugin(const lldb::ModuleSP &module_sp, // SymbolVendor constructor SymbolVendor::SymbolVendor(const lldb::ModuleSP &module_sp) - : ModuleChild(module_sp), m_type_list(), m_compile_units(), m_sym_file_up(), - m_symtab() {} + : ModuleChild(module_sp), m_sym_file_up() {} // Destructor SymbolVendor::~SymbolVendor() {} @@ -69,414 +68,8 @@ void SymbolVendor::AddSymbolFileRepresentation(const ObjectFileSP &objfile_sp) { ModuleSP module_sp(GetModule()); if (module_sp) { std::lock_guard<std::recursive_mutex> guard(module_sp->GetMutex()); - if (objfile_sp) { - m_objfile_sp = objfile_sp; - m_sym_file_up.reset(SymbolFile::FindPlugin(objfile_sp.get())); - } - } -} - -bool SymbolVendor::SetCompileUnitAtIndex(size_t idx, const CompUnitSP &cu_sp) { - ModuleSP module_sp(GetModule()); - if (module_sp) { - std::lock_guard<std::recursive_mutex> guard(module_sp->GetMutex()); - const size_t num_compile_units = GetNumCompileUnits(); - if (idx < num_compile_units) { - // Fire off an assertion if this compile unit already exists for now. The - // partial parsing should take care of only setting the compile unit - // once, so if this assertion fails, we need to make sure that we don't - // have a race condition, or have a second parse of the same compile - // unit. - assert(m_compile_units[idx].get() == nullptr); - m_compile_units[idx] = cu_sp; - return true; - } else { - // This should NOT happen, and if it does, we want to crash and know - // about it - assert(idx < num_compile_units); - } - } - return false; -} - -size_t SymbolVendor::GetNumCompileUnits() { - ModuleSP module_sp(GetModule()); - if (module_sp) { - std::lock_guard<std::recursive_mutex> guard(module_sp->GetMutex()); - if (m_compile_units.empty()) { - if (m_sym_file_up) { - // Resize our array of compile unit shared pointers -- which will each - // remain NULL until someone asks for the actual compile unit - // information. When this happens, the symbol file will be asked to - // parse this compile unit information. - m_compile_units.resize(m_sym_file_up->GetNumCompileUnits()); - } - } - } - return m_compile_units.size(); -} - -lldb::LanguageType SymbolVendor::ParseLanguage(CompileUnit &comp_unit) { - ModuleSP module_sp(GetModule()); - if (module_sp) { - std::lock_guard<std::recursive_mutex> guard(module_sp->GetMutex()); - if (m_sym_file_up) - return m_sym_file_up->ParseLanguage(comp_unit); - } - return eLanguageTypeUnknown; -} - -size_t SymbolVendor::ParseFunctions(CompileUnit &comp_unit) { - ModuleSP module_sp(GetModule()); - if (module_sp) { - std::lock_guard<std::recursive_mutex> guard(module_sp->GetMutex()); - if (m_sym_file_up) - return m_sym_file_up->ParseFunctions(comp_unit); - } - return 0; -} - -bool SymbolVendor::ParseLineTable(CompileUnit &comp_unit) { - ModuleSP module_sp(GetModule()); - if (module_sp) { - std::lock_guard<std::recursive_mutex> guard(module_sp->GetMutex()); - if (m_sym_file_up) - return m_sym_file_up->ParseLineTable(comp_unit); - } - return false; -} - -bool SymbolVendor::ParseDebugMacros(CompileUnit &comp_unit) { - ModuleSP module_sp(GetModule()); - if (module_sp) { - std::lock_guard<std::recursive_mutex> guard(module_sp->GetMutex()); - if (m_sym_file_up) - return m_sym_file_up->ParseDebugMacros(comp_unit); - } - return false; -} -bool SymbolVendor::ParseSupportFiles(CompileUnit &comp_unit, - FileSpecList &support_files) { - ModuleSP module_sp(GetModule()); - if (module_sp) { - std::lock_guard<std::recursive_mutex> guard(module_sp->GetMutex()); - if (m_sym_file_up) - return m_sym_file_up->ParseSupportFiles(comp_unit, support_files); - } - return false; -} - -bool SymbolVendor::ParseIsOptimized(CompileUnit &comp_unit) { - ModuleSP module_sp(GetModule()); - if (module_sp) { - std::lock_guard<std::recursive_mutex> guard(module_sp->GetMutex()); - if (m_sym_file_up) - return m_sym_file_up->ParseIsOptimized(comp_unit); - } - return false; -} - -bool SymbolVendor::ParseImportedModules( - const SymbolContext &sc, std::vector<SourceModule> &imported_modules) { - ModuleSP module_sp(GetModule()); - if (module_sp) { - std::lock_guard<std::recursive_mutex> guard(module_sp->GetMutex()); - if (m_sym_file_up) - return m_sym_file_up->ParseImportedModules(sc, imported_modules); - } - return false; -} - -size_t SymbolVendor::ParseBlocksRecursive(Function &func) { - ModuleSP module_sp(GetModule()); - if (module_sp) { - std::lock_guard<std::recursive_mutex> guard(module_sp->GetMutex()); - if (m_sym_file_up) - return m_sym_file_up->ParseBlocksRecursive(func); - } - return 0; -} - -size_t SymbolVendor::ParseTypes(CompileUnit &comp_unit) { - ModuleSP module_sp(GetModule()); - if (module_sp) { - std::lock_guard<std::recursive_mutex> guard(module_sp->GetMutex()); - if (m_sym_file_up) - return m_sym_file_up->ParseTypes(comp_unit); - } - return 0; -} - -size_t SymbolVendor::ParseVariablesForContext(const SymbolContext &sc) { - ModuleSP module_sp(GetModule()); - if (module_sp) { - std::lock_guard<std::recursive_mutex> guard(module_sp->GetMutex()); - if (m_sym_file_up) - return m_sym_file_up->ParseVariablesForContext(sc); - } - return 0; -} - -Type *SymbolVendor::ResolveTypeUID(lldb::user_id_t type_uid) { - ModuleSP module_sp(GetModule()); - if (module_sp) { - std::lock_guard<std::recursive_mutex> guard(module_sp->GetMutex()); - if (m_sym_file_up) - return m_sym_file_up->ResolveTypeUID(type_uid); - } - return nullptr; -} - -uint32_t SymbolVendor::ResolveSymbolContext(const Address &so_addr, - SymbolContextItem resolve_scope, - SymbolContext &sc) { - ModuleSP module_sp(GetModule()); - if (module_sp) { - std::lock_guard<std::recursive_mutex> guard(module_sp->GetMutex()); - if (m_sym_file_up) - return m_sym_file_up->ResolveSymbolContext(so_addr, resolve_scope, sc); - } - return 0; -} - -uint32_t SymbolVendor::ResolveSymbolContext(const FileSpec &file_spec, - uint32_t line, bool check_inlines, - SymbolContextItem resolve_scope, - SymbolContextList &sc_list) { - ModuleSP module_sp(GetModule()); - if (module_sp) { - std::lock_guard<std::recursive_mutex> guard(module_sp->GetMutex()); - if (m_sym_file_up) - return m_sym_file_up->ResolveSymbolContext(file_spec, line, check_inlines, - resolve_scope, sc_list); - } - return 0; -} - -size_t -SymbolVendor::FindGlobalVariables(ConstString name, - const CompilerDeclContext *parent_decl_ctx, - size_t max_matches, VariableList &variables) { - ModuleSP module_sp(GetModule()); - if (module_sp) { - std::lock_guard<std::recursive_mutex> guard(module_sp->GetMutex()); - if (m_sym_file_up) - return m_sym_file_up->FindGlobalVariables(name, parent_decl_ctx, - max_matches, variables); - } - return 0; -} - -size_t SymbolVendor::FindGlobalVariables(const RegularExpression ®ex, - size_t max_matches, - VariableList &variables) { - ModuleSP module_sp(GetModule()); - if (module_sp) { - std::lock_guard<std::recursive_mutex> guard(module_sp->GetMutex()); - if (m_sym_file_up) - return m_sym_file_up->FindGlobalVariables(regex, max_matches, variables); - } - return 0; -} - -size_t SymbolVendor::FindFunctions(ConstString name, - const CompilerDeclContext *parent_decl_ctx, - FunctionNameType name_type_mask, - bool include_inlines, bool append, - SymbolContextList &sc_list) { - ModuleSP module_sp(GetModule()); - if (module_sp) { - std::lock_guard<std::recursive_mutex> guard(module_sp->GetMutex()); - if (m_sym_file_up) - return m_sym_file_up->FindFunctions(name, parent_decl_ctx, name_type_mask, - include_inlines, append, sc_list); - } - return 0; -} - -size_t SymbolVendor::FindFunctions(const RegularExpression ®ex, - bool include_inlines, bool append, - SymbolContextList &sc_list) { - ModuleSP module_sp(GetModule()); - if (module_sp) { - std::lock_guard<std::recursive_mutex> guard(module_sp->GetMutex()); - if (m_sym_file_up) - return m_sym_file_up->FindFunctions(regex, include_inlines, append, - sc_list); - } - return 0; -} - -size_t SymbolVendor::FindTypes( - ConstString name, const CompilerDeclContext *parent_decl_ctx, - bool append, size_t max_matches, - llvm::DenseSet<lldb_private::SymbolFile *> &searched_symbol_files, - TypeMap &types) { - ModuleSP module_sp(GetModule()); - if (module_sp) { - std::lock_guard<std::recursive_mutex> guard(module_sp->GetMutex()); - if (m_sym_file_up) - return m_sym_file_up->FindTypes(name, parent_decl_ctx, append, - max_matches, searched_symbol_files, - types); - } - if (!append) - types.Clear(); - return 0; -} - -size_t SymbolVendor::FindTypes(const std::vector<CompilerContext> &context, - bool append, TypeMap &types) { - ModuleSP module_sp(GetModule()); - if (module_sp) { - std::lock_guard<std::recursive_mutex> guard(module_sp->GetMutex()); - if (m_sym_file_up) - return m_sym_file_up->FindTypes(context, append, types); - } - if (!append) - types.Clear(); - return 0; -} - -size_t SymbolVendor::GetTypes(SymbolContextScope *sc_scope, TypeClass type_mask, - lldb_private::TypeList &type_list) { - ModuleSP module_sp(GetModule()); - if (module_sp) { - std::lock_guard<std::recursive_mutex> guard(module_sp->GetMutex()); - if (m_sym_file_up) - return m_sym_file_up->GetTypes(sc_scope, type_mask, type_list); - } - return 0; -} - -CompilerDeclContext -SymbolVendor::FindNamespace(ConstString name, - const CompilerDeclContext *parent_decl_ctx) { - CompilerDeclContext namespace_decl_ctx; - ModuleSP module_sp(GetModule()); - if (module_sp) { - std::lock_guard<std::recursive_mutex> guard(module_sp->GetMutex()); - if (m_sym_file_up) - namespace_decl_ctx = m_sym_file_up->FindNamespace(name, parent_decl_ctx); - } - return namespace_decl_ctx; -} - -void SymbolVendor::Dump(Stream *s) { - ModuleSP module_sp(GetModule()); - if (module_sp) { - std::lock_guard<std::recursive_mutex> guard(module_sp->GetMutex()); - - bool show_context = false; - - s->Printf("%p: ", static_cast<void *>(this)); - s->Indent(); - s->PutCString("SymbolVendor"); - if (m_sym_file_up) { - *s << " " << m_sym_file_up->GetPluginName(); - ObjectFile *objfile = m_sym_file_up->GetObjectFile(); - if (objfile) { - const FileSpec &objfile_file_spec = objfile->GetFileSpec(); - if (objfile_file_spec) { - s->PutCString(" ("); - objfile_file_spec.Dump(s); - s->PutChar(')'); - } - } - } - s->EOL(); - if (m_sym_file_up) - m_sym_file_up->Dump(*s); - s->IndentMore(); - m_type_list.Dump(s, show_context); - - CompileUnitConstIter cu_pos, cu_end; - cu_end = m_compile_units.end(); - for (cu_pos = m_compile_units.begin(); cu_pos != cu_end; ++cu_pos) { - // We currently only dump the compile units that have been parsed - if (*cu_pos) - (*cu_pos)->Dump(s, show_context); - } - - if (Symtab *symtab = GetSymtab()) - symtab->Dump(s, nullptr, eSortOrderNone); - - s->IndentLess(); - } -} - -CompUnitSP SymbolVendor::GetCompileUnitAtIndex(size_t idx) { - CompUnitSP cu_sp; - ModuleSP module_sp(GetModule()); - if (module_sp) { - std::lock_guard<std::recursive_mutex> guard(module_sp->GetMutex()); - const size_t num_compile_units = GetNumCompileUnits(); - if (idx < num_compile_units) { - cu_sp = m_compile_units[idx]; - if (cu_sp.get() == nullptr) { - m_compile_units[idx] = m_sym_file_up->ParseCompileUnitAtIndex(idx); - cu_sp = m_compile_units[idx]; - } - } - } - return cu_sp; -} - -FileSpec SymbolVendor::GetMainFileSpec() const { - if (m_sym_file_up) { - const ObjectFile *symfile_objfile = m_sym_file_up->GetObjectFile(); - if (symfile_objfile) - return symfile_objfile->GetFileSpec(); - } - - return FileSpec(); -} - -Symtab *SymbolVendor::GetSymtab() { - ModuleSP module_sp(GetModule()); - if (!module_sp) - return nullptr; - - std::lock_guard<std::recursive_mutex> guard(module_sp->GetMutex()); - - if (m_symtab) - return m_symtab; - - ObjectFile *objfile = module_sp->GetObjectFile(); - if (!objfile) - return nullptr; - - m_symtab = objfile->GetSymtab(); - if (m_symtab && m_sym_file_up) - m_sym_file_up->AddSymbols(*m_symtab); - - return m_symtab; -} - -void SymbolVendor::ClearSymtab() { - ModuleSP module_sp(GetModule()); - if (module_sp) { - ObjectFile *objfile = module_sp->GetObjectFile(); - if (objfile) { - // Clear symbol table from unified section list. - objfile->ClearSymtab(); - } - } -} - -void SymbolVendor::SectionFileAddressesChanged() { - ModuleSP module_sp(GetModule()); - if (module_sp) { - ObjectFile *module_objfile = module_sp->GetObjectFile(); - if (m_sym_file_up) { - ObjectFile *symfile_objfile = m_sym_file_up->GetObjectFile(); - if (symfile_objfile != module_objfile) - symfile_objfile->SectionFileAddressesChanged(); - } - Symtab *symtab = GetSymtab(); - if (symtab) { - symtab->SectionFileAddressesChanged(); - } + if (objfile_sp) + m_sym_file_up.reset(SymbolFile::FindPlugin(objfile_sp)); } } diff --git a/source/Symbol/Symtab.cpp b/source/Symbol/Symtab.cpp index 29c390e83878..c4e6c2ccfb09 100644 --- a/source/Symbol/Symtab.cpp +++ b/source/Symbol/Symtab.cpp @@ -738,7 +738,7 @@ Symbol *Symtab::FindSymbolWithType(SymbolType symbol_type, return nullptr; } -size_t +void Symtab::FindAllSymbolsWithNameAndType(ConstString name, SymbolType symbol_type, std::vector<uint32_t> &symbol_indexes) { @@ -756,10 +756,9 @@ Symtab::FindAllSymbolsWithNameAndType(ConstString name, // the symbols and match the symbol_type if any was given. AppendSymbolIndexesWithNameAndType(name, symbol_type, symbol_indexes); } - return symbol_indexes.size(); } -size_t Symtab::FindAllSymbolsWithNameAndType( +void Symtab::FindAllSymbolsWithNameAndType( ConstString name, SymbolType symbol_type, Debug symbol_debug_type, Visibility symbol_visibility, std::vector<uint32_t> &symbol_indexes) { std::lock_guard<std::recursive_mutex> guard(m_mutex); @@ -777,10 +776,9 @@ size_t Symtab::FindAllSymbolsWithNameAndType( AppendSymbolIndexesWithNameAndType(name, symbol_type, symbol_debug_type, symbol_visibility, symbol_indexes); } - return symbol_indexes.size(); } -size_t Symtab::FindAllSymbolsMatchingRexExAndType( +void Symtab::FindAllSymbolsMatchingRexExAndType( const RegularExpression ®ex, SymbolType symbol_type, Debug symbol_debug_type, Visibility symbol_visibility, std::vector<uint32_t> &symbol_indexes) { @@ -788,7 +786,6 @@ size_t Symtab::FindAllSymbolsMatchingRexExAndType( AppendSymbolIndexesMatchingRegExAndType(regex, symbol_type, symbol_debug_type, symbol_visibility, symbol_indexes); - return symbol_indexes.size(); } Symbol *Symtab::FindFirstSymbolWithNameAndType(ConstString name, @@ -1024,10 +1021,8 @@ void Symtab::SymbolIndicesToSymbolContextList( } } -size_t Symtab::FindFunctionSymbols(ConstString name, - uint32_t name_type_mask, - SymbolContextList &sc_list) { - size_t count = 0; +void Symtab::FindFunctionSymbols(ConstString name, uint32_t name_type_mask, + SymbolContextList &sc_list) { std::vector<uint32_t> symbol_indexes; // eFunctionNameTypeAuto should be pre-resolved by a call to @@ -1108,11 +1103,8 @@ size_t Symtab::FindFunctionSymbols(ConstString name, symbol_indexes.erase( std::unique(symbol_indexes.begin(), symbol_indexes.end()), symbol_indexes.end()); - count = symbol_indexes.size(); SymbolIndicesToSymbolContextList(symbol_indexes, sc_list); } - - return count; } const Symbol *Symtab::GetParent(Symbol *child_symbol) const { diff --git a/source/Symbol/Type.cpp b/source/Symbol/Type.cpp index 4ee8330ce288..5666590c2246 100644 --- a/source/Symbol/Type.cpp +++ b/source/Symbol/Type.cpp @@ -11,6 +11,7 @@ #include "lldb/Core/Module.h" #include "lldb/Utility/DataBufferHeap.h" #include "lldb/Utility/DataExtractor.h" +#include "lldb/Utility/Log.h" #include "lldb/Utility/Scalar.h" #include "lldb/Utility/StreamString.h" @@ -29,15 +30,41 @@ #include "llvm/ADT/StringRef.h" -#include "clang/AST/Decl.h" -#include "clang/AST/DeclObjC.h" - using namespace lldb; using namespace lldb_private; +bool lldb_private::contextMatches(llvm::ArrayRef<CompilerContext> context_chain, + llvm::ArrayRef<CompilerContext> pattern) { + auto ctx = context_chain.begin(); + auto ctx_end = context_chain.end(); + for (const CompilerContext &pat : pattern) { + // Early exit if the pattern is too long. + if (ctx == ctx_end) + return false; + if (*ctx != pat) { + // Skip any number of module matches. + if (pat.kind == CompilerContextKind::AnyModule) { + // Greedily match 0..n modules. + ctx = std::find_if(ctx, ctx_end, [](const CompilerContext &ctx) { + return ctx.kind != CompilerContextKind::Module; + }); + continue; + } + // See if there is a kind mismatch; they should have 1 bit in common. + if (((uint16_t)ctx->kind & (uint16_t)pat.kind) == 0) + return false; + // The name is ignored for AnyModule, but not for AnyType. + if (pat.kind != CompilerContextKind::AnyModule && ctx->name != pat.name) + return false; + } + ++ctx; + } + return true; +} + void CompilerContext::Dump() const { - switch (type) { - case CompilerContextKind::Invalid: + switch (kind) { + default: printf("Invalid"); break; case CompilerContextKind::TranslationUnit: @@ -52,7 +79,7 @@ void CompilerContext::Dump() const { case CompilerContextKind::Class: printf("Class"); break; - case CompilerContextKind::Structure: + case CompilerContextKind::Struct: printf("Structure"); break; case CompilerContextKind::Union: @@ -64,12 +91,18 @@ void CompilerContext::Dump() const { case CompilerContextKind::Variable: printf("Variable"); break; - case CompilerContextKind::Enumeration: + case CompilerContextKind::Enum: printf("Enumeration"); break; case CompilerContextKind::Typedef: printf("Typedef"); break; + case CompilerContextKind::AnyModule: + printf("AnyModule"); + break; + case CompilerContextKind::AnyType: + printf("AnyType"); + break; } printf("(\"%s\")\n", name.GetCString()); } @@ -425,8 +458,6 @@ bool Type::WriteToMemory(ExecutionContext *exe_ctx, lldb::addr_t addr, return false; } -TypeList *Type::GetTypeList() { return GetSymbolFile()->GetTypeList(); } - const Declaration &Type::GetDeclaration() const { return m_decl; } bool Type::ResolveClangType(ResolveState compiler_type_resolve_state) { @@ -488,47 +519,54 @@ bool Type::ResolveClangType(ResolveState compiler_type_resolve_state) { } } else { // We have no encoding type, return void? - TypeSystem *type_system = + auto type_system_or_err = m_symbol_file->GetTypeSystemForLanguage(eLanguageTypeC); - CompilerType void_compiler_type = - type_system->GetBasicTypeFromAST(eBasicTypeVoid); - switch (m_encoding_uid_type) { - case eEncodingIsUID: - m_compiler_type = void_compiler_type; - break; + if (auto err = type_system_or_err.takeError()) { + LLDB_LOG_ERROR( + lldb_private::GetLogIfAnyCategoriesSet(LIBLLDB_LOG_SYMBOLS), + std::move(err), + "Unable to construct void type from ClangASTContext"); + } else { + CompilerType void_compiler_type = + type_system_or_err->GetBasicTypeFromAST(eBasicTypeVoid); + switch (m_encoding_uid_type) { + case eEncodingIsUID: + m_compiler_type = void_compiler_type; + break; - case eEncodingIsConstUID: - m_compiler_type = void_compiler_type.AddConstModifier(); - break; + case eEncodingIsConstUID: + m_compiler_type = void_compiler_type.AddConstModifier(); + break; - case eEncodingIsRestrictUID: - m_compiler_type = void_compiler_type.AddRestrictModifier(); - break; + case eEncodingIsRestrictUID: + m_compiler_type = void_compiler_type.AddRestrictModifier(); + break; - case eEncodingIsVolatileUID: - m_compiler_type = void_compiler_type.AddVolatileModifier(); - break; + case eEncodingIsVolatileUID: + m_compiler_type = void_compiler_type.AddVolatileModifier(); + break; - case eEncodingIsTypedefUID: - m_compiler_type = void_compiler_type.CreateTypedef( - m_name.AsCString("__lldb_invalid_typedef_name"), - GetSymbolFile()->GetDeclContextContainingUID(GetID())); - break; + case eEncodingIsTypedefUID: + m_compiler_type = void_compiler_type.CreateTypedef( + m_name.AsCString("__lldb_invalid_typedef_name"), + GetSymbolFile()->GetDeclContextContainingUID(GetID())); + break; - case eEncodingIsPointerUID: - m_compiler_type = void_compiler_type.GetPointerType(); - break; + case eEncodingIsPointerUID: + m_compiler_type = void_compiler_type.GetPointerType(); + break; - case eEncodingIsLValueReferenceUID: - m_compiler_type = void_compiler_type.GetLValueReferenceType(); - break; + case eEncodingIsLValueReferenceUID: + m_compiler_type = void_compiler_type.GetLValueReferenceType(); + break; - case eEncodingIsRValueReferenceUID: - m_compiler_type = void_compiler_type.GetRValueReferenceType(); - break; + case eEncodingIsRValueReferenceUID: + m_compiler_type = void_compiler_type.GetRValueReferenceType(); + break; - default: - llvm_unreachable("Unhandled encoding_data_type."); + default: + llvm_unreachable("Unhandled encoding_data_type."); + } } } diff --git a/source/Symbol/TypeMap.cpp b/source/Symbol/TypeMap.cpp index bc6e272449f0..4ee1026bed24 100644 --- a/source/Symbol/TypeMap.cpp +++ b/source/Symbol/TypeMap.cpp @@ -8,18 +8,6 @@ #include <vector> -#include "clang/AST/ASTConsumer.h" -#include "clang/AST/ASTContext.h" -#include "clang/AST/Decl.h" -#include "clang/AST/DeclCXX.h" -#include "clang/AST/DeclGroup.h" - -#include "clang/Basic/Builtins.h" -#include "clang/Basic/IdentifierTable.h" -#include "clang/Basic/LangOptions.h" -#include "clang/Basic/SourceManager.h" -#include "clang/Basic/TargetInfo.h" - #include "llvm/Support/FormattedStream.h" #include "llvm/Support/raw_ostream.h" @@ -30,7 +18,6 @@ using namespace lldb; using namespace lldb_private; -using namespace clang; TypeMap::TypeMap() : m_types() {} diff --git a/source/Symbol/TypeSystem.cpp b/source/Symbol/TypeSystem.cpp index fb9c8e71acb3..c63f24aea335 100644 --- a/source/Symbol/TypeSystem.cpp +++ b/source/Symbol/TypeSystem.cpp @@ -20,10 +20,29 @@ #include "lldb/Core/PluginManager.h" #include "lldb/Symbol/CompilerType.h" +#include "lldb/Target/Language.h" using namespace lldb_private; using namespace lldb; +/// A 64-bit SmallBitVector is only small up to 64-7 bits, and the +/// setBitsInMask interface wants to write full bytes. +static const size_t g_num_small_bitvector_bits = 64 - 8; +static_assert(eNumLanguageTypes < g_num_small_bitvector_bits, + "Languages bit vector is no longer small on 64 bit systems"); +LanguageSet::LanguageSet() : bitvector(eNumLanguageTypes, 0) {} + +llvm::Optional<LanguageType> LanguageSet::GetSingularLanguage() { + if (bitvector.count() == 1) + return (LanguageType)bitvector.find_first(); + return {}; +} + +void LanguageSet::Insert(LanguageType language) { bitvector.set(language); } +size_t LanguageSet::Size() const { return bitvector.count(); } +bool LanguageSet::Empty() const { return bitvector.none(); } +bool LanguageSet::operator[](unsigned i) const { return bitvector[i]; } + TypeSystem::TypeSystem(LLVMCastKind kind) : m_kind(kind), m_sym_file(nullptr) {} TypeSystem::~TypeSystem() {} @@ -198,65 +217,140 @@ void TypeSystemMap::ForEach(std::function<bool(TypeSystem *)> const &callback) { } } -TypeSystem *TypeSystemMap::GetTypeSystemForLanguage(lldb::LanguageType language, - Module *module, - bool can_create) { +llvm::Expected<TypeSystem &> +TypeSystemMap::GetTypeSystemForLanguage(lldb::LanguageType language, + Module *module, bool can_create) { + llvm::Error error = llvm::Error::success(); + assert(!error); // Check the success value when assertions are enabled std::lock_guard<std::mutex> guard(m_mutex); - collection::iterator pos = m_map.find(language); - if (pos != m_map.end()) - return pos->second.get(); - - for (const auto &pair : m_map) { - if (pair.second && pair.second->SupportsLanguage(language)) { - // Add a new mapping for "language" to point to an already existing - // TypeSystem that supports this language - AddToMap(language, pair.second); - return pair.second.get(); + if (m_clear_in_progress) { + error = llvm::make_error<llvm::StringError>( + "Unable to get TypeSystem because TypeSystemMap is being cleared", + llvm::inconvertibleErrorCode()); + } else { + collection::iterator pos = m_map.find(language); + if (pos != m_map.end()) { + auto *type_system = pos->second.get(); + if (type_system) { + llvm::consumeError(std::move(error)); + return *type_system; + } + error = llvm::make_error<llvm::StringError>( + "TypeSystem for language " + + llvm::toStringRef(Language::GetNameForLanguageType(language)) + + " doesn't exist", + llvm::inconvertibleErrorCode()); + return std::move(error); } - } - if (!can_create) - return nullptr; + for (const auto &pair : m_map) { + if (pair.second && pair.second->SupportsLanguage(language)) { + // Add a new mapping for "language" to point to an already existing + // TypeSystem that supports this language + m_map[language] = pair.second; + if (pair.second.get()) { + llvm::consumeError(std::move(error)); + return *pair.second.get(); + } + error = llvm::make_error<llvm::StringError>( + "TypeSystem for language " + + llvm::toStringRef(Language::GetNameForLanguageType(language)) + + " doesn't exist", + llvm::inconvertibleErrorCode()); + return std::move(error); + } + } + + if (!can_create) { + error = llvm::make_error<llvm::StringError>( + "Unable to find type system for language " + + llvm::toStringRef(Language::GetNameForLanguageType(language)), + llvm::inconvertibleErrorCode()); + } else { + // Cache even if we get a shared pointer that contains a null type system + // back + auto type_system_sp = TypeSystem::CreateInstance(language, module); + m_map[language] = type_system_sp; + if (type_system_sp.get()) { + llvm::consumeError(std::move(error)); + return *type_system_sp.get(); + } + error = llvm::make_error<llvm::StringError>( + "TypeSystem for language " + + llvm::toStringRef(Language::GetNameForLanguageType(language)) + + " doesn't exist", + llvm::inconvertibleErrorCode()); + } + } - // Cache even if we get a shared pointer that contains null type system back - lldb::TypeSystemSP type_system_sp = - TypeSystem::CreateInstance(language, module); - AddToMap(language, type_system_sp); - return type_system_sp.get(); + return std::move(error); } -TypeSystem *TypeSystemMap::GetTypeSystemForLanguage(lldb::LanguageType language, - Target *target, - bool can_create) { +llvm::Expected<TypeSystem &> +TypeSystemMap::GetTypeSystemForLanguage(lldb::LanguageType language, + Target *target, bool can_create) { + llvm::Error error = llvm::Error::success(); + assert(!error); // Check the success value when assertions are enabled std::lock_guard<std::mutex> guard(m_mutex); - collection::iterator pos = m_map.find(language); - if (pos != m_map.end()) - return pos->second.get(); + if (m_clear_in_progress) { + error = llvm::make_error<llvm::StringError>( + "Unable to get TypeSystem because TypeSystemMap is being cleared", + llvm::inconvertibleErrorCode()); + } else { + collection::iterator pos = m_map.find(language); + if (pos != m_map.end()) { + auto *type_system = pos->second.get(); + if (type_system) { + llvm::consumeError(std::move(error)); + return *type_system; + } + error = llvm::make_error<llvm::StringError>( + "TypeSystem for language " + + llvm::toStringRef(Language::GetNameForLanguageType(language)) + + " doesn't exist", + llvm::inconvertibleErrorCode()); + return std::move(error); + } - for (const auto &pair : m_map) { - if (pair.second && pair.second->SupportsLanguage(language)) { - // Add a new mapping for "language" to point to an already existing - // TypeSystem that supports this language + for (const auto &pair : m_map) { + if (pair.second && pair.second->SupportsLanguage(language)) { + // Add a new mapping for "language" to point to an already existing + // TypeSystem that supports this language + m_map[language] = pair.second; + if (pair.second.get()) { + llvm::consumeError(std::move(error)); + return *pair.second.get(); + } + error = llvm::make_error<llvm::StringError>( + "TypeSystem for language " + + llvm::toStringRef(Language::GetNameForLanguageType(language)) + + " doesn't exist", + llvm::inconvertibleErrorCode()); + return std::move(error); + } + } - AddToMap(language, pair.second); - return pair.second.get(); + if (!can_create) { + error = llvm::make_error<llvm::StringError>( + "Unable to find type system for language " + + llvm::toStringRef(Language::GetNameForLanguageType(language)), + llvm::inconvertibleErrorCode()); + } else { + // Cache even if we get a shared pointer that contains a null type system + // back + auto type_system_sp = TypeSystem::CreateInstance(language, target); + m_map[language] = type_system_sp; + if (type_system_sp.get()) { + llvm::consumeError(std::move(error)); + return *type_system_sp.get(); + } + error = llvm::make_error<llvm::StringError>( + "TypeSystem for language " + + llvm::toStringRef(Language::GetNameForLanguageType(language)) + + " doesn't exist", + llvm::inconvertibleErrorCode()); } } - if (!can_create) - return nullptr; - - // Cache even if we get a shared pointer that contains null type system back - lldb::TypeSystemSP type_system_sp; - if (!m_clear_in_progress) - type_system_sp = TypeSystem::CreateInstance(language, target); - - AddToMap(language, type_system_sp); - return type_system_sp.get(); -} - -void TypeSystemMap::AddToMap(lldb::LanguageType language, - lldb::TypeSystemSP const &type_system_sp) { - if (!m_clear_in_progress) - m_map[language] = type_system_sp; + return std::move(error); } diff --git a/source/Symbol/UnwindPlan.cpp b/source/Symbol/UnwindPlan.cpp index 774f9cb587ee..15443ce5d8ac 100644 --- a/source/Symbol/UnwindPlan.cpp +++ b/source/Symbol/UnwindPlan.cpp @@ -170,7 +170,8 @@ operator==(const UnwindPlan::Row::FAValue &rhs) const { if (m_type == rhs.m_type) { switch (m_type) { case unspecified: - return true; + case isRaSearch: + return m_value.ra_search_offset == rhs.m_value.ra_search_offset; case isRegisterPlusOffset: return m_value.reg.offset == rhs.m_value.reg.offset; @@ -205,9 +206,12 @@ void UnwindPlan::Row::FAValue::Dump(Stream &s, const UnwindPlan *unwind_plan, llvm::makeArrayRef(m_value.expr.opcodes, m_value.expr.length), thread); break; - default: + case unspecified: s.PutCString("unspecified"); break; + case isRaSearch: + s.Printf("RaSearch@SP%+d", m_value.ra_search_offset); + break; } } @@ -402,10 +406,10 @@ const UnwindPlan::RowSP UnwindPlan::GetRowAtIndex(uint32_t idx) const { return m_row_list[idx]; else { Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_UNWIND)); - if (log) - log->Printf("error: UnwindPlan::GetRowAtIndex(idx = %u) invalid index " - "(number rows is %u)", - idx, (uint32_t)m_row_list.size()); + LLDB_LOGF(log, + "error: UnwindPlan::GetRowAtIndex(idx = %u) invalid index " + "(number rows is %u)", + idx, (uint32_t)m_row_list.size()); return UnwindPlan::RowSP(); } } @@ -413,8 +417,7 @@ const UnwindPlan::RowSP UnwindPlan::GetRowAtIndex(uint32_t idx) const { const UnwindPlan::RowSP UnwindPlan::GetLastRow() const { if (m_row_list.empty()) { Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_UNWIND)); - if (log) - log->Printf("UnwindPlan::GetLastRow() when rows are empty"); + LLDB_LOGF(log, "UnwindPlan::GetLastRow() when rows are empty"); return UnwindPlan::RowSP(); } return m_row_list.back(); @@ -434,13 +437,14 @@ bool UnwindPlan::PlanValidAtAddress(Address addr) { if (log) { StreamString s; if (addr.Dump(&s, nullptr, Address::DumpStyleSectionNameOffset)) { - log->Printf("UnwindPlan is invalid -- no unwind rows for UnwindPlan " - "'%s' at address %s", - m_source_name.GetCString(), s.GetData()); + LLDB_LOGF(log, + "UnwindPlan is invalid -- no unwind rows for UnwindPlan " + "'%s' at address %s", + m_source_name.GetCString(), s.GetData()); } else { - log->Printf( - "UnwindPlan is invalid -- no unwind rows for UnwindPlan '%s'", - m_source_name.GetCString()); + LLDB_LOGF(log, + "UnwindPlan is invalid -- no unwind rows for UnwindPlan '%s'", + m_source_name.GetCString()); } } return false; @@ -456,13 +460,15 @@ bool UnwindPlan::PlanValidAtAddress(Address addr) { if (log) { StreamString s; if (addr.Dump(&s, nullptr, Address::DumpStyleSectionNameOffset)) { - log->Printf("UnwindPlan is invalid -- no CFA register defined in row 0 " - "for UnwindPlan '%s' at address %s", - m_source_name.GetCString(), s.GetData()); + LLDB_LOGF(log, + "UnwindPlan is invalid -- no CFA register defined in row 0 " + "for UnwindPlan '%s' at address %s", + m_source_name.GetCString(), s.GetData()); } else { - log->Printf("UnwindPlan is invalid -- no CFA register defined in row 0 " - "for UnwindPlan '%s'", - m_source_name.GetCString()); + LLDB_LOGF(log, + "UnwindPlan is invalid -- no CFA register defined in row 0 " + "for UnwindPlan '%s'", + m_source_name.GetCString()); } } return false; diff --git a/source/Symbol/UnwindTable.cpp b/source/Symbol/UnwindTable.cpp index a8f451dc4643..045957a67b3b 100644 --- a/source/Symbol/UnwindTable.cpp +++ b/source/Symbol/UnwindTable.cpp @@ -13,6 +13,7 @@ #include "lldb/Core/Module.h" #include "lldb/Core/Section.h" #include "lldb/Symbol/ArmUnwindInfo.h" +#include "lldb/Symbol/CallFrameInfo.h" #include "lldb/Symbol/CompactUnwindInfo.h" #include "lldb/Symbol/DWARFCallFrameInfo.h" #include "lldb/Symbol/FuncUnwinders.h" @@ -29,7 +30,8 @@ using namespace lldb_private; UnwindTable::UnwindTable(Module &module) : m_module(module), m_unwinds(), m_initialized(false), m_mutex(), - m_eh_frame_up(), m_compact_unwind_up(), m_arm_unwind_up() {} + m_object_file_unwind_up(), m_eh_frame_up(), m_compact_unwind_up(), + m_arm_unwind_up() {} // We can't do some of this initialization when the ObjectFile is running its // ctor; delay doing it until needed for something. @@ -47,6 +49,8 @@ void UnwindTable::Initialize() { if (!object_file) return; + m_object_file_unwind_up = object_file->CreateCallFrameInfo(); + SectionList *sl = m_module.GetSectionList(); if (!sl) return; @@ -83,7 +87,12 @@ llvm::Optional<AddressRange> UnwindTable::GetAddressRange(const Address &addr, SymbolContext &sc) { AddressRange range; - // First check the symbol context + // First check the unwind info from the object file plugin + if (m_object_file_unwind_up && + m_object_file_unwind_up->GetAddressRange(addr, range)) + return range; + + // Check the symbol context if (sc.GetAddressRange(eSymbolContextFunction | eSymbolContextSymbol, 0, false, range) && range.GetBaseAddress().IsValid()) @@ -162,6 +171,11 @@ void UnwindTable::Dump(Stream &s) { s.EOL(); } +lldb_private::CallFrameInfo *UnwindTable::GetObjectFileUnwindInfo() { + Initialize(); + return m_object_file_unwind_up.get(); +} + DWARFCallFrameInfo *UnwindTable::GetEHFrameInfo() { Initialize(); return m_eh_frame_up.get(); @@ -182,11 +196,7 @@ ArmUnwindInfo *UnwindTable::GetArmUnwindInfo() { return m_arm_unwind_up.get(); } -SymbolFile *UnwindTable::GetSymbolFile() { - if (SymbolVendor *vendor = m_module.GetSymbolVendor()) - return vendor->GetSymbolFile(); - return nullptr; -} +SymbolFile *UnwindTable::GetSymbolFile() { return m_module.GetSymbolFile(); } ArchSpec UnwindTable::GetArchitecture() { return m_module.GetArchitecture(); } diff --git a/source/Symbol/Variable.cpp b/source/Symbol/Variable.cpp index 29a7a5191f61..3f3d7c198f15 100644 --- a/source/Symbol/Variable.cpp +++ b/source/Symbol/Variable.cpp @@ -35,14 +35,12 @@ using namespace lldb; using namespace lldb_private; -// Variable constructor -Variable::Variable( - lldb::user_id_t uid, const char *name, - const char *mangled, // The mangled or fully qualified name of the variable. - const lldb::SymbolFileTypeSP &symfile_type_sp, ValueType scope, - SymbolContextScope *context, const RangeList &scope_range, - Declaration *decl_ptr, const DWARFExpression &location, bool external, - bool artificial, bool static_member) +Variable::Variable(lldb::user_id_t uid, const char *name, const char *mangled, + const lldb::SymbolFileTypeSP &symfile_type_sp, + ValueType scope, SymbolContextScope *context, + const RangeList &scope_range, Declaration *decl_ptr, + const DWARFExpression &location, bool external, + bool artificial, bool static_member) : UserID(uid), m_name(name), m_mangled(ConstString(mangled)), m_symfile_type_sp(symfile_type_sp), m_scope(scope), m_owner_scope(context), m_scope_range(scope_range), @@ -50,14 +48,22 @@ Variable::Variable( m_artificial(artificial), m_loc_is_const_data(false), m_static_member(static_member) {} -// Destructor Variable::~Variable() {} lldb::LanguageType Variable::GetLanguage() const { - SymbolContext variable_sc; - m_owner_scope->CalculateSymbolContext(&variable_sc); - if (variable_sc.comp_unit) - return variable_sc.comp_unit->GetLanguage(); + lldb::LanguageType lang = m_mangled.GuessLanguage(); + if (lang != lldb::eLanguageTypeUnknown) + return lang; + + if (auto *func = m_owner_scope->CalculateSymbolContextFunction()) { + if ((lang = func->GetLanguage()) != lldb::eLanguageTypeUnknown) + return lang; + } else if (auto *comp_unit = + m_owner_scope->CalculateSymbolContextCompileUnit()) { + if ((lang = comp_unit->GetLanguage()) != lldb::eLanguageTypeUnknown) + return lang; + } + return lldb::eLanguageTypeUnknown; } @@ -381,21 +387,15 @@ Status Variable::GetValuesForVariableExpressionPath( default: { static RegularExpression g_regex( llvm::StringRef("^([A-Za-z_:][A-Za-z_0-9:]*)(.*)")); - RegularExpression::Match regex_match(1); - std::string variable_name; + llvm::SmallVector<llvm::StringRef, 2> matches; variable_list.Clear(); - if (!g_regex.Execute(variable_expr_path, ®ex_match)) { - error.SetErrorStringWithFormat( - "unable to extract a variable name from '%s'", - variable_expr_path.str().c_str()); - return error; - } - if (!regex_match.GetMatchAtIndex(variable_expr_path, 1, variable_name)) { + if (!g_regex.Execute(variable_expr_path, &matches)) { error.SetErrorStringWithFormat( "unable to extract a variable name from '%s'", variable_expr_path.str().c_str()); return error; } + std::string variable_name = matches[1].str(); if (!callback(baton, variable_name.c_str(), variable_list)) { error.SetErrorString("unknown error"); return error; @@ -485,24 +485,21 @@ static void PrivateAutoComplete( StackFrame *frame, llvm::StringRef partial_path, const llvm::Twine &prefix_path, // Anything that has been resolved already will be in here - const CompilerType &compiler_type, - StringList &matches, bool &word_complete); + const CompilerType &compiler_type, CompletionRequest &request); static void PrivateAutoCompleteMembers( StackFrame *frame, const std::string &partial_member_name, llvm::StringRef partial_path, const llvm::Twine &prefix_path, // Anything that has been resolved already will be in here - const CompilerType &compiler_type, - StringList &matches, bool &word_complete); + const CompilerType &compiler_type, CompletionRequest &request); static void PrivateAutoCompleteMembers( StackFrame *frame, const std::string &partial_member_name, llvm::StringRef partial_path, const llvm::Twine &prefix_path, // Anything that has been resolved already will be in here - const CompilerType &compiler_type, - StringList &matches, bool &word_complete) { + const CompilerType &compiler_type, CompletionRequest &request) { // We are in a type parsing child members const uint32_t num_bases = compiler_type.GetNumDirectBaseClasses(); @@ -512,9 +509,9 @@ static void PrivateAutoCompleteMembers( CompilerType base_class_type = compiler_type.GetDirectBaseClassAtIndex(i, nullptr); - PrivateAutoCompleteMembers( - frame, partial_member_name, partial_path, prefix_path, - base_class_type.GetCanonicalType(), matches, word_complete); + PrivateAutoCompleteMembers(frame, partial_member_name, partial_path, + prefix_path, + base_class_type.GetCanonicalType(), request); } } @@ -525,9 +522,9 @@ static void PrivateAutoCompleteMembers( CompilerType vbase_class_type = compiler_type.GetVirtualBaseClassAtIndex(i, nullptr); - PrivateAutoCompleteMembers( - frame, partial_member_name, partial_path, prefix_path, - vbase_class_type.GetCanonicalType(), matches, word_complete); + PrivateAutoCompleteMembers(frame, partial_member_name, partial_path, + prefix_path, + vbase_class_type.GetCanonicalType(), request); } } @@ -548,9 +545,9 @@ static void PrivateAutoCompleteMembers( frame, partial_path, prefix_path + member_name, // Anything that has been resolved // already will be in here - member_compiler_type.GetCanonicalType(), matches, word_complete); + member_compiler_type.GetCanonicalType(), request); } else { - matches.AppendString((prefix_path + member_name).str()); + request.AddCompletion((prefix_path + member_name).str()); } } } @@ -561,8 +558,7 @@ static void PrivateAutoComplete( StackFrame *frame, llvm::StringRef partial_path, const llvm::Twine &prefix_path, // Anything that has been resolved already will be in here - const CompilerType &compiler_type, - StringList &matches, bool &word_complete) { + const CompilerType &compiler_type, CompletionRequest &request) { // printf ("\nPrivateAutoComplete()\n\tprefix_path = '%s'\n\tpartial_path = // '%s'\n", prefix_path.c_str(), partial_path.c_str()); std::string remaining_partial_path; @@ -583,15 +579,14 @@ static void PrivateAutoComplete( case eTypeClassReference: case eTypeClassTypedef: case eTypeClassVector: { - matches.AppendString(prefix_path.str()); - word_complete = matches.GetSize() == 1; + request.AddCompletion(prefix_path.str()); } break; case eTypeClassClass: case eTypeClassStruct: case eTypeClassUnion: if (prefix_path.str().back() != '.') - matches.AppendString((prefix_path + ".").str()); + request.AddCompletion((prefix_path + ".").str()); break; case eTypeClassObjCObject: @@ -601,10 +596,9 @@ static void PrivateAutoComplete( case eTypeClassPointer: { bool omit_empty_base_classes = true; if (compiler_type.GetNumChildren(omit_empty_base_classes, nullptr) > 0) - matches.AppendString((prefix_path + "->").str()); + request.AddCompletion((prefix_path + "->").str()); else { - matches.AppendString(prefix_path.str()); - word_complete = true; + request.AddCompletion(prefix_path.str()); } } break; } @@ -618,7 +612,7 @@ static void PrivateAutoComplete( const size_t num_variables = variable_list->GetSize(); for (size_t i = 0; i < num_variables; ++i) { Variable *variable = variable_list->GetVariableAtIndex(i).get(); - matches.AppendString(variable->GetName().AsCString()); + request.AddCompletion(variable->GetName().AsCString()); } } } @@ -629,14 +623,14 @@ static void PrivateAutoComplete( case '*': if (prefix_path.str().empty()) { PrivateAutoComplete(frame, partial_path.substr(1), "*", compiler_type, - matches, word_complete); + request); } break; case '&': if (prefix_path.isTriviallyEmpty()) { PrivateAutoComplete(frame, partial_path.substr(1), std::string("&"), - compiler_type, matches, word_complete); + compiler_type, request); } break; @@ -648,14 +642,14 @@ static void PrivateAutoComplete( CompilerType pointee_type(compiler_type.GetPointeeType()); if (partial_path.size() > 2 && partial_path[2]) { // If there is more after the "->", then search deeper - PrivateAutoComplete( - frame, partial_path.substr(2), prefix_path + "->", - pointee_type.GetCanonicalType(), matches, word_complete); + PrivateAutoComplete(frame, partial_path.substr(2), + prefix_path + "->", + pointee_type.GetCanonicalType(), request); } else { // Nothing after the "->", so list all members PrivateAutoCompleteMembers( frame, std::string(), std::string(), prefix_path + "->", - pointee_type.GetCanonicalType(), matches, word_complete); + pointee_type.GetCanonicalType(), request); } } break; default: @@ -673,14 +667,13 @@ static void PrivateAutoComplete( if (partial_path.size() > 1 && partial_path[1]) { // If there is more after the ".", then search deeper PrivateAutoComplete(frame, partial_path.substr(1), - prefix_path + ".", compiler_type, matches, - word_complete); + prefix_path + ".", compiler_type, request); } else { // Nothing after the ".", so list all members PrivateAutoCompleteMembers(frame, std::string(), partial_path, prefix_path + ".", compiler_type, - matches, word_complete); + request); } break; default: @@ -706,8 +699,7 @@ static void PrivateAutoComplete( if (compiler_type.IsValid()) { PrivateAutoCompleteMembers(frame, token, remaining_partial_path, - prefix_path, compiler_type, matches, - word_complete); + prefix_path, compiler_type, request); } else if (frame) { // We haven't found our variable yet const bool get_file_globals = true; @@ -736,13 +728,12 @@ static void PrivateAutoComplete( frame, remaining_partial_path, prefix_path + token, // Anything that has been resolved // already will be in here - variable_compiler_type.GetCanonicalType(), matches, - word_complete); + variable_compiler_type.GetCanonicalType(), request); } else { - matches.AppendString((prefix_path + variable_name).str()); + request.AddCompletion((prefix_path + variable_name).str()); } } else if (remaining_partial_path.empty()) { - matches.AppendString((prefix_path + variable_name).str()); + request.AddCompletion((prefix_path + variable_name).str()); } } } @@ -753,16 +744,10 @@ static void PrivateAutoComplete( } } -size_t Variable::AutoComplete(const ExecutionContext &exe_ctx, - CompletionRequest &request) { +void Variable::AutoComplete(const ExecutionContext &exe_ctx, + CompletionRequest &request) { CompilerType compiler_type; - bool word_complete = false; - StringList matches; PrivateAutoComplete(exe_ctx.GetFramePtr(), request.GetCursorArgumentPrefix(), - "", compiler_type, matches, word_complete); - request.SetWordComplete(word_complete); - request.AddCompletions(matches); - - return request.GetNumberOfMatches(); + "", compiler_type, request); } diff --git a/source/Symbol/VerifyDecl.cpp b/source/Symbol/VerifyDecl.cpp deleted file mode 100644 index 1873d3a5d03c..000000000000 --- a/source/Symbol/VerifyDecl.cpp +++ /dev/null @@ -1,15 +0,0 @@ -//===-- VerifyDecl.cpp ------------------------------------------*- C++ -*-===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// - -#include "lldb/Symbol/VerifyDecl.h" -#include "clang/AST/DeclBase.h" - -void lldb_private::VerifyDecl(clang::Decl *decl) { - assert(decl && "VerifyDecl called with nullptr?"); - decl->getAccess(); -} diff --git a/source/Target/ABI.cpp b/source/Target/ABI.cpp index 28cd9aec665c..005261e0ddee 100644 --- a/source/Target/ABI.cpp +++ b/source/Target/ABI.cpp @@ -15,6 +15,8 @@ #include "lldb/Symbol/TypeSystem.h" #include "lldb/Target/Target.h" #include "lldb/Target/Thread.h" +#include "lldb/Utility/Log.h" +#include "llvm/Support/TargetRegistry.h" using namespace lldb; using namespace lldb_private; @@ -210,3 +212,20 @@ bool ABI::GetFallbackRegisterLocation( return false; } + +std::unique_ptr<llvm::MCRegisterInfo> ABI::MakeMCRegisterInfo(const ArchSpec &arch) { + std::string triple = arch.GetTriple().getTriple(); + std::string lookup_error; + const llvm::Target *target = + llvm::TargetRegistry::lookupTarget(triple, lookup_error); + if (!target) { + LLDB_LOG(GetLogIfAllCategoriesSet(LIBLLDB_LOG_PROCESS), + "Failed to create an llvm target for {0}: {1}", triple, + lookup_error); + return nullptr; + } + std::unique_ptr<llvm::MCRegisterInfo> info_up( + target->createMCRegInfo(triple)); + assert(info_up); + return info_up; +} diff --git a/source/Target/ExecutionContext.cpp b/source/Target/ExecutionContext.cpp index 77327372f88b..a24a098eb300 100644 --- a/source/Target/ExecutionContext.cpp +++ b/source/Target/ExecutionContext.cpp @@ -183,9 +183,9 @@ uint32_t ExecutionContext::GetAddressByteSize() const { lldb::ByteOrder ExecutionContext::GetByteOrder() const { if (m_target_sp && m_target_sp->GetArchitecture().IsValid()) - m_target_sp->GetArchitecture().GetByteOrder(); + return m_target_sp->GetArchitecture().GetByteOrder(); if (m_process_sp) - m_process_sp->GetByteOrder(); + return m_process_sp->GetByteOrder(); return endian::InlHostByteOrder(); } diff --git a/source/Target/Language.cpp b/source/Target/Language.cpp index 3c3ef2841d44..43d0be0f737c 100644 --- a/source/Target/Language.cpp +++ b/source/Target/Language.cpp @@ -357,26 +357,16 @@ std::set<lldb::LanguageType> Language::GetSupportedLanguages() { return supported_languages; } -void Language::GetLanguagesSupportingTypeSystems( - std::set<lldb::LanguageType> &languages, - std::set<lldb::LanguageType> &languages_for_expressions) { - uint32_t idx = 0; - - while (TypeSystemEnumerateSupportedLanguages enumerate = PluginManager:: - GetTypeSystemEnumerateSupportedLanguagesCallbackAtIndex(idx++)) { - (*enumerate)(languages, languages_for_expressions); - } +LanguageSet Language::GetLanguagesSupportingTypeSystems() { + return PluginManager::GetAllTypeSystemSupportedLanguagesForTypes(); } -void Language::GetLanguagesSupportingREPLs( - std::set<lldb::LanguageType> &languages) { - uint32_t idx = 0; +LanguageSet Language::GetLanguagesSupportingTypeSystemsForExpressions() { + return PluginManager::GetAllTypeSystemSupportedLanguagesForExpressions(); +} - while (REPLEnumerateSupportedLanguages enumerate = - PluginManager::GetREPLEnumerateSupportedLanguagesCallbackAtIndex( - idx++)) { - (*enumerate)(languages); - } +LanguageSet Language::GetLanguagesSupportingREPLs() { + return PluginManager::GetREPLAllTypeSystemSupportedLanguages(); } std::unique_ptr<Language::TypeScavenger> Language::GetTypeScavenger() { diff --git a/source/Target/LanguageRuntime.cpp b/source/Target/LanguageRuntime.cpp index dd4415810613..999ac99e93c3 100644 --- a/source/Target/LanguageRuntime.cpp +++ b/source/Target/LanguageRuntime.cpp @@ -111,12 +111,11 @@ public: ~ExceptionBreakpointResolver() override = default; Searcher::CallbackReturn SearchCallback(SearchFilter &filter, - SymbolContext &context, Address *addr, - bool containing) override { + SymbolContext &context, + Address *addr) override { if (SetActualResolver()) - return m_actual_resolver_sp->SearchCallback(filter, context, addr, - containing); + return m_actual_resolver_sp->SearchCallback(filter, context, addr); else return eCallbackReturnStop; } diff --git a/source/Target/Memory.cpp b/source/Target/Memory.cpp index 31a378069cec..7c77cc06eb03 100644 --- a/source/Target/Memory.cpp +++ b/source/Target/Memory.cpp @@ -348,10 +348,11 @@ AllocatedMemoryCache::AllocatePage(uint32_t byte_size, uint32_t permissions, Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_PROCESS)); if (log) { - log->Printf("Process::DoAllocateMemory (byte_size = 0x%8.8" PRIx32 - ", permissions = %s) => 0x%16.16" PRIx64, - (uint32_t)page_byte_size, GetPermissionsAsCString(permissions), - (uint64_t)addr); + LLDB_LOGF(log, + "Process::DoAllocateMemory (byte_size = 0x%8.8" PRIx32 + ", permissions = %s) => 0x%16.16" PRIx64, + (uint32_t)page_byte_size, GetPermissionsAsCString(permissions), + (uint64_t)addr); } if (addr != LLDB_INVALID_ADDRESS) { @@ -385,12 +386,11 @@ lldb::addr_t AllocatedMemoryCache::AllocateMemory(size_t byte_size, addr = block_sp->ReserveBlock(byte_size); } Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_PROCESS)); - if (log) - log->Printf( - "AllocatedMemoryCache::AllocateMemory (byte_size = 0x%8.8" PRIx32 - ", permissions = %s) => 0x%16.16" PRIx64, - (uint32_t)byte_size, GetPermissionsAsCString(permissions), - (uint64_t)addr); + LLDB_LOGF(log, + "AllocatedMemoryCache::AllocateMemory (byte_size = 0x%8.8" PRIx32 + ", permissions = %s) => 0x%16.16" PRIx64, + (uint32_t)byte_size, GetPermissionsAsCString(permissions), + (uint64_t)addr); return addr; } @@ -406,9 +406,9 @@ bool AllocatedMemoryCache::DeallocateMemory(lldb::addr_t addr) { } } Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_PROCESS)); - if (log) - log->Printf("AllocatedMemoryCache::DeallocateMemory (addr = 0x%16.16" PRIx64 - ") => %i", - (uint64_t)addr, success); + LLDB_LOGF(log, + "AllocatedMemoryCache::DeallocateMemory (addr = 0x%16.16" PRIx64 + ") => %i", + (uint64_t)addr, success); return success; } diff --git a/source/Target/ModuleCache.cpp b/source/Target/ModuleCache.cpp index 444c9806f98b..124cdacfb4d2 100644 --- a/source/Target/ModuleCache.cpp +++ b/source/Target/ModuleCache.cpp @@ -48,7 +48,7 @@ std::string GetEscapedHostname(const char *hostname) { class ModuleLock { private: - File m_file; + FileUP m_file_up; std::unique_ptr<lldb_private::LockFile> m_lock; FileSpec m_file_spec; @@ -94,9 +94,8 @@ void DeleteExistingModule(const FileSpec &root_dir_spec, Status error; ModuleLock lock(root_dir_spec, module_uuid, error); if (error.Fail()) { - if (log) - log->Printf("Failed to lock module %s: %s", - module_uuid.GetAsString().c_str(), error.AsCString()); + LLDB_LOGF(log, "Failed to lock module %s: %s", + module_uuid.GetAsString().c_str(), error.AsCString()); } namespace fs = llvm::sys::fs; @@ -158,16 +157,19 @@ ModuleLock::ModuleLock(const FileSpec &root_dir_spec, const UUID &uuid, return; m_file_spec = JoinPath(lock_dir_spec, uuid.GetAsString().c_str()); - FileSystem::Instance().Open(m_file, m_file_spec, - File::eOpenOptionWrite | - File::eOpenOptionCanCreate | - File::eOpenOptionCloseOnExec); - if (!m_file) { - error.SetErrorToErrno(); + + auto file = FileSystem::Instance().Open( + m_file_spec, File::eOpenOptionWrite | File::eOpenOptionCanCreate | + File::eOpenOptionCloseOnExec); + if (file) + m_file_up = std::move(file.get()); + else { + m_file_up.reset(); + error = Status(file.takeError()); return; } - m_lock.reset(new lldb_private::LockFile(m_file.GetDescriptor())); + m_lock.reset(new lldb_private::LockFile(m_file_up->GetDescriptor())); error = m_lock->WriteLock(0, 1); if (error.Fail()) error.SetErrorStringWithFormat("Failed to lock file: %s", @@ -175,10 +177,11 @@ ModuleLock::ModuleLock(const FileSpec &root_dir_spec, const UUID &uuid, } void ModuleLock::Delete() { - if (!m_file) + if (!m_file_up) return; - m_file.Close(); + m_file_up->Close(); + m_file_up.reset(); llvm::sys::fs::remove(m_file_spec.GetPath()); } diff --git a/source/Target/Platform.cpp b/source/Target/Platform.cpp index 710f82eaefa9..c9849a9e5f09 100644 --- a/source/Target/Platform.cpp +++ b/source/Target/Platform.cpp @@ -63,13 +63,13 @@ const char *Platform::GetHostPlatformName() { return "host"; } namespace { -static constexpr PropertyDefinition g_properties[] = { - {"use-module-cache", OptionValue::eTypeBoolean, true, true, nullptr, - {}, "Use module cache."}, - {"module-cache-directory", OptionValue::eTypeFileSpec, true, 0, nullptr, - {}, "Root directory for cached modules."}}; +#define LLDB_PROPERTIES_platform +#include "TargetProperties.inc" -enum { ePropertyUseModuleCache, ePropertyModuleCacheDirectory }; +enum { +#define LLDB_PROPERTIES_platform +#include "TargetPropertiesEnum.inc" +}; } // namespace @@ -80,7 +80,7 @@ ConstString PlatformProperties::GetSettingName() { PlatformProperties::PlatformProperties() { m_collection_sp = std::make_shared<OptionValueProperties>(GetSettingName()); - m_collection_sp->Initialize(g_properties); + m_collection_sp->Initialize(g_platform_properties); auto module_cache_dir = GetModuleCacheDirectory(); if (module_cache_dir) @@ -99,7 +99,7 @@ PlatformProperties::PlatformProperties() { bool PlatformProperties::GetUseModuleCache() const { const auto idx = ePropertyUseModuleCache; return m_collection_sp->GetPropertyAtIndexAsBoolean( - nullptr, idx, g_properties[idx].default_uint_value != 0); + nullptr, idx, g_platform_properties[idx].default_uint_value != 0); } bool PlatformProperties::SetUseModuleCache(bool use_module_cache) { @@ -384,10 +384,9 @@ Platform::Platform(bool is_host) m_rsync_opts(), m_rsync_prefix(), m_supports_ssh(false), m_ssh_opts(), m_ignores_remote_hostname(false), m_trap_handlers(), m_calculated_trap_handlers(false), - m_module_cache(llvm::make_unique<ModuleCache>()) { + m_module_cache(std::make_unique<ModuleCache>()) { Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_OBJECT)); - if (log) - log->Printf("%p Platform::Platform()", static_cast<void *>(this)); + LLDB_LOGF(log, "%p Platform::Platform()", static_cast<void *>(this)); } /// Destructor. @@ -396,8 +395,7 @@ Platform::Platform(bool is_host) /// inherited from by the plug-in instance. Platform::~Platform() { Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_OBJECT)); - if (log) - log->Printf("%p Platform::~Platform()", static_cast<void *>(this)); + LLDB_LOGF(log, "%p Platform::~Platform()", static_cast<void *>(this)); } void Platform::GetStatus(Stream &strm) { @@ -637,9 +635,8 @@ Status Platform::Install(const FileSpec &src, const FileSpec &dst) { Status error; Log *log = GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PLATFORM); - if (log) - log->Printf("Platform::Install (src='%s', dst='%s')", src.GetPath().c_str(), - dst.GetPath().c_str()); + LLDB_LOGF(log, "Platform::Install (src='%s', dst='%s')", + src.GetPath().c_str(), dst.GetPath().c_str()); FileSpec fixed_dst(dst); if (!fixed_dst.GetFilename()) @@ -690,10 +687,9 @@ Status Platform::Install(const FileSpec &src, const FileSpec &dst) { } } - if (log) - log->Printf("Platform::Install (src='%s', dst='%s') fixed_dst='%s'", - src.GetPath().c_str(), dst.GetPath().c_str(), - fixed_dst.GetPath().c_str()); + LLDB_LOGF(log, "Platform::Install (src='%s', dst='%s') fixed_dst='%s'", + src.GetPath().c_str(), dst.GetPath().c_str(), + fixed_dst.GetPath().c_str()); if (GetSupportsRSync()) { error = PutFile(src, dst); @@ -821,9 +817,8 @@ ConstString Platform::GetFullNameForDylib(ConstString basename) { bool Platform::SetRemoteWorkingDirectory(const FileSpec &working_dir) { Log *log = GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PLATFORM); - if (log) - log->Printf("Platform::SetRemoteWorkingDirectory('%s')", - working_dir.GetCString()); + LLDB_LOGF(log, "Platform::SetRemoteWorkingDirectory('%s')", + working_dir.GetCString()); m_working_dir = working_dir; return true; } @@ -1010,8 +1005,7 @@ uint32_t Platform::FindProcesses(const ProcessInstanceInfoMatch &match_info, Status Platform::LaunchProcess(ProcessLaunchInfo &launch_info) { Status error; Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_PLATFORM)); - if (log) - log->Printf("Platform::%s()", __FUNCTION__); + LLDB_LOGF(log, "Platform::%s()", __FUNCTION__); // Take care of the host case so that each subclass can just call this // function to get the host functionality. @@ -1027,10 +1021,10 @@ Status Platform::LaunchProcess(ProcessLaunchInfo &launch_info) { if (log) { const FileSpec &shell = launch_info.GetShell(); std::string shell_str = (shell) ? shell.GetPath() : "<null>"; - log->Printf( - "Platform::%s GetResumeCountForLaunchInfo() returned %" PRIu32 - ", shell is '%s'", - __FUNCTION__, num_resumes, shell_str.c_str()); + LLDB_LOGF(log, + "Platform::%s GetResumeCountForLaunchInfo() returned %" PRIu32 + ", shell is '%s'", + __FUNCTION__, num_resumes, shell_str.c_str()); } if (!launch_info.ConvertArgumentsForLaunchingInShell( @@ -1048,9 +1042,8 @@ Status Platform::LaunchProcess(ProcessLaunchInfo &launch_info) { } } - if (log) - log->Printf("Platform::%s final launch_info resume count: %" PRIu32, - __FUNCTION__, launch_info.GetResumeCount()); + LLDB_LOGF(log, "Platform::%s final launch_info resume count: %" PRIu32, + __FUNCTION__, launch_info.GetResumeCount()); error = Host::LaunchProcess(launch_info); } else @@ -1067,8 +1060,7 @@ Status Platform::ShellExpandArguments(ProcessLaunchInfo &launch_info) { Status Platform::KillProcess(const lldb::pid_t pid) { Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_PLATFORM)); - if (log) - log->Printf("Platform::%s, pid %" PRIu64, __FUNCTION__, pid); + LLDB_LOGF(log, "Platform::%s, pid %" PRIu64, __FUNCTION__, pid); // Try to find a process plugin to handle this Kill request. If we can't, // fall back to the default OS implementation. @@ -1098,9 +1090,8 @@ Platform::DebugProcess(ProcessLaunchInfo &launch_info, Debugger &debugger, // new target, else use existing one Status &error) { Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_PLATFORM)); - if (log) - log->Printf("Platform::%s entered (target %p)", __FUNCTION__, - static_cast<void *>(target)); + LLDB_LOGF(log, "Platform::%s entered (target %p)", __FUNCTION__, + static_cast<void *>(target)); ProcessSP process_sp; // Make sure we stop at the entry point @@ -1124,10 +1115,10 @@ Platform::DebugProcess(ProcessLaunchInfo &launch_info, Debugger &debugger, // Give this ProcessLaunchInfo filter a chance to adjust the launch info. error = (*filter_callback)(launch_info, target); if (!error.Success()) { - if (log) - log->Printf("Platform::%s() StructuredDataPlugin launch " - "filter failed.", - __FUNCTION__); + LLDB_LOGF(log, + "Platform::%s() StructuredDataPlugin launch " + "filter failed.", + __FUNCTION__); return process_sp; } } @@ -1135,17 +1126,15 @@ Platform::DebugProcess(ProcessLaunchInfo &launch_info, Debugger &debugger, error = LaunchProcess(launch_info); if (error.Success()) { - if (log) - log->Printf("Platform::%s LaunchProcess() call succeeded (pid=%" PRIu64 - ")", - __FUNCTION__, launch_info.GetProcessID()); + LLDB_LOGF(log, + "Platform::%s LaunchProcess() call succeeded (pid=%" PRIu64 ")", + __FUNCTION__, launch_info.GetProcessID()); if (launch_info.GetProcessID() != LLDB_INVALID_PROCESS_ID) { ProcessAttachInfo attach_info(launch_info); process_sp = Attach(attach_info, debugger, target, error); if (process_sp) { - if (log) - log->Printf("Platform::%s Attach() succeeded, Process plugin: %s", - __FUNCTION__, process_sp->GetPluginName().AsCString()); + LLDB_LOGF(log, "Platform::%s Attach() succeeded, Process plugin: %s", + __FUNCTION__, process_sp->GetPluginName().AsCString()); launch_info.SetHijackListener(attach_info.GetHijackListener()); // Since we attached to the process, it will think it needs to detach @@ -1163,20 +1152,18 @@ Platform::DebugProcess(ProcessLaunchInfo &launch_info, Debugger &debugger, process_sp->SetSTDIOFileDescriptor(pty_fd); } } else { - if (log) - log->Printf("Platform::%s Attach() failed: %s", __FUNCTION__, - error.AsCString()); + LLDB_LOGF(log, "Platform::%s Attach() failed: %s", __FUNCTION__, + error.AsCString()); } } else { - if (log) - log->Printf("Platform::%s LaunchProcess() returned launch_info with " - "invalid process id", - __FUNCTION__); + LLDB_LOGF(log, + "Platform::%s LaunchProcess() returned launch_info with " + "invalid process id", + __FUNCTION__); } } else { - if (log) - log->Printf("Platform::%s LaunchProcess() failed: %s", __FUNCTION__, - error.AsCString()); + LLDB_LOGF(log, "Platform::%s LaunchProcess() failed: %s", __FUNCTION__, + error.AsCString()); } return process_sp; @@ -1231,30 +1218,28 @@ bool Platform::IsCompatibleArchitecture(const ArchSpec &arch, Status Platform::PutFile(const FileSpec &source, const FileSpec &destination, uint32_t uid, uint32_t gid) { Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_PLATFORM)); - if (log) - log->Printf("[PutFile] Using block by block transfer....\n"); + LLDB_LOGF(log, "[PutFile] Using block by block transfer....\n"); - uint32_t source_open_options = + auto source_open_options = File::eOpenOptionRead | File::eOpenOptionCloseOnExec; namespace fs = llvm::sys::fs; if (fs::is_symlink_file(source.GetPath())) source_open_options |= File::eOpenOptionDontFollowSymlinks; - File source_file; - Status error = FileSystem::Instance().Open( - source_file, source, source_open_options, lldb::eFilePermissionsUserRW); - uint32_t permissions = source_file.GetPermissions(error); + auto source_file = FileSystem::Instance().Open(source, source_open_options, + lldb::eFilePermissionsUserRW); + if (!source_file) + return Status(source_file.takeError()); + Status error; + uint32_t permissions = source_file.get()->GetPermissions(error); if (permissions == 0) permissions = lldb::eFilePermissionsFileDefault; - if (!source_file.IsValid()) - return Status("PutFile: unable to open source file"); lldb::user_id_t dest_file = OpenFile( destination, File::eOpenOptionCanCreate | File::eOpenOptionWrite | File::eOpenOptionTruncate | File::eOpenOptionCloseOnExec, permissions, error); - if (log) - log->Printf("dest_file = %" PRIu64 "\n", dest_file); + LLDB_LOGF(log, "dest_file = %" PRIu64 "\n", dest_file); if (error.Fail()) return error; @@ -1264,7 +1249,7 @@ Status Platform::PutFile(const FileSpec &source, const FileSpec &destination, uint64_t offset = 0; for (;;) { size_t bytes_read = buffer_sp->GetByteSize(); - error = source_file.Read(buffer_sp->GetBytes(), bytes_read); + error = source_file.get()->Read(buffer_sp->GetBytes(), bytes_read); if (error.Fail() || bytes_read == 0) break; @@ -1277,7 +1262,7 @@ Status Platform::PutFile(const FileSpec &source, const FileSpec &destination, if (bytes_written != bytes_read) { // We didn't write the correct number of bytes, so adjust the file // position in the source file we are reading from... - source_file.SeekFromStart(offset); + source_file.get()->SeekFromStart(offset); } } CloseFile(dest_file, error); @@ -1630,10 +1615,9 @@ bool Platform::GetCachedSharedModule(const ModuleSpec &module_spec, if (error.Success()) return true; - if (log) - log->Printf("Platform::%s - module %s not found in local cache: %s", - __FUNCTION__, module_spec.GetUUID().GetAsString().c_str(), - error.AsCString()); + LLDB_LOGF(log, "Platform::%s - module %s not found in local cache: %s", + __FUNCTION__, module_spec.GetUUID().GetAsString().c_str(), + error.AsCString()); return false; } @@ -1644,7 +1628,7 @@ Status Platform::DownloadModuleSlice(const FileSpec &src_file_spec, Status error; std::error_code EC; - llvm::raw_fd_ostream dst(dst_file_spec.GetPath(), EC, llvm::sys::fs::F_None); + llvm::raw_fd_ostream dst(dst_file_spec.GetPath(), EC, llvm::sys::fs::OF_None); if (EC) { error.SetErrorStringWithFormat("unable to open destination file: %s", dst_file_spec.GetPath().c_str()); @@ -1736,7 +1720,7 @@ uint32_t Platform::LoadImage(lldb_private::Process *process, return LLDB_INVALID_IMAGE_TOKEN; } return DoLoadImage(process, target_file, nullptr, error); - } + } if (remote_file) { // Only remote file was specified so we don't have to do any copying @@ -1769,7 +1753,7 @@ uint32_t Platform::LoadImageUsingPaths(lldb_private::Process *process, remote_filename.GetPathStyle()); else file_to_use = remote_filename; - + return DoLoadImage(process, file_to_use, &paths, error, loaded_path); } @@ -1812,8 +1796,7 @@ lldb::ProcessSP Platform::ConnectProcess(llvm::StringRef connect_url, if (!process_sp) return nullptr; - error = - process_sp->ConnectRemote(debugger.GetOutputFile().get(), connect_url); + error = process_sp->ConnectRemote(&debugger.GetOutputStream(), connect_url); if (error.Fail()) return nullptr; @@ -1833,12 +1816,19 @@ size_t Platform::GetSoftwareBreakpointTrapOpcode(Target &target, size_t trap_opcode_size = 0; switch (arch.GetMachine()) { + case llvm::Triple::aarch64_32: case llvm::Triple::aarch64: { static const uint8_t g_aarch64_opcode[] = {0x00, 0x00, 0x20, 0xd4}; trap_opcode = g_aarch64_opcode; trap_opcode_size = sizeof(g_aarch64_opcode); } break; + case llvm::Triple::arc: { + static const uint8_t g_hex_opcode[] = { 0xff, 0x7f }; + trap_opcode = g_hex_opcode; + trap_opcode_size = sizeof(g_hex_opcode); + } break; + // TODO: support big-endian arm and thumb trap codes. case llvm::Triple::arm: { // The ARM reference recommends the use of 0xe7fddefe and 0xdefe but the diff --git a/source/Target/Process.cpp b/source/Target/Process.cpp index 6c634dba00c7..ed0b951fbce1 100644 --- a/source/Target/Process.cpp +++ b/source/Target/Process.cpp @@ -13,7 +13,6 @@ #include "llvm/Support/ScopedPrinter.h" #include "llvm/Support/Threading.h" -#include "Plugins/Process/Utility/InferiorCallPOSIX.h" #include "lldb/Breakpoint/BreakpointLocation.h" #include "lldb/Breakpoint/StoppointCallbackContext.h" #include "lldb/Core/Debugger.h" @@ -59,6 +58,7 @@ #include "lldb/Target/Thread.h" #include "lldb/Target/ThreadPlan.h" #include "lldb/Target/ThreadPlanBase.h" +#include "lldb/Target/ThreadPlanCallFunction.h" #include "lldb/Target/UnixSignals.h" #include "lldb/Utility/Event.h" #include "lldb/Utility/Log.h" @@ -112,55 +112,12 @@ public: } }; -static constexpr PropertyDefinition g_properties[] = { - {"disable-memory-cache", OptionValue::eTypeBoolean, false, - DISABLE_MEM_CACHE_DEFAULT, nullptr, {}, - "Disable reading and caching of memory in fixed-size units."}, - {"extra-startup-command", OptionValue::eTypeArray, false, - OptionValue::eTypeString, nullptr, {}, - "A list containing extra commands understood by the particular process " - "plugin used. " - "For instance, to turn on debugserver logging set this to " - "\"QSetLogging:bitmask=LOG_DEFAULT;\""}, - {"ignore-breakpoints-in-expressions", OptionValue::eTypeBoolean, true, true, - nullptr, {}, - "If true, breakpoints will be ignored during expression evaluation."}, - {"unwind-on-error-in-expressions", OptionValue::eTypeBoolean, true, true, - nullptr, {}, "If true, errors in expression evaluation will unwind " - "the stack back to the state before the call."}, - {"python-os-plugin-path", OptionValue::eTypeFileSpec, false, true, nullptr, - {}, "A path to a python OS plug-in module file that contains a " - "OperatingSystemPlugIn class."}, - {"stop-on-sharedlibrary-events", OptionValue::eTypeBoolean, true, false, - nullptr, {}, - "If true, stop when a shared library is loaded or unloaded."}, - {"detach-keeps-stopped", OptionValue::eTypeBoolean, true, false, nullptr, - {}, "If true, detach will attempt to keep the process stopped."}, - {"memory-cache-line-size", OptionValue::eTypeUInt64, false, 512, nullptr, - {}, "The memory cache line size"}, - {"optimization-warnings", OptionValue::eTypeBoolean, false, true, nullptr, - {}, "If true, warn when stopped in code that is optimized where " - "stepping and variable availability may not behave as expected."}, - {"stop-on-exec", OptionValue::eTypeBoolean, true, true, - nullptr, {}, - "If true, stop when a shared library is loaded or unloaded."}, - {"utility-expression-timeout", OptionValue::eTypeUInt64, false, 15, - nullptr, {}, - "The time in seconds to wait for LLDB-internal utility expressions."} -}; +#define LLDB_PROPERTIES_process +#include "TargetProperties.inc" enum { - ePropertyDisableMemCache, - ePropertyExtraStartCommand, - ePropertyIgnoreBreakpointsInExpressions, - ePropertyUnwindOnErrorInExpressions, - ePropertyPythonOSPluginPath, - ePropertyStopOnSharedLibraryEvents, - ePropertyDetachKeepsStopped, - ePropertyMemCacheLineSize, - ePropertyWarningOptimization, - ePropertyStopOnExec, - ePropertyUtilityExpressionTimeout, +#define LLDB_PROPERTIES_process +#include "TargetPropertiesEnum.inc" }; ProcessProperties::ProcessProperties(lldb_private::Process *process) @@ -171,7 +128,7 @@ ProcessProperties::ProcessProperties(lldb_private::Process *process) // Global process properties, set them up one time m_collection_sp = std::make_shared<ProcessOptionValueProperties>(ConstString("process")); - m_collection_sp->Initialize(g_properties); + m_collection_sp->Initialize(g_process_properties); m_collection_sp->AppendProperty( ConstString("thread"), ConstString("Settings specific to threads."), true, Thread::GetGlobalProperties()->GetValueProperties()); @@ -196,13 +153,13 @@ void ProcessProperties::OptionValueChangedCallback(void *baton, bool ProcessProperties::GetDisableMemoryCache() const { const uint32_t idx = ePropertyDisableMemCache; return m_collection_sp->GetPropertyAtIndexAsBoolean( - nullptr, idx, g_properties[idx].default_uint_value != 0); + nullptr, idx, g_process_properties[idx].default_uint_value != 0); } uint64_t ProcessProperties::GetMemoryCacheLineSize() const { const uint32_t idx = ePropertyMemCacheLineSize; return m_collection_sp->GetPropertyAtIndexAsUInt64( - nullptr, idx, g_properties[idx].default_uint_value); + nullptr, idx, g_process_properties[idx].default_uint_value); } Args ProcessProperties::GetExtraStartupCommands() const { @@ -230,7 +187,7 @@ void ProcessProperties::SetPythonOSPluginPath(const FileSpec &file) { bool ProcessProperties::GetIgnoreBreakpointsInExpressions() const { const uint32_t idx = ePropertyIgnoreBreakpointsInExpressions; return m_collection_sp->GetPropertyAtIndexAsBoolean( - nullptr, idx, g_properties[idx].default_uint_value != 0); + nullptr, idx, g_process_properties[idx].default_uint_value != 0); } void ProcessProperties::SetIgnoreBreakpointsInExpressions(bool ignore) { @@ -241,7 +198,7 @@ void ProcessProperties::SetIgnoreBreakpointsInExpressions(bool ignore) { bool ProcessProperties::GetUnwindOnErrorInExpressions() const { const uint32_t idx = ePropertyUnwindOnErrorInExpressions; return m_collection_sp->GetPropertyAtIndexAsBoolean( - nullptr, idx, g_properties[idx].default_uint_value != 0); + nullptr, idx, g_process_properties[idx].default_uint_value != 0); } void ProcessProperties::SetUnwindOnErrorInExpressions(bool ignore) { @@ -252,7 +209,7 @@ void ProcessProperties::SetUnwindOnErrorInExpressions(bool ignore) { bool ProcessProperties::GetStopOnSharedLibraryEvents() const { const uint32_t idx = ePropertyStopOnSharedLibraryEvents; return m_collection_sp->GetPropertyAtIndexAsBoolean( - nullptr, idx, g_properties[idx].default_uint_value != 0); + nullptr, idx, g_process_properties[idx].default_uint_value != 0); } void ProcessProperties::SetStopOnSharedLibraryEvents(bool stop) { @@ -263,7 +220,7 @@ void ProcessProperties::SetStopOnSharedLibraryEvents(bool stop) { bool ProcessProperties::GetDetachKeepsStopped() const { const uint32_t idx = ePropertyDetachKeepsStopped; return m_collection_sp->GetPropertyAtIndexAsBoolean( - nullptr, idx, g_properties[idx].default_uint_value != 0); + nullptr, idx, g_process_properties[idx].default_uint_value != 0); } void ProcessProperties::SetDetachKeepsStopped(bool stop) { @@ -274,19 +231,19 @@ void ProcessProperties::SetDetachKeepsStopped(bool stop) { bool ProcessProperties::GetWarningsOptimization() const { const uint32_t idx = ePropertyWarningOptimization; return m_collection_sp->GetPropertyAtIndexAsBoolean( - nullptr, idx, g_properties[idx].default_uint_value != 0); + nullptr, idx, g_process_properties[idx].default_uint_value != 0); } bool ProcessProperties::GetStopOnExec() const { const uint32_t idx = ePropertyStopOnExec; return m_collection_sp->GetPropertyAtIndexAsBoolean( - nullptr, idx, g_properties[idx].default_uint_value != 0); + nullptr, idx, g_process_properties[idx].default_uint_value != 0); } std::chrono::seconds ProcessProperties::GetUtilityExpressionTimeout() const { const uint32_t idx = ePropertyUtilityExpressionTimeout; uint64_t value = m_collection_sp->GetPropertyAtIndexAsUInt64( - nullptr, idx, g_properties[idx].default_uint_value); + nullptr, idx, g_process_properties[idx].default_uint_value); return std::chrono::seconds(value); } @@ -544,8 +501,7 @@ Process::Process(lldb::TargetSP target_sp, ListenerSP listener_sp, CheckInWithManager(); Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_OBJECT)); - if (log) - log->Printf("%p Process::Process()", static_cast<void *>(this)); + LLDB_LOGF(log, "%p Process::Process()", static_cast<void *>(this)); if (!m_unix_signals_sp) m_unix_signals_sp = std::make_shared<UnixSignals>(); @@ -593,8 +549,7 @@ Process::Process(lldb::TargetSP target_sp, ListenerSP listener_sp, Process::~Process() { Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_OBJECT)); - if (log) - log->Printf("%p Process::~Process()", static_cast<void *>(this)); + LLDB_LOGF(log, "%p Process::~Process()", static_cast<void *>(this)); StopPrivateStateThread(); // ThreadList::Clear() will try to acquire this process's mutex, so @@ -781,10 +736,10 @@ StateType Process::WaitForProcessToStop(const Timeout<std::micro> &timeout, if (!wait_always && StateIsStoppedState(state, true) && StateIsStoppedState(GetPrivateState(), true)) { - if (log) - log->Printf("Process::%s returning without waiting for events; process " - "private and public states are already 'stopped'.", - __FUNCTION__); + LLDB_LOGF(log, + "Process::%s returning without waiting for events; process " + "private and public states are already 'stopped'.", + __FUNCTION__); // We need to toggle the run lock as this won't get done in // SetPublicState() if the process is hijacked. if (hijack_listener_sp && use_run_lock) @@ -1073,19 +1028,17 @@ StateType Process::GetStateChangedEvents(EventSP &event_sp, Event *Process::PeekAtStateChangedEvents() { Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_PROCESS)); - if (log) - log->Printf("Process::%s...", __FUNCTION__); + LLDB_LOGF(log, "Process::%s...", __FUNCTION__); Event *event_ptr; event_ptr = m_listener_sp->PeekAtNextEventForBroadcasterWithType( this, eBroadcastBitStateChanged); if (log) { if (event_ptr) { - log->Printf( - "Process::%s (event_ptr) => %s", __FUNCTION__, - StateAsCString(ProcessEventData::GetStateFromEvent(event_ptr))); + LLDB_LOGF(log, "Process::%s (event_ptr) => %s", __FUNCTION__, + StateAsCString(ProcessEventData::GetStateFromEvent(event_ptr))); } else { - log->Printf("Process::%s no events found", __FUNCTION__); + LLDB_LOGF(log, "Process::%s no events found", __FUNCTION__); } } return event_ptr; @@ -1149,17 +1102,14 @@ bool Process::SetExitStatus(int status, const char *cstr) { Log *log(lldb_private::GetLogIfAnyCategoriesSet(LIBLLDB_LOG_STATE | LIBLLDB_LOG_PROCESS)); - if (log) - log->Printf( - "Process::SetExitStatus (status=%i (0x%8.8x), description=%s%s%s)", - status, status, cstr ? "\"" : "", cstr ? cstr : "NULL", - cstr ? "\"" : ""); + LLDB_LOGF( + log, "Process::SetExitStatus (status=%i (0x%8.8x), description=%s%s%s)", + status, status, cstr ? "\"" : "", cstr ? cstr : "NULL", cstr ? "\"" : ""); // We were already in the exited state if (m_private_state.GetValue() == eStateExited) { - if (log) - log->Printf("Process::SetExitStatus () ignoring exit status because " - "state was already set to eStateExited"); + LLDB_LOGF(log, "Process::SetExitStatus () ignoring exit status because " + "state was already set to eStateExited"); return false; } @@ -1207,10 +1157,10 @@ bool Process::SetProcessExitStatus( int exit_status // Exit value of process if signal is zero ) { Log *log(lldb_private::GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PROCESS)); - if (log) - log->Printf("Process::SetProcessExitStatus (pid=%" PRIu64 - ", exited=%i, signal=%i, exit_status=%i)\n", - pid, exited, signo, exit_status); + LLDB_LOGF(log, + "Process::SetProcessExitStatus (pid=%" PRIu64 + ", exited=%i, signal=%i, exit_status=%i)\n", + pid, exited, signo, exit_status); if (exited) { TargetSP target_sp(Debugger::FindTargetWithProcessID(pid)); @@ -1353,9 +1303,8 @@ StateType Process::GetState() { void Process::SetPublicState(StateType new_state, bool restarted) { Log *log(lldb_private::GetLogIfAnyCategoriesSet(LIBLLDB_LOG_STATE | LIBLLDB_LOG_PROCESS)); - if (log) - log->Printf("Process::SetPublicState (state = %s, restarted = %i)", - StateAsCString(new_state), restarted); + LLDB_LOGF(log, "Process::SetPublicState (state = %s, restarted = %i)", + StateAsCString(new_state), restarted); const StateType old_state = m_public_state.GetValue(); m_public_state.SetValue(new_state); @@ -1364,19 +1313,17 @@ void Process::SetPublicState(StateType new_state, bool restarted) { // program to run. if (!StateChangedIsExternallyHijacked()) { if (new_state == eStateDetached) { - if (log) - log->Printf( - "Process::SetPublicState (%s) -- unlocking run lock for detach", - StateAsCString(new_state)); + LLDB_LOGF(log, + "Process::SetPublicState (%s) -- unlocking run lock for detach", + StateAsCString(new_state)); m_public_run_lock.SetStopped(); } else { const bool old_state_is_stopped = StateIsStoppedState(old_state, false); const bool new_state_is_stopped = StateIsStoppedState(new_state, false); if ((old_state_is_stopped != new_state_is_stopped)) { if (new_state_is_stopped && !restarted) { - if (log) - log->Printf("Process::SetPublicState (%s) -- unlocking run lock", - StateAsCString(new_state)); + LLDB_LOGF(log, "Process::SetPublicState (%s) -- unlocking run lock", + StateAsCString(new_state)); m_public_run_lock.SetStopped(); } } @@ -1387,12 +1334,10 @@ void Process::SetPublicState(StateType new_state, bool restarted) { Status Process::Resume() { Log *log(lldb_private::GetLogIfAnyCategoriesSet(LIBLLDB_LOG_STATE | LIBLLDB_LOG_PROCESS)); - if (log) - log->Printf("Process::Resume -- locking run lock"); + LLDB_LOGF(log, "Process::Resume -- locking run lock"); if (!m_public_run_lock.TrySetRunning()) { Status error("Resume request failed - process still running."); - if (log) - log->Printf("Process::Resume: -- TrySetRunning failed, not resuming."); + LLDB_LOGF(log, "Process::Resume: -- TrySetRunning failed, not resuming."); return error; } Status error = PrivateResume(); @@ -1408,12 +1353,10 @@ static const char *g_resume_sync_name = "lldb.Process.ResumeSynchronous.hijack"; Status Process::ResumeSynchronous(Stream *stream) { Log *log(lldb_private::GetLogIfAnyCategoriesSet(LIBLLDB_LOG_STATE | LIBLLDB_LOG_PROCESS)); - if (log) - log->Printf("Process::ResumeSynchronous -- locking run lock"); + LLDB_LOGF(log, "Process::ResumeSynchronous -- locking run lock"); if (!m_public_run_lock.TrySetRunning()) { Status error("Resume request failed - process still running."); - if (log) - log->Printf("Process::Resume: -- TrySetRunning failed, not resuming."); + LLDB_LOGF(log, "Process::Resume: -- TrySetRunning failed, not resuming."); return error; } @@ -1472,8 +1415,7 @@ void Process::SetPrivateState(StateType new_state) { LIBLLDB_LOG_PROCESS)); bool state_changed = false; - if (log) - log->Printf("Process::SetPrivateState (%s)", StateAsCString(new_state)); + LLDB_LOGF(log, "Process::SetPrivateState (%s)", StateAsCString(new_state)); std::lock_guard<std::recursive_mutex> thread_guard(m_thread_list.GetMutex()); std::lock_guard<std::recursive_mutex> guard(m_private_state.GetMutex()); @@ -1512,9 +1454,8 @@ void Process::SetPrivateState(StateType new_state) { if (!m_mod_id.IsLastResumeForUserExpression()) m_mod_id.SetStopEventForLastNaturalStopID(event_sp); m_memory_cache.Clear(); - if (log) - log->Printf("Process::SetPrivateState (%s) stop_id = %u", - StateAsCString(new_state), m_mod_id.GetStopID()); + LLDB_LOGF(log, "Process::SetPrivateState (%s) stop_id = %u", + StateAsCString(new_state), m_mod_id.GetStopID()); } // Use our target to get a shared pointer to ourselves... @@ -1523,10 +1464,9 @@ void Process::SetPrivateState(StateType new_state) { else m_private_state_broadcaster.BroadcastEvent(event_sp); } else { - if (log) - log->Printf( - "Process::SetPrivateState (%s) state didn't change. Ignoring...", - StateAsCString(new_state)); + LLDB_LOGF(log, + "Process::SetPrivateState (%s) state didn't change. Ignoring...", + StateAsCString(new_state)); } } @@ -1709,7 +1649,7 @@ Process::CreateBreakpointSite(const BreakpointLocationSP &owner, Address symbol_address = symbol->GetAddress(); load_addr = ResolveIndirectFunction(&symbol_address, error); if (!error.Success() && show_error) { - GetTarget().GetDebugger().GetErrorFile()->Printf( + GetTarget().GetDebugger().GetErrorStream().Printf( "warning: failed to resolve indirect function at 0x%" PRIx64 " for breakpoint %i.%i: %s\n", symbol->GetLoadAddress(&GetTarget()), @@ -1748,7 +1688,7 @@ Process::CreateBreakpointSite(const BreakpointLocationSP &owner, } else { if (show_error || use_hardware) { // Report error for setting breakpoint... - GetTarget().GetDebugger().GetErrorFile()->Printf( + GetTarget().GetDebugger().GetErrorStream().Printf( "warning: failed to set breakpoint site at 0x%" PRIx64 " for breakpoint %i.%i: %s\n", load_addr, owner->GetBreakpoint().GetID(), owner->GetID(), @@ -1816,16 +1756,15 @@ Status Process::EnableSoftwareBreakpoint(BreakpointSite *bp_site) { assert(bp_site != nullptr); Log *log(lldb_private::GetLogIfAnyCategoriesSet(LIBLLDB_LOG_BREAKPOINTS)); const addr_t bp_addr = bp_site->GetLoadAddress(); - if (log) - log->Printf( - "Process::EnableSoftwareBreakpoint (site_id = %d) addr = 0x%" PRIx64, - bp_site->GetID(), (uint64_t)bp_addr); + LLDB_LOGF( + log, "Process::EnableSoftwareBreakpoint (site_id = %d) addr = 0x%" PRIx64, + bp_site->GetID(), (uint64_t)bp_addr); if (bp_site->IsEnabled()) { - if (log) - log->Printf( - "Process::EnableSoftwareBreakpoint (site_id = %d) addr = 0x%" PRIx64 - " -- already enabled", - bp_site->GetID(), (uint64_t)bp_addr); + LLDB_LOGF( + log, + "Process::EnableSoftwareBreakpoint (site_id = %d) addr = 0x%" PRIx64 + " -- already enabled", + bp_site->GetID(), (uint64_t)bp_addr); return error; } @@ -1864,10 +1803,10 @@ Status Process::EnableSoftwareBreakpoint(BreakpointSite *bp_site) { bp_opcode_size) == 0) { bp_site->SetEnabled(true); bp_site->SetType(BreakpointSite::eSoftware); - if (log) - log->Printf("Process::EnableSoftwareBreakpoint (site_id = %d) " - "addr = 0x%" PRIx64 " -- SUCCESS", - bp_site->GetID(), (uint64_t)bp_addr); + LLDB_LOGF(log, + "Process::EnableSoftwareBreakpoint (site_id = %d) " + "addr = 0x%" PRIx64 " -- SUCCESS", + bp_site->GetID(), (uint64_t)bp_addr); } else error.SetErrorString( "failed to verify the breakpoint trap in memory."); @@ -1880,7 +1819,8 @@ Status Process::EnableSoftwareBreakpoint(BreakpointSite *bp_site) { error.SetErrorString("Unable to read memory at breakpoint address."); } if (log && error.Fail()) - log->Printf( + LLDB_LOGF( + log, "Process::EnableSoftwareBreakpoint (site_id = %d) addr = 0x%" PRIx64 " -- FAILED: %s", bp_site->GetID(), (uint64_t)bp_addr, error.AsCString()); @@ -1893,10 +1833,10 @@ Status Process::DisableSoftwareBreakpoint(BreakpointSite *bp_site) { Log *log(lldb_private::GetLogIfAnyCategoriesSet(LIBLLDB_LOG_BREAKPOINTS)); addr_t bp_addr = bp_site->GetLoadAddress(); lldb::user_id_t breakID = bp_site->GetID(); - if (log) - log->Printf("Process::DisableSoftwareBreakpoint (breakID = %" PRIu64 - ") addr = 0x%" PRIx64, - breakID, (uint64_t)bp_addr); + LLDB_LOGF(log, + "Process::DisableSoftwareBreakpoint (breakID = %" PRIu64 + ") addr = 0x%" PRIx64, + breakID, (uint64_t)bp_addr); if (bp_site->IsHardware()) { error.SetErrorString("Breakpoint site is a hardware breakpoint."); @@ -1943,10 +1883,10 @@ Status Process::DisableSoftwareBreakpoint(BreakpointSite *bp_site) { break_op_size) == 0) { // SUCCESS bp_site->SetEnabled(false); - if (log) - log->Printf("Process::DisableSoftwareBreakpoint (site_id = %d) " - "addr = 0x%" PRIx64 " -- SUCCESS", - bp_site->GetID(), (uint64_t)bp_addr); + LLDB_LOGF(log, + "Process::DisableSoftwareBreakpoint (site_id = %d) " + "addr = 0x%" PRIx64 " -- SUCCESS", + bp_site->GetID(), (uint64_t)bp_addr); return error; } else { if (break_op_found) @@ -1961,19 +1901,19 @@ Status Process::DisableSoftwareBreakpoint(BreakpointSite *bp_site) { "Unable to read memory that should contain the breakpoint trap."); } } else { - if (log) - log->Printf( - "Process::DisableSoftwareBreakpoint (site_id = %d) addr = 0x%" PRIx64 - " -- already disabled", - bp_site->GetID(), (uint64_t)bp_addr); + LLDB_LOGF( + log, + "Process::DisableSoftwareBreakpoint (site_id = %d) addr = 0x%" PRIx64 + " -- already disabled", + bp_site->GetID(), (uint64_t)bp_addr); return error; } - if (log) - log->Printf( - "Process::DisableSoftwareBreakpoint (site_id = %d) addr = 0x%" PRIx64 - " -- FAILED: %s", - bp_site->GetID(), (uint64_t)bp_addr, error.AsCString()); + LLDB_LOGF( + log, + "Process::DisableSoftwareBreakpoint (site_id = %d) addr = 0x%" PRIx64 + " -- FAILED: %s", + bp_site->GetID(), (uint64_t)bp_addr, error.AsCString()); return error; } @@ -2371,13 +2311,13 @@ addr_t Process::AllocateMemory(size_t size, uint32_t permissions, #else addr_t allocated_addr = DoAllocateMemory(size, permissions, error); Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_PROCESS)); - if (log) - log->Printf("Process::AllocateMemory(size=%" PRIu64 - ", permissions=%s) => 0x%16.16" PRIx64 - " (m_stop_id = %u m_memory_id = %u)", - (uint64_t)size, GetPermissionsAsCString(permissions), - (uint64_t)allocated_addr, m_mod_id.GetStopID(), - m_mod_id.GetMemoryID()); + LLDB_LOGF(log, + "Process::AllocateMemory(size=%" PRIu64 + ", permissions=%s) => 0x%16.16" PRIx64 + " (m_stop_id = %u m_memory_id = %u)", + (uint64_t)size, GetPermissionsAsCString(permissions), + (uint64_t)allocated_addr, m_mod_id.GetStopID(), + m_mod_id.GetMemoryID()); return allocated_addr; #endif } @@ -2403,16 +2343,16 @@ bool Process::CanJIT() { if (err.Success()) { m_can_jit = eCanJITYes; - if (log) - log->Printf("Process::%s pid %" PRIu64 - " allocation test passed, CanJIT () is true", - __FUNCTION__, GetID()); + LLDB_LOGF(log, + "Process::%s pid %" PRIu64 + " allocation test passed, CanJIT () is true", + __FUNCTION__, GetID()); } else { m_can_jit = eCanJITNo; - if (log) - log->Printf("Process::%s pid %" PRIu64 - " allocation test failed, CanJIT () is false: %s", - __FUNCTION__, GetID(), err.AsCString()); + LLDB_LOGF(log, + "Process::%s pid %" PRIu64 + " allocation test failed, CanJIT () is false: %s", + __FUNCTION__, GetID(), err.AsCString()); } DeallocateMemory(allocated_memory); @@ -2441,11 +2381,11 @@ Status Process::DeallocateMemory(addr_t ptr) { error = DoDeallocateMemory(ptr); Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_PROCESS)); - if (log) - log->Printf("Process::DeallocateMemory(addr=0x%16.16" PRIx64 - ") => err = %s (m_stop_id = %u, m_memory_id = %u)", - ptr, error.AsCString("SUCCESS"), m_mod_id.GetStopID(), - m_mod_id.GetMemoryID()); + LLDB_LOGF(log, + "Process::DeallocateMemory(addr=0x%16.16" PRIx64 + ") => err = %s (m_stop_id = %u, m_memory_id = %u)", + ptr, error.AsCString("SUCCESS"), m_mod_id.GetStopID(), + m_mod_id.GetMemoryID()); #endif return error; } @@ -2455,8 +2395,9 @@ ModuleSP Process::ReadModuleFromMemory(const FileSpec &file_spec, size_t size_to_read) { Log *log = lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_HOST); if (log) { - log->Printf("Process::ReadModuleFromMemory reading %s binary from memory", - file_spec.GetPath().c_str()); + LLDB_LOGF(log, + "Process::ReadModuleFromMemory reading %s binary from memory", + file_spec.GetPath().c_str()); } ModuleSP module_sp(new Module(file_spec, ArchSpec())); if (module_sp) { @@ -2691,9 +2632,8 @@ Status Process::LoadCore() { if (!StateIsStoppedState(state, false)) { Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_PROCESS)); - if (log) - log->Printf("Process::Halt() failed to stop, state is: %s", - StateAsCString(state)); + LLDB_LOGF(log, "Process::Halt() failed to stop, state is: %s", + StateAsCString(state)); error.SetErrorString( "Did not get stopped event after loading the core file."); } @@ -2728,10 +2668,10 @@ Process::AttachCompletionHandler::AttachCompletionHandler(Process *process, uint32_t exec_count) : NextEventAction(process), m_exec_count(exec_count) { Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_PROCESS)); - if (log) - log->Printf( - "Process::AttachCompletionHandler::%s process=%p, exec_count=%" PRIu32, - __FUNCTION__, static_cast<void *>(process), exec_count); + LLDB_LOGF( + log, + "Process::AttachCompletionHandler::%s process=%p, exec_count=%" PRIu32, + __FUNCTION__, static_cast<void *>(process), exec_count); } Process::NextEventAction::EventActionResult @@ -2739,10 +2679,9 @@ Process::AttachCompletionHandler::PerformAction(lldb::EventSP &event_sp) { Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_PROCESS)); StateType state = ProcessEventData::GetStateFromEvent(event_sp.get()); - if (log) - log->Printf( - "Process::AttachCompletionHandler::%s called with state %s (%d)", - __FUNCTION__, StateAsCString(state), static_cast<int>(state)); + LLDB_LOGF(log, + "Process::AttachCompletionHandler::%s called with state %s (%d)", + __FUNCTION__, StateAsCString(state), static_cast<int>(state)); switch (state) { case eStateAttaching: @@ -2764,18 +2703,18 @@ Process::AttachCompletionHandler::PerformAction(lldb::EventSP &event_sp) { if (m_exec_count > 0) { --m_exec_count; - if (log) - log->Printf("Process::AttachCompletionHandler::%s state %s: reduced " - "remaining exec count to %" PRIu32 ", requesting resume", - __FUNCTION__, StateAsCString(state), m_exec_count); + LLDB_LOGF(log, + "Process::AttachCompletionHandler::%s state %s: reduced " + "remaining exec count to %" PRIu32 ", requesting resume", + __FUNCTION__, StateAsCString(state), m_exec_count); RequestResume(); return eEventActionRetry; } else { - if (log) - log->Printf("Process::AttachCompletionHandler::%s state %s: no more " - "execs expected to start, continuing with attach", - __FUNCTION__, StateAsCString(state)); + LLDB_LOGF(log, + "Process::AttachCompletionHandler::%s state %s: no more " + "execs expected to start, continuing with attach", + __FUNCTION__, StateAsCString(state)); m_process->CompleteAttach(); return eEventActionSuccess; @@ -2932,8 +2871,7 @@ Status Process::Attach(ProcessAttachInfo &attach_info) { void Process::CompleteAttach() { Log *log(lldb_private::GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PROCESS | LIBLLDB_LOG_TARGET)); - if (log) - log->Printf("Process::%s()", __FUNCTION__); + LLDB_LOGF(log, "Process::%s()", __FUNCTION__); // Let the process subclass figure out at much as it can about the process // before we go looking for a dynamic loader plug-in. @@ -2944,9 +2882,10 @@ void Process::CompleteAttach() { GetTarget().SetArchitecture(process_arch); if (log) { const char *triple_str = process_arch.GetTriple().getTriple().c_str(); - log->Printf("Process::%s replacing process architecture with DidAttach() " - "architecture: %s", - __FUNCTION__, triple_str ? triple_str : "<null>"); + LLDB_LOGF(log, + "Process::%s replacing process architecture with DidAttach() " + "architecture: %s", + __FUNCTION__, triple_str ? triple_str : "<null>"); } } @@ -2965,11 +2904,11 @@ void Process::CompleteAttach() { if (platform_sp) { GetTarget().SetPlatform(platform_sp); GetTarget().SetArchitecture(platform_arch); - if (log) - log->Printf("Process::%s switching platform to %s and architecture " - "to %s based on info from attach", - __FUNCTION__, platform_sp->GetName().AsCString(""), - platform_arch.GetTriple().getTriple().c_str()); + LLDB_LOGF(log, + "Process::%s switching platform to %s and architecture " + "to %s based on info from attach", + __FUNCTION__, platform_sp->GetName().AsCString(""), + platform_arch.GetTriple().getTriple().c_str()); } } else if (!process_arch.IsValid()) { ProcessInstanceInfo process_info; @@ -2978,11 +2917,11 @@ void Process::CompleteAttach() { if (process_arch.IsValid() && !GetTarget().GetArchitecture().IsExactMatch(process_arch)) { GetTarget().SetArchitecture(process_arch); - if (log) - log->Printf("Process::%s switching architecture to %s based on info " - "the platform retrieved for pid %" PRIu64, - __FUNCTION__, - process_arch.GetTriple().getTriple().c_str(), GetID()); + LLDB_LOGF(log, + "Process::%s switching architecture to %s based on info " + "the platform retrieved for pid %" PRIu64, + __FUNCTION__, process_arch.GetTriple().getTriple().c_str(), + GetID()); } } } @@ -2994,12 +2933,13 @@ void Process::CompleteAttach() { dyld->DidAttach(); if (log) { ModuleSP exe_module_sp = GetTarget().GetExecutableModule(); - log->Printf("Process::%s after DynamicLoader::DidAttach(), target " - "executable is %s (using %s plugin)", - __FUNCTION__, - exe_module_sp ? exe_module_sp->GetFileSpec().GetPath().c_str() - : "<none>", - dyld->GetPluginName().AsCString("<unnamed>")); + LLDB_LOGF(log, + "Process::%s after DynamicLoader::DidAttach(), target " + "executable is %s (using %s plugin)", + __FUNCTION__, + exe_module_sp ? exe_module_sp->GetFileSpec().GetPath().c_str() + : "<none>", + dyld->GetPluginName().AsCString("<unnamed>")); } } @@ -3010,12 +2950,13 @@ void Process::CompleteAttach() { system_runtime->DidAttach(); if (log) { ModuleSP exe_module_sp = GetTarget().GetExecutableModule(); - log->Printf("Process::%s after SystemRuntime::DidAttach(), target " - "executable is %s (using %s plugin)", - __FUNCTION__, - exe_module_sp ? exe_module_sp->GetFileSpec().GetPath().c_str() - : "<none>", - system_runtime->GetPluginName().AsCString("<unnamed>")); + LLDB_LOGF(log, + "Process::%s after SystemRuntime::DidAttach(), target " + "executable is %s (using %s plugin)", + __FUNCTION__, + exe_module_sp ? exe_module_sp->GetFileSpec().GetPath().c_str() + : "<none>", + system_runtime->GetPluginName().AsCString("<unnamed>")); } } @@ -3048,7 +2989,8 @@ void Process::CompleteAttach() { eLoadDependentsNo); if (log) { ModuleSP exe_module_sp = GetTarget().GetExecutableModule(); - log->Printf( + LLDB_LOGF( + log, "Process::%s after looping through modules, target executable is %s", __FUNCTION__, exe_module_sp ? exe_module_sp->GetFileSpec().GetPath().c_str() @@ -3092,11 +3034,11 @@ Status Process::ConnectRemote(Stream *strm, llvm::StringRef remote_url) { Status Process::PrivateResume() { Log *log(lldb_private::GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PROCESS | LIBLLDB_LOG_STEP)); - if (log) - log->Printf("Process::PrivateResume() m_stop_id = %u, public state: %s " - "private state: %s", - m_mod_id.GetStopID(), StateAsCString(m_public_state.GetValue()), - StateAsCString(m_private_state.GetValue())); + LLDB_LOGF(log, + "Process::PrivateResume() m_stop_id = %u, public state: %s " + "private state: %s", + m_mod_id.GetStopID(), StateAsCString(m_public_state.GetValue()), + StateAsCString(m_private_state.GetValue())); // If signals handing status changed we might want to update our signal // filters before resuming. @@ -3123,12 +3065,9 @@ Status Process::PrivateResume() { if (error.Success()) { DidResume(); m_thread_list.DidResume(); - if (log) - log->Printf("Process thinks the process has resumed."); + LLDB_LOGF(log, "Process thinks the process has resumed."); } else { - if (log) - log->Printf( - "Process::PrivateResume() DoResume failed."); + LLDB_LOGF(log, "Process::PrivateResume() DoResume failed."); return error; } } @@ -3137,16 +3076,15 @@ Status Process::PrivateResume() { // from one frame of a set of inlined frames that share the same PC to // another.) So generate a continue & a stopped event, and let the world // handle them. - if (log) - log->Printf( - "Process::PrivateResume() asked to simulate a start & stop."); + LLDB_LOGF(log, + "Process::PrivateResume() asked to simulate a start & stop."); SetPrivateState(eStateRunning); SetPrivateState(eStateStopped); } - } else if (log) - log->Printf("Process::PrivateResume() got an error \"%s\".", - error.AsCString("<unknown error>")); + } else + LLDB_LOGF(log, "Process::PrivateResume() got an error \"%s\".", + error.AsCString("<unknown error>")); return error; } @@ -3199,8 +3137,7 @@ Status Process::StopForDestroyOrDetach(lldb::EventSP &exit_event_sp) { if (m_public_state.GetValue() == eStateRunning || m_private_state.GetValue() == eStateRunning) { Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_PROCESS)); - if (log) - log->Printf("Process::%s() About to stop.", __FUNCTION__); + LLDB_LOGF(log, "Process::%s() About to stop.", __FUNCTION__); ListenerSP listener_sp( Listener::MakeListener("lldb.Process.StopForDestroyOrDetach.hijack")); @@ -3220,17 +3157,15 @@ Status Process::StopForDestroyOrDetach(lldb::EventSP &exit_event_sp) { // anymore... if (state == eStateExited || m_private_state.GetValue() == eStateExited) { - if (log) - log->Printf("Process::%s() Process exited while waiting to stop.", - __FUNCTION__); + LLDB_LOGF(log, "Process::%s() Process exited while waiting to stop.", + __FUNCTION__); return error; } else exit_event_sp.reset(); // It is ok to consume any non-exit stop events if (state != eStateStopped) { - if (log) - log->Printf("Process::%s() failed to stop, state is: %s", __FUNCTION__, - StateAsCString(state)); + LLDB_LOGF(log, "Process::%s() failed to stop, state is: %s", __FUNCTION__, + StateAsCString(state)); // If we really couldn't stop the process then we should just error out // here, but if the lower levels just bobbled sending the event and we // really are stopped, then continue on. @@ -3475,10 +3410,10 @@ bool Process::ShouldBroadcastEvent(Event *event_ptr) { m_stdio_communication.SynchronizeWithReadThread(); RefreshStateAfterStop(); if (ProcessEventData::GetInterruptedFromEvent(event_ptr)) { - if (log) - log->Printf("Process::ShouldBroadcastEvent (%p) stopped due to an " - "interrupt, state: %s", - static_cast<void *>(event_ptr), StateAsCString(state)); + LLDB_LOGF(log, + "Process::ShouldBroadcastEvent (%p) stopped due to an " + "interrupt, state: %s", + static_cast<void *>(event_ptr), StateAsCString(state)); // Even though we know we are going to stop, we should let the threads // have a look at the stop, so they can properly set their state. m_thread_list.ShouldStop(event_ptr); @@ -3496,11 +3431,11 @@ bool Process::ShouldBroadcastEvent(Event *event_ptr) { if (was_restarted || should_resume || m_resume_requested) { Vote stop_vote = m_thread_list.ShouldReportStop(event_ptr); - if (log) - log->Printf("Process::ShouldBroadcastEvent: should_resume: %i state: " - "%s was_restarted: %i stop_vote: %d.", - should_resume, StateAsCString(state), was_restarted, - stop_vote); + LLDB_LOGF(log, + "Process::ShouldBroadcastEvent: should_resume: %i state: " + "%s was_restarted: %i stop_vote: %d.", + should_resume, StateAsCString(state), was_restarted, + stop_vote); switch (stop_vote) { case eVoteYes: @@ -3513,10 +3448,10 @@ bool Process::ShouldBroadcastEvent(Event *event_ptr) { } if (!was_restarted) { - if (log) - log->Printf("Process::ShouldBroadcastEvent (%p) Restarting process " - "from state: %s", - static_cast<void *>(event_ptr), StateAsCString(state)); + LLDB_LOGF(log, + "Process::ShouldBroadcastEvent (%p) Restarting process " + "from state: %s", + static_cast<void *>(event_ptr), StateAsCString(state)); ProcessEventData::SetRestartedInEvent(event_ptr, true); PrivateResume(); } @@ -3543,12 +3478,12 @@ bool Process::ShouldBroadcastEvent(Event *event_ptr) { if (return_value) m_last_broadcast_state = state; - if (log) - log->Printf("Process::ShouldBroadcastEvent (%p) => new state: %s, last " - "broadcast state: %s - %s", - static_cast<void *>(event_ptr), StateAsCString(state), - StateAsCString(m_last_broadcast_state), - return_value ? "YES" : "NO"); + LLDB_LOGF(log, + "Process::ShouldBroadcastEvent (%p) => new state: %s, last " + "broadcast state: %s - %s", + static_cast<void *>(event_ptr), StateAsCString(state), + StateAsCString(m_last_broadcast_state), + return_value ? "YES" : "NO"); return return_value; } @@ -3556,10 +3491,9 @@ bool Process::StartPrivateStateThread(bool is_secondary_thread) { Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_EVENTS)); bool already_running = PrivateStateThreadIsValid(); - if (log) - log->Printf("Process::%s()%s ", __FUNCTION__, - already_running ? " already running" - : " starting private state thread"); + LLDB_LOGF(log, "Process::%s()%s ", __FUNCTION__, + already_running ? " already running" + : " starting private state thread"); if (!is_secondary_thread && already_running) return true; @@ -3617,9 +3551,9 @@ void Process::StopPrivateStateThread() { ControlPrivateStateThread(eBroadcastInternalStateControlStop); else { Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_PROCESS)); - if (log) - log->Printf( - "Went to stop the private state thread, but it was already invalid."); + LLDB_LOGF( + log, + "Went to stop the private state thread, but it was already invalid."); } } @@ -3630,8 +3564,7 @@ void Process::ControlPrivateStateThread(uint32_t signal) { signal == eBroadcastInternalStateControlPause || signal == eBroadcastInternalStateControlResume); - if (log) - log->Printf("Process::%s (signal = %d)", __FUNCTION__, signal); + LLDB_LOGF(log, "Process::%s (signal = %d)", __FUNCTION__, signal); // Signal the private state thread if (m_private_state_thread.IsJoinable()) { @@ -3640,8 +3573,7 @@ void Process::ControlPrivateStateThread(uint32_t signal) { // possible that the thread state is invalid but that the thread is waiting // on a control event instead of simply being on its way out (this should // not happen, but it apparently can). - if (log) - log->Printf("Sending control event of type: %d.", signal); + LLDB_LOGF(log, "Sending control event of type: %d.", signal); std::shared_ptr<EventDataReceipt> event_receipt_sp(new EventDataReceipt()); m_private_state_control_broadcaster.BroadcastEvent(signal, event_receipt_sp); @@ -3669,9 +3601,9 @@ void Process::ControlPrivateStateThread(uint32_t signal) { m_private_state_thread.Reset(); } } else { - if (log) - log->Printf( - "Private state thread already dead, no need to signal it to stop."); + LLDB_LOGF( + log, + "Private state thread already dead, no need to signal it to stop."); } } @@ -3694,8 +3626,7 @@ void Process::HandlePrivateEvent(EventSP &event_sp) { if (m_next_event_action_up) { NextEventAction::EventActionResult action_result = m_next_event_action_up->PerformAction(event_sp); - if (log) - log->Printf("Ran next event action, result was %d.", action_result); + LLDB_LOGF(log, "Ran next event action, result was %d.", action_result); switch (action_result) { case NextEventAction::eEventActionSuccess: @@ -3726,11 +3657,12 @@ void Process::HandlePrivateEvent(EventSP &event_sp) { if (should_broadcast) { const bool is_hijacked = IsHijackedForEvent(eBroadcastBitStateChanged); if (log) { - log->Printf("Process::%s (pid = %" PRIu64 - ") broadcasting new state %s (old state %s) to %s", - __FUNCTION__, GetID(), StateAsCString(new_state), - StateAsCString(GetState()), - is_hijacked ? "hijacked" : "public"); + LLDB_LOGF(log, + "Process::%s (pid = %" PRIu64 + ") broadcasting new state %s (old state %s) to %s", + __FUNCTION__, GetID(), StateAsCString(new_state), + StateAsCString(GetState()), + is_hijacked ? "hijacked" : "public"); } Process::ProcessEventData::SetUpdateStateOnRemoval(event_sp.get()); if (StateIsRunningState(new_state)) { @@ -3742,9 +3674,8 @@ void Process::HandlePrivateEvent(EventSP &event_sp) { PushProcessIOHandler(); m_iohandler_sync.SetValue(m_iohandler_sync.GetValue() + 1, eBroadcastAlways); - if (log) - log->Printf("Process::%s updated m_iohandler_sync to %d", - __FUNCTION__, m_iohandler_sync.GetValue()); + LLDB_LOGF(log, "Process::%s updated m_iohandler_sync to %d", + __FUNCTION__, m_iohandler_sync.GetValue()); } } else if (StateIsStoppedState(new_state, false)) { if (!Process::ProcessEventData::GetRestartedFromEvent(event_sp.get())) { @@ -3785,7 +3716,8 @@ void Process::HandlePrivateEvent(EventSP &event_sp) { BroadcastEvent(event_sp); } else { if (log) { - log->Printf( + LLDB_LOGF( + log, "Process::%s (pid = %" PRIu64 ") suppressing state %s (old state %s): should_broadcast == false", __FUNCTION__, GetID(), StateAsCString(new_state), @@ -3820,9 +3752,8 @@ thread_result_t Process::RunPrivateStateThread(bool is_secondary_thread) { bool control_only = true; Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_PROCESS)); - if (log) - log->Printf("Process::%s (arg = %p, pid = %" PRIu64 ") thread starting...", - __FUNCTION__, static_cast<void *>(this), GetID()); + LLDB_LOGF(log, "Process::%s (arg = %p, pid = %" PRIu64 ") thread starting...", + __FUNCTION__, static_cast<void *>(this), GetID()); bool exit_now = false; bool interrupt_requested = false; @@ -3830,11 +3761,11 @@ thread_result_t Process::RunPrivateStateThread(bool is_secondary_thread) { EventSP event_sp; GetEventsPrivate(event_sp, llvm::None, control_only); if (event_sp->BroadcasterIs(&m_private_state_control_broadcaster)) { - if (log) - log->Printf("Process::%s (arg = %p, pid = %" PRIu64 - ") got a control event: %d", - __FUNCTION__, static_cast<void *>(this), GetID(), - event_sp->GetType()); + LLDB_LOGF(log, + "Process::%s (arg = %p, pid = %" PRIu64 + ") got a control event: %d", + __FUNCTION__, static_cast<void *>(this), GetID(), + event_sp->GetType()); switch (event_sp->GetType()) { case eBroadcastInternalStateControlStop: @@ -3853,23 +3784,24 @@ thread_result_t Process::RunPrivateStateThread(bool is_secondary_thread) { continue; } else if (event_sp->GetType() == eBroadcastBitInterrupt) { if (m_public_state.GetValue() == eStateAttaching) { - if (log) - log->Printf("Process::%s (arg = %p, pid = %" PRIu64 - ") woke up with an interrupt while attaching - " - "forwarding interrupt.", - __FUNCTION__, static_cast<void *>(this), GetID()); + LLDB_LOGF(log, + "Process::%s (arg = %p, pid = %" PRIu64 + ") woke up with an interrupt while attaching - " + "forwarding interrupt.", + __FUNCTION__, static_cast<void *>(this), GetID()); BroadcastEvent(eBroadcastBitInterrupt, nullptr); } else if (StateIsRunningState(m_last_broadcast_state)) { - if (log) - log->Printf("Process::%s (arg = %p, pid = %" PRIu64 - ") woke up with an interrupt - Halting.", - __FUNCTION__, static_cast<void *>(this), GetID()); + LLDB_LOGF(log, + "Process::%s (arg = %p, pid = %" PRIu64 + ") woke up with an interrupt - Halting.", + __FUNCTION__, static_cast<void *>(this), GetID()); Status error = HaltPrivate(); if (error.Fail() && log) - log->Printf("Process::%s (arg = %p, pid = %" PRIu64 - ") failed to halt the process: %s", - __FUNCTION__, static_cast<void *>(this), GetID(), - error.AsCString()); + LLDB_LOGF(log, + "Process::%s (arg = %p, pid = %" PRIu64 + ") failed to halt the process: %s", + __FUNCTION__, static_cast<void *>(this), GetID(), + error.AsCString()); // Halt should generate a stopped event. Make a note of the fact that // we were doing the interrupt, so we can set the interrupted flag // after we receive the event. We deliberately set this to true even if @@ -3883,10 +3815,9 @@ thread_result_t Process::RunPrivateStateThread(bool is_secondary_thread) { // request. We use m_last_broadcast_state, because the Stopped event // may not have been popped of the event queue yet, which is when the // public state gets updated. - if (log) - log->Printf( - "Process::%s ignoring interrupt as we have already stopped.", - __FUNCTION__); + LLDB_LOGF(log, + "Process::%s ignoring interrupt as we have already stopped.", + __FUNCTION__); } continue; } @@ -3908,9 +3839,10 @@ thread_result_t Process::RunPrivateStateThread(bool is_secondary_thread) { ProcessEventData::SetInterruptedInEvent(event_sp.get(), true); interrupt_requested = false; } else if (log) { - log->Printf("Process::%s interrupt_requested, but a non-stopped " - "state '%s' received.", - __FUNCTION__, StateAsCString(internal_state)); + LLDB_LOGF(log, + "Process::%s interrupt_requested, but a non-stopped " + "state '%s' received.", + __FUNCTION__, StateAsCString(internal_state)); } } @@ -3919,20 +3851,19 @@ thread_result_t Process::RunPrivateStateThread(bool is_secondary_thread) { if (internal_state == eStateInvalid || internal_state == eStateExited || internal_state == eStateDetached) { - if (log) - log->Printf("Process::%s (arg = %p, pid = %" PRIu64 - ") about to exit with internal state %s...", - __FUNCTION__, static_cast<void *>(this), GetID(), - StateAsCString(internal_state)); + LLDB_LOGF(log, + "Process::%s (arg = %p, pid = %" PRIu64 + ") about to exit with internal state %s...", + __FUNCTION__, static_cast<void *>(this), GetID(), + StateAsCString(internal_state)); break; } } // Verify log is still enabled before attempting to write to it... - if (log) - log->Printf("Process::%s (arg = %p, pid = %" PRIu64 ") thread exiting...", - __FUNCTION__, static_cast<void *>(this), GetID()); + LLDB_LOGF(log, "Process::%s (arg = %p, pid = %" PRIu64 ") thread exiting...", + __FUNCTION__, static_cast<void *>(this), GetID()); // If we are a secondary thread, then the primary thread we are working for // will have already acquired the public_run_lock, and isn't done with what @@ -4042,10 +3973,10 @@ void Process::ProcessEventData::DoOnRemoval(Event *event_ptr) { if (curr_thread_list.GetSize() != num_threads) { Log *log(lldb_private::GetLogIfAnyCategoriesSet(LIBLLDB_LOG_STEP | LIBLLDB_LOG_PROCESS)); - if (log) - log->Printf( - "Number of threads changed from %u to %u while processing event.", - num_threads, curr_thread_list.GetSize()); + LLDB_LOGF( + log, + "Number of threads changed from %u to %u while processing event.", + num_threads, curr_thread_list.GetSize()); break; } @@ -4054,10 +3985,10 @@ void Process::ProcessEventData::DoOnRemoval(Event *event_ptr) { if (thread_sp->GetIndexID() != thread_index_array[idx]) { Log *log(lldb_private::GetLogIfAnyCategoriesSet(LIBLLDB_LOG_STEP | LIBLLDB_LOG_PROCESS)); - if (log) - log->Printf("The thread at position %u changed from %u to %u while " - "processing event.", - idx, thread_index_array[idx], thread_sp->GetIndexID()); + LLDB_LOGF(log, + "The thread at position %u changed from %u to %u while " + "processing event.", + idx, thread_index_array[idx], thread_sp->GetIndexID()); break; } @@ -4303,9 +4234,8 @@ size_t Process::GetAsyncProfileData(char *buf, size_t buf_size, Status &error) { size_t bytes_available = one_profile_data.size(); if (bytes_available > 0) { Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_PROCESS)); - if (log) - log->Printf("Process::GetProfileData (buf = %p, size = %" PRIu64 ")", - static_cast<void *>(buf), static_cast<uint64_t>(buf_size)); + LLDB_LOGF(log, "Process::GetProfileData (buf = %p, size = %" PRIu64 ")", + static_cast<void *>(buf), static_cast<uint64_t>(buf_size)); if (bytes_available > buf_size) { memcpy(buf, one_profile_data.c_str(), buf_size); one_profile_data.erase(0, buf_size); @@ -4325,9 +4255,8 @@ size_t Process::GetSTDOUT(char *buf, size_t buf_size, Status &error) { size_t bytes_available = m_stdout_data.size(); if (bytes_available > 0) { Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_PROCESS)); - if (log) - log->Printf("Process::GetSTDOUT (buf = %p, size = %" PRIu64 ")", - static_cast<void *>(buf), static_cast<uint64_t>(buf_size)); + LLDB_LOGF(log, "Process::GetSTDOUT (buf = %p, size = %" PRIu64 ")", + static_cast<void *>(buf), static_cast<uint64_t>(buf_size)); if (bytes_available > buf_size) { memcpy(buf, m_stdout_data.c_str(), buf_size); m_stdout_data.erase(0, buf_size); @@ -4345,9 +4274,8 @@ size_t Process::GetSTDERR(char *buf, size_t buf_size, Status &error) { size_t bytes_available = m_stderr_data.size(); if (bytes_available > 0) { Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_PROCESS)); - if (log) - log->Printf("Process::GetSTDERR (buf = %p, size = %" PRIu64 ")", - static_cast<void *>(buf), static_cast<uint64_t>(buf_size)); + LLDB_LOGF(log, "Process::GetSTDERR (buf = %p, size = %" PRIu64 ")", + static_cast<void *>(buf), static_cast<uint64_t>(buf_size)); if (bytes_available > buf_size) { memcpy(buf, m_stderr_data.c_str(), buf_size); m_stderr_data.erase(0, buf_size); @@ -4371,9 +4299,10 @@ public: IOHandlerProcessSTDIO(Process *process, int write_fd) : IOHandler(process->GetTarget().GetDebugger(), IOHandler::Type::ProcessIO), - m_process(process), m_write_file(write_fd, false) { + m_process(process), + m_read_file(GetInputFD(), File::eOpenOptionRead, false), + m_write_file(write_fd, File::eOpenOptionWrite, false) { m_pipe.CreateNew(false); - m_read_file.SetDescriptor(GetInputFD(), false); } ~IOHandlerProcessSTDIO() override = default; @@ -4493,9 +4422,9 @@ public: protected: Process *m_process; - File m_read_file; // Read from this file (usually actual STDIN for LLDB - File m_write_file; // Write to this file (usually the master pty for getting - // io to debuggee) + NativeFile m_read_file; // Read from this file (usually actual STDIN for LLDB + NativeFile m_write_file; // Write to this file (usually the master pty for + // getting io to debuggee) Pipe m_pipe; std::atomic<bool> m_is_running{false}; }; @@ -4532,8 +4461,7 @@ bool Process::PushProcessIOHandler() { IOHandlerSP io_handler_sp(m_process_input_reader); if (io_handler_sp) { Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_PROCESS)); - if (log) - log->Printf("Process::%s pushing IO handler", __FUNCTION__); + LLDB_LOGF(log, "Process::%s pushing IO handler", __FUNCTION__); io_handler_sp->SetIsDone(false); // If we evaluate an utility function, then we don't cancel the current @@ -4797,9 +4725,8 @@ Process::RunThreadPlan(ExecutionContext &exe_ctx, // public events. The simplest thing to do is to spin up a temporary thread // to handle private state thread events while we are fielding public // events here. - if (log) - log->Printf("Running thread plan on private state thread, spinning up " - "another state thread to handle the events."); + LLDB_LOGF(log, "Running thread plan on private state thread, spinning up " + "another state thread to handle the events."); backup_private_state_thread = m_private_state_thread; @@ -4854,9 +4781,10 @@ Process::RunThreadPlan(ExecutionContext &exe_ctx, if (log) { StreamString s; thread_plan_sp->GetDescription(&s, lldb::eDescriptionLevelVerbose); - log->Printf("Process::RunThreadPlan(): Resuming thread %u - 0x%4.4" PRIx64 - " to run thread plan \"%s\".", - thread->GetIndexID(), thread->GetID(), s.GetData()); + LLDB_LOGF(log, + "Process::RunThreadPlan(): Resuming thread %u - 0x%4.4" PRIx64 + " to run thread plan \"%s\".", + thread->GetIndexID(), thread->GetID(), s.GetData()); } bool got_event; @@ -4877,10 +4805,9 @@ Process::RunThreadPlan(ExecutionContext &exe_ctx, if (!options.GetStopOthers() || !options.GetTryAllThreads()) before_first_timeout = false; - if (log) - log->Printf("Stop others: %u, try all: %u, before_first: %u.\n", - options.GetStopOthers(), options.GetTryAllThreads(), - before_first_timeout); + LLDB_LOGF(log, "Stop others: %u, try all: %u, before_first: %u.\n", + options.GetStopOthers(), options.GetTryAllThreads(), + before_first_timeout); // This isn't going to work if there are unfetched events on the queue. Are // there cases where we might want to run the remaining events here, and @@ -4919,10 +4846,10 @@ Process::RunThreadPlan(ExecutionContext &exe_ctx, // loop. The only exception is if we get two running events with no // intervening stop, which can happen, we will just wait for then next // stop event. - if (log) - log->Printf("Top of while loop: do_resume: %i handle_running_event: %i " - "before_first_timeout: %i.", - do_resume, handle_running_event, before_first_timeout); + LLDB_LOGF(log, + "Top of while loop: do_resume: %i handle_running_event: %i " + "before_first_timeout: %i.", + do_resume, handle_running_event, before_first_timeout); if (do_resume || handle_running_event) { // Do the initial resume and wait for the running event before going @@ -4944,10 +4871,10 @@ Process::RunThreadPlan(ExecutionContext &exe_ctx, got_event = listener_sp->GetEvent(event_sp, GetUtilityExpressionTimeout()); if (!got_event) { - if (log) - log->Printf("Process::RunThreadPlan(): didn't get any event after " - "resume %" PRIu32 ", exiting.", - num_resumes); + LLDB_LOGF(log, + "Process::RunThreadPlan(): didn't get any event after " + "resume %" PRIu32 ", exiting.", + num_resumes); diagnostic_manager.Printf(eDiagnosticSeverityError, "didn't get any event after resume %" PRIu32 @@ -4966,13 +4893,13 @@ Process::RunThreadPlan(ExecutionContext &exe_ctx, if (stop_state == eStateStopped) { restarted = Process::ProcessEventData::GetRestartedFromEvent( event_sp.get()); - if (log) - log->Printf( - "Process::RunThreadPlan(): didn't get running event after " - "resume %d, got %s instead (restarted: %i, do_resume: %i, " - "handle_running_event: %i).", - num_resumes, StateAsCString(stop_state), restarted, do_resume, - handle_running_event); + LLDB_LOGF( + log, + "Process::RunThreadPlan(): didn't get running event after " + "resume %d, got %s instead (restarted: %i, do_resume: %i, " + "handle_running_event: %i).", + num_resumes, StateAsCString(stop_state), restarted, do_resume, + handle_running_event); } if (restarted) { @@ -5015,19 +4942,20 @@ Process::RunThreadPlan(ExecutionContext &exe_ctx, if (log) { if (timeout) { auto now = system_clock::now(); - log->Printf("Process::RunThreadPlan(): about to wait - now is %s - " - "endpoint is %s", - llvm::to_string(now).c_str(), - llvm::to_string(now + *timeout).c_str()); + LLDB_LOGF(log, + "Process::RunThreadPlan(): about to wait - now is %s - " + "endpoint is %s", + llvm::to_string(now).c_str(), + llvm::to_string(now + *timeout).c_str()); } else { - log->Printf("Process::RunThreadPlan(): about to wait forever."); + LLDB_LOGF(log, "Process::RunThreadPlan(): about to wait forever."); } } #ifdef LLDB_RUN_THREAD_HALT_WITH_EVENT // See comment above... if (miss_first_event) { - usleep(1000); + std::this_thread::sleep_for(std::chrono::milliseconds(1)); miss_first_event = false; got_event = false; } else @@ -5044,17 +4972,15 @@ Process::RunThreadPlan(ExecutionContext &exe_ctx, return_value = eExpressionInterrupted; diagnostic_manager.PutString(eDiagnosticSeverityRemark, "execution halted by user interrupt."); - if (log) - log->Printf("Process::RunThreadPlan(): Got interrupted by " - "eBroadcastBitInterrupted, exiting."); + LLDB_LOGF(log, "Process::RunThreadPlan(): Got interrupted by " + "eBroadcastBitInterrupted, exiting."); break; } else { stop_state = Process::ProcessEventData::GetStateFromEvent(event_sp.get()); - if (log) - log->Printf( - "Process::RunThreadPlan(): in while loop, got event: %s.", - StateAsCString(stop_state)); + LLDB_LOGF(log, + "Process::RunThreadPlan(): in while loop, got event: %s.", + StateAsCString(stop_state)); switch (stop_state) { case lldb::eStateStopped: { @@ -5064,18 +4990,18 @@ Process::RunThreadPlan(ExecutionContext &exe_ctx, if (!thread_sp) { // Ooh, our thread has vanished. Unlikely that this was // successful execution... - if (log) - log->Printf("Process::RunThreadPlan(): execution completed " - "but our thread (index-id=%u) has vanished.", - thread_idx_id); + LLDB_LOGF(log, + "Process::RunThreadPlan(): execution completed " + "but our thread (index-id=%u) has vanished.", + thread_idx_id); return_value = eExpressionInterrupted; } else if (Process::ProcessEventData::GetRestartedFromEvent( event_sp.get())) { // If we were restarted, we just need to go back up to fetch // another event. if (log) { - log->Printf("Process::RunThreadPlan(): Got a stop and " - "restart, so we'll continue waiting."); + LLDB_LOGF(log, "Process::RunThreadPlan(): Got a stop and " + "restart, so we'll continue waiting."); } keep_going = true; do_resume = false; @@ -5098,10 +5024,10 @@ Process::RunThreadPlan(ExecutionContext &exe_ctx, break; default: - if (log) - log->Printf("Process::RunThreadPlan(): execution stopped with " - "unexpected state: %s.", - StateAsCString(stop_state)); + LLDB_LOGF(log, + "Process::RunThreadPlan(): execution stopped with " + "unexpected state: %s.", + StateAsCString(stop_state)); if (stop_state == eStateExited) event_to_broadcast_sp = event_sp; @@ -5162,8 +5088,7 @@ Process::RunThreadPlan(ExecutionContext &exe_ctx, while (try_halt_again < num_retries) { Status halt_error; if (do_halt) { - if (log) - log->Printf("Process::RunThreadPlan(): Running Halt."); + LLDB_LOGF(log, "Process::RunThreadPlan(): Running Halt."); const bool clear_thread_plans = false; const bool use_run_lock = false; Halt(clear_thread_plans, use_run_lock); @@ -5179,8 +5104,9 @@ Process::RunThreadPlan(ExecutionContext &exe_ctx, stop_state = Process::ProcessEventData::GetStateFromEvent(event_sp.get()); if (log) { - log->Printf("Process::RunThreadPlan(): Stopped with event: %s", - StateAsCString(stop_state)); + LLDB_LOGF(log, + "Process::RunThreadPlan(): Stopped with event: %s", + StateAsCString(stop_state)); if (stop_state == lldb::eStateStopped && Process::ProcessEventData::GetInterruptedFromEvent( event_sp.get())) @@ -5379,24 +5305,25 @@ Process::RunThreadPlan(ExecutionContext &exe_ctx, } while (false); if (event_explanation) - log->Printf("Process::RunThreadPlan(): execution interrupted: %s %s", - s.GetData(), event_explanation); + LLDB_LOGF(log, + "Process::RunThreadPlan(): execution interrupted: %s %s", + s.GetData(), event_explanation); else - log->Printf("Process::RunThreadPlan(): execution interrupted: %s", - s.GetData()); + LLDB_LOGF(log, "Process::RunThreadPlan(): execution interrupted: %s", + s.GetData()); } if (should_unwind) { - if (log) - log->Printf("Process::RunThreadPlan: ExecutionInterrupted - " - "discarding thread plans up to %p.", - static_cast<void *>(thread_plan_sp.get())); + LLDB_LOGF(log, + "Process::RunThreadPlan: ExecutionInterrupted - " + "discarding thread plans up to %p.", + static_cast<void *>(thread_plan_sp.get())); thread->DiscardThreadPlansUpToPlan(thread_plan_sp); } else { - if (log) - log->Printf("Process::RunThreadPlan: ExecutionInterrupted - for " - "plan: %p not discarding.", - static_cast<void *>(thread_plan_sp.get())); + LLDB_LOGF(log, + "Process::RunThreadPlan: ExecutionInterrupted - for " + "plan: %p not discarding.", + static_cast<void *>(thread_plan_sp.get())); } } else if (return_value == eExpressionSetupError) { if (log) @@ -5559,9 +5486,8 @@ size_t Process::GetThreadStatus(Stream &strm, ++num_thread_infos_dumped; } else { Log *log(lldb_private::GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PROCESS)); - if (log) - log->Printf("Process::GetThreadStatus - thread 0x" PRIu64 - " vanished while running Thread::GetStatus."); + LLDB_LOGF(log, "Process::GetThreadStatus - thread 0x" PRIu64 + " vanished while running Thread::GetStatus."); } } return num_thread_infos_dumped; @@ -5612,6 +5538,12 @@ ProcessRunLock &Process::GetRunLock() { return m_public_run_lock; } +bool Process::CurrentThreadIsPrivateStateThread() +{ + return m_private_state_thread.EqualsThread(Host::GetCurrentThread()); +} + + void Process::Flush() { m_thread_list.Flush(); m_extended_thread_list.Flush(); @@ -5622,8 +5554,7 @@ void Process::Flush() { void Process::DidExec() { Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_PROCESS)); - if (log) - log->Printf("Process::%s()", __FUNCTION__); + LLDB_LOGF(log, "Process::%s()", __FUNCTION__); Target &target = GetTarget(); target.CleanupProcess(); @@ -5669,7 +5600,7 @@ addr_t Process::ResolveIndirectFunction(const Address *address, Status &error) { if (iter != m_resolved_indirect_addresses.end()) { function_addr = (*iter).second; } else { - if (!InferiorCall(this, address, function_addr)) { + if (!CallVoidArgVoidPtrReturn(address, function_addr)) { Symbol *symbol = address->CalculateSymbolContextSymbol(); error.SetErrorStringWithFormat( "Unable to call resolver for indirect function %s", @@ -5929,19 +5860,18 @@ void Process::MapSupportedStructuredDataPlugins( // Bail out early if there are no type names to map. if (supported_type_names.GetSize() == 0) { - if (log) - log->Printf("Process::%s(): no structured data types supported", - __FUNCTION__); + LLDB_LOGF(log, "Process::%s(): no structured data types supported", + __FUNCTION__); return; } // Convert StructuredData type names to ConstString instances. std::set<ConstString> const_type_names; - if (log) - log->Printf("Process::%s(): the process supports the following async " - "structured data types:", - __FUNCTION__); + LLDB_LOGF(log, + "Process::%s(): the process supports the following async " + "structured data types:", + __FUNCTION__); supported_type_names.ForEach( [&const_type_names, &log](StructuredData::Object *object) { @@ -5988,11 +5918,11 @@ void Process::MapSupportedStructuredDataPlugins( m_structured_data_plugin_map.insert( std::make_pair(type_name, plugin_sp)); names_to_remove.push_back(type_name); - if (log) - log->Printf("Process::%s(): using plugin %s for type name " - "%s", - __FUNCTION__, plugin_sp->GetPluginName().GetCString(), - type_name.GetCString()); + LLDB_LOGF(log, + "Process::%s(): using plugin %s for type name " + "%s", + __FUNCTION__, plugin_sp->GetPluginName().GetCString(), + type_name.GetCString()); } } @@ -6042,7 +5972,62 @@ UtilityFunction *Process::GetLoadImageUtilityFunction( llvm::function_ref<std::unique_ptr<UtilityFunction>()> factory) { if (platform != GetTarget().GetPlatform().get()) return nullptr; - std::call_once(m_dlopen_utility_func_flag_once, - [&] { m_dlopen_utility_func_up = factory(); }); + llvm::call_once(m_dlopen_utility_func_flag_once, + [&] { m_dlopen_utility_func_up = factory(); }); return m_dlopen_utility_func_up.get(); } + +bool Process::CallVoidArgVoidPtrReturn(const Address *address, + addr_t &returned_func, + bool trap_exceptions) { + Thread *thread = GetThreadList().GetExpressionExecutionThread().get(); + if (thread == nullptr || address == nullptr) + return false; + + EvaluateExpressionOptions options; + options.SetStopOthers(true); + options.SetUnwindOnError(true); + options.SetIgnoreBreakpoints(true); + options.SetTryAllThreads(true); + options.SetDebug(false); + options.SetTimeout(GetUtilityExpressionTimeout()); + options.SetTrapExceptions(trap_exceptions); + + auto type_system_or_err = + GetTarget().GetScratchTypeSystemForLanguage(eLanguageTypeC); + if (!type_system_or_err) { + llvm::consumeError(type_system_or_err.takeError()); + return false; + } + CompilerType void_ptr_type = + type_system_or_err->GetBasicTypeFromAST(eBasicTypeVoid).GetPointerType(); + lldb::ThreadPlanSP call_plan_sp(new ThreadPlanCallFunction( + *thread, *address, void_ptr_type, llvm::ArrayRef<addr_t>(), options)); + if (call_plan_sp) { + DiagnosticManager diagnostics; + + StackFrame *frame = thread->GetStackFrameAtIndex(0).get(); + if (frame) { + ExecutionContext exe_ctx; + frame->CalculateExecutionContext(exe_ctx); + ExpressionResults result = + RunThreadPlan(exe_ctx, call_plan_sp, options, diagnostics); + if (result == eExpressionCompleted) { + returned_func = + call_plan_sp->GetReturnValueObject()->GetValueAsUnsigned( + LLDB_INVALID_ADDRESS); + + if (GetAddressByteSize() == 4) { + if (returned_func == UINT32_MAX) + return false; + } else if (GetAddressByteSize() == 8) { + if (returned_func == UINT64_MAX) + return false; + } + return true; + } + } + } + + return false; +} diff --git a/source/Target/RegisterContext.cpp b/source/Target/RegisterContext.cpp index c960260f30c8..f29cf435d028 100644 --- a/source/Target/RegisterContext.cpp +++ b/source/Target/RegisterContext.cpp @@ -82,14 +82,12 @@ RegisterContext::UpdateDynamicRegisterSize(const lldb_private::ArchSpec &arch, DataExtractor dwarf_data(dwarf_opcode_ptr, dwarf_opcode_len, arch.GetByteOrder(), addr_size); ModuleSP opcode_ctx; - DWARFExpression dwarf_expr(opcode_ctx, dwarf_data, nullptr, 0, - dwarf_opcode_len); + DWARFExpression dwarf_expr(opcode_ctx, dwarf_data, nullptr); Value result; Status error; - const lldb::offset_t offset = 0; if (dwarf_expr.Evaluate(&exe_ctx, this, opcode_ctx, dwarf_data, nullptr, - offset, dwarf_opcode_len, eRegisterKindDWARF, nullptr, - nullptr, result, &error)) { + eRegisterKindDWARF, nullptr, nullptr, result, + &error)) { expr_result = result.GetScalar().SInt(-1); switch (expr_result) { case 0: diff --git a/source/Target/RemoteAwarePlatform.cpp b/source/Target/RemoteAwarePlatform.cpp index 1704e1533e9c..faa217ac83ef 100644 --- a/source/Target/RemoteAwarePlatform.cpp +++ b/source/Target/RemoteAwarePlatform.cpp @@ -61,8 +61,8 @@ Status RemoteAwarePlatform::SetFilePermissions(const FileSpec &file_spec, } lldb::user_id_t RemoteAwarePlatform::OpenFile(const FileSpec &file_spec, - uint32_t flags, uint32_t mode, - Status &error) { + File::OpenOptions flags, + uint32_t mode, Status &error) { if (IsHost()) return FileCache::GetInstance().OpenFile(file_spec, flags, mode, error); if (m_remote_platform_sp) diff --git a/source/Target/SectionLoadList.cpp b/source/Target/SectionLoadList.cpp index 598f49ca13de..f2546a893194 100644 --- a/source/Target/SectionLoadList.cpp +++ b/source/Target/SectionLoadList.cpp @@ -121,7 +121,8 @@ bool SectionLoadList::SetSectionLoadAddress(const lldb::SectionSP §ion, } else { if (log) { - log->Printf( + LLDB_LOGF( + log, "SectionLoadList::%s (section = %p (%s), load_addr = 0x%16.16" PRIx64 ") error: module has been deleted", __FUNCTION__, static_cast<void *>(section.get()), @@ -145,9 +146,9 @@ size_t SectionLoadList::SetSectionUnloaded(const lldb::SectionSP §ion_sp) { section_sp->GetModule()->GetFileSpec()); module_name = module_file_spec.GetPath(); } - log->Printf("SectionLoadList::%s (section = %p (%s.%s))", __FUNCTION__, - static_cast<void *>(section_sp.get()), module_name.c_str(), - section_sp->GetName().AsCString()); + LLDB_LOGF(log, "SectionLoadList::%s (section = %p (%s.%s))", __FUNCTION__, + static_cast<void *>(section_sp.get()), module_name.c_str(), + section_sp->GetName().AsCString()); } std::lock_guard<std::recursive_mutex> guard(m_mutex); @@ -179,7 +180,8 @@ bool SectionLoadList::SetSectionUnloaded(const lldb::SectionSP §ion_sp, const FileSpec &module_file_spec(section_sp->GetModule()->GetFileSpec()); module_name = module_file_spec.GetPath(); } - log->Printf( + LLDB_LOGF( + log, "SectionLoadList::%s (section = %p (%s.%s), load_addr = 0x%16.16" PRIx64 ")", __FUNCTION__, static_cast<void *>(section_sp.get()), diff --git a/source/Target/StackFrame.cpp b/source/Target/StackFrame.cpp index f8b22d96e16f..5e5a596e471d 100644 --- a/source/Target/StackFrame.cpp +++ b/source/Target/StackFrame.cpp @@ -29,6 +29,7 @@ #include "lldb/Target/StackFrameRecognizer.h" #include "lldb/Target/Target.h" #include "lldb/Target/Thread.h" +#include "lldb/Utility/Log.h" #include "lldb/Utility/RegisterValue.h" #include "lldb/lldb-enumerations.h" @@ -50,14 +51,16 @@ using namespace lldb_private; StackFrame::StackFrame(const ThreadSP &thread_sp, user_id_t frame_idx, user_id_t unwind_frame_index, addr_t cfa, bool cfa_is_valid, addr_t pc, StackFrame::Kind kind, + bool behaves_like_zeroth_frame, const SymbolContext *sc_ptr) : m_thread_wp(thread_sp), m_frame_index(frame_idx), m_concrete_frame_index(unwind_frame_index), m_reg_context_sp(), m_id(pc, cfa, nullptr), m_frame_code_addr(pc), m_sc(), m_flags(), m_frame_base(), m_frame_base_error(), m_cfa_is_valid(cfa_is_valid), - m_stack_frame_kind(kind), m_variable_list_sp(), - m_variable_list_value_objects(), m_recognized_frame_sp(), m_disassembly(), - m_mutex() { + m_stack_frame_kind(kind), + m_behaves_like_zeroth_frame(behaves_like_zeroth_frame), + m_variable_list_sp(), m_variable_list_value_objects(), + m_recognized_frame_sp(), m_disassembly(), m_mutex() { // If we don't have a CFA value, use the frame index for our StackID so that // recursive functions properly aren't confused with one another on a history // stack. @@ -74,15 +77,17 @@ StackFrame::StackFrame(const ThreadSP &thread_sp, user_id_t frame_idx, StackFrame::StackFrame(const ThreadSP &thread_sp, user_id_t frame_idx, user_id_t unwind_frame_index, const RegisterContextSP ®_context_sp, addr_t cfa, - addr_t pc, const SymbolContext *sc_ptr) + addr_t pc, bool behaves_like_zeroth_frame, + const SymbolContext *sc_ptr) : m_thread_wp(thread_sp), m_frame_index(frame_idx), m_concrete_frame_index(unwind_frame_index), m_reg_context_sp(reg_context_sp), m_id(pc, cfa, nullptr), m_frame_code_addr(pc), m_sc(), m_flags(), m_frame_base(), m_frame_base_error(), m_cfa_is_valid(true), - m_stack_frame_kind(StackFrame::Kind::Regular), m_variable_list_sp(), - m_variable_list_value_objects(), m_recognized_frame_sp(), m_disassembly(), - m_mutex() { + m_stack_frame_kind(StackFrame::Kind::Regular), + m_behaves_like_zeroth_frame(behaves_like_zeroth_frame), + m_variable_list_sp(), m_variable_list_value_objects(), + m_recognized_frame_sp(), m_disassembly(), m_mutex() { if (sc_ptr != nullptr) { m_sc = *sc_ptr; m_flags.Set(m_sc.GetResolvedMask()); @@ -98,7 +103,8 @@ StackFrame::StackFrame(const ThreadSP &thread_sp, user_id_t frame_idx, StackFrame::StackFrame(const ThreadSP &thread_sp, user_id_t frame_idx, user_id_t unwind_frame_index, const RegisterContextSP ®_context_sp, addr_t cfa, - const Address &pc_addr, const SymbolContext *sc_ptr) + const Address &pc_addr, bool behaves_like_zeroth_frame, + const SymbolContext *sc_ptr) : m_thread_wp(thread_sp), m_frame_index(frame_idx), m_concrete_frame_index(unwind_frame_index), m_reg_context_sp(reg_context_sp), @@ -106,9 +112,10 @@ StackFrame::StackFrame(const ThreadSP &thread_sp, user_id_t frame_idx, nullptr), m_frame_code_addr(pc_addr), m_sc(), m_flags(), m_frame_base(), m_frame_base_error(), m_cfa_is_valid(true), - m_stack_frame_kind(StackFrame::Kind::Regular), m_variable_list_sp(), - m_variable_list_value_objects(), m_recognized_frame_sp(), m_disassembly(), - m_mutex() { + m_stack_frame_kind(StackFrame::Kind::Regular), + m_behaves_like_zeroth_frame(behaves_like_zeroth_frame), + m_variable_list_sp(), m_variable_list_value_objects(), + m_recognized_frame_sp(), m_disassembly(), m_mutex() { if (sc_ptr != nullptr) { m_sc = *sc_ptr; m_flags.Set(m_sc.GetResolvedMask()); @@ -288,7 +295,7 @@ StackFrame::GetSymbolContext(SymbolContextItem resolve_scope) { // following the function call instruction... Address lookup_addr(GetFrameCodeAddress()); - if (m_frame_index > 0 && lookup_addr.IsValid()) { + if (!m_behaves_like_zeroth_frame && lookup_addr.IsValid()) { addr_t offset = lookup_addr.GetOffset(); if (offset > 0) { lookup_addr.SetOffset(offset - 1); @@ -1357,13 +1364,16 @@ lldb::ValueObjectSP StackFrame::GuessValueForAddress(lldb::addr_t addr) { if (target_sp->ResolveLoadAddress(base_and_offset.first->m_immediate + base_and_offset.second, addr)) { - TypeSystem *c_type_system = - target_sp->GetScratchTypeSystemForLanguage(nullptr, eLanguageTypeC); - if (!c_type_system) { + auto c_type_system_or_err = + target_sp->GetScratchTypeSystemForLanguage(eLanguageTypeC); + if (auto err = c_type_system_or_err.takeError()) { + LLDB_LOG_ERROR( + lldb_private::GetLogIfAnyCategoriesSet(LIBLLDB_LOG_THREAD), + std::move(err), "Unable to guess value for given address"); return ValueObjectSP(); } else { CompilerType void_ptr_type = - c_type_system + c_type_system_or_err ->GetBasicTypeFromAST(lldb::BasicType::eBasicTypeChar) .GetPointerType(); return ValueObjectMemory::Create(this, "", addr, void_ptr_type); diff --git a/source/Target/StackFrameList.cpp b/source/Target/StackFrameList.cpp index 5492dda46402..6d0c46259c20 100644 --- a/source/Target/StackFrameList.cpp +++ b/source/Target/StackFrameList.cpp @@ -67,7 +67,8 @@ uint32_t StackFrameList::GetCurrentInlinedDepth() { m_current_inlined_depth = UINT32_MAX; Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_STEP)); if (log && log->GetVerbose()) - log->Printf( + LLDB_LOGF( + log, "GetCurrentInlinedDepth: invalidating current inlined depth.\n"); } return m_current_inlined_depth; @@ -90,7 +91,8 @@ void StackFrameList::ResetCurrentInlinedDepth() { m_current_inlined_pc = LLDB_INVALID_ADDRESS; Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_STEP)); if (log && log->GetVerbose()) - log->Printf( + LLDB_LOGF( + log, "ResetCurrentInlinedDepth: Invalidating current inlined depth.\n"); return; } @@ -184,9 +186,10 @@ void StackFrameList::ResetCurrentInlinedDepth() { m_current_inlined_depth = num_inlined_functions + 1; Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_STEP)); if (log && log->GetVerbose()) - log->Printf("ResetCurrentInlinedDepth: setting inlined " - "depth: %d 0x%" PRIx64 ".\n", - m_current_inlined_depth, curr_pc); + LLDB_LOGF(log, + "ResetCurrentInlinedDepth: setting inlined " + "depth: %d 0x%" PRIx64 ".\n", + m_current_inlined_depth, curr_pc); break; } @@ -247,26 +250,19 @@ static void FindInterveningFrames(Function &begin, Function &end, begin.GetDisplayName(), end.GetDisplayName(), return_pc); // Find a non-tail calling edge with the correct return PC. - auto first_level_edges = begin.GetCallEdges(); if (log) - for (const CallEdge &edge : first_level_edges) + for (const CallEdge &edge : begin.GetCallEdges()) LLDB_LOG(log, "FindInterveningFrames: found call with retn-PC = {0:x}", edge.GetReturnPCAddress(begin, target)); - auto first_edge_it = std::lower_bound( - first_level_edges.begin(), first_level_edges.end(), return_pc, - [&](const CallEdge &edge, addr_t target_pc) { - return edge.GetReturnPCAddress(begin, target) < target_pc; - }); - if (first_edge_it == first_level_edges.end() || - first_edge_it->GetReturnPCAddress(begin, target) != return_pc) { + CallEdge *first_edge = begin.GetCallEdgeForReturnAddress(return_pc, target); + if (!first_edge) { LLDB_LOG(log, "No call edge outgoing from {0} with retn-PC == {1:x}", begin.GetDisplayName(), return_pc); return; } - CallEdge &first_edge = const_cast<CallEdge &>(*first_edge_it); // The first callee may not be resolved, or there may be nothing to fill in. - Function *first_callee = first_edge.GetCallee(images); + Function *first_callee = first_edge->GetCallee(images); if (!first_callee) { LLDB_LOG(log, "Could not resolve callee"); return; @@ -290,15 +286,15 @@ static void FindInterveningFrames(Function &begin, Function &end, DFS(Function *end, ModuleList &images) : end(end), images(images) {} - void search(Function *first_callee, std::vector<Function *> &path) { + void search(Function &first_callee, std::vector<Function *> &path) { dfs(first_callee); if (!ambiguous) path = std::move(solution_path); } - void dfs(Function *callee) { + void dfs(Function &callee) { // Found a path to the target function. - if (callee == end) { + if (&callee == end) { if (solution_path.empty()) solution_path = active_path; else @@ -310,19 +306,19 @@ static void FindInterveningFrames(Function &begin, Function &end, // there's more than one way to reach a target. This errs on the side of // caution: it conservatively stops searching when some solutions are // still possible to save time in the average case. - if (!visited_nodes.insert(callee).second) { + if (!visited_nodes.insert(&callee).second) { ambiguous = true; return; } // Search the calls made from this callee. - active_path.push_back(callee); - for (CallEdge &edge : callee->GetTailCallingEdges()) { + active_path.push_back(&callee); + for (CallEdge &edge : callee.GetTailCallingEdges()) { Function *next_callee = edge.GetCallee(images); if (!next_callee) continue; - dfs(next_callee); + dfs(*next_callee); if (ambiguous) return; } @@ -330,7 +326,7 @@ static void FindInterveningFrames(Function &begin, Function &end, } }; - DFS(&end, images).search(first_callee, path); + DFS(&end, images).search(*first_callee, path); } /// Given that \p next_frame will be appended to the frame list, synthesize @@ -394,11 +390,13 @@ void StackFrameList::SynthesizeTailCallFrames(StackFrame &next_frame) { bool cfa_is_valid = false; addr_t pc = callee->GetAddressRange().GetBaseAddress().GetLoadAddress(&target); + constexpr bool behaves_like_zeroth_frame = false; SymbolContext sc; callee->CalculateSymbolContext(&sc); auto synth_frame = std::make_shared<StackFrame>( m_thread.shared_from_this(), frame_idx, concrete_frame_idx, cfa, - cfa_is_valid, pc, StackFrame::Kind::Artificial, &sc); + cfa_is_valid, pc, StackFrame::Kind::Artificial, + behaves_like_zeroth_frame, &sc); m_frames.push_back(synth_frame); LLDB_LOG(log, "Pushed frame {0}", callee->GetDisplayName()); } @@ -448,6 +446,7 @@ void StackFrameList::GetFramesUpTo(uint32_t end_idx) { uint32_t idx = m_concrete_frames_fetched++; lldb::addr_t pc = LLDB_INVALID_ADDRESS; lldb::addr_t cfa = LLDB_INVALID_ADDRESS; + bool behaves_like_zeroth_frame = (idx == 0); if (idx == 0) { // We might have already created frame zero, only create it if we need // to. @@ -455,8 +454,9 @@ void StackFrameList::GetFramesUpTo(uint32_t end_idx) { RegisterContextSP reg_ctx_sp(m_thread.GetRegisterContext()); if (reg_ctx_sp) { - const bool success = - unwinder && unwinder->GetFrameInfoAtIndex(idx, cfa, pc); + const bool success = unwinder && + unwinder->GetFrameInfoAtIndex( + idx, cfa, pc, behaves_like_zeroth_frame); // There shouldn't be any way not to get the frame info for frame // 0. But if the unwinder can't make one, lets make one by hand // with the SP as the CFA and see if that gets any further. @@ -467,7 +467,7 @@ void StackFrameList::GetFramesUpTo(uint32_t end_idx) { unwind_frame_sp = std::make_shared<StackFrame>( m_thread.shared_from_this(), m_frames.size(), idx, reg_ctx_sp, - cfa, pc, nullptr); + cfa, pc, behaves_like_zeroth_frame, nullptr); m_frames.push_back(unwind_frame_sp); } } else { @@ -475,8 +475,9 @@ void StackFrameList::GetFramesUpTo(uint32_t end_idx) { cfa = unwind_frame_sp->m_id.GetCallFrameAddress(); } } else { - const bool success = - unwinder && unwinder->GetFrameInfoAtIndex(idx, cfa, pc); + const bool success = unwinder && + unwinder->GetFrameInfoAtIndex( + idx, cfa, pc, behaves_like_zeroth_frame); if (!success) { // We've gotten to the end of the stack. SetAllFramesFetched(); @@ -485,7 +486,7 @@ void StackFrameList::GetFramesUpTo(uint32_t end_idx) { const bool cfa_is_valid = true; unwind_frame_sp = std::make_shared<StackFrame>( m_thread.shared_from_this(), m_frames.size(), idx, cfa, cfa_is_valid, - pc, StackFrame::Kind::Regular, nullptr); + pc, StackFrame::Kind::Regular, behaves_like_zeroth_frame, nullptr); // Create synthetic tail call frames between the previous frame and the // newly-found frame. The new frame's index may change after this call, @@ -527,10 +528,11 @@ void StackFrameList::GetFramesUpTo(uint32_t end_idx) { while (unwind_sc.GetParentOfInlinedScope( curr_frame_address, next_frame_sc, next_frame_address)) { next_frame_sc.line_entry.ApplyFileMappings(target_sp); - StackFrameSP frame_sp( - new StackFrame(m_thread.shared_from_this(), m_frames.size(), idx, - unwind_frame_sp->GetRegisterContextSP(), cfa, - next_frame_address, &next_frame_sc)); + behaves_like_zeroth_frame = false; + StackFrameSP frame_sp(new StackFrame( + m_thread.shared_from_this(), m_frames.size(), idx, + unwind_frame_sp->GetRegisterContextSP(), cfa, next_frame_address, + behaves_like_zeroth_frame, &next_frame_sc)); m_frames.push_back(frame_sp); unwind_sc = next_frame_sc; @@ -661,11 +663,13 @@ StackFrameSP StackFrameList::GetFrameAtIndex(uint32_t idx) { Unwind *unwinder = m_thread.GetUnwinder(); if (unwinder) { addr_t pc, cfa; - if (unwinder->GetFrameInfoAtIndex(idx, cfa, pc)) { + bool behaves_like_zeroth_frame = (idx == 0); + if (unwinder->GetFrameInfoAtIndex(idx, cfa, pc, + behaves_like_zeroth_frame)) { const bool cfa_is_valid = true; frame_sp = std::make_shared<StackFrame>( m_thread.shared_from_this(), idx, idx, cfa, cfa_is_valid, pc, - StackFrame::Kind::Regular, nullptr); + StackFrame::Kind::Regular, behaves_like_zeroth_frame, nullptr); Function *function = frame_sp->GetSymbolContext(eSymbolContextFunction).function; diff --git a/source/Target/StopInfo.cpp b/source/Target/StopInfo.cpp index 6db0c2b037e9..28179b7e1ce0 100644 --- a/source/Target/StopInfo.cpp +++ b/source/Target/StopInfo.cpp @@ -147,10 +147,10 @@ public: } else { Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_PROCESS)); - if (log) - log->Printf( - "Process::%s could not find breakpoint site id: %" PRId64 "...", - __FUNCTION__, m_value); + LLDB_LOGF(log, + "Process::%s could not find breakpoint site id: %" PRId64 + "...", + __FUNCTION__, m_value); m_should_stop = true; } @@ -270,7 +270,7 @@ protected: if (!thread_sp->IsValid()) { // This shouldn't ever happen, but just in case, don't do more harm. if (log) { - log->Printf("PerformAction got called with an invalid thread."); + LLDB_LOGF(log, "PerformAction got called with an invalid thread."); } m_should_stop = true; m_should_stop_is_valid = true; @@ -339,10 +339,9 @@ protected: return; } - if (log) - log->Printf("StopInfoBreakpoint::PerformAction - Hit a " - "breakpoint while running an expression," - " not running commands to avoid recursion."); + LLDB_LOGF(log, "StopInfoBreakpoint::PerformAction - Hit a " + "breakpoint while running an expression," + " not running commands to avoid recursion."); bool ignoring_breakpoints = process->GetIgnoreBreakpointsInExpressions(); if (ignoring_breakpoints) { @@ -359,10 +358,10 @@ protected: } else { m_should_stop = true; } - if (log) - log->Printf("StopInfoBreakpoint::PerformAction - in expression, " - "continuing: %s.", - m_should_stop ? "true" : "false"); + LLDB_LOGF(log, + "StopInfoBreakpoint::PerformAction - in expression, " + "continuing: %s.", + m_should_stop ? "true" : "false"); process->GetTarget().GetDebugger().GetAsyncOutputStream()->Printf( "Warning: hit breakpoint while running function, skipping " "commands and conditions to prevent recursion.\n"); @@ -402,10 +401,11 @@ protected: // aren't: if (!bp_loc_sp->ValidForThisThread(thread_sp.get())) { if (log) { - log->Printf("Breakpoint %s hit on thread 0x%llx but it was not " - "for this thread, continuing.", - loc_desc.GetData(), static_cast<unsigned long long>( - thread_sp->GetID())); + LLDB_LOGF(log, + "Breakpoint %s hit on thread 0x%llx but it was not " + "for this thread, continuing.", + loc_desc.GetData(), + static_cast<unsigned long long>(thread_sp->GetID())); } continue; } @@ -445,21 +445,18 @@ protected: error_sp->EOL(); const char *err_str = condition_error.AsCString("<Unknown Error>"); - if (log) - log->Printf("Error evaluating condition: \"%s\"\n", err_str); + LLDB_LOGF(log, "Error evaluating condition: \"%s\"\n", err_str); error_sp->PutCString(err_str); error_sp->EOL(); error_sp->Flush(); } else { - if (log) { - log->Printf("Condition evaluated for breakpoint %s on thread " - "0x%llx conditon_says_stop: %i.", - loc_desc.GetData(), - static_cast<unsigned long long>( - thread_sp->GetID()), - condition_says_stop); - } + LLDB_LOGF(log, + "Condition evaluated for breakpoint %s on thread " + "0x%llx conditon_says_stop: %i.", + loc_desc.GetData(), + static_cast<unsigned long long>(thread_sp->GetID()), + condition_says_stop); if (!condition_says_stop) { // We don't want to increment the hit count of breakpoints if // the condition fails. We've already bumped it by the time @@ -479,9 +476,9 @@ protected: bool auto_continue_says_stop = true; if (bp_loc_sp->IsAutoContinue()) { - if (log) - log->Printf("Continuing breakpoint %s as AutoContinue was set.", - loc_desc.GetData()); + LLDB_LOGF(log, + "Continuing breakpoint %s as AutoContinue was set.", + loc_desc.GetData()); // We want this stop reported, so you will know we auto-continued // but only for external breakpoints: if (!internal_breakpoint) @@ -533,10 +530,10 @@ protected: Log *log_process( lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_PROCESS)); - if (log_process) - log_process->Printf( - "Process::%s could not find breakpoint site id: %" PRId64 "...", - __FUNCTION__, m_value); + LLDB_LOGF(log_process, + "Process::%s could not find breakpoint site id: %" PRId64 + "...", + __FUNCTION__, m_value); } if ((!m_should_stop || internal_breakpoint) && @@ -546,15 +543,15 @@ protected: // additionally to the breakpoint m_should_stop = true; - // Here we clean the preset stop info so the next GetStopInfo call will - // find the appropriate stop info, which should be the stop info - // related to the completed plan - thread_sp->ResetStopInfo(); + // We know we're stopping for a completed plan and we don't want to + // show the breakpoint stop, so compute the public stop info immediately + // here. + thread_sp->CalculatePublicStopInfo(); } - if (log) - log->Printf("Process::%s returning from action with m_should_stop: %d.", - __FUNCTION__, m_should_stop); + LLDB_LOGF(log, + "Process::%s returning from action with m_should_stop: %d.", + __FUNCTION__, m_should_stop); } } @@ -664,11 +661,10 @@ protected: } else { Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_PROCESS)); - if (log) - log->Printf( - "Process::%s could not find watchpoint location id: %" PRId64 - "...", - __FUNCTION__, GetValue()); + LLDB_LOGF(log, + "Process::%s could not find watchpoint location id: %" PRId64 + "...", + __FUNCTION__, GetValue()); m_should_stop = true; } @@ -817,15 +813,14 @@ protected: m_should_stop = false; } else m_should_stop = true; - if (log) - log->Printf( - "Condition successfully evaluated, result is %s.\n", - m_should_stop ? "true" : "false"); + LLDB_LOGF(log, + "Condition successfully evaluated, result is %s.\n", + m_should_stop ? "true" : "false"); } else { m_should_stop = true; - if (log) - log->Printf( - "Failed to get an integer result from the expression."); + LLDB_LOGF( + log, + "Failed to get an integer result from the expression."); } } } else { @@ -836,8 +831,7 @@ protected: error_sp->Printf(": \"%s\"", wp_sp->GetConditionText()); error_sp->EOL(); const char *err_str = error.AsCString("<Unknown Error>"); - if (log) - log->Printf("Error evaluating condition: \"%s\"\n", err_str); + LLDB_LOGF(log, "Error evaluating condition: \"%s\"\n", err_str); error_sp->PutCString(err_str); error_sp->EOL(); @@ -889,14 +883,13 @@ protected: Log *log_process( lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_PROCESS)); - if (log_process) - log_process->Printf( - "Process::%s could not find watchpoint id: %" PRId64 "...", - __FUNCTION__, m_value); + LLDB_LOGF(log_process, + "Process::%s could not find watchpoint id: %" PRId64 "...", + __FUNCTION__, m_value); } - if (log) - log->Printf("Process::%s returning from action with m_should_stop: %d.", - __FUNCTION__, m_should_stop); + LLDB_LOGF(log, + "Process::%s returning from action with m_should_stop: %d.", + __FUNCTION__, m_should_stop); m_should_stop_is_valid = true; } diff --git a/source/Target/Target.cpp b/source/Target/Target.cpp index 4941cb585c55..4b9a1b77ad16 100644 --- a/source/Target/Target.cpp +++ b/source/Target/Target.cpp @@ -71,7 +71,7 @@ Target::Arch::Arch(const ArchSpec &spec) : m_spec(spec), m_plugin_up(PluginManager::CreateArchitectureInstance(spec)) {} -const Target::Arch& Target::Arch::operator=(const ArchSpec &spec) { +const Target::Arch &Target::Arch::operator=(const ArchSpec &spec) { m_spec = spec; m_plugin_up = PluginManager::CreateArchitectureInstance(spec); return *this; @@ -106,21 +106,19 @@ Target::Target(Debugger &debugger, const ArchSpec &target_arch, CheckInWithManager(); - Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_OBJECT)); - if (log) - log->Printf("%p Target::Target()", static_cast<void *>(this)); + LLDB_LOG(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_OBJECT), + "{0} Target::Target()", static_cast<void *>(this)); if (target_arch.IsValid()) { - LogIfAnyCategoriesSet(LIBLLDB_LOG_TARGET, - "Target::Target created with architecture %s (%s)", - target_arch.GetArchitectureName(), - target_arch.GetTriple().getTriple().c_str()); + LLDB_LOG(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_TARGET), + "Target::Target created with architecture {0} ({1})", + target_arch.GetArchitectureName(), + target_arch.GetTriple().getTriple().c_str()); } } Target::~Target() { Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_OBJECT)); - if (log) - log->Printf("%p Target::~Target()", static_cast<void *>(this)); + LLDB_LOG(log, "{0} Target::~Target()", static_cast<void *>(this)); DeleteCurrentProcess(); } @@ -137,10 +135,9 @@ void Target::PrimeFromDummyTarget(Target *target) { BreakpointSP new_bp(new Breakpoint(*this, *breakpoint_sp.get())); AddBreakpoint(new_bp, false); } - - for (auto bp_name_entry : target->m_breakpoint_names) - { - + + for (auto bp_name_entry : target->m_breakpoint_names) { + BreakpointName *new_bp_name = new BreakpointName(*bp_name_entry.second); AddBreakpointName(new_bp_name); } @@ -209,13 +206,11 @@ const lldb::ProcessSP &Target::GetProcessSP() const { return m_process_sp; } lldb::REPLSP Target::GetREPL(Status &err, lldb::LanguageType language, const char *repl_options, bool can_create) { if (language == eLanguageTypeUnknown) { - std::set<LanguageType> repl_languages; + LanguageSet repl_languages = Language::GetLanguagesSupportingREPLs(); - Language::GetLanguagesSupportingREPLs(repl_languages); - - if (repl_languages.size() == 1) { - language = *repl_languages.begin(); - } else if (repl_languages.size() == 0) { + if (auto single_lang = repl_languages.GetSingularLanguage()) { + language = *single_lang; + } else if (repl_languages.Empty()) { err.SetErrorStringWithFormat( "LLDB isn't configured with REPL support for any languages."); return REPLSP(); @@ -310,14 +305,14 @@ BreakpointSP Target::CreateSourceRegexBreakpoint( const FileSpecList *containingModules, const FileSpecList *source_file_spec_list, const std::unordered_set<std::string> &function_names, - RegularExpression &source_regex, bool internal, bool hardware, + RegularExpression source_regex, bool internal, bool hardware, LazyBool move_to_nearest_code) { SearchFilterSP filter_sp(GetSearchFilterForModuleAndCUList( containingModules, source_file_spec_list)); if (move_to_nearest_code == eLazyBoolCalculate) move_to_nearest_code = GetMoveToNearestCode() ? eLazyBoolYes : eLazyBoolNo; BreakpointResolverSP resolver_sp(new BreakpointResolverFileRegex( - nullptr, source_regex, function_names, + nullptr, std::move(source_regex), function_names, !static_cast<bool>(move_to_nearest_code))); return CreateBreakpoint(filter_sp, resolver_sp, internal, hardware, true); @@ -552,7 +547,7 @@ SearchFilterSP Target::GetSearchFilterForModuleAndCUList( BreakpointSP Target::CreateFuncRegexBreakpoint( const FileSpecList *containingModules, - const FileSpecList *containingSourceFiles, RegularExpression &func_regex, + const FileSpecList *containingSourceFiles, RegularExpression func_regex, lldb::LanguageType requested_language, LazyBool skip_prologue, bool internal, bool hardware) { SearchFilterSP filter_sp(GetSearchFilterForModuleAndCUList( @@ -561,7 +556,7 @@ BreakpointSP Target::CreateFuncRegexBreakpoint( ? GetSkipPrologue() : static_cast<bool>(skip_prologue); BreakpointResolverSP resolver_sp(new BreakpointResolverName( - nullptr, func_regex, requested_language, 0, skip)); + nullptr, std::move(func_regex), requested_language, 0, skip)); return CreateBreakpoint(filter_sp, resolver_sp, internal, hardware, true); } @@ -584,46 +579,40 @@ Target::CreateExceptionBreakpoint(enum lldb::LanguageType language, return exc_bkpt_sp; } -lldb::BreakpointSP -Target::CreateScriptedBreakpoint(const llvm::StringRef class_name, - const FileSpecList *containingModules, - const FileSpecList *containingSourceFiles, - bool internal, - bool request_hardware, - StructuredData::ObjectSP extra_args_sp, - Status *creation_error) -{ +lldb::BreakpointSP Target::CreateScriptedBreakpoint( + const llvm::StringRef class_name, const FileSpecList *containingModules, + const FileSpecList *containingSourceFiles, bool internal, + bool request_hardware, StructuredData::ObjectSP extra_args_sp, + Status *creation_error) { SearchFilterSP filter_sp; - + lldb::SearchDepth depth = lldb::eSearchDepthTarget; - bool has_files = containingSourceFiles && containingSourceFiles->GetSize() > 0; + bool has_files = + containingSourceFiles && containingSourceFiles->GetSize() > 0; bool has_modules = containingModules && containingModules->GetSize() > 0; - + if (has_files && has_modules) { - filter_sp = GetSearchFilterForModuleAndCUList( - containingModules, containingSourceFiles); + filter_sp = GetSearchFilterForModuleAndCUList(containingModules, + containingSourceFiles); } else if (has_files) { - filter_sp = GetSearchFilterForModuleAndCUList( - nullptr, containingSourceFiles); + filter_sp = + GetSearchFilterForModuleAndCUList(nullptr, containingSourceFiles); } else if (has_modules) { filter_sp = GetSearchFilterForModuleList(containingModules); } else { filter_sp = std::make_shared<SearchFilterForUnconstrainedSearches>( shared_from_this()); } - + StructuredDataImpl *extra_args_impl = new StructuredDataImpl(); if (extra_args_sp) extra_args_impl->SetObjectSP(extra_args_sp); BreakpointResolverSP resolver_sp(new BreakpointResolverScripted( - nullptr, class_name, depth, extra_args_impl, - *GetDebugger().GetScriptInterpreter())); + nullptr, class_name, depth, extra_args_impl)); return CreateBreakpoint(filter_sp, resolver_sp, internal, false, true); - } - BreakpointSP Target::CreateBreakpoint(SearchFilterSP &filter_sp, BreakpointResolverSP &resolver_sp, bool internal, bool request_hardware, @@ -651,8 +640,8 @@ void Target::AddBreakpoint(lldb::BreakpointSP bp_sp, bool internal) { if (log) { StreamString s; bp_sp->GetDescription(&s, lldb::eDescriptionLevelVerbose); - log->Printf("Target::%s (internal = %s) => break_id = %s\n", __FUNCTION__, - bp_sp->IsInternal() ? "yes" : "no", s.GetData()); + LLDB_LOGF(log, "Target::%s (internal = %s) => break_id = %s\n", + __FUNCTION__, bp_sp->IsInternal() ? "yes" : "no", s.GetData()); } bp_sp->ResolveBreakpoint(); @@ -662,71 +651,61 @@ void Target::AddBreakpoint(lldb::BreakpointSP bp_sp, bool internal) { } } -void Target::AddNameToBreakpoint(BreakpointID &id, - const char *name, - Status &error) - { - BreakpointSP bp_sp - = m_breakpoint_list.FindBreakpointByID(id.GetBreakpointID()); - if (!bp_sp) - { - StreamString s; - id.GetDescription(&s, eDescriptionLevelBrief); - error.SetErrorStringWithFormat("Could not find breakpoint %s", - s.GetData()); - return; - } - AddNameToBreakpoint(bp_sp, name, error); - } - -void Target::AddNameToBreakpoint(BreakpointSP &bp_sp, - const char *name, - Status &error) - { - if (!bp_sp) - return; - - BreakpointName *bp_name = FindBreakpointName(ConstString(name), true, error); - if (!bp_name) - return; - - bp_name->ConfigureBreakpoint(bp_sp); - bp_sp->AddName(name); - } +void Target::AddNameToBreakpoint(BreakpointID &id, const char *name, + Status &error) { + BreakpointSP bp_sp = + m_breakpoint_list.FindBreakpointByID(id.GetBreakpointID()); + if (!bp_sp) { + StreamString s; + id.GetDescription(&s, eDescriptionLevelBrief); + error.SetErrorStringWithFormat("Could not find breakpoint %s", s.GetData()); + return; + } + AddNameToBreakpoint(bp_sp, name, error); +} + +void Target::AddNameToBreakpoint(BreakpointSP &bp_sp, const char *name, + Status &error) { + if (!bp_sp) + return; + + BreakpointName *bp_name = FindBreakpointName(ConstString(name), true, error); + if (!bp_name) + return; + + bp_name->ConfigureBreakpoint(bp_sp); + bp_sp->AddName(name); +} void Target::AddBreakpointName(BreakpointName *bp_name) { m_breakpoint_names.insert(std::make_pair(bp_name->GetName(), bp_name)); } -BreakpointName *Target::FindBreakpointName(ConstString name, - bool can_create, - Status &error) -{ +BreakpointName *Target::FindBreakpointName(ConstString name, bool can_create, + Status &error) { BreakpointID::StringIsBreakpointName(name.GetStringRef(), error); if (!error.Success()) return nullptr; BreakpointNameList::iterator iter = m_breakpoint_names.find(name); if (iter == m_breakpoint_names.end()) { - if (!can_create) - { + if (!can_create) { error.SetErrorStringWithFormat("Breakpoint name \"%s\" doesn't exist and " - "can_create is false.", name.AsCString()); + "can_create is false.", + name.AsCString()); return nullptr; } - iter = m_breakpoint_names.insert(std::make_pair(name, - new BreakpointName(name))) - .first; + iter = m_breakpoint_names + .insert(std::make_pair(name, new BreakpointName(name))) + .first; } return (iter->second); } -void -Target::DeleteBreakpointName(ConstString name) -{ +void Target::DeleteBreakpointName(ConstString name) { BreakpointNameList::iterator iter = m_breakpoint_names.find(name); - + if (iter != m_breakpoint_names.end()) { const char *name_cstr = name.AsCString(); m_breakpoint_names.erase(iter); @@ -736,15 +715,13 @@ Target::DeleteBreakpointName(ConstString name) } void Target::RemoveNameFromBreakpoint(lldb::BreakpointSP &bp_sp, - ConstString name) -{ + ConstString name) { bp_sp->RemoveName(name.AsCString()); } -void Target::ConfigureBreakpointName(BreakpointName &bp_name, - const BreakpointOptions &new_options, - const BreakpointName::Permissions &new_permissions) -{ +void Target::ConfigureBreakpointName( + BreakpointName &bp_name, const BreakpointOptions &new_options, + const BreakpointName::Permissions &new_permissions) { bp_name.GetOptions().CopyOverSetOptions(new_options); bp_name.GetPermissions().MergeInto(new_permissions); ApplyNameToBreakpoints(bp_name); @@ -752,15 +729,14 @@ void Target::ConfigureBreakpointName(BreakpointName &bp_name, void Target::ApplyNameToBreakpoints(BreakpointName &bp_name) { BreakpointList bkpts_with_name(false); - m_breakpoint_list.FindBreakpointsByName(bp_name.GetName().AsCString(), + m_breakpoint_list.FindBreakpointsByName(bp_name.GetName().AsCString(), bkpts_with_name); for (auto bp_sp : bkpts_with_name.Breakpoints()) bp_name.ConfigureBreakpoint(bp_sp); } -void Target::GetBreakpointNames(std::vector<std::string> &names) -{ +void Target::GetBreakpointNames(std::vector<std::string> &names) { names.clear(); for (auto bp_name : m_breakpoint_names) { names.push_back(bp_name.first.AsCString()); @@ -797,10 +773,10 @@ WatchpointSP Target::CreateWatchpoint(lldb::addr_t addr, size_t size, const CompilerType *type, uint32_t kind, Status &error) { Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_WATCHPOINTS)); - if (log) - log->Printf("Target::%s (addr = 0x%8.8" PRIx64 " size = %" PRIu64 - " type = %u)\n", - __FUNCTION__, addr, (uint64_t)size, kind); + LLDB_LOGF(log, + "Target::%s (addr = 0x%8.8" PRIx64 " size = %" PRIu64 + " type = %u)\n", + __FUNCTION__, addr, (uint64_t)size, kind); WatchpointSP wp_sp; if (!ProcessIsValid()) { @@ -855,10 +831,9 @@ WatchpointSP Target::CreateWatchpoint(lldb::addr_t addr, size_t size, } error = m_process_sp->EnableWatchpoint(wp_sp.get(), notify); - if (log) - log->Printf("Target::%s (creation of watchpoint %s with id = %u)\n", - __FUNCTION__, error.Success() ? "succeeded" : "failed", - wp_sp->GetID()); + LLDB_LOGF(log, "Target::%s (creation of watchpoint %s with id = %u)\n", + __FUNCTION__, error.Success() ? "succeeded" : "failed", + wp_sp->GetID()); if (error.Fail()) { // Enabling the watchpoint on the device side failed. Remove the said @@ -875,22 +850,19 @@ WatchpointSP Target::CreateWatchpoint(lldb::addr_t addr, size_t size, return wp_sp; } -void Target::RemoveAllowedBreakpoints () -{ +void Target::RemoveAllowedBreakpoints() { Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_BREAKPOINTS)); - if (log) - log->Printf("Target::%s \n", __FUNCTION__); + LLDB_LOGF(log, "Target::%s \n", __FUNCTION__); m_breakpoint_list.RemoveAllowed(true); - + m_last_created_breakpoint.reset(); } void Target::RemoveAllBreakpoints(bool internal_also) { Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_BREAKPOINTS)); - if (log) - log->Printf("Target::%s (internal_also = %s)\n", __FUNCTION__, - internal_also ? "yes" : "no"); + LLDB_LOGF(log, "Target::%s (internal_also = %s)\n", __FUNCTION__, + internal_also ? "yes" : "no"); m_breakpoint_list.RemoveAll(true); if (internal_also) @@ -901,9 +873,8 @@ void Target::RemoveAllBreakpoints(bool internal_also) { void Target::DisableAllBreakpoints(bool internal_also) { Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_BREAKPOINTS)); - if (log) - log->Printf("Target::%s (internal_also = %s)\n", __FUNCTION__, - internal_also ? "yes" : "no"); + LLDB_LOGF(log, "Target::%s (internal_also = %s)\n", __FUNCTION__, + internal_also ? "yes" : "no"); m_breakpoint_list.SetEnabledAll(false); if (internal_also) @@ -912,17 +883,15 @@ void Target::DisableAllBreakpoints(bool internal_also) { void Target::DisableAllowedBreakpoints() { Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_BREAKPOINTS)); - if (log) - log->Printf("Target::%s", __FUNCTION__); + LLDB_LOGF(log, "Target::%s", __FUNCTION__); m_breakpoint_list.SetEnabledAllowed(false); } void Target::EnableAllBreakpoints(bool internal_also) { Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_BREAKPOINTS)); - if (log) - log->Printf("Target::%s (internal_also = %s)\n", __FUNCTION__, - internal_also ? "yes" : "no"); + LLDB_LOGF(log, "Target::%s (internal_also = %s)\n", __FUNCTION__, + internal_also ? "yes" : "no"); m_breakpoint_list.SetEnabledAll(true); if (internal_also) @@ -931,17 +900,15 @@ void Target::EnableAllBreakpoints(bool internal_also) { void Target::EnableAllowedBreakpoints() { Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_BREAKPOINTS)); - if (log) - log->Printf("Target::%s", __FUNCTION__); + LLDB_LOGF(log, "Target::%s", __FUNCTION__); m_breakpoint_list.SetEnabledAllowed(true); } bool Target::RemoveBreakpointByID(break_id_t break_id) { Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_BREAKPOINTS)); - if (log) - log->Printf("Target::%s (break_id = %i, internal = %s)\n", __FUNCTION__, - break_id, LLDB_BREAK_ID_IS_INTERNAL(break_id) ? "yes" : "no"); + LLDB_LOGF(log, "Target::%s (break_id = %i, internal = %s)\n", __FUNCTION__, + break_id, LLDB_BREAK_ID_IS_INTERNAL(break_id) ? "yes" : "no"); if (DisableBreakpointByID(break_id)) { if (LLDB_BREAK_ID_IS_INTERNAL(break_id)) @@ -960,9 +927,8 @@ bool Target::RemoveBreakpointByID(break_id_t break_id) { bool Target::DisableBreakpointByID(break_id_t break_id) { Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_BREAKPOINTS)); - if (log) - log->Printf("Target::%s (break_id = %i, internal = %s)\n", __FUNCTION__, - break_id, LLDB_BREAK_ID_IS_INTERNAL(break_id) ? "yes" : "no"); + LLDB_LOGF(log, "Target::%s (break_id = %i, internal = %s)\n", __FUNCTION__, + break_id, LLDB_BREAK_ID_IS_INTERNAL(break_id) ? "yes" : "no"); BreakpointSP bp_sp; @@ -979,9 +945,8 @@ bool Target::DisableBreakpointByID(break_id_t break_id) { bool Target::EnableBreakpointByID(break_id_t break_id) { Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_BREAKPOINTS)); - if (log) - log->Printf("Target::%s (break_id = %i, internal = %s)\n", __FUNCTION__, - break_id, LLDB_BREAK_ID_IS_INTERNAL(break_id) ? "yes" : "no"); + LLDB_LOGF(log, "Target::%s (break_id = %i, internal = %s)\n", __FUNCTION__, + break_id, LLDB_BREAK_ID_IS_INTERNAL(break_id) ? "yes" : "no"); BreakpointSP bp_sp; @@ -1031,10 +996,9 @@ Status Target::SerializeBreakpointsToFile(const FileSpec &file, } StreamFile out_file(path.c_str(), - File::OpenOptions::eOpenOptionTruncate | - File::OpenOptions::eOpenOptionWrite | - File::OpenOptions::eOpenOptionCanCreate | - File::OpenOptions::eOpenOptionCloseOnExec, + File::eOpenOptionTruncate | File::eOpenOptionWrite | + File::eOpenOptionCanCreate | + File::eOpenOptionCloseOnExec, lldb::eFilePermissionsFileDefault); if (!out_file.GetFile().IsValid()) { error.SetErrorStringWithFormat("Unable to open output file: %s.", @@ -1159,8 +1123,7 @@ Status Target::CreateBreakpointsFromFile(const FileSpec &file, // to end operations. bool Target::RemoveAllWatchpoints(bool end_to_end) { Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_WATCHPOINTS)); - if (log) - log->Printf("Target::%s\n", __FUNCTION__); + LLDB_LOGF(log, "Target::%s\n", __FUNCTION__); if (!end_to_end) { m_watchpoint_list.RemoveAll(true); @@ -1191,8 +1154,7 @@ bool Target::RemoveAllWatchpoints(bool end_to_end) { // to end operations. bool Target::DisableAllWatchpoints(bool end_to_end) { Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_WATCHPOINTS)); - if (log) - log->Printf("Target::%s\n", __FUNCTION__); + LLDB_LOGF(log, "Target::%s\n", __FUNCTION__); if (!end_to_end) { m_watchpoint_list.SetEnabledAll(false); @@ -1221,8 +1183,7 @@ bool Target::DisableAllWatchpoints(bool end_to_end) { // to end operations. bool Target::EnableAllWatchpoints(bool end_to_end) { Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_WATCHPOINTS)); - if (log) - log->Printf("Target::%s\n", __FUNCTION__); + LLDB_LOGF(log, "Target::%s\n", __FUNCTION__); if (!end_to_end) { m_watchpoint_list.SetEnabledAll(true); @@ -1250,8 +1211,7 @@ bool Target::EnableAllWatchpoints(bool end_to_end) { // Assumption: Caller holds the list mutex lock for m_watchpoint_list. bool Target::ClearAllWatchpointHitCounts() { Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_WATCHPOINTS)); - if (log) - log->Printf("Target::%s\n", __FUNCTION__); + LLDB_LOGF(log, "Target::%s\n", __FUNCTION__); size_t num_watchpoints = m_watchpoint_list.GetSize(); for (size_t i = 0; i < num_watchpoints; ++i) { @@ -1267,8 +1227,7 @@ bool Target::ClearAllWatchpointHitCounts() { // Assumption: Caller holds the list mutex lock for m_watchpoint_list. bool Target::ClearAllWatchpointHistoricValues() { Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_WATCHPOINTS)); - if (log) - log->Printf("Target::%s\n", __FUNCTION__); + LLDB_LOGF(log, "Target::%s\n", __FUNCTION__); size_t num_watchpoints = m_watchpoint_list.GetSize(); for (size_t i = 0; i < num_watchpoints; ++i) { @@ -1285,8 +1244,7 @@ bool Target::ClearAllWatchpointHistoricValues() { // these operations. bool Target::IgnoreAllWatchpoints(uint32_t ignore_count) { Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_WATCHPOINTS)); - if (log) - log->Printf("Target::%s\n", __FUNCTION__); + LLDB_LOGF(log, "Target::%s\n", __FUNCTION__); if (!ProcessIsValid()) return false; @@ -1305,8 +1263,7 @@ bool Target::IgnoreAllWatchpoints(uint32_t ignore_count) { // Assumption: Caller holds the list mutex lock for m_watchpoint_list. bool Target::DisableWatchpointByID(lldb::watch_id_t watch_id) { Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_WATCHPOINTS)); - if (log) - log->Printf("Target::%s (watch_id = %i)\n", __FUNCTION__, watch_id); + LLDB_LOGF(log, "Target::%s (watch_id = %i)\n", __FUNCTION__, watch_id); if (!ProcessIsValid()) return false; @@ -1325,8 +1282,7 @@ bool Target::DisableWatchpointByID(lldb::watch_id_t watch_id) { // Assumption: Caller holds the list mutex lock for m_watchpoint_list. bool Target::EnableWatchpointByID(lldb::watch_id_t watch_id) { Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_WATCHPOINTS)); - if (log) - log->Printf("Target::%s (watch_id = %i)\n", __FUNCTION__, watch_id); + LLDB_LOGF(log, "Target::%s (watch_id = %i)\n", __FUNCTION__, watch_id); if (!ProcessIsValid()) return false; @@ -1345,8 +1301,7 @@ bool Target::EnableWatchpointByID(lldb::watch_id_t watch_id) { // Assumption: Caller holds the list mutex lock for m_watchpoint_list. bool Target::RemoveWatchpointByID(lldb::watch_id_t watch_id) { Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_WATCHPOINTS)); - if (log) - log->Printf("Target::%s (watch_id = %i)\n", __FUNCTION__, watch_id); + LLDB_LOGF(log, "Target::%s (watch_id = %i)\n", __FUNCTION__, watch_id); WatchpointSP watch_to_remove_sp = m_watchpoint_list.FindByID(watch_id); if (watch_to_remove_sp == m_last_created_watchpoint) @@ -1363,8 +1318,7 @@ bool Target::RemoveWatchpointByID(lldb::watch_id_t watch_id) { bool Target::IgnoreWatchpointByID(lldb::watch_id_t watch_id, uint32_t ignore_count) { Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_WATCHPOINTS)); - if (log) - log->Printf("Target::%s (watch_id = %i)\n", __FUNCTION__, watch_id); + LLDB_LOGF(log, "Target::%s (watch_id = %i)\n", __FUNCTION__, watch_id); if (!ProcessIsValid()) return false; @@ -1399,19 +1353,18 @@ static void LoadScriptingResourceForModule(const ModuleSP &module_sp, Target *target) { Status error; StreamString feedback_stream; - if (module_sp && - !module_sp->LoadScriptingResourceInTarget(target, error, - &feedback_stream)) { + if (module_sp && !module_sp->LoadScriptingResourceInTarget( + target, error, &feedback_stream)) { if (error.AsCString()) - target->GetDebugger().GetErrorFile()->Printf( + target->GetDebugger().GetErrorStream().Printf( "unable to load scripting data for module %s - error reported was " "%s\n", module_sp->GetFileSpec().GetFileNameStrippingExtension().GetCString(), error.AsCString()); } if (feedback_stream.GetSize()) - target->GetDebugger().GetErrorFile()->Printf("%s\n", - feedback_stream.GetData()); + target->GetDebugger().GetErrorStream().Printf("%s\n", + feedback_stream.GetData()); } void Target::ClearModules(bool delete_locations) { @@ -1440,7 +1393,8 @@ void Target::SetExecutableModule(ModuleSP &executable_sp, executable_sp->GetFileSpec().GetPath().c_str()); const bool notify = true; - m_images.Append(executable_sp, notify); // The first image is our executable file + m_images.Append(executable_sp, + notify); // The first image is our executable file // If we haven't set an architecture yet, reset our architecture based on // what we found in the executable module. @@ -1481,10 +1435,10 @@ void Target::SetExecutableModule(ModuleSP &executable_sp, platform_dependent_file_spec = dependent_file_spec; ModuleSpec module_spec(platform_dependent_file_spec, m_arch.GetSpec()); - ModuleSP image_module_sp(GetOrCreateModule(module_spec, - false /* notify */)); + ModuleSP image_module_sp( + GetOrCreateModule(module_spec, false /* notify */)); if (image_module_sp) { - added_modules.AppendIfNeeded (image_module_sp, false); + added_modules.AppendIfNeeded(image_module_sp, false); ObjectFile *objfile = image_module_sp->GetObjectFile(); if (objfile) objfile->GetDependentModules(dependent_files); @@ -1531,8 +1485,9 @@ bool Target::SetArchitecture(const ArchSpec &arch_spec, bool set_platform) { bool arch_changed, vendor_changed, os_changed, os_ver_changed, env_changed; - m_arch.GetSpec().PiecewiseTripleCompare(other, arch_changed, vendor_changed, - os_changed, os_ver_changed, env_changed); + m_arch.GetSpec().PiecewiseTripleCompare(other, arch_changed, + vendor_changed, os_changed, + os_ver_changed, env_changed); if (!arch_changed && !vendor_changed && !os_changed && !env_changed) replace_local_arch = false; @@ -1554,10 +1509,9 @@ bool Target::SetArchitecture(const ArchSpec &arch_spec, bool set_platform) { // If we have an executable file, try to reset the executable to the desired // architecture - if (log) - log->Printf("Target::SetArchitecture changing architecture to %s (%s)", - arch_spec.GetArchitectureName(), - arch_spec.GetTriple().getTriple().c_str()); + LLDB_LOGF(log, "Target::SetArchitecture changing architecture to %s (%s)", + arch_spec.GetArchitectureName(), + arch_spec.GetTriple().getTriple().c_str()); m_arch = other; ModuleSP executable_sp = GetExecutableModule(); @@ -1565,16 +1519,15 @@ bool Target::SetArchitecture(const ArchSpec &arch_spec, bool set_platform) { // Need to do something about unsetting breakpoints. if (executable_sp) { - if (log) - log->Printf("Target::SetArchitecture Trying to select executable file " - "architecture %s (%s)", - arch_spec.GetArchitectureName(), - arch_spec.GetTriple().getTriple().c_str()); + LLDB_LOGF(log, + "Target::SetArchitecture Trying to select executable file " + "architecture %s (%s)", + arch_spec.GetArchitectureName(), + arch_spec.GetTriple().getTriple().c_str()); ModuleSpec module_spec(executable_sp->GetFileSpec(), other); FileSpecList search_paths = GetExecutableSearchPaths(); Status error = ModuleList::GetSharedModule(module_spec, executable_sp, - &search_paths, - nullptr, nullptr); + &search_paths, nullptr, nullptr); if (!error.Fail() && executable_sp) { SetExecutableModule(executable_sp, eLoadDependentsYes); @@ -1591,11 +1544,11 @@ bool Target::MergeArchitecture(const ArchSpec &arch_spec) { // The current target arch is compatible with "arch_spec", see if we can // improve our current architecture using bits from "arch_spec" - if (log) - log->Printf("Target::MergeArchitecture target has arch %s, merging with " - "arch %s", - m_arch.GetSpec().GetTriple().getTriple().c_str(), - arch_spec.GetTriple().getTriple().c_str()); + LLDB_LOGF(log, + "Target::MergeArchitecture target has arch %s, merging with " + "arch %s", + m_arch.GetSpec().GetTriple().getTriple().c_str(), + arch_spec.GetTriple().getTriple().c_str()); // Merge bits from arch_spec into "merged_arch" and set our architecture ArchSpec merged_arch(m_arch.GetSpec()); @@ -1612,7 +1565,7 @@ bool Target::MergeArchitecture(const ArchSpec &arch_spec) { void Target::NotifyWillClearList(const ModuleList &module_list) {} void Target::NotifyModuleAdded(const ModuleList &module_list, - const ModuleSP &module_sp) { + const ModuleSP &module_sp) { // A module is being added to this target for the first time if (m_valid) { ModuleList my_module_list; @@ -1622,7 +1575,7 @@ void Target::NotifyModuleAdded(const ModuleList &module_list, } void Target::NotifyModuleRemoved(const ModuleList &module_list, - const ModuleSP &module_sp) { + const ModuleSP &module_sp) { // A module is being removed from this target. if (m_valid) { ModuleList my_module_list; @@ -1632,8 +1585,8 @@ void Target::NotifyModuleRemoved(const ModuleList &module_list, } void Target::NotifyModuleUpdated(const ModuleList &module_list, - const ModuleSP &old_module_sp, - const ModuleSP &new_module_sp) { + const ModuleSP &old_module_sp, + const ModuleSP &new_module_sp) { // A module is replacing an already added module if (m_valid) { m_breakpoint_list.UpdateBreakpointsWhenModuleIsReplaced(old_module_sp, @@ -1644,10 +1597,9 @@ void Target::NotifyModuleUpdated(const ModuleList &module_list, } void Target::NotifyModulesRemoved(lldb_private::ModuleList &module_list) { - ModulesDidUnload (module_list, false); + ModulesDidUnload(module_list, false); } - void Target::ModulesDidLoad(ModuleList &module_list) { const size_t num_images = module_list.GetSize(); if (m_valid && num_images) { @@ -1696,11 +1648,11 @@ bool Target::ModuleIsExcludedForUnconstrainedSearches( if (GetBreakpointsConsultPlatformAvoidList()) { ModuleList matchingModules; ModuleSpec module_spec(module_file_spec); - size_t num_modules = GetImages().FindModules(module_spec, matchingModules); + GetImages().FindModules(module_spec, matchingModules); + size_t num_modules = matchingModules.GetSize(); - // If there is more than one module for this file spec, only return true if - // ALL the modules are on the - // black list. + // If there is more than one module for this file spec, only + // return true if ALL the modules are on the black list. if (num_modules > 0) { for (size_t i = 0; i < num_modules; i++) { if (!ModuleIsExcludedForUnconstrainedSearches( @@ -1967,8 +1919,8 @@ bool Target::ReadPointerFromMemory(const Address &addr, bool prefer_file_cache, Status &error, Address &pointer_addr) { Scalar scalar; if (ReadScalarIntegerFromMemory(addr, prefer_file_cache, - m_arch.GetSpec().GetAddressByteSize(), false, scalar, - error)) { + m_arch.GetSpec().GetAddressByteSize(), false, + scalar, error)) { addr_t pointer_vm_addr = scalar.ULongLong(LLDB_INVALID_ADDRESS); if (pointer_vm_addr != LLDB_INVALID_ADDRESS) { SectionLoadList §ion_load_list = GetSectionLoadList(); @@ -2021,8 +1973,8 @@ ModuleSP Target::GetOrCreateModule(const ModuleSpec &module_spec, bool notify, transformed_spec.GetFileSpec().GetFilename() = module_spec.GetFileSpec().GetFilename(); error = ModuleList::GetSharedModule(transformed_spec, module_sp, - &search_paths, - &old_module_sp, &did_create_module); + &search_paths, &old_module_sp, + &did_create_module); } } @@ -2037,9 +1989,9 @@ ModuleSP Target::GetOrCreateModule(const ModuleSpec &module_spec, bool notify, // cache. if (module_spec.GetUUID().IsValid()) { // We have a UUID, it is OK to check the global module list... - error = ModuleList::GetSharedModule(module_spec, module_sp, - &search_paths, - &old_module_sp, &did_create_module); + error = + ModuleList::GetSharedModule(module_spec, module_sp, &search_paths, + &old_module_sp, &did_create_module); } if (!module_sp) { @@ -2047,8 +1999,8 @@ ModuleSP Target::GetOrCreateModule(const ModuleSpec &module_spec, bool notify, // module in the shared module cache. if (m_platform_sp) { error = m_platform_sp->GetSharedModule( - module_spec, m_process_sp.get(), module_sp, - &search_paths, &old_module_sp, &did_create_module); + module_spec, m_process_sp.get(), module_sp, &search_paths, + &old_module_sp, &did_create_module); } else { error.SetErrorString("no platform is currently set"); } @@ -2107,11 +2059,9 @@ ModuleSP Target::GetOrCreateModule(const ModuleSpec &module_spec, bool notify, module_spec_copy.GetUUID().Clear(); ModuleList found_modules; - size_t num_found = - m_images.FindModules(module_spec_copy, found_modules); - if (num_found == 1) { + m_images.FindModules(module_spec_copy, found_modules); + if (found_modules.GetSize() == 1) old_module_sp = found_modules.GetModuleAtIndex(0); - } } } @@ -2120,9 +2070,8 @@ ModuleSP Target::GetOrCreateModule(const ModuleSpec &module_spec, bool notify, if (GetPreloadSymbols()) module_sp->PreloadSymbols(); - if (old_module_sp && - m_images.GetIndexForModule(old_module_sp.get()) != - LLDB_INVALID_INDEX32) { + if (old_module_sp && m_images.GetIndexForModule(old_module_sp.get()) != + LLDB_INVALID_INDEX32) { m_images.ReplaceModule(old_module_sp, module_sp); Module *old_module_ptr = old_module_sp.get(); old_module_sp.reset(); @@ -2164,34 +2113,28 @@ void Target::ImageSearchPathsChanged(const PathMappingList &path_list, target->SetExecutableModule(exe_module_sp, eLoadDependentsYes); } -TypeSystem *Target::GetScratchTypeSystemForLanguage(Status *error, - lldb::LanguageType language, - bool create_on_demand) { +llvm::Expected<TypeSystem &> +Target::GetScratchTypeSystemForLanguage(lldb::LanguageType language, + bool create_on_demand) { if (!m_valid) - return nullptr; - - if (error) { - error->Clear(); - } + return llvm::make_error<llvm::StringError>("Invalid Target", + llvm::inconvertibleErrorCode()); if (language == eLanguageTypeMipsAssembler // GNU AS and LLVM use it for all // assembly code || language == eLanguageTypeUnknown) { - std::set<lldb::LanguageType> languages_for_types; - std::set<lldb::LanguageType> languages_for_expressions; + LanguageSet languages_for_expressions = + Language::GetLanguagesSupportingTypeSystemsForExpressions(); - Language::GetLanguagesSupportingTypeSystems(languages_for_types, - languages_for_expressions); - - if (languages_for_expressions.count(eLanguageTypeC)) { + if (languages_for_expressions[eLanguageTypeC]) { language = eLanguageTypeC; // LLDB's default. Override by setting the // target language. } else { - if (languages_for_expressions.empty()) { - return nullptr; - } else { - language = *languages_for_expressions.begin(); - } + if (languages_for_expressions.Empty()) + return llvm::make_error<llvm::StringError>( + "No expression support for any languages", + llvm::inconvertibleErrorCode()); + language = (LanguageType)languages_for_expressions.bitvector.find_first(); } } @@ -2199,39 +2142,63 @@ TypeSystem *Target::GetScratchTypeSystemForLanguage(Status *error, create_on_demand); } +std::vector<TypeSystem *> Target::GetScratchTypeSystems(bool create_on_demand) { + if (!m_valid) + return {}; + + std::vector<TypeSystem *> scratch_type_systems; + + LanguageSet languages_for_expressions = + Language::GetLanguagesSupportingTypeSystemsForExpressions(); + + for (auto bit : languages_for_expressions.bitvector.set_bits()) { + auto language = (LanguageType)bit; + auto type_system_or_err = + GetScratchTypeSystemForLanguage(language, create_on_demand); + if (!type_system_or_err) + LLDB_LOG_ERROR(lldb_private::GetLogIfAnyCategoriesSet(LIBLLDB_LOG_TARGET), + type_system_or_err.takeError(), + "Language '{}' has expression support but no scratch type " + "system available", + Language::GetNameForLanguageType(language)); + else + scratch_type_systems.emplace_back(&type_system_or_err.get()); + } + + return scratch_type_systems; +} + PersistentExpressionState * Target::GetPersistentExpressionStateForLanguage(lldb::LanguageType language) { - TypeSystem *type_system = - GetScratchTypeSystemForLanguage(nullptr, language, true); + auto type_system_or_err = GetScratchTypeSystemForLanguage(language, true); - if (type_system) { - return type_system->GetPersistentExpressionState(); - } else { + if (auto err = type_system_or_err.takeError()) { + LLDB_LOG_ERROR(lldb_private::GetLogIfAnyCategoriesSet(LIBLLDB_LOG_TARGET), + std::move(err), + "Unable to get persistent expression state for language {}", + Language::GetNameForLanguageType(language)); return nullptr; } + + return type_system_or_err->GetPersistentExpressionState(); } UserExpression *Target::GetUserExpressionForLanguage( llvm::StringRef expr, llvm::StringRef prefix, lldb::LanguageType language, Expression::ResultType desired_type, - const EvaluateExpressionOptions &options, - ValueObject *ctx_obj, Status &error) { - Status type_system_error; - - TypeSystem *type_system = - GetScratchTypeSystemForLanguage(&type_system_error, language); - UserExpression *user_expr = nullptr; - - if (!type_system) { + const EvaluateExpressionOptions &options, ValueObject *ctx_obj, + Status &error) { + auto type_system_or_err = GetScratchTypeSystemForLanguage(language); + if (auto err = type_system_or_err.takeError()) { error.SetErrorStringWithFormat( "Could not find type system for language %s: %s", Language::GetNameForLanguageType(language), - type_system_error.AsCString()); + llvm::toString(std::move(err)).c_str()); return nullptr; } - user_expr = type_system->GetUserExpression(expr, prefix, language, - desired_type, options, ctx_obj); + auto *user_expr = type_system_or_err->GetUserExpression( + expr, prefix, language, desired_type, options, ctx_obj); if (!user_expr) error.SetErrorStringWithFormat( "Could not create an expression for language %s", @@ -2244,21 +2211,17 @@ FunctionCaller *Target::GetFunctionCallerForLanguage( lldb::LanguageType language, const CompilerType &return_type, const Address &function_address, const ValueList &arg_value_list, const char *name, Status &error) { - Status type_system_error; - TypeSystem *type_system = - GetScratchTypeSystemForLanguage(&type_system_error, language); - FunctionCaller *persistent_fn = nullptr; - - if (!type_system) { + auto type_system_or_err = GetScratchTypeSystemForLanguage(language); + if (auto err = type_system_or_err.takeError()) { error.SetErrorStringWithFormat( "Could not find type system for language %s: %s", Language::GetNameForLanguageType(language), - type_system_error.AsCString()); - return persistent_fn; + llvm::toString(std::move(err)).c_str()); + return nullptr; } - persistent_fn = type_system->GetFunctionCaller(return_type, function_address, - arg_value_list, name); + auto *persistent_fn = type_system_or_err->GetFunctionCaller( + return_type, function_address, arg_value_list, name); if (!persistent_fn) error.SetErrorStringWithFormat( "Could not create an expression for language %s", @@ -2271,20 +2234,17 @@ UtilityFunction * Target::GetUtilityFunctionForLanguage(const char *text, lldb::LanguageType language, const char *name, Status &error) { - Status type_system_error; - TypeSystem *type_system = - GetScratchTypeSystemForLanguage(&type_system_error, language); - UtilityFunction *utility_fn = nullptr; + auto type_system_or_err = GetScratchTypeSystemForLanguage(language); - if (!type_system) { + if (auto err = type_system_or_err.takeError()) { error.SetErrorStringWithFormat( "Could not find type system for language %s: %s", Language::GetNameForLanguageType(language), - type_system_error.AsCString()); - return utility_fn; + llvm::toString(std::move(err)).c_str()); + return nullptr; } - utility_fn = type_system->GetUtilityFunction(text, name); + auto *utility_fn = type_system_or_err->GetUtilityFunction(text, name); if (!utility_fn) error.SetErrorStringWithFormat( "Could not create an expression for language %s", @@ -2294,12 +2254,17 @@ Target::GetUtilityFunctionForLanguage(const char *text, } ClangASTContext *Target::GetScratchClangASTContext(bool create_on_demand) { - if (m_valid) { - if (TypeSystem *type_system = GetScratchTypeSystemForLanguage( - nullptr, eLanguageTypeC, create_on_demand)) - return llvm::dyn_cast<ClangASTContext>(type_system); + if (!m_valid) + return nullptr; + + auto type_system_or_err = + GetScratchTypeSystemForLanguage(eLanguageTypeC, create_on_demand); + if (auto err = type_system_or_err.takeError()) { + LLDB_LOG_ERROR(lldb_private::GetLogIfAnyCategoriesSet(LIBLLDB_LOG_TARGET), + std::move(err), "Couldn't get scratch ClangASTContext"); + return nullptr; } - return nullptr; + return llvm::dyn_cast<ClangASTContext>(&type_system_or_err.get()); } ClangASTImporterSP Target::GetClangASTImporter() { @@ -2340,10 +2305,10 @@ ArchSpec Target::GetDefaultArchitecture() { void Target::SetDefaultArchitecture(const ArchSpec &arch) { TargetPropertiesSP properties_sp(Target::GetGlobalProperties()); if (properties_sp) { - LogIfAnyCategoriesSet( - LIBLLDB_LOG_TARGET, "Target::SetDefaultArchitecture setting target's " - "default architecture to %s (%s)", - arch.GetArchitectureName(), arch.GetTriple().getTriple().c_str()); + LLDB_LOG(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_TARGET), + "Target::SetDefaultArchitecture setting target's " + "default architecture to {0} ({1})", + arch.GetArchitectureName(), arch.GetTriple().getTriple()); return properties_sp->SetDefaultArchitecture(arch); } } @@ -2378,7 +2343,8 @@ ExpressionResults Target::EvaluateExpression( bool old_suppress_value = m_suppress_stop_hooks; m_suppress_stop_hooks = true; auto on_exit = llvm::make_scope_exit([this, old_suppress_value]() { - m_suppress_stop_hooks = old_suppress_value; }); + m_suppress_stop_hooks = old_suppress_value; + }); ExecutionContext exe_ctx; @@ -2392,13 +2358,19 @@ ExpressionResults Target::EvaluateExpression( // Make sure we aren't just trying to see the value of a persistent variable // (something like "$0") - lldb::ExpressionVariableSP persistent_var_sp; // Only check for persistent variables the expression starts with a '$' - if (expr[0] == '$') - persistent_var_sp = GetScratchTypeSystemForLanguage(nullptr, eLanguageTypeC) - ->GetPersistentExpressionState() - ->GetVariable(expr); - + lldb::ExpressionVariableSP persistent_var_sp; + if (expr[0] == '$') { + auto type_system_or_err = + GetScratchTypeSystemForLanguage(eLanguageTypeC); + if (auto err = type_system_or_err.takeError()) { + LLDB_LOG_ERROR(lldb_private::GetLogIfAnyCategoriesSet(LIBLLDB_LOG_TARGET), + std::move(err), "Unable to get scratch type system"); + } else { + persistent_var_sp = + type_system_or_err->GetPersistentExpressionState()->GetVariable(expr); + } + } if (persistent_var_sp) { result_valobj_sp = persistent_var_sp->GetValueObject(); execution_results = eExpressionCompleted; @@ -2415,8 +2387,7 @@ ExpressionResults Target::EvaluateExpression( return execution_results; } -lldb::ExpressionVariableSP -Target::GetPersistentVariable(ConstString name) { +lldb::ExpressionVariableSP Target::GetPersistentVariable(ConstString name) { lldb::ExpressionVariableSP variable_sp; m_scratch_type_system_map.ForEach( [name, &variable_sp](TypeSystem *type_system) -> bool { @@ -2448,24 +2419,61 @@ lldb::addr_t Target::GetPersistentSymbol(ConstString name) { return address; } +llvm::Expected<lldb_private::Address> Target::GetEntryPointAddress() { + Module *exe_module = GetExecutableModulePointer(); + llvm::Error error = llvm::Error::success(); + assert(!error); // Check the success value when assertions are enabled. + + if (!exe_module || !exe_module->GetObjectFile()) { + error = llvm::make_error<llvm::StringError>("No primary executable found", + llvm::inconvertibleErrorCode()); + } else { + Address entry_addr = exe_module->GetObjectFile()->GetEntryPointAddress(); + if (entry_addr.IsValid()) + return entry_addr; + + error = llvm::make_error<llvm::StringError>( + "Could not find entry point address for executable module \"" + + exe_module->GetFileSpec().GetFilename().GetStringRef() + "\"", + llvm::inconvertibleErrorCode()); + } + + const ModuleList &modules = GetImages(); + const size_t num_images = modules.GetSize(); + for (size_t idx = 0; idx < num_images; ++idx) { + ModuleSP module_sp(modules.GetModuleAtIndex(idx)); + if (!module_sp || !module_sp->GetObjectFile()) + continue; + + Address entry_addr = module_sp->GetObjectFile()->GetEntryPointAddress(); + if (entry_addr.IsValid()) { + // Discard the error. + llvm::consumeError(std::move(error)); + return entry_addr; + } + } + + return std::move(error); +} + lldb::addr_t Target::GetCallableLoadAddress(lldb::addr_t load_addr, AddressClass addr_class) const { auto arch_plugin = GetArchitecturePlugin(); - return arch_plugin ? - arch_plugin->GetCallableLoadAddress(load_addr, addr_class) : load_addr; + return arch_plugin + ? arch_plugin->GetCallableLoadAddress(load_addr, addr_class) + : load_addr; } lldb::addr_t Target::GetOpcodeLoadAddress(lldb::addr_t load_addr, AddressClass addr_class) const { auto arch_plugin = GetArchitecturePlugin(); - return arch_plugin ? - arch_plugin->GetOpcodeLoadAddress(load_addr, addr_class) : load_addr; + return arch_plugin ? arch_plugin->GetOpcodeLoadAddress(load_addr, addr_class) + : load_addr; } lldb::addr_t Target::GetBreakableLoadAddress(lldb::addr_t addr) { auto arch_plugin = GetArchitecturePlugin(); - return arch_plugin ? - arch_plugin->GetBreakableLoadAddress(addr, *this) : addr; + return arch_plugin ? arch_plugin->GetBreakableLoadAddress(addr, *this) : addr; } SourceManager &Target::GetSourceManager() { @@ -2539,7 +2547,7 @@ void Target::RunStopHooks() { if (!m_process_sp) return; - + // Somebody might have restarted the process: if (m_process_sp->GetState() != eStateStopped) return; @@ -2658,11 +2666,12 @@ void Target::RunStopHooks() { // But only complain if there were more stop hooks to do: StopHookCollection::iterator tmp = pos; if (++tmp != end) - result.AppendMessageWithFormat("\nAborting stop hooks, hook %" PRIu64 - " set the program running.\n" - " Consider using '-G true' to make " - "stop hooks auto-continue.\n", - cur_hook_sp->GetID()); + result.AppendMessageWithFormat( + "\nAborting stop hooks, hook %" PRIu64 + " set the program running.\n" + " Consider using '-G true' to make " + "stop hooks auto-continue.\n", + cur_hook_sp->GetID()); keep_going = false; did_restart = true; } @@ -2820,9 +2829,8 @@ Status Target::Launch(ProcessLaunchInfo &launch_info, Stream *stream) { Status error; Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_TARGET)); - if (log) - log->Printf("Target::%s() called for %s", __FUNCTION__, - launch_info.GetExecutableFile().GetPath().c_str()); + LLDB_LOGF(log, "Target::%s() called for %s", __FUNCTION__, + launch_info.GetExecutableFile().GetPath().c_str()); StateType state = eStateInvalid; @@ -2834,14 +2842,12 @@ Status Target::Launch(ProcessLaunchInfo &launch_info, Stream *stream) { if (process_sp) { state = process_sp->GetState(); - if (log) - log->Printf( - "Target::%s the process exists, and its current state is %s", - __FUNCTION__, StateAsCString(state)); + LLDB_LOGF(log, + "Target::%s the process exists, and its current state is %s", + __FUNCTION__, StateAsCString(state)); } else { - if (log) - log->Printf("Target::%s the process instance doesn't currently exist.", - __FUNCTION__); + LLDB_LOGF(log, "Target::%s the process instance doesn't currently exist.", + __FUNCTION__); } } @@ -2873,24 +2879,23 @@ Status Target::Launch(ProcessLaunchInfo &launch_info, Stream *stream) { // that can launch a process for debugging, go ahead and do that here. if (state != eStateConnected && platform_sp && platform_sp->CanDebugProcess()) { - if (log) - log->Printf("Target::%s asking the platform to debug the process", - __FUNCTION__); + LLDB_LOGF(log, "Target::%s asking the platform to debug the process", + __FUNCTION__); // If there was a previous process, delete it before we make the new one. // One subtle point, we delete the process before we release the reference // to m_process_sp. That way even if we are the last owner, the process // will get Finalized before it gets destroyed. DeleteCurrentProcess(); - + m_process_sp = GetPlatform()->DebugProcess(launch_info, debugger, this, error); } else { - if (log) - log->Printf("Target::%s the platform doesn't know how to debug a " - "process, getting a process plugin to do this for us.", - __FUNCTION__); + LLDB_LOGF(log, + "Target::%s the platform doesn't know how to debug a " + "process, getting a process plugin to do this for us.", + __FUNCTION__); if (state == eStateConnected) { assert(m_process_sp); @@ -2928,9 +2933,9 @@ Status Target::Launch(ProcessLaunchInfo &launch_info, Stream *stream) { if (state == eStateStopped) { if (!launch_info.GetFlags().Test(eLaunchFlagStopAtEntry)) { if (synchronous_execution) { - // Now we have handled the stop-from-attach, and we are just switching - // to a synchronous resume. So we should switch to the SyncResume - // hijacker. + // Now we have handled the stop-from-attach, and we are just + // switching to a synchronous resume. So we should switch to the + // SyncResume hijacker. m_process_sp->RestoreProcessEvents(); m_process_sp->ResumeSynchronous(stream); } else { @@ -3213,33 +3218,51 @@ void Target::StopHook::GetDescription(Stream *s, s->SetIndentLevel(indent_level); } -// class TargetProperties - -// clang-format off static constexpr OptionEnumValueElement g_dynamic_value_types[] = { - {eNoDynamicValues, "no-dynamic-values", - "Don't calculate the dynamic type of values"}, - {eDynamicCanRunTarget, "run-target", "Calculate the dynamic type of values " - "even if you have to run the target."}, - {eDynamicDontRunTarget, "no-run-target", - "Calculate the dynamic type of values, but don't run the target."} }; + { + eNoDynamicValues, + "no-dynamic-values", + "Don't calculate the dynamic type of values", + }, + { + eDynamicCanRunTarget, + "run-target", + "Calculate the dynamic type of values " + "even if you have to run the target.", + }, + { + eDynamicDontRunTarget, + "no-run-target", + "Calculate the dynamic type of values, but don't run the target.", + }, +}; OptionEnumValues lldb_private::GetDynamicValueTypes() { return OptionEnumValues(g_dynamic_value_types); } static constexpr OptionEnumValueElement g_inline_breakpoint_enums[] = { - {eInlineBreakpointsNever, "never", "Never look for inline breakpoint " - "locations (fastest). This setting " - "should only be used if you know that " - "no inlining occurs in your programs."}, - {eInlineBreakpointsHeaders, "headers", - "Only check for inline breakpoint locations when setting breakpoints in " - "header files, but not when setting breakpoint in implementation source " - "files (default)."}, - {eInlineBreakpointsAlways, "always", - "Always look for inline breakpoint locations when setting file and line " - "breakpoints (slower but most accurate)."} }; + { + eInlineBreakpointsNever, + "never", + "Never look for inline breakpoint locations (fastest). This setting " + "should only be used if you know that no inlining occurs in your" + "programs.", + }, + { + eInlineBreakpointsHeaders, + "headers", + "Only check for inline breakpoint locations when setting breakpoints " + "in header files, but not when setting breakpoint in implementation " + "source files (default).", + }, + { + eInlineBreakpointsAlways, + "always", + "Always look for inline breakpoint locations when setting file and " + "line breakpoints (slower but most accurate).", + }, +}; enum x86DisassemblyFlavor { eX86DisFlavorDefault, @@ -3248,258 +3271,99 @@ enum x86DisassemblyFlavor { }; static constexpr OptionEnumValueElement g_x86_dis_flavor_value_types[] = { - {eX86DisFlavorDefault, "default", "Disassembler default (currently att)."}, - {eX86DisFlavorIntel, "intel", "Intel disassembler flavor."}, - {eX86DisFlavorATT, "att", "AT&T disassembler flavor."} }; + { + eX86DisFlavorDefault, + "default", + "Disassembler default (currently att).", + }, + { + eX86DisFlavorIntel, + "intel", + "Intel disassembler flavor.", + }, + { + eX86DisFlavorATT, + "att", + "AT&T disassembler flavor.", + }, +}; static constexpr OptionEnumValueElement g_hex_immediate_style_values[] = { - {Disassembler::eHexStyleC, "c", "C-style (0xffff)."}, - {Disassembler::eHexStyleAsm, "asm", "Asm-style (0ffffh)."} }; + { + Disassembler::eHexStyleC, + "c", + "C-style (0xffff).", + }, + { + Disassembler::eHexStyleAsm, + "asm", + "Asm-style (0ffffh).", + }, +}; static constexpr OptionEnumValueElement g_load_script_from_sym_file_values[] = { - {eLoadScriptFromSymFileTrue, "true", - "Load debug scripts inside symbol files"}, - {eLoadScriptFromSymFileFalse, "false", - "Do not load debug scripts inside symbol files."}, - {eLoadScriptFromSymFileWarn, "warn", - "Warn about debug scripts inside symbol files but do not load them."} }; - -static constexpr -OptionEnumValueElement g_load_current_working_dir_lldbinit_values[] = { - {eLoadCWDlldbinitTrue, "true", - "Load .lldbinit files from current directory"}, - {eLoadCWDlldbinitFalse, "false", - "Do not load .lldbinit files from current directory"}, - {eLoadCWDlldbinitWarn, "warn", - "Warn about loading .lldbinit files from current directory"} }; + { + eLoadScriptFromSymFileTrue, + "true", + "Load debug scripts inside symbol files", + }, + { + eLoadScriptFromSymFileFalse, + "false", + "Do not load debug scripts inside symbol files.", + }, + { + eLoadScriptFromSymFileWarn, + "warn", + "Warn about debug scripts inside symbol files but do not load them.", + }, +}; + +static constexpr OptionEnumValueElement g_load_cwd_lldbinit_values[] = { + { + eLoadCWDlldbinitTrue, + "true", + "Load .lldbinit files from current directory", + }, + { + eLoadCWDlldbinitFalse, + "false", + "Do not load .lldbinit files from current directory", + }, + { + eLoadCWDlldbinitWarn, + "warn", + "Warn about loading .lldbinit files from current directory", + }, +}; static constexpr OptionEnumValueElement g_memory_module_load_level_values[] = { - {eMemoryModuleLoadLevelMinimal, "minimal", - "Load minimal information when loading modules from memory. Currently " - "this setting loads sections only."}, - {eMemoryModuleLoadLevelPartial, "partial", - "Load partial information when loading modules from memory. Currently " - "this setting loads sections and function bounds."}, - {eMemoryModuleLoadLevelComplete, "complete", - "Load complete information when loading modules from memory. Currently " - "this setting loads sections and all symbols."} }; - -static constexpr PropertyDefinition g_properties[] = { - {"default-arch", OptionValue::eTypeArch, true, 0, nullptr, {}, - "Default architecture to choose, when there's a choice."}, - {"move-to-nearest-code", OptionValue::eTypeBoolean, false, true, nullptr, - {}, "Move breakpoints to nearest code."}, - {"language", OptionValue::eTypeLanguage, false, eLanguageTypeUnknown, - nullptr, {}, - "The language to use when interpreting expressions entered in commands."}, - {"expr-prefix", OptionValue::eTypeFileSpec, false, 0, nullptr, {}, - "Path to a file containing expressions to be prepended to all " - "expressions."}, - {"prefer-dynamic-value", OptionValue::eTypeEnum, false, - eDynamicDontRunTarget, nullptr, OptionEnumValues(g_dynamic_value_types), - "Should printed values be shown as their dynamic value."}, - {"enable-synthetic-value", OptionValue::eTypeBoolean, false, true, nullptr, - {}, "Should synthetic values be used by default whenever available."}, - {"skip-prologue", OptionValue::eTypeBoolean, false, true, nullptr, {}, - "Skip function prologues when setting breakpoints by name."}, - {"source-map", OptionValue::eTypePathMap, false, 0, nullptr, {}, - "Source path remappings are used to track the change of location between " - "a source file when built, and " - "where it exists on the current system. It consists of an array of " - "duples, the first element of each duple is " - "some part (starting at the root) of the path to the file when it was " - "built, " - "and the second is where the remainder of the original build hierarchy is " - "rooted on the local system. " - "Each element of the array is checked in order and the first one that " - "results in a match wins."}, - {"exec-search-paths", OptionValue::eTypeFileSpecList, false, 0, nullptr, - {}, "Executable search paths to use when locating executable files " - "whose paths don't match the local file system."}, - {"debug-file-search-paths", OptionValue::eTypeFileSpecList, false, 0, - nullptr, {}, - "List of directories to be searched when locating debug symbol files. " - "See also symbols.enable-external-lookup."}, - {"clang-module-search-paths", OptionValue::eTypeFileSpecList, false, 0, - nullptr, {}, - "List of directories to be searched when locating modules for Clang."}, - {"auto-import-clang-modules", OptionValue::eTypeBoolean, false, true, - nullptr, {}, - "Automatically load Clang modules referred to by the program."}, - {"import-std-module", OptionValue::eTypeBoolean, false, false, - nullptr, {}, - "Import the C++ std module to improve debugging STL containers."}, - {"auto-apply-fixits", OptionValue::eTypeBoolean, false, true, nullptr, - {}, "Automatically apply fix-it hints to expressions."}, - {"notify-about-fixits", OptionValue::eTypeBoolean, false, true, nullptr, - {}, "Print the fixed expression text."}, - {"save-jit-objects", OptionValue::eTypeBoolean, false, false, nullptr, - {}, "Save intermediate object files generated by the LLVM JIT"}, - {"max-children-count", OptionValue::eTypeSInt64, false, 256, nullptr, - {}, "Maximum number of children to expand in any level of depth."}, - {"max-string-summary-length", OptionValue::eTypeSInt64, false, 1024, - nullptr, {}, - "Maximum number of characters to show when using %s in summary strings."}, - {"max-memory-read-size", OptionValue::eTypeSInt64, false, 1024, nullptr, - {}, "Maximum number of bytes that 'memory read' will fetch before " - "--force must be specified."}, - {"breakpoints-use-platform-avoid-list", OptionValue::eTypeBoolean, false, - true, nullptr, {}, "Consult the platform module avoid list when " - "setting non-module specific breakpoints."}, - {"arg0", OptionValue::eTypeString, false, 0, nullptr, {}, - "The first argument passed to the program in the argument array which can " - "be different from the executable itself."}, - {"run-args", OptionValue::eTypeArgs, false, 0, nullptr, {}, - "A list containing all the arguments to be passed to the executable when " - "it is run. Note that this does NOT include the argv[0] which is in " - "target.arg0."}, - {"env-vars", OptionValue::eTypeDictionary, false, OptionValue::eTypeString, - nullptr, {}, "A list of all the environment variables to be passed " - "to the executable's environment, and their values."}, - {"inherit-env", OptionValue::eTypeBoolean, false, true, nullptr, {}, - "Inherit the environment from the process that is running LLDB."}, - {"input-path", OptionValue::eTypeFileSpec, false, 0, nullptr, {}, - "The file/path to be used by the executable program for reading its " - "standard input."}, - {"output-path", OptionValue::eTypeFileSpec, false, 0, nullptr, {}, - "The file/path to be used by the executable program for writing its " - "standard output."}, - {"error-path", OptionValue::eTypeFileSpec, false, 0, nullptr, {}, - "The file/path to be used by the executable program for writing its " - "standard error."}, - {"detach-on-error", OptionValue::eTypeBoolean, false, true, nullptr, - {}, "debugserver will detach (rather than killing) a process if it " - "loses connection with lldb."}, - {"preload-symbols", OptionValue::eTypeBoolean, false, true, nullptr, {}, - "Enable loading of symbol tables before they are needed."}, - {"disable-aslr", OptionValue::eTypeBoolean, false, true, nullptr, {}, - "Disable Address Space Layout Randomization (ASLR)"}, - {"disable-stdio", OptionValue::eTypeBoolean, false, false, nullptr, {}, - "Disable stdin/stdout for process (e.g. for a GUI application)"}, - {"inline-breakpoint-strategy", OptionValue::eTypeEnum, false, - eInlineBreakpointsAlways, nullptr, - OptionEnumValues(g_inline_breakpoint_enums), - "The strategy to use when settings breakpoints by file and line. " - "Breakpoint locations can end up being inlined by the compiler, so that a " - "compile unit 'a.c' might contain an inlined function from another source " - "file. " - "Usually this is limited to breakpoint locations from inlined functions " - "from header or other include files, or more accurately " - "non-implementation source files. " - "Sometimes code might #include implementation files and cause inlined " - "breakpoint locations in inlined implementation files. " - "Always checking for inlined breakpoint locations can be expensive " - "(memory and time), so if you have a project with many headers " - "and find that setting breakpoints is slow, then you can change this " - "setting to headers. " - "This setting allows you to control exactly which strategy is used when " - "setting " - "file and line breakpoints."}, - // FIXME: This is the wrong way to do per-architecture settings, but we - // don't have a general per architecture settings system in place yet. - {"x86-disassembly-flavor", OptionValue::eTypeEnum, false, - eX86DisFlavorDefault, nullptr, - OptionEnumValues(g_x86_dis_flavor_value_types), - "The default disassembly flavor to use for x86 or x86-64 targets."}, - {"use-hex-immediates", OptionValue::eTypeBoolean, false, true, nullptr, - {}, "Show immediates in disassembly as hexadecimal."}, - {"hex-immediate-style", OptionValue::eTypeEnum, false, - Disassembler::eHexStyleC, nullptr, - OptionEnumValues(g_hex_immediate_style_values), - "Which style to use for printing hexadecimal disassembly values."}, - {"use-fast-stepping", OptionValue::eTypeBoolean, false, true, nullptr, - {}, "Use a fast stepping algorithm based on running from branch to " - "branch rather than instruction single-stepping."}, - {"load-script-from-symbol-file", OptionValue::eTypeEnum, false, - eLoadScriptFromSymFileWarn, nullptr, - OptionEnumValues(g_load_script_from_sym_file_values), - "Allow LLDB to load scripting resources embedded in symbol files when " - "available."}, - {"load-cwd-lldbinit", OptionValue::eTypeEnum, false, eLoadCWDlldbinitWarn, - nullptr, OptionEnumValues(g_load_current_working_dir_lldbinit_values), - "Allow LLDB to .lldbinit files from the current directory automatically."}, - {"memory-module-load-level", OptionValue::eTypeEnum, false, - eMemoryModuleLoadLevelComplete, nullptr, - OptionEnumValues(g_memory_module_load_level_values), - "Loading modules from memory can be slow as reading the symbol tables and " - "other data can take a long time depending on your connection to the " - "debug target. " - "This setting helps users control how much information gets loaded when " - "loading modules from memory." - "'complete' is the default value for this setting which will load all " - "sections and symbols by reading them from memory (slowest, most " - "accurate). " - "'partial' will load sections and attempt to find function bounds without " - "downloading the symbol table (faster, still accurate, missing symbol " - "names). " - "'minimal' is the fastest setting and will load section data with no " - "symbols, but should rarely be used as stack frames in these memory " - "regions will be inaccurate and not provide any context (fastest). "}, - {"display-expression-in-crashlogs", OptionValue::eTypeBoolean, false, false, - nullptr, {}, "Expressions that crash will show up in crash logs if " - "the host system supports executable specific crash log " - "strings and this setting is set to true."}, - {"trap-handler-names", OptionValue::eTypeArray, true, - OptionValue::eTypeString, nullptr, {}, - "A list of trap handler function names, e.g. a common Unix user process " - "one is _sigtramp."}, - {"display-runtime-support-values", OptionValue::eTypeBoolean, false, false, - nullptr, {}, "If true, LLDB will show variables that are meant to " - "support the operation of a language's runtime support."}, - {"display-recognized-arguments", OptionValue::eTypeBoolean, false, false, - nullptr, {}, "Show recognized arguments in variable listings by default."}, - {"non-stop-mode", OptionValue::eTypeBoolean, false, 0, nullptr, {}, - "Disable lock-step debugging, instead control threads independently."}, - {"require-hardware-breakpoint", OptionValue::eTypeBoolean, false, 0, - nullptr, {}, "Require all breakpoints to be hardware breakpoints."}}; -// clang-format on + { + eMemoryModuleLoadLevelMinimal, + "minimal", + "Load minimal information when loading modules from memory. Currently " + "this setting loads sections only.", + }, + { + eMemoryModuleLoadLevelPartial, + "partial", + "Load partial information when loading modules from memory. Currently " + "this setting loads sections and function bounds.", + }, + { + eMemoryModuleLoadLevelComplete, + "complete", + "Load complete information when loading modules from memory. Currently " + "this setting loads sections and all symbols.", + }, +}; + +#define LLDB_PROPERTIES_target +#include "TargetProperties.inc" enum { - ePropertyDefaultArch, - ePropertyMoveToNearestCode, - ePropertyLanguage, - ePropertyExprPrefix, - ePropertyPreferDynamic, - ePropertyEnableSynthetic, - ePropertySkipPrologue, - ePropertySourceMap, - ePropertyExecutableSearchPaths, - ePropertyDebugFileSearchPaths, - ePropertyClangModuleSearchPaths, - ePropertyAutoImportClangModules, - ePropertyImportStdModule, - ePropertyAutoApplyFixIts, - ePropertyNotifyAboutFixIts, - ePropertySaveObjects, - ePropertyMaxChildrenCount, - ePropertyMaxSummaryLength, - ePropertyMaxMemReadSize, - ePropertyBreakpointUseAvoidList, - ePropertyArg0, - ePropertyRunArgs, - ePropertyEnvVars, - ePropertyInheritEnv, - ePropertyInputPath, - ePropertyOutputPath, - ePropertyErrorPath, - ePropertyDetachOnError, - ePropertyPreloadSymbols, - ePropertyDisableASLR, - ePropertyDisableSTDIO, - ePropertyInlineStrategy, - ePropertyDisassemblyFlavor, - ePropertyUseHexImmediates, - ePropertyHexImmediateStyle, - ePropertyUseFastStepping, - ePropertyLoadScriptFromSymbolFile, - ePropertyLoadCWDlldbinitFile, - ePropertyMemoryModuleLoadLevel, - ePropertyDisplayExpressionsInCrashlogs, - ePropertyTrapHandlerNames, - ePropertyDisplayRuntimeSupportValues, - ePropertyDisplayRecognizedArguments, - ePropertyNonStopModeEnabled, - ePropertyRequireHardwareBreakpoints, +#define LLDB_PROPERTIES_target +#include "TargetPropertiesEnum.inc" ePropertyExperimental, }; @@ -3547,7 +3411,7 @@ protected: m_got_host_env = true; const uint32_t idx = ePropertyInheritEnv; if (GetPropertyAtIndexAsBoolean( - nullptr, idx, g_properties[idx].default_uint_value != 0)) { + nullptr, idx, g_target_properties[idx].default_uint_value != 0)) { PlatformSP platform_sp(m_target->GetPlatform()); if (platform_sp) { Environment env = platform_sp->GetEnvironment(); @@ -3575,17 +3439,13 @@ protected: }; // TargetProperties -static constexpr PropertyDefinition g_experimental_properties[]{ - {"inject-local-vars", OptionValue::eTypeBoolean, true, true, nullptr, - {}, - "If true, inject local variables explicitly into the expression text. " - "This will fix symbol resolution when there are name collisions between " - "ivars and local variables. " - "But it can make expressions run much more slowly."}, - {"use-modern-type-lookup", OptionValue::eTypeBoolean, true, false, nullptr, - {}, "If true, use Clang's modern type lookup infrastructure."}}; - -enum { ePropertyInjectLocalVars = 0, ePropertyUseModernTypeLookup }; +#define LLDB_PROPERTIES_experimental +#include "TargetProperties.inc" + +enum { +#define LLDB_PROPERTIES_experimental +#include "TargetPropertiesEnum.inc" +}; class TargetExperimentalOptionValueProperties : public OptionValueProperties { public: @@ -3655,7 +3515,7 @@ TargetProperties::TargetProperties(Target *target) } else { m_collection_sp = std::make_shared<TargetOptionValueProperties>(ConstString("target")); - m_collection_sp->Initialize(g_properties); + m_collection_sp->Initialize(g_target_properties); m_experimental_properties_up.reset(new TargetExperimentalProperties()); m_collection_sp->AppendProperty( ConstString(Properties::GetExperimentalSettingsName()), @@ -3724,14 +3584,14 @@ void TargetProperties::SetDefaultArchitecture(const ArchSpec &arch) { bool TargetProperties::GetMoveToNearestCode() const { const uint32_t idx = ePropertyMoveToNearestCode; return m_collection_sp->GetPropertyAtIndexAsBoolean( - nullptr, idx, g_properties[idx].default_uint_value != 0); + nullptr, idx, g_target_properties[idx].default_uint_value != 0); } lldb::DynamicValueType TargetProperties::GetPreferDynamicValue() const { const uint32_t idx = ePropertyPreferDynamic; return (lldb::DynamicValueType) m_collection_sp->GetPropertyAtIndexAsEnumeration( - nullptr, idx, g_properties[idx].default_uint_value); + nullptr, idx, g_target_properties[idx].default_uint_value); } bool TargetProperties::SetPreferDynamicValue(lldb::DynamicValueType d) { @@ -3742,7 +3602,7 @@ bool TargetProperties::SetPreferDynamicValue(lldb::DynamicValueType d) { bool TargetProperties::GetPreloadSymbols() const { const uint32_t idx = ePropertyPreloadSymbols; return m_collection_sp->GetPropertyAtIndexAsBoolean( - nullptr, idx, g_properties[idx].default_uint_value != 0); + nullptr, idx, g_target_properties[idx].default_uint_value != 0); } void TargetProperties::SetPreloadSymbols(bool b) { @@ -3753,7 +3613,7 @@ void TargetProperties::SetPreloadSymbols(bool b) { bool TargetProperties::GetDisableASLR() const { const uint32_t idx = ePropertyDisableASLR; return m_collection_sp->GetPropertyAtIndexAsBoolean( - nullptr, idx, g_properties[idx].default_uint_value != 0); + nullptr, idx, g_target_properties[idx].default_uint_value != 0); } void TargetProperties::SetDisableASLR(bool b) { @@ -3764,7 +3624,7 @@ void TargetProperties::SetDisableASLR(bool b) { bool TargetProperties::GetDetachOnError() const { const uint32_t idx = ePropertyDetachOnError; return m_collection_sp->GetPropertyAtIndexAsBoolean( - nullptr, idx, g_properties[idx].default_uint_value != 0); + nullptr, idx, g_target_properties[idx].default_uint_value != 0); } void TargetProperties::SetDetachOnError(bool b) { @@ -3775,7 +3635,7 @@ void TargetProperties::SetDetachOnError(bool b) { bool TargetProperties::GetDisableSTDIO() const { const uint32_t idx = ePropertyDisableSTDIO; return m_collection_sp->GetPropertyAtIndexAsBoolean( - nullptr, idx, g_properties[idx].default_uint_value != 0); + nullptr, idx, g_target_properties[idx].default_uint_value != 0); } void TargetProperties::SetDisableSTDIO(bool b) { @@ -3789,7 +3649,7 @@ const char *TargetProperties::GetDisassemblyFlavor() const { x86DisassemblyFlavor flavor_value = (x86DisassemblyFlavor)m_collection_sp->GetPropertyAtIndexAsEnumeration( - nullptr, idx, g_properties[idx].default_uint_value); + nullptr, idx, g_target_properties[idx].default_uint_value); return_value = g_x86_dis_flavor_value_types[flavor_value].string_value; return return_value; } @@ -3797,18 +3657,18 @@ const char *TargetProperties::GetDisassemblyFlavor() const { InlineStrategy TargetProperties::GetInlineStrategy() const { const uint32_t idx = ePropertyInlineStrategy; return (InlineStrategy)m_collection_sp->GetPropertyAtIndexAsEnumeration( - nullptr, idx, g_properties[idx].default_uint_value); + nullptr, idx, g_target_properties[idx].default_uint_value); } llvm::StringRef TargetProperties::GetArg0() const { const uint32_t idx = ePropertyArg0; - return m_collection_sp->GetPropertyAtIndexAsString(nullptr, idx, llvm::StringRef()); + return m_collection_sp->GetPropertyAtIndexAsString(nullptr, idx, + llvm::StringRef()); } void TargetProperties::SetArg0(llvm::StringRef arg) { const uint32_t idx = ePropertyArg0; - m_collection_sp->SetPropertyAtIndexAsString( - nullptr, idx, arg); + m_collection_sp->SetPropertyAtIndexAsString(nullptr, idx, arg); m_launch_info.SetArg0(arg); } @@ -3841,7 +3701,7 @@ void TargetProperties::SetEnvironment(Environment env) { bool TargetProperties::GetSkipPrologue() const { const uint32_t idx = ePropertySkipPrologue; return m_collection_sp->GetPropertyAtIndexAsBoolean( - nullptr, idx, g_properties[idx].default_uint_value != 0); + nullptr, idx, g_target_properties[idx].default_uint_value != 0); } PathMappingList &TargetProperties::GetSourcePathMap() const { @@ -3853,7 +3713,7 @@ PathMappingList &TargetProperties::GetSourcePathMap() const { return option_value->GetCurrentValue(); } -void TargetProperties::AppendExecutableSearchPaths(const FileSpec& dir) { +void TargetProperties::AppendExecutableSearchPaths(const FileSpec &dir) { const uint32_t idx = ePropertyExecutableSearchPaths; OptionValueFileSpecList *option_value = m_collection_sp->GetPropertyAtIndexAsOptionValueFileSpecList(nullptr, @@ -3892,55 +3752,61 @@ FileSpecList TargetProperties::GetClangModuleSearchPaths() { bool TargetProperties::GetEnableAutoImportClangModules() const { const uint32_t idx = ePropertyAutoImportClangModules; return m_collection_sp->GetPropertyAtIndexAsBoolean( - nullptr, idx, g_properties[idx].default_uint_value != 0); + nullptr, idx, g_target_properties[idx].default_uint_value != 0); } bool TargetProperties::GetEnableImportStdModule() const { const uint32_t idx = ePropertyImportStdModule; return m_collection_sp->GetPropertyAtIndexAsBoolean( - nullptr, idx, g_properties[idx].default_uint_value != 0); + nullptr, idx, g_target_properties[idx].default_uint_value != 0); } bool TargetProperties::GetEnableAutoApplyFixIts() const { const uint32_t idx = ePropertyAutoApplyFixIts; return m_collection_sp->GetPropertyAtIndexAsBoolean( - nullptr, idx, g_properties[idx].default_uint_value != 0); + nullptr, idx, g_target_properties[idx].default_uint_value != 0); } bool TargetProperties::GetEnableNotifyAboutFixIts() const { const uint32_t idx = ePropertyNotifyAboutFixIts; return m_collection_sp->GetPropertyAtIndexAsBoolean( - nullptr, idx, g_properties[idx].default_uint_value != 0); + nullptr, idx, g_target_properties[idx].default_uint_value != 0); } bool TargetProperties::GetEnableSaveObjects() const { const uint32_t idx = ePropertySaveObjects; return m_collection_sp->GetPropertyAtIndexAsBoolean( - nullptr, idx, g_properties[idx].default_uint_value != 0); + nullptr, idx, g_target_properties[idx].default_uint_value != 0); } bool TargetProperties::GetEnableSyntheticValue() const { const uint32_t idx = ePropertyEnableSynthetic; return m_collection_sp->GetPropertyAtIndexAsBoolean( - nullptr, idx, g_properties[idx].default_uint_value != 0); + nullptr, idx, g_target_properties[idx].default_uint_value != 0); +} + +uint32_t TargetProperties::GetMaxZeroPaddingInFloatFormat() const { + const uint32_t idx = ePropertyMaxZeroPaddingInFloatFormat; + return m_collection_sp->GetPropertyAtIndexAsUInt64( + nullptr, idx, g_target_properties[idx].default_uint_value); } uint32_t TargetProperties::GetMaximumNumberOfChildrenToDisplay() const { const uint32_t idx = ePropertyMaxChildrenCount; return m_collection_sp->GetPropertyAtIndexAsSInt64( - nullptr, idx, g_properties[idx].default_uint_value); + nullptr, idx, g_target_properties[idx].default_uint_value); } uint32_t TargetProperties::GetMaximumSizeOfStringSummary() const { const uint32_t idx = ePropertyMaxSummaryLength; return m_collection_sp->GetPropertyAtIndexAsSInt64( - nullptr, idx, g_properties[idx].default_uint_value); + nullptr, idx, g_target_properties[idx].default_uint_value); } uint32_t TargetProperties::GetMaximumMemReadSize() const { const uint32_t idx = ePropertyMaxMemReadSize; return m_collection_sp->GetPropertyAtIndexAsSInt64( - nullptr, idx, g_properties[idx].default_uint_value); + nullptr, idx, g_target_properties[idx].default_uint_value); } FileSpec TargetProperties::GetStandardInputPath() const { @@ -4000,52 +3866,52 @@ llvm::StringRef TargetProperties::GetExpressionPrefixContents() { bool TargetProperties::GetBreakpointsConsultPlatformAvoidList() { const uint32_t idx = ePropertyBreakpointUseAvoidList; return m_collection_sp->GetPropertyAtIndexAsBoolean( - nullptr, idx, g_properties[idx].default_uint_value != 0); + nullptr, idx, g_target_properties[idx].default_uint_value != 0); } bool TargetProperties::GetUseHexImmediates() const { const uint32_t idx = ePropertyUseHexImmediates; return m_collection_sp->GetPropertyAtIndexAsBoolean( - nullptr, idx, g_properties[idx].default_uint_value != 0); + nullptr, idx, g_target_properties[idx].default_uint_value != 0); } bool TargetProperties::GetUseFastStepping() const { const uint32_t idx = ePropertyUseFastStepping; return m_collection_sp->GetPropertyAtIndexAsBoolean( - nullptr, idx, g_properties[idx].default_uint_value != 0); + nullptr, idx, g_target_properties[idx].default_uint_value != 0); } bool TargetProperties::GetDisplayExpressionsInCrashlogs() const { const uint32_t idx = ePropertyDisplayExpressionsInCrashlogs; return m_collection_sp->GetPropertyAtIndexAsBoolean( - nullptr, idx, g_properties[idx].default_uint_value != 0); + nullptr, idx, g_target_properties[idx].default_uint_value != 0); } LoadScriptFromSymFile TargetProperties::GetLoadScriptFromSymbolFile() const { const uint32_t idx = ePropertyLoadScriptFromSymbolFile; return (LoadScriptFromSymFile) m_collection_sp->GetPropertyAtIndexAsEnumeration( - nullptr, idx, g_properties[idx].default_uint_value); + nullptr, idx, g_target_properties[idx].default_uint_value); } LoadCWDlldbinitFile TargetProperties::GetLoadCWDlldbinitFile() const { const uint32_t idx = ePropertyLoadCWDlldbinitFile; return (LoadCWDlldbinitFile)m_collection_sp->GetPropertyAtIndexAsEnumeration( - nullptr, idx, g_properties[idx].default_uint_value); + nullptr, idx, g_target_properties[idx].default_uint_value); } Disassembler::HexImmediateStyle TargetProperties::GetHexImmediateStyle() const { const uint32_t idx = ePropertyHexImmediateStyle; return (Disassembler::HexImmediateStyle) m_collection_sp->GetPropertyAtIndexAsEnumeration( - nullptr, idx, g_properties[idx].default_uint_value); + nullptr, idx, g_target_properties[idx].default_uint_value); } MemoryModuleLoadLevel TargetProperties::GetMemoryModuleLoadLevel() const { const uint32_t idx = ePropertyMemoryModuleLoadLevel; return (MemoryModuleLoadLevel) m_collection_sp->GetPropertyAtIndexAsEnumeration( - nullptr, idx, g_properties[idx].default_uint_value); + nullptr, idx, g_target_properties[idx].default_uint_value); } bool TargetProperties::GetUserSpecifiedTrapHandlerNames(Args &args) const { @@ -4122,7 +3988,7 @@ void TargetProperties::SetProcessLaunchInfo( bool TargetProperties::GetRequireHardwareBreakpoints() const { const uint32_t idx = ePropertyRequireHardwareBreakpoints; return m_collection_sp->GetPropertyAtIndexAsBoolean( - nullptr, idx, g_properties[idx].default_uint_value != 0); + nullptr, idx, g_target_properties[idx].default_uint_value != 0); } void TargetProperties::SetRequireHardwareBreakpoints(bool b) { @@ -4259,3 +4125,10 @@ Target::TargetEventData::GetModuleListFromEvent(const Event *event_ptr) { module_list = event_data->m_module_list; return module_list; } + +std::recursive_mutex &Target::GetAPIMutex() { + if (GetProcessSP() && GetProcessSP()->CurrentThreadIsPrivateStateThread()) + return m_private_mutex; + else + return m_mutex; +} diff --git a/source/Target/TargetProperties.td b/source/Target/TargetProperties.td new file mode 100644 index 000000000000..9079c3cf4276 --- /dev/null +++ b/source/Target/TargetProperties.td @@ -0,0 +1,237 @@ +include "../../include/lldb/Core/PropertiesBase.td" + +let Definition = "experimental" in { + def InjectLocalVars : Property<"inject-local-vars", "Boolean">, + Global, DefaultTrue, + Desc<"If true, inject local variables explicitly into the expression text. This will fix symbol resolution when there are name collisions between ivars and local variables. But it can make expressions run much more slowly.">; + def UseModernTypeLookup : Property<"use-modern-type-lookup", "Boolean">, + Global, DefaultFalse, + Desc<"If true, use Clang's modern type lookup infrastructure.">; +} + +let Definition = "target" in { + def DefaultArch: Property<"default-arch", "Arch">, + Global, + DefaultStringValue<"">, + Desc<"Default architecture to choose, when there's a choice.">; + def MoveToNearestCode: Property<"move-to-nearest-code", "Boolean">, + DefaultTrue, + Desc<"Move breakpoints to nearest code.">; + def Language: Property<"language", "Language">, + DefaultEnumValue<"eLanguageTypeUnknown">, + Desc<"The language to use when interpreting expressions entered in commands.">; + def ExprPrefix: Property<"expr-prefix", "FileSpec">, + DefaultStringValue<"">, + Desc<"Path to a file containing expressions to be prepended to all expressions.">; + def PreferDynamic: Property<"prefer-dynamic-value", "Enum">, + DefaultEnumValue<"eDynamicDontRunTarget">, + EnumValues<"OptionEnumValues(g_dynamic_value_types)">, + Desc<"Should printed values be shown as their dynamic value.">; + def EnableSynthetic: Property<"enable-synthetic-value", "Boolean">, + DefaultTrue, + Desc<"Should synthetic values be used by default whenever available.">; + def SkipPrologue: Property<"skip-prologue", "Boolean">, + DefaultTrue, + Desc<"Skip function prologues when setting breakpoints by name.">; + def SourceMap: Property<"source-map", "PathMap">, + DefaultStringValue<"">, + Desc<"Source path remappings are used to track the change of location between a source file when built, and where it exists on the current system. It consists of an array of duples, the first element of each duple is some part (starting at the root) of the path to the file when it was built, and the second is where the remainder of the original build hierarchy is rooted on the local system. Each element of the array is checked in order and the first one that results in a match wins.">; + def ExecutableSearchPaths: Property<"exec-search-paths", "FileSpecList">, + DefaultStringValue<"">, + Desc<"Executable search paths to use when locating executable files whose paths don't match the local file system.">; + def DebugFileSearchPaths: Property<"debug-file-search-paths", "FileSpecList">, + DefaultStringValue<"">, + Desc<"List of directories to be searched when locating debug symbol files. See also symbols.enable-external-lookup.">; + def ClangModuleSearchPaths: Property<"clang-module-search-paths", "FileSpecList">, + DefaultStringValue<"">, + Desc<"List of directories to be searched when locating modules for Clang.">; + def AutoImportClangModules: Property<"auto-import-clang-modules", "Boolean">, + DefaultTrue, + Desc<"Automatically load Clang modules referred to by the program.">; + def ImportStdModule: Property<"import-std-module", "Boolean">, + DefaultFalse, + Desc<"Import the C++ std module to improve debugging STL containers.">; + def AutoApplyFixIts: Property<"auto-apply-fixits", "Boolean">, + DefaultTrue, + Desc<"Automatically apply fix-it hints to expressions.">; + def NotifyAboutFixIts: Property<"notify-about-fixits", "Boolean">, + DefaultTrue, + Desc<"Print the fixed expression text.">; + def SaveObjects: Property<"save-jit-objects", "Boolean">, + DefaultFalse, + Desc<"Save intermediate object files generated by the LLVM JIT">; + def MaxZeroPaddingInFloatFormat: Property<"max-zero-padding-in-float-format", "UInt64">, + DefaultUnsignedValue<6>, + Desc<"The maximum number of zeroes to insert when displaying a very small float before falling back to scientific notation.">; + def MaxChildrenCount: Property<"max-children-count", "SInt64">, + DefaultUnsignedValue<256>, + Desc<"Maximum number of children to expand in any level of depth.">; + def MaxSummaryLength: Property<"max-string-summary-length", "SInt64">, + DefaultUnsignedValue<1024>, + Desc<"Maximum number of characters to show when using %s in summary strings.">; + def MaxMemReadSize: Property<"max-memory-read-size", "SInt64">, + DefaultUnsignedValue<1024>, + Desc<"Maximum number of bytes that 'memory read' will fetch before --force must be specified.">; + def BreakpointUseAvoidList: Property<"breakpoints-use-platform-avoid-list", "Boolean">, + DefaultTrue, + Desc<"Consult the platform module avoid list when setting non-module specific breakpoints.">; + def Arg0: Property<"arg0", "String">, + DefaultStringValue<"">, + Desc<"The first argument passed to the program in the argument array which can be different from the executable itself.">; + def RunArgs: Property<"run-args", "Args">, + DefaultStringValue<"">, + Desc<"A list containing all the arguments to be passed to the executable when it is run. Note that this does NOT include the argv[0] which is in target.arg0.">; + def EnvVars: Property<"env-vars", "Dictionary">, + DefaultUnsignedValue<16>, + Desc<"A list of all the environment variables to be passed to the executable's environment, and their values.">; + def InheritEnv: Property<"inherit-env", "Boolean">, + DefaultTrue, + Desc<"Inherit the environment from the process that is running LLDB.">; + def InputPath: Property<"input-path", "FileSpec">, + DefaultStringValue<"">, + Desc<"The file/path to be used by the executable program for reading its standard input.">; + def OutputPath: Property<"output-path", "FileSpec">, + DefaultStringValue<"">, + Desc<"The file/path to be used by the executable program for writing its standard output.">; + def ErrorPath: Property<"error-path", "FileSpec">, + DefaultStringValue<"">, + Desc<"The file/path to be used by the executable program for writing its standard error.">; + def DetachOnError: Property<"detach-on-error", "Boolean">, + DefaultTrue, + Desc<"debugserver will detach (rather than killing) a process if it loses connection with lldb.">; + def PreloadSymbols: Property<"preload-symbols", "Boolean">, + DefaultTrue, + Desc<"Enable loading of symbol tables before they are needed.">; + def DisableASLR: Property<"disable-aslr", "Boolean">, + DefaultTrue, + Desc<"Disable Address Space Layout Randomization (ASLR)">; + def DisableSTDIO: Property<"disable-stdio", "Boolean">, + DefaultFalse, + Desc<"Disable stdin/stdout for process (e.g. for a GUI application)">; + def InlineStrategy: Property<"inline-breakpoint-strategy", "Enum">, + DefaultEnumValue<"eInlineBreakpointsAlways">, + EnumValues<"OptionEnumValues(g_inline_breakpoint_enums)">, + Desc<"The strategy to use when settings breakpoints by file and line. Breakpoint locations can end up being inlined by the compiler, so that a compile unit 'a.c' might contain an inlined function from another source file. Usually this is limited to breakpoint locations from inlined functions from header or other include files, or more accurately non-implementation source files. Sometimes code might #include implementation files and cause inlined breakpoint locations in inlined implementation files. Always checking for inlined breakpoint locations can be expensive (memory and time), so if you have a project with many headers and find that setting breakpoints is slow, then you can change this setting to headers. This setting allows you to control exactly which strategy is used when setting file and line breakpoints.">; + def DisassemblyFlavor: Property<"x86-disassembly-flavor", "Enum">, + DefaultEnumValue<"eX86DisFlavorDefault">, + EnumValues<"OptionEnumValues(g_x86_dis_flavor_value_types)">, + Desc<"The default disassembly flavor to use for x86 or x86-64 targets.">; + def UseHexImmediates: Property<"use-hex-immediates", "Boolean">, + DefaultTrue, + Desc<"Show immediates in disassembly as hexadecimal.">; + def HexImmediateStyle: Property<"hex-immediate-style", "Enum">, + DefaultEnumValue<"Disassembler::eHexStyleC">, + EnumValues<"OptionEnumValues(g_hex_immediate_style_values)">, + Desc<"Which style to use for printing hexadecimal disassembly values.">; + def UseFastStepping: Property<"use-fast-stepping", "Boolean">, + DefaultTrue, + Desc<"Use a fast stepping algorithm based on running from branch to branch rather than instruction single-stepping.">; + def LoadScriptFromSymbolFile: Property<"load-script-from-symbol-file", "Enum">, + DefaultEnumValue<"eLoadScriptFromSymFileWarn">, + EnumValues<"OptionEnumValues(g_load_script_from_sym_file_values)">, + Desc<"Allow LLDB to load scripting resources embedded in symbol files when available.">; + def LoadCWDlldbinitFile: Property<"load-cwd-lldbinit", "Enum">, + DefaultEnumValue<"eLoadCWDlldbinitWarn">, + EnumValues<"OptionEnumValues(g_load_cwd_lldbinit_values)">, + Desc<"Allow LLDB to .lldbinit files from the current directory automatically.">; + def MemoryModuleLoadLevel: Property<"memory-module-load-level", "Enum">, + DefaultEnumValue<"eMemoryModuleLoadLevelComplete">, + EnumValues<"OptionEnumValues(g_memory_module_load_level_values)">, + Desc<"Loading modules from memory can be slow as reading the symbol tables and other data can take a long time depending on your connection to the debug target. This setting helps users control how much information gets loaded when loading modules from memory.'complete' is the default value for this setting which will load all sections and symbols by reading them from memory (slowest, most accurate). 'partial' will load sections and attempt to find function bounds without downloading the symbol table (faster, still accurate, missing symbol names). 'minimal' is the fastest setting and will load section data with no symbols, but should rarely be used as stack frames in these memory regions will be inaccurate and not provide any context (fastest). ">; + def DisplayExpressionsInCrashlogs: Property<"display-expression-in-crashlogs", "Boolean">, + DefaultFalse, + Desc<"Expressions that crash will show up in crash logs if the host system supports executable specific crash log strings and this setting is set to true.">; + def TrapHandlerNames: Property<"trap-handler-names", "Array">, + Global, + DefaultUnsignedValue<16>, + Desc<"A list of trap handler function names, e.g. a common Unix user process one is _sigtramp.">; + def DisplayRuntimeSupportValues: Property<"display-runtime-support-values", "Boolean">, + DefaultFalse, + Desc<"If true, LLDB will show variables that are meant to support the operation of a language's runtime support.">; + def DisplayRecognizedArguments: Property<"display-recognized-arguments", "Boolean">, + DefaultFalse, + Desc<"Show recognized arguments in variable listings by default.">; + def NonStopModeEnabled: Property<"non-stop-mode", "Boolean">, + DefaultFalse, + Desc<"Disable lock-step debugging, instead control threads independently.">; + def RequireHardwareBreakpoints: Property<"require-hardware-breakpoint", "Boolean">, + DefaultFalse, + Desc<"Require all breakpoints to be hardware breakpoints.">; +} + +let Definition = "process" in { + def DisableMemCache: Property<"disable-memory-cache", "Boolean">, + DefaultFalse, + Desc<"Disable reading and caching of memory in fixed-size units.">; + def ExtraStartCommand: Property<"extra-startup-command", "Array">, + DefaultUnsignedValue<16>, + Desc<"A list containing extra commands understood by the particular process plugin used. For instance, to turn on debugserver logging set this to 'QSetLogging:bitmask=LOG_DEFAULT;'">; + def IgnoreBreakpointsInExpressions: Property<"ignore-breakpoints-in-expressions", "Boolean">, + Global, + DefaultTrue, + Desc<"If true, breakpoints will be ignored during expression evaluation.">; + def UnwindOnErrorInExpressions: Property<"unwind-on-error-in-expressions", "Boolean">, + Global, + DefaultTrue, + Desc<"If true, errors in expression evaluation will unwind the stack back to the state before the call.">; + def PythonOSPluginPath: Property<"python-os-plugin-path", "FileSpec">, + DefaultUnsignedValue<1>, + Desc<"A path to a python OS plug-in module file that contains a OperatingSystemPlugIn class.">; + def StopOnSharedLibraryEvents: Property<"stop-on-sharedlibrary-events", "Boolean">, + Global, + DefaultFalse, + Desc<"If true, stop when a shared library is loaded or unloaded.">; + def DetachKeepsStopped: Property<"detach-keeps-stopped", "Boolean">, + Global, + DefaultFalse, + Desc<"If true, detach will attempt to keep the process stopped.">; + def MemCacheLineSize: Property<"memory-cache-line-size", "UInt64">, + DefaultUnsignedValue<512>, + Desc<"The memory cache line size">; + def WarningOptimization: Property<"optimization-warnings", "Boolean">, + DefaultTrue, + Desc<"If true, warn when stopped in code that is optimized where stepping and variable availability may not behave as expected.">; + def StopOnExec: Property<"stop-on-exec", "Boolean">, + Global, + DefaultTrue, + Desc<"If true, stop when a shared library is loaded or unloaded.">; + def UtilityExpressionTimeout: Property<"utility-expression-timeout", "UInt64">, + DefaultUnsignedValue<15>, + Desc<"The time in seconds to wait for LLDB-internal utility expressions.">; +} + +let Definition = "platform" in { + def UseModuleCache: Property<"use-module-cache", "Boolean">, + Global, + DefaultTrue, + Desc<"Use module cache.">; + def ModuleCacheDirectory: Property<"module-cache-directory", "FileSpec">, + Global, + DefaultStringValue<"">, + Desc<"Root directory for cached modules.">; +} + +let Definition = "thread" in { + def StepInAvoidsNoDebug: Property<"step-in-avoid-nodebug", "Boolean">, + Global, + DefaultTrue, + Desc<"If true, step-in will not stop in functions with no debug information.">; + def StepOutAvoidsNoDebug: Property<"step-out-avoid-nodebug", "Boolean">, + Global, + DefaultFalse, + Desc<"If true, when step-in/step-out/step-over leave the current frame, they will continue to step out till they come to a function with debug information. Passing a frame argument to step-out will override this option.">; + def StepAvoidRegex: Property<"step-avoid-regexp", "Regex">, + Global, + DefaultStringValue<"^std::">, + Desc<"A regular expression defining functions step-in won't stop in.">; + def StepAvoidLibraries: Property<"step-avoid-libraries", "FileSpecList">, + Global, + DefaultStringValue<"">, + Desc<"A list of libraries that source stepping won't stop in.">; + def EnableThreadTrace: Property<"trace-thread", "Boolean">, + DefaultFalse, + Desc<"If true, this thread will single-step and log execution.">; + def MaxBacktraceDepth: Property<"max-backtrace-depth", "UInt64">, + DefaultUnsignedValue<300000>, + Desc<"Maximum number of frames to backtrace.">; +} diff --git a/source/Target/Thread.cpp b/source/Target/Thread.cpp index 7a6b49e55252..e12b90501103 100644 --- a/source/Target/Thread.cpp +++ b/source/Target/Thread.cpp @@ -13,6 +13,7 @@ #include "lldb/Core/Debugger.h" #include "lldb/Core/FormatEntity.h" #include "lldb/Core/Module.h" +#include "lldb/Core/StructuredDataImpl.h" #include "lldb/Core/ValueObject.h" #include "lldb/Host/Host.h" #include "lldb/Interpreter/OptionValueFileSpecList.h" @@ -63,31 +64,12 @@ const ThreadPropertiesSP &Thread::GetGlobalProperties() { return *g_settings_sp_ptr; } -static constexpr PropertyDefinition g_properties[] = { - {"step-in-avoid-nodebug", OptionValue::eTypeBoolean, true, true, nullptr, - {}, - "If true, step-in will not stop in functions with no debug information."}, - {"step-out-avoid-nodebug", OptionValue::eTypeBoolean, true, false, nullptr, - {}, "If true, when step-in/step-out/step-over leave the current frame, " - "they will continue to step out till they come to a function with " - "debug information. Passing a frame argument to step-out will " - "override this option."}, - {"step-avoid-regexp", OptionValue::eTypeRegex, true, 0, "^std::", {}, - "A regular expression defining functions step-in won't stop in."}, - {"step-avoid-libraries", OptionValue::eTypeFileSpecList, true, 0, nullptr, - {}, "A list of libraries that source stepping won't stop in."}, - {"trace-thread", OptionValue::eTypeBoolean, false, false, nullptr, {}, - "If true, this thread will single-step and log execution."}, - {"max-backtrace-depth", OptionValue::eTypeUInt64, false, 300000, nullptr, - {}, "Maximum number of frames to backtrace."}}; +#define LLDB_PROPERTIES_thread +#include "TargetProperties.inc" enum { - ePropertyStepInAvoidsNoDebug, - ePropertyStepOutAvoidsNoDebug, - ePropertyStepAvoidRegex, - ePropertyStepAvoidLibraries, - ePropertyEnableThreadTrace, - ePropertyMaxBacktraceDepth +#define LLDB_PROPERTIES_thread +#include "TargetPropertiesEnum.inc" }; class ThreadOptionValueProperties : public OptionValueProperties { @@ -125,7 +107,7 @@ ThreadProperties::ThreadProperties(bool is_global) : Properties() { if (is_global) { m_collection_sp = std::make_shared<ThreadOptionValueProperties>(ConstString("thread")); - m_collection_sp->Initialize(g_properties); + m_collection_sp->Initialize(g_thread_properties); } else m_collection_sp = std::make_shared<ThreadOptionValueProperties>( Thread::GetGlobalProperties().get()); @@ -150,25 +132,25 @@ FileSpecList ThreadProperties::GetLibrariesToAvoid() const { bool ThreadProperties::GetTraceEnabledState() const { const uint32_t idx = ePropertyEnableThreadTrace; return m_collection_sp->GetPropertyAtIndexAsBoolean( - nullptr, idx, g_properties[idx].default_uint_value != 0); + nullptr, idx, g_thread_properties[idx].default_uint_value != 0); } bool ThreadProperties::GetStepInAvoidsNoDebug() const { const uint32_t idx = ePropertyStepInAvoidsNoDebug; return m_collection_sp->GetPropertyAtIndexAsBoolean( - nullptr, idx, g_properties[idx].default_uint_value != 0); + nullptr, idx, g_thread_properties[idx].default_uint_value != 0); } bool ThreadProperties::GetStepOutAvoidsNoDebug() const { const uint32_t idx = ePropertyStepOutAvoidsNoDebug; return m_collection_sp->GetPropertyAtIndexAsBoolean( - nullptr, idx, g_properties[idx].default_uint_value != 0); + nullptr, idx, g_thread_properties[idx].default_uint_value != 0); } uint64_t ThreadProperties::GetMaxBacktraceDepth() const { const uint32_t idx = ePropertyMaxBacktraceDepth; return m_collection_sp->GetPropertyAtIndexAsUInt64( - nullptr, idx, g_properties[idx].default_uint_value != 0); + nullptr, idx, g_thread_properties[idx].default_uint_value != 0); } // Thread Event Data @@ -256,9 +238,8 @@ Thread::Thread(Process &process, lldb::tid_t tid, bool use_invalid_index_id) m_override_should_notify(eLazyBoolCalculate), m_extended_info_fetched(false), m_extended_info() { Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_OBJECT)); - if (log) - log->Printf("%p Thread::Thread(tid = 0x%4.4" PRIx64 ")", - static_cast<void *>(this), GetID()); + LLDB_LOGF(log, "%p Thread::Thread(tid = 0x%4.4" PRIx64 ")", + static_cast<void *>(this), GetID()); CheckInWithManager(); @@ -267,9 +248,8 @@ Thread::Thread(Process &process, lldb::tid_t tid, bool use_invalid_index_id) Thread::~Thread() { Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_OBJECT)); - if (log) - log->Printf("%p Thread::~Thread(tid = 0x%4.4" PRIx64 ")", - static_cast<void *>(this), GetID()); + LLDB_LOGF(log, "%p Thread::~Thread(tid = 0x%4.4" PRIx64 ")", + static_cast<void *>(this), GetID()); /// If you hit this assert, it means your derived class forgot to call /// DoDestroy in its destructor. assert(m_destroy_called); @@ -411,6 +391,11 @@ lldb::StopInfoSP Thread::GetStopInfo() { } } +void Thread::CalculatePublicStopInfo() { + ResetStopInfo(); + SetStopInfo(GetStopInfo()); +} + lldb::StopInfoSP Thread::GetPrivateStopInfo() { if (m_destroy_called) return m_stop_info_sp; @@ -490,11 +475,10 @@ void Thread::SetStopInfo(const lldb::StopInfoSP &stop_info_sp) { else m_stop_info_stop_id = UINT32_MAX; Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_THREAD)); - if (log) - log->Printf("%p: tid = 0x%" PRIx64 ": stop info = %s (stop_id = %u)", - static_cast<void *>(this), GetID(), - stop_info_sp ? stop_info_sp->GetDescription() : "<NULL>", - m_stop_info_stop_id); + LLDB_LOGF(log, "%p: tid = 0x%" PRIx64 ": stop info = %s (stop_id = %u)", + static_cast<void *>(this), GetID(), + stop_info_sp ? stop_info_sp->GetDescription() : "<NULL>", + m_stop_info_stop_id); } void Thread::SetShouldReportStop(Vote vote) { @@ -721,18 +705,18 @@ bool Thread::ShouldStop(Event *event_ptr) { Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_STEP)); if (GetResumeState() == eStateSuspended) { - if (log) - log->Printf("Thread::%s for tid = 0x%4.4" PRIx64 " 0x%4.4" PRIx64 - ", should_stop = 0 (ignore since thread was suspended)", - __FUNCTION__, GetID(), GetProtocolID()); + LLDB_LOGF(log, + "Thread::%s for tid = 0x%4.4" PRIx64 " 0x%4.4" PRIx64 + ", should_stop = 0 (ignore since thread was suspended)", + __FUNCTION__, GetID(), GetProtocolID()); return false; } if (GetTemporaryResumeState() == eStateSuspended) { - if (log) - log->Printf("Thread::%s for tid = 0x%4.4" PRIx64 " 0x%4.4" PRIx64 - ", should_stop = 0 (ignore since thread was suspended)", - __FUNCTION__, GetID(), GetProtocolID()); + LLDB_LOGF(log, + "Thread::%s for tid = 0x%4.4" PRIx64 " 0x%4.4" PRIx64 + ", should_stop = 0 (ignore since thread was suspended)", + __FUNCTION__, GetID(), GetProtocolID()); return false; } @@ -740,28 +724,28 @@ bool Thread::ShouldStop(Event *event_ptr) { // thread caused the process to stop. NOTE: this must take place before the // plan is moved from the current plan stack to the completed plan stack. if (!ThreadStoppedForAReason()) { - if (log) - log->Printf("Thread::%s for tid = 0x%4.4" PRIx64 " 0x%4.4" PRIx64 - ", pc = 0x%16.16" PRIx64 - ", should_stop = 0 (ignore since no stop reason)", - __FUNCTION__, GetID(), GetProtocolID(), - GetRegisterContext() ? GetRegisterContext()->GetPC() - : LLDB_INVALID_ADDRESS); + LLDB_LOGF(log, + "Thread::%s for tid = 0x%4.4" PRIx64 " 0x%4.4" PRIx64 + ", pc = 0x%16.16" PRIx64 + ", should_stop = 0 (ignore since no stop reason)", + __FUNCTION__, GetID(), GetProtocolID(), + GetRegisterContext() ? GetRegisterContext()->GetPC() + : LLDB_INVALID_ADDRESS); return false; } if (log) { - log->Printf("Thread::%s(%p) for tid = 0x%4.4" PRIx64 " 0x%4.4" PRIx64 - ", pc = 0x%16.16" PRIx64, - __FUNCTION__, static_cast<void *>(this), GetID(), - GetProtocolID(), - GetRegisterContext() ? GetRegisterContext()->GetPC() - : LLDB_INVALID_ADDRESS); - log->Printf("^^^^^^^^ Thread::ShouldStop Begin ^^^^^^^^"); + LLDB_LOGF(log, + "Thread::%s(%p) for tid = 0x%4.4" PRIx64 " 0x%4.4" PRIx64 + ", pc = 0x%16.16" PRIx64, + __FUNCTION__, static_cast<void *>(this), GetID(), GetProtocolID(), + GetRegisterContext() ? GetRegisterContext()->GetPC() + : LLDB_INVALID_ADDRESS); + LLDB_LOGF(log, "^^^^^^^^ Thread::ShouldStop Begin ^^^^^^^^"); StreamString s; s.IndentMore(); DumpThreadPlans(&s); - log->Printf("Plan stack initial state:\n%s", s.GetData()); + LLDB_LOGF(log, "Plan stack initial state:\n%s", s.GetData()); } // The top most plan always gets to do the trace log... @@ -774,9 +758,8 @@ bool Thread::ShouldStop(Event *event_ptr) { StopInfoSP private_stop_info(GetPrivateStopInfo()); if (private_stop_info && !private_stop_info->ShouldStopSynchronous(event_ptr)) { - if (log) - log->Printf("StopInfo::ShouldStop async callback says we should not " - "stop, returning ShouldStop of false."); + LLDB_LOGF(log, "StopInfo::ShouldStop async callback says we should not " + "stop, returning ShouldStop of false."); return false; } @@ -840,15 +823,13 @@ bool Thread::ShouldStop(Event *event_ptr) { if (!done_processing_current_plan) { bool over_ride_stop = current_plan->ShouldAutoContinue(event_ptr); - if (log) - log->Printf("Plan %s explains stop, auto-continue %i.", - current_plan->GetName(), over_ride_stop); + LLDB_LOGF(log, "Plan %s explains stop, auto-continue %i.", + current_plan->GetName(), over_ride_stop); // We're starting from the base plan, so just let it decide; if (PlanIsBasePlan(current_plan)) { should_stop = current_plan->ShouldStop(event_ptr); - if (log) - log->Printf("Base plan says should stop: %i.", should_stop); + LLDB_LOGF(log, "Base plan says should stop: %i.", should_stop); } else { // Otherwise, don't let the base plan override what the other plans say // to do, since presumably if there were other plans they would know what @@ -858,9 +839,8 @@ bool Thread::ShouldStop(Event *event_ptr) { break; should_stop = current_plan->ShouldStop(event_ptr); - if (log) - log->Printf("Plan %s should stop: %d.", current_plan->GetName(), - should_stop); + LLDB_LOGF(log, "Plan %s should stop: %d.", current_plan->GetName(), + should_stop); if (current_plan->MischiefManaged()) { if (should_stop) current_plan->WillStop(); @@ -907,10 +887,10 @@ bool Thread::ShouldStop(Event *event_ptr) { plan_ptr = GetPreviousPlan(examined_plan); if (stale) { - if (log) - log->Printf( - "Plan %s being discarded in cleanup, it says it is already done.", - examined_plan->GetName()); + LLDB_LOGF( + log, + "Plan %s being discarded in cleanup, it says it is already done.", + examined_plan->GetName()); while (GetCurrentPlan() != examined_plan) { DiscardPlan(); } @@ -929,9 +909,9 @@ bool Thread::ShouldStop(Event *event_ptr) { StreamString s; s.IndentMore(); DumpThreadPlans(&s); - log->Printf("Plan stack final state:\n%s", s.GetData()); - log->Printf("vvvvvvvv Thread::ShouldStop End (returning %i) vvvvvvvv", - should_stop); + LLDB_LOGF(log, "Plan stack final state:\n%s", s.GetData()); + LLDB_LOGF(log, "vvvvvvvv Thread::ShouldStop End (returning %i) vvvvvvvv", + should_stop); } return should_stop; } @@ -943,37 +923,36 @@ Vote Thread::ShouldReportStop(Event *event_ptr) { Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_STEP)); if (thread_state == eStateSuspended || thread_state == eStateInvalid) { - if (log) - log->Printf("Thread::ShouldReportStop() tid = 0x%4.4" PRIx64 - ": returning vote %i (state was suspended or invalid)", - GetID(), eVoteNoOpinion); + LLDB_LOGF(log, + "Thread::ShouldReportStop() tid = 0x%4.4" PRIx64 + ": returning vote %i (state was suspended or invalid)", + GetID(), eVoteNoOpinion); return eVoteNoOpinion; } if (temp_thread_state == eStateSuspended || temp_thread_state == eStateInvalid) { - if (log) - log->Printf( - "Thread::ShouldReportStop() tid = 0x%4.4" PRIx64 - ": returning vote %i (temporary state was suspended or invalid)", - GetID(), eVoteNoOpinion); + LLDB_LOGF(log, + "Thread::ShouldReportStop() tid = 0x%4.4" PRIx64 + ": returning vote %i (temporary state was suspended or invalid)", + GetID(), eVoteNoOpinion); return eVoteNoOpinion; } if (!ThreadStoppedForAReason()) { - if (log) - log->Printf("Thread::ShouldReportStop() tid = 0x%4.4" PRIx64 - ": returning vote %i (thread didn't stop for a reason.)", - GetID(), eVoteNoOpinion); + LLDB_LOGF(log, + "Thread::ShouldReportStop() tid = 0x%4.4" PRIx64 + ": returning vote %i (thread didn't stop for a reason.)", + GetID(), eVoteNoOpinion); return eVoteNoOpinion; } if (m_completed_plan_stack.size() > 0) { // Don't use GetCompletedPlan here, since that suppresses private plans. - if (log) - log->Printf("Thread::ShouldReportStop() tid = 0x%4.4" PRIx64 - ": returning vote for complete stack's back plan", - GetID()); + LLDB_LOGF(log, + "Thread::ShouldReportStop() tid = 0x%4.4" PRIx64 + ": returning vote for complete stack's back plan", + GetID()); return m_completed_plan_stack.back()->ShouldReportStop(event_ptr); } else { Vote thread_vote = eVoteNoOpinion; @@ -988,10 +967,10 @@ Vote Thread::ShouldReportStop(Event *event_ptr) { else plan_ptr = GetPreviousPlan(plan_ptr); } - if (log) - log->Printf("Thread::ShouldReportStop() tid = 0x%4.4" PRIx64 - ": returning vote %i for current plan", - GetID(), thread_vote); + LLDB_LOGF(log, + "Thread::ShouldReportStop() tid = 0x%4.4" PRIx64 + ": returning vote %i for current plan", + GetID(), thread_vote); return thread_vote; } @@ -1007,21 +986,21 @@ Vote Thread::ShouldReportRun(Event *event_ptr) { Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_STEP)); if (m_completed_plan_stack.size() > 0) { // Don't use GetCompletedPlan here, since that suppresses private plans. - if (log) - log->Printf("Current Plan for thread %d(%p) (0x%4.4" PRIx64 - ", %s): %s being asked whether we should report run.", - GetIndexID(), static_cast<void *>(this), GetID(), - StateAsCString(GetTemporaryResumeState()), - m_completed_plan_stack.back()->GetName()); + LLDB_LOGF(log, + "Current Plan for thread %d(%p) (0x%4.4" PRIx64 + ", %s): %s being asked whether we should report run.", + GetIndexID(), static_cast<void *>(this), GetID(), + StateAsCString(GetTemporaryResumeState()), + m_completed_plan_stack.back()->GetName()); return m_completed_plan_stack.back()->ShouldReportRun(event_ptr); } else { - if (log) - log->Printf("Current Plan for thread %d(%p) (0x%4.4" PRIx64 - ", %s): %s being asked whether we should report run.", - GetIndexID(), static_cast<void *>(this), GetID(), - StateAsCString(GetTemporaryResumeState()), - GetCurrentPlan()->GetName()); + LLDB_LOGF(log, + "Current Plan for thread %d(%p) (0x%4.4" PRIx64 + ", %s): %s being asked whether we should report run.", + GetIndexID(), static_cast<void *>(this), GetID(), + StateAsCString(GetTemporaryResumeState()), + GetCurrentPlan()->GetName()); return GetCurrentPlan()->ShouldReportRun(event_ptr); } @@ -1048,9 +1027,9 @@ void Thread::PushPlan(ThreadPlanSP &thread_plan_sp) { if (log) { StreamString s; thread_plan_sp->GetDescription(&s, lldb::eDescriptionLevelFull); - log->Printf("Thread::PushPlan(0x%p): \"%s\", tid = 0x%4.4" PRIx64 ".", - static_cast<void *>(this), s.GetData(), - thread_plan_sp->GetThread().GetID()); + LLDB_LOGF(log, "Thread::PushPlan(0x%p): \"%s\", tid = 0x%4.4" PRIx64 ".", + static_cast<void *>(this), s.GetData(), + thread_plan_sp->GetThread().GetID()); } } } @@ -1063,8 +1042,8 @@ void Thread::PopPlan() { else { ThreadPlanSP &plan = m_plan_stack.back(); if (log) { - log->Printf("Popping plan: \"%s\", tid = 0x%4.4" PRIx64 ".", - plan->GetName(), plan->GetThread().GetID()); + LLDB_LOGF(log, "Popping plan: \"%s\", tid = 0x%4.4" PRIx64 ".", + plan->GetName(), plan->GetThread().GetID()); } m_completed_plan_stack.push_back(plan); plan->WillPop(); @@ -1076,9 +1055,8 @@ void Thread::DiscardPlan() { Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_STEP)); if (m_plan_stack.size() > 1) { ThreadPlanSP &plan = m_plan_stack.back(); - if (log) - log->Printf("Discarding plan: \"%s\", tid = 0x%4.4" PRIx64 ".", - plan->GetName(), plan->GetThread().GetID()); + LLDB_LOGF(log, "Discarding plan: \"%s\", tid = 0x%4.4" PRIx64 ".", + plan->GetName(), plan->GetThread().GetID()); m_discarded_plan_stack.push_back(plan); plan->WillPop(); @@ -1252,10 +1230,10 @@ void Thread::DiscardThreadPlansUpToPlan(lldb::ThreadPlanSP &up_to_plan_sp) { void Thread::DiscardThreadPlansUpToPlan(ThreadPlan *up_to_plan_ptr) { Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_STEP)); - if (log) - log->Printf("Discarding thread plans for thread tid = 0x%4.4" PRIx64 - ", up to %p", - GetID(), static_cast<void *>(up_to_plan_ptr)); + LLDB_LOGF(log, + "Discarding thread plans for thread tid = 0x%4.4" PRIx64 + ", up to %p", + GetID(), static_cast<void *>(up_to_plan_ptr)); int stack_size = m_plan_stack.size(); @@ -1285,9 +1263,10 @@ void Thread::DiscardThreadPlansUpToPlan(ThreadPlan *up_to_plan_ptr) { void Thread::DiscardThreadPlans(bool force) { Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_STEP)); if (log) { - log->Printf("Discarding thread plans for thread (tid = 0x%4.4" PRIx64 - ", force %d)", - GetID(), force); + LLDB_LOGF(log, + "Discarding thread plans for thread (tid = 0x%4.4" PRIx64 + ", force %d)", + GetID(), force); } if (force) { @@ -1504,9 +1483,18 @@ ThreadPlanSP Thread::QueueThreadPlanForStepUntil( } lldb::ThreadPlanSP Thread::QueueThreadPlanForStepScripted( - bool abort_other_plans, const char *class_name, bool stop_other_threads, + bool abort_other_plans, const char *class_name, + StructuredData::ObjectSP extra_args_sp, bool stop_other_threads, Status &status) { - ThreadPlanSP thread_plan_sp(new ThreadPlanPython(*this, class_name)); + + StructuredDataImpl *extra_args_impl = nullptr; + if (extra_args_sp) { + extra_args_impl = new StructuredDataImpl(); + extra_args_impl->SetObjectSP(extra_args_sp); + } + + ThreadPlanSP thread_plan_sp(new ThreadPlanPython(*this, class_name, + extra_args_impl)); status = QueueThreadPlan(thread_plan_sp, abort_other_plans); return thread_plan_sp; @@ -2062,6 +2050,7 @@ Unwind *Thread::GetUnwinder() { case llvm::Triple::x86: case llvm::Triple::arm: case llvm::Triple::aarch64: + case llvm::Triple::aarch64_32: case llvm::Triple::thumb: case llvm::Triple::mips: case llvm::Triple::mipsel: @@ -2072,6 +2061,7 @@ Unwind *Thread::GetUnwinder() { case llvm::Triple::ppc64le: case llvm::Triple::systemz: case llvm::Triple::hexagon: + case llvm::Triple::arc: m_unwinder_up.reset(new UnwindLLDB(*this)); break; diff --git a/source/Target/ThreadList.cpp b/source/Target/ThreadList.cpp index afdfda3b0ae1..183b39c2cfa9 100644 --- a/source/Target/ThreadList.cpp +++ b/source/Target/ThreadList.cpp @@ -267,10 +267,11 @@ bool ThreadList::ShouldStop(Event *event_ptr) { if (log) { log->PutCString(""); - log->Printf("ThreadList::%s: %" PRIu64 " threads, %" PRIu64 - " unsuspended threads", - __FUNCTION__, (uint64_t)m_threads.size(), - (uint64_t)threads_copy.size()); + LLDB_LOGF(log, + "ThreadList::%s: %" PRIu64 " threads, %" PRIu64 + " unsuspended threads", + __FUNCTION__, (uint64_t)m_threads.size(), + (uint64_t)threads_copy.size()); } bool did_anybody_stop_for_a_reason = false; @@ -279,10 +280,9 @@ bool ThreadList::ShouldStop(Event *event_ptr) { // what. Otherwise, presume we won't stop. bool should_stop = false; if (Process::ProcessEventData::GetInterruptedFromEvent(event_ptr)) { - if (log) - log->Printf( - "ThreadList::%s handling interrupt event, should stop set to true", - __FUNCTION__); + LLDB_LOGF( + log, "ThreadList::%s handling interrupt event, should stop set to true", + __FUNCTION__); should_stop = true; } @@ -334,15 +334,14 @@ bool ThreadList::ShouldStop(Event *event_ptr) { if (!should_stop && !did_anybody_stop_for_a_reason) { should_stop = true; - if (log) - log->Printf("ThreadList::%s we stopped but no threads had a stop reason, " - "overriding should_stop and stopping.", - __FUNCTION__); + LLDB_LOGF(log, + "ThreadList::%s we stopped but no threads had a stop reason, " + "overriding should_stop and stopping.", + __FUNCTION__); } - if (log) - log->Printf("ThreadList::%s overall should_stop = %i", __FUNCTION__, - should_stop); + LLDB_LOGF(log, "ThreadList::%s overall should_stop = %i", __FUNCTION__, + should_stop); if (should_stop) { for (pos = threads_copy.begin(); pos != end; ++pos) { @@ -363,9 +362,8 @@ Vote ThreadList::ShouldReportStop(Event *event_ptr) { Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_STEP)); - if (log) - log->Printf("ThreadList::%s %" PRIu64 " threads", __FUNCTION__, - (uint64_t)m_threads.size()); + LLDB_LOGF(log, "ThreadList::%s %" PRIu64 " threads", __FUNCTION__, + (uint64_t)m_threads.size()); // Run through the threads and ask whether we should report this event. For // stopping, a YES vote wins over everything. A NO vote wins over NO @@ -430,10 +428,10 @@ Vote ThreadList::ShouldReportRun(Event *event_ptr) { result = eVoteYes; break; case eVoteNo: - if (log) - log->Printf("ThreadList::ShouldReportRun() thread %d (0x%4.4" PRIx64 - ") says don't report.", - (*pos)->GetIndexID(), (*pos)->GetID()); + LLDB_LOGF(log, + "ThreadList::ShouldReportRun() thread %d (0x%4.4" PRIx64 + ") says don't report.", + (*pos)->GetIndexID(), (*pos)->GetID()); result = eVoteNo; break; } @@ -464,8 +462,9 @@ void ThreadList::RefreshStateAfterStop() { Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_STEP)); if (log && log->GetVerbose()) - log->Printf("Turning off notification of new threads while single stepping " - "a thread."); + LLDB_LOGF(log, + "Turning off notification of new threads while single stepping " + "a thread."); collection::iterator pos, end = m_threads.end(); for (pos = m_threads.begin(); pos != end; ++pos) @@ -517,14 +516,14 @@ bool ThreadList::WillResume() { if (wants_solo_run) { Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_STEP)); if (log && log->GetVerbose()) - log->Printf("Turning on notification of new threads while single " - "stepping a thread."); + LLDB_LOGF(log, "Turning on notification of new threads while single " + "stepping a thread."); m_process->StartNoticingNewThreads(); } else { Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_STEP)); if (log && log->GetVerbose()) - log->Printf("Turning off notification of new threads while single " - "stepping a thread."); + LLDB_LOGF(log, "Turning off notification of new threads while single " + "stepping a thread."); m_process->StopNoticingNewThreads(); } diff --git a/source/Target/ThreadPlan.cpp b/source/Target/ThreadPlan.cpp index 1d8cc18db4d6..ba56f8d15d8a 100644 --- a/source/Target/ThreadPlan.cpp +++ b/source/Target/ThreadPlan.cpp @@ -108,7 +108,8 @@ bool ThreadPlan::WillResume(StateType resume_state, bool current_plan) { addr_t pc = reg_ctx->GetPC(); addr_t sp = reg_ctx->GetSP(); addr_t fp = reg_ctx->GetFP(); - log->Printf( + LLDB_LOGF( + log, "%s Thread #%u (0x%p): tid = 0x%4.4" PRIx64 ", pc = 0x%8.8" PRIx64 ", sp = 0x%8.8" PRIx64 ", fp = 0x%8.8" PRIx64 ", " "plan = '%s', state = %s, stop others = %d", diff --git a/source/Target/ThreadPlanBase.cpp b/source/Target/ThreadPlanBase.cpp index 9cd4bcb455be..821643d4bce5 100644 --- a/source/Target/ThreadPlanBase.cpp +++ b/source/Target/ThreadPlanBase.cpp @@ -92,11 +92,11 @@ bool ThreadPlanBase::ShouldStop(Event *event_ptr) { // If we are going to stop for a breakpoint, then unship the other // plans at this point. Don't force the discard, however, so Master // plans can stay in place if they want to. - if (log) - log->Printf( - "Base plan discarding thread plans for thread tid = 0x%4.4" PRIx64 - " (breakpoint hit.)", - m_thread.GetID()); + LLDB_LOGF( + log, + "Base plan discarding thread plans for thread tid = 0x%4.4" PRIx64 + " (breakpoint hit.)", + m_thread.GetID()); m_thread.DiscardThreadPlans(false); return true; } @@ -122,11 +122,11 @@ bool ThreadPlanBase::ShouldStop(Event *event_ptr) { // If we crashed, discard thread plans and stop. Don't force the // discard, however, since on rerun the target may clean up this // exception and continue normally from there. - if (log) - log->Printf( - "Base plan discarding thread plans for thread tid = 0x%4.4" PRIx64 - " (exception: %s)", - m_thread.GetID(), stop_info_sp->GetDescription()); + LLDB_LOGF( + log, + "Base plan discarding thread plans for thread tid = 0x%4.4" PRIx64 + " (exception: %s)", + m_thread.GetID(), stop_info_sp->GetDescription()); m_thread.DiscardThreadPlans(false); return true; @@ -134,22 +134,22 @@ bool ThreadPlanBase::ShouldStop(Event *event_ptr) { // If we crashed, discard thread plans and stop. Don't force the // discard, however, since on rerun the target may clean up this // exception and continue normally from there. - if (log) - log->Printf( - "Base plan discarding thread plans for thread tid = 0x%4.4" PRIx64 - " (exec.)", - m_thread.GetID()); + LLDB_LOGF( + log, + "Base plan discarding thread plans for thread tid = 0x%4.4" PRIx64 + " (exec.)", + m_thread.GetID()); m_thread.DiscardThreadPlans(false); return true; case eStopReasonThreadExiting: case eStopReasonSignal: if (stop_info_sp->ShouldStop(event_ptr)) { - if (log) - log->Printf( - "Base plan discarding thread plans for thread tid = 0x%4.4" PRIx64 - " (signal: %s)", - m_thread.GetID(), stop_info_sp->GetDescription()); + LLDB_LOGF( + log, + "Base plan discarding thread plans for thread tid = 0x%4.4" PRIx64 + " (signal: %s)", + m_thread.GetID(), stop_info_sp->GetDescription()); m_thread.DiscardThreadPlans(false); return true; } else { diff --git a/source/Target/ThreadPlanCallFunction.cpp b/source/Target/ThreadPlanCallFunction.cpp index 68d771c37946..23d114e30990 100644 --- a/source/Target/ThreadPlanCallFunction.cpp +++ b/source/Target/ThreadPlanCallFunction.cpp @@ -59,46 +59,21 @@ bool ThreadPlanCallFunction::ConstructorSetup( m_constructor_errors.Printf( "Trying to put the stack in unreadable memory at: 0x%" PRIx64 ".", m_function_sp); - if (log) - log->Printf("ThreadPlanCallFunction(%p): %s.", static_cast<void *>(this), - m_constructor_errors.GetData()); + LLDB_LOGF(log, "ThreadPlanCallFunction(%p): %s.", static_cast<void *>(this), + m_constructor_errors.GetData()); return false; } - Module *exe_module = GetTarget().GetExecutableModulePointer(); - - if (exe_module == nullptr) { + llvm::Expected<Address> start_address = GetTarget().GetEntryPointAddress(); + if (!start_address) { m_constructor_errors.Printf( - "Can't execute code without an executable module."); - if (log) - log->Printf("ThreadPlanCallFunction(%p): %s.", static_cast<void *>(this), - m_constructor_errors.GetData()); + "%s", llvm::toString(start_address.takeError()).c_str()); + LLDB_LOGF(log, "ThreadPlanCallFunction(%p): %s.", static_cast<void *>(this), + m_constructor_errors.GetData()); return false; - } else { - ObjectFile *objectFile = exe_module->GetObjectFile(); - if (!objectFile) { - m_constructor_errors.Printf( - "Could not find object file for module \"%s\".", - exe_module->GetFileSpec().GetFilename().AsCString()); - - if (log) - log->Printf("ThreadPlanCallFunction(%p): %s.", - static_cast<void *>(this), m_constructor_errors.GetData()); - return false; - } - - m_start_addr = objectFile->GetEntryPointAddress(); - if (!m_start_addr.IsValid()) { - m_constructor_errors.Printf( - "Could not find entry point address for executable module \"%s\".", - exe_module->GetFileSpec().GetFilename().AsCString()); - if (log) - log->Printf("ThreadPlanCallFunction(%p): %s.", - static_cast<void *>(this), m_constructor_errors.GetData()); - return false; - } } + m_start_addr = *start_address; start_load_addr = m_start_addr.GetLoadAddress(&GetTarget()); // Checkpoint the thread state so we can restore it later. @@ -109,9 +84,8 @@ bool ThreadPlanCallFunction::ConstructorSetup( if (!thread.CheckpointThreadState(m_stored_thread_state)) { m_constructor_errors.Printf("Setting up ThreadPlanCallFunction, failed to " "checkpoint thread state."); - if (log) - log->Printf("ThreadPlanCallFunction(%p): %s.", static_cast<void *>(this), - m_constructor_errors.GetData()); + LLDB_LOGF(log, "ThreadPlanCallFunction(%p): %s.", static_cast<void *>(this), + m_constructor_errors.GetData()); return false; } function_load_addr = m_function_addr.GetLoadAddress(&GetTarget()); @@ -196,10 +170,10 @@ void ThreadPlanCallFunction::DoTakedown(bool success) { if (!m_valid) { // Don't call DoTakedown if we were never valid to begin with. - if (log) - log->Printf("ThreadPlanCallFunction(%p): Log called on " - "ThreadPlanCallFunction that was never valid.", - static_cast<void *>(this)); + LLDB_LOGF(log, + "ThreadPlanCallFunction(%p): Log called on " + "ThreadPlanCallFunction that was never valid.", + static_cast<void *>(this)); return; } @@ -207,20 +181,20 @@ void ThreadPlanCallFunction::DoTakedown(bool success) { if (success) { SetReturnValue(); } - if (log) - log->Printf("ThreadPlanCallFunction(%p): DoTakedown called for thread " - "0x%4.4" PRIx64 ", m_valid: %d complete: %d.\n", - static_cast<void *>(this), m_thread.GetID(), m_valid, - IsPlanComplete()); + LLDB_LOGF(log, + "ThreadPlanCallFunction(%p): DoTakedown called for thread " + "0x%4.4" PRIx64 ", m_valid: %d complete: %d.\n", + static_cast<void *>(this), m_thread.GetID(), m_valid, + IsPlanComplete()); m_takedown_done = true; m_stop_address = m_thread.GetStackFrameAtIndex(0)->GetRegisterContext()->GetPC(); m_real_stop_info_sp = GetPrivateStopInfo(); if (!m_thread.RestoreRegisterStateFromCheckpoint(m_stored_thread_state)) { - if (log) - log->Printf("ThreadPlanCallFunction(%p): DoTakedown failed to restore " - "register state", - static_cast<void *>(this)); + LLDB_LOGF(log, + "ThreadPlanCallFunction(%p): DoTakedown failed to restore " + "register state", + static_cast<void *>(this)); } SetPlanComplete(success); ClearBreakpoints(); @@ -228,11 +202,11 @@ void ThreadPlanCallFunction::DoTakedown(bool success) { ReportRegisterState("Restoring thread state after function call. " "Restored register state:"); } else { - if (log) - log->Printf("ThreadPlanCallFunction(%p): DoTakedown called as no-op for " - "thread 0x%4.4" PRIx64 ", m_valid: %d complete: %d.\n", - static_cast<void *>(this), m_thread.GetID(), m_valid, - IsPlanComplete()); + LLDB_LOGF(log, + "ThreadPlanCallFunction(%p): DoTakedown called as no-op for " + "thread 0x%4.4" PRIx64 ", m_valid: %d complete: %d.\n", + static_cast<void *>(this), m_thread.GetID(), m_valid, + IsPlanComplete()); } } @@ -288,10 +262,9 @@ bool ThreadPlanCallFunction::DoPlanExplainsStop(Event *event_ptr) { stop_reason = eStopReasonNone; else stop_reason = m_real_stop_info_sp->GetStopReason(); - if (log) - log->Printf( - "ThreadPlanCallFunction::PlanExplainsStop: Got stop reason - %s.", - Thread::StopReasonAsCString(stop_reason)); + LLDB_LOGF(log, + "ThreadPlanCallFunction::PlanExplainsStop: Got stop reason - %s.", + Thread::StopReasonAsCString(stop_reason)); if (stop_reason == eStopReasonBreakpoint && BreakpointsExplainStop()) return true; @@ -300,9 +273,8 @@ bool ThreadPlanCallFunction::DoPlanExplainsStop(Event *event_ptr) { // then we should not consider ourselves complete. Return true to // acknowledge the stop. if (Process::ProcessEventData::GetInterruptedFromEvent(event_ptr)) { - if (log) - log->Printf("ThreadPlanCallFunction::PlanExplainsStop: The event is an " - "Interrupt, returning true."); + LLDB_LOGF(log, "ThreadPlanCallFunction::PlanExplainsStop: The event is an " + "Interrupt, returning true."); return true; } // We control breakpoints separately from other "stop reasons." So first, @@ -321,10 +293,10 @@ bool ThreadPlanCallFunction::DoPlanExplainsStop(Event *event_ptr) { bool is_internal = true; for (uint32_t i = 0; i < num_owners; i++) { Breakpoint &bp = bp_site_sp->GetOwnerAtIndex(i)->GetBreakpoint(); - if (log) - log->Printf("ThreadPlanCallFunction::PlanExplainsStop: hit " - "breakpoint %d while calling function", - bp.GetID()); + LLDB_LOGF(log, + "ThreadPlanCallFunction::PlanExplainsStop: hit " + "breakpoint %d while calling function", + bp.GetID()); if (!bp.IsInternal()) { is_internal = false; @@ -332,25 +304,23 @@ bool ThreadPlanCallFunction::DoPlanExplainsStop(Event *event_ptr) { } } if (is_internal) { - if (log) - log->Printf("ThreadPlanCallFunction::PlanExplainsStop hit an " - "internal breakpoint, not stopping."); + LLDB_LOGF(log, "ThreadPlanCallFunction::PlanExplainsStop hit an " + "internal breakpoint, not stopping."); return false; } } if (m_ignore_breakpoints) { - if (log) - log->Printf("ThreadPlanCallFunction::PlanExplainsStop: we are ignoring " - "breakpoints, overriding breakpoint stop info ShouldStop, " - "returning true"); + LLDB_LOGF(log, + "ThreadPlanCallFunction::PlanExplainsStop: we are ignoring " + "breakpoints, overriding breakpoint stop info ShouldStop, " + "returning true"); m_real_stop_info_sp->OverrideShouldStop(false); return true; } else { - if (log) - log->Printf("ThreadPlanCallFunction::PlanExplainsStop: we are not " - "ignoring breakpoints, overriding breakpoint stop info " - "ShouldStop, returning true"); + LLDB_LOGF(log, "ThreadPlanCallFunction::PlanExplainsStop: we are not " + "ignoring breakpoints, overriding breakpoint stop info " + "ShouldStop, returning true"); m_real_stop_info_sp->OverrideShouldStop(true); return false; } @@ -418,9 +388,8 @@ bool ThreadPlanCallFunction::MischiefManaged() { Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_STEP)); if (IsPlanComplete()) { - if (log) - log->Printf("ThreadPlanCallFunction(%p): Completed call function plan.", - static_cast<void *>(this)); + LLDB_LOGF(log, "ThreadPlanCallFunction(%p): Completed call function plan.", + static_cast<void *>(this)); ThreadPlan::MischiefManaged(); return true; @@ -469,9 +438,8 @@ bool ThreadPlanCallFunction::BreakpointsExplainStop() { m_objc_language_runtime->ExceptionBreakpointsExplainStop( stop_info_sp))) { Log *log(lldb_private::GetLogIfAnyCategoriesSet(LIBLLDB_LOG_STEP)); - if (log) - log->Printf("ThreadPlanCallFunction::BreakpointsExplainStop - Hit an " - "exception breakpoint, setting plan complete."); + LLDB_LOGF(log, "ThreadPlanCallFunction::BreakpointsExplainStop - Hit an " + "exception breakpoint, setting plan complete."); SetPlanComplete(false); diff --git a/source/Target/ThreadPlanCallUserExpression.cpp b/source/Target/ThreadPlanCallUserExpression.cpp index 864808a4b5ea..436938c8f207 100644 --- a/source/Target/ThreadPlanCallUserExpression.cpp +++ b/source/Target/ThreadPlanCallUserExpression.cpp @@ -69,9 +69,8 @@ bool ThreadPlanCallUserExpression::MischiefManaged() { Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_STEP)); if (IsPlanComplete()) { - if (log) - log->Printf("ThreadPlanCallFunction(%p): Completed call function plan.", - static_cast<void *>(this)); + LLDB_LOGF(log, "ThreadPlanCallFunction(%p): Completed call function plan.", + static_cast<void *>(this)); if (m_manage_materialization && PlanSucceeded() && m_user_expression_sp) { lldb::addr_t function_stack_top; diff --git a/source/Target/ThreadPlanPython.cpp b/source/Target/ThreadPlanPython.cpp index 8b30c4ea7cb1..df432a0af3da 100644 --- a/source/Target/ThreadPlanPython.cpp +++ b/source/Target/ThreadPlanPython.cpp @@ -25,10 +25,11 @@ using namespace lldb_private; // ThreadPlanPython -ThreadPlanPython::ThreadPlanPython(Thread &thread, const char *class_name) +ThreadPlanPython::ThreadPlanPython(Thread &thread, const char *class_name, + StructuredDataImpl *args_data) : ThreadPlan(ThreadPlan::eKindPython, "Python based Thread Plan", thread, eVoteNoOpinion, eVoteNoOpinion), - m_class_name(class_name), m_did_push(false) { + m_class_name(class_name), m_args_data(args_data), m_did_push(false) { SetIsMasterPlan(true); SetOkayToDiscard(true); SetPrivate(false); @@ -45,7 +46,9 @@ bool ThreadPlanPython::ValidatePlan(Stream *error) { if (!m_implementation_sp) { if (error) - error->Printf("Python thread plan does not have an implementation"); + error->Printf("Error constructing Python ThreadPlan: %s", + m_error_str.empty() ? "<unknown error>" + : m_error_str.c_str()); return false; } @@ -63,16 +66,16 @@ void ThreadPlanPython::DidPush() { .GetScriptInterpreter(); if (script_interp) { m_implementation_sp = script_interp->CreateScriptedThreadPlan( - m_class_name.c_str(), this->shared_from_this()); + m_class_name.c_str(), m_args_data, m_error_str, + this->shared_from_this()); } } } bool ThreadPlanPython::ShouldStop(Event *event_ptr) { Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_THREAD)); - if (log) - log->Printf("%s called on Python Thread Plan: %s )", LLVM_PRETTY_FUNCTION, - m_class_name.c_str()); + LLDB_LOGF(log, "%s called on Python Thread Plan: %s )", LLVM_PRETTY_FUNCTION, + m_class_name.c_str()); bool should_stop = true; if (m_implementation_sp) { @@ -93,9 +96,8 @@ bool ThreadPlanPython::ShouldStop(Event *event_ptr) { bool ThreadPlanPython::IsPlanStale() { Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_THREAD)); - if (log) - log->Printf("%s called on Python Thread Plan: %s )", LLVM_PRETTY_FUNCTION, - m_class_name.c_str()); + LLDB_LOGF(log, "%s called on Python Thread Plan: %s )", LLVM_PRETTY_FUNCTION, + m_class_name.c_str()); bool is_stale = true; if (m_implementation_sp) { @@ -116,9 +118,8 @@ bool ThreadPlanPython::IsPlanStale() { bool ThreadPlanPython::DoPlanExplainsStop(Event *event_ptr) { Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_THREAD)); - if (log) - log->Printf("%s called on Python Thread Plan: %s )", LLVM_PRETTY_FUNCTION, - m_class_name.c_str()); + LLDB_LOGF(log, "%s called on Python Thread Plan: %s )", LLVM_PRETTY_FUNCTION, + m_class_name.c_str()); bool explains_stop = true; if (m_implementation_sp) { @@ -139,9 +140,8 @@ bool ThreadPlanPython::DoPlanExplainsStop(Event *event_ptr) { bool ThreadPlanPython::MischiefManaged() { Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_THREAD)); - if (log) - log->Printf("%s called on Python Thread Plan: %s )", LLVM_PRETTY_FUNCTION, - m_class_name.c_str()); + LLDB_LOGF(log, "%s called on Python Thread Plan: %s )", LLVM_PRETTY_FUNCTION, + m_class_name.c_str()); bool mischief_managed = true; if (m_implementation_sp) { // I don't really need mischief_managed, since it's simpler to just call @@ -155,9 +155,8 @@ bool ThreadPlanPython::MischiefManaged() { lldb::StateType ThreadPlanPython::GetPlanRunState() { Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_THREAD)); - if (log) - log->Printf("%s called on Python Thread Plan: %s )", LLVM_PRETTY_FUNCTION, - m_class_name.c_str()); + LLDB_LOGF(log, "%s called on Python Thread Plan: %s )", LLVM_PRETTY_FUNCTION, + m_class_name.c_str()); lldb::StateType run_state = eStateRunning; if (m_implementation_sp) { ScriptInterpreter *script_interp = m_thread.GetProcess() @@ -188,8 +187,7 @@ void ThreadPlanPython::GetDescription(Stream *s, lldb::DescriptionLevel level) { bool ThreadPlanPython::WillStop() { Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_THREAD)); - if (log) - log->Printf("%s called on Python Thread Plan: %s )", LLVM_PRETTY_FUNCTION, - m_class_name.c_str()); + LLDB_LOGF(log, "%s called on Python Thread Plan: %s )", LLVM_PRETTY_FUNCTION, + m_class_name.c_str()); return true; } diff --git a/source/Target/ThreadPlanRunToAddress.cpp b/source/Target/ThreadPlanRunToAddress.cpp index a973bd112796..160743a9f3f8 100644 --- a/source/Target/ThreadPlanRunToAddress.cpp +++ b/source/Target/ThreadPlanRunToAddress.cpp @@ -182,8 +182,7 @@ bool ThreadPlanRunToAddress::MischiefManaged() { m_break_ids[i] = LLDB_INVALID_BREAK_ID; } } - if (log) - log->Printf("Completed run to address plan."); + LLDB_LOGF(log, "Completed run to address plan."); ThreadPlan::MischiefManaged(); return true; } else diff --git a/source/Target/ThreadPlanShouldStopHere.cpp b/source/Target/ThreadPlanShouldStopHere.cpp index a0b7072a1071..9599d8197b07 100644 --- a/source/Target/ThreadPlanShouldStopHere.cpp +++ b/source/Target/ThreadPlanShouldStopHere.cpp @@ -46,8 +46,8 @@ bool ThreadPlanShouldStopHere::InvokeShouldStopHereCallback( lldb::addr_t current_addr = m_owner->GetThread().GetRegisterContext()->GetPC(0); - log->Printf("ShouldStopHere callback returned %u from 0x%" PRIx64 ".", - should_stop_here, current_addr); + LLDB_LOGF(log, "ShouldStopHere callback returned %u from 0x%" PRIx64 ".", + should_stop_here, current_addr); } } @@ -69,8 +69,7 @@ bool ThreadPlanShouldStopHere::DefaultShouldStopHereCallback( (operation == eFrameCompareSameParent && flags.Test(eStepInAvoidNoDebug))) { if (!frame->HasDebugInformation()) { - if (log) - log->Printf("Stepping out of frame with no debug info"); + LLDB_LOGF(log, "Stepping out of frame with no debug info"); should_stop_here = false; } @@ -118,16 +117,14 @@ ThreadPlanSP ThreadPlanShouldStopHere::DefaultStepFromHereCallback( symbol_end.Slide(sc.symbol->GetByteSize() - 1); if (range.ContainsFileAddress(sc.symbol->GetAddress()) && range.ContainsFileAddress(symbol_end)) { - if (log) - log->Printf("Stopped in a function with only line 0 lines, just " - "stepping out."); + LLDB_LOGF(log, "Stopped in a function with only line 0 lines, just " + "stepping out."); just_step_out = true; } } if (!just_step_out) { - if (log) - log->Printf("ThreadPlanShouldStopHere::DefaultStepFromHereCallback " - "Queueing StepInRange plan to step through line 0 code."); + LLDB_LOGF(log, "ThreadPlanShouldStopHere::DefaultStepFromHereCallback " + "Queueing StepInRange plan to step through line 0 code."); return_plan_sp = current_plan->GetThread().QueueThreadPlanForStepInRange( false, range, sc, nullptr, eOnlyDuringStepping, status, diff --git a/source/Target/ThreadPlanStepInRange.cpp b/source/Target/ThreadPlanStepInRange.cpp index 2065fa55fa6a..71045cc7a990 100644 --- a/source/Target/ThreadPlanStepInRange.cpp +++ b/source/Target/ThreadPlanStepInRange.cpp @@ -148,7 +148,7 @@ bool ThreadPlanStepInRange::ShouldStop(Event *event_ptr) { s.Address( m_thread.GetRegisterContext()->GetPC(), m_thread.CalculateTarget()->GetArchitecture().GetAddressByteSize()); - log->Printf("ThreadPlanStepInRange reached %s.", s.GetData()); + LLDB_LOGF(log, "ThreadPlanStepInRange reached %s.", s.GetData()); } if (IsPlanComplete()) @@ -197,13 +197,14 @@ bool ThreadPlanStepInRange::ShouldStop(Event *event_ptr) { CheckShouldStopHereAndQueueStepOut(frame_order, m_status); if (log) { if (m_sub_plan_sp) - log->Printf("ShouldStopHere found plan to step out of this frame."); + LLDB_LOGF(log, + "ShouldStopHere found plan to step out of this frame."); else - log->Printf("ShouldStopHere no plan to step out of this frame."); + LLDB_LOGF(log, "ShouldStopHere no plan to step out of this frame."); } } else if (log) { - log->Printf( - "Thought I stepped out, but in fact arrived at a trampoline."); + LLDB_LOGF( + log, "Thought I stepped out, but in fact arrived at a trampoline."); } } else if (frame_order == eFrameCompareEqual && InSymbol()) { // If we are not in a place we should step through, we're done. One @@ -237,9 +238,10 @@ bool ThreadPlanStepInRange::ShouldStop(Event *event_ptr) { if (log) { if (m_sub_plan_sp) - log->Printf("Found a step through plan: %s", m_sub_plan_sp->GetName()); + LLDB_LOGF(log, "Found a step through plan: %s", + m_sub_plan_sp->GetName()); else - log->Printf("No step through plan found."); + LLDB_LOGF(log, "No step through plan found."); } // If not, give the "should_stop" callback a chance to push a plan to get @@ -289,8 +291,7 @@ bool ThreadPlanStepInRange::ShouldStop(Event *event_ptr) { if (bytes_to_skip != 0) { func_start_address.Slide(bytes_to_skip); log = lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_STEP); - if (log) - log->Printf("Pushing past prologue "); + LLDB_LOGF(log, "Pushing past prologue "); m_sub_plan_sp = m_thread.QueueThreadPlanForRunToAddress( false, func_start_address, true, m_status); @@ -312,10 +313,10 @@ bool ThreadPlanStepInRange::ShouldStop(Event *event_ptr) { void ThreadPlanStepInRange::SetAvoidRegexp(const char *name) { auto name_ref = llvm::StringRef::withNullAsEmpty(name); - if (!m_avoid_regexp_up) + if (m_avoid_regexp_up) + *m_avoid_regexp_up = RegularExpression(name_ref); + else m_avoid_regexp_up.reset(new RegularExpression(name_ref)); - - m_avoid_regexp_up->Compile(name_ref); } void ThreadPlanStepInRange::SetDefaultFlagValue(uint32_t new_value) { @@ -360,25 +361,17 @@ bool ThreadPlanStepInRange::FrameMatchesAvoidCriteria() { sc.GetFunctionName(Mangled::ePreferDemangledWithoutArguments) .GetCString(); if (frame_function_name) { - size_t num_matches = 0; - Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_STEP)); - if (log) - num_matches = 1; - - RegularExpression::Match regex_match(num_matches); - + llvm::SmallVector<llvm::StringRef, 2> matches; bool return_value = - avoid_regexp_to_use->Execute(frame_function_name, ®ex_match); - if (return_value) { - if (log) { - std::string match; - regex_match.GetMatchAtIndex(frame_function_name, 0, match); - log->Printf("Stepping out of function \"%s\" because it matches " - "the avoid regexp \"%s\" - match substring: \"%s\".", - frame_function_name, - avoid_regexp_to_use->GetText().str().c_str(), - match.c_str()); - } + avoid_regexp_to_use->Execute(frame_function_name, &matches); + if (return_value && matches.size() > 1) { + std::string match = matches[1].str(); + LLDB_LOGF(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_STEP), + "Stepping out of function \"%s\" because it matches " + "the avoid regexp \"%s\" - match substring: \"%s\".", + frame_function_name, + avoid_regexp_to_use->GetText().str().c_str(), + match.c_str()); } return return_value; } @@ -424,10 +417,11 @@ bool ThreadPlanStepInRange::DefaultShouldStopHereCallback( should_stop_here = false; } if (log && !should_stop_here) - log->Printf("Stepping out of frame %s which did not match step into " - "target %s.", - sc.GetFunctionName().AsCString(), - step_in_range_plan->m_step_into_target.AsCString()); + LLDB_LOGF(log, + "Stepping out of frame %s which did not match step into " + "target %s.", + sc.GetFunctionName().AsCString(), + step_in_range_plan->m_step_into_target.AsCString()); } } @@ -496,10 +490,10 @@ bool ThreadPlanStepInRange::DoWillResume(lldb::StateType resume_state, bool step_without_resume = m_thread.DecrementCurrentInlinedDepth(); if (step_without_resume) { Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_STEP)); - if (log) - log->Printf("ThreadPlanStepInRange::DoWillResume: returning false, " - "inline_depth: %d", - m_thread.GetCurrentInlinedDepth()); + LLDB_LOGF(log, + "ThreadPlanStepInRange::DoWillResume: returning false, " + "inline_depth: %d", + m_thread.GetCurrentInlinedDepth()); SetStopInfo(StopInfo::CreateStopReasonToTrace(m_thread)); // FIXME: Maybe it would be better to create a InlineStep stop reason, but diff --git a/source/Target/ThreadPlanStepInstruction.cpp b/source/Target/ThreadPlanStepInstruction.cpp index a11b623c8acf..0c75cb811156 100644 --- a/source/Target/ThreadPlanStepInstruction.cpp +++ b/source/Target/ThreadPlanStepInstruction.cpp @@ -114,8 +114,9 @@ bool ThreadPlanStepInstruction::IsPlanStale() { return !m_step_over; } else { if (log) { - log->Printf("ThreadPlanStepInstruction::IsPlanStale - Current frame is " - "older than start frame, plan is stale."); + LLDB_LOGF(log, + "ThreadPlanStepInstruction::IsPlanStale - Current frame is " + "older than start frame, plan is stale."); } return true; } @@ -127,9 +128,9 @@ bool ThreadPlanStepInstruction::ShouldStop(Event *event_ptr) { StackFrameSP cur_frame_sp = m_thread.GetStackFrameAtIndex(0); if (!cur_frame_sp) { - if (log) - log->Printf( - "ThreadPlanStepInstruction couldn't get the 0th frame, stopping."); + LLDB_LOGF( + log, + "ThreadPlanStepInstruction couldn't get the 0th frame, stopping."); SetPlanComplete(); return true; } @@ -168,8 +169,9 @@ bool ThreadPlanStepInstruction::ShouldStop(Event *event_ptr) { cur_frame_sp->GetConcreteFrameIndex()) { SetPlanComplete(); if (log) { - log->Printf("Frame we stepped into is inlined into the frame " - "we were stepping from, stopping."); + LLDB_LOGF(log, + "Frame we stepped into is inlined into the frame " + "we were stepping from, stopping."); } return true; } @@ -188,7 +190,7 @@ bool ThreadPlanStepInstruction::ShouldStop(Event *event_ptr) { s.Address(return_addr, m_thread.CalculateTarget() ->GetArchitecture() .GetAddressByteSize()); - log->Printf("%s.", s.GetData()); + LLDB_LOGF(log, "%s.", s.GetData()); } // StepInstruction should probably have the tri-state RunMode, but @@ -209,8 +211,7 @@ bool ThreadPlanStepInstruction::ShouldStop(Event *event_ptr) { return true; } } else { - if (log) - log->Printf("Could not find previous frame, stopping."); + LLDB_LOGF(log, "Could not find previous frame, stopping."); SetPlanComplete(); return true; } @@ -243,8 +244,7 @@ bool ThreadPlanStepInstruction::WillStop() { return true; } bool ThreadPlanStepInstruction::MischiefManaged() { if (IsPlanComplete()) { Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_STEP)); - if (log) - log->Printf("Completed single instruction step plan."); + LLDB_LOGF(log, "Completed single instruction step plan."); ThreadPlan::MischiefManaged(); return true; } else { diff --git a/source/Target/ThreadPlanStepOut.cpp b/source/Target/ThreadPlanStepOut.cpp index bf55c376513d..d7dae446b229 100644 --- a/source/Target/ThreadPlanStepOut.cpp +++ b/source/Target/ThreadPlanStepOut.cpp @@ -408,7 +408,7 @@ bool ThreadPlanStepOut::MischiefManaged() { Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_STEP)); if (log) - log->Printf("Completed step out plan."); + LLDB_LOGF(log, "Completed step out plan."); if (m_return_bp_id != LLDB_INVALID_BREAK_ID) { m_thread.CalculateTarget()->RemoveBreakpointByID(m_return_bp_id); m_return_bp_id = LLDB_INVALID_BREAK_ID; @@ -433,7 +433,7 @@ bool ThreadPlanStepOut::QueueInlinedStepPlan(bool queue_now) { if (log) { StreamString s; immediate_return_from_sp->Dump(&s, true, false); - log->Printf("Queuing inlined frame to step past: %s.", s.GetData()); + LLDB_LOGF(log, "Queuing inlined frame to step past: %s.", s.GetData()); } Block *from_block = immediate_return_from_sp->GetFrameBlock(); diff --git a/source/Target/ThreadPlanStepOverBreakpoint.cpp b/source/Target/ThreadPlanStepOverBreakpoint.cpp index 4770b57ab7f2..725669b1e9a8 100644 --- a/source/Target/ThreadPlanStepOverBreakpoint.cpp +++ b/source/Target/ThreadPlanStepOverBreakpoint.cpp @@ -62,11 +62,9 @@ bool ThreadPlanStepOverBreakpoint::DoPlanExplainsStop(Event *event_ptr) { StopReason reason = stop_info_sp->GetStopReason(); Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_STEP)); + LLDB_LOGF(log, "Step over breakpoint stopped for reason: %s.", + Thread::StopReasonAsCString(reason)); - if (log) - log->Printf("Step over breakpoint stopped for reason: %s.", - Thread::StopReasonAsCString(reason)); - switch (reason) { case eStopReasonTrace: case eStopReasonNone: @@ -91,9 +89,10 @@ bool ThreadPlanStepOverBreakpoint::DoPlanExplainsStop(Event *event_ptr) { lldb::addr_t pc_addr = m_thread.GetRegisterContext()->GetPC(); if (pc_addr == m_breakpoint_addr) { - if (log) - log->Printf("Got breakpoint stop reason but pc: 0x%" PRIx64 - "hasn't changed.", pc_addr); + LLDB_LOGF(log, + "Got breakpoint stop reason but pc: 0x%" PRIx64 + "hasn't changed.", + pc_addr); return true; } @@ -149,8 +148,7 @@ bool ThreadPlanStepOverBreakpoint::MischiefManaged() { return false; } else { Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_STEP)); - if (log) - log->Printf("Completed step over breakpoint plan."); + LLDB_LOGF(log, "Completed step over breakpoint plan."); // Otherwise, re-enable the breakpoint we were stepping over, and we're // done. ReenableBreakpointSite(); diff --git a/source/Target/ThreadPlanStepOverRange.cpp b/source/Target/ThreadPlanStepOverRange.cpp index 3aaeac9f5b21..2de678597c8a 100644 --- a/source/Target/ThreadPlanStepOverRange.cpp +++ b/source/Target/ThreadPlanStepOverRange.cpp @@ -131,7 +131,7 @@ bool ThreadPlanStepOverRange::ShouldStop(Event *event_ptr) { s.Address( m_thread.GetRegisterContext()->GetPC(), m_thread.CalculateTarget()->GetArchitecture().GetAddressByteSize()); - log->Printf("ThreadPlanStepOverRange reached %s.", s.GetData()); + LLDB_LOGF(log, "ThreadPlanStepOverRange reached %s.", s.GetData()); } // If we're out of the range but in the same frame or in our caller's frame @@ -155,8 +155,8 @@ bool ThreadPlanStepOverRange::ShouldStop(Event *event_ptr) { stop_others, m_status); if (new_plan_sp && log) - log->Printf( - "Thought I stepped out, but in fact arrived at a trampoline."); + LLDB_LOGF(log, + "Thought I stepped out, but in fact arrived at a trampoline."); } else if (frame_order == eFrameCompareYounger) { // Make sure we really are in a new frame. Do that by unwinding and seeing // if the start function really is our start function... @@ -371,10 +371,10 @@ bool ThreadPlanStepOverRange::DoWillResume(lldb::StateType resume_state, bool in_inlined_stack = m_thread.DecrementCurrentInlinedDepth(); if (in_inlined_stack) { Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_STEP)); - if (log) - log->Printf("ThreadPlanStepInRange::DoWillResume: adjusting range to " - "the frame at inlined depth %d.", - m_thread.GetCurrentInlinedDepth()); + LLDB_LOGF(log, + "ThreadPlanStepInRange::DoWillResume: adjusting range to " + "the frame at inlined depth %d.", + m_thread.GetCurrentInlinedDepth()); StackFrameSP stack_sp = m_thread.GetStackFrameAtIndex(0); if (stack_sp) { Block *frame_block = stack_sp->GetFrameBlock(); diff --git a/source/Target/ThreadPlanStepRange.cpp b/source/Target/ThreadPlanStepRange.cpp index 49c72dbf0911..27513a34eadb 100644 --- a/source/Target/ThreadPlanStepRange.cpp +++ b/source/Target/ThreadPlanStepRange.cpp @@ -68,9 +68,8 @@ Vote ThreadPlanStepRange::ShouldReportStop(Event *event_ptr) { Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_STEP)); const Vote vote = IsPlanComplete() ? eVoteYes : eVoteNo; - if (log) - log->Printf("ThreadPlanStepRange::ShouldReportStop() returning vote %i\n", - vote); + LLDB_LOGF(log, "ThreadPlanStepRange::ShouldReportStop() returning vote %i\n", + vote); return vote; } @@ -137,7 +136,8 @@ bool ThreadPlanStepRange::InRange() { true, Address::DumpStyleLoadAddress, Address::DumpStyleLoadAddress, true); - log->Printf( + LLDB_LOGF( + log, "Step range plan stepped to another range of same line: %s", s.GetData()); } @@ -155,9 +155,10 @@ bool ThreadPlanStepRange::InRange() { true, Address::DumpStyleLoadAddress, Address::DumpStyleLoadAddress, true); - log->Printf("Step range plan stepped to a range at linenumber 0 " - "stepping through that range: %s", - s.GetData()); + LLDB_LOGF(log, + "Step range plan stepped to a range at linenumber 0 " + "stepping through that range: %s", + s.GetData()); } } else if (new_context.line_entry.range.GetBaseAddress().GetLoadAddress( m_thread.CalculateTarget().get()) != pc_load_addr) { @@ -177,9 +178,10 @@ bool ThreadPlanStepRange::InRange() { true, Address::DumpStyleLoadAddress, Address::DumpStyleLoadAddress, true); - log->Printf("Step range plan stepped to the middle of new " - "line(%d): %s, continuing to clear this line.", - new_context.line_entry.line, s.GetData()); + LLDB_LOGF(log, + "Step range plan stepped to the middle of new " + "line(%d): %s, continuing to clear this line.", + new_context.line_entry.line, s.GetData()); } } } @@ -187,7 +189,7 @@ bool ThreadPlanStepRange::InRange() { } if (!ret_value && log) - log->Printf("Step range plan out of range to 0x%" PRIx64, pc_load_addr); + LLDB_LOGF(log, "Step range plan out of range to 0x%" PRIx64, pc_load_addr); return ret_value; } @@ -285,9 +287,8 @@ InstructionList *ThreadPlanStepRange::GetInstructionsForAddress( void ThreadPlanStepRange::ClearNextBranchBreakpoint() { if (m_next_branch_bp_sp) { Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_STEP)); - if (log) - log->Printf("Removing next branch breakpoint: %d.", - m_next_branch_bp_sp->GetID()); + LLDB_LOGF(log, "Removing next branch breakpoint: %d.", + m_next_branch_bp_sp->GetID()); GetTarget().RemoveBreakpointByID(m_next_branch_bp_sp->GetID()); m_next_branch_bp_sp.reset(); m_could_not_resolve_hw_bp = false; @@ -357,11 +358,12 @@ bool ThreadPlanStepRange::SetNextBranchBreakpoint() { bp_site_id = bp_site->GetID(); } } - log->Printf("ThreadPlanStepRange::SetNextBranchBreakpoint - Setting " - "breakpoint %d (site %d) to run to address 0x%" PRIx64, - m_next_branch_bp_sp->GetID(), bp_site_id, - run_to_address.GetLoadAddress( - &m_thread.GetProcess()->GetTarget())); + LLDB_LOGF(log, + "ThreadPlanStepRange::SetNextBranchBreakpoint - Setting " + "breakpoint %d (site %d) to run to address 0x%" PRIx64, + m_next_branch_bp_sp->GetID(), bp_site_id, + run_to_address.GetLoadAddress( + &m_thread.GetProcess()->GetTarget())); } m_next_branch_bp_sp->SetThreadID(m_thread.GetID()); @@ -402,11 +404,11 @@ bool ThreadPlanStepRange::NextRangeBreakpointExplainsStop( break; } } - if (log) - log->Printf("ThreadPlanStepRange::NextRangeBreakpointExplainsStop - Hit " - "next range breakpoint which has %" PRIu64 - " owners - explains stop: %u.", - (uint64_t)num_owners, explains_stop); + LLDB_LOGF(log, + "ThreadPlanStepRange::NextRangeBreakpointExplainsStop - Hit " + "next range breakpoint which has %" PRIu64 + " owners - explains stop: %u.", + (uint64_t)num_owners, explains_stop); ClearNextBranchBreakpoint(); return explains_stop; } @@ -445,8 +447,7 @@ bool ThreadPlanStepRange::MischiefManaged() { if (done) { Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_STEP)); - if (log) - log->Printf("Completed step through range plan."); + LLDB_LOGF(log, "Completed step through range plan."); ClearNextBranchBreakpoint(); ThreadPlan::MischiefManaged(); return true; @@ -461,8 +462,8 @@ bool ThreadPlanStepRange::IsPlanStale() { if (frame_order == eFrameCompareOlder) { if (log) { - log->Printf("ThreadPlanStepRange::IsPlanStale returning true, we've " - "stepped out."); + LLDB_LOGF(log, "ThreadPlanStepRange::IsPlanStale returning true, we've " + "stepped out."); } return true; } else if (frame_order == eFrameCompareEqual && InSymbol()) { diff --git a/source/Target/ThreadPlanStepThrough.cpp b/source/Target/ThreadPlanStepThrough.cpp index e46eba00184e..92b7fce1bc90 100644 --- a/source/Target/ThreadPlanStepThrough.cpp +++ b/source/Target/ThreadPlanStepThrough.cpp @@ -64,8 +64,8 @@ ThreadPlanStepThrough::ThreadPlanStepThrough(Thread &thread, } Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_STEP)); if (log) { - log->Printf("Setting backstop breakpoint %d at address: 0x%" PRIx64, - m_backstop_bkpt_id, m_backstop_addr); + LLDB_LOGF(log, "Setting backstop breakpoint %d at address: 0x%" PRIx64, + m_backstop_bkpt_id, m_backstop_addr); } } } @@ -103,11 +103,12 @@ void ThreadPlanStepThrough::LookForPlanToStepThroughFromCurrentPC() { if (m_sub_plan_sp) { StreamString s; m_sub_plan_sp->GetDescription(&s, lldb::eDescriptionLevelFull); - log->Printf("Found step through plan from 0x%" PRIx64 ": %s", - current_address, s.GetData()); + LLDB_LOGF(log, "Found step through plan from 0x%" PRIx64 ": %s", + current_address, s.GetData()); } else { - log->Printf("Couldn't find step through plan from address 0x%" PRIx64 ".", - current_address); + LLDB_LOGF(log, + "Couldn't find step through plan from address 0x%" PRIx64 ".", + current_address); } } } @@ -234,8 +235,7 @@ bool ThreadPlanStepThrough::MischiefManaged() { if (!IsPlanComplete()) { return false; } else { - if (log) - log->Printf("Completed step through step plan."); + LLDB_LOGF(log, "Completed step through step plan."); ClearBackstopBreakpoint(); ThreadPlan::MischiefManaged(); diff --git a/source/Target/ThreadPlanStepUntil.cpp b/source/Target/ThreadPlanStepUntil.cpp index d4109c3d38da..54d276337488 100644 --- a/source/Target/ThreadPlanStepUntil.cpp +++ b/source/Target/ThreadPlanStepUntil.cpp @@ -326,8 +326,7 @@ bool ThreadPlanStepUntil::MischiefManaged() { bool done = false; if (IsPlanComplete()) { Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_STEP)); - if (log) - log->Printf("Completed step until plan."); + LLDB_LOGF(log, "Completed step until plan."); Clear(); done = true; diff --git a/source/Target/ThreadPlanTracer.cpp b/source/Target/ThreadPlanTracer.cpp index 4e79b6b1e59d..5782fe8e6443 100644 --- a/source/Target/ThreadPlanTracer.cpp +++ b/source/Target/ThreadPlanTracer.cpp @@ -46,7 +46,7 @@ Stream *ThreadPlanTracer::GetLogStream() { else { TargetSP target_sp(m_thread.CalculateTarget()); if (target_sp) - return target_sp->GetDebugger().GetOutputFile().get(); + return &(target_sp->GetDebugger().GetOutputStream()); } return nullptr; } @@ -93,15 +93,20 @@ Disassembler *ThreadPlanAssemblyTracer::GetDisassembler() { TypeFromUser ThreadPlanAssemblyTracer::GetIntPointerType() { if (!m_intptr_type.IsValid()) { - TargetSP target_sp(m_thread.CalculateTarget()); - if (target_sp) { - TypeSystem *type_system = - target_sp->GetScratchTypeSystemForLanguage(nullptr, eLanguageTypeC); - if (type_system) - m_intptr_type = - TypeFromUser(type_system->GetBuiltinTypeForEncodingAndBitSize( + if (auto target_sp = m_thread.CalculateTarget()) { + auto type_system_or_err = + target_sp->GetScratchTypeSystemForLanguage(eLanguageTypeC); + if (auto err = type_system_or_err.takeError()) { + LLDB_LOG_ERROR( + lldb_private::GetLogIfAnyCategoriesSet(LIBLLDB_LOG_TYPES), + std::move(err), + "Unable to get integer pointer type from TypeSystem"); + } else { + m_intptr_type = TypeFromUser( + type_system_or_err->GetBuiltinTypeForEncodingAndBitSize( eEncodingUint, target_sp->GetArchitecture().GetAddressByteSize() * 8)); + } } } return m_intptr_type; diff --git a/source/Utility/ArchSpec.cpp b/source/Utility/ArchSpec.cpp index 81b87fff88d4..40cc4a092b0d 100644 --- a/source/Utility/ArchSpec.cpp +++ b/source/Utility/ArchSpec.cpp @@ -101,6 +101,8 @@ static const CoreDefinition g_core_definitions[] = { ArchSpec::eCore_arm_arm64, "arm64"}, {eByteOrderLittle, 8, 4, 4, llvm::Triple::aarch64, ArchSpec::eCore_arm_armv8, "armv8"}, + {eByteOrderLittle, 4, 4, 4, llvm::Triple::aarch64_32, + ArchSpec::eCore_arm_arm64_32, "arm64_32"}, {eByteOrderLittle, 8, 4, 4, llvm::Triple::aarch64, ArchSpec::eCore_arm_aarch64, "aarch64"}, @@ -214,6 +216,7 @@ static const CoreDefinition g_core_definitions[] = { ArchSpec::eCore_uknownMach32, "unknown-mach-32"}, {eByteOrderLittle, 8, 4, 4, llvm::Triple::UnknownArch, ArchSpec::eCore_uknownMach64, "unknown-mach-64"}, + {eByteOrderLittle, 4, 2, 4, llvm::Triple::arc, ArchSpec::eCore_arc, "arc"} }; // Ensure that we have an entry in the g_core_definitions for each core. If you @@ -243,19 +246,9 @@ void ArchSpec::ListSupportedArchNames(StringList &list) { list.AppendString(g_core_definitions[i].name); } -size_t ArchSpec::AutoComplete(CompletionRequest &request) { - if (!request.GetCursorArgumentPrefix().empty()) { - for (uint32_t i = 0; i < llvm::array_lengthof(g_core_definitions); ++i) { - if (NameMatches(g_core_definitions[i].name, NameMatch::StartsWith, - request.GetCursorArgumentPrefix())) - request.AddCompletion(g_core_definitions[i].name); - } - } else { - StringList matches; - ListSupportedArchNames(matches); - request.AddCompletions(matches); - } - return request.GetNumberOfMatches(); +void ArchSpec::AutoComplete(CompletionRequest &request) { + for (uint32_t i = 0; i < llvm::array_lengthof(g_core_definitions); ++i) + request.TryCompleteCurrentArg(g_core_definitions[i].name); } #define CPU_ANY (UINT32_MAX) @@ -306,6 +299,10 @@ static const ArchDefinitionEntry g_macho_arch_entries[] = { SUBTYPE_MASK}, {ArchSpec::eCore_arm_arm64, llvm::MachO::CPU_TYPE_ARM64, 13, UINT32_MAX, SUBTYPE_MASK}, + {ArchSpec::eCore_arm_arm64_32, llvm::MachO::CPU_TYPE_ARM64_32, 0, + UINT32_MAX, SUBTYPE_MASK}, + {ArchSpec::eCore_arm_arm64_32, llvm::MachO::CPU_TYPE_ARM64_32, 1, + UINT32_MAX, SUBTYPE_MASK}, {ArchSpec::eCore_arm_arm64, llvm::MachO::CPU_TYPE_ARM64, CPU_ANY, UINT32_MAX, SUBTYPE_MASK}, {ArchSpec::eCore_thumb, llvm::MachO::CPU_TYPE_ARM, 0, UINT32_MAX, @@ -446,6 +443,8 @@ static const ArchDefinitionEntry g_elf_arch_entries[] = { ArchSpec::eMIPSSubType_mips64r6el, 0xFFFFFFFFu, 0xFFFFFFFFu}, // mips64r6el {ArchSpec::eCore_hexagon_generic, llvm::ELF::EM_HEXAGON, LLDB_INVALID_CPUTYPE, 0xFFFFFFFFu, 0xFFFFFFFFu}, // HEXAGON + {ArchSpec::eCore_arc, llvm::ELF::EM_ARC_COMPACT2, LLDB_INVALID_CPUTYPE, + 0xFFFFFFFFu, 0xFFFFFFFFu }, // ARC }; static const ArchDefinition g_elf_arch_def = { @@ -469,7 +468,9 @@ static const ArchDefinitionEntry g_coff_arch_entries[] = { {ArchSpec::eCore_thumb, llvm::COFF::IMAGE_FILE_MACHINE_THUMB, LLDB_INVALID_CPUTYPE, 0xFFFFFFFFu, 0xFFFFFFFFu}, // ARMv7 {ArchSpec::eCore_x86_64_x86_64, llvm::COFF::IMAGE_FILE_MACHINE_AMD64, - LLDB_INVALID_CPUTYPE, 0xFFFFFFFFu, 0xFFFFFFFFu} // AMD64 + LLDB_INVALID_CPUTYPE, 0xFFFFFFFFu, 0xFFFFFFFFu}, // AMD64 + {ArchSpec::eCore_arm_arm64, llvm::COFF::IMAGE_FILE_MACHINE_ARM64, + LLDB_INVALID_CPUTYPE, 0xFFFFFFFFu, 0xFFFFFFFFu} // ARM64 }; static const ArchDefinition g_coff_arch_def = { @@ -760,6 +761,7 @@ bool ArchSpec::CharIsSignedByDefault() const { return true; case llvm::Triple::aarch64: + case llvm::Triple::aarch64_32: case llvm::Triple::aarch64_be: case llvm::Triple::arm: case llvm::Triple::armeb: @@ -946,8 +948,10 @@ bool ArchSpec::SetArchitecture(ArchitectureType arch_type, uint32_t cpu, } } else { Log *log(lldb_private::GetLogIfAnyCategoriesSet(LIBLLDB_LOG_TARGET | LIBLLDB_LOG_PROCESS | LIBLLDB_LOG_PLATFORM)); - if (log) - log->Printf("Unable to find a core definition for cpu 0x%" PRIx32 " sub %" PRId32, cpu, sub); + LLDB_LOGF(log, + "Unable to find a core definition for cpu 0x%" PRIx32 + " sub %" PRId32, + cpu, sub); } } CoreUpdated(update_triple); @@ -1245,6 +1249,14 @@ static bool cores_match(const ArchSpec::Core core1, const ArchSpec::Core core2, } break; + case ArchSpec::eCore_arm_arm64_32: + if (!enforce_exact_match) { + if (core2 == ArchSpec::eCore_arm_generic) + return true; + try_inverse = false; + } + break; + case ArchSpec::eCore_mips32: if (!enforce_exact_match) { if (core2 >= ArchSpec::kCore_mips32_first && diff --git a/source/Utility/Args.cpp b/source/Utility/Args.cpp index 77b0d43254a1..9fcc833ce432 100644 --- a/source/Utility/Args.cpp +++ b/source/Utility/Args.cpp @@ -163,7 +163,6 @@ Args::ArgEntry::ArgEntry(llvm::StringRef str, char quote) : quote(quote) { ::memcpy(data(), str.data() ? str.data() : "", size); ptr[size] = 0; - ref = llvm::StringRef(c_str(), size); } // Args constructor @@ -172,8 +171,8 @@ Args::Args(llvm::StringRef command) { SetCommandString(command); } Args::Args(const Args &rhs) { *this = rhs; } Args::Args(const StringList &list) : Args() { - for (size_t i = 0; i < list.GetSize(); ++i) - AppendArgument(list[i]); + for (const std::string &arg : list) + AppendArgument(arg); } Args &Args::operator=(const Args &rhs) { @@ -182,7 +181,7 @@ Args &Args::operator=(const Args &rhs) { m_argv.clear(); m_entries.clear(); for (auto &entry : rhs.m_entries) { - m_entries.emplace_back(entry.ref, entry.quote); + m_entries.emplace_back(entry.ref(), entry.quote); m_argv.push_back(m_entries.back().data()); } m_argv.push_back(nullptr); @@ -199,7 +198,7 @@ void Args::Dump(Stream &s, const char *label_name) const { int i = 0; for (auto &entry : m_entries) { s.Indent(); - s.Format("{0}[{1}]=\"{2}\"\n", label_name, i++, entry.ref); + s.Format("{0}[{1}]=\"{2}\"\n", label_name, i++, entry.ref()); } s.Format("{0}[{1}]=NULL\n", label_name, i); s.EOL(); @@ -211,7 +210,7 @@ bool Args::GetCommandString(std::string &command) const { for (size_t i = 0; i < m_entries.size(); ++i) { if (i > 0) command += ' '; - command += m_entries[i].ref; + command += m_entries[i].ref(); } return !m_entries.empty(); @@ -226,10 +225,10 @@ bool Args::GetQuotedCommandString(std::string &command) const { if (m_entries[i].quote) { command += m_entries[i].quote; - command += m_entries[i].ref; + command += m_entries[i].ref(); command += m_entries[i].quote; } else { - command += m_entries[i].ref; + command += m_entries[i].ref(); } } @@ -260,12 +259,6 @@ const char *Args::GetArgumentAtIndex(size_t idx) const { return nullptr; } -char Args::GetArgumentQuoteCharAtIndex(size_t idx) const { - if (idx < m_entries.size()) - return m_entries[idx].quote; - return '\0'; -} - char **Args::GetArgumentVector() { assert(!m_argv.empty()); // TODO: functions like execve and posix_spawnp exhibit undefined behavior @@ -299,7 +292,7 @@ void Args::AppendArguments(const Args &rhs) { assert(m_argv.back() == nullptr); m_argv.pop_back(); for (auto &entry : rhs.m_entries) { - m_entries.emplace_back(entry.ref, entry.quote); + m_entries.emplace_back(entry.ref(), entry.quote); m_argv.push_back(m_entries.back().data()); } m_argv.push_back(nullptr); @@ -342,15 +335,8 @@ void Args::ReplaceArgumentAtIndex(size_t idx, llvm::StringRef arg_str, if (idx >= m_entries.size()) return; - if (arg_str.size() > m_entries[idx].ref.size()) { - m_entries[idx] = ArgEntry(arg_str, quote_char); - m_argv[idx] = m_entries[idx].data(); - } else { - const char *src_data = arg_str.data() ? arg_str.data() : ""; - ::memcpy(m_entries[idx].data(), src_data, arg_str.size()); - m_entries[idx].ptr[arg_str.size()] = 0; - m_entries[idx].ref = m_entries[idx].ref.take_front(arg_str.size()); - } + m_entries[idx] = ArgEntry(arg_str, quote_char); + m_argv[idx] = m_entries[idx].data(); } void Args::DeleteArgumentAtIndex(size_t idx) { @@ -388,29 +374,6 @@ void Args::Clear() { m_argv.push_back(nullptr); } -const char *Args::StripSpaces(std::string &s, bool leading, bool trailing, - bool return_null_if_empty) { - static const char *k_white_space = " \t\v"; - if (!s.empty()) { - if (leading) { - size_t pos = s.find_first_not_of(k_white_space); - if (pos == std::string::npos) - s.clear(); - else if (pos > 0) - s.erase(0, pos); - } - - if (trailing) { - size_t rpos = s.find_last_not_of(k_white_space); - if (rpos != std::string::npos && rpos + 1 < s.size()) - s.erase(rpos + 1); - } - } - if (return_null_if_empty && s.empty()) - return nullptr; - return s.c_str(); -} - const char *Args::GetShellSafeArgument(const FileSpec &shell, const char *unsafe_arg, std::string &safe_arg) { diff --git a/source/Utility/Broadcaster.cpp b/source/Utility/Broadcaster.cpp index 597888cfa0e2..148fdf7ba5b1 100644 --- a/source/Utility/Broadcaster.cpp +++ b/source/Utility/Broadcaster.cpp @@ -214,11 +214,12 @@ void Broadcaster::BroadcasterImpl::PrivateBroadcastEvent(EventSP &event_sp, if (Log *log = lldb_private::GetLogIfAnyCategoriesSet(LIBLLDB_LOG_EVENTS)) { StreamString event_description; event_sp->Dump(&event_description); - log->Printf("%p Broadcaster(\"%s\")::BroadcastEvent (event_sp = {%s}, " - "unique =%i) hijack = %p", - static_cast<void *>(this), GetBroadcasterName(), - event_description.GetData(), unique, - static_cast<void *>(hijacking_listener_sp.get())); + LLDB_LOGF(log, + "%p Broadcaster(\"%s\")::BroadcastEvent (event_sp = {%s}, " + "unique =%i) hijack = %p", + static_cast<void *>(this), GetBroadcasterName(), + event_description.GetData(), unique, + static_cast<void *>(hijacking_listener_sp.get())); } if (hijacking_listener_sp) { diff --git a/source/Utility/CompletionRequest.cpp b/source/Utility/CompletionRequest.cpp index c62ec4f56ffa..3b5a4570e324 100644 --- a/source/Utility/CompletionRequest.cpp +++ b/source/Utility/CompletionRequest.cpp @@ -13,46 +13,32 @@ using namespace lldb_private; CompletionRequest::CompletionRequest(llvm::StringRef command_line, unsigned raw_cursor_pos, - int match_start_point, - int max_return_elements, CompletionResult &result) : m_command(command_line), m_raw_cursor_pos(raw_cursor_pos), - m_match_start_point(match_start_point), - m_max_return_elements(max_return_elements), m_result(result) { + m_result(result) { + assert(raw_cursor_pos <= command_line.size() && "Out of bounds cursor?"); // We parse the argument up to the cursor, so the last argument in // parsed_line is the one containing the cursor, and the cursor is after the // last character. - m_parsed_line = Args(command_line); - m_partial_parsed_line = Args(command_line.substr(0, raw_cursor_pos)); + llvm::StringRef partial_command(command_line.substr(0, raw_cursor_pos)); + m_parsed_line = Args(partial_command); - m_cursor_index = m_partial_parsed_line.GetArgumentCount() - 1; - - if (m_cursor_index == -1) + if (GetParsedLine().GetArgumentCount() == 0) { + m_cursor_index = 0; m_cursor_char_position = 0; - else + } else { + m_cursor_index = GetParsedLine().GetArgumentCount() - 1U; m_cursor_char_position = - strlen(m_partial_parsed_line.GetArgumentAtIndex(m_cursor_index)); - - const char *cursor = command_line.data() + raw_cursor_pos; - if (raw_cursor_pos > 0 && cursor[-1] == ' ') { - // We are just after a space. If we are in an argument, then we will - // continue parsing, but if we are between arguments, then we have to - // complete whatever the next element would be. We can distinguish the two - // cases because if we are in an argument (e.g. because the space is - // protected by a quote) then the space will also be in the parsed - // argument... - - const char *current_elem = - m_partial_parsed_line.GetArgumentAtIndex(m_cursor_index); - if (m_cursor_char_position == 0 || - current_elem[m_cursor_char_position - 1] != ' ') { - m_parsed_line.InsertArgumentAtIndex(m_cursor_index + 1, llvm::StringRef(), - '\0'); - m_cursor_index++; - m_cursor_char_position = 0; - } + strlen(GetParsedLine().GetArgumentAtIndex(m_cursor_index)); } + + // The cursor is after a space but the space is not part of the argument. + // Let's add an empty fake argument to the end to make sure the completion + // code. Note: The space could be part of the last argument when it's quoted. + if (partial_command.endswith(" ") && + !GetCursorArgumentPrefix().endswith(" ")) + AppendEmptyArgument(); } std::string CompletionResult::Completion::GetUniqueKey() const { @@ -66,13 +52,16 @@ std::string CompletionResult::Completion::GetUniqueKey() const { std::string result; result.append(std::to_string(m_completion.size())); result.append(m_completion); + result.append(std::to_string(static_cast<int>(m_mode))); + result.append(":"); result.append(m_descripton); return result; } void CompletionResult::AddResult(llvm::StringRef completion, - llvm::StringRef description) { - Completion r(completion, description); + llvm::StringRef description, + CompletionMode mode) { + Completion r(completion, description, mode); // Add the completion if we haven't seen the same value before. if (m_added_values.insert(r.GetUniqueKey()).second) @@ -82,11 +71,11 @@ void CompletionResult::AddResult(llvm::StringRef completion, void CompletionResult::GetMatches(StringList &matches) const { matches.Clear(); for (const Completion &completion : m_results) - matches.AppendString(completion.m_completion); + matches.AppendString(completion.GetCompletion()); } void CompletionResult::GetDescriptions(StringList &descriptions) const { descriptions.Clear(); for (const Completion &completion : m_results) - descriptions.AppendString(completion.m_descripton); + descriptions.AppendString(completion.GetDescription()); } diff --git a/source/Utility/ConstString.cpp b/source/Utility/ConstString.cpp index 46b7ab259383..2516ecf6a989 100644 --- a/source/Utility/ConstString.cpp +++ b/source/Utility/ConstString.cpp @@ -59,23 +59,6 @@ public: return nullptr; } - bool SetMangledCounterparts(const char *key_ccstr, const char *value_ccstr) { - if (key_ccstr != nullptr && value_ccstr != nullptr) { - { - const uint8_t h = hash(llvm::StringRef(key_ccstr)); - llvm::sys::SmartScopedWriter<false> wlock(m_string_pools[h].m_mutex); - GetStringMapEntryFromKeyData(key_ccstr).setValue(value_ccstr); - } - { - const uint8_t h = hash(llvm::StringRef(value_ccstr)); - llvm::sys::SmartScopedWriter<false> wlock(m_string_pools[h].m_mutex); - GetStringMapEntryFromKeyData(value_ccstr).setValue(key_ccstr); - } - return true; - } - return false; - } - const char *GetConstCString(const char *cstr) { if (cstr != nullptr) return GetConstCStringWithLength(cstr, strlen(cstr)); diff --git a/source/Utility/DataExtractor.cpp b/source/Utility/DataExtractor.cpp index 79a1f75d737c..f642a8fc7639 100644 --- a/source/Utility/DataExtractor.cpp +++ b/source/Utility/DataExtractor.cpp @@ -816,26 +816,25 @@ DataExtractor::CopyByteOrderedData(offset_t src_offset, offset_t src_len, // non-zero and there aren't enough available bytes, nullptr will be returned // and "offset_ptr" will not be updated. const char *DataExtractor::GetCStr(offset_t *offset_ptr) const { - const char *cstr = reinterpret_cast<const char *>(PeekData(*offset_ptr, 1)); - if (cstr) { - const char *cstr_end = cstr; - const char *end = reinterpret_cast<const char *>(m_end); - while (cstr_end < end && *cstr_end) - ++cstr_end; - - // Now we are either at the end of the data or we point to the - // NULL C string terminator with cstr_end... - if (*cstr_end == '\0') { - // Advance the offset with one extra byte for the NULL terminator - *offset_ptr += (cstr_end - cstr + 1); - return cstr; - } + const char *start = reinterpret_cast<const char *>(PeekData(*offset_ptr, 1)); + // Already at the end of the data. + if (!start) + return nullptr; - // We reached the end of the data without finding a NULL C string - // terminator. Fall through and return nullptr otherwise anyone that would - // have used the result as a C string can wander into unknown memory... - } - return nullptr; + const char *end = reinterpret_cast<const char *>(m_end); + + // Check all bytes for a null terminator that terminates a C string. + const char *terminator_or_end = std::find(start, end, '\0'); + + // We didn't find a null terminator, so return nullptr to indicate that there + // is no valid C string at that offset. + if (terminator_or_end == end) + return nullptr; + + // Update offset_ptr for the caller to point to the data behind the + // terminator (which is 1 byte long). + *offset_ptr += (terminator_or_end - start + 1UL); + return start; } // Extracts a NULL terminated C string from the fixed length field of length diff --git a/source/Utility/FileCollector.cpp b/source/Utility/FileCollector.cpp deleted file mode 100644 index ed9359192205..000000000000 --- a/source/Utility/FileCollector.cpp +++ /dev/null @@ -1,182 +0,0 @@ -//===-- FileCollector.cpp ---------------------------------------*- C++ -*-===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// - -#include "lldb/Utility/FileCollector.h" - -#include "llvm/ADT/SmallString.h" -#include "llvm/Support/FileSystem.h" -#include "llvm/Support/Path.h" -#include "llvm/Support/Process.h" - -using namespace lldb_private; -using namespace llvm; - -static bool IsCaseSensitivePath(StringRef path) { - SmallString<256> tmp_dest = path, upper_dest, real_dest; - - // Remove component traversals, links, etc. - if (!sys::fs::real_path(path, tmp_dest)) - return true; // Current default value in vfs.yaml - path = tmp_dest; - - // Change path to all upper case and ask for its real path, if the latter - // exists and is equal to path, it's not case sensitive. Default to case - // sensitive in the absence of real_path, since this is the YAMLVFSWriter - // default. - upper_dest = path.upper(); - if (sys::fs::real_path(upper_dest, real_dest) && path.equals(real_dest)) - return false; - return true; -} - -FileCollector::FileCollector(const FileSpec &root, const FileSpec &overlay_root) - : m_root(root), m_overlay_root(overlay_root) { - sys::fs::create_directories(m_root.GetPath(), true); -} - -bool FileCollector::GetRealPath(StringRef src_path, - SmallVectorImpl<char> &result) { - SmallString<256> real_path; - StringRef FileName = sys::path::filename(src_path); - std::string directory = sys::path::parent_path(src_path).str(); - auto dir_with_symlink = m_symlink_map.find(directory); - - // Use real_path to fix any symbolic link component present in a path. - // Computing the real path is expensive, cache the search through the - // parent path directory. - if (dir_with_symlink == m_symlink_map.end()) { - auto ec = sys::fs::real_path(directory, real_path); - if (ec) - return false; - m_symlink_map[directory] = real_path.str(); - } else { - real_path = dir_with_symlink->second; - } - - sys::path::append(real_path, FileName); - result.swap(real_path); - return true; -} - -void FileCollector::AddFile(const Twine &file) { - std::lock_guard<std::mutex> lock(m_mutex); - std::string file_str = file.str(); - if (MarkAsSeen(file_str)) - AddFileImpl(file_str); -} - -void FileCollector::AddFileImpl(StringRef src_path) { - std::string root = m_root.GetPath(); - - // We need an absolute src path to append to the root. - SmallString<256> absolute_src = src_path; - sys::fs::make_absolute(absolute_src); - - // Canonicalize src to a native path to avoid mixed separator styles. - sys::path::native(absolute_src); - - // Remove redundant leading "./" pieces and consecutive separators. - absolute_src = sys::path::remove_leading_dotslash(absolute_src); - - // Canonicalize the source path by removing "..", "." components. - SmallString<256> virtual_path = absolute_src; - sys::path::remove_dots(virtual_path, /*remove_dot_dot=*/true); - - // If a ".." component is present after a symlink component, remove_dots may - // lead to the wrong real destination path. Let the source be canonicalized - // like that but make sure we always use the real path for the destination. - SmallString<256> copy_from; - if (!GetRealPath(absolute_src, copy_from)) - copy_from = virtual_path; - - SmallString<256> dst_path = StringRef(root); - sys::path::append(dst_path, sys::path::relative_path(copy_from)); - - // Always map a canonical src path to its real path into the YAML, by doing - // this we map different virtual src paths to the same entry in the VFS - // overlay, which is a way to emulate symlink inside the VFS; this is also - // needed for correctness, not doing that can lead to module redefinition - // errors. - AddFileToMapping(virtual_path, dst_path); -} - -/// Set the access and modification time for the given file from the given -/// status object. -static std::error_code -CopyAccessAndModificationTime(StringRef filename, - const sys::fs::file_status &stat) { - int fd; - - if (auto ec = - sys::fs::openFileForWrite(filename, fd, sys::fs::CD_OpenExisting)) - return ec; - - if (auto ec = sys::fs::setLastAccessAndModificationTime( - fd, stat.getLastAccessedTime(), stat.getLastModificationTime())) - return ec; - - if (auto ec = sys::Process::SafelyCloseFileDescriptor(fd)) - return ec; - - return {}; -} - -std::error_code FileCollector::CopyFiles(bool stop_on_error) { - for (auto &entry : m_vfs_writer.getMappings()) { - // Create directory tree. - if (std::error_code ec = - sys::fs::create_directories(sys::path::parent_path(entry.RPath), - /*IgnoreExisting=*/true)) { - if (stop_on_error) - return ec; - } - - // Copy file over. - if (std::error_code ec = sys::fs::copy_file(entry.VPath, entry.RPath)) { - if (stop_on_error) - return ec; - } - - // Copy over permissions. - if (auto perms = sys::fs::getPermissions(entry.VPath)) { - if (std::error_code ec = sys::fs::setPermissions(entry.RPath, *perms)) { - if (stop_on_error) - return ec; - } - } - - // Copy over modification time. - sys::fs::file_status stat; - if (std::error_code ec = sys::fs::status(entry.VPath, stat)) { - if (stop_on_error) - return ec; - continue; - } - CopyAccessAndModificationTime(entry.RPath, stat); - } - return {}; -} - -std::error_code FileCollector::WriteMapping(const FileSpec &mapping_file) { - std::lock_guard<std::mutex> lock(m_mutex); - - std::string root = m_overlay_root.GetPath(); - - m_vfs_writer.setOverlayDir(root); - m_vfs_writer.setCaseSensitivity(IsCaseSensitivePath(root)); - m_vfs_writer.setUseExternalNames(false); - - std::error_code ec; - raw_fd_ostream os(mapping_file.GetPath(), ec, sys::fs::F_Text); - if (ec) - return ec; - - m_vfs_writer.write(os); - - return {}; -} diff --git a/source/Utility/FileSpec.cpp b/source/Utility/FileSpec.cpp index 35d22404b948..f22ab4d84e40 100644 --- a/source/Utility/FileSpec.cpp +++ b/source/Utility/FileSpec.cpp @@ -72,8 +72,8 @@ FileSpec::FileSpec(llvm::StringRef path, Style style) : m_style(style) { SetFile(path, style); } -FileSpec::FileSpec(llvm::StringRef path, const llvm::Triple &Triple) - : FileSpec{path, Triple.isOSWindows() ? Style::windows : Style::posix} {} +FileSpec::FileSpec(llvm::StringRef path, const llvm::Triple &triple) + : FileSpec{path, triple.isOSWindows() ? Style::windows : Style::posix} {} // Copy constructor FileSpec::FileSpec(const FileSpec *rhs) : m_directory(), m_filename() { @@ -228,8 +228,8 @@ void FileSpec::SetFile(llvm::StringRef pathname, Style style) { m_directory.SetString(directory); } -void FileSpec::SetFile(llvm::StringRef path, const llvm::Triple &Triple) { - return SetFile(path, Triple.isOSWindows() ? Style::windows : Style::posix); +void FileSpec::SetFile(llvm::StringRef path, const llvm::Triple &triple) { + return SetFile(path, triple.isOSWindows() ? Style::windows : Style::posix); } // Convert to pointer operator. This allows code to check any FileSpec objects diff --git a/source/Utility/GDBRemote.cpp b/source/Utility/GDBRemote.cpp new file mode 100644 index 000000000000..85c4bc69a8d1 --- /dev/null +++ b/source/Utility/GDBRemote.cpp @@ -0,0 +1,105 @@ +//===-- GDBRemote.cpp -----------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#include "lldb/Utility/GDBRemote.h" + +#include "lldb/Utility/Flags.h" +#include "lldb/Utility/Stream.h" + +#include <stdio.h> + +using namespace lldb; +using namespace lldb_private; +using namespace llvm; + +StreamGDBRemote::StreamGDBRemote() : StreamString() {} + +StreamGDBRemote::StreamGDBRemote(uint32_t flags, uint32_t addr_size, + ByteOrder byte_order) + : StreamString(flags, addr_size, byte_order) {} + +StreamGDBRemote::~StreamGDBRemote() {} + +int StreamGDBRemote::PutEscapedBytes(const void *s, size_t src_len) { + int bytes_written = 0; + const uint8_t *src = static_cast<const uint8_t *>(s); + bool binary_is_set = m_flags.Test(eBinary); + m_flags.Clear(eBinary); + while (src_len) { + uint8_t byte = *src; + src++; + src_len--; + if (byte == 0x23 || byte == 0x24 || byte == 0x7d || byte == 0x2a) { + bytes_written += PutChar(0x7d); + byte ^= 0x20; + } + bytes_written += PutChar(byte); + }; + if (binary_is_set) + m_flags.Set(eBinary); + return bytes_written; +} + +void GDBRemotePacket::Serialize(raw_ostream &strm) const { + yaml::Output yout(strm); + yout << const_cast<GDBRemotePacket &>(*this); + strm.flush(); +} + +llvm::StringRef GDBRemotePacket::GetTypeStr() const { + switch (type) { + case GDBRemotePacket::ePacketTypeSend: + return "send"; + case GDBRemotePacket::ePacketTypeRecv: + return "read"; + case GDBRemotePacket::ePacketTypeInvalid: + return "invalid"; + } + llvm_unreachable("All enum cases should be handled"); +} + +void GDBRemotePacket::Dump(Stream &strm) const { + strm.Printf("tid=0x%4.4" PRIx64 " <%4u> %s packet: %s\n", tid, + bytes_transmitted, GetTypeStr().data(), packet.data.c_str()); +} + +void yaml::ScalarEnumerationTraits<GDBRemotePacket::Type>::enumeration( + IO &io, GDBRemotePacket::Type &value) { + io.enumCase(value, "Invalid", GDBRemotePacket::ePacketTypeInvalid); + io.enumCase(value, "Send", GDBRemotePacket::ePacketTypeSend); + io.enumCase(value, "Recv", GDBRemotePacket::ePacketTypeRecv); +} + +void yaml::ScalarTraits<GDBRemotePacket::BinaryData>::output( + const GDBRemotePacket::BinaryData &Val, void *, raw_ostream &Out) { + Out << toHex(Val.data); +} + +StringRef yaml::ScalarTraits<GDBRemotePacket::BinaryData>::input( + StringRef Scalar, void *, GDBRemotePacket::BinaryData &Val) { + Val.data = fromHex(Scalar); + return {}; +} + +void yaml::MappingTraits<GDBRemotePacket>::mapping(IO &io, + GDBRemotePacket &Packet) { + io.mapRequired("packet", Packet.packet); + io.mapRequired("type", Packet.type); + io.mapRequired("bytes", Packet.bytes_transmitted); + io.mapRequired("index", Packet.packet_idx); + io.mapRequired("tid", Packet.tid); +} + +StringRef +yaml::MappingTraits<GDBRemotePacket>::validate(IO &io, + GDBRemotePacket &Packet) { + if (Packet.bytes_transmitted != Packet.packet.data.size()) + return "BinaryData size doesn't match bytes transmitted"; + + return {}; +} diff --git a/source/Utility/JSON.cpp b/source/Utility/JSON.cpp deleted file mode 100644 index 2c3f6229eda1..000000000000 --- a/source/Utility/JSON.cpp +++ /dev/null @@ -1,550 +0,0 @@ -//===--------------------- JSON.cpp -----------------------------*- C++ -*-===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// - -#include "lldb/Utility/JSON.h" - -#include "lldb/Utility/Stream.h" -#include "lldb/Utility/StreamString.h" -#include "llvm/ADT/StringRef.h" -#include "llvm/Support/ErrorHandling.h" - -#include <inttypes.h> -#include <limits.h> -#include <stddef.h> -#include <utility> - -using namespace lldb_private; - -std::string JSONString::json_string_quote_metachars(const std::string &s) { - if (s.find_first_of("\\\n\"") == std::string::npos) - return s; - - std::string output; - const size_t s_size = s.size(); - const char *s_chars = s.c_str(); - for (size_t i = 0; i < s_size; i++) { - unsigned char ch = *(s_chars + i); - if (ch == '"' || ch == '\\' || ch == '\n') { - output.push_back('\\'); - if (ch == '\n') ch = 'n'; - } - output.push_back(ch); - } - return output; -} - -JSONString::JSONString() : JSONValue(JSONValue::Kind::String), m_data() {} - -JSONString::JSONString(const char *s) - : JSONValue(JSONValue::Kind::String), m_data(s ? s : "") {} - -JSONString::JSONString(const std::string &s) - : JSONValue(JSONValue::Kind::String), m_data(s) {} - -void JSONString::Write(Stream &s) { - s.Printf("\"%s\"", json_string_quote_metachars(m_data).c_str()); -} - -uint64_t JSONNumber::GetAsUnsigned() const { - switch (m_data_type) { - case DataType::Unsigned: - return m_data.m_unsigned; - case DataType::Signed: - return static_cast<uint64_t>(m_data.m_signed); - case DataType::Double: - return static_cast<uint64_t>(m_data.m_double); - } - llvm_unreachable("Unhandled data type"); -} - -int64_t JSONNumber::GetAsSigned() const { - switch (m_data_type) { - case DataType::Unsigned: - return static_cast<int64_t>(m_data.m_unsigned); - case DataType::Signed: - return m_data.m_signed; - case DataType::Double: - return static_cast<int64_t>(m_data.m_double); - } - llvm_unreachable("Unhandled data type"); -} - -double JSONNumber::GetAsDouble() const { - switch (m_data_type) { - case DataType::Unsigned: - return static_cast<double>(m_data.m_unsigned); - case DataType::Signed: - return static_cast<double>(m_data.m_signed); - case DataType::Double: - return m_data.m_double; - } - llvm_unreachable("Unhandled data type"); -} - -void JSONNumber::Write(Stream &s) { - switch (m_data_type) { - case DataType::Unsigned: - s.Printf("%" PRIu64, m_data.m_unsigned); - break; - case DataType::Signed: - s.Printf("%" PRId64, m_data.m_signed); - break; - case DataType::Double: - s.Printf("%g", m_data.m_double); - break; - } -} - -JSONTrue::JSONTrue() : JSONValue(JSONValue::Kind::True) {} - -void JSONTrue::Write(Stream &s) { s.Printf("true"); } - -JSONFalse::JSONFalse() : JSONValue(JSONValue::Kind::False) {} - -void JSONFalse::Write(Stream &s) { s.Printf("false"); } - -JSONNull::JSONNull() : JSONValue(JSONValue::Kind::Null) {} - -void JSONNull::Write(Stream &s) { s.Printf("null"); } - -JSONObject::JSONObject() : JSONValue(JSONValue::Kind::Object) {} - -void JSONObject::Write(Stream &s) { - bool first = true; - s.PutChar('{'); - auto iter = m_elements.begin(), end = m_elements.end(); - for (; iter != end; iter++) { - if (first) - first = false; - else - s.PutChar(','); - JSONString key(iter->first); - JSONValue::SP value(iter->second); - key.Write(s); - s.PutChar(':'); - value->Write(s); - } - s.PutChar('}'); -} - -bool JSONObject::SetObject(const std::string &key, JSONValue::SP value) { - if (key.empty() || nullptr == value.get()) - return false; - m_elements[key] = value; - return true; -} - -JSONValue::SP JSONObject::GetObject(const std::string &key) { - auto iter = m_elements.find(key), end = m_elements.end(); - if (iter == end) - return JSONValue::SP(); - return iter->second; -} - -JSONArray::JSONArray() : JSONValue(JSONValue::Kind::Array) {} - -void JSONArray::Write(Stream &s) { - bool first = true; - s.PutChar('['); - auto iter = m_elements.begin(), end = m_elements.end(); - for (; iter != end; iter++) { - if (first) - first = false; - else - s.PutChar(','); - (*iter)->Write(s); - } - s.PutChar(']'); -} - -bool JSONArray::SetObject(Index i, JSONValue::SP value) { - if (value.get() == nullptr) - return false; - if (i < m_elements.size()) { - m_elements[i] = value; - return true; - } - if (i == m_elements.size()) { - m_elements.push_back(value); - return true; - } - return false; -} - -bool JSONArray::AppendObject(JSONValue::SP value) { - if (value.get() == nullptr) - return false; - m_elements.push_back(value); - return true; -} - -JSONValue::SP JSONArray::GetObject(Index i) { - if (i < m_elements.size()) - return m_elements[i]; - return JSONValue::SP(); -} - -JSONArray::Size JSONArray::GetNumElements() { return m_elements.size(); } - -JSONParser::JSONParser(llvm::StringRef data) : StringExtractor(data) {} - -JSONParser::Token JSONParser::GetToken(std::string &value) { - StreamString error; - - value.clear(); - SkipSpaces(); - const uint64_t start_index = m_index; - const char ch = GetChar(); - switch (ch) { - case '{': - return Token::ObjectStart; - case '}': - return Token::ObjectEnd; - case '[': - return Token::ArrayStart; - case ']': - return Token::ArrayEnd; - case ',': - return Token::Comma; - case ':': - return Token::Colon; - case '\0': - return Token::EndOfFile; - case 't': - if (GetChar() == 'r') - if (GetChar() == 'u') - if (GetChar() == 'e') - return Token::True; - break; - - case 'f': - if (GetChar() == 'a') - if (GetChar() == 'l') - if (GetChar() == 's') - if (GetChar() == 'e') - return Token::False; - break; - - case 'n': - if (GetChar() == 'u') - if (GetChar() == 'l') - if (GetChar() == 'l') - return Token::Null; - break; - - case '"': { - while (true) { - bool was_escaped = false; - int escaped_ch = GetEscapedChar(was_escaped); - if (escaped_ch == -1) { - error.Printf( - "error: an error occurred getting a character from offset %" PRIu64, - start_index); - value = std::move(error.GetString()); - return Token::Status; - - } else { - const bool is_end_quote = escaped_ch == '"'; - const bool is_null = escaped_ch == 0; - if (was_escaped || (!is_end_quote && !is_null)) { - if (CHAR_MIN <= escaped_ch && escaped_ch <= CHAR_MAX) { - value.append(1, static_cast<char>(escaped_ch)); - } else { - error.Printf("error: wide character support is needed for unicode " - "character 0x%4.4x at offset %" PRIu64, - escaped_ch, start_index); - value = std::move(error.GetString()); - return Token::Status; - } - } else if (is_end_quote) { - return Token::String; - } else if (is_null) { - value = "error: missing end quote for string"; - return Token::Status; - } - } - } - } break; - - case '-': - case '0': - case '1': - case '2': - case '3': - case '4': - case '5': - case '6': - case '7': - case '8': - case '9': { - bool done = false; - bool got_decimal_point = false; - uint64_t exp_index = 0; - bool got_int_digits = (ch >= '0') && (ch <= '9'); - bool got_frac_digits = false; - bool got_exp_digits = false; - while (!done) { - const char next_ch = PeekChar(); - switch (next_ch) { - case '0': - case '1': - case '2': - case '3': - case '4': - case '5': - case '6': - case '7': - case '8': - case '9': - if (exp_index != 0) { - got_exp_digits = true; - } else if (got_decimal_point) { - got_frac_digits = true; - } else { - got_int_digits = true; - } - ++m_index; // Skip this character - break; - - case '.': - if (got_decimal_point) { - error.Printf("error: extra decimal point found at offset %" PRIu64, - start_index); - value = std::move(error.GetString()); - return Token::Status; - } else { - got_decimal_point = true; - ++m_index; // Skip this character - } - break; - - case 'e': - case 'E': - if (exp_index != 0) { - error.Printf( - "error: extra exponent character found at offset %" PRIu64, - start_index); - value = std::move(error.GetString()); - return Token::Status; - } else { - exp_index = m_index; - ++m_index; // Skip this character - } - break; - - case '+': - case '-': - // The '+' and '-' can only come after an exponent character... - if (exp_index == m_index - 1) { - ++m_index; // Skip the exponent sign character - } else { - error.Printf("error: unexpected %c character at offset %" PRIu64, - next_ch, start_index); - value = std::move(error.GetString()); - return Token::Status; - } - break; - - default: - done = true; - break; - } - } - - if (m_index > start_index) { - value = m_packet.substr(start_index, m_index - start_index); - if (got_decimal_point) { - if (exp_index != 0) { - // We have an exponent, make sure we got exponent digits - if (got_exp_digits) { - return Token::Float; - } else { - error.Printf("error: got exponent character but no exponent digits " - "at offset in float value \"%s\"", - value.c_str()); - value = std::move(error.GetString()); - return Token::Status; - } - } else { - // No exponent, but we need at least one decimal after the decimal - // point - if (got_frac_digits) { - return Token::Float; - } else { - error.Printf("error: no digits after decimal point \"%s\"", - value.c_str()); - value = std::move(error.GetString()); - return Token::Status; - } - } - } else { - // No decimal point - if (got_int_digits) { - // We need at least some integer digits to make an integer - return Token::Integer; - } else { - error.Printf("error: no digits negate sign \"%s\"", value.c_str()); - value = std::move(error.GetString()); - return Token::Status; - } - } - } else { - error.Printf("error: invalid number found at offset %" PRIu64, - start_index); - value = std::move(error.GetString()); - return Token::Status; - } - } break; - default: - break; - } - error.Printf("error: failed to parse token at offset %" PRIu64 - " (around character '%c')", - start_index, ch); - value = std::move(error.GetString()); - return Token::Status; -} - -int JSONParser::GetEscapedChar(bool &was_escaped) { - was_escaped = false; - const char ch = GetChar(); - if (ch == '\\') { - was_escaped = true; - const char ch2 = GetChar(); - switch (ch2) { - case '"': - case '\\': - case '/': - default: - break; - - case 'b': - return '\b'; - case 'f': - return '\f'; - case 'n': - return '\n'; - case 'r': - return '\r'; - case 't': - return '\t'; - case 'u': { - const int hi_byte = DecodeHexU8(); - const int lo_byte = DecodeHexU8(); - if (hi_byte >= 0 && lo_byte >= 0) - return hi_byte << 8 | lo_byte; - return -1; - } break; - } - return ch2; - } - return ch; -} - -JSONValue::SP JSONParser::ParseJSONObject() { - // The "JSONParser::Token::ObjectStart" token should have already been - // consumed by the time this function is called - std::unique_ptr<JSONObject> dict_up(new JSONObject()); - - std::string value; - std::string key; - while (true) { - JSONParser::Token token = GetToken(value); - - if (token == JSONParser::Token::String) { - key.swap(value); - token = GetToken(value); - if (token == JSONParser::Token::Colon) { - JSONValue::SP value_sp = ParseJSONValue(); - if (value_sp) - dict_up->SetObject(key, value_sp); - else - break; - } - } else if (token == JSONParser::Token::ObjectEnd) { - return JSONValue::SP(dict_up.release()); - } else if (token == JSONParser::Token::Comma) { - continue; - } else { - break; - } - } - return JSONValue::SP(); -} - -JSONValue::SP JSONParser::ParseJSONArray() { - // The "JSONParser::Token::ObjectStart" token should have already been - // consumed by the time this function is called - std::unique_ptr<JSONArray> array_up(new JSONArray()); - - std::string value; - std::string key; - while (true) { - JSONValue::SP value_sp = ParseJSONValue(); - if (value_sp) - array_up->AppendObject(value_sp); - else - break; - - JSONParser::Token token = GetToken(value); - if (token == JSONParser::Token::Comma) { - continue; - } else if (token == JSONParser::Token::ArrayEnd) { - return JSONValue::SP(array_up.release()); - } else { - break; - } - } - return JSONValue::SP(); -} - -JSONValue::SP JSONParser::ParseJSONValue() { - std::string value; - const JSONParser::Token token = GetToken(value); - switch (token) { - case JSONParser::Token::ObjectStart: - return ParseJSONObject(); - - case JSONParser::Token::ArrayStart: - return ParseJSONArray(); - - case JSONParser::Token::Integer: { - if (value.front() == '-') { - int64_t sval = 0; - if (!llvm::StringRef(value).getAsInteger(0, sval)) - return JSONValue::SP(new JSONNumber(sval)); - } else { - uint64_t uval = 0; - if (!llvm::StringRef(value).getAsInteger(0, uval)) - return JSONValue::SP(new JSONNumber(uval)); - } - } break; - - case JSONParser::Token::Float: { - double D; - if (!llvm::StringRef(value).getAsDouble(D)) - return JSONValue::SP(new JSONNumber(D)); - } break; - - case JSONParser::Token::String: - return JSONValue::SP(new JSONString(value)); - - case JSONParser::Token::True: - return JSONValue::SP(new JSONTrue()); - - case JSONParser::Token::False: - return JSONValue::SP(new JSONFalse()); - - case JSONParser::Token::Null: - return JSONValue::SP(new JSONNull()); - - default: - break; - } - return JSONValue::SP(); -} diff --git a/source/Utility/Listener.cpp b/source/Utility/Listener.cpp index 50c56406c2ca..c2e537ba7dee 100644 --- a/source/Utility/Listener.cpp +++ b/source/Utility/Listener.cpp @@ -42,8 +42,8 @@ Listener::Listener(const char *name) m_events_mutex() { Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_OBJECT)); if (log != nullptr) - log->Printf("%p Listener::Listener('%s')", static_cast<void *>(this), - m_name.c_str()); + LLDB_LOGF(log, "%p Listener::Listener('%s')", static_cast<void *>(this), + m_name.c_str()); } Listener::~Listener() { @@ -51,9 +51,8 @@ Listener::~Listener() { Clear(); - if (log) - log->Printf("%p Listener::%s('%s')", static_cast<void *>(this), - __FUNCTION__, m_name.c_str()); + LLDB_LOGF(log, "%p Listener::%s('%s')", static_cast<void *>(this), + __FUNCTION__, m_name.c_str()); } void Listener::Clear() { @@ -78,9 +77,8 @@ void Listener::Clear() { manager_sp->RemoveListener(this); } - if (log) - log->Printf("%p Listener::%s('%s')", static_cast<void *>(this), - __FUNCTION__, m_name.c_str()); + LLDB_LOGF(log, "%p Listener::%s('%s')", static_cast<void *>(this), + __FUNCTION__, m_name.c_str()); } uint32_t Listener::StartListeningForEvents(Broadcaster *broadcaster, @@ -101,10 +99,11 @@ uint32_t Listener::StartListeningForEvents(Broadcaster *broadcaster, Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_EVENTS)); if (log != nullptr) - log->Printf("%p Listener::StartListeningForEvents (broadcaster = %p, " - "mask = 0x%8.8x) acquired_mask = 0x%8.8x for %s", - static_cast<void *>(this), static_cast<void *>(broadcaster), - event_mask, acquired_mask, m_name.c_str()); + LLDB_LOGF(log, + "%p Listener::StartListeningForEvents (broadcaster = %p, " + "mask = 0x%8.8x) acquired_mask = 0x%8.8x for %s", + static_cast<void *>(this), static_cast<void *>(broadcaster), + event_mask, acquired_mask, m_name.c_str()); return acquired_mask; } @@ -132,12 +131,13 @@ uint32_t Listener::StartListeningForEvents(Broadcaster *broadcaster, Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_EVENTS)); if (log != nullptr) { void **pointer = reinterpret_cast<void **>(&callback); - log->Printf("%p Listener::StartListeningForEvents (broadcaster = %p, " - "mask = 0x%8.8x, callback = %p, user_data = %p) " - "acquired_mask = 0x%8.8x for %s", - static_cast<void *>(this), static_cast<void *>(broadcaster), - event_mask, *pointer, static_cast<void *>(callback_user_data), - acquired_mask, m_name.c_str()); + LLDB_LOGF(log, + "%p Listener::StartListeningForEvents (broadcaster = %p, " + "mask = 0x%8.8x, callback = %p, user_data = %p) " + "acquired_mask = 0x%8.8x for %s", + static_cast<void *>(this), static_cast<void *>(broadcaster), + event_mask, *pointer, static_cast<void *>(callback_user_data), + acquired_mask, m_name.c_str()); } return acquired_mask; @@ -202,9 +202,9 @@ void Listener::BroadcasterManagerWillDestruct(BroadcasterManagerSP manager_sp) { void Listener::AddEvent(EventSP &event_sp) { Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_EVENTS)); if (log != nullptr) - log->Printf("%p Listener('%s')::AddEvent (event_sp = {%p})", - static_cast<void *>(this), m_name.c_str(), - static_cast<void *>(event_sp.get())); + LLDB_LOGF(log, "%p Listener('%s')::AddEvent (event_sp = {%p})", + static_cast<void *>(this), m_name.c_str(), + static_cast<void *>(event_sp.get())); std::lock_guard<std::mutex> guard(m_events_mutex); m_events.push_back(event_sp); @@ -290,14 +290,15 @@ bool Listener::FindNextEventInternal( event_sp = *pos; if (log != nullptr) - log->Printf("%p '%s' Listener::FindNextEventInternal(broadcaster=%p, " - "broadcaster_names=%p[%u], event_type_mask=0x%8.8x, " - "remove=%i) event %p", - static_cast<void *>(this), GetName(), - static_cast<void *>(broadcaster), - static_cast<const void *>(broadcaster_names), - num_broadcaster_names, event_type_mask, remove, - static_cast<void *>(event_sp.get())); + LLDB_LOGF(log, + "%p '%s' Listener::FindNextEventInternal(broadcaster=%p, " + "broadcaster_names=%p[%u], event_type_mask=0x%8.8x, " + "remove=%i) event %p", + static_cast<void *>(this), GetName(), + static_cast<void *>(broadcaster), + static_cast<const void *>(broadcaster_names), + num_broadcaster_names, event_type_mask, remove, + static_cast<void *>(event_sp.get())); if (remove) { m_events.erase(pos); @@ -366,15 +367,13 @@ bool Listener::GetEventInternal( if (result == std::cv_status::timeout) { log = lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_EVENTS); - if (log) - log->Printf("%p Listener::GetEventInternal() timed out for %s", - static_cast<void *>(this), m_name.c_str()); + LLDB_LOGF(log, "%p Listener::GetEventInternal() timed out for %s", + static_cast<void *>(this), m_name.c_str()); return false; } else if (result != std::cv_status::no_timeout) { log = lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_EVENTS); - if (log) - log->Printf("%p Listener::GetEventInternal() unknown error for %s", - static_cast<void *>(this), m_name.c_str()); + LLDB_LOGF(log, "%p Listener::GetEventInternal() unknown error for %s", + static_cast<void *>(this), m_name.c_str()); return false; } } diff --git a/source/Utility/Log.cpp b/source/Utility/Log.cpp index 217b0d2ba97b..ab5e630114a6 100644 --- a/source/Utility/Log.cpp +++ b/source/Utility/Log.cpp @@ -9,7 +9,6 @@ #include "lldb/Utility/Log.h" #include "lldb/Utility/VASPrintf.h" -#include "llvm/ADT/STLExtras.h" #include "llvm/ADT/SmallString.h" #include "llvm/ADT/Twine.h" #include "llvm/ADT/iterator.h" @@ -38,13 +37,22 @@ using namespace lldb_private; llvm::ManagedStatic<Log::ChannelMap> Log::g_channel_map; -void Log::ListCategories(llvm::raw_ostream &stream, const ChannelMap::value_type &entry) { - stream << llvm::formatv("Logging categories for '{0}':\n", entry.first()); - stream << " all - all available logging categories\n"; - stream << " default - default set of logging categories\n"; +void Log::ForEachCategory( + const Log::ChannelMap::value_type &entry, + llvm::function_ref<void(llvm::StringRef, llvm::StringRef)> lambda) { + lambda("all", "all available logging categories"); + lambda("default", "default set of logging categories"); for (const auto &category : entry.second.m_channel.categories) - stream << llvm::formatv(" {0} - {1}\n", category.name, - category.description); + lambda(category.name, category.description); +} + +void Log::ListCategories(llvm::raw_ostream &stream, + const ChannelMap::value_type &entry) { + stream << llvm::formatv("Logging categories for '{0}':\n", entry.first()); + ForEachCategory(entry, + [&stream](llvm::StringRef name, llvm::StringRef description) { + stream << llvm::formatv(" {0} - {1}\n", name, description); + }); } uint32_t Log::GetFlags(llvm::raw_ostream &stream, const ChannelMap::value_type &entry, @@ -237,6 +245,23 @@ void Log::DisableAllLogChannels() { entry.second.Disable(UINT32_MAX); } +void Log::ForEachChannelCategory( + llvm::StringRef channel, + llvm::function_ref<void(llvm::StringRef, llvm::StringRef)> lambda) { + auto ch = g_channel_map->find(channel); + if (ch == g_channel_map->end()) + return; + + ForEachCategory(*ch, lambda); +} + +std::vector<llvm::StringRef> Log::ListChannels() { + std::vector<llvm::StringRef> result; + for (const auto &channel : *g_channel_map) + result.push_back(channel.first()); + return result; +} + void Log::ListAllLogChannels(llvm::raw_ostream &stream) { if (g_channel_map->empty()) { stream << "No logging channels are currently registered.\n"; diff --git a/source/Utility/Logging.cpp b/source/Utility/Logging.cpp index c0856e5d9267..22f38192fa5d 100644 --- a/source/Utility/Logging.cpp +++ b/source/Utility/Logging.cpp @@ -62,13 +62,3 @@ Log *lldb_private::GetLogIfAllCategoriesSet(uint32_t mask) { Log *lldb_private::GetLogIfAnyCategoriesSet(uint32_t mask) { return g_log_channel.GetLogIfAny(mask); } - - -void lldb_private::LogIfAnyCategoriesSet(uint32_t mask, const char *format, ...) { - if (Log *log = GetLogIfAnyCategoriesSet(mask)) { - va_list args; - va_start(args, format); - log->VAPrintf(format, args); - va_end(args); - } -} diff --git a/source/Utility/ProcessInfo.cpp b/source/Utility/ProcessInfo.cpp index b67ae8779000..5743d223be4f 100644 --- a/source/Utility/ProcessInfo.cpp +++ b/source/Utility/ProcessInfo.cpp @@ -42,8 +42,8 @@ const char *ProcessInfo::GetName() const { return m_executable.GetFilename().GetCString(); } -size_t ProcessInfo::GetNameLength() const { - return m_executable.GetFilename().GetLength(); +llvm::StringRef ProcessInfo::GetNameAsStringRef() const { + return m_executable.GetFilename().GetStringRef(); } void ProcessInfo::Dump(Stream &s, Platform *platform) const { @@ -169,13 +169,15 @@ void ProcessInstanceInfo::DumpTableHeader(Stream &s, bool show_args, if (verbose) { s.Printf("PID PARENT USER GROUP EFF USER EFF GROUP TRIPLE " - " %s\n", + " %s\n", label); - s.PutCString("====== ====== ========== ========== ========== ========== " - "======================== ============================\n"); + s.PutCString( + "====== ====== ========== ========== ========== ========== " + "============================== ============================\n"); } else { - s.Printf("PID PARENT USER TRIPLE %s\n", label); - s.PutCString("====== ====== ========== ======================== " + s.Printf("PID PARENT USER TRIPLE %s\n", + label); + s.PutCString("====== ====== ========== ============================== " "============================\n"); } } @@ -189,34 +191,47 @@ void ProcessInstanceInfo::DumpAsTableRow(Stream &s, UserIDResolver &resolver, if (m_arch.IsValid()) m_arch.DumpTriple(arch_strm); - auto print = [&](UserIDResolver::id_t id, - llvm::Optional<llvm::StringRef> (UserIDResolver::*get)( + auto print = [&](bool (ProcessInstanceInfo::*isValid)() const, + uint32_t (ProcessInstanceInfo::*getID)() const, + llvm::Optional<llvm::StringRef> (UserIDResolver::*getName)( UserIDResolver::id_t id)) { - if (auto name = (resolver.*get)(id)) - s.Format("{0,-10} ", *name); + const char *format = "{0,-10} "; + if (!(this->*isValid)()) { + s.Format(format, ""); + return; + } + uint32_t id = (this->*getID)(); + if (auto name = (resolver.*getName)(id)) + s.Format(format, *name); else - s.Format("{0,-10} ", id); + s.Format(format, id); }; if (verbose) { - print(m_uid, &UserIDResolver::GetUserName); - print(m_gid, &UserIDResolver::GetGroupName); - print(m_euid, &UserIDResolver::GetUserName); - print(m_egid, &UserIDResolver::GetGroupName); - - s.Printf("%-24s ", arch_strm.GetData()); + print(&ProcessInstanceInfo::UserIDIsValid, + &ProcessInstanceInfo::GetUserID, &UserIDResolver::GetUserName); + print(&ProcessInstanceInfo::GroupIDIsValid, + &ProcessInstanceInfo::GetGroupID, &UserIDResolver::GetGroupName); + print(&ProcessInstanceInfo::EffectiveUserIDIsValid, + &ProcessInstanceInfo::GetEffectiveUserID, + &UserIDResolver::GetUserName); + print(&ProcessInstanceInfo::EffectiveGroupIDIsValid, + &ProcessInstanceInfo::GetEffectiveGroupID, + &UserIDResolver::GetGroupName); + + s.Printf("%-30s ", arch_strm.GetData()); } else { - print(m_euid, &UserIDResolver::GetUserName); - s.Printf(" %-24s ", arch_strm.GetData()); + print(&ProcessInstanceInfo::EffectiveUserIDIsValid, + &ProcessInstanceInfo::GetEffectiveUserID, + &UserIDResolver::GetUserName); + s.Printf("%-30s ", arch_strm.GetData()); } if (verbose || show_args) { + s.PutCString(m_arg0); const uint32_t argc = m_arguments.GetArgumentCount(); - if (argc > 0) { - for (uint32_t i = 0; i < argc; i++) { - if (i > 0) - s.PutChar(' '); - s.PutCString(m_arguments.GetArgumentAtIndex(i)); - } + for (uint32_t i = 0; i < argc; i++) { + s.PutChar(' '); + s.PutCString(m_arguments.GetArgumentAtIndex(i)); } } else { s.PutCString(GetName()); @@ -226,8 +241,14 @@ void ProcessInstanceInfo::DumpAsTableRow(Stream &s, UserIDResolver &resolver, } } +bool ProcessInstanceInfoMatch::ArchitectureMatches( + const ArchSpec &arch_spec) const { + return !m_match_info.GetArchitecture().IsValid() || + m_match_info.GetArchitecture().IsCompatibleMatch(arch_spec); +} + bool ProcessInstanceInfoMatch::NameMatches(const char *process_name) const { - if (m_name_match_type == NameMatch::Ignore || process_name == nullptr) + if (m_name_match_type == NameMatch::Ignore) return true; const char *match_name = m_match_info.GetName(); if (!match_name) @@ -236,11 +257,8 @@ bool ProcessInstanceInfoMatch::NameMatches(const char *process_name) const { return lldb_private::NameMatches(process_name, m_name_match_type, match_name); } -bool ProcessInstanceInfoMatch::Matches( +bool ProcessInstanceInfoMatch::ProcessIDsMatch( const ProcessInstanceInfo &proc_info) const { - if (!NameMatches(proc_info.GetName())) - return false; - if (m_match_info.ProcessIDIsValid() && m_match_info.GetProcessID() != proc_info.GetProcessID()) return false; @@ -248,7 +266,11 @@ bool ProcessInstanceInfoMatch::Matches( if (m_match_info.ParentProcessIDIsValid() && m_match_info.GetParentProcessID() != proc_info.GetParentProcessID()) return false; + return true; +} +bool ProcessInstanceInfoMatch::UserIDsMatch( + const ProcessInstanceInfo &proc_info) const { if (m_match_info.UserIDIsValid() && m_match_info.GetUserID() != proc_info.GetUserID()) return false; @@ -264,13 +286,14 @@ bool ProcessInstanceInfoMatch::Matches( if (m_match_info.EffectiveGroupIDIsValid() && m_match_info.GetEffectiveGroupID() != proc_info.GetEffectiveGroupID()) return false; - - if (m_match_info.GetArchitecture().IsValid() && - !m_match_info.GetArchitecture().IsCompatibleMatch( - proc_info.GetArchitecture())) - return false; return true; } +bool ProcessInstanceInfoMatch::Matches( + const ProcessInstanceInfo &proc_info) const { + return ArchitectureMatches(proc_info.GetArchitecture()) && + ProcessIDsMatch(proc_info) && UserIDsMatch(proc_info) && + NameMatches(proc_info.GetName()); +} bool ProcessInstanceInfoMatch::MatchAllProcesses() const { if (m_name_match_type != NameMatch::Ignore) diff --git a/source/Utility/RegularExpression.cpp b/source/Utility/RegularExpression.cpp index 0192e8b8a01a..fd9d963f7294 100644 --- a/source/Utility/RegularExpression.cpp +++ b/source/Utility/RegularExpression.cpp @@ -8,168 +8,34 @@ #include "lldb/Utility/RegularExpression.h" -#include "llvm/ADT/StringRef.h" - #include <string> -// Enable enhanced mode if it is available. This allows for things like \d for -// digit, \s for space, and many more, but it isn't available everywhere. -#if defined(REG_ENHANCED) -#define DEFAULT_COMPILE_FLAGS (REG_ENHANCED | REG_EXTENDED) -#else -#define DEFAULT_COMPILE_FLAGS (REG_EXTENDED) -#endif - using namespace lldb_private; -RegularExpression::RegularExpression() : m_re(), m_comp_err(1), m_preg() { - memset(&m_preg, 0, sizeof(m_preg)); -} - -// Constructor that compiles "re" using "flags" and stores the resulting -// compiled regular expression into this object. RegularExpression::RegularExpression(llvm::StringRef str) - : RegularExpression() { - Compile(str); -} + : m_regex_text(str), + // m_regex does not reference str anymore after it is constructed. + m_regex(llvm::Regex(str)) {} RegularExpression::RegularExpression(const RegularExpression &rhs) - : RegularExpression() { - Compile(rhs.GetText()); -} - -const RegularExpression &RegularExpression:: -operator=(const RegularExpression &rhs) { - if (&rhs != this) - Compile(rhs.GetText()); - return *this; -} - -// Destructor -// -// Any previously compiled regular expression contained in this object will be -// freed. -RegularExpression::~RegularExpression() { Free(); } - -// Compile a regular expression using the supplied regular expression text and -// flags. The compiled regular expression lives in this object so that it can -// be readily used for regular expression matches. Execute() can be called -// after the regular expression is compiled. Any previously compiled regular -// expression contained in this object will be freed. -// -// RETURNS -// True if the regular expression compiles successfully, false -// otherwise. -bool RegularExpression::Compile(llvm::StringRef str) { - Free(); - - // regcomp() on darwin does not recognize "" as a valid regular expression, - // so we substitute it with an equivalent non-empty one. - m_re = str.empty() ? "()" : str; - m_comp_err = ::regcomp(&m_preg, m_re.c_str(), DEFAULT_COMPILE_FLAGS); - return m_comp_err == 0; -} + : RegularExpression(rhs.GetText()) {} -// Execute a regular expression match using the compiled regular expression -// that is already in this object against the match string "s". If any parens -// are used for regular expression matches "match_count" should indicate the -// number of regmatch_t values that are present in "match_ptr". The regular -// expression will be executed using the "execute_flags". -bool RegularExpression::Execute(llvm::StringRef str, Match *match) const { - int err = 1; - if (m_comp_err == 0) { - // Argument to regexec must be null-terminated. - std::string reg_str = str; - if (match) { - err = ::regexec(&m_preg, reg_str.c_str(), match->GetSize(), - match->GetData(), 0); - } else { - err = ::regexec(&m_preg, reg_str.c_str(), 0, nullptr, 0); - } - } - - if (err != 0) { - // The regular expression didn't compile, so clear the matches - if (match) - match->Clear(); +bool RegularExpression::Execute( + llvm::StringRef str, + llvm::SmallVectorImpl<llvm::StringRef> *matches) const { + if (!IsValid()) return false; - } - return true; -} - -bool RegularExpression::Match::GetMatchAtIndex(llvm::StringRef s, uint32_t idx, - std::string &match_str) const { - llvm::StringRef match_str_ref; - if (GetMatchAtIndex(s, idx, match_str_ref)) { - match_str = match_str_ref.str(); - return true; - } - return false; + return m_regex.match(str, matches); } -bool RegularExpression::Match::GetMatchAtIndex( - llvm::StringRef s, uint32_t idx, llvm::StringRef &match_str) const { - if (idx < m_matches.size()) { - if (m_matches[idx].rm_eo == -1 && m_matches[idx].rm_so == -1) - return false; - - if (m_matches[idx].rm_eo == m_matches[idx].rm_so) { - // Matched the empty string... - match_str = llvm::StringRef(); - return true; - } else if (m_matches[idx].rm_eo > m_matches[idx].rm_so) { - match_str = s.substr(m_matches[idx].rm_so, - m_matches[idx].rm_eo - m_matches[idx].rm_so); - return true; - } - } - return false; -} - -bool RegularExpression::Match::GetMatchSpanningIndices( - llvm::StringRef s, uint32_t idx1, uint32_t idx2, - llvm::StringRef &match_str) const { - if (idx1 < m_matches.size() && idx2 < m_matches.size()) { - if (m_matches[idx1].rm_so == m_matches[idx2].rm_eo) { - // Matched the empty string... - match_str = llvm::StringRef(); - return true; - } else if (m_matches[idx1].rm_so < m_matches[idx2].rm_eo) { - match_str = s.substr(m_matches[idx1].rm_so, - m_matches[idx2].rm_eo - m_matches[idx1].rm_so); - return true; - } - } - return false; -} +bool RegularExpression::IsValid() const { return m_regex.isValid(); } -// Returns true if the regular expression compiled and is ready for execution. -bool RegularExpression::IsValid() const { return m_comp_err == 0; } - -// Returns the text that was used to compile the current regular expression. -llvm::StringRef RegularExpression::GetText() const { return m_re; } - -// Free any contained compiled regular expressions. -void RegularExpression::Free() { - if (m_comp_err == 0) { - m_re.clear(); - regfree(&m_preg); - // Set a compile error since we no longer have a valid regex - m_comp_err = 1; - } -} - -size_t RegularExpression::GetErrorAsCString(char *err_str, - size_t err_str_max_len) const { - if (m_comp_err == 0) { - if (err_str && err_str_max_len) - *err_str = '\0'; - return 0; - } - - return ::regerror(m_comp_err, &m_preg, err_str, err_str_max_len); -} +llvm::StringRef RegularExpression::GetText() const { return m_regex_text; } -bool RegularExpression::operator<(const RegularExpression &rhs) const { - return (m_re < rhs.m_re); +llvm::Error RegularExpression::GetError() const { + std::string error; + if (!m_regex.isValid(error)) + return llvm::make_error<llvm::StringError>(llvm::inconvertibleErrorCode(), + error); + return llvm::Error::success(); } diff --git a/source/Utility/Reproducer.cpp b/source/Utility/Reproducer.cpp index 479ed311d1de..4777d7576a32 100644 --- a/source/Utility/Reproducer.cpp +++ b/source/Utility/Reproducer.cpp @@ -136,7 +136,17 @@ FileSpec Reproducer::GetReproducerPath() const { return {}; } -Generator::Generator(const FileSpec &root) : m_root(root), m_done(false) {} +static FileSpec MakeAbsolute(FileSpec file_spec) { + SmallString<128> path; + file_spec.GetPath(path, false); + llvm::sys::fs::make_absolute(path); + return FileSpec(path, file_spec.GetPathStyle()); +} + +Generator::Generator(FileSpec root) + : m_root(MakeAbsolute(std::move(root))), m_done(false) { + GetOrCreate<repro::WorkingDirectoryProvider>(); +} Generator::~Generator() {} @@ -175,8 +185,8 @@ void Generator::AddProvidersToIndex() { index.AppendPathComponent("index.yaml"); std::error_code EC; - auto strm = llvm::make_unique<raw_fd_ostream>(index.GetPath(), EC, - sys::fs::OpenFlags::F_None); + auto strm = std::make_unique<raw_fd_ostream>(index.GetPath(), EC, + sys::fs::OpenFlags::OF_None); yaml::Output yout(*strm); std::vector<std::string> files; @@ -188,7 +198,8 @@ void Generator::AddProvidersToIndex() { yout << files; } -Loader::Loader(const FileSpec &root) : m_root(root), m_loaded(false) {} +Loader::Loader(FileSpec root) + : m_root(MakeAbsolute(std::move(root))), m_loaded(false) {} llvm::Error Loader::LoadIndex() { if (m_loaded) @@ -223,7 +234,7 @@ bool Loader::HasFile(StringRef file) { llvm::Expected<std::unique_ptr<DataRecorder>> DataRecorder::Create(const FileSpec &filename) { std::error_code ec; - auto recorder = llvm::make_unique<DataRecorder>(std::move(filename), ec); + auto recorder = std::make_unique<DataRecorder>(std::move(filename), ec); if (ec) return llvm::errorCodeToError(ec); return std::move(recorder); @@ -254,7 +265,7 @@ void CommandProvider::Keep() { FileSpec file = GetRoot().CopyByAppendingPathComponent(Info::file); std::error_code ec; - llvm::raw_fd_ostream os(file.GetPath(), ec, llvm::sys::fs::F_Text); + llvm::raw_fd_ostream os(file.GetPath(), ec, llvm::sys::fs::OF_Text); if (ec) return; yaml::Output yout(os); @@ -266,20 +277,78 @@ void CommandProvider::Discard() { m_data_recorders.clear(); } void VersionProvider::Keep() { FileSpec file = GetRoot().CopyByAppendingPathComponent(Info::file); std::error_code ec; - llvm::raw_fd_ostream os(file.GetPath(), ec, llvm::sys::fs::F_Text); + llvm::raw_fd_ostream os(file.GetPath(), ec, llvm::sys::fs::OF_Text); if (ec) return; os << m_version << "\n"; } +void WorkingDirectoryProvider::Keep() { + FileSpec file = GetRoot().CopyByAppendingPathComponent(Info::file); + std::error_code ec; + llvm::raw_fd_ostream os(file.GetPath(), ec, llvm::sys::fs::OF_Text); + if (ec) + return; + os << m_cwd << "\n"; +} + +llvm::raw_ostream *ProcessGDBRemoteProvider::GetHistoryStream() { + FileSpec history_file = GetRoot().CopyByAppendingPathComponent(Info::file); + + std::error_code EC; + m_stream_up = std::make_unique<raw_fd_ostream>(history_file.GetPath(), EC, + sys::fs::OpenFlags::OF_Text); + return m_stream_up.get(); +} + +std::unique_ptr<CommandLoader> CommandLoader::Create(Loader *loader) { + if (!loader) + return {}; + + FileSpec file = loader->GetFile<repro::CommandProvider::Info>(); + if (!file) + return {}; + + auto error_or_file = llvm::MemoryBuffer::getFile(file.GetPath()); + if (auto err = error_or_file.getError()) + return {}; + + std::vector<std::string> files; + llvm::yaml::Input yin((*error_or_file)->getBuffer()); + yin >> files; + + if (auto err = yin.error()) + return {}; + + for (auto &file : files) { + FileSpec absolute_path = + loader->GetRoot().CopyByAppendingPathComponent(file); + file = absolute_path.GetPath(); + } + + return std::make_unique<CommandLoader>(std::move(files)); +} + +llvm::Optional<std::string> CommandLoader::GetNextFile() { + if (m_index >= m_files.size()) + return {}; + return m_files[m_index++]; +} + void ProviderBase::anchor() {} -char ProviderBase::ID = 0; char CommandProvider::ID = 0; char FileProvider::ID = 0; +char ProcessGDBRemoteProvider::ID = 0; +char ProviderBase::ID = 0; char VersionProvider::ID = 0; +char WorkingDirectoryProvider::ID = 0; const char *CommandProvider::Info::file = "command-interpreter.yaml"; const char *CommandProvider::Info::name = "command-interpreter"; const char *FileProvider::Info::file = "files.yaml"; const char *FileProvider::Info::name = "files"; +const char *ProcessGDBRemoteProvider::Info::file = "gdb-remote.yaml"; +const char *ProcessGDBRemoteProvider::Info::name = "gdb-remote"; const char *VersionProvider::Info::file = "version.txt"; const char *VersionProvider::Info::name = "version"; +const char *WorkingDirectoryProvider::Info::file = "cwd.txt"; +const char *WorkingDirectoryProvider::Info::name = "cwd"; diff --git a/source/Utility/Scalar.cpp b/source/Utility/Scalar.cpp index 23d50b9eaba5..e9aec17b6650 100644 --- a/source/Utility/Scalar.cpp +++ b/source/Utility/Scalar.cpp @@ -416,6 +416,51 @@ Scalar &Scalar::operator=(llvm::APInt rhs) { Scalar::~Scalar() = default; +Scalar::Type Scalar::GetBestTypeForBitSize(size_t bit_size, bool sign) { + // Scalar types are always host types, hence the sizeof(). + if (sign) { + if (bit_size <= sizeof(int)*8) return Scalar::e_sint; + if (bit_size <= sizeof(long)*8) return Scalar::e_slong; + if (bit_size <= sizeof(long long)*8) return Scalar::e_slonglong; + if (bit_size <= 128) return Scalar::e_sint128; + if (bit_size <= 256) return Scalar::e_sint256; + if (bit_size <= 512) return Scalar::e_sint512; + } else { + if (bit_size <= sizeof(unsigned int)*8) return Scalar::e_uint; + if (bit_size <= sizeof(unsigned long)*8) return Scalar::e_ulong; + if (bit_size <= sizeof(unsigned long long)*8) return Scalar::e_ulonglong; + if (bit_size <= 128) return Scalar::e_uint128; + if (bit_size <= 256) return Scalar::e_uint256; + if (bit_size <= 512) return Scalar::e_uint512; + } + return Scalar::e_void; +} + +void Scalar::TruncOrExtendTo(Scalar::Type type, uint16_t bits) { + switch (type) { + case e_sint: + case e_slong: + case e_slonglong: + case e_sint128: + case e_sint256: + case e_sint512: + m_integer = m_integer.sextOrTrunc(bits); + break; + case e_uint: + case e_ulong: + case e_ulonglong: + case e_uint128: + case e_uint256: + case e_uint512: + m_integer = m_integer.zextOrTrunc(bits); + break; + default: + llvm_unreachable("Promoting a Scalar to a specific number of bits is only " + "supported for integer types."); + } + m_type = type; +} + bool Scalar::Promote(Scalar::Type type) { bool success = false; switch (m_type) { diff --git a/source/Utility/SelectHelper.cpp b/source/Utility/SelectHelper.cpp index ff21d99e400a..9f5ca586e1ef 100644 --- a/source/Utility/SelectHelper.cpp +++ b/source/Utility/SelectHelper.cpp @@ -92,7 +92,7 @@ static void updateMaxFd(llvm::Optional<lldb::socket_t> &vold, lldb_private::Status SelectHelper::Select() { lldb_private::Status error; -#ifdef _MSC_VER +#ifdef _WIN32 // On windows FD_SETSIZE limits the number of file descriptors, not their // numeric value. lldbassert(m_fd_map.size() <= FD_SETSIZE); @@ -107,7 +107,7 @@ lldb_private::Status SelectHelper::Select() { for (auto &pair : m_fd_map) { pair.second.PrepareForSelect(); const lldb::socket_t fd = pair.first; -#if !defined(__APPLE__) && !defined(_MSC_VER) +#if !defined(__APPLE__) && !defined(_WIN32) lldbassert(fd < static_cast<int>(FD_SETSIZE)); if (fd >= static_cast<int>(FD_SETSIZE)) { error.SetErrorStringWithFormat("%i is too large for select()", fd); diff --git a/source/Utility/StreamGDBRemote.cpp b/source/Utility/StreamGDBRemote.cpp deleted file mode 100644 index c710bbe3eecb..000000000000 --- a/source/Utility/StreamGDBRemote.cpp +++ /dev/null @@ -1,45 +0,0 @@ -//===-- StreamGDBRemote.cpp -------------------------------------*- C++ -*-===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// - -#include "lldb/Utility/StreamGDBRemote.h" - -#include "lldb/Utility/Flags.h" -#include "lldb/Utility/Stream.h" - -#include <stdio.h> - -using namespace lldb; -using namespace lldb_private; - -StreamGDBRemote::StreamGDBRemote() : StreamString() {} - -StreamGDBRemote::StreamGDBRemote(uint32_t flags, uint32_t addr_size, - ByteOrder byte_order) - : StreamString(flags, addr_size, byte_order) {} - -StreamGDBRemote::~StreamGDBRemote() {} - -int StreamGDBRemote::PutEscapedBytes(const void *s, size_t src_len) { - int bytes_written = 0; - const uint8_t *src = static_cast<const uint8_t *>(s); - bool binary_is_set = m_flags.Test(eBinary); - m_flags.Clear(eBinary); - while (src_len) { - uint8_t byte = *src; - src++; - src_len--; - if (byte == 0x23 || byte == 0x24 || byte == 0x7d || byte == 0x2a) { - bytes_written += PutChar(0x7d); - byte ^= 0x20; - } - bytes_written += PutChar(byte); - }; - if (binary_is_set) - m_flags.Set(eBinary); - return bytes_written; -} diff --git a/source/Utility/StringExtractor.cpp b/source/Utility/StringExtractor.cpp index 502f468da3cc..87fe4f13e450 100644 --- a/source/Utility/StringExtractor.cpp +++ b/source/Utility/StringExtractor.cpp @@ -296,34 +296,6 @@ size_t StringExtractor::GetHexBytesAvail(llvm::MutableArrayRef<uint8_t> dest) { return bytes_extracted; } -// Consume ASCII hex nibble character pairs until we have decoded byte_size -// bytes of data. - -uint64_t StringExtractor::GetHexWithFixedSize(uint32_t byte_size, - bool little_endian, - uint64_t fail_value) { - if (byte_size <= 8 && GetBytesLeft() >= byte_size * 2) { - uint64_t result = 0; - uint32_t i; - if (little_endian) { - // Little Endian - uint32_t shift_amount; - for (i = 0, shift_amount = 0; i < byte_size && IsGood(); - ++i, shift_amount += 8) { - result |= (static_cast<uint64_t>(GetHexU8()) << shift_amount); - } - } else { - // Big Endian - for (i = 0; i < byte_size && IsGood(); ++i) { - result <<= 8; - result |= GetHexU8(); - } - } - } - m_index = UINT64_MAX; - return fail_value; -} - size_t StringExtractor::GetHexByteString(std::string &str) { str.clear(); str.reserve(GetBytesLeft() / 2); diff --git a/source/Utility/StringLexer.cpp b/source/Utility/StringLexer.cpp index 958a9580db7a..c357cb0fb553 100644 --- a/source/Utility/StringLexer.cpp +++ b/source/Utility/StringLexer.cpp @@ -11,7 +11,7 @@ #include <algorithm> #include <assert.h> -using namespace lldb_utility; +using namespace lldb_private; StringLexer::StringLexer(std::string s) : m_data(s), m_position(0) {} diff --git a/source/Utility/StringList.cpp b/source/Utility/StringList.cpp index fb0d9be8797d..5e06b6b69fc0 100644 --- a/source/Utility/StringList.cpp +++ b/source/Utility/StringList.cpp @@ -61,10 +61,8 @@ void StringList::AppendList(const char **strv, int strc) { } void StringList::AppendList(StringList strings) { - size_t len = strings.GetSize(); - - for (size_t i = 0; i < len; ++i) - m_strings.push_back(strings.GetStringAtIndex(i)); + m_strings.reserve(m_strings.size() + strings.GetSize()); + m_strings.insert(m_strings.end(), strings.begin(), strings.end()); } size_t StringList::GetSize() const { return m_strings.size(); } @@ -100,10 +98,9 @@ void StringList::Join(const char *separator, Stream &strm) { void StringList::Clear() { m_strings.clear(); } -void StringList::LongestCommonPrefix(std::string &common_prefix) { - common_prefix.clear(); +std::string StringList::LongestCommonPrefix() { if (m_strings.empty()) - return; + return {}; auto args = llvm::makeArrayRef(m_strings); llvm::StringRef prefix = args.front(); @@ -115,7 +112,7 @@ void StringList::LongestCommonPrefix(std::string &common_prefix) { } prefix = prefix.take_front(count); } - common_prefix = prefix; + return prefix.str(); } void StringList::InsertStringAtIndex(size_t idx, const char *str) { @@ -226,29 +223,6 @@ StringList &StringList::operator=(const std::vector<std::string> &rhs) { return *this; } -size_t StringList::AutoComplete(llvm::StringRef s, StringList &matches, - size_t &exact_idx) const { - matches.Clear(); - exact_idx = SIZE_MAX; - if (s.empty()) { - // No string, so it matches everything - matches = *this; - return matches.GetSize(); - } - - const size_t s_len = s.size(); - const size_t num_strings = m_strings.size(); - - for (size_t i = 0; i < num_strings; ++i) { - if (m_strings[i].find(s) == 0) { - if (exact_idx == SIZE_MAX && m_strings[i].size() == s_len) - exact_idx = matches.GetSize(); - matches.AppendString(m_strings[i]); - } - } - return matches.GetSize(); -} - void StringList::LogDump(Log *log, const char *name) { if (!log) return; diff --git a/source/Utility/StructuredData.cpp b/source/Utility/StructuredData.cpp index 0e203f9739d1..783a08082174 100644 --- a/source/Utility/StructuredData.cpp +++ b/source/Utility/StructuredData.cpp @@ -9,9 +9,7 @@ #include "lldb/Utility/StructuredData.h" #include "lldb/Utility/DataBuffer.h" #include "lldb/Utility/FileSpec.h" -#include "lldb/Utility/JSON.h" #include "lldb/Utility/Status.h" -#include "lldb/Utility/Stream.h" #include "lldb/Utility/StreamString.h" #include "llvm/ADT/STLExtras.h" #include "llvm/Support/MemoryBuffer.h" @@ -21,11 +19,20 @@ #include <limits> using namespace lldb_private; +using namespace llvm; -// Functions that use a JSONParser to parse JSON into StructuredData -static StructuredData::ObjectSP ParseJSONValue(JSONParser &json_parser); -static StructuredData::ObjectSP ParseJSONObject(JSONParser &json_parser); -static StructuredData::ObjectSP ParseJSONArray(JSONParser &json_parser); +static StructuredData::ObjectSP ParseJSONValue(json::Value &value); +static StructuredData::ObjectSP ParseJSONObject(json::Object *object); +static StructuredData::ObjectSP ParseJSONArray(json::Array *array); + +StructuredData::ObjectSP StructuredData::ParseJSON(std::string json_text) { + llvm::Expected<json::Value> value = json::parse(json_text); + if (!value) { + llvm::consumeError(value.takeError()); + return nullptr; + } + return ParseJSONValue(*value); +} StructuredData::ObjectSP StructuredData::ParseJSONFromFile(const FileSpec &input_spec, Status &error) { @@ -38,112 +45,53 @@ StructuredData::ParseJSONFromFile(const FileSpec &input_spec, Status &error) { buffer_or_error.getError().message()); return return_sp; } - - JSONParser json_parser(buffer_or_error.get()->getBuffer()); - return_sp = ParseJSONValue(json_parser); - return return_sp; + return ParseJSON(buffer_or_error.get()->getBuffer().str()); } -static StructuredData::ObjectSP ParseJSONObject(JSONParser &json_parser) { - // The "JSONParser::Token::ObjectStart" token should have already been - // consumed by the time this function is called - auto dict_up = llvm::make_unique<StructuredData::Dictionary>(); +static StructuredData::ObjectSP ParseJSONValue(json::Value &value) { + if (json::Object *O = value.getAsObject()) + return ParseJSONObject(O); - std::string value; - std::string key; - while (true) { - JSONParser::Token token = json_parser.GetToken(value); + if (json::Array *A = value.getAsArray()) + return ParseJSONArray(A); - if (token == JSONParser::Token::String) { - key.swap(value); - token = json_parser.GetToken(value); - if (token == JSONParser::Token::Colon) { - StructuredData::ObjectSP value_sp = ParseJSONValue(json_parser); - if (value_sp) - dict_up->AddItem(key, value_sp); - else - break; - } - } else if (token == JSONParser::Token::ObjectEnd) { - return StructuredData::ObjectSP(dict_up.release()); - } else if (token == JSONParser::Token::Comma) { - continue; - } else { - break; - } - } - return StructuredData::ObjectSP(); -} + std::string s; + if (json::fromJSON(value, s)) + return std::make_shared<StructuredData::String>(s); -static StructuredData::ObjectSP ParseJSONArray(JSONParser &json_parser) { - // The "JSONParser::Token::ObjectStart" token should have already been - // consumed by the time this function is called - auto array_up = llvm::make_unique<StructuredData::Array>(); + bool b; + if (json::fromJSON(value, b)) + return std::make_shared<StructuredData::Boolean>(b); - std::string value; - std::string key; - while (true) { - StructuredData::ObjectSP value_sp = ParseJSONValue(json_parser); - if (value_sp) - array_up->AddItem(value_sp); - else - break; + int64_t i; + if (json::fromJSON(value, i)) + return std::make_shared<StructuredData::Integer>(i); + + double d; + if (json::fromJSON(value, d)) + return std::make_shared<StructuredData::Float>(d); - JSONParser::Token token = json_parser.GetToken(value); - if (token == JSONParser::Token::Comma) { - continue; - } else if (token == JSONParser::Token::ArrayEnd) { - return StructuredData::ObjectSP(array_up.release()); - } else { - break; - } - } return StructuredData::ObjectSP(); } -static StructuredData::ObjectSP ParseJSONValue(JSONParser &json_parser) { - std::string value; - const JSONParser::Token token = json_parser.GetToken(value); - switch (token) { - case JSONParser::Token::ObjectStart: - return ParseJSONObject(json_parser); - - case JSONParser::Token::ArrayStart: - return ParseJSONArray(json_parser); - - case JSONParser::Token::Integer: { - uint64_t uval; - if (llvm::to_integer(value, uval, 0)) - return std::make_shared<StructuredData::Integer>(uval); - } break; - - case JSONParser::Token::Float: { - double val; - if (llvm::to_float(value, val)) - return std::make_shared<StructuredData::Float>(val); - } break; - - case JSONParser::Token::String: - return std::make_shared<StructuredData::String>(value); - - case JSONParser::Token::True: - case JSONParser::Token::False: - return std::make_shared<StructuredData::Boolean>(token == - JSONParser::Token::True); - - case JSONParser::Token::Null: - return std::make_shared<StructuredData::Null>(); - - default: - break; +static StructuredData::ObjectSP ParseJSONObject(json::Object *object) { + auto dict_up = std::make_unique<StructuredData::Dictionary>(); + for (auto &KV : *object) { + StringRef key = KV.first; + json::Value value = KV.second; + if (StructuredData::ObjectSP value_sp = ParseJSONValue(value)) + dict_up->AddItem(key, value_sp); } - return StructuredData::ObjectSP(); + return dict_up; } -StructuredData::ObjectSP StructuredData::ParseJSON(std::string json_text) { - JSONParser json_parser(json_text); - StructuredData::ObjectSP object_sp = ParseJSONValue(json_parser); - return object_sp; +static StructuredData::ObjectSP ParseJSONArray(json::Array *array) { + auto array_up = std::make_unique<StructuredData::Array>(); + for (json::Value &value : *array) { + if (StructuredData::ObjectSP value_sp = ParseJSONValue(value)) + array_up->AddItem(value_sp); + } + return array_up; } StructuredData::ObjectSP @@ -181,98 +129,48 @@ StructuredData::Object::GetObjectForDotSeparatedPath(llvm::StringRef path) { } void StructuredData::Object::DumpToStdout(bool pretty_print) const { - StreamString stream; - Dump(stream, pretty_print); - llvm::outs() << stream.GetString(); + json::OStream stream(llvm::outs(), pretty_print ? 2 : 0); + Serialize(stream); } -void StructuredData::Array::Dump(Stream &s, bool pretty_print) const { - bool first = true; - s << "["; - if (pretty_print) { - s << "\n"; - s.IndentMore(); - } +void StructuredData::Array::Serialize(json::OStream &s) const { + s.arrayBegin(); for (const auto &item_sp : m_items) { - if (first) { - first = false; - } else { - s << ","; - if (pretty_print) - s << "\n"; - } - - if (pretty_print) - s.Indent(); - item_sp->Dump(s, pretty_print); - } - if (pretty_print) { - s.IndentLess(); - s.EOL(); - s.Indent(); + item_sp->Serialize(s); } - s << "]"; + s.arrayEnd(); } -void StructuredData::Integer::Dump(Stream &s, bool pretty_print) const { - s.Printf("%" PRIu64, m_value); +void StructuredData::Integer::Serialize(json::OStream &s) const { + s.value(static_cast<int64_t>(m_value)); } -void StructuredData::Float::Dump(Stream &s, bool pretty_print) const { - s.Printf("%lg", m_value); +void StructuredData::Float::Serialize(json::OStream &s) const { + s.value(m_value); } -void StructuredData::Boolean::Dump(Stream &s, bool pretty_print) const { - if (m_value) - s.PutCString("true"); - else - s.PutCString("false"); +void StructuredData::Boolean::Serialize(json::OStream &s) const { + s.value(m_value); } -void StructuredData::String::Dump(Stream &s, bool pretty_print) const { - std::string quoted; - const size_t strsize = m_value.size(); - for (size_t i = 0; i < strsize; ++i) { - char ch = m_value[i]; - if (ch == '"' || ch == '\\') - quoted.push_back('\\'); - quoted.push_back(ch); - } - s.Printf("\"%s\"", quoted.c_str()); +void StructuredData::String::Serialize(json::OStream &s) const { + s.value(m_value); } -void StructuredData::Dictionary::Dump(Stream &s, bool pretty_print) const { - bool first = true; - s << "{"; - if (pretty_print) { - s << "\n"; - s.IndentMore(); - } +void StructuredData::Dictionary::Serialize(json::OStream &s) const { + s.objectBegin(); for (const auto &pair : m_dict) { - if (first) - first = false; - else { - s << ","; - if (pretty_print) - s << "\n"; - } - if (pretty_print) - s.Indent(); - s << "\"" << pair.first.AsCString() << "\" : "; - pair.second->Dump(s, pretty_print); - } - if (pretty_print) { - s.IndentLess(); - s.EOL(); - s.Indent(); + s.attributeBegin(pair.first.AsCString()); + pair.second->Serialize(s); + s.attributeEnd(); } - s << "}"; + s.objectEnd(); } -void StructuredData::Null::Dump(Stream &s, bool pretty_print) const { - s << "null"; +void StructuredData::Null::Serialize(json::OStream &s) const { + s.value(nullptr); } -void StructuredData::Generic::Dump(Stream &s, bool pretty_print) const { - s << "0x" << m_object; +void StructuredData::Generic::Serialize(json::OStream &s) const { + s.value(llvm::formatv("{0:X}", m_object)); } |