Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 15 additions & 0 deletions lldb/test/Shell/RPC/Generator/Inputs/Client/CheckArrayPointer.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
#ifndef LLDB_API_SBRPC_CHECKARRAYPTR_H
#define LLDB_API_SBRPC_CHECKARRAYPTR_H

namespace lldb {
class SBRPC_CheckArrayPtr {
public:
// Pointers to arrays followed by length must use a
// Bytes object constructed using that pointer and the sizeof()
// the array object.
int CheckArrayPtr(int *array, int array_len);

}; // class SBRPC_CheckArrayPtr
} // namespace lldb

#endif // LLDB_API_SBRPC_CHECKARRAYPTR_H
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
#ifndef LLDB_API_SBRPC_CHECKCONSTCHARPTRPTRWITHLEN_H
#define LLDB_API_SBRPC_CHECKCONSTCHARPTRPTRWITHLEN_H

namespace lldb {
class SBRPC_CheckConstCharPtrPtrWithLen {
public:
// const char ** followed by len must use a StringList
// when being encoded.
int CheckConstCharPtrPtrWithLen(const char **arg1, int len);

}; // class SBRPC_CheckConstCharPtrPtrWithLen
} // namespace lldb

#endif // LLDB_API_SBRPC_CHECKCONSTCHARPTRPTRWITHLEN_H
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
#ifndef LLDB_API_SBRPC_CHECKNONCONSTSBREF_H
#define LLDB_API_SBRPC_CHECKNONCONSTSBREF_H

#include "lldb/API/SBDefines.h"

namespace lldb {
class LLDB_API SBRPC_CheckNonConstSBRef {
public:
// Non-const references to SB classes will have an assert
// added that trips if it has an invalid ObjectRef.
int CheckNonConstSBRef(SBDebugger &debugger_ref);

}; // class SBRPC_CheckNonConstSBRef
} // namespace lldb

#endif // LLDB_API_SBRPC_CHECKNONCONSTSBREF_H
18 changes: 18 additions & 0 deletions lldb/test/Shell/RPC/Generator/Inputs/Client/CheckSBPointer.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
#ifndef LLDB_API_SBRPC_CHECKSBPTR_H
#define LLDB_API_SBRPC_CHECKSBPTR_H

#include "lldb/API/SBDefines.h"

namespace lldb {
class LLDB_API SBRPC_CheckSBPtr {
public:
// Pointers to SB objects must be checked to
// see if they're null. If so, then a new object of the given
// class must be created and encoded. Otherwise, the original
// parameter will be encoded.
int CheckSBPtr(SBDebugger *debugger_ptr);

}; // class SBRPC_CheckSBPtr
} // namespace lldb

#endif // LLDB_API_SBRPC_CHECKSBPTR_H
14 changes: 14 additions & 0 deletions lldb/test/Shell/RPC/Generator/Inputs/Client/CheckVoidPtr.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
#ifndef LLDB_API_SBRPC_CHECKVOIDPTR_H
#define LLDB_API_SBRPC_CHECKVOIDPTR_H

namespace lldb {
class SBRPC_CheckVoidPtr {
public:
// void * followed by length must use a Bytes object
// when being encoded.
int CheckVoidPtr(void *buf, int len);

}; // class SBRPC_CheckVoidPtr
} // namespace lldb

#endif // LLDB_API_SBRPC_CHECKVOIDPTR_H
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
RUN: mkdir -p %t/server
RUN: mkdir -p %t/lib
RUN: %lldb-rpc-gen --output-dir=%t %S/../../Inputs/Client/CheckArrayPointer.h

RUN: cat %t/lib/CheckArrayPointer.cpp | FileCheck %s

# Pointers to arrays followed by length must use a
# Bytes object constructed using that pointer and the sizeof()
# the array object.
CHECK: Bytes array_buffer(array, sizeof(int) * array_len);
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
RUN: mkdir -p %t/server
RUN: mkdir -p %t/lib
RUN: %lldb-rpc-gen --output-dir=%t %S/../../Inputs/Client/CheckConstCharPtrPtrWithLen.h

RUN: cat %t/lib/CheckConstCharPtrPtrWithLen.cpp | FileCheck %s

# const char ** followed by len must use a StringList
# when being encoded.
CHECK: StringList arg1_list
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
RUN: mkdir -p %t/server
RUN: mkdir -p %t/lib
RUN: %lldb-rpc-gen --output-dir=%t %S/../../Inputs/Client/CheckNonConstSBRef.h

RUN: cat %t/lib/CheckNonConstSBRef.cpp | FileCheck %s

# Non-const references to SB classes will have an assert
# added that trips if it has an invalid ObjectRef.
CHECK: assert(debugger_ref.ObjectRefIsValid() && "SB object refs must be valid before encoding");
CHECK-NEXT: RPCValueEncoder(send, rpc_common::RPCPacket::ValueType::Argument, debugger_ref);
14 changes: 14 additions & 0 deletions lldb/test/Shell/RPC/Generator/Tests/Client/CheckSBPointer.test
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
RUN: mkdir -p %t/server
RUN: mkdir -p %t/lib
RUN: %lldb-rpc-gen --output-dir=%t %S/../../Inputs/Client/CheckSBPointer.h

