diff --git a/lldb/include/lldb/API/SBData.h b/lldb/include/lldb/API/SBData.h index 89a699f2f713a..7e462b37bd12b 100644 --- a/lldb/include/lldb/API/SBData.h +++ b/lldb/include/lldb/API/SBData.h @@ -69,6 +69,7 @@ class LLDB_API SBData { const char *GetString(lldb::SBError &error, lldb::offset_t offset); + LLDB_RPC_POINTER_PLUS_LEN size_t ReadRawData(lldb::SBError &error, lldb::offset_t offset, void *buf, size_t size); @@ -80,9 +81,11 @@ class LLDB_API SBData { // DataExtractor, but having two SetData() signatures triggers a SWIG bug // where the typemap isn't applied before resolving the overload, and thus // the right function never gets called + LLDB_RPC_POINTER_PLUS_LEN void SetData(lldb::SBError &error, const void *buf, size_t size, lldb::ByteOrder endian, uint8_t addr_size); + LLDB_RPC_POINTER_PLUS_LEN void SetDataWithOwnership(lldb::SBError &error, const void *buf, size_t size, lldb::ByteOrder endian, uint8_t addr_size); @@ -96,26 +99,31 @@ class LLDB_API SBData { // in the following CreateData*() and SetData*() prototypes, the two // parameters array and array_len should not be renamed or rearranged, // because doing so will break the SWIG typemap + LLDB_RPC_POINTER_PLUS_LEN static lldb::SBData CreateDataFromUInt64Array(lldb::ByteOrder endian, uint32_t addr_byte_size, uint64_t *array, size_t array_len); + LLDB_RPC_POINTER_PLUS_LEN static lldb::SBData CreateDataFromUInt32Array(lldb::ByteOrder endian, uint32_t addr_byte_size, uint32_t *array, size_t array_len); + LLDB_RPC_POINTER_PLUS_LEN static lldb::SBData CreateDataFromSInt64Array(lldb::ByteOrder endian, uint32_t addr_byte_size, int64_t *array, size_t array_len); + LLDB_RPC_POINTER_PLUS_LEN static lldb::SBData CreateDataFromSInt32Array(lldb::ByteOrder endian, uint32_t addr_byte_size, int32_t *array, size_t array_len); + LLDB_RPC_POINTER_PLUS_LEN static lldb::SBData CreateDataFromDoubleArray(lldb::ByteOrder endian, uint32_t addr_byte_size, double *array, @@ -123,14 +131,19 @@ class LLDB_API SBData { bool SetDataFromCString(const char *data); + LLDB_RPC_POINTER_PLUS_LEN bool SetDataFromUInt64Array(uint64_t *array, size_t array_len); + LLDB_RPC_POINTER_PLUS_LEN bool SetDataFromUInt32Array(uint32_t *array, size_t array_len); + LLDB_RPC_POINTER_PLUS_LEN bool SetDataFromSInt64Array(int64_t *array, size_t array_len); + LLDB_RPC_POINTER_PLUS_LEN bool SetDataFromSInt32Array(int32_t *array, size_t array_len); + LLDB_RPC_POINTER_PLUS_LEN bool SetDataFromDoubleArray(double *array, size_t array_len); protected: diff --git a/lldb/include/lldb/API/SBDebugger.h b/lldb/include/lldb/API/SBDebugger.h index f77b0c1d7f0ee..41da742a8de54 100644 --- a/lldb/include/lldb/API/SBDebugger.h +++ b/lldb/include/lldb/API/SBDebugger.h @@ -421,6 +421,7 @@ class LLDB_API SBDebugger { bool GetUseSourceCache() const; /// Get the default architecture. + LLDB_RPC_POINTER_PLUS_LEN static bool GetDefaultArchitecture(char *arch_name, size_t arch_name_len); /// Set the default architecture. @@ -476,6 +477,7 @@ class LLDB_API SBDebugger { #endif /// Dispatch input to the debugger. + LLDB_RPC_POINTER_PLUS_LEN void DispatchInput(const void *data, size_t data_len); /// Interrupt the current input dispatch. diff --git a/lldb/include/lldb/API/SBDefines.h b/lldb/include/lldb/API/SBDefines.h index 85f6bbeea5bf9..e5fec5907a6ea 100644 --- a/lldb/include/lldb/API/SBDefines.h +++ b/lldb/include/lldb/API/SBDefines.h @@ -39,6 +39,13 @@ #define LLDB_DEPRECATED_FIXME(MSG, FIX) #endif +#if defined(LLDB_RPC_GEN) +#define LLDB_RPC_POINTER_PLUS_LEN \ + __attribute__((annotate("lldb-rpc-gen pointer plus len"))) +#else +#define LLDB_RPC_POINTER_PLUS_LEN +#endif + // Forward Declarations namespace lldb { diff --git a/lldb/include/lldb/API/SBFile.h b/lldb/include/lldb/API/SBFile.h index ebdc5607b7942..8d0990bbf0078 100644 --- a/lldb/include/lldb/API/SBFile.h +++ b/lldb/include/lldb/API/SBFile.h @@ -34,7 +34,9 @@ class LLDB_API SBFile { SBFile &operator=(const SBFile &rhs); + LLDB_RPC_POINTER_PLUS_LEN SBError Read(uint8_t *buf, size_t num_bytes, size_t *OUTPUT); + LLDB_RPC_POINTER_PLUS_LEN SBError Write(const uint8_t *buf, size_t num_bytes, size_t *OUTPUT); SBError Flush(); bool IsValid() const; diff --git a/lldb/include/lldb/API/SBFileSpec.h b/lldb/include/lldb/API/SBFileSpec.h index 36641843aabeb..800341620984a 100644 --- a/lldb/include/lldb/API/SBFileSpec.h +++ b/lldb/include/lldb/API/SBFileSpec.h @@ -51,8 +51,10 @@ class LLDB_API SBFileSpec { void SetDirectory(const char *directory); + LLDB_RPC_POINTER_PLUS_LEN uint32_t GetPath(char *dst_path, size_t dst_len) const; + LLDB_RPC_POINTER_PLUS_LEN static int ResolvePath(const char *src_path, char *dst_path, size_t dst_len); bool GetDescription(lldb::SBStream &description) const; diff --git a/lldb/include/lldb/API/SBModule.h b/lldb/include/lldb/API/SBModule.h index 85332066ee687..a172d8d81ffa8 100644 --- a/lldb/include/lldb/API/SBModule.h +++ b/lldb/include/lldb/API/SBModule.h @@ -274,6 +274,7 @@ class LLDB_API SBModule { /// This function always returns the number of version numbers /// that this object file has regardless of the number of /// version numbers that were copied into \a versions. + LLDB_RPC_POINTER_PLUS_LEN uint32_t GetVersion(uint32_t *versions, uint32_t num_versions); /// Get accessor for the symbol file specification. diff --git a/lldb/include/lldb/API/SBModuleSpec.h b/lldb/include/lldb/API/SBModuleSpec.h index 8d1ecfe6e6f8b..4aaad4e0d56d4 100644 --- a/lldb/include/lldb/API/SBModuleSpec.h +++ b/lldb/include/lldb/API/SBModuleSpec.h @@ -71,6 +71,7 @@ class LLDB_API SBModuleSpec { void SetTriple(const char *triple); + LLDB_RPC_POINTER_PLUS_LEN const uint8_t *GetUUIDBytes(); size_t GetUUIDLength(); diff --git a/lldb/include/lldb/API/SBProcess.h b/lldb/include/lldb/API/SBProcess.h index 882b8bd837131..b7d42eff82076 100644 --- a/lldb/include/lldb/API/SBProcess.h +++ b/lldb/include/lldb/API/SBProcess.h @@ -63,10 +63,13 @@ class LLDB_API SBProcess { size_t PutSTDIN(const char *src, size_t src_len); + LLDB_RPC_POINTER_PLUS_LEN size_t GetSTDOUT(char *dst, size_t dst_len) const; + LLDB_RPC_POINTER_PLUS_LEN size_t GetSTDERR(char *dst, size_t dst_len) const; + LLDB_RPC_POINTER_PLUS_LEN size_t GetAsyncProfileData(char *dst, size_t dst_len) const; #ifndef SWIG @@ -197,11 +200,14 @@ class LLDB_API SBProcess { /// void ForceScriptedState(StateType new_state); + LLDB_RPC_POINTER_PLUS_LEN size_t ReadMemory(addr_t addr, void *buf, size_t size, lldb::SBError &error); + LLDB_RPC_POINTER_PLUS_LEN size_t WriteMemory(addr_t addr, const void *buf, size_t size, lldb::SBError &error); + LLDB_RPC_POINTER_PLUS_LEN size_t ReadCStringFromMemory(addr_t addr, void *char_buf, size_t size, lldb::SBError &error); diff --git a/lldb/include/lldb/API/SBStructuredData.h b/lldb/include/lldb/API/SBStructuredData.h index f96e169f236ed..a05043ca141f8 100644 --- a/lldb/include/lldb/API/SBStructuredData.h +++ b/lldb/include/lldb/API/SBStructuredData.h @@ -104,6 +104,7 @@ class SBStructuredData { /// \return /// Returns the byte size needed to completely write the string value at /// \a dst in all cases. + LLDB_RPC_POINTER_PLUS_LEN size_t GetStringValue(char *dst, size_t dst_len) const; /// Return the generic pointer if this data structure is a generic type. diff --git a/lldb/include/lldb/API/SBTarget.h b/lldb/include/lldb/API/SBTarget.h index 2776a8f9010fe..d42a56b23766a 100644 --- a/lldb/include/lldb/API/SBTarget.h +++ b/lldb/include/lldb/API/SBTarget.h @@ -607,6 +607,7 @@ class LLDB_API SBTarget { /// /// \return /// The amount of data read in host bytes. + LLDB_RPC_POINTER_PLUS_LEN size_t ReadMemory(const SBAddress addr, void *buf, size_t size, lldb::SBError &error); @@ -688,12 +689,13 @@ class LLDB_API SBTarget { const SBFileSpecList &module_list, const SBFileSpecList &comp_unit_list); + LLDB_RPC_POINTER_PLUS_LEN lldb::SBBreakpoint BreakpointCreateByNames( const char *symbol_name[], uint32_t num_names, uint32_t name_type_mask, // Logical OR one or more FunctionNameType enum bits - lldb::LanguageType symbol_language, - const SBFileSpecList &module_list, const SBFileSpecList &comp_unit_list); + lldb::LanguageType symbol_language, const SBFileSpecList &module_list, + const SBFileSpecList &comp_unit_list); lldb::SBBreakpoint BreakpointCreateByNames( const char *symbol_name[], uint32_t num_names, @@ -900,20 +902,24 @@ class LLDB_API SBTarget { lldb::SBAddress end_addr, const char *flavor_string); + LLDB_RPC_POINTER_PLUS_LEN lldb::SBInstructionList GetInstructions(lldb::SBAddress base_addr, const void *buf, size_t size); // The "WithFlavor" is necessary to keep SWIG from getting confused about // overloaded arguments when using the buf + size -> Python Object magic. + LLDB_RPC_POINTER_PLUS_LEN lldb::SBInstructionList GetInstructionsWithFlavor(lldb::SBAddress base_addr, const char *flavor_string, const void *buf, size_t size); #ifndef SWIG + LLDB_RPC_POINTER_PLUS_LEN lldb::SBInstructionList GetInstructions(lldb::addr_t base_addr, const void *buf, size_t size); + LLDB_RPC_POINTER_PLUS_LEN lldb::SBInstructionList GetInstructionsWithFlavor(lldb::addr_t base_addr, const char *flavor_string, const void *buf, diff --git a/lldb/include/lldb/API/SBThread.h b/lldb/include/lldb/API/SBThread.h index f8ae627da5ace..6d48f10e92544 100644 --- a/lldb/include/lldb/API/SBThread.h +++ b/lldb/include/lldb/API/SBThread.h @@ -81,6 +81,7 @@ class LLDB_API SBThread { SBThreadCollection GetStopReasonExtendedBacktraces(InstrumentationRuntimeType type); + LLDB_RPC_POINTER_PLUS_LEN size_t GetStopDescription(char *dst_or_null, size_t dst_len); SBValue GetStopReturnValue(); diff --git a/lldb/tools/lldb-rpc-gen/RPCCommon.cpp b/lldb/tools/lldb-rpc-gen/RPCCommon.cpp index 7af6ee37f248b..0ebc93697647a 100644 --- a/lldb/tools/lldb-rpc-gen/RPCCommon.cpp +++ b/lldb/tools/lldb-rpc-gen/RPCCommon.cpp @@ -10,6 +10,7 @@ #include "clang/AST/AST.h" #include "clang/AST/Attr.h" +#include "clang/AST/Attrs.inc" #include "clang/AST/DeclBase.h" #include "clang/AST/Mangle.h" #include "clang/Lex/Lexer.h" @@ -21,6 +22,7 @@ #include "llvm/Support/raw_ostream.h" #include +#include using namespace clang; @@ -80,53 +82,6 @@ static constexpr llvm::StringRef ClassesWithoutCopyOperations[] = { "SBProgress", }; -static constexpr llvm::StringRef MethodsWithPointerPlusLen[] = { - "_ZN4lldb6SBData11ReadRawDataERNS_7SBErrorEyPvm", - "_ZN4lldb6SBData7SetDataERNS_7SBErrorEPKvmNS_9ByteOrderEh", - "_ZN4lldb6SBData20SetDataWithOwnershipERNS_7SBErrorEPKvmNS_9ByteOrderEh", - "_ZN4lldb6SBData25CreateDataFromUInt64ArrayENS_9ByteOrderEjPym", - "_ZN4lldb6SBData25CreateDataFromUInt32ArrayENS_9ByteOrderEjPjm", - "_ZN4lldb6SBData25CreateDataFromSInt64ArrayENS_9ByteOrderEjPxm", - "_ZN4lldb6SBData25CreateDataFromSInt32ArrayENS_9ByteOrderEjPim", - "_ZN4lldb6SBData25CreateDataFromDoubleArrayENS_9ByteOrderEjPdm", - "_ZN4lldb6SBData22SetDataFromUInt64ArrayEPym", - "_ZN4lldb6SBData22SetDataFromUInt32ArrayEPjm", - "_ZN4lldb6SBData22SetDataFromSInt64ArrayEPxm", - "_ZN4lldb6SBData22SetDataFromSInt32ArrayEPim", - "_ZN4lldb6SBData22SetDataFromDoubleArrayEPdm", - "_ZN4lldb10SBDebugger22GetDefaultArchitectureEPcm", - "_ZN4lldb10SBDebugger13DispatchInputEPvPKvm", - "_ZN4lldb10SBDebugger13DispatchInputEPKvm", - "_ZN4lldb6SBFile4ReadEPhmPm", - "_ZN4lldb6SBFile5WriteEPKhmPm", - "_ZNK4lldb10SBFileSpec7GetPathEPcm", - "_ZN4lldb10SBFileSpec11ResolvePathEPKcPcm", - "_ZN4lldb8SBModule10GetVersionEPjj", - "_ZN4lldb12SBModuleSpec12SetUUIDBytesEPKhm", - "_ZNK4lldb9SBProcess9GetSTDOUTEPcm", - "_ZNK4lldb9SBProcess9GetSTDERREPcm", - "_ZNK4lldb9SBProcess19GetAsyncProfileDataEPcm", - "_ZN4lldb9SBProcess10ReadMemoryEyPvmRNS_7SBErrorE", - "_ZN4lldb9SBProcess11WriteMemoryEyPKvmRNS_7SBErrorE", - "_ZN4lldb9SBProcess21ReadCStringFromMemoryEyPvmRNS_7SBErrorE", - "_ZNK4lldb16SBStructuredData14GetStringValueEPcm", - "_ZN4lldb8SBTarget23BreakpointCreateByNamesEPPKcjjRKNS_" - "14SBFileSpecListES6_", - "_ZN4lldb8SBTarget10ReadMemoryENS_9SBAddressEPvmRNS_7SBErrorE", - "_ZN4lldb8SBTarget15GetInstructionsENS_9SBAddressEPKvm", - "_ZN4lldb8SBTarget25GetInstructionsWithFlavorENS_9SBAddressEPKcPKvm", - "_ZN4lldb8SBTarget15GetInstructionsEyPKvm", - "_ZN4lldb8SBTarget25GetInstructionsWithFlavorEyPKcPKvm", - "_ZN4lldb8SBThread18GetStopDescriptionEPcm", - // The below mangled names are used for dummy methods in shell tests - // that test the emitters' output. If you're adding any new mangled names - // from the actual SB API to this list please add them above. - "_ZN4lldb33SBRPC_" - "CHECKCONSTCHARPTRPTRWITHLEN27CheckConstCharPtrPtrWithLenEPPKcm", - "_ZN4lldb19SBRPC_CHECKARRAYPTR13CheckArrayPtrEPPKcm", - "_ZN4lldb18SBRPC_CHECKVOIDPTR12CheckVoidPtrEPvm", -}; - // These classes inherit from rpc::ObjectRef directly (as opposed to // rpc::LocalObjectRef). Changing them from ObjectRef to LocalObjectRef is ABI // breaking, so we preserve that compatibility here. @@ -194,6 +149,7 @@ std::string lldb_rpc_gen::GetMangledName(ASTContext &Context, return Mangled; } +static auto CheckTypeForLLDBPrivate = [](const Type *Ty) {}; bool lldb_rpc_gen::TypeIsFromLLDBPrivate(QualType T) { auto CheckTypeForLLDBPrivate = [](const Type *Ty) { if (!Ty) @@ -308,6 +264,19 @@ bool lldb_rpc_gen::MethodIsDisallowed(ASTContext &Context, return isDisallowed; } +// Methods that have a pointer parameter followed by a length param need to be +// kept track of in RPC. Such methods are annotated in the main SB API using +// this Clang attribute: [[clang::annotate("lldb-rpc-gen pointer plus len")]]. +// This method checks that a given method has this attribute. +bool lldb_rpc_gen::MethodContainsPointerPlusLen(CXXMethodDecl *MDecl) { + if (!MDecl->hasAttr()) + return false; + + auto *annotation = MDecl->getAttr(); + return strcmp(annotation->getAnnotation().data(), + "lldb-rpc-gen pointer plus len") == 0; +} + // NOTE: There's possibly a more clever way to do this, but we're keeping // the string replacement way here. Here is why it is written this way: // By the time we have already created a `Method` object, we have extracted the @@ -408,9 +377,10 @@ lldb_rpc_gen::Method::Method(CXXMethodDecl *MDecl, const PrintingPolicy &Policy, const bool IsIntegerType = param.Type->isIntegerType() && !param.Type->isBooleanType() && !param.Type->isEnumeralType(); - if (IsIntegerType && llvm::is_contained(MethodsWithPointerPlusLen, - llvm::StringRef(MangledName))) + if (IsIntegerType && lldb_rpc_gen::MethodContainsPointerPlusLen(MDecl)) { + Params.back().IsFollowedByLen = true; + } } if (param.Type->isPointerType() && diff --git a/lldb/tools/lldb-rpc-gen/RPCCommon.h b/lldb/tools/lldb-rpc-gen/RPCCommon.h index 2a309d05e5ef7..fe831a509ec4d 100644 --- a/lldb/tools/lldb-rpc-gen/RPCCommon.h +++ b/lldb/tools/lldb-rpc-gen/RPCCommon.h @@ -32,6 +32,7 @@ bool TypeIsDisallowedClass(QualType T); bool TypeIsCallbackFunctionPointer(QualType T); bool MethodIsDisallowed(ASTContext &Context, CXXMethodDecl *MDecl); +bool MethodContainsPointerPlusLen(CXXMethodDecl *MDecl); std::string ReplaceLLDBNamespaceWithRPCNamespace(std::string Name); std::string StripLLDBNamespace(std::string Name); diff --git a/lldb/tools/lldb-rpc/LLDBRPCGeneration.cmake b/lldb/tools/lldb-rpc/LLDBRPCGeneration.cmake index a4cacf8692a85..e8c24728abaaa 100644 --- a/lldb/tools/lldb-rpc/LLDBRPCGeneration.cmake +++ b/lldb/tools/lldb-rpc/LLDBRPCGeneration.cmake @@ -78,3 +78,7 @@ add_custom_target(lldb-rpc-generate-sources lldb-sbapi-dwarf-enums) add_dependencies(lldb-rpc-generate-sources clang-resource-headers) + +# Add a compile definition to liblldb in order to create a macro for +# a Clang attribute for lldb-rpc-gen. +target_compile_definitions(liblldb PUBLIC LLDB_RPC_GEN)