1da0c48c4Sopenharmony_ci/* Test program for dwarf_die_addr_die.
2da0c48c4Sopenharmony_ci   Copyright (C) 2018 Red Hat, Inc.
3da0c48c4Sopenharmony_ci   This file is part of elfutils.
4da0c48c4Sopenharmony_ci
5da0c48c4Sopenharmony_ci   This file is free software; you can redistribute it and/or modify
6da0c48c4Sopenharmony_ci   it under the terms of the GNU General Public License as published by
7da0c48c4Sopenharmony_ci   the Free Software Foundation; either version 3 of the License, or
8da0c48c4Sopenharmony_ci   (at your option) any later version.
9da0c48c4Sopenharmony_ci
10da0c48c4Sopenharmony_ci   elfutils is distributed in the hope that it will be useful, but
11da0c48c4Sopenharmony_ci   WITHOUT ANY WARRANTY; without even the implied warranty of
12da0c48c4Sopenharmony_ci   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13da0c48c4Sopenharmony_ci   GNU General Public License for more details.
14da0c48c4Sopenharmony_ci
15da0c48c4Sopenharmony_ci   You should have received a copy of the GNU General Public License
16da0c48c4Sopenharmony_ci   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
17da0c48c4Sopenharmony_ci
18da0c48c4Sopenharmony_ci#include <config.h>
19da0c48c4Sopenharmony_ci#include ELFUTILS_HEADER(dw)
20da0c48c4Sopenharmony_ci#include <dwarf.h>
21da0c48c4Sopenharmony_ci#include <sys/types.h>
22da0c48c4Sopenharmony_ci#include <sys/stat.h>
23da0c48c4Sopenharmony_ci#include <fcntl.h>
24da0c48c4Sopenharmony_ci#include <stdio.h>
25da0c48c4Sopenharmony_ci#include <stdint.h>
26da0c48c4Sopenharmony_ci#include <stdlib.h>
27da0c48c4Sopenharmony_ci#include <assert.h>
28da0c48c4Sopenharmony_ci#include <inttypes.h>
29da0c48c4Sopenharmony_ci#include <string.h>
30da0c48c4Sopenharmony_ci#include <errno.h>
31da0c48c4Sopenharmony_ci#include <unistd.h>
32da0c48c4Sopenharmony_ci
33da0c48c4Sopenharmony_ci/* The main Dwarf file.  */
34da0c48c4Sopenharmony_cistatic Dwarf *dwarf;
35da0c48c4Sopenharmony_ci
36da0c48c4Sopenharmony_ciint
37da0c48c4Sopenharmony_cicheck_die (Dwarf_Die *die)
38da0c48c4Sopenharmony_ci{
39da0c48c4Sopenharmony_ci  if (dwarf_tag (die) == DW_TAG_invalid)
40da0c48c4Sopenharmony_ci    {
41da0c48c4Sopenharmony_ci      printf ("Invalid die\n");
42da0c48c4Sopenharmony_ci      return -1;
43da0c48c4Sopenharmony_ci    }
44da0c48c4Sopenharmony_ci
45da0c48c4Sopenharmony_ci  int res = 0;
46da0c48c4Sopenharmony_ci  void *addr = die->addr;
47da0c48c4Sopenharmony_ci  Dwarf_Die die2;
48da0c48c4Sopenharmony_ci  if (dwarf_die_addr_die (dwarf, addr, &die2) == NULL)
49da0c48c4Sopenharmony_ci    {
50da0c48c4Sopenharmony_ci      printf ("Bad die addr die at offset %" PRIx64 "\n",
51da0c48c4Sopenharmony_ci	      dwarf_dieoffset (die));
52da0c48c4Sopenharmony_ci      res = -1;
53da0c48c4Sopenharmony_ci    }
54da0c48c4Sopenharmony_ci
55da0c48c4Sopenharmony_ci  if (dwarf_tag (die) != dwarf_tag (&die2))
56da0c48c4Sopenharmony_ci    {
57da0c48c4Sopenharmony_ci      printf ("Tags differ for die at offset %" PRIx64 "\n",
58da0c48c4Sopenharmony_ci	      dwarf_dieoffset (die));
59da0c48c4Sopenharmony_ci      res = -1;
60da0c48c4Sopenharmony_ci    }
61da0c48c4Sopenharmony_ci
62da0c48c4Sopenharmony_ci  if (dwarf_cuoffset (die) != dwarf_cuoffset (&die2))
63da0c48c4Sopenharmony_ci    {
64da0c48c4Sopenharmony_ci      printf ("CU offsets differ for die at offset %" PRIx64 "\n",
65da0c48c4Sopenharmony_ci	      dwarf_dieoffset (die));
66da0c48c4Sopenharmony_ci      res = -1;
67da0c48c4Sopenharmony_ci    }
68da0c48c4Sopenharmony_ci
69da0c48c4Sopenharmony_ci  Dwarf_Die child;
70da0c48c4Sopenharmony_ci  if (dwarf_child (die, &child) == 0)
71da0c48c4Sopenharmony_ci    res |= check_die (&child);
72da0c48c4Sopenharmony_ci
73da0c48c4Sopenharmony_ci  Dwarf_Die sibling;
74da0c48c4Sopenharmony_ci  if (dwarf_siblingof (die, &sibling) == 0)
75da0c48c4Sopenharmony_ci    res |= check_die (&sibling);
76da0c48c4Sopenharmony_ci
77da0c48c4Sopenharmony_ci  return res;
78da0c48c4Sopenharmony_ci}
79da0c48c4Sopenharmony_ci
80da0c48c4Sopenharmony_ciint
81da0c48c4Sopenharmony_cicheck_dbg (Dwarf *dbg)
82da0c48c4Sopenharmony_ci{
83da0c48c4Sopenharmony_ci  int res = 0;
84da0c48c4Sopenharmony_ci  Dwarf_Off off = 0;
85da0c48c4Sopenharmony_ci  Dwarf_Off old_off = 0;
86da0c48c4Sopenharmony_ci  size_t hsize;
87da0c48c4Sopenharmony_ci  Dwarf_Off abbrev;
88da0c48c4Sopenharmony_ci  uint8_t addresssize;
89da0c48c4Sopenharmony_ci  uint8_t offsetsize;
90da0c48c4Sopenharmony_ci  while (dwarf_nextcu (dbg, off, &off, &hsize, &abbrev, &addresssize,
91da0c48c4Sopenharmony_ci                       &offsetsize) == 0)
92da0c48c4Sopenharmony_ci    {
93da0c48c4Sopenharmony_ci      Dwarf_Die die;
94da0c48c4Sopenharmony_ci      if (dwarf_offdie (dbg, old_off + hsize, &die) != NULL)
95da0c48c4Sopenharmony_ci	{
96da0c48c4Sopenharmony_ci	  printf ("checking CU at %" PRIx64 "\n", old_off);
97da0c48c4Sopenharmony_ci	  res |= check_die (&die);
98da0c48c4Sopenharmony_ci	}
99da0c48c4Sopenharmony_ci
100da0c48c4Sopenharmony_ci      old_off = off;
101da0c48c4Sopenharmony_ci    }
102da0c48c4Sopenharmony_ci
103da0c48c4Sopenharmony_ci  // Same for type...
104da0c48c4Sopenharmony_ci  Dwarf_Half version;
105da0c48c4Sopenharmony_ci  uint64_t typesig;
106da0c48c4Sopenharmony_ci  Dwarf_Off typeoff;
107da0c48c4Sopenharmony_ci  off = 0;
108da0c48c4Sopenharmony_ci  old_off = 0;
109da0c48c4Sopenharmony_ci  while (dwarf_next_unit (dbg, off, &off, &hsize, &version, &abbrev,
110da0c48c4Sopenharmony_ci			  &addresssize, &offsetsize, &typesig, &typeoff) == 0)
111da0c48c4Sopenharmony_ci    {
112da0c48c4Sopenharmony_ci      Dwarf_Die die;
113da0c48c4Sopenharmony_ci      if (dwarf_offdie_types (dbg, old_off + hsize, &die) != NULL)
114da0c48c4Sopenharmony_ci	{
115da0c48c4Sopenharmony_ci	  printf ("checking TU at %" PRIx64 "\n", old_off);
116da0c48c4Sopenharmony_ci	  res |= check_die (&die);
117da0c48c4Sopenharmony_ci	}
118da0c48c4Sopenharmony_ci
119da0c48c4Sopenharmony_ci      // We should have seen this already, but double check...
120da0c48c4Sopenharmony_ci      if (dwarf_offdie_types (dbg, old_off + typeoff, &die) != NULL)
121da0c48c4Sopenharmony_ci	{
122da0c48c4Sopenharmony_ci	  printf ("checking Type DIE at %" PRIx64 "\n",
123da0c48c4Sopenharmony_ci		  old_off + hsize + typeoff);
124da0c48c4Sopenharmony_ci	  res |= check_die (&die);
125da0c48c4Sopenharmony_ci	}
126da0c48c4Sopenharmony_ci
127da0c48c4Sopenharmony_ci      old_off = off;
128da0c48c4Sopenharmony_ci    }
129da0c48c4Sopenharmony_ci
130da0c48c4Sopenharmony_ci  Dwarf *alt = dwarf_getalt (dbg);
131da0c48c4Sopenharmony_ci  if (alt != NULL)
132da0c48c4Sopenharmony_ci    {
133da0c48c4Sopenharmony_ci      printf ("checking alt debug\n");
134da0c48c4Sopenharmony_ci      res |= check_dbg (alt);
135da0c48c4Sopenharmony_ci    }
136da0c48c4Sopenharmony_ci
137da0c48c4Sopenharmony_ci  // Split or Type Dwarf_Dies gotten through dwarf_get_units.
138da0c48c4Sopenharmony_ci  Dwarf_CU *cu = NULL;
139da0c48c4Sopenharmony_ci  Dwarf_Die subdie;
140da0c48c4Sopenharmony_ci  uint8_t unit_type;
141da0c48c4Sopenharmony_ci  while (dwarf_get_units (dbg, cu, &cu, NULL,
142da0c48c4Sopenharmony_ci                          &unit_type, NULL, &subdie) == 0)
143da0c48c4Sopenharmony_ci    {
144da0c48c4Sopenharmony_ci      if (dwarf_tag (&subdie) != DW_TAG_invalid)
145da0c48c4Sopenharmony_ci        {
146da0c48c4Sopenharmony_ci	  printf ("checking %" PRIx8 " subdie\n", unit_type);
147da0c48c4Sopenharmony_ci	  res |= check_die (&subdie);
148da0c48c4Sopenharmony_ci	}
149da0c48c4Sopenharmony_ci    }
150da0c48c4Sopenharmony_ci
151da0c48c4Sopenharmony_ci  return res;
152da0c48c4Sopenharmony_ci}
153da0c48c4Sopenharmony_ci
154da0c48c4Sopenharmony_ciint
155da0c48c4Sopenharmony_cimain (int argc, char *argv[])
156da0c48c4Sopenharmony_ci{
157da0c48c4Sopenharmony_ci  if (argc < 2)
158da0c48c4Sopenharmony_ci    {
159da0c48c4Sopenharmony_ci      printf ("No file given.\n");
160da0c48c4Sopenharmony_ci      return -1;
161da0c48c4Sopenharmony_ci    }
162da0c48c4Sopenharmony_ci
163da0c48c4Sopenharmony_ci  const char *name = argv[1];
164da0c48c4Sopenharmony_ci  int fd = open (name, O_RDONLY);
165da0c48c4Sopenharmony_ci  if (fd < 0)
166da0c48c4Sopenharmony_ci    {
167da0c48c4Sopenharmony_ci      printf ("Cannot open '%s': %s\n", name, strerror (errno));
168da0c48c4Sopenharmony_ci      return -1;
169da0c48c4Sopenharmony_ci    }
170da0c48c4Sopenharmony_ci
171da0c48c4Sopenharmony_ci  dwarf = dwarf_begin (fd, DWARF_C_READ);
172da0c48c4Sopenharmony_ci  if (dwarf == NULL)
173da0c48c4Sopenharmony_ci    {
174da0c48c4Sopenharmony_ci      printf ("Not a Dwarf file '%s': %s\n", name, dwarf_errmsg (-1));
175da0c48c4Sopenharmony_ci      close (fd);
176da0c48c4Sopenharmony_ci      return -1;
177da0c48c4Sopenharmony_ci    }
178da0c48c4Sopenharmony_ci
179da0c48c4Sopenharmony_ci  printf ("checking %s\n", name);
180da0c48c4Sopenharmony_ci  int res = check_dbg (dwarf);
181da0c48c4Sopenharmony_ci
182da0c48c4Sopenharmony_ci  dwarf_end (dwarf);
183da0c48c4Sopenharmony_ci  close (fd);
184da0c48c4Sopenharmony_ci
185da0c48c4Sopenharmony_ci  return res;
186da0c48c4Sopenharmony_ci}
187