1 /* Test program for dwarf_getscopes. 2 Copyright (C) 2005, 2014 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 ELFUTILS_HEADER(dwfl) 22 #include <dwarf.h> 23 #include <argp.h> 24 #include <stdio.h> 25 #include <stdio_ext.h> 26 #include <locale.h> 27 #include <stdlib.h> 28 #include <error.h> 29 #include <string.h> 30 #include <fnmatch.h> 31 32 33 static void 34 paddr (const char *prefix, Dwarf_Addr addr, Dwfl_Line *line) 35 { 36 const char *src; 37 int lineno, linecol; 38 if (line != NULL 39 && (src = dwfl_lineinfo (line, &addr, &lineno, &linecol, 40 NULL, NULL)) != NULL) 41 { 42 if (linecol != 0) 43 printf ("%s%#" PRIx64 " (%s:%d:%d)", 44 prefix, addr, src, lineno, linecol); 45 else 46 printf ("%s%#" PRIx64 " (%s:%d)", 47 prefix, addr, src, lineno); 48 } 49 else 50 printf ("%s%#" PRIx64, prefix, addr); 51 } 52 53 54 static void 55 print_vars (unsigned int indent, Dwarf_Die *die) 56 { 57 Dwarf_Die child; 58 if (dwarf_child (die, &child) == 0) 59 do 60 switch (dwarf_tag (&child)) 61 { 62 case DW_TAG_variable: 63 case DW_TAG_formal_parameter: 64 printf ("%*s%-30s[%6" PRIx64 "]\n", indent, "", 65 dwarf_diename (&child), 66 (uint64_t) dwarf_dieoffset (&child)); 67 break; 68 default: 69 break; 70 } 71 while (dwarf_siblingof (&child, &child) == 0); 72 73 Dwarf_Attribute attr_mem; 74 Dwarf_Die origin; 75 if (dwarf_hasattr (die, DW_AT_abstract_origin) 76 && dwarf_formref_die (dwarf_attr (die, DW_AT_abstract_origin, &attr_mem), 77 &origin) != NULL 78 && dwarf_child (&origin, &child) == 0) 79 do 80 switch (dwarf_tag (&child)) 81 { 82 case DW_TAG_variable: 83 case DW_TAG_formal_parameter: 84 printf ("%*s%s (abstract)\n", indent, "", 85 dwarf_diename (&child)); 86 break; 87 default: 88 break; 89 } 90 while (dwarf_siblingof (&child, &child) == 0); 91 } 92 93 94 #define INDENT 4 95 96 struct args 97 { 98 Dwfl *dwfl; 99 Dwarf_Die *cu; 100 Dwarf_Addr dwbias; 101 char **argv; 102 }; 103 104 static int 105 handle_function (Dwarf_Die *funcdie, void *arg) 106 { 107 struct args *a = arg; 108 109 const char *name = dwarf_diename (funcdie); 110 char **argv = a->argv; 111 if (argv[0] != NULL) 112 { 113 bool match; 114 do 115 match = fnmatch (*argv, name, 0) == 0; 116 while (!match && *++argv); 117 if (!match) 118 return 0; 119 } 120 121 Dwarf_Die *scopes; 122 int n = dwarf_getscopes_die (funcdie, &scopes); 123 if (n <= 0) 124 error (EXIT_FAILURE, 0, "dwarf_getscopes_die: %s", dwarf_errmsg (-1)); 125 else 126 { 127 Dwarf_Addr start, end; 128 const char *fname; 129 const char *modname = dwfl_module_info (dwfl_cumodule (a->cu), NULL, 130 &start, &end, 131 NULL, NULL, 132 &fname, NULL); 133 if (modname == NULL) 134 error (EXIT_FAILURE, 0, "dwfl_module_info: %s", dwarf_errmsg (-1)); 135 if (modname[0] == '\0') 136 modname = fname; 137 printf ("%s: %#" PRIx64 " .. %#" PRIx64 "\n", modname, start, end); 138 139 unsigned int indent = 0; 140 while (n-- > 0) 141 { 142 Dwarf_Die *const die = &scopes[n]; 143 144 indent += INDENT; 145 printf ("%*s%s (%#x)", indent, "", 146 dwarf_diename (die) ?: "<unnamed>", 147 dwarf_tag (die)); 148 149 Dwarf_Addr lowpc, highpc; 150 if (dwarf_lowpc (die, &lowpc) == 0 151 && dwarf_highpc (die, &highpc) == 0) 152 { 153 lowpc += a->dwbias; 154 highpc += a->dwbias; 155 Dwfl_Line *loline = dwfl_getsrc (a->dwfl, lowpc); 156 Dwfl_Line *hiline = dwfl_getsrc (a->dwfl, highpc - 1); 157 paddr (": ", lowpc, loline); 158 if (highpc != lowpc) 159 paddr (" .. ", highpc - 1, hiline == loline ? NULL : hiline); 160 } 161 puts (""); 162 163 print_vars (indent + INDENT, die); 164 } 165 free (scopes); 166 } 167 168 return 0; 169 } 170 171 172 int 173 main (int argc, char *argv[]) 174 { 175 int remaining; 176 177 /* Set locale. */ 178 (void) setlocale (LC_ALL, ""); 179 180 struct args a = { .dwfl = NULL, .cu = NULL }; 181 182 (void) argp_parse (dwfl_standard_argp (), argc, argv, 0, &remaining, 183 &a.dwfl); 184 assert (a.dwfl != NULL); 185 a.argv = &argv[remaining]; 186 187 int result = 0; 188 189 while ((a.cu = dwfl_nextcu (a.dwfl, a.cu, &a.dwbias)) != NULL) 190 dwarf_getfuncs (a.cu, &handle_function, &a, 0); 191 192 dwfl_end (a.dwfl); 193 194 return result; 195 } 196