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