Skip to content

Commit 5a97d76

Browse files
Rahul Reddy ChamalaRahul Reddy Chamala
authored andcommitted
Add support for ondemand sourcefile fetch using python callback
Summary: Test Plan: Reviewers: Subscribers: Tasks: Tags: Differential Revision: https://phabricator.intern.facebook.com/D66931972
1 parent 1b984ba commit 5a97d76

File tree

11 files changed

+253
-6
lines changed

11 files changed

+253
-6
lines changed

lldb/bindings/python/python-typemaps.swig

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -696,3 +696,47 @@ template <> bool SetNumberFromPyObject<double>(double &number, PyObject *obj) {
696696
$1 = $input == Py_None;
697697
$1 = $1 || PyCallable_Check(reinterpret_cast<PyObject *>($input));
698698
}
699+
700+
// For lldb::SBPlatformResolveSourceFileCallback
701+
%typemap(in) (lldb::SBPlatformResolveSourceFileCallback callback, void *callback_baton) {
702+
if (!($input == Py_None ||
703+
PyCallable_Check(reinterpret_cast<PyObject *>($input)))) {
704+
PyErr_SetString(PyExc_TypeError, "Need a callable object or None!");
705+
SWIG_fail;
706+
}
707+
708+
if ($input == Py_None) {
709+
$1 = nullptr;
710+
$2 = nullptr;
711+
} else {
712+
PythonCallable callable = Retain<PythonCallable>($input);
713+
if (!callable.IsValid()) {
714+
PyErr_SetString(PyExc_TypeError, "Need a valid callable object");
715+
SWIG_fail;
716+
}
717+
718+
llvm::Expected<PythonCallable::ArgInfo> arg_info = callable.GetArgInfo();
719+
if (!arg_info) {
720+
PyErr_SetString(PyExc_TypeError,
721+
("Could not get arguments: " +
722+
llvm::toString(arg_info.takeError())).c_str());
723+
SWIG_fail;
724+
}
725+
726+
if (arg_info.get().max_positional_args != 3) {
727+
PyErr_SetString(PyExc_TypeError, "Expected 3 argument callable object");
728+
SWIG_fail;
729+
}
730+
731+
Py_INCREF($input);
732+
733+
$1 = LLDBSwigPythonCallResolveSourceFileCallback;
734+
$2 = $input;
735+
}
736+
}
737+
738+
%typemap(typecheck) (lldb::SBPlatformResolveSourceFileCallback callback,
739+
void *callback_baton) {
740+
$1 = $input == Py_None;
741+
$1 = $1 || PyCallable_Check(reinterpret_cast<PyObject *>($input));
742+
}

lldb/bindings/python/python-wrapper.swig

Lines changed: 47 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -844,7 +844,7 @@ bool lldb_private::python::SWIGBridge::LLDBSwigPythonCallParsedCommandObject(
844844
auto pfunc = self.ResolveName<PythonCallable>("__call__");
845845

846846
if (!pfunc.IsAllocated()) {
847-
cmd_retobj.AppendError("Could not find '__call__' method in implementation class");
847+
cmd_retobj.AppendError("Could not find '__call__' method in implementation class");
848848
return false;
849849
}
850850

@@ -1148,4 +1148,50 @@ static SBError LLDBSwigPythonCallLocateModuleCallback(
11481148

11491149
return *sb_error_ptr;
11501150
}
1151+
1152+
static SBError LLDBSwigPythonCallResolveSourceFileCallback(
1153+
void *callback_baton,
1154+
const char* build_id,
1155+
const SBFileSpec &original_source_file_spec_sb,
1156+
SBFileSpec &resolved_source_file_spec_sb) {
1157+
SWIG_Python_Thread_Block swig_thread_block;
1158+
1159+
PyErr_Cleaner py_err_cleaner(true);
1160+
1161+
PyObject *py_build_id = PyUnicode_FromString(build_id);
1162+
PythonObject build_id_arg(PyRefType::Borrowed,py_build_id);
1163+
PythonObject original_source_file_spec_arg = SWIGBridge::ToSWIGWrapper(
1164+
std::make_unique<SBFileSpec>(original_source_file_spec_sb));
1165+
PythonObject resolved_source_file_spec_arg = SWIGBridge::ToSWIGWrapper(
1166+
std::make_unique<SBFileSpec>(resolved_source_file_spec_sb));
1167+
1168+
PythonCallable callable =
1169+
Retain<PythonCallable>(reinterpret_cast<PyObject *>(callback_baton));
1170+
if (!callable.IsValid()) {
1171+
return SBError("The callback callable is not valid.");
1172+
}
1173+
1174+
PythonObject result = callable(build_id_arg, original_source_file_spec_arg,
1175+
resolved_source_file_spec_arg);
1176+
1177+
if (!result.IsAllocated())
1178+
return SBError("No result.");
1179+
lldb::SBError *sb_error_ptr = nullptr;
1180+
if (SWIG_ConvertPtr(result.get(), (void **)&sb_error_ptr,
1181+
SWIGTYPE_p_lldb__SBError, 0) == -1) {
1182+
return SBError("Result is not SBError.");
1183+
}
1184+
1185+
if (sb_error_ptr->Success()) {
1186+
lldb::SBFileSpec *sb_resolved_source_file_spec_ptr = nullptr;
1187+
if (SWIG_ConvertPtr(resolved_source_file_spec_arg.get(),
1188+
(void **)&sb_resolved_source_file_spec_ptr,
1189+
SWIGTYPE_p_lldb__SBFileSpec, 0) == -1)
1190+
return SBError("resolved_source_file_spec is not SBFileSpec.");
1191+
1192+
resolved_source_file_spec_sb = *sb_resolved_source_file_spec_ptr;
1193+
}
1194+
1195+
return *sb_error_ptr;
1196+
}
11511197
%}

