1/* Test program for libdwfl basic module tracking, relocation. 2 Copyright (C) 2005, 2007 Red Hat, Inc. 3 This file is part of elfutils. 4 5 This file is free software; you can redistribute it and/or modify 6 it under the terms of the GNU General Public License as published by 7 the Free Software Foundation; either version 3 of the License, or 8 (at your option) any later version. 9 10 elfutils is distributed in the hope that it will be useful, but 11 WITHOUT ANY WARRANTY; without even the implied warranty of 12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 GNU General Public License for more details. 14 15 You should have received a copy of the GNU General Public License 16 along with this program. If not, see <http://www.gnu.org/licenses/>. */ 17 18#include <config.h> 19#include <assert.h> 20#include <inttypes.h> 21#include <sys/types.h> 22#include <stdio.h> 23#include <stdio_ext.h> 24#include <stdlib.h> 25#include <string.h> 26#include <error.h> 27#include <locale.h> 28#include <argp.h> 29#include ELFUTILS_HEADER(dwfl) 30#include <dwarf.h> 31 32static bool show_inlines; 33 34struct info 35{ 36 Dwarf_Die *cudie; 37 Dwarf_Addr dwbias; 38}; 39 40static int 41print_instance (Dwarf_Die *instance, void *arg) 42{ 43 const struct info *info = arg; 44 45 printf (" inlined"); 46 47 Dwarf_Files *files; 48 if (dwarf_getsrcfiles (info->cudie, &files, NULL) == 0) 49 { 50 Dwarf_Attribute attr_mem; 51 Dwarf_Word val; 52 if (dwarf_formudata (dwarf_attr (instance, DW_AT_call_file, 53 &attr_mem), &val) == 0) 54 { 55 const char *file = dwarf_filesrc (files, val, NULL, NULL); 56 int lineno = 0, colno = 0; 57 if (dwarf_formudata (dwarf_attr (instance, DW_AT_call_line, 58 &attr_mem), &val) == 0) 59 lineno = val; 60 if (dwarf_formudata (dwarf_attr (instance, DW_AT_call_column, 61 &attr_mem), &val) == 0) 62 colno = val; 63 if (lineno == 0) 64 { 65 if (file != NULL) 66 printf (" from %s", file); 67 } 68 else if (colno == 0) 69 printf (" at %s:%u", file, lineno); 70 else 71 printf (" at %s:%u:%u", file, lineno, colno); 72 } 73 } 74 75 Dwarf_Addr lo = -1, hi = -1, entry = -1; 76 if (dwarf_lowpc (instance, &lo) == 0) 77 lo += info->dwbias; 78 else 79 printf (" (lowpc => %s)", dwarf_errmsg (-1)); 80 if (dwarf_highpc (instance, &hi) == 0) 81 hi += info->dwbias; 82 else 83 printf (" (highpc => %s)", dwarf_errmsg (-1)); 84 85 Dwarf_Attribute attr_mem; 86 Dwarf_Attribute *attr = dwarf_attr (instance, DW_AT_entry_pc, &attr_mem); 87 if (attr != NULL) 88 { 89 if (dwarf_formaddr (attr, &entry) == 0) 90 entry += info->dwbias; 91 else 92 printf (" (entrypc => %s)", dwarf_errmsg (-1)); 93 } 94 95 if (lo != (Dwarf_Addr) -1 || hi != (Dwarf_Addr) -1) 96 printf (" %#" PRIx64 "..%#" PRIx64, lo, hi); 97 if (entry != (Dwarf_Addr) -1) 98 printf (" => %#" PRIx64 "\n", entry); 99 else 100 puts (""); 101 102 return DWARF_CB_OK; 103} 104 105static void 106print_inline (Dwarf_Die *func, void *arg) 107{ 108 if (dwarf_func_inline_instances (func, &print_instance, arg) != 0) 109 printf (" error finding instances: %s\n", dwarf_errmsg (-1)); 110} 111 112static int 113print_func (Dwarf_Die *func, void *arg) 114{ 115 const struct info *info = arg; 116 117 const char *file = dwarf_decl_file (func); 118 int line = -1; 119 dwarf_decl_line (func, &line); 120 const char *fct = dwarf_diename (func); 121 122 printf (" %s:%d: %s:", file, line, fct); 123 124 if (dwarf_func_inline (func)) 125 { 126 puts (" inline function"); 127 if (show_inlines) 128 print_inline (func, arg); 129 } 130 else 131 { 132 Dwarf_Addr lo = -1, hi = -1, entry = -1; 133 if (dwarf_lowpc (func, &lo) == 0) 134 lo += info->dwbias; 135 else 136 printf (" (lowpc => %s)", dwarf_errmsg (-1)); 137 if (dwarf_highpc (func, &hi) == 0) 138 hi += info->dwbias; 139 else 140 printf (" (highpc => %s)", dwarf_errmsg (-1)); 141 if (dwarf_entrypc (func, &entry) == 0) 142 entry += info->dwbias; 143 else 144 printf (" (entrypc => %s)", dwarf_errmsg (-1)); 145 146 if (lo != (Dwarf_Addr) -1 || hi != (Dwarf_Addr) -1 147 || entry != (Dwarf_Addr) -1) 148 printf (" %#" PRIx64 "..%#" PRIx64 " => %#" PRIx64 "\n", 149 lo, hi, entry); 150 else 151 puts (""); 152 } 153 154 return DWARF_CB_OK; 155} 156 157static int 158list_module (Dwfl_Module *mod __attribute__ ((unused)), 159 void **userdata __attribute__ ((unused)), 160 const char *name, Dwarf_Addr base, 161 void *arg __attribute__ ((unused))) 162{ 163 Dwarf_Addr start; 164 Dwarf_Addr end; 165 const char *file; 166 const char *debug; 167 if (dwfl_module_info (mod, NULL, &start, &end, 168 NULL, NULL, &file, &debug) != name 169 || start != base) 170 abort (); 171 printf ("module: %30s %08" PRIx64 "..%08" PRIx64 " %s %s\n", 172 name, start, end, file, debug); 173 return DWARF_CB_OK; 174} 175 176static int 177print_module (Dwfl_Module *mod __attribute__ ((unused)), 178 void **userdata __attribute__ ((unused)), 179 const char *name, Dwarf_Addr base, 180 Dwarf *dw, Dwarf_Addr bias, 181 void *arg) 182{ 183 printf ("module: %30s %08" PRIx64 " %s %" PRIx64 " (%s)\n", 184 name, base, dw == NULL ? "no" : "DWARF", bias, dwfl_errmsg (-1)); 185 186 if (dw != NULL && *(const bool *) arg) 187 { 188 Dwarf_Off off = 0; 189 size_t cuhl; 190 Dwarf_Off noff; 191 192 while (dwarf_nextcu (dw, off, &noff, &cuhl, NULL, NULL, NULL) == 0) 193 { 194 Dwarf_Die die_mem; 195 struct info info = { dwarf_offdie (dw, off + cuhl, &die_mem), bias }; 196 (void) dwarf_getfuncs (info.cudie, print_func, &info, 0); 197 198 off = noff; 199 } 200 } 201 202 return DWARF_CB_OK; 203} 204 205static bool show_functions; 206 207/* gettext helper macro. */ 208#undef N_ 209#define N_(Str) Str 210 211static const struct argp_option options[] = 212 { 213 { "functions", 'f', NULL, 0, N_("Additionally show function names"), 0 }, 214 { "inlines", 'i', NULL, 0, N_("Show instances of inlined functions"), 0 }, 215 { NULL, 0, NULL, 0, NULL, 0 } 216 }; 217 218static error_t 219parse_opt (int key, char *arg __attribute__ ((unused)), 220 struct argp_state *state __attribute__ ((unused))) 221{ 222 switch (key) 223 { 224 case ARGP_KEY_INIT: 225 state->child_inputs[0] = state->input; 226 break; 227 228 case 'f': 229 show_functions = true; 230 break; 231 232 case 'i': 233 show_inlines = show_functions = true; 234 break; 235 236 default: 237 return ARGP_ERR_UNKNOWN; 238 } 239 return 0; 240} 241 242int 243main (int argc, char **argv) 244{ 245 /* We use no threads here which can interfere with handling a stream. */ 246 (void) __fsetlocking (stdout, FSETLOCKING_BYCALLER); 247 248 /* Set locale. */ 249 (void) setlocale (LC_ALL, ""); 250 251 Dwfl *dwfl = NULL; 252 const struct argp_child argp_children[] = 253 { 254 { .argp = dwfl_standard_argp () }, 255 { .argp = NULL } 256 }; 257 const struct argp argp = 258 { 259 options, parse_opt, NULL, NULL, argp_children, NULL, NULL 260 }; 261 (void) argp_parse (&argp, argc, argv, 0, NULL, &dwfl); 262 assert (dwfl != NULL); 263 264 ptrdiff_t p = 0; 265 do 266 p = dwfl_getmodules (dwfl, &list_module, NULL, p); 267 while (p > 0); 268 if (p < 0) 269 error (2, 0, "dwfl_getmodules: %s", dwfl_errmsg (-1)); 270 271 do 272 p = dwfl_getdwarf (dwfl, &print_module, &show_functions, p); 273 while (p > 0); 274 if (p < 0) 275 error (2, 0, "dwfl_getdwarf: %s", dwfl_errmsg (-1)); 276 277 p = 0; 278 do 279 p = dwfl_getmodules (dwfl, &list_module, NULL, p); 280 while (p > 0); 281 if (p < 0) 282 error (2, 0, "dwfl_getmodules: %s", dwfl_errmsg (-1)); 283 284 dwfl_end (dwfl); 285 286 return 0; 287} 288