Home | History | Annotate | Download | only in tests
      1 /* Test program for libdwfl basic module tracking, relocation.
      2    Copyright (C) 2005, 2007 Red Hat, Inc.
      3    This file is part of Red Hat elfutils.
      4 
      5    Red Hat elfutils is free software; you can redistribute it and/or modify
      6    it under the terms of the GNU General Public License as published by the
      7    Free Software Foundation; version 2 of the License.
      8 
      9    Red Hat 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 GNU
     12    General Public License for more details.
     13 
     14    You should have received a copy of the GNU General Public License along
     15    with Red Hat elfutils; if not, write to the Free Software Foundation,
     16    Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301 USA.
     17 
     18    Red Hat elfutils is an included package of the Open Invention Network.
     19    An included package of the Open Invention Network is a package for which
     20    Open Invention Network licensees cross-license their patents.  No patent
     21    license is granted, either expressly or impliedly, by designation as an
     22    included package.  Should you wish to participate in the Open Invention
     23    Network licensing program, please visit www.openinventionnetwork.com
     24    <http://www.openinventionnetwork.com>.  */
     25 
     26 #include <config.h>
     27 #include <assert.h>
     28 #include <inttypes.h>
     29 #include <sys/types.h>
     30 #include <stdio.h>
     31 #include <stdio_ext.h>
     32 #include <stdlib.h>
     33 #include <string.h>
     34 #include <error.h>
     35 #include <locale.h>
     36 #include <argp.h>
     37 #include ELFUTILS_HEADER(dwfl)
     38 #include <dwarf.h>
     39 
     40 static bool show_inlines;
     41 
     42 struct info
     43 {
     44   Dwarf_Die *cudie;
     45   Dwarf_Addr dwbias;
     46 };
     47 
     48 static int
     49 print_instance (Dwarf_Die *instance, void *arg)
     50 {
     51   const struct info *info = arg;
     52 
     53   printf ("    inlined");
     54 
     55   Dwarf_Files *files;
     56   if (dwarf_getsrcfiles (info->cudie, &files, NULL) == 0)
     57     {
     58       Dwarf_Attribute attr_mem;
     59       Dwarf_Word val;
     60       if (dwarf_formudata (dwarf_attr (instance, DW_AT_call_file,
     61 				       &attr_mem), &val) == 0)
     62 	{
     63 	  const char *file = dwarf_filesrc (files, val, NULL, NULL);
     64 	  int lineno = 0, colno = 0;
     65 	  if (dwarf_formudata (dwarf_attr (instance, DW_AT_call_line,
     66 					   &attr_mem), &val) == 0)
     67 	    lineno = val;
     68 	  if (dwarf_formudata (dwarf_attr (instance, DW_AT_call_column,
     69 					   &attr_mem), &val) == 0)
     70 	    colno = val;
     71 	  if (lineno == 0)
     72 	    {
     73 	      if (file != NULL)
     74 		printf (" from %s", file);
     75 	    }
     76 	  else if (colno == 0)
     77 	    printf (" at %s:%u", file, lineno);
     78 	  else
     79 	    printf (" at %s:%u:%u", file, lineno, colno);
     80 	}
     81     }
     82 
     83   Dwarf_Addr lo = -1, hi = -1, entry = -1;
     84   if (dwarf_lowpc (instance, &lo) == 0)
     85     lo += info->dwbias;
     86   else
     87     printf (" (lowpc => %s)", dwarf_errmsg (-1));
     88   if (dwarf_highpc (instance, &hi) == 0)
     89     hi += info->dwbias;
     90   else
     91     printf (" (highpc => %s)", dwarf_errmsg (-1));
     92 
     93   Dwarf_Attribute attr_mem;
     94   Dwarf_Attribute *attr = dwarf_attr (instance, DW_AT_entry_pc, &attr_mem);
     95   if (attr != NULL)
     96     {
     97       if (dwarf_formaddr (attr, &entry) == 0)
     98 	entry += info->dwbias;
     99       else
    100 	printf (" (entrypc => %s)", dwarf_errmsg (-1));
    101     }
    102 
    103   if (lo != (Dwarf_Addr) -1 || hi != (Dwarf_Addr) -1)
    104     printf (" %#" PRIx64 "..%#" PRIx64, lo, hi);
    105   if (entry != (Dwarf_Addr) -1)
    106     printf (" => %#" PRIx64 "\n", entry);
    107   else
    108     puts ("");
    109 
    110   return DWARF_CB_OK;
    111 }
    112 
    113 static void
    114 print_inline (Dwarf_Die *func, void *arg)
    115 {
    116   if (dwarf_func_inline_instances (func, &print_instance, arg) != 0)
    117     printf ("  error finding instances: %s\n", dwarf_errmsg (-1));
    118 }
    119 
    120 static int
    121 print_func (Dwarf_Die *func, void *arg)
    122 {
    123   const struct info *info = arg;
    124 
    125   const char *file = dwarf_decl_file (func);
    126   int line = -1;
    127   dwarf_decl_line (func, &line);
    128   const char *fct = dwarf_diename (func);
    129 
    130   printf ("  %s:%d: %s:", file, line, fct);
    131 
    132   if (dwarf_func_inline (func))
    133     {
    134       puts (" inline function");
    135       if (show_inlines)
    136 	print_inline (func, arg);
    137     }
    138   else
    139     {
    140       Dwarf_Addr lo = -1, hi = -1, entry = -1;
    141       if (dwarf_lowpc (func, &lo) == 0)
    142 	lo += info->dwbias;
    143       else
    144 	printf (" (lowpc => %s)", dwarf_errmsg (-1));
    145       if (dwarf_highpc (func, &hi) == 0)
    146 	hi += info->dwbias;
    147       else
    148 	printf (" (highpc => %s)", dwarf_errmsg (-1));
    149       if (dwarf_entrypc (func, &entry) == 0)
    150 	entry += info->dwbias;
    151       else
    152 	printf (" (entrypc => %s)", dwarf_errmsg (-1));
    153 
    154       if (lo != (Dwarf_Addr) -1 || hi != (Dwarf_Addr) -1
    155 	  || entry != (Dwarf_Addr) -1)
    156 	printf (" %#" PRIx64 "..%#" PRIx64 " => %#" PRIx64 "\n",
    157 		lo, hi, entry);
    158       else
    159 	puts ("");
    160     }
    161 
    162   return DWARF_CB_OK;
    163 }
    164 
    165 static int
    166 list_module (Dwfl_Module *mod __attribute__ ((unused)),
    167 	     void **userdata __attribute__ ((unused)),
    168 	     const char *name, Dwarf_Addr base,
    169 	     void *arg __attribute__ ((unused)))
    170 {
    171   Dwarf_Addr start;
    172   Dwarf_Addr end;
    173   const char *file;
    174   const char *debug;
    175   if (dwfl_module_info (mod, NULL, &start, &end,
    176 			NULL, NULL, &file, &debug) != name
    177       || start != base)
    178     abort ();
    179   printf ("module: %30s %08" PRIx64 "..%08" PRIx64 " %s %s\n",
    180 	  name, start, end, file, debug);
    181   return DWARF_CB_OK;
    182 }
    183 
    184 static int
    185 print_module (Dwfl_Module *mod __attribute__ ((unused)),
    186 	      void **userdata __attribute__ ((unused)),
    187 	      const char *name, Dwarf_Addr base,
    188 	      Dwarf *dw, Dwarf_Addr bias,
    189 	      void *arg)
    190 {
    191   printf ("module: %30s %08" PRIx64 " %s %" PRIx64 " (%s)\n",
    192 	  name, base, dw == NULL ? "no" : "DWARF", bias, dwfl_errmsg (-1));
    193 
    194   if (dw != NULL && *(const bool *) arg)
    195     {
    196       Dwarf_Off off = 0;
    197       size_t cuhl;
    198       Dwarf_Off noff;
    199 
    200       while (dwarf_nextcu (dw, off, &noff, &cuhl, NULL, NULL, NULL) == 0)
    201 	{
    202 	  Dwarf_Die die_mem;
    203 	  struct info info = { dwarf_offdie (dw, off + cuhl, &die_mem), bias };
    204 	  (void) dwarf_getfuncs (info.cudie, print_func, &info, 0);
    205 
    206 	  off = noff;
    207 	}
    208     }
    209 
    210   return DWARF_CB_OK;
    211 }
    212 
    213 static bool show_functions;
    214 
    215 /* gettext helper macro.  */
    216 #undef	N_
    217 #define N_(Str) Str
    218 
    219 static const struct argp_option options[] =
    220   {
    221     { "functions", 'f', NULL, 0, N_("Additionally show function names"), 0 },
    222     { "inlines", 'i', NULL, 0, N_("Show instances of inlined functions"), 0 },
    223     { NULL, 0, NULL, 0, NULL, 0 }
    224   };
    225 
    226 static error_t
    227 parse_opt (int key, char *arg __attribute__ ((unused)),
    228 	   struct argp_state *state __attribute__ ((unused)))
    229 {
    230   switch (key)
    231     {
    232     case ARGP_KEY_INIT:
    233       state->child_inputs[0] = state->input;
    234       break;
    235 
    236     case 'f':
    237       show_functions = true;
    238       break;
    239 
    240     case 'i':
    241       show_inlines = show_functions = true;
    242       break;
    243 
    244     default:
    245       return ARGP_ERR_UNKNOWN;
    246     }
    247   return 0;
    248 }
    249 
    250 int
    251 main (int argc, char **argv)
    252 {
    253   /* We use no threads here which can interfere with handling a stream.  */
    254   (void) __fsetlocking (stdout, FSETLOCKING_BYCALLER);
    255 
    256   /* Set locale.  */
    257   (void) setlocale (LC_ALL, "");
    258 
    259   Dwfl *dwfl = NULL;
    260   const struct argp_child argp_children[] =
    261     {
    262       { .argp = dwfl_standard_argp () },
    263       { .argp = NULL }
    264     };
    265   const struct argp argp =
    266     {
    267       options, parse_opt, NULL, NULL, argp_children, NULL, NULL
    268     };
    269   (void) argp_parse (&argp, argc, argv, 0, NULL, &dwfl);
    270   assert (dwfl != NULL);
    271 
    272   ptrdiff_t p = 0;
    273   do
    274     p = dwfl_getmodules (dwfl, &list_module, NULL, p);
    275   while (p > 0);
    276   if (p < 0)
    277     error (2, 0, "dwfl_getmodules: %s", dwfl_errmsg (-1));
    278 
    279   do
    280     p = dwfl_getdwarf (dwfl, &print_module, &show_functions, p);
    281   while (p > 0);
    282   if (p < 0)
    283     error (2, 0, "dwfl_getdwarf: %s", dwfl_errmsg (-1));
    284 
    285   p = 0;
    286   do
    287     p = dwfl_getmodules (dwfl, &list_module, NULL, p);
    288   while (p > 0);
    289   if (p < 0)
    290     error (2, 0, "dwfl_getmodules: %s", dwfl_errmsg (-1));
    291 
    292   dwfl_end (dwfl);
    293 
    294   return 0;
    295 }
    296