xref: /third_party/elfutils/tests/low_high_pc.c (revision da0c48c4)
1/* Test program for dwarf_lowpc and dwarf_highpc
2   Copyright (C) 2012, 2018 Red Hat, Inc.
3   This file is part of elfutils.
4
5   This file is free software; you can redistribute it and/or modify
6   it under the terms of the GNU General Public License as published by
7   the Free Software Foundation; either version 3 of the License, or
8   (at your option) any later version.
9
10   elfutils is distributed in the hope that it will be useful, but
11   WITHOUT ANY WARRANTY; without even the implied warranty of
12   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13   GNU General Public License for more details.
14
15   You should have received a copy of the GNU General Public License
16   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
17
18#include <config.h>
19#include <assert.h>
20#include <inttypes.h>
21#include ELFUTILS_HEADER(dwfl)
22#include <dwarf.h>
23#include <argp.h>
24#include <stdio.h>
25#include <stdio_ext.h>
26#include <locale.h>
27#include <stdlib.h>
28#include <string.h>
29#include <fnmatch.h>
30
31struct args
32{
33  Dwfl *dwfl;
34  Dwarf_Die *cu;
35  Dwarf_Addr dwbias;
36  char **argv;
37  const char *file;
38};
39
40static struct args *args;
41
42static void
43fail(Dwarf_Off off, const char *name, const char *msg)
44{
45  printf("%s: [%" PRIx64 "] '%s' %s\n", args->file, off, name, msg);
46  exit(-1);
47}
48
49static int
50handle_die (Dwarf_Die *die, void *arg)
51{
52  args = arg;
53  Dwarf_Off off = dwarf_dieoffset (die);
54
55  const char *name = dwarf_diename (die);
56  if (name == NULL)
57    name = "<no name>";
58
59  printf ("[%" PRIx64 "] %s\n", off, name);
60
61  Dwarf_Addr lowpc = 0;
62  Dwarf_Addr highpc = 0;
63  if (dwarf_lowpc (die, &lowpc) != 0 && dwarf_hasattr (die, DW_AT_low_pc))
64    fail (off, name, "has DW_AT_low_pc but dwarf_lowpc fails");
65  if (dwarf_highpc (die, &highpc) != 0 && dwarf_hasattr (die, DW_AT_high_pc))
66    fail (off, name, "has DW_AT_high_pc but dwarf_highpc fails");
67
68  /* GCC < 4.7 had a bug where no code CUs got a highpc == lowpc.
69     Allow that, because it is not the main purpose of this test.  */
70  if (dwarf_hasattr (die, DW_AT_low_pc)
71      && dwarf_hasattr (die, DW_AT_high_pc)
72      && highpc <= lowpc
73      && ! (dwarf_tag (die) == DW_TAG_compile_unit && highpc == lowpc))
74    {
75      printf("lowpc: %" PRIx64 ", highpc: %" PRIx64 "\n", lowpc, highpc);
76      fail (off, name, "highpc <= lowpc");
77    }
78
79  return 0;
80}
81
82
83int
84main (int argc, char *argv[])
85{
86  int remaining;
87
88  /* Set locale.  */
89  (void) setlocale (LC_ALL, "");
90
91  struct args a = { .dwfl = NULL, .cu = NULL };
92
93  (void) argp_parse (dwfl_standard_argp (), argc, argv, 0, &remaining,
94		     &a.dwfl);
95  assert (a.dwfl != NULL);
96  a.argv = &argv[remaining];
97
98  int result = 0;
99
100  while ((a.cu = dwfl_nextcu (a.dwfl, a.cu, &a.dwbias)) != NULL)
101    {
102      a.file = dwarf_diename (a.cu);
103      handle_die (a.cu, &a);
104      dwarf_getfuncs (a.cu, &handle_die, &a, 0);
105
106      uint8_t unit_type;
107      Dwarf_Die subdie;
108      if (dwarf_cu_info (a.cu->cu, NULL, &unit_type, NULL, &subdie,
109			 NULL, NULL, NULL) != 0)
110	{
111	  Dwarf_Off off = dwarf_dieoffset (a.cu);
112	  fail (off, "dwarf_cu_info", dwarf_errmsg (-1));
113	}
114
115      if (unit_type == DW_UT_skeleton)
116	{
117	  const char *name = dwarf_diename (&subdie) ?: "<unknown>";
118	  printf ("Following split subdie: %s\n", name);
119	  struct args b = a;
120	  b.cu = &subdie;
121	  handle_die (b.cu, &b);
122	  dwarf_getfuncs (b.cu, &handle_die, &b, 0);
123	  printf ("Done subdie: %s\n", name);
124	}
125    }
126
127  dwfl_end (a.dwfl);
128
129  printf ("\n");
130
131  return result;
132}
133