lldb/include/lldb/API/SBDefines.h

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
#include "lldb/lldb-defines.h"
1313
#include "lldb/lldb-enumerations.h"
1414
#include "lldb/lldb-forward.h"
15+
#include "lldb/lldb-private.h"
1516
#include "lldb/lldb-types.h"
1617
#include "lldb/lldb-versioning.h"
1718

@@ -141,9 +142,14 @@ typedef bool (*SBBreakpointHitCallback)(void *baton, SBProcess &process,
141142
typedef void (*SBDebuggerDestroyCallback)(lldb::user_id_t debugger_id,
142143
void *baton);
143144

144-
typedef SBError (*SBPlatformLocateModuleCallback)(
145+
typedef lldb::SBError (*SBPlatformLocateModuleCallback)(
145146
void *baton, const SBModuleSpec &module_spec, SBFileSpec &module_file_spec,
146147
SBFileSpec &symbol_file_spec);
148+
149+
typedef lldb::SBError (*SBPlatformResolveSourceFileCallback)(
150+
void *baton, const char *buildId,
151+
const SBFileSpec &original_source_file_spec,
152+
SBFileSpec &resolved_source_file_spec);
147153
}
148154

149155
#endif // LLDB_API_SBDEFINES_H

lldb/include/lldb/API/SBPlatform.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -190,6 +190,9 @@ class LLDB_API SBPlatform {
190190
SBError SetLocateModuleCallback(lldb::SBPlatformLocateModuleCallback callback,
191191
void *callback_baton);
192192

193+
SBError SetResolveSourceFileCallback(
194+
lldb::SBPlatformResolveSourceFileCallback callback, void *callback_baton);
195+
193196
protected:
194197
friend class SBDebugger;
195198
friend class SBTarget;

lldb/include/lldb/Symbol/LineEntry.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -128,7 +128,7 @@ struct LineEntry {
128128
///
129129
/// \param[in] target_sp
130130
/// Shared pointer to the target this LineEntry belongs to.
131-
void ApplyFileMappings(lldb::TargetSP target_sp);
131+
void ApplyFileMappings(lldb::TargetSP target_sp, const Address &address);
132132

133133
/// Helper to access the file.
134134
const FileSpec &GetFile() const { return file_sp->GetSpecOnly(); }
@@ -181,6 +181,7 @@ struct LineEntry {
181181
/// Returns \b true if lhs < rhs, false otherwise.
182182
bool operator<(const LineEntry &lhs, const LineEntry &rhs);
183183

184+
// Add signature for CallFetchSourceFileCallBack
184185
} // namespace lldb_private
185186

186187
#endif // LLDB_SYMBOL_LINEENTRY_H

lldb/include/lldb/Target/Platform.h

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -329,6 +329,10 @@ class Platform : public PluginInterface {
329329
virtual bool GetModuleSpec(const FileSpec &module_file_spec,
330330
const ArchSpec &arch, ModuleSpec &module_spec);
331331

332+
void CallResolveSourceFileCallbackIfSet(
333+
const char *build_id, const FileSpec &original_source_file_spec,
334+
FileSpec &resolved_source_file_spec, bool *did_create_ptr);
335+
332336
virtual Status ConnectRemote(Args &args);
333337

334338
virtual Status DisconnectRemote();
@@ -921,6 +925,11 @@ class Platform : public PluginInterface {
921925
FileSpec &symbol_file_spec)>
922926
LocateModuleCallback;
923927

928+
typedef std::function<Status(const char *buildId,
929+
const FileSpec &original_fileSpec,
930+
FileSpec &newFileSpec)>
931+
ResolveSourceFileCallback;
932+
924933
/// Set locate module callback. This allows users to implement their own
925934
/// module cache system. For example, to leverage artifacts of build system,
926935
/// to bypass pulling files from remote platform, or to search symbol files
@@ -929,6 +938,10 @@ class Platform : public PluginInterface {
929938

930939
LocateModuleCallback GetLocateModuleCallback() const;
931940

941+
void SetResolveSourceFileCallback(ResolveSourceFileCallback callback);
942+
943+
ResolveSourceFileCallback GetResolveSourceFileCallback() const;
944+
932945
protected:
933946
/// Create a list of ArchSpecs with the given OS and a architectures. The
934947
/// vendor field is left as an "unspecified unknown".
@@ -977,6 +990,7 @@ class Platform : public PluginInterface {
977990
bool m_calculated_trap_handlers;
978991
const std::unique_ptr<ModuleCache> m_module_cache;
979992
LocateModuleCallback m_locate_module_callback;
993+
ResolveSourceFileCallback m_resolve_source_file_callback;
980994

981995
/// Ask the Platform subclass to fill in the list of trap handler names
982996
///

lldb/source/API/SBPlatform.cpp

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -734,3 +734,39 @@ SBError SBPlatform::SetLocateModuleCallback(
734734
});
735735
return SBError();
736736
}
737+
738+
SBError SBPlatform::SetResolveSourceFileCallback(
739+
lldb::SBPlatformResolveSourceFileCallback callback, void *callback_baton) {
740+
LLDB_INSTRUMENT_VA(this, callback, callback_baton);
741+
PlatformSP platform_sp(GetSP());
742+
if (!platform_sp) {
743+
return SBError("invalid platform");
744+
}
745+
746+
if (!callback) {
747+
// Clear the callback.
748+
platform_sp->SetResolveSourceFileCallback(nullptr);
749+
return SBError("invalid callback");
750+
}
751+
752+
// Platform.h does not accept lldb::SBPlatformFetchSourceFileCallback
753+
// directly because of the SBFileSpec dependencies. Use a lambda to convert
754+
// FileSpec <--> SBFileSpec for the callback arguments.
755+
platform_sp->SetResolveSourceFileCallback(
756+
[callback, callback_baton](const char *build_id,
757+
const FileSpec &original_source_file_spec,
758+
FileSpec &resolved_source_file_spec) {
759+
SBFileSpec resolved_source_file_spec_sb(resolved_source_file_spec);
760+
761+
SBError error =
762+
callback(callback_baton, build_id, original_source_file_spec,
763+
resolved_source_file_spec_sb);
764+
765+
if (error.Success()) {
766+
resolved_source_file_spec = resolved_source_file_spec_sb.ref();
767+
}
768+
769+
return error.ref();
770+
});
771+
return SBError();
772+
}

lldb/source/Symbol/LineEntry.cpp

Lines changed: 43 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,10 @@
77
//===----------------------------------------------------------------------===//
88

99
#include "lldb/Symbol/LineEntry.h"
10+
#include "lldb/Core/Module.h"
1011
#include "lldb/Symbol/CompileUnit.h"
12+
#include "lldb/Symbol/SymbolContext.h"
13+
#include "lldb/Target/Platform.h"
1114
#include "lldb/Target/Process.h"
1215
#include "lldb/Target/Target.h"
1316

@@ -240,8 +243,47 @@ AddressRange LineEntry::GetSameLineContiguousAddressRange(
240243
return complete_line_range;
241244
}
242245

243-
void LineEntry::ApplyFileMappings(lldb::TargetSP target_sp) {
246+
void LineEntry::ApplyFileMappings(lldb::TargetSP target_sp,
247+
const Address &address) {
244248
if (target_sp) {
249+
250+
SymbolContext sc;
251+
target_sp->GetImages().ResolveSymbolContextForAddress(
252+
address, lldb::eSymbolContextModule, sc);
253+
lldb::ModuleSP module_sp = sc.module_sp;
254+
255+
auto spec = original_file_sp->GetSpecOnly();
256+
std::string path = spec.GetPath();
257+
258+
if (module_sp) {
259+
ObjectFile *obj_file = module_sp->GetObjectFile();
260+
module_sp->GetFileSpec();
261+
if (obj_file) {
262+
263+
UUID build_id = obj_file->GetUUID();
264+
auto buildId_string = new std::string(build_id.GetAsString());
265+
266+
const char *build_id_ptr = buildId_string->c_str();
267+
268+
FileSpec newSpec;
269+
// Fetches the new spec file
270+
bool *didFetchSourceFile = new bool(false);
271+
272+
lldb::PlatformSP platform_sp = target_sp->GetPlatform();
273+
if (!platform_sp)
274+
return;
275+
276+
FileSpec resolved_source_file_spec;
277+
platform_sp->CallResolveSourceFileCallbackIfSet(
278+
build_id_ptr, spec, resolved_source_file_spec, didFetchSourceFile);
279+
if (didFetchSourceFile) {
280+
original_file_sp =
281+
std::make_shared<SupportFile>(resolved_source_file_spec);
282+
file_sp = std::make_shared<SupportFile>(resolved_source_file_spec);
283+
}
284+
}
285+
}
286+
245287
// Apply any file remappings to our file.
246288
if (auto new_file_spec = target_sp->GetSourcePathMap().FindFile(
247289
original_file_sp->GetSpecOnly()))

lldb/source/Target/Platform.cpp

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1756,6 +1756,50 @@ void Platform::CallLocateModuleCallbackIfSet(const ModuleSpec &module_spec,
17561756
}
17571757
}
17581758

1759+
void Platform::CallResolveSourceFileCallbackIfSet(
1760+
const char *build_id, const FileSpec &original_source_file_spec,
1761+
FileSpec &resolved_source_file_spec, bool *did_create_ptr) {
1762+
if (!m_resolve_source_file_callback) {
1763+
// Fetch source file callback is not set.
1764+
return;
1765+
}
1766+
1767+
FileSpec module_file_spec;
1768+
Status error = m_resolve_source_file_callback(
1769+
build_id, original_source_file_spec, resolved_source_file_spec);
1770+
1771+
// Fetch source file callback is set and called. Check the error.
1772+
Log *log = GetLog(LLDBLog::Platform);
1773+
if (error.Fail()) {
1774+
LLDB_LOGF(log, "%s: Fetch source file callback failed: %s",
1775+
LLVM_PRETTY_FUNCTION, error.AsCString());
1776+
return;
1777+
}
1778+
1779+
if (!resolved_source_file_spec) {
1780+
LLDB_LOGF(log,
1781+
"%s: fetch source file callback did not set "
1782+
"resolved_source_file_spec",
1783+
LLVM_PRETTY_FUNCTION);
1784+
return;
1785+
}
1786+
1787+
// If the callback returned a source file, it should exist.
1788+
if (resolved_source_file_spec &&
1789+
!FileSystem::Instance().Exists(resolved_source_file_spec)) {
1790+
LLDB_LOGF(log,
1791+
"%s: fetch source file callback set a non-existent file to "
1792+
"source_file_spec: %s",
1793+
LLVM_PRETTY_FUNCTION,
1794+
resolved_source_file_spec.GetPath().c_str());
1795+
// Clear source_file_spec for the error.
1796+
resolved_source_file_spec.Clear();
1797+
return;
1798+
}
1799+
1800+
*did_create_ptr = true;
1801+
}
1802+
17591803
bool Platform::GetCachedSharedModule(const ModuleSpec &module_spec,
17601804
lldb::ModuleSP &module_sp,
17611805
bool *did_create_ptr) {
@@ -2161,6 +2205,16 @@ Platform::LocateModuleCallback Platform::GetLocateModuleCallback() const {
21612205
return m_locate_module_callback;
21622206
}
21632207

2208+
void Platform::SetResolveSourceFileCallback(
2209+
ResolveSourceFileCallback callback) {
2210+
m_resolve_source_file_callback = callback;
2211+
}
2212+
2213+
Platform::ResolveSourceFileCallback
2214+
Platform::GetResolveSourceFileCallback() const {
2215+
return m_resolve_source_file_callback;
2216+
}
2217+
21642218
PlatformSP PlatformList::GetOrCreate(llvm::StringRef name) {
21652219
std::lock_guard<std::recursive_mutex> guard(m_mutex);
21662220
for (const PlatformSP &platform_sp : m_platforms) {

lldb/source/Target/StackFrame.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -395,7 +395,7 @@ StackFrame::GetSymbolContext(SymbolContextItem resolve_scope) {
395395
if ((resolved & eSymbolContextLineEntry) &&
396396
!m_sc.line_entry.IsValid()) {
397397
m_sc.line_entry = sc.line_entry;
398-
m_sc.line_entry.ApplyFileMappings(m_sc.target_sp);
398+
m_sc.line_entry.ApplyFileMappings(m_sc.target_sp, lookup_addr);
399399
}
400400
}
401401
} else {

0 commit comments

Comments
 (0)