@@ -14,6 +14,45 @@ namespace pystack {
1414
1515using file_unique_ptr = std::unique_ptr<FILE , std::function<int (FILE *)>>;
1616
17+ static int
18+ set_module_process_pid_userdata (
19+ Dwfl_Module* mod __attribute__ ((unused)),
20+ void** userdata,
21+ const char* name __attribute__((unused)),
22+ Dwarf_Addr start __attribute__((unused)),
23+ void* arg)
24+ {
25+ *userdata = arg;
26+ return DWARF_CB_OK ;
27+ }
28+
29+ // Retry an absolute module path relative to /proc/<pid>/root for container targets.
30+ static int
31+ find_elf_through_proc_pid_root (void ** userdata, const char * modname, char ** file_name)
32+ {
33+ if (userdata == nullptr || *userdata == nullptr || modname == nullptr || modname[0 ] != ' /' ) {
34+ return -1 ;
35+ }
36+
37+ const auto pid = *static_cast <const int *>(*userdata);
38+ const std::string rooted_path = " /proc/" + std::to_string (pid) + " /root" + modname;
39+ int fd = open (rooted_path.c_str (), O_RDONLY );
40+ if (fd < 0 ) {
41+ return -1 ;
42+ }
43+ if (file_name == nullptr ) {
44+ return fd;
45+ }
46+
47+ *file_name = strdup (rooted_path.c_str ());
48+ if (*file_name == nullptr ) {
49+ close (fd);
50+ return -1 ;
51+ }
52+
53+ return fd;
54+ }
55+
1756int
1857pystack_find_elf (
1958 Dwfl_Module* mod,
@@ -31,10 +70,14 @@ pystack_find_elf(
3170 return ret;
3271 }
3372 ret = dwfl_linux_proc_find_elf (mod, userdata, modname, base, file_name, elfp);
34- if (file_name == nullptr ) {
73+ if (ret < 0 ) {
74+ ret = find_elf_through_proc_pid_root (userdata, modname, file_name);
75+ }
76+ if (ret < 0 ) {
3577 LOG (DEBUG ) << " Could not locate debug info for " << the_modname;
3678 } else {
37- LOG (DEBUG ) << " Located debug info for " << the_modname << " by path in " << *file_name;
79+ const char * the_filename = (file_name == nullptr || *file_name == nullptr ) ? " ???" : *file_name;
80+ LOG (DEBUG ) << " Located debug info for " << the_modname << " by path in " << the_filename;
3881 }
3982 return ret;
4083}
@@ -285,6 +328,11 @@ ProcessAnalyzer::ProcessAnalyzer(pid_t pid)
285328 throw ElfAnalyzerError (" Failed to analyze DWARF information for the remote process" );
286329 }
287330
331+ // The find_elf callback needs the PID to retry module paths through /proc/<pid>/root.
332+ if (dwfl_getmodules (d_dwfl.get (), set_module_process_pid_userdata, &d_pid, 0 ) == -1 ) {
333+ throw ElfAnalyzerError (" Failed to associate DWARF modules with the remote process" );
334+ }
335+
288336 if (dwfl_linux_proc_attach (d_dwfl.get (), pid, true ) != 0 ) {
289337 throw ElfAnalyzerError (" Could not attach the DWARF process analyzer" );
290338 }
0 commit comments