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 *
dwarf_encoding_string(unsigned int code)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
first_module(Dwfl_Module * mod,void ** userdatap,const char * name,Dwarf_Addr low_addr,void * arg)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
compare(const void * r1,const void * r2)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
one_register(void * arg,int regno,const char * setname,const char * prefix,const char * regname,int bits,int type)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
match_register(void * arg,int regno,const char * setname,const char * prefix,const char * regname,int bits,int type)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
main(int argc,char ** argv)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