Skip to content

Commit 83d5ba2

Browse files
committed
Resolve container native library lookup
- Retry failed libdwfl module opens through /proc/<pid>/root for container-private absolute paths. - Store target PID in DWFL module userdata so find_elf can build the process-root path. - Preserve build-id and normal host path lookup before falling back to the target process root. Signed-off-by: Pramod Kumbhar <prkumbhar@nvidia.com>
1 parent 1edfe2b commit 83d5ba2

1 file changed

Lines changed: 50 additions & 2 deletions

File tree

src/pystack/_pystack/elf_common.cpp

Lines changed: 50 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,45 @@ namespace pystack {
1414

1515
using 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+
1756
int
1857
pystack_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

Comments
 (0)