From 1370a1cb5b97ecfc4fd2cb550159db9c9ebd3a68 Mon Sep 17 00:00:00 2001 From: Med Ismail Bennani Date: Mon, 22 May 2023 13:52:09 -0700 Subject: [lldb] Add support for negative integer to {SB,}StructuredData This patch refactors the `StructuredData::Integer` class to make it templated, makes it private and adds 2 public specialization for both `int64_t` & `uint64_t` with a public type aliases, respectively `SignedInteger` & `UnsignedInteger`. It adds new getter for signed and unsigned interger values to the `StructuredData::Object` base class and changes the implementation of `StructuredData::Array::GetItemAtIndexAsInteger` and `StructuredData::Dictionary::GetValueForKeyAsInteger` to support signed and unsigned integers. This patch also adds 2 new `Get{Signed,Unsigned}IntegerValue` to the `SBStructuredData` class and marks `GetIntegerValue` as deprecated. Finally, this patch audits all the caller of `StructuredData::Integer` or `StructuredData::GetIntegerValue` to use the proper type as well the various tests that uses `SBStructuredData.GetIntegerValue`. rdar://105575764 Differential Revision: https://reviews.llvm.org/D150485 Signed-off-by: Med Ismail Bennani --- .../ScriptInterpreter/Python/PythonDataObjects.cpp | 51 ++++++++++++++++------ .../ScriptInterpreter/Python/PythonDataObjects.h | 6 ++- .../Python/ScriptedProcessPythonInterface.cpp | 4 +- .../Python/ScriptedThreadPythonInterface.cpp | 4 +- 4 files changed, 46 insertions(+), 19 deletions(-) (limited to 'lldb/source/Plugins/ScriptInterpreter/Python') diff --git a/lldb/source/Plugins/ScriptInterpreter/Python/PythonDataObjects.cpp b/lldb/source/Plugins/ScriptInterpreter/Python/PythonDataObjects.cpp index 2291856..eee2f6f 100644 --- a/lldb/source/Plugins/ScriptInterpreter/Python/PythonDataObjects.cpp +++ b/lldb/source/Plugins/ScriptInterpreter/Python/PythonDataObjects.cpp @@ -25,6 +25,7 @@ #include "llvm/Support/Errno.h" #include +#include using namespace lldb_private; using namespace lldb; @@ -101,7 +102,7 @@ Expected PythonObject::AsLongLong() const { return r; } -Expected PythonObject::AsUnsignedLongLong() const { +Expected PythonObject::AsUnsignedLongLong() const { if (!m_py_obj) return nullDeref(); assert(!PyErr_Occurred()); @@ -117,6 +118,7 @@ Expected PythonObject::AsModuloUnsignedLongLong() const { return nullDeref(); assert(!PyErr_Occurred()); unsigned long long r = PyLong_AsUnsignedLongLongMask(m_py_obj); + // FIXME: We should fetch the exception message and hoist it. if (PyErr_Occurred()) return exception(); return r; @@ -267,9 +269,15 @@ StructuredData::ObjectSP PythonObject::CreateStructuredObject() const { case PyObjectType::Boolean: return PythonBoolean(PyRefType::Borrowed, m_py_obj) .CreateStructuredBoolean(); - case PyObjectType::Integer: - return PythonInteger(PyRefType::Borrowed, m_py_obj) - .CreateStructuredInteger(); + case PyObjectType::Integer: { + StructuredData::IntegerSP int_sp = + PythonInteger(PyRefType::Borrowed, m_py_obj).CreateStructuredInteger(); + if (std::holds_alternative(int_sp)) + return std::get(int_sp); + if (std::holds_alternative(int_sp)) + return std::get(int_sp); + return nullptr; + }; case PyObjectType::List: return PythonList(PyRefType::Borrowed, m_py_obj).CreateStructuredArray(); case PyObjectType::String: @@ -459,17 +467,32 @@ void PythonInteger::SetInteger(int64_t value) { } StructuredData::IntegerSP PythonInteger::CreateStructuredInteger() const { - StructuredData::IntegerSP result(new StructuredData::Integer); - // FIXME this is really not ideal. Errors are silently converted to 0 - // and overflows are silently wrapped. But we'd need larger changes - // to StructuredData to fix it, so that's how it is for now. - llvm::Expected value = AsModuloUnsignedLongLong(); - if (!value) { + StructuredData::UnsignedIntegerSP uint_sp = CreateStructuredUnsignedInteger(); + return uint_sp ? StructuredData::IntegerSP(uint_sp) + : CreateStructuredSignedInteger(); +} + +StructuredData::UnsignedIntegerSP +PythonInteger::CreateStructuredUnsignedInteger() const { + StructuredData::UnsignedIntegerSP result = nullptr; + llvm::Expected value = AsUnsignedLongLong(); + if (!value) llvm::consumeError(value.takeError()); - result->SetValue(0); - } else { - result->SetValue(value.get()); - } + else + result = std::make_shared(value.get()); + + return result; +} + +StructuredData::SignedIntegerSP +PythonInteger::CreateStructuredSignedInteger() const { + StructuredData::SignedIntegerSP result = nullptr; + llvm::Expected value = AsLongLong(); + if (!value) + llvm::consumeError(value.takeError()); + else + result = std::make_shared(value.get()); + return result; } diff --git a/lldb/source/Plugins/ScriptInterpreter/Python/PythonDataObjects.h b/lldb/source/Plugins/ScriptInterpreter/Python/PythonDataObjects.h index 33092209..61ec4307 100644 --- a/lldb/source/Plugins/ScriptInterpreter/Python/PythonDataObjects.h +++ b/lldb/source/Plugins/ScriptInterpreter/Python/PythonDataObjects.h @@ -354,7 +354,7 @@ public: llvm::Expected AsLongLong() const; - llvm::Expected AsUnsignedLongLong() const; + llvm::Expected AsUnsignedLongLong() const; // wraps on overflow, instead of raising an error. llvm::Expected AsModuloUnsignedLongLong() const; @@ -480,6 +480,10 @@ public: void SetInteger(int64_t value); StructuredData::IntegerSP CreateStructuredInteger() const; + + StructuredData::UnsignedIntegerSP CreateStructuredUnsignedInteger() const; + + StructuredData::SignedIntegerSP CreateStructuredSignedInteger() const; }; class PythonBoolean : public TypedPythonObject { diff --git a/lldb/source/Plugins/ScriptInterpreter/Python/ScriptedProcessPythonInterface.cpp b/lldb/source/Plugins/ScriptInterpreter/Python/ScriptedProcessPythonInterface.cpp index ad92185..019924f 100644 --- a/lldb/source/Plugins/ScriptInterpreter/Python/ScriptedProcessPythonInterface.cpp +++ b/lldb/source/Plugins/ScriptInterpreter/Python/ScriptedProcessPythonInterface.cpp @@ -152,7 +152,7 @@ lldb::offset_t ScriptedProcessPythonInterface::WriteMemoryAtAddress( if (py_error.Fail()) error = py_error; - return obj->GetIntegerValue(LLDB_INVALID_OFFSET); + return obj->GetUnsignedIntegerValue(LLDB_INVALID_OFFSET); } StructuredData::ArraySP ScriptedProcessPythonInterface::GetLoadedImages() { @@ -173,7 +173,7 @@ lldb::pid_t ScriptedProcessPythonInterface::GetProcessID() { if (!CheckStructuredDataObject(LLVM_PRETTY_FUNCTION, obj, error)) return LLDB_INVALID_PROCESS_ID; - return obj->GetIntegerValue(LLDB_INVALID_PROCESS_ID); + return obj->GetUnsignedIntegerValue(LLDB_INVALID_PROCESS_ID); } bool ScriptedProcessPythonInterface::IsAlive() { diff --git a/lldb/source/Plugins/ScriptInterpreter/Python/ScriptedThreadPythonInterface.cpp b/lldb/source/Plugins/ScriptInterpreter/Python/ScriptedThreadPythonInterface.cpp index 1e0ca39..5603a15 100644 --- a/lldb/source/Plugins/ScriptInterpreter/Python/ScriptedThreadPythonInterface.cpp +++ b/lldb/source/Plugins/ScriptInterpreter/Python/ScriptedThreadPythonInterface.cpp @@ -69,7 +69,7 @@ lldb::tid_t ScriptedThreadPythonInterface::GetThreadID() { if (!CheckStructuredDataObject(LLVM_PRETTY_FUNCTION, obj, error)) return LLDB_INVALID_THREAD_ID; - return obj->GetIntegerValue(LLDB_INVALID_THREAD_ID); + return obj->GetUnsignedIntegerValue(LLDB_INVALID_THREAD_ID); } std::optional ScriptedThreadPythonInterface::GetName() { @@ -89,7 +89,7 @@ lldb::StateType ScriptedThreadPythonInterface::GetState() { if (!CheckStructuredDataObject(LLVM_PRETTY_FUNCTION, obj, error)) return eStateInvalid; - return static_cast(obj->GetIntegerValue(eStateInvalid)); + return static_cast(obj->GetUnsignedIntegerValue(eStateInvalid)); } std::optional ScriptedThreadPythonInterface::GetQueue() { -- cgit v1.1