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