1 /* Copyright (C) 2005 Red Hat, Inc. 2 This file is part of elfutils. 3 4 This file is free software; you can redistribute it and/or modify 5 it under the terms of the GNU General Public License as published by 6 the Free Software Foundation; either version 3 of the License, or 7 (at your option) any later version. 8 9 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 12 GNU General Public License for more details. 13 14 You should have received a copy of the GNU General Public License 15 along with this program. If not, see <http://www.gnu.org/licenses/>. */ 16 17 #ifdef HAVE_CONFIG_H 18 # include <config.h> 19 #endif 20 21 #include <inttypes.h> 22 #include <assert.h> 23 #include ELFUTILS_HEADER(dwfl) 24 #include <argp.h> 25 #include <stdio.h> 26 #include <locale.h> 27 #include <stdlib.h> 28 #include <string.h> 29 #include "system.h" 30 31 32 static void 33 print_address (Dwfl_Module *mod, Dwarf_Addr address) 34 { 35 int n = dwfl_module_relocations (mod); 36 if (n < 0) 37 error (0, 0, "dwfl_module_relocations: %s", dwfl_errmsg (-1)); 38 else if (n > 0) 39 { 40 int i = dwfl_module_relocate_address (mod, &address); 41 if (i < 0) 42 error (0, 0, "dwfl_module_relocate_address: %s", dwfl_errmsg (-1)); 43 else 44 { 45 const char *modname = dwfl_module_info (mod, NULL, NULL, NULL, 46 NULL, NULL, NULL, NULL); 47 const char *secname = dwfl_module_relocation_info (mod, i, NULL); 48 if (n > 1 || secname[0] != '\0') 49 printf ("%s(%s)+%#" PRIx64, modname, secname, address); 50 else 51 printf ("%s+%#" PRIx64, modname, address); 52 return; 53 } 54 } 55 56 printf ("%#" PRIx64, address); 57 } 58 59 60 struct args 61 { 62 const char *arg; 63 char *file; 64 int line; 65 }; 66 67 static int 68 handle_module (Dwfl_Module *mod __attribute__ ((unused)), 69 void **udata __attribute__ ((unused)), 70 const char *modname, Dwarf_Addr base __attribute__ ((unused)), 71 Dwarf *dbg __attribute__ ((unused)), 72 Dwarf_Addr bias __attribute__ ((unused)), void *arg) 73 { 74 const struct args *const a = arg; 75 76 Dwfl_Line **lines = NULL; 77 size_t nlines = 0; 78 79 if (dwfl_module_getsrc_file (mod, a->file, a->line, 0, &lines, &nlines) == 0) 80 { 81 for (size_t inner = 0; inner < nlines; ++inner) 82 { 83 Dwarf_Addr addr; 84 int line = a->line, col = 0; 85 const char *file = dwfl_lineinfo (lines[inner], &addr, &line, &col, 86 NULL, NULL); 87 if (file != NULL) 88 { 89 printf ("%s -> ", a->arg); 90 print_address (mod, addr); 91 if (modname[0] != '\0') 92 printf (" (%s:", modname); 93 if (strcmp (file, a->file) || line != a->line || col != 0) 94 printf (" %s%s:%d", modname[0] != '\0' ? "" : "(", 95 file, line); 96 if (col != 0) 97 printf (":%d", col); 98 if (modname[0] != '\0' 99 || strcmp (file, a->file) || line != a->line || col != 0) 100 puts (")"); 101 else 102 puts (""); 103 } 104 } 105 free (lines); 106 } 107 108 return DWARF_CB_OK; 109 } 110 111 int 112 main (int argc, char *argv[]) 113 { 114 int cnt; 115 116 /* Set locale. */ 117 (void) setlocale (LC_ALL, ""); 118 119 Dwfl *dwfl = NULL; 120 (void) argp_parse (dwfl_standard_argp (), argc, argv, 0, &cnt, &dwfl); 121 assert (dwfl != NULL); 122 123 for (; cnt < argc; ++cnt) 124 { 125 struct args a = { .arg = argv[cnt] }; 126 127 switch (sscanf (a.arg, "%m[^:]:%d", &a.file, &a.line)) 128 { 129 default: 130 case 0: 131 printf ("ignored %s\n", argv[cnt]); 132 continue; 133 case 1: 134 a.line = 0; 135 break; 136 case 2: 137 break; 138 } 139 140 (void) dwfl_getdwarf (dwfl, &handle_module, &a, 0); 141 142 free (a.file); 143 } 144 145 dwfl_end (dwfl); 146 147 return 0; 148 } 149