blob: 3394cd29fe4148812d265a100c3e96b4afbf2b32 [file] [log] [blame]
Roland McGrath9a1f3652005-08-18 20:57:04 +00001/* Test program for dwarf_getscopes.
2 Copyright (C) 2005 Red Hat, Inc.
Ulrich Drepper361df7d2006-04-04 21:38:57 +00003 This file is part of Red Hat elfutils.
Roland McGrath9a1f3652005-08-18 20:57:04 +00004
Ulrich Drepper361df7d2006-04-04 21:38:57 +00005 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.
Roland McGrath9a1f3652005-08-18 20:57:04 +00008
Ulrich Drepper361df7d2006-04-04 21:38:57 +00009 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,
Ulrich Drepper1e9ef502006-04-04 22:29:06 +000016 Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301 USA.
Ulrich Drepper361df7d2006-04-04 21:38:57 +000017
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>. */
Roland McGrath9a1f3652005-08-18 20:57:04 +000025
26#include <config.h>
27#include <assert.h>
28#include <inttypes.h>
Roland McGrathd7f8d0c2005-11-17 02:32:03 +000029#include ELFUTILS_HEADER(dwfl)
Roland McGrath9a1f3652005-08-18 20:57:04 +000030#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
40static void
41paddr (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
Roland McGrath9a1f3652005-08-18 20:57:04 +000060static void
61print_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, "",
Roland McGrath71e15a02005-08-27 10:33:26 +000071 dwarf_diename (&child),
Roland McGrath9a1f3652005-08-18 20:57:04 +000072 (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, "",
Roland McGrath71e15a02005-08-27 10:33:26 +000091 dwarf_diename (&child));
Roland McGrath9a1f3652005-08-18 20:57:04 +000092 break;
93 default:
94 break;
95 }
96 while (dwarf_siblingof (&child, &child) == 0);
97}
98
99
100#define INDENT 4
101
102static void
103handle_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, "",
Roland McGrath71e15a02005-08-27 10:33:26 +0000126 dwarf_diename (die) ?: "<unnamed>",
Roland McGrath9a1f3652005-08-18 20:57:04 +0000127 dwarf_tag (die));
128
129 Dwarf_Addr lowpc, highpc;
130 if (dwarf_lowpc (die, &lowpc) == 0
131 && dwarf_highpc (die, &highpc) == 0)
132 {
Roland McGrathb0bc2782005-08-27 21:07:16 +0000133 lowpc += cubias;
134 highpc += cubias;
Roland McGrath9a1f3652005-08-18 20:57:04 +0000135 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
148int
149main (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
Roland McGrath994b4892005-12-05 22:46:21 +0000200 dwfl_end (dwfl);
201
Roland McGrath9a1f3652005-08-18 20:57:04 +0000202 return result;
203}