1/* Copyright (C) 2005, 2006, 2015 Red Hat, Inc. 2 This file is part of elfutils. 3 4 This file is free software; you can redistribute it and/or modify 5 it under the terms of the GNU General Public License as published by 6 the Free Software Foundation; either version 3 of the License, or 7 (at your option) any later version. 8 9 elfutils is distributed in the hope that it will be useful, but 10 WITHOUT ANY WARRANTY; without even the implied warranty of 11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 GNU General Public License for more details. 13 14 You should have received a copy of the GNU General Public License 15 along with this program. If not, see <http://www.gnu.org/licenses/>. */ 16 17#ifdef HAVE_CONFIG_H 18# include <config.h> 19#endif 20 21#include <stdio.h> 22#include <stdlib.h> 23#include <string.h> 24#include <error.h> 25#include <locale.h> 26#include <argp.h> 27#include <assert.h> 28#include ELFUTILS_HEADER(dwfl) 29#include <dwarf.h> 30 31#include "../libdw/known-dwarf.h" 32 33static const char * 34dwarf_encoding_string (unsigned int code) 35{ 36 static const char *const known[] = 37 { 38#define DWARF_ONE_KNOWN_DW_ATE(NAME, CODE) [CODE] = #NAME, 39 DWARF_ALL_KNOWN_DW_ATE 40#undef DWARF_ONE_KNOWN_DW_ATE 41 }; 42 43 if (likely (code < sizeof (known) / sizeof (known[0]))) 44 return known[code]; 45 46 return NULL; 47} 48 49 50static int 51first_module (Dwfl_Module *mod, 52 void **userdatap __attribute__ ((unused)), 53 const char *name __attribute__ ((unused)), 54 Dwarf_Addr low_addr __attribute__ ((unused)), 55 void *arg) 56{ 57 Dwarf_Addr bias; 58 if (dwfl_module_getelf (mod, &bias) == NULL) /* Not really a module. */ 59 return DWARF_CB_OK; 60 61 *(Dwfl_Module **) arg = mod; 62 return DWARF_CB_ABORT; 63} 64 65 66struct state 67{ 68 struct reginfo *info; 69 int nregs; 70}; 71 72struct reginfo 73{ 74 const char *set, *pfx; 75 int regno; 76 int bits; 77 int type; 78 char name[32]; 79}; 80 81static int 82compare (const void *r1, const void *r2) 83{ 84 const struct reginfo *a = r1, *b = r2; 85 if (a->set == b->set) 86 return a->regno - b->regno; 87 if (a->set == NULL) 88 return 1; 89 if (b->set == NULL) 90 return -1; 91 if (!strcmp (a->set, "integer")) 92 return -1; 93 if (!strcmp (b->set, "integer")) 94 return 1; 95 return strcmp (a->set, b->set); 96} 97 98static int 99one_register (void *arg, 100 int regno, 101 const char *setname, 102 const char *prefix, 103 const char *regname, 104 int bits, int type) 105{ 106 struct state *state = arg; 107 108 if (regno >= state->nregs) 109 { 110 state->info = realloc (state->info, (regno + 1) * sizeof state->info[0]); 111 memset (&state->info[state->nregs], 0, 112 ((void *) &state->info[regno + 1] 113 - (void *) &state->info[state->nregs])); 114 state->nregs = regno + 1; 115 } 116 117 state->info[regno].regno = regno; 118 state->info[regno].set = setname; 119 state->info[regno].pfx = prefix; 120 state->info[regno].bits = bits; 121 state->info[regno].type = type; 122 assert (strlen (regname) < sizeof state->info[regno].name); 123 strcpy (state->info[regno].name, regname); 124 125 return DWARF_CB_OK; 126} 127 128 129static int 130match_register (void *arg, 131 int regno, 132 const char *setname, 133 const char *prefix, 134 const char *regname, 135 int bits, int type) 136{ 137 if (regno == *(int *) arg) 138 printf ("%5d => %s register %s%s %s %d bits\n", 139 regno, setname, prefix, regname, 140 dwarf_encoding_string (type), bits); 141 142 return DWARF_CB_ABORT; 143} 144 145 146int 147main (int argc, char **argv) 148{ 149 int remaining; 150 151 /* Set locale. */ 152 (void) setlocale (LC_ALL, ""); 153 154 Dwfl *dwfl = NULL; 155 (void) argp_parse (dwfl_standard_argp (), argc, argv, 0, &remaining, &dwfl); 156 assert (dwfl != NULL); 157 158 Dwfl_Module *mod = NULL; 159 if (dwfl_getmodules (dwfl, &first_module, &mod, 0) < 0) 160 error (EXIT_FAILURE, 0, "dwfl_getmodules: %s", dwfl_errmsg (-1)); 161 162 if (remaining == argc) 163 { 164 struct state state = { NULL, 0 }; 165 int result = dwfl_module_register_names (mod, &one_register, &state); 166 if (result != 0 || state.nregs == 0) 167 error (EXIT_FAILURE, 0, "dwfl_module_register_names: %s", 168 result ? dwfl_errmsg (-1) : "no backend registers known"); 169 170 qsort (state.info, state.nregs, sizeof state.info[0], &compare); 171 172 const char *set = NULL; 173 for (int i = 0; i < state.nregs; ++i) 174 if (state.info[i].set != NULL) 175 { 176 if (set != state.info[i].set) 177 printf ("%s registers:\n", state.info[i].set); 178 set = state.info[i].set; 179 180 printf ("\t%3d: %s%s (%s), %s %d bits\n", 181 state.info[i].regno, 182 state.info[i].pfx ?: "", state.info[i].name, 183 state.info[i].name, 184 dwarf_encoding_string (state.info[i].type), 185 state.info[i].bits); 186 } 187 free (state.info); 188 } 189 else 190 do 191 { 192 const char *arg = argv[remaining++]; 193 int regno = atoi (arg); 194 int result = dwfl_module_register_names (mod, &match_register, ®no); 195 if (result != DWARF_CB_ABORT) 196 error (EXIT_FAILURE, 0, "dwfl_module_register_names: %s", 197 result ? dwfl_errmsg (-1) : "no backend registers known"); 198 } 199 while (remaining < argc); 200 201 dwfl_end (dwfl); 202 203 return 0; 204} 205