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