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 <locale.h>
25 #include <argp.h>
26 #include <assert.h>
27 #include ELFUTILS_HEADER(dwfl)
28 #include <dwarf.h>
29 
30 #include "system.h"
31 #include "../libdw/known-dwarf.h"
32 
33 static const char *
dwarf_encoding_string(unsigned int code)34 dwarf_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 
50 static int
first_module(Dwfl_Module * mod,void ** userdatap,const char * name,Dwarf_Addr low_addr,void * arg)51 first_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 
66 struct state
67 {
68   struct reginfo *info;
69   int nregs;
70 };
71 
72 struct reginfo
73 {
74   const char *set, *pfx;
75   int regno;
76   int bits;
77   int type;
78   char name[32];
79 };
80 
81 static int
compare(const void * r1,const void * r2)82 compare (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 
98 static int
one_register(void * arg,int regno,const char * setname,const char * prefix,const char * regname,int bits,int type)99 one_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 
129 static int
match_register(void * arg,int regno,const char * setname,const char * prefix,const char * regname,int bits,int type)130 match_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 
146 int
main(int argc,char ** argv)147 main (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, &regno);
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