1/* Test program for dwarf_die_addr_die. 2 Copyright (C) 2018 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#include <string.h> 30#include <errno.h> 31#include <unistd.h> 32 33/* The main Dwarf file. */ 34static Dwarf *dwarf; 35 36int 37check_die (Dwarf_Die *die) 38{ 39 if (dwarf_tag (die) == DW_TAG_invalid) 40 { 41 printf ("Invalid die\n"); 42 return -1; 43 } 44 45 int res = 0; 46 void *addr = die->addr; 47 Dwarf_Die die2; 48 if (dwarf_die_addr_die (dwarf, addr, &die2) == NULL) 49 { 50 printf ("Bad die addr die at offset %" PRIx64 "\n", 51 dwarf_dieoffset (die)); 52 res = -1; 53 } 54 55 if (dwarf_tag (die) != dwarf_tag (&die2)) 56 { 57 printf ("Tags differ for die at offset %" PRIx64 "\n", 58 dwarf_dieoffset (die)); 59 res = -1; 60 } 61 62 if (dwarf_cuoffset (die) != dwarf_cuoffset (&die2)) 63 { 64 printf ("CU offsets differ for die at offset %" PRIx64 "\n", 65 dwarf_dieoffset (die)); 66 res = -1; 67 } 68 69 Dwarf_Die child; 70 if (dwarf_child (die, &child) == 0) 71 res |= check_die (&child); 72 73 Dwarf_Die sibling; 74 if (dwarf_siblingof (die, &sibling) == 0) 75 res |= check_die (&sibling); 76 77 return res; 78} 79 80int 81check_dbg (Dwarf *dbg) 82{ 83 int res = 0; 84 Dwarf_Off off = 0; 85 Dwarf_Off old_off = 0; 86 size_t hsize; 87 Dwarf_Off abbrev; 88 uint8_t addresssize; 89 uint8_t offsetsize; 90 while (dwarf_nextcu (dbg, off, &off, &hsize, &abbrev, &addresssize, 91 &offsetsize) == 0) 92 { 93 Dwarf_Die die; 94 if (dwarf_offdie (dbg, old_off + hsize, &die) != NULL) 95 { 96 printf ("checking CU at %" PRIx64 "\n", old_off); 97 res |= check_die (&die); 98 } 99 100 old_off = off; 101 } 102 103 // Same for type... 104 Dwarf_Half version; 105 uint64_t typesig; 106 Dwarf_Off typeoff; 107 off = 0; 108 old_off = 0; 109 while (dwarf_next_unit (dbg, off, &off, &hsize, &version, &abbrev, 110 &addresssize, &offsetsize, &typesig, &typeoff) == 0) 111 { 112 Dwarf_Die die; 113 if (dwarf_offdie_types (dbg, old_off + hsize, &die) != NULL) 114 { 115 printf ("checking TU at %" PRIx64 "\n", old_off); 116 res |= check_die (&die); 117 } 118 119 // We should have seen this already, but double check... 120 if (dwarf_offdie_types (dbg, old_off + typeoff, &die) != NULL) 121 { 122 printf ("checking Type DIE at %" PRIx64 "\n", 123 old_off + hsize + typeoff); 124 res |= check_die (&die); 125 } 126 127 old_off = off; 128 } 129 130 Dwarf *alt = dwarf_getalt (dbg); 131 if (alt != NULL) 132 { 133 printf ("checking alt debug\n"); 134 res |= check_dbg (alt); 135 } 136 137 // Split or Type Dwarf_Dies gotten through dwarf_get_units. 138 Dwarf_CU *cu = NULL; 139 Dwarf_Die subdie; 140 uint8_t unit_type; 141 while (dwarf_get_units (dbg, cu, &cu, NULL, 142 &unit_type, NULL, &subdie) == 0) 143 { 144 if (dwarf_tag (&subdie) != DW_TAG_invalid) 145 { 146 printf ("checking %" PRIx8 " subdie\n", unit_type); 147 res |= check_die (&subdie); 148 } 149 } 150 151 return res; 152} 153 154int 155main (int argc, char *argv[]) 156{ 157 if (argc < 2) 158 { 159 printf ("No file given.\n"); 160 return -1; 161 } 162 163 const char *name = argv[1]; 164 int fd = open (name, O_RDONLY); 165 if (fd < 0) 166 { 167 printf ("Cannot open '%s': %s\n", name, strerror (errno)); 168 return -1; 169 } 170 171 dwarf = dwarf_begin (fd, DWARF_C_READ); 172 if (dwarf == NULL) 173 { 174 printf ("Not a Dwarf file '%s': %s\n", name, dwarf_errmsg (-1)); 175 close (fd); 176 return -1; 177 } 178 179 printf ("checking %s\n", name); 180 int res = check_dbg (dwarf); 181 182 dwarf_end (dwarf); 183 close (fd); 184 185 return res; 186} 187