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
40static const char *
41dwarf_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
76static int
77first_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
92struct state
93{
94  struct reginfo *info;
95  int nregs;
96};
97
98struct reginfo
99{
100  const char *set, *pfx;
101  int regno;
102  int bits;
103  int type;
104  char name[32];
105};
106
107static int
108compare (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
124static int
125one_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
155static int
156match_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
172int
173main (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, &regno);
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