Skip to content

Commit dd04b9d

Browse files
committed
[DRAFT][lldb] Upstream lldb-rpc-gen and LLDB RPC server-side emitters
This commit upstreams lldb-rpc-gen, a tool that emits the client and server interfaces used for LLDB RPC. This is the initial commit in the upstreaming process for LLDB RPC. lldb-rpc-gen is a ClangTool that reads the LLDB SB API headers and uses their information to generate the interfaces for RPC. This commit specifically adds the server-side emitters for easier review. The client-side interface will be added in a later commit. RFC: https://discourse.llvm.org/t/rfc-upstreaming-lldb-rpc/85804
1 parent d35bf17 commit dd04b9d

27 files changed

+2589
-0
lines changed
Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
#!/usr/bin/env python3
2+
# Usage: convert-lldb-header-to-rpc-header.py <path/to/input-header.h> <path/to/output-header.h>
3+
4+
import argparse
5+
import os
6+
import re
7+
import subprocess
8+
9+
10+
def main():
11+
parser = argparse.ArgumentParser()
12+
parser.add_argument("input")
13+
parser.add_argument("output")
14+
args = parser.parse_args()
15+
input_path = str(args.input)
16+
output_path = str(args.output)
17+
with open(input_path, "r+") as input_file:
18+
lines = input_file.readlines()
19+
20+
with open(output_path, "w+") as output_file:
21+
for line in lines:
22+
# NOTE: We do not use lldb-forward or lldb-versioning in RPC.
23+
if re.match(
24+
r'#include "lldb/lldb-forward|#include "lldb/lldb-versioning', line
25+
):
26+
continue
27+
# For lldb-defines.h
28+
elif re.match(r".+LLDB_LLDB_", line):
29+
output_file.write(re.sub(r"LLDB_LLDB_", r"LLDB_RPC_", line))
30+
# For SBDefines.h
31+
elif re.match(r".+LLDB_API_", line):
32+
output_file.write(re.sub(r"LLDB_API_", r"LLDB_RPC_API_", line))
33+
# For lldb-rpc-version.h and lldb-rpc-defines.h
34+
elif re.match(r".+LLDB_VERSION", line):
35+
output_file.write(re.sub(r"LLDB_VERSION", r"LLDB_RPC_VERSION", line))
36+
elif re.match(r".+LLDB_REVISION", line):
37+
output_file.write(re.sub(r"LLDB_REVISION", r"LLDB_RPC_REVISION", line))
38+
elif re.match(r".+LLDB_VERSION_STRING", line):
39+
output_file.write(
40+
re.sub(r"LLDB_VERSION_STRING", r"LLDB_RPC_VERSION_STRING", line)
41+
)
42+
# For local #includes
43+
elif re.match(r'#include "lldb/lldb-', line):
44+
output_file.write(re.sub(r"lldb/lldb-", r"lldb-rpc-", line))
45+
# Rename the lldb namespace to lldb-rpc
46+
elif re.match(r"namespace lldb", line):
47+
output_file.write(re.sub(r"lldb", r"lldb_rpc", line))
48+
# Rename namespace references
49+
elif re.match(r".+lldb::", line):
50+
output_file.write(re.sub(r"lldb::", r"lldb_rpc::", line))
51+
else:
52+
# Write any line that doesn't need to be converted
53+
output_file.write(line)
54+
55+
56+
if __name__ == "__main__":
57+
main()
Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
#!/usr/bin/env python3
2+
# Usage: framework-header-include-fix.py <path/to/input-header.h> <path/to/output-header.h>
3+
4+
import argparse
5+
import os
6+
import re
7+
import subprocess
8+
9+
10+
def main():
11+
parser = argparse.ArgumentParser()
12+
parser.add_argument("input")
13+
parser.add_argument("output")
14+
args = parser.parse_args()
15+
input_path = str(args.input)
16+
output_path = str(args.output)
17+
with open(input_path, "r+") as input_file:
18+
lines = input_file.readlines()
19+
20+
with open(output_path, "w+") as output_file:
21+
for line in lines:
22+
if re.match(r".+<lldb-rpc/common", line):
23+
output_file.write(re.sub(r"<lldb-rpc/common", r"<LLDBRPC", line))
24+
elif re.match(r'#include "(.*)"', line):
25+
include_filename = re.search(r'#include "(.*)"', line).groups()[0]
26+
output_file.write(
27+
re.sub(
28+
r'#include "(.*)"',
29+
r"#include <LLDBRPC/" + include_filename + ">",
30+
line,
31+
)
32+
)
33+
else:
34+
# Write any line that doesn't need to be converted
35+
output_file.write(line)
36+
37+
38+
if __name__ == "__main__":
39+
main()
Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
#!/usr/bin/env python3
2+
# Usage: framework-header-version-fix.py <path/to/input-header.h> <path/to/output-header.h> MAJOR MINOR PATCH
3+
4+
import argparse
5+
import os
6+
import re
7+
import subprocess
8+
9+
10+
def main():
11+
parser = argparse.ArgumentParser()
12+
parser.add_argument("input")
13+
parser.add_argument("output")
14+
parser.add_argument("lldb_version_major")
15+
parser.add_argument("lldb_version_minor")
16+
parser.add_argument("lldb_version_patch")
17+
args = parser.parse_args()
18+
input_path = str(args.input)
19+
output_path = str(args.output)
20+
lldb_version_major = str(args.lldb_version_major)
21+
lldb_version_minor = str(args.lldb_version_minor)
22+
lldb_version_patch = str(args.lldb_version_patch)
23+
24+
with open(input_path, "r+") as input_file:
25+
lines = input_file.readlines()
26+
27+
with open(output_path, "w+") as output_file:
28+
for line in lines:
29+
if re.match(r"//#define LLDB_RPC_VERSION$", line):
30+
output_file.write(
31+
re.sub(
32+
r"//#define LLDB_RPC_VERSION",
33+
r"#define LLDB_RPC_VERSION " + lldb_version_major,
34+
line,
35+
)
36+
)
37+
elif re.match(r"//#define LLDB_RPC_REVISION$", line):
38+
output_file.write(
39+
re.sub(
40+
r"//#define LLDB_RPC_REVISION",
41+
r"#define LLDB_RPC_REVISION " + lldb_version_minor,
42+
line,
43+
)
44+
)
45+
elif re.match(r"//#define LLDB_RPC_VERSION_STRING$", line):
46+
output_file.write(
47+
re.sub(
48+
r"//#define LLDB_RPC_VERSION_STRING",
49+
r'#define LLDB_RPC_VERSION_STRING "{0}.{1}.{2}"'.format(
50+
lldb_version_major, lldb_version_minor, lldb_version_patch
51+
),
52+
line,
53+
)
54+
)
55+
else:
56+
# Write any line that doesn't need to be converted
57+
output_file.write(line)
58+
59+
60+
if __name__ == "__main__":
61+
main()
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
#ifndef LLDB_API_SBRPC_CHECKARRAYPTR_H
2+
#define LLDB_API_SBRPC_CHECKARRAYPTR_H
3+
4+
#include <cstddef>
5+
#include <cstdio>
6+
7+
#include "lldb/API/SBDefines.h"
8+
9+
namespace lldb {
10+
class LLDB_API SBRPC_CHECKARRAYPTR {
11+
public:
12+
// Pointers to arrays followed by length must use a
13+
// Bytes object constructed using that pointer and the sizeof()
14+
// the array object.
15+
int CheckArrayPtr(uint64_t * array, size_t array_len);
16+
17+
}; // class SBRPC_CHECKARRAYPTR
18+
} // namespace lldb
19+
20+
#endif // LLDB_API_SBRPC_CHECKARRAYPTR_H
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
#ifndef LLDB_API_SBRPC_CHECKCONSTCHARPTRPTRWITHLEN_H
2+
#define LLDB_API_SBRPC_CHECKCONSTCHARPTRPTRWITHLEN_H
3+
4+
#include <cstddef>
5+
#include <cstdio>
6+
7+
#include "lldb/API/SBDefines.h"
8+
9+
namespace lldb {
10+
class LLDB_API SBRPC_CHECKCONSTCHARPTRPTRWITHLEN {
11+
public:
12+
// const char ** followed by len must use a StringList
13+
// when being encoded.
14+
int CheckConstCharPtrPtrWithLen(const char **arg1, size_t len);
15+
16+
}; // class SBRPC_CHECKCONSTCHARPTRPTRWITHLEN
17+
} // namespace lldb
18+
19+
#endif // LLDB_API_SBRPC_CHECKCONSTCHARPTRPTRWITHLEN_H
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
#ifndef LLDB_API_SBRPC_CHECKCONSTSBREF_H
2+
#define LLDB_API_SBRPC_CHECKCONSTSBREF_H
3+
4+
#include <cstddef>
5+
#include <cstdio>
6+
7+
#include "lldb/API/SBDefines.h"
8+
9+
namespace lldb {
10+
class LLDB_API SBRPC_CHECKCONSTSBREF {
11+
public:
12+
// Const references to SB classes should be encoded as usual without
13+
// needing to create a new object with its own connection.
14+
int CheckConstSBRef(const SBDebugger &debugger_ref);
15+
16+
}; // class SBRPC_CHECKCONSTSBREF
17+
} // namespace lldb
18+
19+
#endif // LLDB_API_SBRPC_CHECKCONSTSBREF_H
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
#ifndef LLDB_API_SBRPC_CHECKNONCONSTSBREF_H
2+
#define LLDB_API_SBRPC_CHECKNONCONSTSBREF_H
3+
4+
#include <cstddef>
5+
#include <cstdio>
6+
7+
#include "lldb/API/SBDefines.h"
8+
9+
namespace lldb {
10+
class LLDB_API SBRPC_CHECKNONCONSTSBREF {
11+
public:
12+
// Non-const references to SB classes will have new objects
13+
// of that class constructed with the connection as the first parameter
14+
// before being encoded if their existing connection is invalid.
15+
int CheckNonConstSBRef(SBDebugger & debugger_ref);
16+
17+
}; // class SBRPC_CHECKNONCONSTSBREF
18+
} // namespace lldb
19+
20+
#endif // LLDB_API_SBRPC_CHECKNONCONSTSBREF_H
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
#ifndef LLDB_API_SBRPC_CHECKSBPTR_H
2+
#define LLDB_API_SBRPC_CHECKSBPTR_H
3+
4+
#include <cstddef>
5+
#include <cstdio>
6+
7+
#include "lldb/API/SBDefines.h"
8+
9+
namespace lldb {
10+
class LLDB_API SBRPC_CHECKSBPTR {
11+
public:
12+
// Pointers to SB objects must be checked to
13+
// see if they're null. If so, then a new object of the given
14+
// class must be created and encoded. Otherwise, the original
15+
// parameter will be encoded.
16+
int CheckSBPtr(SBDebugger *debugger_ptr);
17+
18+
}; // class SBRPC_CHECKSBPTR
19+
} // namespace lldb
20+
21+
#endif // LLDB_API_SBRPC_CHECKSBPTR_H
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
#ifndef LLDB_API_SBRPC_CHECKVOIDPTR_H
2+
#define LLDB_API_SBRPC_CHECKVOIDPTR_H
3+
4+
#include <cstddef>
5+
#include <cstdio>
6+
7+
#include "lldb/API/SBDefines.h"
8+
9+
namespace lldb {
10+
class LLDB_API SBRPC_CHECKVOIDPTR {
11+
public:
12+
// void * followed by length must use a Bytes object
13+
// when being encoded.
14+
int CheckVoidPtr(void * buf, size_t len);
15+
16+
}; // class SBRPC_CHECKVOIDPTR
17+
} // namespace lldb
18+
19+
#endif // LLDB_API_SBRPC_CHECKVOIDPTR_H
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
// Skipping temporarily due to rdar://149500008
2+
# XFAIL: system-darwin
3+
# RUN: mkdir -p %t/server
4+
# RUN: mkdir -p %t/lib
5+
# RUN: %lldb-rpc-gen --output-dir=%t %S/../../Inputs/CheckArrayPointer.h
6+
7+
# RUN: cat %t/lib/CheckArrayPointer.cpp | FileCheck %s
8+
9+
// Pointers to arrays followed by length must use a
10+
// Bytes object constructed using that pointer and the sizeof()
11+
// the array object.
12+
# CHECK: lldb_rpc::SBRPC_CHECKARRAYPTR::CheckArrayPtr
13+
# CHECK: Bytes array_buffer(array, sizeof(uint64_t));
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
// Skipping temporarily due to rdar://149500008
2+
# XFAIL: system-darwin
3+
# RUN: mkdir -p %t/server
4+
# RUN: mkdir -p %t/lib
5+
# RUN: %lldb-rpc-gen --output-dir=%t %S/../../Inputs/CheckConstCharPtrPtrWithLen.h
6+
7+
# RUN: cat %t/lib/CheckConstCharPtrPtrWithLen.cpp | FileCheck %s
8+
9+
// const char ** followed by len must use a StringList
10+
// when being encoded.
11+
# CHECK: lldb_rpc::SBRPC_CHECKCONSTCHARPTRPTRWITHLEN::CheckConstCharPtrPtrWithLen
12+
# CHECK: StringList arg1_list
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
// Skipping temporarily due to rdar://149500008
2+
# XFAIL: system-darwin
3+
# RUN: mkdir -p %t/server
4+
# RUN: mkdir -p %t/lib
5+
# RUN: %lldb-rpc-gen --output-dir=%t %S/../../Inputs/CheckConstSBRef.h
6+
7+
# RUN: cat %t/lib/CheckConstSBRef.cpp | FileCheck %s
8+
9+
// Const references to SB classes should be encoded as usual without
10+
// needing to create a new object with its own connection. Here
11+
// we're checking to make sure that the given SB object ref will get
12+
// encoded immediately after the previous argument gets encoded without
13+
// anything happening in between.
14+
# CHECK: lldb_rpc::SBRPC_CHECKCONSTSBREF::CheckConstSBRef
15+
# CHECK: RPCValueEncoder(send, rpc_common::RPCPacket::ValueType::Argument, *this);
16+
# CHECK: RPCValueEncoder(send, rpc_common::RPCPacket::ValueType::Argument, debugger_ref)
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
// Skipping temporarily due to rdar://149500008
2+
# XFAIL: system-darwin
3+
# RUN: mkdir -p %t/server
4+
# RUN: mkdir -p %t/lib
5+
# RUN: %lldb-rpc-gen --output-dir=%t %S/../../Inputs/CheckNonConstSBRef.h
6+
7+
# RUN: cat %t/lib/CheckNonConstSBRef.cpp | FileCheck %s
8+
9+
// Non-const references to SB classes will have new objects
10+
// of that class constructed with the connection as the first parameter
11+
// before being encoded if their existing connection is invalid.
12+
# CHECK: lldb_rpc::SBRPC_CHECKNONCONSTSBREF::CheckNonConstSBRef
13+
# CHECK: if (connection_sp && !debugger_ref.ObjectRefIsValid())
14+
# CHECK: debugger_ref = lldb_rpc::SBDebugger(connection_sp);
15+
# CHECK: RPCValueEncoder(send, rpc_common::RPCPacket::ValueType::Argument, debugger_ref);
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
// Skipping temporarily due to rdar://149500008
2+
# XFAIL: system-darwin
3+
# RUN: mkdir -p %t/server
4+
# RUN: mkdir -p %t/lib
5+
# RUN: %lldb-rpc-gen --output-dir=%t %S/../../Inputs/CheckSBPointer.h
6+
7+
# RUN: cat %t/lib/CheckSBPointer.cpp | FileCheck %s
8+
9+
// Pointers to SB objects must be checked to
10+
// see if they're null. If so, then a new object of the given
11+
// class must be created and encoded. Otherwise, the original
12+
// parameter will be encoded.
13+
# CHECK: lldb_rpc::SBRPC_CHECKSBPTR::CheckSBPtr
14+
# CHECK: if (debugger_ptr)
15+
# CHECK: RPCValueEncoder(send, rpc_common::RPCPacket::ValueType::Argument, *debugger_ptr);
16+
# CHECK: else
17+
# CHECK: RPCValueEncoder(send, rpc_common::RPCPacket::ValueType::Argument, rpc::ObjectRef(ObjectRefGetConnectionID(), eClass_lldb_SBDebugger, LLDB_RPC_INVALID_OBJECT_ID));
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
// Skipping temporarily due to rdar://149500008
2+
# XFAIL: system-darwin
3+
# RUN: mkdir -p %t/server
4+
# RUN: mkdir -p %t/lib
5+
# RUN: %lldb-rpc-gen --output-dir=%t %S/../../Inputs/CheckVoidPtr.h
6+
7+
# RUN: cat %t/lib/CheckVoidPtr.cpp | FileCheck %s
8+
9+
// void * followed by length must use a Bytes object
10+
// when being encoded.
11+
# CHECK: lldb_rpc::SBRPC_CHECKVOIDPTR::CheckVoidPtr
12+
# CHECK: Bytes buf_buffer(buf, len);

lldb/tools/CMakeLists.txt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,8 @@ add_subdirectory(intel-features)
77
# example is `check-lldb`. So, we pass EXCLUDE_FROM_ALL here.
88
add_subdirectory(lldb-test EXCLUDE_FROM_ALL)
99
add_subdirectory(lldb-fuzzer EXCLUDE_FROM_ALL)
10+
add_subdirectory(lldb-rpc EXCLUDE_FROM_ALL)
11+
1012

1113
add_lldb_tool_subdirectory(lldb-instr)
1214
add_lldb_tool_subdirectory(lldb-dap)

0 commit comments

Comments
 (0)