1 /* Test program for dwarf_getscopes. 2 Copyright (C) 2005 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 ELFUTILS_HEADER(dwfl) 30 #include <dwarf.h> 31 #include <argp.h> 32 #include <stdio.h> 33 #include <stdio_ext.h> 34 #include <locale.h> 35 #include <stdlib.h> 36 #include <error.h> 37 #include <string.h> 38 39 40 static void 41 paddr (const char *prefix, Dwarf_Addr addr, Dwfl_Line *line) 42 { 43 const char *src; 44 int lineno, linecol; 45 if (line != NULL 46 && (src = dwfl_lineinfo (line, &addr, &lineno, &linecol, 47 NULL, NULL)) != NULL) 48 { 49 if (linecol != 0) 50 printf ("%s%#" PRIx64 " (%s:%d:%d)", 51 prefix, addr, src, lineno, linecol); 52 else 53 printf ("%s%#" PRIx64 " (%s:%d)", 54 prefix, addr, src, lineno); 55 } 56 else 57 printf ("%s%#" PRIx64, prefix, addr); 58 } 59 60 static void 61 print_vars (unsigned int indent, Dwarf_Die *die) 62 { 63 Dwarf_Die child; 64 if (dwarf_child (die, &child) == 0) 65 do 66 switch (dwarf_tag (&child)) 67 { 68 case DW_TAG_variable: 69 case DW_TAG_formal_parameter: 70 printf ("%*s%-30s[%6" PRIx64 "]\n", indent, "", 71 dwarf_diename (&child), 72 (uint64_t) dwarf_dieoffset (&child)); 73 break; 74 default: 75 break; 76 } 77 while (dwarf_siblingof (&child, &child) == 0); 78 79 Dwarf_Attribute attr_mem; 80 Dwarf_Die origin; 81 if (dwarf_hasattr (die, DW_AT_abstract_origin) 82 && dwarf_formref_die (dwarf_attr (die, DW_AT_abstract_origin, &attr_mem), 83 &origin) != NULL 84 && dwarf_child (&origin, &child) == 0) 85 do 86 switch (dwarf_tag (&child)) 87 { 88 case DW_TAG_variable: 89 case DW_TAG_formal_parameter: 90 printf ("%*s%s (abstract)\n", indent, "", 91 dwarf_diename (&child)); 92 break; 93 default: 94 break; 95 } 96 while (dwarf_siblingof (&child, &child) == 0); 97 } 98 99 100 #define INDENT 4 101 102 static void 103 handle_address (GElf_Addr pc, Dwfl *dwfl) 104 { 105 Dwarf_Addr cubias; 106 Dwarf_Die *cudie = dwfl_addrdie (dwfl, pc, &cubias); 107 if (cudie == NULL) 108 error (EXIT_FAILURE, 0, "dwfl_addrdie: %s", dwfl_errmsg (-1)); 109 110 Dwarf_Die *scopes; 111 int n = dwarf_getscopes (cudie, pc - cubias, &scopes); 112 if (n < 0) 113 error (EXIT_FAILURE, 0, "dwarf_getscopes: %s", dwarf_errmsg (-1)); 114 else if (n == 0) 115 printf ("%#" PRIx64 ": not in any scope\n", pc); 116 else 117 { 118 printf ("%#" PRIx64 ":\n", pc); 119 unsigned int indent = 0; 120 while (n-- > 0) 121 { 122 Dwarf_Die *const die = &scopes[n]; 123 124 indent += INDENT; 125 printf ("%*s%s (%#x)", indent, "", 126 dwarf_diename (die) ?: "<unnamed>", 127 dwarf_tag (die)); 128 129 Dwarf_Addr lowpc, highpc; 130 if (dwarf_lowpc (die, &lowpc) == 0 131 && dwarf_highpc (die, &highpc) == 0) 132 { 133 lowpc += cubias; 134 highpc += cubias; 135 Dwfl_Line *loline = dwfl_getsrc (dwfl, lowpc); 136 Dwfl_Line *hiline = dwfl_getsrc (dwfl, highpc); 137 paddr (": ", lowpc, loline); 138 if (highpc != lowpc) 139 paddr (" .. ", lowpc, hiline == loline ? NULL : hiline); 140 } 141 puts (""); 142 143 print_vars (indent + INDENT, die); 144 } 145 } 146 } 147 148 int 149 main (int argc, char *argv[]) 150 { 151 int remaining; 152 153 /* Set locale. */ 154 (void) setlocale (LC_ALL, ""); 155 156 Dwfl *dwfl = NULL; 157 (void) argp_parse (dwfl_standard_argp (), argc, argv, 0, &remaining, &dwfl); 158 assert (dwfl != NULL); 159 160 int result = 0; 161 162 /* Now handle the addresses. In case none are given on the command 163 line, read from stdin. */ 164 if (remaining == argc) 165 { 166 /* We use no threads here which can interfere with handling a stream. */ 167 (void) __fsetlocking (stdin, FSETLOCKING_BYCALLER); 168 169 char *buf = NULL; 170 size_t len = 0; 171 while (!feof_unlocked (stdin)) 172 { 173 if (getline (&buf, &len, stdin) < 0) 174 break; 175 176 char *endp; 177 uintmax_t addr = strtoumax (buf, &endp, 0); 178 if (endp != buf) 179 handle_address (addr, dwfl); 180 else 181 result = 1; 182 } 183 184 free (buf); 185 } 186 else 187 { 188 do 189 { 190 char *endp; 191 uintmax_t addr = strtoumax (argv[remaining], &endp, 0); 192 if (endp != argv[remaining]) 193 handle_address (addr, dwfl); 194 else 195 result = 1; 196 } 197 while (++remaining < argc); 198 } 199 200 dwfl_end (dwfl); 201 202 return result; 203 } 204