1 /* Copyright (C) 2005, 2006 Red Hat, Inc. 2 This file is part of Red Hat elfutils. 3 4 Red Hat elfutils is free software; you can redistribute it and/or modify 5 it under the terms of the GNU General Public License as published by the 6 Free Software Foundation; version 2 of the License. 7 8 Red Hat elfutils is distributed in the hope that it will be useful, but 9 WITHOUT ANY WARRANTY; without even the implied warranty of 10 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 11 General Public License for more details. 12 13 You should have received a copy of the GNU General Public License along 14 with Red Hat elfutils; if not, write to the Free Software Foundation, 15 Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301 USA. 16 17 Red Hat elfutils is an included package of the Open Invention Network. 18 An included package of the Open Invention Network is a package for which 19 Open Invention Network licensees cross-license their patents. No patent 20 license is granted, either expressly or impliedly, by designation as an 21 included package. Should you wish to participate in the Open Invention 22 Network licensing program, please visit www.openinventionnetwork.com 23 <http://www.openinventionnetwork.com>. */ 24 25 #ifdef HAVE_CONFIG_H 26 # include <config.h> 27 #endif 28 29 #include <stdio.h> 30 #include <stdlib.h> 31 #include <string.h> 32 #include <error.h> 33 #include <locale.h> 34 #include <argp.h> 35 #include <assert.h> 36 #include ELFUTILS_HEADER(dwfl) 37 #include <dwarf.h> 38 39 40 static const char * 41 dwarf_encoding_string (unsigned int code) 42 { 43 static const char *known[] = 44 { 45 [DW_ATE_void] = "void", 46 [DW_ATE_address] = "address", 47 [DW_ATE_boolean] = "boolean", 48 [DW_ATE_complex_float] = "complex_float", 49 [DW_ATE_float] = "float", 50 [DW_ATE_signed] = "signed", 51 [DW_ATE_signed_char] = "signed_char", 52 [DW_ATE_unsigned] = "unsigned", 53 [DW_ATE_unsigned_char] = "unsigned_char", 54 [DW_ATE_imaginary_float] = "imaginary_float", 55 [DW_ATE_packed_decimal] = "packed_decimal", 56 [DW_ATE_numeric_string] = "numeric_string", 57 [DW_ATE_edited] = "edited", 58 [DW_ATE_signed_fixed] = "signed_fixed", 59 [DW_ATE_unsigned_fixed] = "unsigned_fixed", 60 [DW_ATE_decimal_float] = "decimal_float", 61 }; 62 63 if (code < sizeof (known) / sizeof (known[0])) 64 return known[code]; 65 66 if (code >= DW_ATE_lo_user && code <= DW_ATE_hi_user) 67 { 68 static char buf[30]; 69 snprintf (buf, sizeof (buf), "lo_user+%u", code - DW_ATE_lo_user); 70 return buf; 71 } 72 73 return "???"; 74 } 75 76 static int 77 first_module (Dwfl_Module *mod, 78 void **userdatap __attribute__ ((unused)), 79 const char *name __attribute__ ((unused)), 80 Dwarf_Addr low_addr __attribute__ ((unused)), 81 void *arg) 82 { 83 Dwarf_Addr bias; 84 if (dwfl_module_getelf (mod, &bias) == NULL) /* Not really a module. */ 85 return DWARF_CB_OK; 86 87 *(Dwfl_Module **) arg = mod; 88 return DWARF_CB_ABORT; 89 } 90 91 92 struct state 93 { 94 struct reginfo *info; 95 int nregs; 96 }; 97 98 struct reginfo 99 { 100 const char *set, *pfx; 101 int regno; 102 int bits; 103 int type; 104 char name[32]; 105 }; 106 107 static int 108 compare (const void *r1, const void *r2) 109 { 110 const struct reginfo *a = r1, *b = r2; 111 if (a->set == b->set) 112 return a->regno - b->regno; 113 if (a->set == NULL) 114 return 1; 115 if (b->set == NULL) 116 return -1; 117 if (!strcmp (a->set, "integer")) 118 return -1; 119 if (!strcmp (b->set, "integer")) 120 return 1; 121 return strcmp (a->set, b->set); 122 } 123 124 static int 125 one_register (void *arg, 126 int regno, 127 const char *setname, 128 const char *prefix, 129 const char *regname, 130 int bits, int type) 131 { 132 struct state *state = arg; 133 134 if (regno >= state->nregs) 135 { 136 state->info = realloc (state->info, (regno + 1) * sizeof state->info[0]); 137 memset (&state->info[state->nregs], 0, 138 ((void *) &state->info[regno + 1] 139 - (void *) &state->info[state->nregs])); 140 state->nregs = regno + 1; 141 } 142 143 state->info[regno].regno = regno; 144 state->info[regno].set = setname; 145 state->info[regno].pfx = prefix; 146 state->info[regno].bits = bits; 147 state->info[regno].type = type; 148 assert (strlen (regname) < sizeof state->info[regno].name); 149 strcpy (state->info[regno].name, regname); 150 151 return DWARF_CB_OK; 152 } 153 154 155 static int 156 match_register (void *arg, 157 int regno, 158 const char *setname, 159 const char *prefix, 160 const char *regname, 161 int bits, int type) 162 { 163 if (regno == *(int *) arg) 164 printf ("%5d => %s register %s%s %s %d bits\n", 165 regno, setname, prefix, regname, 166 dwarf_encoding_string (type), bits); 167 168 return DWARF_CB_ABORT; 169 } 170 171 172 int 173 main (int argc, char **argv) 174 { 175 int remaining; 176 177 /* Set locale. */ 178 (void) setlocale (LC_ALL, ""); 179 180 Dwfl *dwfl = NULL; 181 (void) argp_parse (dwfl_standard_argp (), argc, argv, 0, &remaining, &dwfl); 182 assert (dwfl != NULL); 183 184 Dwfl_Module *mod = NULL; 185 if (dwfl_getmodules (dwfl, &first_module, &mod, 0) < 0) 186 error (EXIT_FAILURE, 0, "dwfl_getmodules: %s", dwfl_errmsg (-1)); 187 188 if (remaining == argc) 189 { 190 struct state state = { NULL, 0 }; 191 int result = dwfl_module_register_names (mod, &one_register, &state); 192 if (result != 0 || state.nregs == 0) 193 error (EXIT_FAILURE, 0, "dwfl_module_register_names: %s", 194 result ? dwfl_errmsg (-1) : "no backend registers known"); 195 196 qsort (state.info, state.nregs, sizeof state.info[0], &compare); 197 198 const char *set = NULL; 199 for (int i = 0; i < state.nregs; ++i) 200 if (state.info[i].set != NULL) 201 { 202 if (set != state.info[i].set) 203 printf ("%s registers:\n", state.info[i].set); 204 set = state.info[i].set; 205 206 printf ("\t%3d: %s%s (%s), %s %d bits\n", 207 state.info[i].regno, 208 state.info[i].pfx ?: "", state.info[i].name, 209 state.info[i].name, 210 dwarf_encoding_string (state.info[i].type), 211 state.info[i].bits); 212 } 213 } 214 else 215 do 216 { 217 const char *arg = argv[remaining++]; 218 int regno = atoi (arg); 219 int result = dwfl_module_register_names (mod, &match_register, ®no); 220 if (result != DWARF_CB_ABORT) 221 error (EXIT_FAILURE, 0, "dwfl_module_register_names: %s", 222 result ? dwfl_errmsg (-1) : "no backend registers known"); 223 } 224 while (remaining < argc); 225 226 dwfl_end (dwfl); 227 228 return 0; 229 } 230