Home | History | Annotate | Download | only in tests
      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 <error.h>
     25 #include <locale.h>
     26 #include <argp.h>
     27 #include <assert.h>
     28 #include ELFUTILS_HEADER(dwfl)
     29 #include <dwarf.h>
     30 
     31 #include "../libdw/known-dwarf.h"
     32 
     33 static const char *
     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
     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
     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
     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
    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
    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