Skip to content

[lldb] Upstream lldb-rpc-gen and LLDB RPC server-side emitters #136748

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
Closed
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
65 changes: 65 additions & 0 deletions lldb/scripts/convert-lldb-header-to-rpc-header.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
#!/usr/bin/env python3
# Usage: convert-lldb-header-to-rpc-header.py <path/to/input-header.h> <path/to/output-header.h>
# This scripts takes common LLDB headers (such as lldb-defines.h) and replaces references to LLDB
# with those for RPC. This happens for:
# - namespace definitions
# - namespace usage
# - version string macros
# - ifdef/ifndef lines

import argparse
import os
import re


def main():
parser = argparse.ArgumentParser()
parser.add_argument("input")
parser.add_argument("output")
args = parser.parse_args()
input_path = str(args.input)
output_path = str(args.output)
with open(input_path, "r") as input_file:
lines = input_file.readlines()

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Add a comment stating the purpose of this whole loop. It's replacing things, a lot of things, but it's hard to see the overall picture.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Also a comment at the top of the script stating what it does would be good. The usage is nice, but not enough.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'll add this, ditto to adding comments for what each of these scripts do.

with open(output_path, "w") as output_file:
for line in lines:
# NOTE: We do not use lldb-forward.h or lldb-versioning.h in RPC, so remove
# all includes that are found for these files.
if re.match(
r'#include "lldb/lldb-forward|#include "lldb/lldb-versioning', line
):
continue
# For lldb-rpc-defines.h, replace the ifndef LLDB_LLDB_ portion with LLDB_RPC_ as we're not
# using LLDB private definitions in RPC.
elif re.match(r".+LLDB_LLDB_", line):
output_file.write(re.sub(r"LLDB_LLDB_", r"LLDB_RPC_", line))
# Similarly to lldb-rpc-defines.h, replace the ifndef for LLDB_API in SBDefines.h to LLDB_RPC_API_ for the same reason.
elif re.match(r".+LLDB_API_", line):
output_file.write(re.sub(r"LLDB_API_", r"LLDB_RPC_API_", line))
# Replace the references for the macros that define the versioning strings in
# lldb-rpc-defines.h.
elif re.match(r".+LLDB_VERSION", line):
output_file.write(re.sub(r"LLDB_VERSION", r"LLDB_RPC_VERSION", line))
elif re.match(r".+LLDB_REVISION", line):
output_file.write(re.sub(r"LLDB_REVISION", r"LLDB_RPC_REVISION", line))
elif re.match(r".+LLDB_VERSION_STRING", line):
output_file.write(
re.sub(r"LLDB_VERSION_STRING", r"LLDB_RPC_VERSION_STRING", line)
)
# For local #includes
elif re.match(r'#include "lldb/lldb-', line):
output_file.write(re.sub(r"lldb/lldb-", r"lldb-rpc-", line))
# Rename the lldb namespace definition to lldb-rpc.
elif re.match(r"namespace lldb", line):
output_file.write(re.sub(r"lldb", r"lldb_rpc", line))
# Rename namespace references
elif re.match(r".+lldb::", line):
output_file.write(re.sub(r"lldb::", r"lldb_rpc::", line))
else:
# Write any line that doesn't need to be converted
output_file.write(line)


if __name__ == "__main__":
main()
44 changes: 44 additions & 0 deletions lldb/scripts/framework-header-include-fix.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
#!/usr/bin/env python3
# Usage: framework-header-include-fix.py <path/to/input-header.h> <path/to/output-header.h>
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Add a short description of what this script does. Mainly, what is it fixing specifically?

# This script modifies all #include lines in all lldb-rpc headers
# from either filesystem or local includes to liblldbrpc includes.

import argparse
import os
import re


def main():
parser = argparse.ArgumentParser()
parser.add_argument("input")
parser.add_argument("output")
args = parser.parse_args()
input_path = str(args.input)
output_path = str(args.output)
with open(input_path, "r+") as input_file:
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

See if you need r+ or would r do. Same for w+ below.

lines = input_file.readlines()

with open(output_path, "w+") as output_file:
for line in lines:
# Replace includes from RPCCommon to liblldbrpc includes.
# e.g. #include <lldb-rpc/common/RPCArgument.h> -> #include <LLDBRPC/RPCArgument.h>
if re.match(r".+<lldb-rpc/common", line):
output_file.write(re.sub(r"<lldb-rpc/common", r"<LLDBRPC", line))
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Add comments to explain why these replacements are done.

# Replace all local file includes to liblldbrpc includes.
# e.g. #include "SBFoo.h" -> #include <LLDBRPC/SBFoo.h>
elif re.match(r'#include "(.*)"', line):
include_filename = re.search(r'#include "(.*)"', line).groups()[0]
output_file.write(
re.sub(
r'#include "(.*)"',
r"#include <LLDBRPC/" + include_filename + ">",
line,
)
)
else:
# Write any line that doesn't need to be converted
output_file.write(line)


