Created
April 8, 2023 11:18
-
-
Save bernhardkaindl/7ea7ebfff29b4a4526ae58fef56ddf7f to your computer and use it in GitHub Desktop.
dwflmodtest.c Modifiled to use dwfl_report_elf() to get debug info for other elf files
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* Test program for libdwfl basic module tracking, relocation. | |
Copyright (C) 2005, 2007 Red Hat, Inc. | |
This file is part of elfutils. | |
This file is free software; you can redistribute it and/or modify | |
it under the terms of the GNU General Public License as published by | |
the Free Software Foundation; either version 3 of the License, or | |
(at your option) any later version. | |
elfutils is distributed in the hope that it will be useful, but | |
WITHOUT ANY WARRANTY; without even the implied warranty of | |
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
GNU General Public License for more details. | |
You should have received a copy of the GNU General Public License | |
along with this program. If not, see <http://www.gnu.org/licenses/>. */ | |
//#include <config.h> | |
#include <assert.h> | |
#include <inttypes.h> | |
#include <sys/types.h> | |
#include <stdio.h> | |
#include <stdio_ext.h> | |
#include <stdlib.h> | |
#include <string.h> | |
#include <locale.h> | |
#include <argp.h> | |
#include <fcntl.h> | |
#include <dwarf.h> | |
#include <elfutils/libdwfl.h> | |
#define error printf | |
static bool show_inlines; | |
struct info | |
{ | |
Dwarf_Die *cudie; | |
Dwarf_Addr dwbias; | |
}; | |
static int | |
print_instance (Dwarf_Die *instance, void *arg) | |
{ | |
const struct info *info = arg; | |
printf (" inlined"); | |
Dwarf_Files *files; | |
if (dwarf_getsrcfiles (info->cudie, &files, NULL) == 0) | |
{ | |
Dwarf_Attribute attr_mem; | |
Dwarf_Word val; | |
if (dwarf_formudata (dwarf_attr (instance, DW_AT_call_file, | |
&attr_mem), &val) == 0) | |
{ | |
const char *file = dwarf_filesrc (files, val, NULL, NULL); | |
int lineno = 0, colno = 0; | |
if (dwarf_formudata (dwarf_attr (instance, DW_AT_call_line, | |
&attr_mem), &val) == 0) | |
lineno = val; | |
if (dwarf_formudata (dwarf_attr (instance, DW_AT_call_column, | |
&attr_mem), &val) == 0) | |
colno = val; | |
if (lineno == 0) | |
{ | |
if (file != NULL) | |
printf (" from %s", file); | |
} | |
else if (colno == 0) | |
printf (" at %s:%u", file, lineno); | |
else | |
printf (" at %s:%u:%u", file, lineno, colno); | |
} | |
} | |
Dwarf_Addr lo = -1, hi = -1, entry = -1; | |
if (dwarf_lowpc (instance, &lo) == 0) | |
lo += info->dwbias; | |
else | |
printf (" (lowpc => %s)", dwarf_errmsg (-1)); | |
if (dwarf_highpc (instance, &hi) == 0) | |
hi += info->dwbias; | |
else | |
printf (" (highpc => %s)", dwarf_errmsg (-1)); | |
Dwarf_Attribute attr_mem; | |
Dwarf_Attribute *attr = dwarf_attr (instance, DW_AT_entry_pc, &attr_mem); | |
if (attr != NULL) | |
{ | |
if (dwarf_formaddr (attr, &entry) == 0) | |
entry += info->dwbias; | |
else | |
printf (" (entrypc => %s)", dwarf_errmsg (-1)); | |
} | |
if (lo != (Dwarf_Addr) -1 || hi != (Dwarf_Addr) -1) | |
printf (" %#" PRIx64 "..%#" PRIx64, lo, hi); | |
if (entry != (Dwarf_Addr) -1) | |
printf (" => %#" PRIx64 "\n", entry); | |
else | |
puts (""); | |
return DWARF_CB_OK; | |
} | |
static void | |
print_inline (Dwarf_Die *func, void *arg) | |
{ | |
if (dwarf_func_inline_instances (func, &print_instance, arg) != 0) | |
printf (" error finding instances: %s\n", dwarf_errmsg (-1)); | |
} | |
static int | |
print_func (Dwarf_Die *func, void *arg) | |
{ | |
const struct info *info = arg; | |
const char *file = dwarf_decl_file (func); | |
int line = -1; | |
dwarf_decl_line (func, &line); | |
const char *fct = dwarf_diename (func); | |
printf (" %s:%d: %s:", file, line, fct); | |
if (dwarf_func_inline (func)) | |
{ | |
puts (" inline function"); | |
if (show_inlines) | |
print_inline (func, arg); | |
} | |
else | |
{ | |
Dwarf_Addr lo = -1, hi = -1, entry = -1; | |
if (dwarf_lowpc (func, &lo) == 0) | |
lo += info->dwbias; | |
else | |
printf (" (lowpc => %s)", dwarf_errmsg (-1)); | |
if (dwarf_highpc (func, &hi) == 0) | |
hi += info->dwbias; | |
else | |
printf (" (highpc => %s)", dwarf_errmsg (-1)); | |
if (dwarf_entrypc (func, &entry) == 0) | |
entry += info->dwbias; | |
else | |
printf (" (entrypc => %s)", dwarf_errmsg (-1)); | |
if (lo != (Dwarf_Addr) -1 || hi != (Dwarf_Addr) -1 | |
|| entry != (Dwarf_Addr) -1) | |
printf (" %#" PRIx64 "..%#" PRIx64 " => %#" PRIx64 "\n", | |
lo, hi, entry); | |
else | |
puts (""); | |
} | |
return DWARF_CB_OK; | |
} | |
static int | |
list_module (Dwfl_Module *mod __attribute__ ((unused)), | |
void **userdata __attribute__ ((unused)), | |
const char *name, Dwarf_Addr base, | |
void *arg __attribute__ ((unused))) | |
{ | |
Dwarf_Addr start; | |
Dwarf_Addr end; | |
const char *file; | |
const char *debug; | |
if (dwfl_module_info (mod, NULL, &start, &end, | |
NULL, NULL, &file, &debug) != name | |
|| start != base) | |
abort (); | |
printf ("module: %30s %08" PRIx64 "..%08" PRIx64 " %s %s\n", | |
name, start, end, file, debug); | |
return DWARF_CB_OK; | |
} | |
static int | |
print_module (Dwfl_Module *mod __attribute__ ((unused)), | |
void **userdata __attribute__ ((unused)), | |
const char *name, Dwarf_Addr base, | |
Dwarf *dw, Dwarf_Addr bias, | |
void *arg) | |
{ | |
printf ("module: %30s %08" PRIx64 " %s %" PRIx64 " (%s)\n", | |
name, base, dw == NULL ? "no" : "DWARF", bias, dwfl_errmsg (-1)); | |
if (dw != NULL && *(const bool *) arg) | |
{ | |
Dwarf_Off off = 0; | |
size_t cuhl; | |
Dwarf_Off noff; | |
while (dwarf_nextcu (dw, off, &noff, &cuhl, NULL, NULL, NULL) == 0) | |
{ | |
Dwarf_Die die_mem; | |
struct info info = { dwarf_offdie (dw, off + cuhl, &die_mem), bias }; | |
(void) dwarf_getfuncs (info.cudie, print_func, &info, 0); | |
off = noff; | |
} | |
} | |
return DWARF_CB_OK; | |
} | |
static bool show_functions; | |
/* gettext helper macro. */ | |
#undef N_ | |
#define N_(Str) Str | |
static const struct argp_option options[] = | |
{ | |
{ "functions", 'f', NULL, 0, N_("Additionally show function names"), 0 }, | |
{ "inlines", 'i', NULL, 0, N_("Show instances of inlined functions"), 0 }, | |
{ NULL, 0, NULL, 0, NULL, 0 } | |
}; | |
static error_t | |
parse_opt (int key, char *arg __attribute__ ((unused)), | |
struct argp_state *state __attribute__ ((unused))) | |
{ | |
switch (key) | |
{ | |
case ARGP_KEY_INIT: | |
state->child_inputs[0] = state->input; | |
break; | |
case 'f': | |
show_functions = true; | |
break; | |
case 'i': | |
show_inlines = show_functions = true; | |
break; | |
default: | |
return ARGP_ERR_UNKNOWN; | |
} | |
return 0; | |
} | |
char *debuginfo_path = ".:/usr/lib/debuginfo"; | |
Dwfl_Callbacks callbacks = { | |
.find_elf = dwfl_linux_proc_find_elf, | |
.find_debuginfo = dwfl_standard_find_debuginfo, | |
.debuginfo_path = &debuginfo_path, | |
}; | |
int | |
main (int argc, char **argv) | |
{ | |
/* We use no threads here which can interfere with handling a stream. */ | |
(void) __fsetlocking (stdout, FSETLOCKING_BYCALLER); | |
/* Set locale. */ | |
(void) setlocale (LC_ALL, ""); | |
Dwfl *dwfl = NULL; | |
const struct argp_child argp_children[] = | |
{ | |
{ .argp = dwfl_standard_argp () }, | |
{ .argp = NULL } | |
}; | |
const struct argp argp = | |
{ | |
options, parse_opt, NULL, NULL, argp_children, NULL, NULL | |
}; | |
(void) argp_parse (&argp, argc, argv, 0, NULL, &dwfl); | |
dwfl = dwfl_begin(&callbacks); | |
// const char*filename = "a.out"; | |
const char*filename = "/usr/bin/pwd"; | |
int fd = open(filename, O_RDONLY); | |
if (fd < 0) { | |
printf("cannot open debug info for %s: %m\n", filename); | |
return -1; | |
} | |
dwfl_report_elf(dwfl, filename, filename, fd, 0, true); | |
dwfl_report_end(dwfl, NULL, NULL); | |
//assert((dwmodule = dwfl_report_offline(dwfl, "", "stack-trace", -1))); | |
assert (dwfl != NULL); | |
ptrdiff_t p = 0; | |
do | |
p = dwfl_getmodules (dwfl, &list_module, NULL, p); | |
while (p > 0); | |
if (p < 0) | |
error ("dwfl_getmodules: %s", dwfl_errmsg (-1)); | |
do | |
p = dwfl_getdwarf (dwfl, &print_module, &show_functions, p); | |
while (p > 0); | |
if (p < 0) | |
error ("dwfl_getdwarf: %s", dwfl_errmsg (-1)); | |
p = 0; | |
do | |
p = dwfl_getmodules (dwfl, &list_module, NULL, p); | |
while (p > 0); | |
if (p < 0) | |
error ("dwfl_getmodules: %s", dwfl_errmsg (-1)); | |
dwfl_end (dwfl); | |
return 0; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment