1 /* Test program for dwarf_lowpc and dwarf_highpc 2 Copyright (C) 2012 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 <assert.h> 20 #include <inttypes.h> 21 #include ELFUTILS_HEADER(dwfl) 22 #include <dwarf.h> 23 #include <argp.h> 24 #include <stdio.h> 25 #include <stdio_ext.h> 26 #include <locale.h> 27 #include <stdlib.h> 28 #include <error.h> 29 #include <string.h> 30 #include <fnmatch.h> 31 32 struct args 33 { 34 Dwfl *dwfl; 35 Dwarf_Die *cu; 36 Dwarf_Addr dwbias; 37 char **argv; 38 const char *file; 39 }; 40 41 static struct args *args; 42 43 static void 44 fail(Dwarf_Off off, const char *name, const char *msg) 45 { 46 printf("%s: [%" PRIx64 "] '%s' %s\n", args->file, off, name, msg); 47 exit(-1); 48 } 49 50 static int 51 handle_die (Dwarf_Die *die, void *arg) 52 { 53 args = arg; 54 Dwarf_Off off = dwarf_dieoffset (die); 55 56 const char *name = dwarf_diename (die); 57 if (name == NULL) 58 fail (off, "<no name>", "die without a name"); 59 60 Dwarf_Addr lowpc = 0; 61 Dwarf_Addr highpc = 0; 62 if (dwarf_lowpc (die, &lowpc) != 0 && dwarf_hasattr (die, DW_AT_low_pc)) 63 fail (off, name, "has DW_AT_low_pc but dwarf_lowpc fails"); 64 if (dwarf_highpc (die, &highpc) != 0 && dwarf_hasattr (die, DW_AT_high_pc)) 65 fail (off, name, "has DW_AT_high_pc but dwarf_highpc fails"); 66 67 /* GCC < 4.7 had a bug where no code CUs got a highpc == lowpc. 68 Allow that, because it is not the main purpose of this test. */ 69 if (dwarf_hasattr (die, DW_AT_low_pc) 70 && dwarf_hasattr (die, DW_AT_high_pc) 71 && highpc <= lowpc 72 && ! (dwarf_tag (die) == DW_TAG_compile_unit && highpc == lowpc)) 73 { 74 printf("lowpc: %" PRIx64 ", highpc: %" PRIx64 "lx\n", lowpc, highpc); 75 fail (off, name, "highpc <= lowpc"); 76 } 77 78 return 0; 79 } 80 81 82 int 83 main (int argc, char *argv[]) 84 { 85 int remaining; 86 87 /* Set locale. */ 88 (void) setlocale (LC_ALL, ""); 89 90 struct args a = { .dwfl = NULL, .cu = NULL }; 91 92 (void) argp_parse (dwfl_standard_argp (), argc, argv, 0, &remaining, 93 &a.dwfl); 94 assert (a.dwfl != NULL); 95 a.argv = &argv[remaining]; 96 97 int result = 0; 98 99 while ((a.cu = dwfl_nextcu (a.dwfl, a.cu, &a.dwbias)) != NULL) 100 { 101 a.file = dwarf_diename (a.cu); 102 handle_die (a.cu, &a); 103 dwarf_getfuncs (a.cu, &handle_die, &a, 0); 104 } 105 106 dwfl_end (a.dwfl); 107 108 return result; 109 } 110