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 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 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 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