RUN: cat %t/lib/CheckSBPointer.cpp | FileCheck %s

# Pointers to SB objects must be checked to
# see if they're null. If so, then a new object of the given
# class must be created and encoded. Otherwise, the original
# parameter will be encoded.
CHECK: if (debugger_ptr)
CHECK-NEXT: RPCValueEncoder(send, rpc_common::RPCPacket::ValueType::Argument, *debugger_ptr);
CHECK-NEXT: else
CHECK-NEXT: RPCValueEncoder(send, rpc_common::RPCPacket::ValueType::Argument, rpc::ObjectRef(ObjectRefGetConnectionID(), eClass_lldb_SBDebugger, LLDB_RPC_INVALID_OBJECT_ID));
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
RUN: mkdir -p %t/server
RUN: mkdir -p %t/lib
RUN: %lldb-rpc-gen --output-dir=%t %S/../../Inputs/Client/CheckVoidPtr.h

RUN: cat %t/lib/CheckVoidPtr.cpp | FileCheck %s

# void * followed by length must use a Bytes object
# when being encoded.
CHECK: Bytes buf_buffer(buf, len);
2 changes: 2 additions & 0 deletions lldb/tools/lldb-rpc-gen/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
add_lldb_tool(lldb-rpc-gen
RPCCommon.cpp
client/RPCLibraryHeaderEmitter.cpp
client/RPCLibrarySourceEmitter.cpp
server/RPCServerHeaderEmitter.cpp
server/RPCServerSourceEmitter.cpp
lldb-rpc-gen.cpp
Expand Down
13 changes: 10 additions & 3 deletions lldb/tools/lldb-rpc-gen/RPCCommon.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -61,10 +61,17 @@ static constexpr llvm::StringRef DisallowedMethods[] = {
// problematic because it returns a pointer to an "opaque" structure
// (thread_t) that is not `void *`, so special casing it is more effort than
// it's worth.

// NOTE: Some methods here have different name mangling between Darwin and
// Linux platforms, the respective name manglings for each platform are
// written here as necessary.
"_ZN4lldb8SBHostOS10ThreadJoinEP17_opaque_pthread_tPPvPNS_7SBErrorE",
"_ZN4lldb8SBHostOS10ThreadJoinEmPPvPNS_7SBErrorE",
"_ZN4lldb8SBHostOS12ThreadCancelEP17_opaque_pthread_tPNS_7SBErrorE",
"_ZN4lldb8SBHostOS12ThreadCancelEmPNS_7SBErrorE",
"_ZN4lldb8SBHostOS12ThreadCreateEPKcPFPvS3_ES3_PNS_7SBErrorE",
"_ZN4lldb8SBHostOS12ThreadDetachEP17_opaque_pthread_tPNS_7SBErrorE",
"_ZN4lldb8SBHostOS12ThreadDetachEmPNS_7SBErrorE",
"_ZN4lldb8SBHostOS13ThreadCreatedEPKc",
};

Expand Down Expand Up @@ -122,9 +129,9 @@ static constexpr llvm::StringRef MethodsWithPointerPlusLen[] = {
// 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",
"CheckConstCharPtrPtrWithLen27CheckConstCharPtrPtrWithLenEPPKci",
"_ZN4lldb19SBRPC_CheckArrayPtr13CheckArrayPtrEPii",
"_ZN4lldb18SBRPC_CheckVoidPtr12CheckVoidPtrEPvi",
};

// These classes inherit from rpc::ObjectRef directly (as opposed to
Expand Down
126 changes: 126 additions & 0 deletions lldb/tools/lldb-rpc-gen/client/RPCLibraryHeaderEmitter.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,126 @@
#include "RPCLibraryHeaderEmitter.h"
#include "RPCCommon.h"

#include "clang/AST/AST.h"
#include "clang/AST/Mangle.h"
#include "clang/Frontend/CompilerInstance.h"

#include "llvm/ADT/StringRef.h"
#include "llvm/Support/ToolOutputFile.h"
#include "llvm/Support/raw_ostream.h"

using namespace clang;
using namespace lldb_rpc_gen;

void RPCLibraryHeaderEmitter::StartClass(std::string ClassName) {
CurrentClass = std::move(ClassName);
std::string BaseClass =
lldb_rpc_gen::SBClassInheritsFromObjectRef(CurrentClass)
? "ObjectRef"
: "LocalObjectRef";
EmitLine("class " + CurrentClass + " : public rpc::" + BaseClass + " {");
EmitLine("public:");
IndentLevel++;
if (lldb_rpc_gen::SBClassRequiresDefaultCtor(CurrentClass))
EmitLine(CurrentClass + "();");

// NOTE: There's currently only one RPC-specific extension that is actually
// used AFAICT. We can generalize this if we need more.
if (CurrentClass == "SBDebugger")
EmitLine("int SetIOFile(const char *path);");
}

void RPCLibraryHeaderEmitter::EndClass() {
if (lldb_rpc_gen::SBClassRequiresCopyCtorAssign(CurrentClass)) {
if (!CopyCtorEmitted)
EmitLine(CurrentClass + "(const lldb_rpc::" + CurrentClass + " &rhs);");
if (!CopyAssignEmitted)
EmitLine(CurrentClass + " &operator=(const lldb_rpc::" + CurrentClass +
" &rhs);");
}
if (!MoveCtorEmitted)
EmitLine(CurrentClass + "(lldb_rpc::" + CurrentClass + " &&rhs);");
if (!MoveAssignEmitted)
EmitLine(CurrentClass + " &operator=(" + CurrentClass + " &&rhs);");

IndentLevel--;
EmitLine("}; // class " + CurrentClass);
CurrentClass.clear();
}

void RPCLibraryHeaderEmitter::EmitMethod(const Method &method) {
std::string DeclarationLine;
llvm::raw_string_ostream DeclarationLineStream(DeclarationLine);

if (method.IsExplicitCtorOrConversionMethod)
DeclarationLineStream << "explicit ";
else if (!method.IsInstance)
DeclarationLineStream << "static ";

if (!method.IsDtor && !method.IsConversionMethod && !method.IsCtor) {
DeclarationLineStream << lldb_rpc_gen::ReplaceLLDBNamespaceWithRPCNamespace(
method.ReturnType.getAsString(method.Policy))
<< " ";
}

DeclarationLineStream << method.BaseName << "("
<< method.CreateParamListAsString(
eLibrary, /*IncludeDefaultValue = */ true)
<< ")";
if (method.IsConst)
DeclarationLineStream << " const";
DeclarationLineStream << ";";

EmitLine(DeclarationLine);

if (method.IsCopyCtor)
CopyCtorEmitted = true;
else if (method.IsCopyAssign)
CopyAssignEmitted = true;
else if (method.IsMoveCtor)
MoveCtorEmitted = true;
else if (method.IsMoveAssign)
MoveAssignEmitted = true;
}

void RPCLibraryHeaderEmitter::EmitEnum(EnumDecl *E) {
// NOTE: All of the enumerations embedded in SB classes are currently
// anonymous and backed by an unsigned int.
EmitLine("enum : unsigned {");
IndentLevel++;
for (const EnumConstantDecl *EC : E->enumerators()) {
std::string EnumValue = EC->getNameAsString();
SmallString<16> ValueStr;
EC->getInitVal().toString(ValueStr);
EnumValue += " = " + ValueStr.str().str() + ", ";
EmitLine(EnumValue);
}

IndentLevel--;
EmitLine("};");
}

std::string RPCLibraryHeaderEmitter::GetHeaderGuard() {
const std::string UpperFilenameNoExt =
llvm::sys::path::stem(
llvm::sys::path::filename(OutputFile->getFilename()))
.upper();
return "GENERATED_LLDB_RPC_LIBRARY_" + UpperFilenameNoExt + "_H";
}

void RPCLibraryHeaderEmitter::Begin() {
const std::string HeaderGuard = GetHeaderGuard();
EmitLine("#ifndef " + HeaderGuard);
EmitLine("#define " + HeaderGuard);
EmitLine("");
EmitLine("#include <lldb-rpc/common/RPCPublic.h>");
EmitLine("#include \"SBDefines.h\"");
EmitLine("#include \"LLDBRPC.h\"");
EmitLine("");
EmitLine("namespace lldb_rpc {");
}

void RPCLibraryHeaderEmitter::End() {
EmitLine("} // namespace lldb_rpc");
EmitLine("#endif // " + GetHeaderGuard());
}
44 changes: 44 additions & 0 deletions lldb/tools/lldb-rpc-gen/client/RPCLibraryHeaderEmitter.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
#ifndef LLDB_RPC_GEN_RPCLIBRARYHEADEREMITTER_H
#define LLDB_RPC_GEN_RPCLIBRARYHEADEREMITTER_H

#include "RPCCommon.h"

#include "clang/AST/AST.h"
#include "llvm/Support/ToolOutputFile.h"

using namespace clang;

namespace lldb_rpc_gen {

class RPCLibraryHeaderEmitter : public FileEmitter {
public:
RPCLibraryHeaderEmitter(std::unique_ptr<llvm::ToolOutputFile> &&OutputFile)
: FileEmitter(std::move(OutputFile)), CurrentClass() {
Begin();
}

~RPCLibraryHeaderEmitter() { End(); }

void StartClass(std::string ClassName);

void EndClass();

void EmitMethod(const Method &method);

void EmitEnum(EnumDecl *E);

private:
std::string GetHeaderGuard();

void Begin();

void End();

std::string CurrentClass;
bool CopyCtorEmitted = false;
bool CopyAssignEmitted = false;
bool MoveCtorEmitted = false;
bool MoveAssignEmitted = false;
};
} // namespace lldb_rpc_gen
#endif // LLDB_RPC_GEN_RPCLIBRARYHEADEREMITTER_H
Loading
Loading