xref: /third_party/elfutils/tests/next-lines.c (revision da0c48c4)
1/* A variant of get-lines that uses dwarf_next_lines.
2   Copyright (C) 2002, 2004, 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#ifdef HAVE_CONFIG_H
19# include <config.h>
20#endif
21
22#include <fcntl.h>
23#include <inttypes.h>
24#include <libelf.h>
25#include ELFUTILS_HEADER(dw)
26#include <stdio.h>
27#include <string.h>
28#include <unistd.h>
29
30
31int
32main (int argc, char *argv[])
33{
34  int result = 0;
35  int cnt;
36
37  for (cnt = 1; cnt < argc; ++cnt)
38    {
39      int fd = open (argv[cnt], O_RDONLY);
40
41      Dwarf *dbg = dwarf_begin (fd, DWARF_C_READ);
42      if  (dbg == NULL)
43	{
44	  printf ("%s not usable: %s\n", argv[cnt], dwarf_errmsg (-1));
45	  close  (fd);
46	  continue;
47	}
48
49      Dwarf_Off off;
50      Dwarf_Off next_off = 0;
51      Dwarf_CU *cu = NULL;
52      Dwarf_Lines *lb;
53      size_t nlb;
54      int res;
55      while ((res = dwarf_next_lines (dbg, off = next_off, &next_off, &cu,
56				      NULL, NULL, &lb, &nlb)) == 0)
57	{
58	  printf ("off = %" PRIu64 "\n", off);
59	  printf (" %zu lines\n", nlb);
60
61	  for (size_t i = 0; i < nlb; ++i)
62	    {
63	      Dwarf_Line *l = dwarf_onesrcline (lb, i);
64	      if (l == NULL)
65		{
66		  printf ("%s: cannot get individual line\n", argv[cnt]);
67		  result = 1;
68		  break;
69		}
70
71	      Dwarf_Addr addr;
72	      if (dwarf_lineaddr (l, &addr) != 0)
73		addr = 0;
74	      const char *file = dwarf_linesrc (l, NULL, NULL);
75	      int line;
76	      if (dwarf_lineno (l, &line) != 0)
77		line = 0;
78
79	      printf ("%" PRIx64 ": %s:%d:", (uint64_t) addr,
80		      file ?: "???", line);
81
82	      /* Getting the file path through the Dwarf_Files should
83		 result in the same path.  */
84	      Dwarf_Files *files;
85	      size_t idx;
86	      if (dwarf_line_file (l, &files, &idx) != 0)
87		{
88		  printf ("%s: cannot get file from line (%zd): %s\n",
89			  argv[cnt], i, dwarf_errmsg (-1));
90		  result = 1;
91		  break;
92		}
93	      const char *path = dwarf_filesrc (files, idx, NULL, NULL);
94	      if ((path == NULL && file != NULL)
95		  || (path != NULL && file == NULL)
96		  || (strcmp (file, path) != 0))
97		{
98		  printf ("%s: line %zd srcline (%s) != file srcline (%s)\n",
99			  argv[cnt], i, file ?: "???", path ?: "???");
100		  result = 1;
101		  break;
102		}
103
104	      int column;
105	      if (dwarf_linecol (l, &column) != 0)
106		column = 0;
107	      if (column >= 0)
108		printf ("%d:", column);
109
110	      bool is_stmt;
111	      if (dwarf_linebeginstatement (l, &is_stmt) != 0)
112		is_stmt = false;
113	      bool end_sequence;
114	      if (dwarf_lineendsequence (l, &end_sequence) != 0)
115		end_sequence = false;
116	      bool basic_block;
117	      if (dwarf_lineblock (l, &basic_block) != 0)
118		basic_block = false;
119	      bool prologue_end;
120	      if (dwarf_lineprologueend (l, &prologue_end) != 0)
121		prologue_end = false;
122	      bool epilogue_begin;
123	      if (dwarf_lineepiloguebegin (l, &epilogue_begin) != 0)
124		epilogue_begin = false;
125
126	      printf (" is_stmt:%s, end_seq:%s, bb:%s, prologue:%s, epilogue:%s\n",
127		      is_stmt ? "yes" : "no", end_sequence ? "yes" : "no",
128		      basic_block ? "yes" : "no", prologue_end  ? "yes" : "no",
129		      epilogue_begin ? "yes" : "no");
130	    }
131	}
132
133      if (res < 0)
134	{
135	  printf ("dwarf_next_lines failed: %s\n", dwarf_errmsg (-1));
136	  result = 1;
137	}
138
139      dwarf_end (dbg);
140      close (fd);
141    }
142
143  return result;
144}
145