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_GNU_transparent_include:
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_GNU_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_GNU_end_file:
77 {
78 --level;
79 printf ("%*s/file\n", level, "");
80 break;
81 }
82
83 case DW_MACINFO_define:
84 case DW_MACRO_GNU_define_indirect:
85 {
86 const char *value;
87 dwarf_macro_param2 (macro, NULL, &value);
88 printf ("%*s%s\n", level, "", value);
89 break;
90 }
91
92 case DW_MACINFO_undef:
93 case DW_MACRO_GNU_undef_indirect:
94 break;
95
96 default:
97 {
98 size_t paramcnt;
99 dwarf_macro_getparamcnt (macro, ¶mcnt);
100 printf ("%*sopcode %u with %zd arguments\n",
101 level, "", opcode, paramcnt);
102 break;
103 }
104 }
105
106 return DWARF_CB_ABORT;
107 }
108
109 static void
include(Dwarf * dbg,Dwarf_Off macoff,ptrdiff_t token)110 include (Dwarf *dbg, Dwarf_Off macoff, ptrdiff_t token)
111 {
112 while ((token = dwarf_getmacros_off (dbg, macoff, mac, dbg, token)) != 0)
113 if (token == -1)
114 {
115 puts (dwarf_errmsg (dwarf_errno ()));
116 break;
117 }
118 }
119
120 int
main(int argc,char * argv[])121 main (int argc, char *argv[])
122 {
123 assert (argc >= 3);
124 const char *name = argv[1];
125 ptrdiff_t cuoff = strtol (argv[2], NULL, 0);
126 bool new_style = argc > 3;
127
128 int fd = open (name, O_RDONLY);
129 Dwarf *dbg = dwarf_begin (fd, DWARF_C_READ);
130
131 Dwarf_Die cudie_mem, *cudie = dwarf_offdie (dbg, cuoff, &cudie_mem);
132
133 for (ptrdiff_t off = new_style ? DWARF_GETMACROS_START : 0;
134 (off = dwarf_getmacros (cudie, mac, dbg, off)); )
135 if (off == -1)
136 {
137 puts (dwarf_errmsg (dwarf_errno ()));
138 break;
139 }
140
141 dwarf_end (dbg);
142
143 return 0;
144 }
145