================
@@ -265,6 +267,349 @@ StructuredData::DictionarySP
ScriptInterpreterPython::GetInterpreterInfo() {
return info_json.CreateStructuredDictionary();
}
+llvm::Expected<std::string> ScriptInterpreterPython::ExtensionToImportPath(
+ lldb::ScriptedExtension extension) {
+ switch (extension) {
+ case eScriptedExtensionOperatingSystem:
+ return "lldb.plugins.operating_system";
+ case eScriptedExtensionScriptedPlatform:
+ return "lldb.plugins.scripted_platform";
+ case eScriptedExtensionScriptedProcess:
+ return "lldb.plugins.scripted_process";
+ case eScriptedExtensionScriptedHook:
+ return "lldb.plugins.scripted_hook";
+ case eScriptedExtensionScriptedBreakpointResolver:
+ return "lldb.plugins.scripted_breakpoint";
+ case eScriptedExtensionScriptedThreadPlan:
+ return "lldb.plugins.scripted_thread_plan";
+ case eScriptedExtensionScriptedFrameProvider:
+ return "lldb.plugins.scripted_frame_provider";
+ case eScriptedExtensionScriptedThread:
+ case eScriptedExtensionScriptedFrame:
+ return "lldb.plugins.scripted_process";
+ case eScriptedExtensionInvalid:
+ return llvm::createStringError("invalid extension name");
+ }
+ return llvm::createStringError("invalid extension name");
+}
+
+llvm::Expected<StructuredData::ObjectSP>
+ScriptInterpreterPython::GetExtensionSchema(
+ llvm::SmallVector<llvm::StringRef> &extension_path) {
+ lldb::ScriptedExtension extension =
+ ScriptInterpreter::StringToExtension(extension_path.back());
+ auto import_path_or_err = ExtensionToImportPath(extension);
+ if (!import_path_or_err)
+ return import_path_or_err.takeError();
+
+ StreamString command_stream;
+ // __import__(path, fromlist=['']) imports the submodule and returns it
+ // directly (rather than the top-level package), as a single expression --
+ // this keeps the whole call eval-able in one line while guaranteeing the
+ // module is imported first; referencing "<import_path>.<ClassName>"
+ // directly would only work if something else had already imported
+ // <import_path> as a side effect.
+ command_stream.Printf("lldb.embedded_interpreter.generate_extension_schema("
+ "__import__('%s', fromlist=['']).%s)",
+ import_path_or_err->c_str(),
+
ScriptInterpreter::ExtensionToString(extension).data());
+
+ // Use eScriptReturnTypeOpaqueObject: it transfers a real owned reference
+ // we can safely extract the string from. eScriptReturnTypeCharStrOrNone
+ // instead hands back a pointer to a temporary Python object's buffer
+ // that gets destroyed (and, for a freshly created string like this one,
+ // deallocated) as soon as ExecuteOneLineWithReturn returns -- reading
+ // it afterwards is a use-after-free.
+ void *result_obj = nullptr;
+ if (!ExecuteOneLineWithReturn(
+ command_stream.GetData(),
+ ScriptInterpreter::eScriptReturnTypeOpaqueObject, &result_obj,
+ ExecuteScriptOptions().SetEnableIO(false)))
+ return llvm::createStringError("invalid extension schema format");
+
+ // ExecuteOneLineWithReturn releases the GIL before returning, so touching
+ // the returned object (Str() below can execute arbitrary Python code) must
+ // re-acquire it first. py_result is scoped so its destructor (a DECREF)
+ // also runs before the GIL is released below, not after.
+ std::string schema_str;
+ {
+ PyGILState_STATE gil_state = PyGILState_Ensure();
+ {
+ PythonObject py_result(PyRefType::Owned,
+ static_cast<PyObject *>(result_obj));
+ if (py_result.IsAllocated() && py_result.get() != Py_None)
+ schema_str = py_result.Str().GetString().str();
+ }
+ PyGILState_Release(gil_state);
+ }
+
+ if (schema_str.empty())
+ return llvm::createStringError("empty extension schema");
+ return StructuredData::ParseJSON(schema_str);
+}
+
+llvm::Error ScriptInterpreterPython::ParseExtensionSchema(
+ Stream &s, llvm::StringRef output_script_prefix,
+ llvm::SmallVector<llvm::StringRef> &extension_path,
+ bool generate_non_abstract_methods, std::set<std::string> &typing_imports)
{
+ auto schema_or_err = GetExtensionSchema(extension_path);
+ if (!schema_or_err)
+ return schema_or_err.takeError();
+
+ StructuredData::ObjectSP schema = *schema_or_err;
+ StructuredData::Dictionary *dict = schema->GetAsDictionary();
----------------
JDevlieghere wrote:
Is `schema` guaranteed to be non-null?
https://github.com/llvm/llvm-project/pull/209647
_______________________________________________
lldb-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits