blob: d1e2f78fde5fdd03332c6bf4838fae525fd0beae [file] [log] [blame]
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00001/* Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc.
Ulrich Drepper361df7d2006-04-04 21:38:57 +00002 This file is part of Red Hat elfutils.
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00003 Written by Ulrich Drepper <drepper@redhat.com>, 1998.
4
Ulrich Drepper361df7d2006-04-04 21:38:57 +00005 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.
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00008
Ulrich Drepper361df7d2006-04-04 21:38:57 +00009 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,
Ulrich Drepper1e9ef502006-04-04 22:29:06 +000016 Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301 USA.
Ulrich Drepper361df7d2006-04-04 21:38:57 +000017
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>. */
Ulrich Drepperb08d5a82005-07-26 05:00:05 +000025
26#include <config.h>
27
28#include <fcntl.h>
29#include <libelf.h>
30#include <libdwarf.h>
31#include <stdio.h>
32#include <string.h>
33#include <unistd.h>
34
35int
36main (int argc, char *argv[])
37{
38 int cnt;
39
40 for (cnt = 1; cnt < argc; ++cnt)
41 {
42 int fd = open (argv[cnt], O_RDONLY);
43 Dwarf_Debug dbg;
44 Dwarf_Signed cie_cnt;
45 Dwarf_Cie *cie_data;
46 Dwarf_Signed fde_cnt;
47 Dwarf_Fde *fde_data;
48 Dwarf_Error err;
49
50 if (dwarf_init (fd, DW_DLC_READ, NULL, NULL, &dbg, &err) != DW_DLV_OK)
51 {
52 printf ("%s not usable: %s\n", argv[cnt], dwarf_errmsg (err));
53 continue;
54 }
55 else if (dwarf_get_fde_list_eh (dbg, &cie_data, &cie_cnt, &fde_data,
56 &fde_cnt, &err) != DW_DLV_OK)
57 printf ("cannot get CIEs and FDEs from %s: %s\n", argv[cnt],
58 dwarf_errmsg (err));
59 else
60 {
61 Dwarf_Addr low_pc;
62 Dwarf_Addr high_pc;
63 Dwarf_Unsigned func_length;
64 Dwarf_Ptr fde_bytes;
65 Dwarf_Unsigned fde_byte_length;
66 Dwarf_Off cie_offset;
67 Dwarf_Signed cie_index;
68 Dwarf_Off fde_offset;
69 Dwarf_Fde fde;
70 int i;
71
72 printf ("%s has %lld CIEs and %lld FDEs\n",
73 basename (argv[cnt]),
74 (long long int) cie_cnt, (long long int) fde_cnt);
75
76 for (i = 0; i < cie_cnt; ++i)
77 {
78 Dwarf_Unsigned bytes_in_cie;
79 Dwarf_Small version;
80 char *augmenter;
81 Dwarf_Unsigned code_alignment_factor;
82 Dwarf_Signed data_alignment_factor;
83 Dwarf_Half return_address_register;
84 Dwarf_Ptr initial_instructions;
85 Dwarf_Unsigned initial_instructions_length;
86
87 if (dwarf_get_cie_info (cie_data[i], &bytes_in_cie, &version,
88 &augmenter, &code_alignment_factor,
89 &data_alignment_factor,
90 &return_address_register,
91 &initial_instructions,
92 &initial_instructions_length, &err)
93 != DW_DLV_OK)
94 printf ("cannot get info for CIE %d: %s\n", i,
95 dwarf_errmsg (err));
96 else
97 {
98 size_t j;
99
100 printf ("CIE[%d]: bytes_in_cie = %llu, version = %hhd, augmenter = \"%s\"\n",
101 i, (unsigned long long int) bytes_in_cie, version,
102 augmenter);
103 printf ("CIE[%d]: code_alignment_factor = %llx\n"
104 "CIE[%d]: data_alignment_factor = %llx\n"
105 "CIE[%d]: return_address_register = %hu\n"
106 "CIE[%d]: bytes =",
107 i, (unsigned long long int) code_alignment_factor,
108 i, (unsigned long long int) data_alignment_factor,
109 i, return_address_register, i);
110
111 for (j = 0; j < initial_instructions_length; ++j)
112 printf (" %02hhx",
113 ((unsigned char *) initial_instructions)[j]);
114
115 putchar ('\n');
116 }
117 }
118
119 for (i = 0; i < fde_cnt; ++i)
120 {
121 Dwarf_Cie cie;
122
123 if (dwarf_get_fde_range (fde_data[i], &low_pc, &func_length,
124 &fde_bytes, &fde_byte_length,
125 &cie_offset, &cie_index, &fde_offset,
126 &err) != DW_DLV_OK)
127 printf ("cannot get range of FDE %d: %s\n", i,
128 dwarf_errmsg (err));
129 else
130 {
131 size_t j;
132 Dwarf_Ptr instrs;
133 Dwarf_Unsigned len;
134
135 printf ("FDE[%d]: low_pc = %#llx, length = %llu\n", i,
136 (unsigned long long int) low_pc,
137 (unsigned long long int) func_length);
138 printf ("FDE[%d]: bytes =", i);
139
140 for (j = 0; j < fde_byte_length; ++j)
141 printf (" %02hhx", ((unsigned char *) fde_bytes)[j]);
142
143 printf ("\nFDE[%d]: cie_offset = %lld, cie_index = %lld, fde_offset = %lld\n",
144 i, (long long int) cie_offset,
145 (long long int) cie_index,
146 (long long int) fde_offset);
147
148 if (dwarf_get_fde_instr_bytes (fde_data[i], &instrs, &len,
149 &err) != DW_DLV_OK)
150 printf ("cannot get instructions of FDE %d: %s\n", i,
151 dwarf_errmsg (err));
152 else
153 {
154 printf ("FDE[%d]: instructions =", i);
155
156 for (j = 0; j < len; ++j)
157 printf (" %02hhx", ((unsigned char *) instrs)[j]);
158
159 putchar ('\n');
160 }
161
162 /* Consistency check. */
163 if (dwarf_get_cie_of_fde (fde_data[i], &cie, &err)
164 != DW_DLV_OK)
165 printf ("cannot get CIE of FDE %d: %s\n", i,
166 dwarf_errmsg (err));
167 else if (cie_data[cie_index] != cie)
168 puts ("cie_index for FDE[%d] does not match dwarf_get_cie_of_fde result");
169 }
170
171 if (dwarf_get_fde_n (fde_data, i, &fde, &err) != DW_DLV_OK)
172 printf ("dwarf_get_fde_n for FDE[%d] failed\n", i);
173 else if (fde != fde_data[i])
174 printf ("dwarf_get_fde_n for FDE[%d] didn't return the right value\n", i);
175 }
176
177 if (dwarf_get_fde_n (fde_data, fde_cnt, &fde, &err)
178 != DW_DLV_NO_ENTRY)
179 puts ("dwarf_get_fde_n for invalid index doesn't return DW_DLV_NO_ENTRY");
180
181 {
182 const unsigned int addrs[] =
183 {
184 0x8048400, 0x804842c, 0x8048454, 0x8048455, 0x80493fc
185 };
186 const int naddrs = sizeof (addrs) / sizeof (addrs[0]);
187
188 for (i = 0; i < naddrs; ++i)
189 if (dwarf_get_fde_at_pc (fde_data, addrs[i], &fde, &low_pc,
190 &high_pc, &err) != DW_DLV_OK)
191 printf ("no FDE at %x\n", addrs[i]);
192 else
193 {
194 Dwarf_Addr other_low_pc;
195
196 if (dwarf_get_fde_range (fde, &other_low_pc, &func_length,
197 &fde_bytes, &fde_byte_length,
198 &cie_offset, &cie_index,
199 &fde_offset, &err) != DW_DLV_OK)
200 printf ("cannot get range of FDE returned by dwarf_get_fde_at_pc for %u: %s\n",
201 addrs[i], dwarf_errmsg (err));
202 else
203 {
204 printf ("FDE[@%x]: cie_offset = %lld, cie_index = %lld, fde_offset = %lld\n",
205 addrs[i],
206 (long long int) cie_offset,
207 (long long int) cie_index,
208 (long long int) fde_offset);
209
210 if (low_pc != other_low_pc)
211 printf ("low_pc returned by dwarf_get_fde_at_pc for %x and dwarf_get_fde_range differs",
212 addrs[i]);
213
214 if (high_pc != low_pc + func_length - 1)
215 printf ("high_pc returned by dwarf_get_fde_at_pc for %x and dwarf_get_fde_range differs",
216 addrs[i]);
217 }
218 }
219 }
220 }
221
222 if (dwarf_finish (dbg, &err) != DW_DLV_OK)
223 printf ("dwarf_finish failed for %s: %s\n", argv[cnt],
224 dwarf_errmsg (err));
225
226 close (fd);
227 }
228
229 return 0;
230}