1da0c48c4Sopenharmony_ci/* Test program for dwarf_getscopes. 2da0c48c4Sopenharmony_ci Copyright (C) 2005, 2014 Red Hat, Inc. 3da0c48c4Sopenharmony_ci This file is part of elfutils. 4da0c48c4Sopenharmony_ci 5da0c48c4Sopenharmony_ci This file is free software; you can redistribute it and/or modify 6da0c48c4Sopenharmony_ci it under the terms of the GNU General Public License as published by 7da0c48c4Sopenharmony_ci the Free Software Foundation; either version 3 of the License, or 8da0c48c4Sopenharmony_ci (at your option) any later version. 9da0c48c4Sopenharmony_ci 10da0c48c4Sopenharmony_ci elfutils is distributed in the hope that it will be useful, but 11da0c48c4Sopenharmony_ci WITHOUT ANY WARRANTY; without even the implied warranty of 12da0c48c4Sopenharmony_ci MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13da0c48c4Sopenharmony_ci GNU General Public License for more details. 14da0c48c4Sopenharmony_ci 15da0c48c4Sopenharmony_ci You should have received a copy of the GNU General Public License 16da0c48c4Sopenharmony_ci along with this program. If not, see <http://www.gnu.org/licenses/>. */ 17da0c48c4Sopenharmony_ci 18da0c48c4Sopenharmony_ci#include <config.h> 19da0c48c4Sopenharmony_ci#include <assert.h> 20da0c48c4Sopenharmony_ci#include <inttypes.h> 21da0c48c4Sopenharmony_ci#include ELFUTILS_HEADER(dwfl) 22da0c48c4Sopenharmony_ci#include <dwarf.h> 23da0c48c4Sopenharmony_ci#include <argp.h> 24da0c48c4Sopenharmony_ci#include <stdio.h> 25da0c48c4Sopenharmony_ci#include <stdio_ext.h> 26da0c48c4Sopenharmony_ci#include <locale.h> 27da0c48c4Sopenharmony_ci#include <stdlib.h> 28da0c48c4Sopenharmony_ci#include <string.h> 29da0c48c4Sopenharmony_ci#include "system.h" 30da0c48c4Sopenharmony_ci 31da0c48c4Sopenharmony_ci 32da0c48c4Sopenharmony_cistatic void 33da0c48c4Sopenharmony_cipaddr (const char *prefix, Dwarf_Addr addr, Dwfl_Line *line) 34da0c48c4Sopenharmony_ci{ 35da0c48c4Sopenharmony_ci const char *src; 36da0c48c4Sopenharmony_ci int lineno, linecol; 37da0c48c4Sopenharmony_ci if (line != NULL 38da0c48c4Sopenharmony_ci && (src = dwfl_lineinfo (line, &addr, &lineno, &linecol, 39da0c48c4Sopenharmony_ci NULL, NULL)) != NULL) 40da0c48c4Sopenharmony_ci { 41da0c48c4Sopenharmony_ci if (linecol != 0) 42da0c48c4Sopenharmony_ci printf ("%s%#" PRIx64 " (%s:%d:%d)", 43da0c48c4Sopenharmony_ci prefix, addr, src, lineno, linecol); 44da0c48c4Sopenharmony_ci else 45da0c48c4Sopenharmony_ci printf ("%s%#" PRIx64 " (%s:%d)", 46da0c48c4Sopenharmony_ci prefix, addr, src, lineno); 47da0c48c4Sopenharmony_ci } 48da0c48c4Sopenharmony_ci else 49da0c48c4Sopenharmony_ci printf ("%s%#" PRIx64, prefix, addr); 50da0c48c4Sopenharmony_ci} 51da0c48c4Sopenharmony_ci 52da0c48c4Sopenharmony_cistatic void 53da0c48c4Sopenharmony_ciprint_vars (unsigned int indent, Dwarf_Die *die) 54da0c48c4Sopenharmony_ci{ 55da0c48c4Sopenharmony_ci Dwarf_Die child; 56da0c48c4Sopenharmony_ci if (dwarf_child (die, &child) == 0) 57da0c48c4Sopenharmony_ci do 58da0c48c4Sopenharmony_ci switch (dwarf_tag (&child)) 59da0c48c4Sopenharmony_ci { 60da0c48c4Sopenharmony_ci case DW_TAG_variable: 61da0c48c4Sopenharmony_ci case DW_TAG_formal_parameter: 62da0c48c4Sopenharmony_ci printf ("%*s%-30s[%6" PRIx64 "]\n", indent, "", 63da0c48c4Sopenharmony_ci dwarf_diename (&child), 64da0c48c4Sopenharmony_ci (uint64_t) dwarf_dieoffset (&child)); 65da0c48c4Sopenharmony_ci break; 66da0c48c4Sopenharmony_ci default: 67da0c48c4Sopenharmony_ci break; 68da0c48c4Sopenharmony_ci } 69da0c48c4Sopenharmony_ci while (dwarf_siblingof (&child, &child) == 0); 70da0c48c4Sopenharmony_ci 71da0c48c4Sopenharmony_ci Dwarf_Attribute attr_mem; 72da0c48c4Sopenharmony_ci Dwarf_Die origin; 73da0c48c4Sopenharmony_ci if (dwarf_hasattr (die, DW_AT_abstract_origin) 74da0c48c4Sopenharmony_ci && dwarf_formref_die (dwarf_attr (die, DW_AT_abstract_origin, &attr_mem), 75da0c48c4Sopenharmony_ci &origin) != NULL 76da0c48c4Sopenharmony_ci && dwarf_child (&origin, &child) == 0) 77da0c48c4Sopenharmony_ci do 78da0c48c4Sopenharmony_ci switch (dwarf_tag (&child)) 79da0c48c4Sopenharmony_ci { 80da0c48c4Sopenharmony_ci case DW_TAG_variable: 81da0c48c4Sopenharmony_ci case DW_TAG_formal_parameter: 82da0c48c4Sopenharmony_ci printf ("%*s%s (abstract)\n", indent, "", 83da0c48c4Sopenharmony_ci dwarf_diename (&child)); 84da0c48c4Sopenharmony_ci break; 85da0c48c4Sopenharmony_ci default: 86da0c48c4Sopenharmony_ci break; 87da0c48c4Sopenharmony_ci } 88da0c48c4Sopenharmony_ci while (dwarf_siblingof (&child, &child) == 0); 89da0c48c4Sopenharmony_ci} 90da0c48c4Sopenharmony_ci 91da0c48c4Sopenharmony_ci 92da0c48c4Sopenharmony_ci#define INDENT 4 93da0c48c4Sopenharmony_ci 94da0c48c4Sopenharmony_cistatic void 95da0c48c4Sopenharmony_cihandle_address (GElf_Addr pc, Dwfl *dwfl) 96da0c48c4Sopenharmony_ci{ 97da0c48c4Sopenharmony_ci Dwarf_Addr cubias; 98da0c48c4Sopenharmony_ci Dwarf_Die *cudie = dwfl_addrdie (dwfl, pc, &cubias); 99da0c48c4Sopenharmony_ci if (cudie == NULL) 100da0c48c4Sopenharmony_ci error (EXIT_FAILURE, 0, "dwfl_addrdie: %s", dwfl_errmsg (-1)); 101da0c48c4Sopenharmony_ci 102da0c48c4Sopenharmony_ci Dwarf_Die *scopes; 103da0c48c4Sopenharmony_ci int n = dwarf_getscopes (cudie, pc - cubias, &scopes); 104da0c48c4Sopenharmony_ci if (n < 0) 105da0c48c4Sopenharmony_ci error (EXIT_FAILURE, 0, "dwarf_getscopes: %s", dwarf_errmsg (-1)); 106da0c48c4Sopenharmony_ci else if (n == 0) 107da0c48c4Sopenharmony_ci printf ("%#" PRIx64 ": not in any scope\n", pc); 108da0c48c4Sopenharmony_ci else 109da0c48c4Sopenharmony_ci { 110da0c48c4Sopenharmony_ci printf ("%#" PRIx64 ":\n", pc); 111da0c48c4Sopenharmony_ci unsigned int indent = 0; 112da0c48c4Sopenharmony_ci while (n-- > 0) 113da0c48c4Sopenharmony_ci { 114da0c48c4Sopenharmony_ci Dwarf_Die *const die = &scopes[n]; 115da0c48c4Sopenharmony_ci 116da0c48c4Sopenharmony_ci indent += INDENT; 117da0c48c4Sopenharmony_ci printf ("%*s%s (%#x)", indent, "", 118da0c48c4Sopenharmony_ci dwarf_diename (die) ?: "<unnamed>", 119da0c48c4Sopenharmony_ci dwarf_tag (die)); 120da0c48c4Sopenharmony_ci 121da0c48c4Sopenharmony_ci Dwarf_Addr lowpc, highpc; 122da0c48c4Sopenharmony_ci if (dwarf_lowpc (die, &lowpc) == 0 123da0c48c4Sopenharmony_ci && dwarf_highpc (die, &highpc) == 0) 124da0c48c4Sopenharmony_ci { 125da0c48c4Sopenharmony_ci lowpc += cubias; 126da0c48c4Sopenharmony_ci highpc += cubias; 127da0c48c4Sopenharmony_ci Dwfl_Line *loline = dwfl_getsrc (dwfl, lowpc); 128da0c48c4Sopenharmony_ci Dwfl_Line *hiline = dwfl_getsrc (dwfl, highpc - 1); 129da0c48c4Sopenharmony_ci paddr (": ", lowpc, loline); 130da0c48c4Sopenharmony_ci if (highpc != lowpc) 131da0c48c4Sopenharmony_ci paddr (" .. ", highpc - 1, hiline == loline ? NULL : hiline); 132da0c48c4Sopenharmony_ci } 133da0c48c4Sopenharmony_ci puts (""); 134da0c48c4Sopenharmony_ci 135da0c48c4Sopenharmony_ci print_vars (indent + INDENT, die); 136da0c48c4Sopenharmony_ci } 137da0c48c4Sopenharmony_ci free (scopes); 138da0c48c4Sopenharmony_ci } 139da0c48c4Sopenharmony_ci} 140da0c48c4Sopenharmony_ci 141da0c48c4Sopenharmony_ciint 142da0c48c4Sopenharmony_cimain (int argc, char *argv[]) 143da0c48c4Sopenharmony_ci{ 144da0c48c4Sopenharmony_ci int remaining; 145da0c48c4Sopenharmony_ci 146da0c48c4Sopenharmony_ci /* Set locale. */ 147da0c48c4Sopenharmony_ci (void) setlocale (LC_ALL, ""); 148da0c48c4Sopenharmony_ci 149da0c48c4Sopenharmony_ci Dwfl *dwfl = NULL; 150da0c48c4Sopenharmony_ci (void) argp_parse (dwfl_standard_argp (), argc, argv, 0, &remaining, &dwfl); 151da0c48c4Sopenharmony_ci assert (dwfl != NULL); 152da0c48c4Sopenharmony_ci 153da0c48c4Sopenharmony_ci int result = 0; 154da0c48c4Sopenharmony_ci 155da0c48c4Sopenharmony_ci /* Now handle the addresses. In case none are given on the command 156da0c48c4Sopenharmony_ci line, read from stdin. */ 157da0c48c4Sopenharmony_ci if (remaining == argc) 158da0c48c4Sopenharmony_ci { 159da0c48c4Sopenharmony_ci /* We use no threads here which can interfere with handling a stream. */ 160da0c48c4Sopenharmony_ci (void) __fsetlocking (stdin, FSETLOCKING_BYCALLER); 161da0c48c4Sopenharmony_ci 162da0c48c4Sopenharmony_ci char *buf = NULL; 163da0c48c4Sopenharmony_ci size_t len = 0; 164da0c48c4Sopenharmony_ci while (!feof_unlocked (stdin)) 165da0c48c4Sopenharmony_ci { 166da0c48c4Sopenharmony_ci if (getline (&buf, &len, stdin) < 0) 167da0c48c4Sopenharmony_ci break; 168da0c48c4Sopenharmony_ci 169da0c48c4Sopenharmony_ci char *endp; 170da0c48c4Sopenharmony_ci uintmax_t addr = strtoumax (buf, &endp, 0); 171da0c48c4Sopenharmony_ci if (endp != buf) 172da0c48c4Sopenharmony_ci handle_address (addr, dwfl); 173da0c48c4Sopenharmony_ci else 174da0c48c4Sopenharmony_ci result = 1; 175da0c48c4Sopenharmony_ci } 176da0c48c4Sopenharmony_ci 177da0c48c4Sopenharmony_ci free (buf); 178da0c48c4Sopenharmony_ci } 179da0c48c4Sopenharmony_ci else 180da0c48c4Sopenharmony_ci { 181da0c48c4Sopenharmony_ci do 182da0c48c4Sopenharmony_ci { 183da0c48c4Sopenharmony_ci char *endp; 184da0c48c4Sopenharmony_ci uintmax_t addr = strtoumax (argv[remaining], &endp, 0); 185da0c48c4Sopenharmony_ci if (endp != argv[remaining]) 186da0c48c4Sopenharmony_ci handle_address (addr, dwfl); 187da0c48c4Sopenharmony_ci else 188da0c48c4Sopenharmony_ci result = 1; 189da0c48c4Sopenharmony_ci } 190da0c48c4Sopenharmony_ci while (++remaining < argc); 191da0c48c4Sopenharmony_ci } 192da0c48c4Sopenharmony_ci 193da0c48c4Sopenharmony_ci dwfl_end (dwfl); 194da0c48c4Sopenharmony_ci 195da0c48c4Sopenharmony_ci return result; 196da0c48c4Sopenharmony_ci} 197