blob: 2a3db05c16e5ee49347552f41ea657de633f4838 [file] [log] [blame]
Roland McGrath3c84db32009-06-24 17:41:40 -07001/* Test program for CFI handling.
2 Copyright (C) 2009 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 ELFUTILS_HEADER(dwfl)
30#include <dwarf.h>
31#include <argp.h>
32#include <stdio.h>
33#include <stdio_ext.h>
34#include <locale.h>
35#include <stdlib.h>
36#include <error.h>
37#include <string.h>
38
39
40static void
41print_detail (int result, const Dwarf_Op *ops, size_t nops, Dwarf_Addr bias)
42{
43 if (result < 0)
44 printf ("indeterminate (%s)\n", dwarf_errmsg (-1));
45 else if (nops == 0)
46 printf ("%s\n", result == 0 ? "same_value" : "undefined");
47 else
48 {
49 printf ("%s expression:", result == 0 ? "location" : "value");
50 for (size_t i = 0; i < nops; ++i)
51 {
52 printf (" %#x", ops[i].atom);
53 if (ops[i].number2 == 0)
54 {
55 if (ops[i].atom == DW_OP_addr)
56 printf ("(%#" PRIx64 ")", ops[i].number + bias);
57 else if (ops[i].number != 0)
58 printf ("(%" PRId64 ")", ops[i].number);
59 }
60 else
61 printf ("(%" PRId64 ",%" PRId64 ")",
62 ops[i].number, ops[i].number2);
63 }
64 puts ("");
65 }
66}
67
68struct stuff
69{
70 Dwarf_Frame *frame;
71 Dwarf_Addr bias;
72};
73
74static int
75print_register (void *arg,
76 int regno,
77 const char *setname,
78 const char *prefix,
79 const char *regname,
80 int bits __attribute__ ((unused)),
81 int type __attribute__ ((unused)))
82{
83 struct stuff *stuff = arg;
84
85 printf ("\t%s reg%u (%s%s): ", setname, regno, prefix, regname);
86
87 Dwarf_Op ops_mem[2];
88 Dwarf_Op *ops;
89 size_t nops;
90 int result = dwarf_frame_register (stuff->frame, regno, ops_mem, &ops, &nops);
91 print_detail (result, ops, nops, stuff->bias);
92
93 return DWARF_CB_OK;
94}
95
96static int
97handle_cfi (Dwfl *dwfl, const char *which, Dwarf_CFI *cfi,
98 GElf_Addr pc, struct stuff *stuff)
99{
100 int result = dwarf_cfi_addrframe (cfi, pc - stuff->bias, &stuff->frame);
101 if (result != 0)
102 {
103 error (0, 0, "dwarf_addrframe (%s): %s", which, dwfl_errmsg (-1));
104 return 1;
105 }
106
107 Dwarf_Addr start = pc;
108 Dwarf_Addr end = pc;
109 bool signalp;
110 int ra_regno = dwarf_frame_info (stuff->frame, &start, &end, &signalp);
111 if (ra_regno >= 0)
112 {
113 start += stuff->bias;
114 end += stuff->bias;
115 }
116
117 printf ("%s has %#" PRIx64 " => [%#" PRIx64 ", %#" PRIx64 "):\n",
118 which, pc, start, end);
119
120 if (ra_regno < 0)
121 printf ("\treturn address register unavailable (%s)\n",
122 dwarf_errmsg (0));
123 else
124 printf ("\treturn address in reg%u%s\n",
125 ra_regno, signalp ? " (signal frame)" : "");
126
127 Dwarf_Op *cfa_ops;
Roland McGrathaf800142009-07-22 13:55:50 -0700128 size_t cfa_nops;
129 result = dwarf_frame_cfa (stuff->frame, &cfa_ops, &cfa_nops);
Roland McGrath3c84db32009-06-24 17:41:40 -0700130
131 printf ("\tCFA ");
Roland McGrathaf800142009-07-22 13:55:50 -0700132 print_detail (result, cfa_ops, cfa_nops, stuff->bias);
Roland McGrath3c84db32009-06-24 17:41:40 -0700133
134 (void) dwfl_module_register_names (dwfl_addrmodule (dwfl, pc),
135 &print_register, stuff);
136
137 return 0;
138}
139
140static int
141handle_address (GElf_Addr pc, Dwfl *dwfl)
142{
143 Dwfl_Module *mod = dwfl_addrmodule (dwfl, pc);
144
145 struct stuff stuff;
146 return (handle_cfi (dwfl, ".eh_frame",
147 dwfl_module_eh_cfi (mod, &stuff.bias), pc, &stuff)
148 & handle_cfi (dwfl, ".debug_frame",
149 dwfl_module_dwarf_cfi (mod, &stuff.bias), pc, &stuff));
150}
151
152int
153main (int argc, char *argv[])
154{
155 int remaining;
156
157 /* Set locale. */
158 (void) setlocale (LC_ALL, "");
159
160 Dwfl *dwfl = NULL;
161 (void) argp_parse (dwfl_standard_argp (), argc, argv, 0, &remaining, &dwfl);
162 assert (dwfl != NULL);
163
164 int result = 0;
165
166 /* Now handle the addresses. In case none are given on the command
167 line, read from stdin. */
168 if (remaining == argc)
169 {
170 /* We use no threads here which can interfere with handling a stream. */
171 (void) __fsetlocking (stdin, FSETLOCKING_BYCALLER);
172
173 char *buf = NULL;
174 size_t len = 0;
175 while (!feof_unlocked (stdin))
176 {
177 if (getline (&buf, &len, stdin) < 0)
178 break;
179
180 char *endp;
181 uintmax_t addr = strtoumax (buf, &endp, 0);
182 if (endp != buf)
183 result |= handle_address (addr, dwfl);
184 else
185 result = 1;
186 }
187
188 free (buf);
189 }
190 else
191 {
192 do
193 {
194 char *endp;
195 uintmax_t addr = strtoumax (argv[remaining], &endp, 0);
196 if (endp != argv[remaining])
197 result |= handle_address (addr, dwfl);
198 else
199 result = 1;
200 }
201 while (++remaining < argc);
202 }
203
204 dwfl_end (dwfl);
205
206 return result;
207}