Skip to content

9.x pr43830 #13

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
wants to merge 2 commits into from
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
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ endif()
add_lldb_library(lldbPluginScriptInterpreterPython PLUGIN
PythonDataObjects.cpp
PythonExceptionState.cpp
PythonReadline.cpp
ScriptInterpreterPython.cpp

LINK_LIBS
Expand Down
80 changes: 80 additions & 0 deletions lldb/source/Plugins/ScriptInterpreter/Python/PythonReadline.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
#include "PythonReadline.h"

#ifdef LLDB_USE_LIBEDIT_READLINE_COMPAT_MODULE

#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.
//
// Bug on the cpython side: https://bugs.python.org/issue38634

PyDoc_STRVAR(moduleDocumentation,
"Simple readline module implementation based on libedit.");

#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

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;
}

PyMODINIT_FUNC initlldb_readline(void) {
PyOS_ReadlineFunctionPointer = simple_readline;

#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
26 changes: 26 additions & 0 deletions lldb/source/Plugins/ScriptInterpreter/Python/PythonReadline.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
//===-- 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

#if !defined(LLDB_DISABLE_LIBEDIT) && defined(__linux__)
// 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"

// no need to hack into Python's readline module if libedit isn't used.
//
#define LLDB_USE_LIBEDIT_READLINE_COMPAT_MODULE 1

extern "C" PyMODINIT_FUNC initlldb_readline(void);

#endif

#endif // LLDB_PLUGINS_SCRIPTINTERPRETER_PYTHON_PYTHONREADLINE_H
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@

#include "PythonDataObjects.h"
#include "PythonExceptionState.h"
#include "PythonReadline.h"
#include "ScriptInterpreterPythonImpl.h"

#include "lldb/API/SBFrame.h"
Expand Down Expand Up @@ -207,6 +208,22 @@ struct InitializePythonRAII {

InitializePythonHome();

#ifdef LLDB_USE_LIBEDIT_READLINE_COMPAT_MODULE
// 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);

Expand Down