serge-sans-paille updated this revision to Diff 227695.
serge-sans-paille edited the summary of this revision.

Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D69793/new/

https://reviews.llvm.org/D69793

Files:
  lldb/source/Plugins/ScriptInterpreter/Python/CMakeLists.txt
  lldb/source/Plugins/ScriptInterpreter/Python/PythonReadline.cpp
  lldb/source/Plugins/ScriptInterpreter/Python/PythonReadline.h
  lldb/source/Plugins/ScriptInterpreter/Python/ScriptInterpreterPython.cpp

Index: lldb/source/Plugins/ScriptInterpreter/Python/ScriptInterpreterPython.cpp
===================================================================
--- lldb/source/Plugins/ScriptInterpreter/Python/ScriptInterpreterPython.cpp
+++ lldb/source/Plugins/ScriptInterpreter/Python/ScriptInterpreterPython.cpp
@@ -17,6 +17,7 @@
 
 #include "PythonDataObjects.h"
 #include "PythonExceptionState.h"
+#include "PythonReadline.h"
 #include "ScriptInterpreterPythonImpl.h"
 
 #include "lldb/API/SBFrame.h"
@@ -207,6 +208,22 @@
 
     InitializePythonHome();
 
+#ifndef LLDB_DISABLE_LIBEDIT
+    // Python's readline is incompatible with libedit being linked into lldb.
+    // Provide a patched version local to the embedded interpreter.
+    bool ReadlinePatched = false;
+    for (auto *p = PyImport_Inittab; p->name != NULL; p++) {
+      if (strcmp(p->name, "readline") == 0) {
+        p->initfunc = initlldb_readline;
+        break;
+      }
+    }
+    if (!ReadlinePatched) {
+      PyImport_AppendInittab("readline", initlldb_readline);
+      ReadlinePatched = true;
+    }
+#endif
+
     // Register _lldb as a built-in module.
     PyImport_AppendInittab("_lldb", LLDBSwigPyInit);
 
Index: lldb/source/Plugins/ScriptInterpreter/Python/PythonReadline.h
===================================================================
--- /dev/null
+++ lldb/source/Plugins/ScriptInterpreter/Python/PythonReadline.h
@@ -0,0 +1,17 @@
+//===-- PythonReadline.h -------------------------------------------*- C++
+//-*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLDB_PLUGINS_SCRIPTINTERPRETER_PYTHON_PYTHONREADLINE_H
+#define LLDB_PLUGINS_SCRIPTINTERPRETER_PYTHON_PYTHONREADLINE_H
+
+#ifndef LLDB_DISABLE_LIBEDIT
+extern "C" PyMODINIT_FUNC initlldb_readline(void);
+#endif
+
+#endif // LLDB_PLUGINS_SCRIPTINTERPRETER_PYTHON_PYTHONREADLINE_H
Index: lldb/source/Plugins/ScriptInterpreter/Python/PythonReadline.cpp
===================================================================
--- /dev/null
+++ lldb/source/Plugins/ScriptInterpreter/Python/PythonReadline.cpp
@@ -0,0 +1,93 @@
+#ifdef LLDB_DISABLE_LIBEDIT
+
+// no need to hack into Python's readline module if libedit isn't used.
+
+#else
+// NOTE: Since Python may define some pre-processor definitions which affect the
+// standard headers on some systems, you must include Python.h before any
+// standard headers are included.
+#include "Python.h"
+
+#include <stdio.h>
+
+#include <editline/readline.h>
+
+// Simple implementation of the Python readline module using libedit.
+// In the event that libedit is excluded from the build, this turns
+// back into a null implementation that blocks the module from pulling
+// in the GNU readline shared lib, which causes linkage confusion when
+// both readline and libedit's readline compatibility symbols collide.
+//
+// Currently it only installs a PyOS_ReadlineFunctionPointer, without
+// implementing any of the readline module methods. This is meant to
+// work around LLVM pr18841 to avoid seg faults in the stock Python
+// readline.so linked against GNU readline.
+
+#ifndef LLDB_DISABLE_LIBEDIT
+PyDoc_STRVAR(moduleDocumentation,
+             "Simple readline module implementation based on libedit.");
+#else
+PyDoc_STRVAR(moduleDocumentation,
+             "Stub module meant to avoid linking GNU readline.");
+#endif
+
+#if PY_MAJOR_VERSION >= 3
+static struct PyModuleDef readline_module = {
+    PyModuleDef_HEAD_INIT, // m_base
+    "lldb_editline",       // m_name
+    moduleDocumentation,   // m_doc
+    -1,                    // m_size
+    nullptr,               // m_methods
+    nullptr,               // m_reload
+    nullptr,               // m_traverse
+    nullptr,               // m_clear
+    nullptr,               // m_free
+};
+#else
+static struct PyMethodDef moduleMethods[] = {{nullptr, nullptr, 0, nullptr}};
+#endif
+
+#ifndef LLDB_DISABLE_LIBEDIT
+static char *
+#if PY_MAJOR_VERSION >= 3
+simple_readline(FILE *stdin, FILE *stdout, const char *prompt)
+#else
+simple_readline(FILE *stdin, FILE *stdout, char *prompt)
+#endif
+{
+  rl_instream = stdin;
+  rl_outstream = stdout;
+  char *line = readline(prompt);
+  if (!line) {
+    char *ret = (char *)PyMem_RawMalloc(1);
+    if (ret != NULL)
+      *ret = '\0';
+    return ret;
+  }
+  if (*line)
+    add_history(line);
+  int n = strlen(line);
+  char *ret = (char *)PyMem_RawMalloc(n + 2);
+  if (ret) {
+    strncpy(ret, line, n);
+    free(line);
+    ret[n] = '\n';
+    ret[n + 1] = '\0';
+  }
+  return ret;
+}
+#endif
+
+PyMODINIT_FUNC initlldb_readline(void) {
+#ifndef LLDB_DISABLE_LIBEDIT
+  PyOS_ReadlineFunctionPointer = simple_readline;
+#endif
+
+#if PY_MAJOR_VERSION >= 3
+  return PyModule_Create(&readline_module);
+#else
+  Py_InitModule4("lldb_readline", moduleMethods, moduleDocumentation,
+                 static_cast<PyObject *>(NULL), PYTHON_API_VERSION);
+#endif
+}
+#endif
Index: lldb/source/Plugins/ScriptInterpreter/Python/CMakeLists.txt
===================================================================
--- lldb/source/Plugins/ScriptInterpreter/Python/CMakeLists.txt
+++ lldb/source/Plugins/ScriptInterpreter/Python/CMakeLists.txt
@@ -14,6 +14,7 @@
 add_lldb_library(lldbPluginScriptInterpreterPython PLUGIN
   PythonDataObjects.cpp
   PythonExceptionState.cpp
+  PythonReadline.cpp
   ScriptInterpreterPython.cpp
 
   LINK_LIBS
_______________________________________________
lldb-commits mailing list
lldb-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits

Reply via email to