if __name__ == "__main__":
main()
65 changes: 65 additions & 0 deletions lldb/scripts/framework-header-version-fix.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
#!/usr/bin/env python3
# Usage: framework-header-version-fix.py <path/to/input-header.h> <path/to/output-header.h> MAJOR MINOR PATCH
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As other files, short description here, audit your imports.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

And the file read/write modes, use the most minimal you can.

# This script modifies lldb-rpc-defines.h to uncomment the macro defines used for the LLDB
# major, minor and patch values as well as populating their definitions.

import argparse
import os
import re


def main():
parser = argparse.ArgumentParser()
parser.add_argument("input")
parser.add_argument("output")
parser.add_argument("lldb_version_major")
parser.add_argument("lldb_version_minor")
parser.add_argument("lldb_version_patch")
args = parser.parse_args()
input_path = str(args.input)
output_path = str(args.output)
lldb_version_major = args.lldb_version_major
lldb_version_minor = args.lldb_version_minor
lldb_version_patch = args.lldb_version_patch

with open(input_path, "r") as input_file:
lines = input_file.readlines()

with open(output_path, "w") as output_file:
for line in lines:
# Uncomment the line that defines the LLDB major version and populate its value.
if re.match(r"//#define LLDB_RPC_VERSION$", line):
output_file.write(
re.sub(
r"//#define LLDB_RPC_VERSION",
r"#define LLDB_RPC_VERSION " + lldb_version_major,
line,
)
)
# Uncomment the line that defines the LLDB minor version and populate its value.
elif re.match(r"//#define LLDB_RPC_REVISION$", line):
output_file.write(
re.sub(
r"//#define LLDB_RPC_REVISION",
r"#define LLDB_RPC_REVISION " + lldb_version_minor,
line,
)
)
# Uncomment the line that defines the complete LLDB version string and populate its value.
elif re.match(r"//#define LLDB_RPC_VERSION_STRING$", line):
output_file.write(
re.sub(
r"//#define LLDB_RPC_VERSION_STRING",
r'#define LLDB_RPC_VERSION_STRING "{0}.{1}.{2}"'.format(
lldb_version_major, lldb_version_minor, lldb_version_patch
),
line,
)
)
else:
# Write any line that doesn't need to be converted
output_file.write(line)


if __name__ == "__main__":
main()
20 changes: 20 additions & 0 deletions lldb/test/Shell/RPC/Generator/Inputs/CheckArrayPointer.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
#ifndef LLDB_API_SBRPC_CHECKARRAYPTR_H
#define LLDB_API_SBRPC_CHECKARRAYPTR_H

#include <cstddef>
#include <cstdio>

#include "lldb/API/SBDefines.h"

namespace lldb {
class LLDB_API 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(uint64_t *array, size_t 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,19 @@
#ifndef LLDB_API_SBRPC_CHECKCONSTCHARPTRPTRWITHLEN_H
#define LLDB_API_SBRPC_CHECKCONSTCHARPTRPTRWITHLEN_H

#include <cstddef>
#include <cstdio>

#include "lldb/API/SBDefines.h"

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

}; // class SBRPC_CHECKCONSTCHARPTRPTRWITHLEN
} // namespace lldb

#endif // LLDB_API_SBRPC_CHECKCONSTCHARPTRPTRWITHLEN_H
19 changes: 19 additions & 0 deletions lldb/test/Shell/RPC/Generator/Inputs/CheckConstSBRef.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
#ifndef LLDB_API_SBRPC_CHECKCONSTSBREF_H
#define LLDB_API_SBRPC_CHECKCONSTSBREF_H

#include <cstddef>
#include <cstdio>

#include "lldb/API/SBDefines.h"

namespace lldb {
class LLDB_API SBRPC_CHECKCONSTSBREF {
public:
// Const references to SB classes should be encoded as usual without
// needing to create a new object with its own connection.
int CheckConstSBRef(const SBDebugger &debugger_ref);

}; // class SBRPC_CHECKCONSTSBREF
} // namespace lldb

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

#include <cstddef>
#include <cstdio>

#include "lldb/API/SBDefines.h"

namespace lldb {
class LLDB_API SBRPC_CHECKNONCONSTSBREF {
public:
// Non-const references to SB classes will have new objects
// of that class constructed with the connection as the first parameter
// before being encoded if their existing connection is invalid.
int CheckNonConstSBRef(SBDebugger &debugger_ref);

}; // class SBRPC_CHECKNONCONSTSBREF
} // namespace lldb

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

#include <cstddef>
#include <cstdio>

#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
19 changes: 19 additions & 0 deletions lldb/test/Shell/RPC/Generator/Inputs/CheckVoidPtr.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
#ifndef LLDB_API_SBRPC_CHECKVOIDPTR_H
#define LLDB_API_SBRPC_CHECKVOIDPTR_H

#include <cstddef>
#include <cstdio>

#include "lldb/API/SBDefines.h"

namespace lldb {
class LLDB_API SBRPC_CHECKVOIDPTR {
public:
// void * followed by length must use a Bytes object
// when being encoded.
int CheckVoidPtr(void *buf, size_t 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,13 @@
// Skipping temporarily due to rdar://149500008
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not a great sign that all the client tests are disabled on the system that they're originally intended for.

What exactly is the issue here?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is probably just an artifact of the downstream fork, I believe @chelcassanova has a fix for this already

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The issue is that the tests need the clang resource dir in order to run properly (since lldb-rpc-gen is a ClangTool). They were originally skipped so that I could add that dir to LLDB lit here: #136761

# XFAIL: system-darwin
# RUN: mkdir -p %t/server
# RUN: mkdir -p %t/lib
# RUN: %lldb-rpc-gen --output-dir=%t %S/../../Inputs/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: lldb_rpc::SBRPC_CHECKARRAYPTR::CheckArrayPtr
# CHECK: Bytes array_buffer(array, sizeof(uint64_t));
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
// Skipping temporarily due to rdar://149500008
# XFAIL: system-darwin
# RUN: mkdir -p %t/server
# RUN: mkdir -p %t/lib
# RUN: %lldb-rpc-gen --output-dir=%t %S/../../Inputs/CheckConstCharPtrPtrWithLen.h

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

// const char ** followed by len must use a StringList
// when being encoded.
# CHECK: lldb_rpc::SBRPC_CHECKCONSTCHARPTRPTRWITHLEN::CheckConstCharPtrPtrWithLen
# CHECK: StringList arg1_list
16 changes: 16 additions & 0 deletions lldb/test/Shell/RPC/Generator/Tests/Client/CheckConstSBRef.test
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
// Skipping temporarily due to rdar://149500008
# XFAIL: system-darwin
# RUN: mkdir -p %t/server
# RUN: mkdir -p %t/lib
# RUN: %lldb-rpc-gen --output-dir=%t %S/../../Inputs/CheckConstSBRef.h

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

// Const references to SB classes should be encoded as usual without
// needing to create a new object with its own connection. Here
// we're checking to make sure that the given SB object ref will get
// encoded immediately after the previous argument gets encoded without
// anything happening in between.
# CHECK: lldb_rpc::SBRPC_CHECKCONSTSBREF::CheckConstSBRef
# CHECK: RPCValueEncoder(send, rpc_common::RPCPacket::ValueType::Argument, *this);
# CHECK: RPCValueEncoder(send, rpc_common::RPCPacket::ValueType::Argument, debugger_ref)
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
// Skipping temporarily due to rdar://149500008
# XFAIL: system-darwin
# RUN: mkdir -p %t/server
# RUN: mkdir -p %t/lib
# RUN: %lldb-rpc-gen --output-dir=%t %S/../../Inputs/CheckNonConstSBRef.h

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

// Non-const references to SB classes will have new objects
// of that class constructed with the connection as the first parameter
// before being encoded if their existing connection is invalid.
# CHECK: lldb_rpc::SBRPC_CHECKNONCONSTSBREF::CheckNonConstSBRef
# CHECK: if (connection_sp && !debugger_ref.ObjectRefIsValid())
# CHECK: debugger_ref = lldb_rpc::SBDebugger(connection_sp);
# CHECK: RPCValueEncoder(send, rpc_common::RPCPacket::ValueType::Argument, debugger_ref);
17 changes: 17 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,17 @@
// Skipping temporarily due to rdar://149500008
# XFAIL: system-darwin
# RUN: mkdir -p %t/server
# RUN: mkdir -p %t/lib
# RUN: %lldb-rpc-gen --output-dir=%t %S/../../Inputs/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: lldb_rpc::SBRPC_CHECKSBPTR::CheckSBPtr
# CHECK: if (debugger_ptr)
# CHECK: RPCValueEncoder(send, rpc_common::RPCPacket::ValueType::Argument, *debugger_ptr);
# CHECK: else
# CHECK: RPCValueEncoder(send, rpc_common::RPCPacket::ValueType::Argument, rpc::ObjectRef(ObjectRefGetConnectionID(), eClass_lldb_SBDebugger, LLDB_RPC_INVALID_OBJECT_ID));
12 changes: 12 additions & 0 deletions lldb/test/Shell/RPC/Generator/Tests/Client/CheckVoidPtr.test
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
// Skipping temporarily due to rdar://149500008
# XFAIL: system-darwin
# RUN: mkdir -p %t/server
# RUN: mkdir -p %t/lib
# RUN: %lldb-rpc-gen --output-dir=%t %S/../../Inputs/CheckVoidPtr.h

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

// void * followed by length must use a Bytes object
// when being encoded.
# CHECK: lldb_rpc::SBRPC_CHECKVOIDPTR::CheckVoidPtr
# CHECK: Bytes buf_buffer(buf, len);
Loading
Loading