1 /* Test program for dwarf_getmacros and related
2 Copyright (C) 2009, 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 ELFUTILS_HEADER(dw)
20 #include <dwarf.h>
21 #include <sys/types.h>
22 #include <sys/stat.h>
23 #include <fcntl.h>
24 #include <stdio.h>
25 #include <stdint.h>
26 #include <stdlib.h>
27 #include <assert.h>
28 #include <inttypes.h>
29
30 static void include (Dwarf *dbg, Dwarf_Off macoff, ptrdiff_t token);
31
32 static int
mac(Dwarf_Macro * macro,void * dbg)33 mac (Dwarf_Macro *macro, void *dbg)
34 {
35 static int level = 0;
36
37 unsigned int opcode;
38 dwarf_macro_opcode (macro, &opcode);
39 switch (opcode)
40 {
41 case DW_MACRO_import:
42 {
43 Dwarf_Attribute at;
44 int r = dwarf_macro_param (macro, 0, &at);
45 assert (r == 0);
46
47 Dwarf_Word w;
48 r = dwarf_formudata (&at, &w);
49 assert (r == 0);
50
51 printf ("%*sinclude %#" PRIx64 "\n", level, "", w);
52 ++level;
53 include (dbg, w, DWARF_GETMACROS_START);
54 --level;
55 printf ("%*s/include\n", level, "");
56 break;
57 }
58
59 case DW_MACRO_start_file:
60 {
61 Dwarf_Files *files;
62 size_t nfiles;
63 if (dwarf_macro_getsrcfiles (dbg, macro, &files, &nfiles) < 0)
64 printf ("dwarf_macro_getsrcfiles: %s\n",
65 dwarf_errmsg (dwarf_errno ()));
66
67 Dwarf_Word w = 0;
68 dwarf_macro_param2 (macro, &w, NULL);
69
70 const char *name = dwarf_filesrc (files, (size_t) w, NULL, NULL);
71 printf ("%*sfile %s\n", level, "", name);
72 ++level;
73 break;
74 }
75
76 case DW_MACRO_end_file:
77 {
78 --level;
79 printf ("%*s/file\n", level, "");
80 break;
81 }
82
83 case DW_MACINFO_define:
84 case DW_MACRO_define_strp:
85 case DW_MACRO_define_sup:
86 case DW_MACRO_define_strx:
87 {
88 const char *value;
89 dwarf_macro_param2 (macro, NULL, &value);
90 printf ("%*s%s\n", level, "", value);
91 break;
92 }
93
94 case DW_MACINFO_undef:
95 case DW_MACRO_undef_strp:
96 case DW_MACRO_undef_sup:
97 case DW_MACRO_undef_strx:
98 break;
99
100 default:
101 {
102 size_t paramcnt;
103 dwarf_macro_getparamcnt (macro, ¶mcnt);
104 printf ("%*sopcode %u with %zd arguments\n",
105 level, "", opcode, paramcnt);
106 break;
107 }
108 }
109
110 return DWARF_CB_ABORT;
111 }
112
113 static void
include(Dwarf * dbg,Dwarf_Off macoff,ptrdiff_t token)114 include (Dwarf *dbg, Dwarf_Off macoff, ptrdiff_t token)
115 {
116 while ((token = dwarf_getmacros_off (dbg, macoff, mac, dbg, token)) != 0)
117 if (token == -1)
118 {
119 puts (dwarf_errmsg (dwarf_errno ()));
120 break;
121 }
122 }
123
124 static void
getmacros(Dwarf * dbg,Dwarf_Die * die,bool new_style)125 getmacros (Dwarf *dbg, Dwarf_Die *die, bool new_style)
126 {
127 for (ptrdiff_t off = new_style ? DWARF_GETMACROS_START : 0;
128 (off = dwarf_getmacros (die, mac, dbg, off)); )
129 if (off == -1)
130 {
131 puts (dwarf_errmsg (-1));
132 break;
133 }
134 }
135
136 int
main(int argc,char * argv[])137 main (int argc, char *argv[])
138 {
139 assert (argc >= 3);
140 const char *name = argv[1];
141 bool new_style = argc > 3;
142
143 int fd = open (name, O_RDONLY);
144 Dwarf *dbg = dwarf_begin (fd, DWARF_C_READ);
145
146 if (argv[2][0] == '\0')
147 {
148 Dwarf_CU *cu = NULL;
149 Dwarf_Die cudie, subdie;
150 uint8_t unit_type;
151 while (dwarf_get_units (dbg, cu, &cu, NULL,
152 &unit_type, &cudie, &subdie) == 0)
153 {
154 Dwarf_Die *die = (unit_type == DW_UT_skeleton
155 ? &subdie : &cudie);
156 if (! dwarf_hasattr (die, DW_AT_macro_info)
157 && ! dwarf_hasattr (die, DW_AT_GNU_macros)
158 && ! dwarf_hasattr (die, DW_AT_macros))
159 continue;
160 printf ("CU %s\n", dwarf_diename (die));
161 getmacros (dbg, die, new_style);
162 }
163 }
164 else
165 {
166 ptrdiff_t cuoff = strtol (argv[2], NULL, 0);
167 Dwarf_Die cudie_mem, *cudie = dwarf_offdie (dbg, cuoff, &cudie_mem);
168 if (cudie == NULL)
169 {
170 puts (dwarf_errmsg (-1));
171 return 1;
172 }
173 getmacros (dbg, cudie, new_style);
174 }
175
176 dwarf_end (dbg);
177
178 return 0;
179 }
180