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 <locale.h> 27#include <argp.h> 28#include ELFUTILS_HEADER(dwfl) 29#include <dwarf.h> 30#include "system.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 207static const struct argp_option options[] = 208 { 209 { "functions", 'f', NULL, 0, N_("Additionally show function names"), 0 }, 210 { "inlines", 'i', NULL, 0, N_("Show instances of inlined functions"), 0 }, 211 { NULL, 0, NULL, 0, NULL, 0 } 212 }; 213 214static error_t 215parse_opt (int key, char *arg __attribute__ ((unused)), 216 struct argp_state *state __attribute__ ((unused))) 217{ 218 switch (key) 219 { 220 case ARGP_KEY_INIT: 221 state->child_inputs[0] = state->input; 222 break; 223 224 case 'f': 225 show_functions = true; 226 break; 227 228 case 'i': 229 show_inlines = show_functions = true; 230 break; 231 232 default: 233 return ARGP_ERR_UNKNOWN; 234 } 235 return 0; 236} 237 238int 239main (int argc, char **argv) 240{ 241 /* We use no threads here which can interfere with handling a stream. */ 242 (void) __fsetlocking (stdout, FSETLOCKING_BYCALLER); 243 244 /* Set locale. */ 245 (void) setlocale (LC_ALL, ""); 246 247 Dwfl *dwfl = NULL; 248 const struct argp_child argp_children[] = 249 { 250 { .argp = dwfl_standard_argp () }, 251 { .argp = NULL } 252 }; 253 const struct argp argp = 254 { 255 options, parse_opt, NULL, NULL, argp_children, NULL, NULL 256 }; 257 (void) argp_parse (&argp, argc, argv, 0, NULL, &dwfl); 258 assert (dwfl != NULL); 259 260 ptrdiff_t p = 0; 261 do 262 p = dwfl_getmodules (dwfl, &list_module, NULL, p); 263 while (p > 0); 264 if (p < 0) 265 error (2, 0, "dwfl_getmodules: %s", dwfl_errmsg (-1)); 266 267 do 268 p = dwfl_getdwarf (dwfl, &print_module, &show_functions, p); 269 while (p > 0); 270 if (p < 0) 271 error (2, 0, "dwfl_getdwarf: %s", dwfl_errmsg (-1)); 272 273 p = 0; 274 do 275 p = dwfl_getmodules (dwfl, &list_module, NULL, p); 276 while (p > 0); 277 if (p < 0) 278 error (2, 0, "dwfl_getmodules: %s", dwfl_errmsg (-1)); 279 280 dwfl_end (dwfl); 281 282 return 0; 283} 284