// gcc -Wall -o dwfl_find_kernel -ldw dwfl_find_kernel.c #include #include #include #include #include #include #include static char *kernel_file = NULL; static int setup_report_kernel (const char* modname, const char* filename) { printf ("setup report modname: %s, filename: %s\n", modname, filename); /* We are only interested in the kernel. */ if (modname != NULL && strcmp (modname, "kernel") == 0) { /* We will get a null filename for modname == "kernel" if the kernel couldn't be found. We still want to stop, not interested in any modules being found. */ if (filename == NULL) return -1; /* Copy the kernel file name and tell dwfl we want this module. */ kernel_file = strdup (filename); return 1; } /* Once we have seen the kernel we don't need any more modules. We are not interested in any kernel modules. */ if (kernel_file != NULL) return -1; /* We don't need this module. But we haven't seen the kernel yet, continue. */ return 0; } static char *kernel_dwarf_file = NULL; static int getdwarf_kernel (Dwfl_Module *mod, void **userdata, const char *name, Dwarf_Addr base, Dwarf *dw, Dwarf_Addr bias, void *arg) { printf ("getdwarf name: %s\n", name); if (name != NULL && strcmp (name, "kernel") == 0) { if (dw == NULL) { printf ("kernel without DWARF\n"); return DWARF_CB_ABORT; } const char *mainfile, *debugfile; dwfl_module_info (mod, NULL, NULL, NULL, NULL, NULL, &mainfile, &debugfile); printf ("mainfile: %s, debugfile: %s\n", mainfile, debugfile); if (debugfile != NULL) kernel_dwarf_file = strdup (debugfile); else kernel_dwarf_file = strdup (mainfile); } return DWARF_CB_OK; } int main (int argc, char **argv) { char *release; if (argc > 1) release = argv[1]; else { struct utsname uts; if (uname (&uts) != 0) { perror ("uname failed"); return -1; } release = uts.release; } char *debuginfo_path; if (argc > 2) debuginfo_path = argv[2]; else debuginfo_path = "+:.debug:/usr/lib/debug"; printf ("Finding kernel release: %s\n", release); printf ("Debuginfo path: %s\n", debuginfo_path); Dwfl_Callbacks kernel_callbacks = { dwfl_linux_kernel_find_elf, dwfl_standard_find_debuginfo, dwfl_offline_section_address, (char **) & debuginfo_path }; Dwfl *dwfl = dwfl_begin (&kernel_callbacks); if (dwfl == NULL) { printf ("dwfl_begin: %s\n", dwfl_errmsg (-1)); return -1; } dwfl_report_begin (dwfl); dwfl_linux_kernel_report_offline (dwfl, release, &setup_report_kernel); dwfl_report_end(dwfl, NULL, NULL); if (kernel_file == NULL) { printf ("Couldn't find kernel\n"); return -1; } printf ("Found kernel file: %s\n", kernel_file); ptrdiff_t p = 0; do p = dwfl_getdwarf (dwfl, &getdwarf_kernel, NULL, p); while (p > 0); if (kernel_dwarf_file == NULL) { printf ("Couldn't get kernel DWARF\n"); return -1; } printf ("Found kernel DWARF file: %s\n", kernel_dwarf_file); dwfl_end (dwfl); free (kernel_file); free (kernel_dwarf_file); return 0; }