1 /* Test program for CFI handling.
2 Copyright (C) 2009-2010 Red Hat, Inc.
3 This file is part of elfutils.
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.
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.
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/>. */
21 #include ELFUTILS_HEADER(dwfl)
25 #include <stdio_ext.h>
33 print_detail (int result, const Dwarf_Op *ops, size_t nops, Dwarf_Addr bias)
36 printf ("indeterminate (%s)\n", dwarf_errmsg (-1));
38 printf ("%s\n", result == 0 ? "same_value" : "undefined");
41 printf ("%s expression:", result == 0 ? "location" : "value");
42 for (size_t i = 0; i < nops; ++i)
44 printf (" %#x", ops[i].atom);
45 if (ops[i].number2 == 0)
47 if (ops[i].atom == DW_OP_addr)
48 printf ("(%#" PRIx64 ")", ops[i].number + bias);
49 else if (ops[i].number != 0)
50 printf ("(%" PRId64 ")", ops[i].number);
53 printf ("(%" PRId64 ",%" PRId64 ")",
54 ops[i].number, ops[i].number2);
67 print_register (void *arg,
72 int bits __attribute__ ((unused)),
73 int type __attribute__ ((unused)))
75 struct stuff *stuff = arg;
77 printf ("\t%s reg%u (%s%s): ", setname, regno, prefix, regname);
82 int result = dwarf_frame_register (stuff->frame, regno, ops_mem, &ops, &nops);
83 print_detail (result, ops, nops, stuff->bias);
89 handle_cfi (Dwfl *dwfl, const char *which, Dwarf_CFI *cfi,
90 GElf_Addr pc, struct stuff *stuff)
92 int result = dwarf_cfi_addrframe (cfi, pc - stuff->bias, &stuff->frame);
95 error (0, 0, "dwarf_cfi_addrframe (%s): %s", which, dwarf_errmsg (-1));
99 Dwarf_Addr start = pc;
102 int ra_regno = dwarf_frame_info (stuff->frame, &start, &end, &signalp);
105 start += stuff->bias;
109 printf ("%s has %#" PRIx64 " => [%#" PRIx64 ", %#" PRIx64 "):\n",
110 which, pc, start, end);
113 printf ("\treturn address register unavailable (%s)\n",
116 printf ("\treturn address in reg%u%s\n",
117 ra_regno, signalp ? " (signal frame)" : "");
121 result = dwarf_frame_cfa (stuff->frame, &cfa_ops, &cfa_nops);
124 print_detail (result, cfa_ops, cfa_nops, stuff->bias);
126 (void) dwfl_module_register_names (dwfl_addrmodule (dwfl, pc),
127 &print_register, stuff);
133 handle_address (GElf_Addr pc, Dwfl *dwfl)
135 Dwfl_Module *mod = dwfl_addrmodule (dwfl, pc);
138 return (handle_cfi (dwfl, ".eh_frame",
139 dwfl_module_eh_cfi (mod, &stuff.bias), pc, &stuff)
140 & handle_cfi (dwfl, ".debug_frame",
141 dwfl_module_dwarf_cfi (mod, &stuff.bias), pc, &stuff));
145 main (int argc, char *argv[])
150 (void) setlocale (LC_ALL, "");
153 (void) argp_parse (dwfl_standard_argp (), argc, argv, 0, &remaining, &dwfl);
154 assert (dwfl != NULL);
158 /* Now handle the addresses. In case none are given on the command
159 line, read from stdin. */
160 if (remaining == argc)
162 /* We use no threads here which can interfere with handling a stream. */
163 (void) __fsetlocking (stdin, FSETLOCKING_BYCALLER);
167 while (!feof_unlocked (stdin))
169 if (getline (&buf, &len, stdin) < 0)
173 uintmax_t addr = strtoumax (buf, &endp, 0);
175 result |= handle_address (addr, dwfl);
187 uintmax_t addr = strtoumax (argv[remaining], &endp, 0);
188 if (endp != argv[remaining])
189 result |= handle_address (addr, dwfl);
193 while (++remaining < argc);