1/* Test program for dwarf_lowpc and dwarf_highpc 2 Copyright (C) 2012, 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 <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 <string.h> 29#include <fnmatch.h> 30 31struct args 32{ 33 Dwfl *dwfl; 34 Dwarf_Die *cu; 35 Dwarf_Addr dwbias; 36 char **argv; 37 const char *file; 38}; 39 40static struct args *args; 41 42static void 43fail(Dwarf_Off off, const char *name, const char *msg) 44{ 45 printf("%s: [%" PRIx64 "] '%s' %s\n", args->file, off, name, msg); 46 exit(-1); 47} 48 49static int 50handle_die (Dwarf_Die *die, void *arg) 51{ 52 args = arg; 53 Dwarf_Off off = dwarf_dieoffset (die); 54 55 const char *name = dwarf_diename (die); 56 if (name == NULL) 57 name = "<no name>"; 58 59 printf ("[%" PRIx64 "] %s\n", off, name); 60 61 Dwarf_Addr lowpc = 0; 62 Dwarf_Addr highpc = 0; 63 if (dwarf_lowpc (die, &lowpc) != 0 && dwarf_hasattr (die, DW_AT_low_pc)) 64 fail (off, name, "has DW_AT_low_pc but dwarf_lowpc fails"); 65 if (dwarf_highpc (die, &highpc) != 0 && dwarf_hasattr (die, DW_AT_high_pc)) 66 fail (off, name, "has DW_AT_high_pc but dwarf_highpc fails"); 67 68 /* GCC < 4.7 had a bug where no code CUs got a highpc == lowpc. 69 Allow that, because it is not the main purpose of this test. */ 70 if (dwarf_hasattr (die, DW_AT_low_pc) 71 && dwarf_hasattr (die, DW_AT_high_pc) 72 && highpc <= lowpc 73 && ! (dwarf_tag (die) == DW_TAG_compile_unit && highpc == lowpc)) 74 { 75 printf("lowpc: %" PRIx64 ", highpc: %" PRIx64 "\n", lowpc, highpc); 76 fail (off, name, "highpc <= lowpc"); 77 } 78 79 return 0; 80} 81 82 83int 84main (int argc, char *argv[]) 85{ 86 int remaining; 87 88 /* Set locale. */ 89 (void) setlocale (LC_ALL, ""); 90 91 struct args a = { .dwfl = NULL, .cu = NULL }; 92 93 (void) argp_parse (dwfl_standard_argp (), argc, argv, 0, &remaining, 94 &a.dwfl); 95 assert (a.dwfl != NULL); 96 a.argv = &argv[remaining]; 97 98 int result = 0; 99 100 while ((a.cu = dwfl_nextcu (a.dwfl, a.cu, &a.dwbias)) != NULL) 101 { 102 a.file = dwarf_diename (a.cu); 103 handle_die (a.cu, &a); 104 dwarf_getfuncs (a.cu, &handle_die, &a, 0); 105 106 uint8_t unit_type; 107 Dwarf_Die subdie; 108 if (dwarf_cu_info (a.cu->cu, NULL, &unit_type, NULL, &subdie, 109 NULL, NULL, NULL) != 0) 110 { 111 Dwarf_Off off = dwarf_dieoffset (a.cu); 112 fail (off, "dwarf_cu_info", dwarf_errmsg (-1)); 113 } 114 115 if (unit_type == DW_UT_skeleton) 116 { 117 const char *name = dwarf_diename (&subdie) ?: "<unknown>"; 118 printf ("Following split subdie: %s\n", name); 119 struct args b = a; 120 b.cu = &subdie; 121 handle_die (b.cu, &b); 122 dwarf_getfuncs (b.cu, &handle_die, &b, 0); 123 printf ("Done subdie: %s\n", name); 124 } 125 } 126 127 dwfl_end (a.dwfl); 128 129 printf ("\n"); 130 131 return result; 132} 133