rdwarf 0.0.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.gitignore +16 -0
- data/.travis.yml +4 -0
- data/Gemfile +4 -0
- data/LICENSE.txt +28 -0
- data/README.md +39 -0
- data/Rakefile +8 -0
- data/bin/console +14 -0
- data/bin/setup +7 -0
- data/ext/rdwarf/depend +5 -0
- data/ext/rdwarf/extconf.rb +29 -0
- data/ext/rdwarf/libdwarf/CHANGES +102 -0
- data/ext/rdwarf/libdwarf/CODINGSTYLE +71 -0
- data/ext/rdwarf/libdwarf/COPYING +28 -0
- data/ext/rdwarf/libdwarf/ChangeLog +619 -0
- data/ext/rdwarf/libdwarf/ChangeLog2006 +835 -0
- data/ext/rdwarf/libdwarf/ChangeLog2007 +217 -0
- data/ext/rdwarf/libdwarf/ChangeLog2008 +263 -0
- data/ext/rdwarf/libdwarf/ChangeLog2009 +348 -0
- data/ext/rdwarf/libdwarf/ChangeLog2010 +175 -0
- data/ext/rdwarf/libdwarf/ChangeLog2011 +297 -0
- data/ext/rdwarf/libdwarf/ChangeLog2012 +131 -0
- data/ext/rdwarf/libdwarf/ChangeLog2013 +238 -0
- data/ext/rdwarf/libdwarf/ChangeLog2014 +399 -0
- data/ext/rdwarf/libdwarf/LGPL.txt +504 -0
- data/ext/rdwarf/libdwarf/LIBDWARFCOPYRIGHT +40 -0
- data/ext/rdwarf/libdwarf/Makefile.in +220 -0
- data/ext/rdwarf/libdwarf/NEWS +535 -0
- data/ext/rdwarf/libdwarf/README +235 -0
- data/ext/rdwarf/libdwarf/checkexamples.c +1179 -0
- data/ext/rdwarf/libdwarf/cmplrs/dwarf_addr_finder.h +55 -0
- data/ext/rdwarf/libdwarf/common.c +62 -0
- data/ext/rdwarf/libdwarf/common.h +38 -0
- data/ext/rdwarf/libdwarf/config.h.in +146 -0
- data/ext/rdwarf/libdwarf/configure +5581 -0
- data/ext/rdwarf/libdwarf/configure.in +167 -0
- data/ext/rdwarf/libdwarf/dw-linetableheader.txt +39 -0
- data/ext/rdwarf/libdwarf/dwarf.h +1342 -0
- data/ext/rdwarf/libdwarf/dwarf_abbrev.c +291 -0
- data/ext/rdwarf/libdwarf/dwarf_abbrev.h +45 -0
- data/ext/rdwarf/libdwarf/dwarf_addr_finder.c +676 -0
- data/ext/rdwarf/libdwarf/dwarf_alloc.c +685 -0
- data/ext/rdwarf/libdwarf/dwarf_alloc.h +38 -0
- data/ext/rdwarf/libdwarf/dwarf_arange.c +595 -0
- data/ext/rdwarf/libdwarf/dwarf_arange.h +62 -0
- data/ext/rdwarf/libdwarf/dwarf_base_types.h +157 -0
- data/ext/rdwarf/libdwarf/dwarf_die_deliv.c +1802 -0
- data/ext/rdwarf/libdwarf/dwarf_die_deliv.h +46 -0
- data/ext/rdwarf/libdwarf/dwarf_elf_access.c +1348 -0
- data/ext/rdwarf/libdwarf/dwarf_elf_access.h +46 -0
- data/ext/rdwarf/libdwarf/dwarf_error.c +492 -0
- data/ext/rdwarf/libdwarf/dwarf_error.h +53 -0
- data/ext/rdwarf/libdwarf/dwarf_form.c +1302 -0
- data/ext/rdwarf/libdwarf/dwarf_frame.c +2454 -0
- data/ext/rdwarf/libdwarf/dwarf_frame.h +418 -0
- data/ext/rdwarf/libdwarf/dwarf_frame2.c +1533 -0
- data/ext/rdwarf/libdwarf/dwarf_frame3.c +282 -0
- data/ext/rdwarf/libdwarf/dwarf_funcs.c +123 -0
- data/ext/rdwarf/libdwarf/dwarf_funcs.h +33 -0
- data/ext/rdwarf/libdwarf/dwarf_gdbindex.c +520 -0
- data/ext/rdwarf/libdwarf/dwarf_gdbindex.h +97 -0
- data/ext/rdwarf/libdwarf/dwarf_global.c +612 -0
- data/ext/rdwarf/libdwarf/dwarf_global.h +117 -0
- data/ext/rdwarf/libdwarf/dwarf_harmless.c +228 -0
- data/ext/rdwarf/libdwarf/dwarf_harmless.h +31 -0
- data/ext/rdwarf/libdwarf/dwarf_incl.h +61 -0
- data/ext/rdwarf/libdwarf/dwarf_init_finish.c +1263 -0
- data/ext/rdwarf/libdwarf/dwarf_leb.c +159 -0
- data/ext/rdwarf/libdwarf/dwarf_line.c +1822 -0
- data/ext/rdwarf/libdwarf/dwarf_line.h +446 -0
- data/ext/rdwarf/libdwarf/dwarf_line2.c +98 -0
- data/ext/rdwarf/libdwarf/dwarf_line_table_reader_common.c +1583 -0
- data/ext/rdwarf/libdwarf/dwarf_loc.c +1525 -0
- data/ext/rdwarf/libdwarf/dwarf_loc.h +149 -0
- data/ext/rdwarf/libdwarf/dwarf_loc2.c +833 -0
- data/ext/rdwarf/libdwarf/dwarf_macro.c +479 -0
- data/ext/rdwarf/libdwarf/dwarf_macro.h +35 -0
- data/ext/rdwarf/libdwarf/dwarf_opaque.h +778 -0
- data/ext/rdwarf/libdwarf/dwarf_original_elf_init.c +219 -0
- data/ext/rdwarf/libdwarf/dwarf_print_lines.c +631 -0
- data/ext/rdwarf/libdwarf/dwarf_pubtypes.c +132 -0
- data/ext/rdwarf/libdwarf/dwarf_query.c +1594 -0
- data/ext/rdwarf/libdwarf/dwarf_ranges.c +194 -0
- data/ext/rdwarf/libdwarf/dwarf_reloc_arm.h +308 -0
- data/ext/rdwarf/libdwarf/dwarf_reloc_mips.h +117 -0
- data/ext/rdwarf/libdwarf/dwarf_reloc_ppc.h +242 -0
- data/ext/rdwarf/libdwarf/dwarf_reloc_ppc64.h +272 -0
- data/ext/rdwarf/libdwarf/dwarf_reloc_x86_64.h +127 -0
- data/ext/rdwarf/libdwarf/dwarf_sort_line.c +665 -0
- data/ext/rdwarf/libdwarf/dwarf_string.c +82 -0
- data/ext/rdwarf/libdwarf/dwarf_stubs.c +38 -0
- data/ext/rdwarf/libdwarf/dwarf_tied.c +423 -0
- data/ext/rdwarf/libdwarf/dwarf_tsearch.h +125 -0
- data/ext/rdwarf/libdwarf/dwarf_tsearchhash.c +675 -0
- data/ext/rdwarf/libdwarf/dwarf_types.c +121 -0
- data/ext/rdwarf/libdwarf/dwarf_types.h +32 -0
- data/ext/rdwarf/libdwarf/dwarf_util.c +913 -0
- data/ext/rdwarf/libdwarf/dwarf_util.h +324 -0
- data/ext/rdwarf/libdwarf/dwarf_vars.c +125 -0
- data/ext/rdwarf/libdwarf/dwarf_vars.h +29 -0
- data/ext/rdwarf/libdwarf/dwarf_weaks.c +123 -0
- data/ext/rdwarf/libdwarf/dwarf_weaks.h +29 -0
- data/ext/rdwarf/libdwarf/dwarf_xu_index.c +579 -0
- data/ext/rdwarf/libdwarf/dwarf_xu_index.h +68 -0
- data/ext/rdwarf/libdwarf/dwgetopt.c +181 -0
- data/ext/rdwarf/libdwarf/dwgetopt.h +51 -0
- data/ext/rdwarf/libdwarf/gennames.c +531 -0
- data/ext/rdwarf/libdwarf/install.sh +119 -0
- data/ext/rdwarf/libdwarf/libdwarf.h.in +3746 -0
- data/ext/rdwarf/libdwarf/libdwarf2.1.mm +9805 -0
- data/ext/rdwarf/libdwarf/libdwarf2.1.pdf +0 -0
- data/ext/rdwarf/libdwarf/libdwarf2p.1.mm +2807 -0
- data/ext/rdwarf/libdwarf/libdwarf2p.1.pdf +0 -0
- data/ext/rdwarf/libdwarf/libdwarfdefs.h +81 -0
- data/ext/rdwarf/libdwarf/malloc_check.c +327 -0
- data/ext/rdwarf/libdwarf/malloc_check.h +52 -0
- data/ext/rdwarf/libdwarf/mips_extensions.mm +1266 -0
- data/ext/rdwarf/libdwarf/mips_extensions.pdf +0 -0
- data/ext/rdwarf/libdwarf/pro_alloc.c +179 -0
- data/ext/rdwarf/libdwarf/pro_alloc.h +33 -0
- data/ext/rdwarf/libdwarf/pro_arange.c +310 -0
- data/ext/rdwarf/libdwarf/pro_arange.h +51 -0
- data/ext/rdwarf/libdwarf/pro_die.c +431 -0
- data/ext/rdwarf/libdwarf/pro_die.h +59 -0
- data/ext/rdwarf/libdwarf/pro_encode_nm.c +108 -0
- data/ext/rdwarf/libdwarf/pro_encode_nm.h +39 -0
- data/ext/rdwarf/libdwarf/pro_error.c +96 -0
- data/ext/rdwarf/libdwarf/pro_error.h +43 -0
- data/ext/rdwarf/libdwarf/pro_expr.c +575 -0
- data/ext/rdwarf/libdwarf/pro_expr.h +36 -0
- data/ext/rdwarf/libdwarf/pro_finish.c +45 -0
- data/ext/rdwarf/libdwarf/pro_forms.c +1271 -0
- data/ext/rdwarf/libdwarf/pro_frame.c +572 -0
- data/ext/rdwarf/libdwarf/pro_frame.h +120 -0
- data/ext/rdwarf/libdwarf/pro_funcs.c +50 -0
- data/ext/rdwarf/libdwarf/pro_incl.h +91 -0
- data/ext/rdwarf/libdwarf/pro_init.c +327 -0
- data/ext/rdwarf/libdwarf/pro_line.c +373 -0
- data/ext/rdwarf/libdwarf/pro_line.h +112 -0
- data/ext/rdwarf/libdwarf/pro_macinfo.c +457 -0
- data/ext/rdwarf/libdwarf/pro_macinfo.h +31 -0
- data/ext/rdwarf/libdwarf/pro_opaque.h +513 -0
- data/ext/rdwarf/libdwarf/pro_pubnames.c +60 -0
- data/ext/rdwarf/libdwarf/pro_reloc.c +253 -0
- data/ext/rdwarf/libdwarf/pro_reloc.h +38 -0
- data/ext/rdwarf/libdwarf/pro_reloc_stream.c +256 -0
- data/ext/rdwarf/libdwarf/pro_reloc_stream.h +52 -0
- data/ext/rdwarf/libdwarf/pro_reloc_symbolic.c +245 -0
- data/ext/rdwarf/libdwarf/pro_reloc_symbolic.h +45 -0
- data/ext/rdwarf/libdwarf/pro_section.c +2233 -0
- data/ext/rdwarf/libdwarf/pro_section.h +100 -0
- data/ext/rdwarf/libdwarf/pro_types.c +274 -0
- data/ext/rdwarf/libdwarf/pro_types.h +34 -0
- data/ext/rdwarf/libdwarf/pro_util.h +38 -0
- data/ext/rdwarf/libdwarf/pro_vars.c +52 -0
- data/ext/rdwarf/libdwarf/pro_weaks.c +51 -0
- data/ext/rdwarf/rdwarf.c +765 -0
- data/ext/rdwarf/rdwarf.h +52 -0
- data/ext/rdwarf/rdwarf_names_gen.rb +109 -0
- data/lib/rdwarf.rb +181 -0
- data/lib/rdwarf/version.rb +3 -0
- data/rdwarf.gemspec +30 -0
- metadata +251 -0
@@ -0,0 +1,418 @@
|
|
1
|
+
/*
|
2
|
+
|
3
|
+
Copyright (C) 2000, 2004, 2006 Silicon Graphics, Inc. All Rights Reserved.
|
4
|
+
Portions Copyright (C) 2011 David Anderson. All Rights Reserved.
|
5
|
+
|
6
|
+
This program is free software; you can redistribute it and/or modify it
|
7
|
+
under the terms of version 2.1 of the GNU Lesser General Public License
|
8
|
+
as published by the Free Software Foundation.
|
9
|
+
|
10
|
+
This program is distributed in the hope that it would be useful, but
|
11
|
+
WITHOUT ANY WARRANTY; without even the implied warranty of
|
12
|
+
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
13
|
+
|
14
|
+
Further, this software is distributed without any warranty that it is
|
15
|
+
free of the rightful claim of any third person regarding infringement
|
16
|
+
or the like. Any license provided herein, whether implied or
|
17
|
+
otherwise, applies only to this software file. Patent licenses, if
|
18
|
+
any, provided herein do not apply to combinations of this program with
|
19
|
+
other software, or any other product whatsoever.
|
20
|
+
|
21
|
+
You should have received a copy of the GNU Lesser General Public
|
22
|
+
License along with this program; if not, write the Free Software
|
23
|
+
Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston MA 02110-1301,
|
24
|
+
USA.
|
25
|
+
|
26
|
+
*/
|
27
|
+
|
28
|
+
|
29
|
+
|
30
|
+
/* The dwarf 2.0 standard dictates that only the following
|
31
|
+
fields can be read when an unexpected augmentation string
|
32
|
+
(in the cie) is encountered: CIE length, CIE_id, version and
|
33
|
+
augmentation; FDE: length, CIE pointer, initial location and
|
34
|
+
address range. Unfortunately, with the above restrictions, it
|
35
|
+
is impossible to read the instruction table from a CIE or a FDE
|
36
|
+
when a new augmentation string is encountered.
|
37
|
+
To fix this problem, the following layout is used, if the
|
38
|
+
augmentation string starts with the string "z".
|
39
|
+
CIE FDE
|
40
|
+
length length
|
41
|
+
CIE_id CIE_pointer
|
42
|
+
version initial_location
|
43
|
+
augmentation address_range
|
44
|
+
|
45
|
+
- length_of_augmented_fields (*NEW*)
|
46
|
+
code_alignment_factor Any new fields as necessary
|
47
|
+
data_alignment_factor instruction_table
|
48
|
+
return_address
|
49
|
+
length_of_augmented fields
|
50
|
+
Any new fields as necessary
|
51
|
+
initial_instructions
|
52
|
+
|
53
|
+
The type of all the old data items are the same as what is
|
54
|
+
described in dwarf 2.0 standard. The length_of_augmented_fields
|
55
|
+
is an LEB128 data item that denotes the size (in bytes) of
|
56
|
+
the augmented fields (not including the size of
|
57
|
+
"length_of_augmented_fields" itself).
|
58
|
+
|
59
|
+
Handling of cie augmentation strings is necessarly a heuristic.
|
60
|
+
See dwarf_frame.c for the currently known augmentation strings.
|
61
|
+
|
62
|
+
|
63
|
+
---START SGI-ONLY COMMENT:
|
64
|
+
SGI-IRIX versions of cie or fde were intended to use "z1", "z2" as the
|
65
|
+
augmenter strings if required for new augmentation.
|
66
|
+
However, that never happened (as of March 2005).
|
67
|
+
|
68
|
+
The fde's augmented by the string "z" have a new field
|
69
|
+
(signed constant, 4 byte field)
|
70
|
+
called offset_into_exception_tables, following the
|
71
|
+
length_of_augmented field. This field contains an offset
|
72
|
+
into the "_MIPS_eh_region", which describes
|
73
|
+
the IRIX CC exception handling tables.
|
74
|
+
---END SGI-ONLY COMMENT
|
75
|
+
|
76
|
+
|
77
|
+
GNU .eh_frame has an augmentation string of z[RLP]* (gcc 3.4)
|
78
|
+
The similarity to IRIX 'z' (and proposed but never
|
79
|
+
implemented IRIX z1, z2 etc) was confusing things.
|
80
|
+
If the section is .eh_frame then 'z' means GNU exception
|
81
|
+
information 'Augmentation Data' not IRIX 'z'.
|
82
|
+
See The Linux Standard Base Core Specification version 3.0
|
83
|
+
*/
|
84
|
+
|
85
|
+
#define DW_DEBUG_FRAME_VERSION 1 /* DWARF2 */
|
86
|
+
#define DW_DEBUG_FRAME_VERSION3 3 /* DWARF3 */
|
87
|
+
#define DW_DEBUG_FRAME_VERSION4 4 /* DWARF4 */
|
88
|
+
/* The following is SGI/IRIX specific, and probably no longer
|
89
|
+
in use anywhere. */
|
90
|
+
#define DW_DEBUG_FRAME_AUGMENTER_STRING "mti v1"
|
91
|
+
|
92
|
+
/* The value of the offset field for Cie's. */
|
93
|
+
#define DW_CIE_OFFSET ~(0x0)
|
94
|
+
|
95
|
+
/* The augmentation string may be NULL. */
|
96
|
+
#define DW_EMPTY_STRING ""
|
97
|
+
|
98
|
+
#define DW_FRAME_INSTR_OPCODE_SHIFT 6
|
99
|
+
#define DW_FRAME_INSTR_OFFSET_MASK 0x3f
|
100
|
+
|
101
|
+
/*
|
102
|
+
This struct denotes the rule for a register in a row of
|
103
|
+
the frame table. In other words, it is one element of
|
104
|
+
the table.
|
105
|
+
*/
|
106
|
+
struct Dwarf_Reg_Rule_s {
|
107
|
+
|
108
|
+
/* Is a flag indicating whether the rule includes the offset
|
109
|
+
field, ie whether the ru_offset field is valid or not.
|
110
|
+
Applies only if DW_EXPR_OFFSET or DW_EXPR_VAL_OFFSET.
|
111
|
+
It is important, since reg+offset (offset of 0) is different from
|
112
|
+
just 'register' since the former means 'read memory at address
|
113
|
+
given by the sum of register contents plus offset to get the
|
114
|
+
value'. whereas the latter means 'the value is in the register'.
|
115
|
+
|
116
|
+
The 'register' numbers are either real registers (ie, table
|
117
|
+
columns defined as real registers) or defined entries that are
|
118
|
+
not really hardware registers, such as DW_FRAME_SAME_VAL or
|
119
|
+
DW_FRAME_CFA_COL. */
|
120
|
+
Dwarf_Sbyte ru_is_off;
|
121
|
+
|
122
|
+
/* DW_EXPR_OFFSET (0, DWARF2)
|
123
|
+
DW_EXPR_VAL_OFFSET 1 (dwarf2/3)
|
124
|
+
DW_EXPR_EXPRESSION 2 (dwarf2/3)
|
125
|
+
DW_EXPR_VAL_EXPRESSION 3 (dwarf2/3)
|
126
|
+
See dwarf_frame.h. */
|
127
|
+
Dwarf_Sbyte ru_value_type;
|
128
|
+
|
129
|
+
/* Register involved in this rule. */
|
130
|
+
Dwarf_Half ru_register;
|
131
|
+
|
132
|
+
/* Offset to add to register, if indicated by ru_is_offset
|
133
|
+
and if DW_EXPR_OFFSET or DW_EXPR_VAL_OFFSET.
|
134
|
+
If DW_EXPR_EXPRESSION or DW_EXPR_VAL_EXPRESSION
|
135
|
+
this is DW_FORM_block block-length, not offset. */
|
136
|
+
Dwarf_Unsigned ru_offset_or_block_len;
|
137
|
+
|
138
|
+
/* For DW_EXPR_EXPRESSION DW_EXPR_VAL_EXPRESSION these is set,
|
139
|
+
else 0. */
|
140
|
+
Dwarf_Small *ru_block;
|
141
|
+
};
|
142
|
+
|
143
|
+
typedef struct Dwarf_Frame_s *Dwarf_Frame;
|
144
|
+
|
145
|
+
/*
|
146
|
+
This structure represents a row of the frame table.
|
147
|
+
Fr_loc is the pc value for this row, and Fr_reg
|
148
|
+
contains the rule for each column.
|
149
|
+
|
150
|
+
Entry DW_FRAME_CFA_COL of fr_reg was the tradional MIPS
|
151
|
+
way of setting CFA. cfa_rule is the new one.
|
152
|
+
*/
|
153
|
+
struct Dwarf_Frame_s {
|
154
|
+
|
155
|
+
/* Pc value corresponding to this row of the frame table. */
|
156
|
+
Dwarf_Addr fr_loc;
|
157
|
+
|
158
|
+
/* Rules for all the registers in this row. */
|
159
|
+
struct Dwarf_Reg_Rule_s fr_cfa_rule;
|
160
|
+
|
161
|
+
/* fr_reg_count is the the number of
|
162
|
+
entries of the fr_reg array. */
|
163
|
+
unsigned long fr_reg_count;
|
164
|
+
struct Dwarf_Reg_Rule_s *fr_reg;
|
165
|
+
|
166
|
+
Dwarf_Frame fr_next;
|
167
|
+
};
|
168
|
+
|
169
|
+
typedef struct Dwarf_Frame_Op_List_s *Dwarf_Frame_Op_List;
|
170
|
+
|
171
|
+
/* This is used to chain together Dwarf_Frame_Op structures. */
|
172
|
+
struct Dwarf_Frame_Op_List_s {
|
173
|
+
Dwarf_Frame_Op *fl_frame_instr;
|
174
|
+
Dwarf_Frame_Op_List fl_next;
|
175
|
+
};
|
176
|
+
|
177
|
+
/* See dwarf_frame.c for the heuristics used to set the
|
178
|
+
Dwarf_Cie ci_augmentation_type.
|
179
|
+
|
180
|
+
This succinctly helps interpret the size and meaning of .debug_frame
|
181
|
+
and (for gcc) .eh_frame.
|
182
|
+
|
183
|
+
In the case of gcc .eh_frame (gcc 3.3, 3.4)
|
184
|
+
z may be followed by one or more of
|
185
|
+
L R P.
|
186
|
+
|
187
|
+
*/
|
188
|
+
enum Dwarf_augmentation_type {
|
189
|
+
aug_empty_string, /* Default empty augmentation string. */
|
190
|
+
aug_irix_exception_table, /* IRIX plain "z",
|
191
|
+
for exception handling, IRIX CC compiler.
|
192
|
+
Proposed z1 z2 ... never implemented. */
|
193
|
+
aug_gcc_eh_z, /* gcc z augmentation, (including
|
194
|
+
L R P variations). gcc 3.3 3.4 exception
|
195
|
+
handling in eh_frame. */
|
196
|
+
aug_irix_mti_v1, /* IRIX "mti v1" augmentation string. Probably
|
197
|
+
never in any released SGI-IRIX compiler. */
|
198
|
+
aug_eh, /* For gcc .eh_frame, "eh" is the string.,
|
199
|
+
gcc 1,2, egcs. Older values. */
|
200
|
+
aug_armcc, /* "armcc+" meaning the cfa calculation
|
201
|
+
is corrected to be standard (output by
|
202
|
+
Arm C RVCT 3.0 SP1 and later). See
|
203
|
+
http://sourceware.org/ml/gdb-patches/2006-12/msg00249.html
|
204
|
+
for details. */
|
205
|
+
aug_unknown, /* Unknown augmentation, we cannot do much. */
|
206
|
+
aug_past_last
|
207
|
+
};
|
208
|
+
|
209
|
+
|
210
|
+
/*
|
211
|
+
This structure contains all the pertinent info for a Cie. Most
|
212
|
+
of the fields are taken straight from the definition of a Cie.
|
213
|
+
Ci_cie_start points to the address (in .debug_frame) where this
|
214
|
+
Cie begins. Ci_cie_instr_start points to the first byte of the
|
215
|
+
frame instructions for this Cie. Ci_dbg points to the associated
|
216
|
+
Dwarf_Debug structure. Ci_initial_table is a pointer to the table
|
217
|
+
row generated by the instructions for this Cie.
|
218
|
+
*/
|
219
|
+
struct Dwarf_Cie_s {
|
220
|
+
Dwarf_Unsigned ci_length;
|
221
|
+
char *ci_augmentation;
|
222
|
+
Dwarf_Small ci_code_alignment_factor;
|
223
|
+
Dwarf_Sbyte ci_data_alignment_factor;
|
224
|
+
Dwarf_Small ci_return_address_register;
|
225
|
+
Dwarf_Small *ci_cie_start;
|
226
|
+
Dwarf_Small *ci_cie_instr_start;
|
227
|
+
Dwarf_Debug ci_dbg;
|
228
|
+
Dwarf_Frame ci_initial_table;
|
229
|
+
Dwarf_Cie ci_next;
|
230
|
+
Dwarf_Small ci_length_size;
|
231
|
+
Dwarf_Small ci_extension_size;
|
232
|
+
Dwarf_Half ci_cie_version_number;
|
233
|
+
enum Dwarf_augmentation_type ci_augmentation_type;
|
234
|
+
|
235
|
+
/* The following 2 for GNU .eh_frame exception handling
|
236
|
+
Augmentation Data. Set if ci_augmentation_type
|
237
|
+
is aug_gcc_eh_z. Zero if unused. */
|
238
|
+
Dwarf_Unsigned ci_gnu_eh_augmentation_len;
|
239
|
+
Dwarf_Ptr ci_gnu_eh_augmentation_bytes;
|
240
|
+
|
241
|
+
/* These are extracted from the gnu eh_frame
|
242
|
+
augmentation if the
|
243
|
+
augmentation begins with 'z'. See Linux LSB documents.
|
244
|
+
Otherwize these are zero. */
|
245
|
+
unsigned char ci_gnu_personality_handler_encoding;
|
246
|
+
unsigned char ci_gnu_lsda_encoding;
|
247
|
+
unsigned char ci_gnu_fde_begin_encoding;
|
248
|
+
|
249
|
+
/* If 'P' augmentation present, is handler addr. Else
|
250
|
+
is zero. */
|
251
|
+
Dwarf_Addr ci_gnu_personality_handler_addr;
|
252
|
+
|
253
|
+
|
254
|
+
/* In creating list of cie's (which will become an array)
|
255
|
+
record the position so fde can get it on fde creation. */
|
256
|
+
Dwarf_Unsigned ci_index;
|
257
|
+
Dwarf_Small * ci_section_ptr;
|
258
|
+
/* DWARF4 adds address size and segment size to the CIE: the .debug_info
|
259
|
+
section may not always be present to allow libdwarf to
|
260
|
+
find address_size from the compilation-unit. */
|
261
|
+
Dwarf_Half ci_address_size;
|
262
|
+
Dwarf_Half ci_segment_size;
|
263
|
+
|
264
|
+
};
|
265
|
+
|
266
|
+
/*
|
267
|
+
This structure contains all the pertinent info for a Fde.
|
268
|
+
Most of the fields are taken straight from the definition.
|
269
|
+
fd_cie_index is the index of the Cie associated with this
|
270
|
+
Fde in the list of Cie's for this debug_frame. Fd_cie
|
271
|
+
points to the corresponsing Dwarf_Cie structure. Fd_fde_start
|
272
|
+
points to the start address of the Fde. Fd_fde_instr_start
|
273
|
+
points to the start of the instructions for this Fde. Fd_dbg
|
274
|
+
points to the associated Dwarf_Debug structure.
|
275
|
+
*/
|
276
|
+
struct Dwarf_Fde_s {
|
277
|
+
Dwarf_Unsigned fd_length;
|
278
|
+
Dwarf_Addr fd_cie_offset;
|
279
|
+
Dwarf_Unsigned fd_cie_index;
|
280
|
+
Dwarf_Cie fd_cie;
|
281
|
+
Dwarf_Addr fd_initial_location;
|
282
|
+
Dwarf_Small *fd_initial_loc_pos;
|
283
|
+
Dwarf_Addr fd_address_range;
|
284
|
+
Dwarf_Small *fd_fde_start;
|
285
|
+
Dwarf_Small *fd_fde_instr_start;
|
286
|
+
Dwarf_Debug fd_dbg;
|
287
|
+
|
288
|
+
/* fd_offset_into_exception_tables is SGI/IRIX exception table
|
289
|
+
offset. Unused and zero if not IRIX .debug_frame. */
|
290
|
+
Dwarf_Signed fd_offset_into_exception_tables;
|
291
|
+
|
292
|
+
Dwarf_Fde fd_next;
|
293
|
+
Dwarf_Small fd_length_size;
|
294
|
+
Dwarf_Small fd_extension_size;
|
295
|
+
/* So we know from an fde which 'count' of fde-s in
|
296
|
+
Dwarf_Debug applies: eh or standard. */
|
297
|
+
Dwarf_Small fd_is_eh;
|
298
|
+
/* The following 2 for GNU .eh_frame exception handling
|
299
|
+
Augmentation Data. Set if CIE ci_augmentation_type
|
300
|
+
is aug_gcc_eh_z. Zero if unused. */
|
301
|
+
Dwarf_Unsigned fd_gnu_eh_augmentation_len;
|
302
|
+
Dwarf_Ptr fd_gnu_eh_augmentation_bytes;
|
303
|
+
Dwarf_Addr fd_gnu_eh_lsda; /* If 'L' augmentation letter
|
304
|
+
present: is address of the
|
305
|
+
Language Specific Data Area (LSDA). If not 'L" is zero. */
|
306
|
+
|
307
|
+
/* The following 3 are about the Elf section the FDEs come from. */
|
308
|
+
Dwarf_Small * fd_section_ptr;
|
309
|
+
Dwarf_Unsigned fd_section_length;
|
310
|
+
Dwarf_Unsigned fd_section_index;
|
311
|
+
|
312
|
+
};
|
313
|
+
|
314
|
+
|
315
|
+
int
|
316
|
+
_dwarf_frame_address_offsets(Dwarf_Debug dbg, Dwarf_Addr ** addrlist,
|
317
|
+
Dwarf_Off ** offsetlist,
|
318
|
+
Dwarf_Signed * returncount,
|
319
|
+
Dwarf_Error * err);
|
320
|
+
|
321
|
+
int
|
322
|
+
_dwarf_get_fde_list_internal(Dwarf_Debug dbg,
|
323
|
+
Dwarf_Cie ** cie_data,
|
324
|
+
Dwarf_Signed * cie_element_count,
|
325
|
+
Dwarf_Fde ** fde_data,
|
326
|
+
Dwarf_Signed * fde_element_count,
|
327
|
+
Dwarf_Small * section_ptr,
|
328
|
+
Dwarf_Unsigned section_index,
|
329
|
+
Dwarf_Unsigned section_length,
|
330
|
+
Dwarf_Unsigned cie_id_value,
|
331
|
+
int use_gnu_cie_calc, /* If non-zero,
|
332
|
+
this is gcc eh_frame. */
|
333
|
+
Dwarf_Error * error);
|
334
|
+
|
335
|
+
enum Dwarf_augmentation_type
|
336
|
+
_dwarf_get_augmentation_type(Dwarf_Debug dbg,
|
337
|
+
Dwarf_Small *augmentation_string,
|
338
|
+
int is_gcc_eh_frame);
|
339
|
+
|
340
|
+
Dwarf_Unsigned _dwarf_get_return_address_reg(Dwarf_Small *frame_ptr,
|
341
|
+
int version,
|
342
|
+
unsigned long *size);
|
343
|
+
|
344
|
+
/* Temporary recording of crucial cie/fde prefix data.
|
345
|
+
Vastly simplifies some argument lists. */
|
346
|
+
struct cie_fde_prefix_s {
|
347
|
+
/* cf_start_addr is a pointer to the first byte
|
348
|
+
of this fde/cie (meaning the length field itself) */
|
349
|
+
Dwarf_Small * cf_start_addr;
|
350
|
+
/* cf_addr_after_prefix is a pointer
|
351
|
+
to the first byte of this fde/cie
|
352
|
+
we are reading now, immediately following
|
353
|
+
the length field read by READ_AREA_LENGTH. */
|
354
|
+
Dwarf_Small * cf_addr_after_prefix;
|
355
|
+
/* cf_length is the length field value from the cie/fde
|
356
|
+
header. */
|
357
|
+
Dwarf_Unsigned cf_length;
|
358
|
+
int cf_local_length_size;
|
359
|
+
int cf_local_extension_size;
|
360
|
+
Dwarf_Unsigned cf_cie_id;
|
361
|
+
Dwarf_Small * cf_cie_id_addr; /* used for eh_frame calculations. */
|
362
|
+
|
363
|
+
/* Simplifies passing around these values to create fde having
|
364
|
+
these here. */
|
365
|
+
/* cf_section_ptr is a pointer to the first byte
|
366
|
+
of the object section the prefix is read from. */
|
367
|
+
Dwarf_Small * cf_section_ptr;
|
368
|
+
Dwarf_Unsigned cf_section_index;
|
369
|
+
Dwarf_Unsigned cf_section_length;
|
370
|
+
};
|
371
|
+
|
372
|
+
int
|
373
|
+
_dwarf_exec_frame_instr(Dwarf_Bool make_instr,
|
374
|
+
Dwarf_Frame_Op ** ret_frame_instr,
|
375
|
+
Dwarf_Bool search_pc,
|
376
|
+
Dwarf_Addr search_pc_val,
|
377
|
+
Dwarf_Addr initial_loc,
|
378
|
+
Dwarf_Small * start_instr_ptr,
|
379
|
+
Dwarf_Small * final_instr_ptr,
|
380
|
+
Dwarf_Frame table,
|
381
|
+
Dwarf_Cie cie,
|
382
|
+
Dwarf_Debug dbg,
|
383
|
+
Dwarf_Half reg_num_of_cfa,
|
384
|
+
Dwarf_Sword * returned_count,
|
385
|
+
int *returned_error);
|
386
|
+
|
387
|
+
|
388
|
+
int dwarf_read_cie_fde_prefix(Dwarf_Debug dbg,
|
389
|
+
Dwarf_Small *frame_ptr_in,
|
390
|
+
Dwarf_Small *section_ptr_in,
|
391
|
+
Dwarf_Unsigned section_index_in,
|
392
|
+
Dwarf_Unsigned section_length_in,
|
393
|
+
struct cie_fde_prefix_s *prefix_out,
|
394
|
+
Dwarf_Error *error);
|
395
|
+
|
396
|
+
int dwarf_create_fde_from_after_start(Dwarf_Debug dbg,
|
397
|
+
struct cie_fde_prefix_s * prefix,
|
398
|
+
Dwarf_Small *section_pointer,
|
399
|
+
Dwarf_Small *frame_ptr,
|
400
|
+
Dwarf_Small *section_ptr_end,
|
401
|
+
int use_gnu_cie_calc,
|
402
|
+
Dwarf_Cie cie_ptr_in,
|
403
|
+
Dwarf_Fde *fde_ptr_out,
|
404
|
+
Dwarf_Error *error);
|
405
|
+
|
406
|
+
int dwarf_create_cie_from_after_start(Dwarf_Debug dbg,
|
407
|
+
struct cie_fde_prefix_s *prefix,
|
408
|
+
Dwarf_Small* section_pointer,
|
409
|
+
Dwarf_Small* frame_ptr,
|
410
|
+
Dwarf_Small *section_ptr_end,
|
411
|
+
Dwarf_Unsigned cie_count,
|
412
|
+
int use_gnu_cie_calc,
|
413
|
+
Dwarf_Cie *cie_ptr_out,
|
414
|
+
Dwarf_Error *error);
|
415
|
+
|
416
|
+
|
417
|
+
int _dwarf_frame_constructor(Dwarf_Debug dbg,void * );
|
418
|
+
void _dwarf_frame_destructor (void *);
|
@@ -0,0 +1,1533 @@
|
|
1
|
+
/*
|
2
|
+
|
3
|
+
Copyright (C) 2000-2006 Silicon Graphics, Inc. All Rights Reserved.
|
4
|
+
Portions Copyright (C) 2007-2012 David Anderson. All Rights Reserved.
|
5
|
+
Portions Copyright (C) 2010-2012 SN Systems Ltd. All Rights Reserved.
|
6
|
+
|
7
|
+
This program is free software; you can redistribute it and/or modify it
|
8
|
+
under the terms of version 2.1 of the GNU Lesser General Public License
|
9
|
+
as published by the Free Software Foundation.
|
10
|
+
|
11
|
+
This program is distributed in the hope that it would be useful, but
|
12
|
+
WITHOUT ANY WARRANTY; without even the implied warranty of
|
13
|
+
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
14
|
+
|
15
|
+
Further, this software is distributed without any warranty that it is
|
16
|
+
free of the rightful claim of any third person regarding infringement
|
17
|
+
or the like. Any license provided herein, whether implied or
|
18
|
+
otherwise, applies only to this software file. Patent licenses, if
|
19
|
+
any, provided herein do not apply to combinations of this program with
|
20
|
+
other software, or any other product whatsoever.
|
21
|
+
|
22
|
+
You should have received a copy of the GNU Lesser General Public
|
23
|
+
License along with this program; if not, write the Free Software
|
24
|
+
Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston MA 02110-1301,
|
25
|
+
USA.
|
26
|
+
|
27
|
+
*/
|
28
|
+
|
29
|
+
/* This implements _dwarf_get_fde_list_internal()
|
30
|
+
and related helper functions for reading cie/fde data. */
|
31
|
+
|
32
|
+
#include "config.h"
|
33
|
+
#include "dwarf_incl.h"
|
34
|
+
#include <stdio.h>
|
35
|
+
#include <stdlib.h>
|
36
|
+
#include "dwarf_frame.h"
|
37
|
+
#include "dwarf_arange.h" /* using Arange as a way to build a list */
|
38
|
+
|
39
|
+
|
40
|
+
static int dwarf_find_existing_cie_ptr(Dwarf_Small * cie_ptr,
|
41
|
+
Dwarf_Cie cur_cie_ptr,
|
42
|
+
Dwarf_Cie * cie_ptr_to_use_out,
|
43
|
+
Dwarf_Cie head_cie_ptr);
|
44
|
+
static void dealloc_fde_cie_list_internal(Dwarf_Fde head_fde_ptr,
|
45
|
+
Dwarf_Cie head_cie_ptr);
|
46
|
+
static int dwarf_create_cie_from_start(Dwarf_Debug dbg,
|
47
|
+
Dwarf_Small * cie_ptr_val,
|
48
|
+
Dwarf_Small * section_ptr,
|
49
|
+
Dwarf_Unsigned section_index,
|
50
|
+
Dwarf_Unsigned section_length,
|
51
|
+
Dwarf_Small * section_ptr_end,
|
52
|
+
Dwarf_Unsigned cie_id_value,
|
53
|
+
Dwarf_Unsigned cie_count,
|
54
|
+
int use_gnu_cie_calc,
|
55
|
+
Dwarf_Cie * cie_ptr_to_use_out,
|
56
|
+
Dwarf_Error * error);
|
57
|
+
|
58
|
+
static Dwarf_Small *get_cieptr_given_offset(Dwarf_Unsigned cie_id_value,
|
59
|
+
int use_gnu_cie_calc,
|
60
|
+
Dwarf_Small * section_ptr,
|
61
|
+
Dwarf_Small * cie_id_addr);
|
62
|
+
static int get_gcc_eh_augmentation(Dwarf_Debug dbg,
|
63
|
+
Dwarf_Small * frame_ptr,
|
64
|
+
unsigned long
|
65
|
+
*size_of_augmentation_data,
|
66
|
+
enum Dwarf_augmentation_type augtype,
|
67
|
+
Dwarf_Small * section_pointer,
|
68
|
+
Dwarf_Small * fde_eh_encoding_out,
|
69
|
+
char *augmentation,
|
70
|
+
Dwarf_Error *error);
|
71
|
+
|
72
|
+
static int
|
73
|
+
gnu_aug_encodings(Dwarf_Debug dbg, char *augmentation,
|
74
|
+
Dwarf_Small * aug_data, Dwarf_Unsigned aug_data_len,
|
75
|
+
Dwarf_Half address_size,
|
76
|
+
unsigned char *pers_hand_enc_out,
|
77
|
+
unsigned char *lsda_enc_out,
|
78
|
+
unsigned char *fde_begin_enc_out,
|
79
|
+
Dwarf_Addr * gnu_pers_addr_out,
|
80
|
+
Dwarf_Error *error);
|
81
|
+
|
82
|
+
|
83
|
+
static int read_encoded_ptr(Dwarf_Debug dbg,
|
84
|
+
Dwarf_Small * section_pointer,
|
85
|
+
Dwarf_Small * input_field,
|
86
|
+
int gnu_encoding,
|
87
|
+
Dwarf_Half address_size,
|
88
|
+
Dwarf_Unsigned * addr,
|
89
|
+
Dwarf_Small ** input_field_out,
|
90
|
+
Dwarf_Error *error);
|
91
|
+
|
92
|
+
|
93
|
+
|
94
|
+
static int qsort_compare(const void *elem1, const void *elem2);
|
95
|
+
|
96
|
+
|
97
|
+
/* Adds 'newone' to the end of the list starting at 'head'
|
98
|
+
and makes the new one 'cur'rent. */
|
99
|
+
static void
|
100
|
+
chain_up_fde(Dwarf_Fde newone, Dwarf_Fde * head, Dwarf_Fde * cur)
|
101
|
+
{
|
102
|
+
if (*head == NULL)
|
103
|
+
*head = newone;
|
104
|
+
else {
|
105
|
+
(*cur)->fd_next = newone;
|
106
|
+
}
|
107
|
+
*cur = newone;
|
108
|
+
|
109
|
+
}
|
110
|
+
|
111
|
+
/* Adds 'newone' to the end of the list starting at 'head'
|
112
|
+
and makes the new one 'cur'rent. */
|
113
|
+
static void
|
114
|
+
chain_up_cie(Dwarf_Cie newone, Dwarf_Cie * head, Dwarf_Cie * cur)
|
115
|
+
{
|
116
|
+
if (*head == NULL) {
|
117
|
+
*head = newone;
|
118
|
+
} else {
|
119
|
+
(*cur)->ci_next = newone;
|
120
|
+
}
|
121
|
+
*cur = newone;
|
122
|
+
}
|
123
|
+
|
124
|
+
/* The size of the length field plus the
|
125
|
+
value of length must be an integral
|
126
|
+
multiple of the address size. Dwarf4 standard.
|
127
|
+
|
128
|
+
A constant that gives the number of bytes of the CIE
|
129
|
+
structure, not including the length field itself
|
130
|
+
(where length mod <size of an address> == 0)
|
131
|
+
(see Section 7.2.2). Dwarf3 standard.
|
132
|
+
|
133
|
+
A uword constant that gives the number of bytes of
|
134
|
+
the CIE structure, not including the
|
135
|
+
length field, itself (length mod <addressing unit size> == 0).
|
136
|
+
Dwarf2 standard.*/
|
137
|
+
static void
|
138
|
+
validate_length(Dwarf_Debug dbg,
|
139
|
+
Dwarf_Cie cieptr, Dwarf_Unsigned length,
|
140
|
+
Dwarf_Unsigned length_size,
|
141
|
+
Dwarf_Unsigned extension_size,
|
142
|
+
Dwarf_Small * section_ptr,
|
143
|
+
Dwarf_Small * ciefde_start,
|
144
|
+
const char * cieorfde)
|
145
|
+
{
|
146
|
+
Dwarf_Unsigned address_size = cieptr->ci_address_size;
|
147
|
+
Dwarf_Unsigned length_field_summed = length_size + extension_size;
|
148
|
+
Dwarf_Unsigned total_len = length + length_field_summed;
|
149
|
+
Dwarf_Unsigned mod = total_len % address_size;
|
150
|
+
|
151
|
+
if (mod != 0) {
|
152
|
+
char msg[DW_HARMLESS_ERROR_MSG_STRING_SIZE];
|
153
|
+
Dwarf_Unsigned sectionoffset = ciefde_start - section_ptr;
|
154
|
+
snprintf(msg,sizeof(msg),
|
155
|
+
"DW_DLE_DEBUG_FRAME_LENGTH_NOT_MULTIPLE"
|
156
|
+
" len=0x%" DW_PR_XZEROS DW_PR_DUx
|
157
|
+
", len size=0x%" DW_PR_XZEROS DW_PR_DUx
|
158
|
+
", extn size=0x%" DW_PR_XZEROS DW_PR_DUx
|
159
|
+
", totl length=0x%" DW_PR_XZEROS DW_PR_DUx
|
160
|
+
", addr size=0x%" DW_PR_XZEROS DW_PR_DUx
|
161
|
+
", mod=0x%" DW_PR_XZEROS DW_PR_DUx " must be zero"
|
162
|
+
" in %s"
|
163
|
+
", offset 0x%" DW_PR_XZEROS DW_PR_DUx ".",
|
164
|
+
length,
|
165
|
+
length_size,
|
166
|
+
extension_size,
|
167
|
+
total_len,address_size, mod,
|
168
|
+
cieorfde,
|
169
|
+
sectionoffset);
|
170
|
+
dwarf_insert_harmless_error(dbg,msg);
|
171
|
+
}
|
172
|
+
return;
|
173
|
+
}
|
174
|
+
|
175
|
+
|
176
|
+
#if 0 /* FOR DEBUGGING */
|
177
|
+
/* For debugging only. */
|
178
|
+
static void
|
179
|
+
print_prefix(struct cie_fde_prefix_s *prefix, int line)
|
180
|
+
{
|
181
|
+
printf("prefix-print, prefix at 0x%lx, line %d\n",
|
182
|
+
(long) prefix, line);
|
183
|
+
printf(" start addr 0x%lx after prefix 0x%lx\n",
|
184
|
+
(long) prefix->cf_start_addr,
|
185
|
+
(long) prefix->cf_addr_after_prefix);
|
186
|
+
printf(" length 0x%" DW_PR_DUx ", len size %d ext size %d\n",
|
187
|
+
(Dwarf_Unsigned) prefix->cf_length,
|
188
|
+
prefix->cf_local_length_size,
|
189
|
+
prefix->cf_local_extension_size);
|
190
|
+
printf(" cie_id 0x%" DW_PR_DUx " cie_id cie_id_addr 0x%lx\n",
|
191
|
+
(Dwarf_Unsigned) prefix->cf_cie_id,
|
192
|
+
(long) prefix->cf_cie_id_addr);
|
193
|
+
printf
|
194
|
+
(" sec ptr 0x%lx sec index %" DW_PR_DSd " sec len 0x%" DW_PR_DUx " sec past end 0x%lx\n",
|
195
|
+
(long) prefix->cf_section_ptr,
|
196
|
+
(Dwarf_Signed) prefix->cf_section_index,
|
197
|
+
(Dwarf_Unsigned) prefix->cf_section_length,
|
198
|
+
(long) prefix->cf_section_ptr + prefix->cf_section_length);
|
199
|
+
}
|
200
|
+
#endif
|
201
|
+
|
202
|
+
|
203
|
+
|
204
|
+
/* Internal function called from various places to create
|
205
|
+
lists of CIEs and FDEs. Not directly called
|
206
|
+
by consumer code */
|
207
|
+
int
|
208
|
+
_dwarf_get_fde_list_internal(Dwarf_Debug dbg, Dwarf_Cie ** cie_data,
|
209
|
+
Dwarf_Signed * cie_element_count,
|
210
|
+
Dwarf_Fde ** fde_data,
|
211
|
+
Dwarf_Signed * fde_element_count,
|
212
|
+
Dwarf_Small * section_ptr,
|
213
|
+
Dwarf_Unsigned section_index,
|
214
|
+
Dwarf_Unsigned section_length,
|
215
|
+
Dwarf_Unsigned cie_id_value,
|
216
|
+
int use_gnu_cie_calc, Dwarf_Error * error)
|
217
|
+
{
|
218
|
+
/* Scans the debug_frame section. */
|
219
|
+
Dwarf_Small *frame_ptr = section_ptr;
|
220
|
+
Dwarf_Small *section_ptr_end = section_ptr + section_length;
|
221
|
+
|
222
|
+
|
223
|
+
|
224
|
+
/* New_cie points to the Cie being read, and head_cie_ptr and
|
225
|
+
cur_cie_ptr are used for chaining them up in sequence.
|
226
|
+
In case cie's are reused aggressively we need tail_cie_ptr
|
227
|
+
to add to the chain. If we re-use an early cie
|
228
|
+
later on, that does not mean we chain a new cie to the early one,
|
229
|
+
we always chain it to the tail. */
|
230
|
+
Dwarf_Cie head_cie_ptr = NULL;
|
231
|
+
Dwarf_Cie cur_cie_ptr = NULL;
|
232
|
+
Dwarf_Cie tail_cie_ptr = NULL;
|
233
|
+
Dwarf_Word cie_count = 0;
|
234
|
+
|
235
|
+
/* Points to a list of contiguous pointers to Dwarf_Cie structures.
|
236
|
+
*/
|
237
|
+
Dwarf_Cie *cie_list_ptr = 0;
|
238
|
+
|
239
|
+
|
240
|
+
/* New_fde points to the Fde being created, and head_fde_ptr and
|
241
|
+
cur_fde_ptr are used to chain them up. */
|
242
|
+
Dwarf_Fde head_fde_ptr = NULL;
|
243
|
+
Dwarf_Fde cur_fde_ptr = NULL;
|
244
|
+
Dwarf_Word fde_count = 0;
|
245
|
+
|
246
|
+
/* Points to a list of contiguous pointers to Dwarf_Fde structures.
|
247
|
+
*/
|
248
|
+
Dwarf_Fde *fde_list_ptr = NULL;
|
249
|
+
|
250
|
+
Dwarf_Word i = 0;
|
251
|
+
int res = DW_DLV_ERROR;
|
252
|
+
|
253
|
+
if (frame_ptr == 0) {
|
254
|
+
return DW_DLV_NO_ENTRY;
|
255
|
+
}
|
256
|
+
|
257
|
+
/* We create the fde and cie arrays. Processing each CIE as we come
|
258
|
+
to it or as an FDE refers to it. We cannot process 'late' CIEs
|
259
|
+
late as GNU .eh_frame complexities mean we need the whole CIE
|
260
|
+
before we can process the FDE correctly. */
|
261
|
+
while (frame_ptr < section_ptr_end) {
|
262
|
+
|
263
|
+
struct cie_fde_prefix_s prefix;
|
264
|
+
|
265
|
+
/* First read in the 'common prefix' to figure out what we are
|
266
|
+
to do with this entry. */
|
267
|
+
memset(&prefix, 0, sizeof(prefix));
|
268
|
+
res = dwarf_read_cie_fde_prefix(dbg,
|
269
|
+
frame_ptr, section_ptr,
|
270
|
+
section_index,
|
271
|
+
section_length, &prefix, error);
|
272
|
+
if (res == DW_DLV_ERROR) {
|
273
|
+
dealloc_fde_cie_list_internal(head_fde_ptr, head_cie_ptr);
|
274
|
+
return res;
|
275
|
+
}
|
276
|
+
if (res == DW_DLV_NO_ENTRY)
|
277
|
+
break;
|
278
|
+
frame_ptr = prefix.cf_addr_after_prefix;
|
279
|
+
if (frame_ptr >= section_ptr_end) {
|
280
|
+
dealloc_fde_cie_list_internal(head_fde_ptr, head_cie_ptr);
|
281
|
+
_dwarf_error(dbg, error, DW_DLE_DEBUG_FRAME_LENGTH_BAD);
|
282
|
+
return DW_DLV_ERROR;
|
283
|
+
}
|
284
|
+
|
285
|
+
if (prefix.cf_cie_id == cie_id_value) {
|
286
|
+
/* This is a CIE. */
|
287
|
+
Dwarf_Cie cie_ptr_to_use = 0;
|
288
|
+
|
289
|
+
int resc = dwarf_find_existing_cie_ptr(prefix.cf_start_addr,
|
290
|
+
cur_cie_ptr,
|
291
|
+
&cie_ptr_to_use,
|
292
|
+
head_cie_ptr);
|
293
|
+
if (resc == DW_DLV_OK) {
|
294
|
+
cur_cie_ptr = cie_ptr_to_use;
|
295
|
+
/* Ok. Seen already. */
|
296
|
+
} else if (resc == DW_DLV_NO_ENTRY) {
|
297
|
+
/* CIE before its FDE in this case. */
|
298
|
+
resc = dwarf_create_cie_from_after_start(dbg,
|
299
|
+
&prefix,
|
300
|
+
section_ptr,
|
301
|
+
frame_ptr,
|
302
|
+
section_ptr_end,
|
303
|
+
cie_count,
|
304
|
+
use_gnu_cie_calc,
|
305
|
+
&cie_ptr_to_use,
|
306
|
+
error);
|
307
|
+
/* ASSERT: res==DW_DLV_NO_ENTRY impossible. */
|
308
|
+
if (resc == DW_DLV_ERROR) {
|
309
|
+
dealloc_fde_cie_list_internal(head_fde_ptr,
|
310
|
+
head_cie_ptr);
|
311
|
+
return resc;
|
312
|
+
}
|
313
|
+
/* ASSERT res != DW_DLV_NO_ENTRY */
|
314
|
+
cie_count++;
|
315
|
+
chain_up_cie(cie_ptr_to_use, &head_cie_ptr,
|
316
|
+
&tail_cie_ptr);
|
317
|
+
cur_cie_ptr = tail_cie_ptr;
|
318
|
+
} else { /* res == DW_DLV_ERROR */
|
319
|
+
|
320
|
+
dealloc_fde_cie_list_internal(head_fde_ptr,
|
321
|
+
head_cie_ptr);
|
322
|
+
return resc;
|
323
|
+
}
|
324
|
+
frame_ptr = cie_ptr_to_use->ci_cie_start +
|
325
|
+
cie_ptr_to_use->ci_length +
|
326
|
+
cie_ptr_to_use->ci_length_size +
|
327
|
+
cie_ptr_to_use->ci_extension_size;
|
328
|
+
continue;
|
329
|
+
} else {
|
330
|
+
/* This is an FDE, Frame Description Entry, see the Dwarf
|
331
|
+
Spec, section 6.4.1 */
|
332
|
+
int resf = DW_DLV_ERROR;
|
333
|
+
Dwarf_Cie cie_ptr_to_use = 0;
|
334
|
+
Dwarf_Fde fde_ptr_to_use = 0;
|
335
|
+
|
336
|
+
/* Do not call this twice on one prefix, as
|
337
|
+
prefix.cf_cie_id_addr is altered as a side effect. */
|
338
|
+
Dwarf_Small *cieptr_val =
|
339
|
+
get_cieptr_given_offset(prefix.cf_cie_id,
|
340
|
+
use_gnu_cie_calc,
|
341
|
+
section_ptr,
|
342
|
+
prefix.cf_cie_id_addr);
|
343
|
+
|
344
|
+
resf = dwarf_find_existing_cie_ptr(cieptr_val,
|
345
|
+
cur_cie_ptr,
|
346
|
+
&cie_ptr_to_use,
|
347
|
+
head_cie_ptr);
|
348
|
+
if (resf == DW_DLV_OK) {
|
349
|
+
cur_cie_ptr = cie_ptr_to_use;
|
350
|
+
/* Ok. Seen CIE already. */
|
351
|
+
} else if (resf == DW_DLV_NO_ENTRY) {
|
352
|
+
resf = dwarf_create_cie_from_start(dbg,
|
353
|
+
cieptr_val,
|
354
|
+
section_ptr,
|
355
|
+
section_index,
|
356
|
+
section_length,
|
357
|
+
section_ptr_end,
|
358
|
+
cie_id_value,
|
359
|
+
cie_count,
|
360
|
+
use_gnu_cie_calc,
|
361
|
+
&cie_ptr_to_use,
|
362
|
+
error);
|
363
|
+
if (resf == DW_DLV_ERROR) {
|
364
|
+
dealloc_fde_cie_list_internal(head_fde_ptr,
|
365
|
+
head_cie_ptr);
|
366
|
+
return resf;
|
367
|
+
} else if (res == DW_DLV_NO_ENTRY) {
|
368
|
+
return resf;
|
369
|
+
}
|
370
|
+
++cie_count;
|
371
|
+
chain_up_cie(cie_ptr_to_use, &head_cie_ptr,
|
372
|
+
&tail_cie_ptr);
|
373
|
+
cur_cie_ptr = tail_cie_ptr;
|
374
|
+
|
375
|
+
} else {
|
376
|
+
/* DW_DLV_ERROR */
|
377
|
+
return resf;
|
378
|
+
}
|
379
|
+
|
380
|
+
resf = dwarf_create_fde_from_after_start(dbg,
|
381
|
+
&prefix,
|
382
|
+
section_ptr,
|
383
|
+
frame_ptr,
|
384
|
+
section_ptr_end,
|
385
|
+
use_gnu_cie_calc,
|
386
|
+
cie_ptr_to_use,
|
387
|
+
&fde_ptr_to_use,
|
388
|
+
error);
|
389
|
+
if (resf == DW_DLV_ERROR) {
|
390
|
+
return resf;
|
391
|
+
}
|
392
|
+
chain_up_fde(fde_ptr_to_use, &head_fde_ptr, &cur_fde_ptr);
|
393
|
+
fde_count++;
|
394
|
+
/* ASSERT: DW_DLV_OK. */
|
395
|
+
frame_ptr = fde_ptr_to_use->fd_fde_start +
|
396
|
+
fde_ptr_to_use->fd_length +
|
397
|
+
fde_ptr_to_use->fd_length_size +
|
398
|
+
fde_ptr_to_use->fd_extension_size;
|
399
|
+
if (frame_ptr < fde_ptr_to_use->fd_fde_instr_start) {
|
400
|
+
/* Sanity check. With a really short fde instruction
|
401
|
+
set and address_size we think is 8
|
402
|
+
as it is ELF64 (but is
|
403
|
+
really 4, as in DWARF{2,3} where we have
|
404
|
+
no FDE address_size) we emit an error.
|
405
|
+
This error means things will not go well. */
|
406
|
+
_dwarf_error(dbg,error,
|
407
|
+
DW_DLE_DEBUG_FRAME_POSSIBLE_ADDRESS_BOTCH);
|
408
|
+
return DW_DLV_ERROR;
|
409
|
+
}
|
410
|
+
|
411
|
+
|
412
|
+
continue;
|
413
|
+
}
|
414
|
+
}
|
415
|
+
/* Now build list of CIEs from the list. If there are no CIEs
|
416
|
+
there should be no FDEs. */
|
417
|
+
if (cie_count > 0) {
|
418
|
+
cie_list_ptr = (Dwarf_Cie *)
|
419
|
+
_dwarf_get_alloc(dbg, DW_DLA_LIST, cie_count);
|
420
|
+
} else {
|
421
|
+
if (fde_count > 0) {
|
422
|
+
dealloc_fde_cie_list_internal(head_fde_ptr, head_cie_ptr);
|
423
|
+
_dwarf_error(dbg, error, DW_DLE_ORPHAN_FDE);
|
424
|
+
return DW_DLV_ERROR;
|
425
|
+
}
|
426
|
+
dealloc_fde_cie_list_internal(head_fde_ptr, head_cie_ptr);
|
427
|
+
return DW_DLV_NO_ENTRY;
|
428
|
+
}
|
429
|
+
if (cie_list_ptr == NULL) {
|
430
|
+
dealloc_fde_cie_list_internal(head_fde_ptr, head_cie_ptr);
|
431
|
+
_dwarf_error(dbg, error, DW_DLE_ALLOC_FAIL);
|
432
|
+
return DW_DLV_ERROR;
|
433
|
+
}
|
434
|
+
cur_cie_ptr = head_cie_ptr;
|
435
|
+
for (i = 0; i < cie_count; i++) {
|
436
|
+
*(cie_list_ptr + i) = cur_cie_ptr;
|
437
|
+
cur_cie_ptr = cur_cie_ptr->ci_next;
|
438
|
+
}
|
439
|
+
|
440
|
+
/* Now build array of FDEs from the list.
|
441
|
+
With orphan CIEs (meaning no FDEs)
|
442
|
+
lets not return DW_DLV_NO_ENTRY */
|
443
|
+
if (fde_count > 0) {
|
444
|
+
fde_list_ptr = (Dwarf_Fde *)
|
445
|
+
_dwarf_get_alloc(dbg, DW_DLA_LIST, fde_count);
|
446
|
+
}
|
447
|
+
|
448
|
+
/* It is ok if fde_list_ptr is NULL, we just have no fdes. */
|
449
|
+
cur_fde_ptr = head_fde_ptr;
|
450
|
+
for (i = 0; i < fde_count; i++) {
|
451
|
+
*(fde_list_ptr + i) = cur_fde_ptr;
|
452
|
+
cur_fde_ptr = cur_fde_ptr->fd_next;
|
453
|
+
}
|
454
|
+
|
455
|
+
|
456
|
+
/* Return arguments. */
|
457
|
+
*cie_data = cie_list_ptr;
|
458
|
+
*cie_element_count = cie_count;
|
459
|
+
|
460
|
+
*fde_data = fde_list_ptr;
|
461
|
+
*fde_element_count = fde_count;
|
462
|
+
if (use_gnu_cie_calc) {
|
463
|
+
dbg->de_fde_data_eh = fde_list_ptr;
|
464
|
+
dbg->de_fde_count_eh = fde_count;
|
465
|
+
dbg->de_cie_data_eh = cie_list_ptr;
|
466
|
+
dbg->de_cie_count_eh = cie_count;
|
467
|
+
} else {
|
468
|
+
dbg->de_fde_data = fde_list_ptr;
|
469
|
+
dbg->de_fde_count = fde_count;
|
470
|
+
dbg->de_cie_data = cie_list_ptr;
|
471
|
+
dbg->de_cie_count = cie_count;
|
472
|
+
}
|
473
|
+
|
474
|
+
/* Sort the list by the address so that dwarf_get_fde_at_pc() can
|
475
|
+
binary search this list. */
|
476
|
+
if (fde_count > 0) {
|
477
|
+
qsort((void *) fde_list_ptr, fde_count, sizeof(Dwarf_Ptr),
|
478
|
+
qsort_compare);
|
479
|
+
}
|
480
|
+
|
481
|
+
return (DW_DLV_OK);
|
482
|
+
}
|
483
|
+
|
484
|
+
/* Internal function, not called by consumer code.
|
485
|
+
'prefix' has accumulated the info up thru the cie-id
|
486
|
+
and now we consume the rest and build a Dwarf_Cie_s structure.
|
487
|
+
*/
|
488
|
+
int
|
489
|
+
dwarf_create_cie_from_after_start(Dwarf_Debug dbg,
|
490
|
+
struct cie_fde_prefix_s *prefix,
|
491
|
+
Dwarf_Small * section_pointer,
|
492
|
+
Dwarf_Small * frame_ptr,
|
493
|
+
Dwarf_Small * section_ptr_end,
|
494
|
+
Dwarf_Unsigned cie_count,
|
495
|
+
int use_gnu_cie_calc,
|
496
|
+
Dwarf_Cie * cie_ptr_out,
|
497
|
+
Dwarf_Error * error)
|
498
|
+
{
|
499
|
+
Dwarf_Cie new_cie = 0;
|
500
|
+
|
501
|
+
/* egcs-1.1.2 .eh_frame uses 0 as the distinguishing id. sgi uses
|
502
|
+
-1 (in .debug_frame). .eh_frame not quite identical to
|
503
|
+
.debug_frame */
|
504
|
+
/* We here default the address size as it is not present
|
505
|
+
in DWARF2 or DWARF3 cie data, below we set it right if
|
506
|
+
it is present. */
|
507
|
+
Dwarf_Half address_size = dbg->de_pointer_size;
|
508
|
+
Dwarf_Small eh_fde_encoding = 0;
|
509
|
+
Dwarf_Small *augmentation = 0;
|
510
|
+
Dwarf_Half segment_size = 0;
|
511
|
+
Dwarf_Sword data_alignment_factor = -1;
|
512
|
+
Dwarf_Word code_alignment_factor = 4;
|
513
|
+
Dwarf_Unsigned return_address_register = 31;
|
514
|
+
int local_length_size = 0;
|
515
|
+
Dwarf_Word leb128_length = 0;
|
516
|
+
Dwarf_Unsigned cie_aug_data_len = 0;
|
517
|
+
Dwarf_Small *cie_aug_data = 0;
|
518
|
+
Dwarf_Addr gnu_personality_handler_addr = 0;
|
519
|
+
unsigned char gnu_personality_handler_encoding = 0;
|
520
|
+
unsigned char gnu_lsda_encoding = 0;
|
521
|
+
unsigned char gnu_fde_begin_encoding = 0;
|
522
|
+
int res = 0;
|
523
|
+
|
524
|
+
|
525
|
+
enum Dwarf_augmentation_type augt = aug_unknown;
|
526
|
+
|
527
|
+
|
528
|
+
/* This is a CIE, Common Information Entry: See the dwarf spec,
|
529
|
+
section 6.4.1 */
|
530
|
+
Dwarf_Small version = *(Dwarf_Small *) frame_ptr;
|
531
|
+
|
532
|
+
frame_ptr++;
|
533
|
+
if (version != DW_CIE_VERSION && version != DW_CIE_VERSION3 &&
|
534
|
+
version != DW_CIE_VERSION4) {
|
535
|
+
_dwarf_error(dbg, error, DW_DLE_FRAME_VERSION_BAD);
|
536
|
+
return (DW_DLV_ERROR);
|
537
|
+
}
|
538
|
+
|
539
|
+
augmentation = frame_ptr;
|
540
|
+
|
541
|
+
res = _dwarf_check_string_valid(dbg,section_pointer,
|
542
|
+
frame_ptr,section_ptr_end,error);
|
543
|
+
if (res != DW_DLV_OK) {
|
544
|
+
return res;
|
545
|
+
}
|
546
|
+
frame_ptr = frame_ptr + strlen((char *) frame_ptr) + 1;
|
547
|
+
augt = _dwarf_get_augmentation_type(dbg,
|
548
|
+
augmentation, use_gnu_cie_calc);
|
549
|
+
if (augt == aug_eh) {
|
550
|
+
/* REFERENCED *//* Not used in this instance */
|
551
|
+
Dwarf_Unsigned exception_table_addr;
|
552
|
+
|
553
|
+
/* this is per egcs-1.1.2 as on RH 6.0 */
|
554
|
+
READ_UNALIGNED(dbg, exception_table_addr,
|
555
|
+
Dwarf_Unsigned, frame_ptr, local_length_size);
|
556
|
+
frame_ptr += local_length_size;
|
557
|
+
}
|
558
|
+
{
|
559
|
+
Dwarf_Unsigned lreg = 0;
|
560
|
+
unsigned long size = 0;
|
561
|
+
|
562
|
+
if (version == DW_CIE_VERSION4) {
|
563
|
+
address_size = *((unsigned char *)frame_ptr);
|
564
|
+
if (address_size > sizeof(Dwarf_Addr)) {
|
565
|
+
_dwarf_error(dbg, error, DW_DLE_ADDRESS_SIZE_ERROR);
|
566
|
+
return (DW_DLV_ERROR);
|
567
|
+
}
|
568
|
+
++frame_ptr;
|
569
|
+
segment_size = *((unsigned char *)frame_ptr);
|
570
|
+
++frame_ptr;
|
571
|
+
if (segment_size > sizeof(Dwarf_Addr)) {
|
572
|
+
_dwarf_error(dbg, error, DW_DLE_SEGMENT_SIZE_BAD);
|
573
|
+
return (DW_DLV_ERROR);
|
574
|
+
}
|
575
|
+
}
|
576
|
+
|
577
|
+
DECODE_LEB128_UWORD(frame_ptr, lreg);
|
578
|
+
code_alignment_factor = (Dwarf_Word) lreg;
|
579
|
+
data_alignment_factor =
|
580
|
+
(Dwarf_Sword) _dwarf_decode_s_leb128(frame_ptr,
|
581
|
+
&leb128_length);
|
582
|
+
frame_ptr = frame_ptr + leb128_length;
|
583
|
+
return_address_register =
|
584
|
+
_dwarf_get_return_address_reg(frame_ptr, version, &size);
|
585
|
+
if (return_address_register > dbg->de_frame_reg_rules_entry_count) {
|
586
|
+
_dwarf_error(dbg, error, DW_DLE_CIE_RET_ADDR_REG_ERROR);
|
587
|
+
return (DW_DLV_ERROR);
|
588
|
+
}
|
589
|
+
frame_ptr += size;
|
590
|
+
}
|
591
|
+
switch (augt) {
|
592
|
+
case aug_empty_string:
|
593
|
+
break;
|
594
|
+
case aug_irix_mti_v1:
|
595
|
+
break;
|
596
|
+
case aug_irix_exception_table:{
|
597
|
+
Dwarf_Unsigned lreg = 0;
|
598
|
+
Dwarf_Word length_of_augmented_fields;
|
599
|
+
|
600
|
+
/* Decode the length of augmented fields. */
|
601
|
+
DECODE_LEB128_UWORD(frame_ptr, lreg);
|
602
|
+
length_of_augmented_fields = (Dwarf_Word) lreg;
|
603
|
+
/* set the frame_ptr to point at the instruction start. */
|
604
|
+
frame_ptr += length_of_augmented_fields;
|
605
|
+
}
|
606
|
+
break;
|
607
|
+
|
608
|
+
case aug_eh:{
|
609
|
+
int err = 0;
|
610
|
+
unsigned long increment = 0;
|
611
|
+
|
612
|
+
if (!use_gnu_cie_calc) {
|
613
|
+
/* This should be impossible. */
|
614
|
+
_dwarf_error(dbg, error,DW_DLE_FRAME_AUGMENTATION_UNKNOWN);
|
615
|
+
return DW_DLV_ERROR;
|
616
|
+
}
|
617
|
+
|
618
|
+
err = get_gcc_eh_augmentation(dbg, frame_ptr, &increment,
|
619
|
+
augt,
|
620
|
+
prefix->cf_section_ptr,
|
621
|
+
&eh_fde_encoding,
|
622
|
+
(char *) augmentation,error);
|
623
|
+
if (err == DW_DLV_ERROR) {
|
624
|
+
_dwarf_error(dbg, error,DW_DLE_FRAME_AUGMENTATION_UNKNOWN);
|
625
|
+
return DW_DLV_ERROR;
|
626
|
+
}
|
627
|
+
frame_ptr += increment;
|
628
|
+
}
|
629
|
+
break;
|
630
|
+
case aug_gcc_eh_z:{
|
631
|
+
/* Here we have Augmentation Data Length (uleb128) followed
|
632
|
+
by Augmentation Data bytes. */
|
633
|
+
int res = DW_DLV_ERROR;
|
634
|
+
Dwarf_Unsigned adlen = 0;
|
635
|
+
|
636
|
+
DECODE_LEB128_UWORD(frame_ptr, adlen);
|
637
|
+
cie_aug_data_len = adlen;
|
638
|
+
cie_aug_data = frame_ptr;
|
639
|
+
res = gnu_aug_encodings(dbg,
|
640
|
+
(char *) augmentation,
|
641
|
+
cie_aug_data,
|
642
|
+
cie_aug_data_len,
|
643
|
+
address_size,
|
644
|
+
&gnu_personality_handler_encoding,
|
645
|
+
&gnu_lsda_encoding,
|
646
|
+
&gnu_fde_begin_encoding,
|
647
|
+
&gnu_personality_handler_addr,
|
648
|
+
error);
|
649
|
+
if (res != DW_DLV_OK) {
|
650
|
+
_dwarf_error(dbg, error,
|
651
|
+
DW_DLE_FRAME_AUGMENTATION_UNKNOWN);
|
652
|
+
return res;
|
653
|
+
}
|
654
|
+
frame_ptr += adlen;
|
655
|
+
}
|
656
|
+
break;
|
657
|
+
case aug_armcc:
|
658
|
+
break;
|
659
|
+
default:{
|
660
|
+
/* We do not understand the augmentation string. No
|
661
|
+
assumption can be made about any fields other than what
|
662
|
+
we have already read. */
|
663
|
+
frame_ptr = prefix->cf_start_addr +
|
664
|
+
prefix->cf_length + prefix->cf_local_length_size
|
665
|
+
+ prefix->cf_local_extension_size;
|
666
|
+
/* FIX -- What are the values of data_alignment_factor,
|
667
|
+
code_alignement_factor, return_address_register and
|
668
|
+
instruction start? They were clearly uninitalized in the
|
669
|
+
previous version and I am leaving them the same way. */
|
670
|
+
}
|
671
|
+
break;
|
672
|
+
} /* End switch on augmentation type. */
|
673
|
+
|
674
|
+
new_cie = (Dwarf_Cie) _dwarf_get_alloc(dbg, DW_DLA_CIE, 1);
|
675
|
+
if (new_cie == NULL) {
|
676
|
+
_dwarf_error(dbg, error, DW_DLE_ALLOC_FAIL);
|
677
|
+
return (DW_DLV_ERROR);
|
678
|
+
}
|
679
|
+
|
680
|
+
new_cie->ci_cie_version_number = version;
|
681
|
+
new_cie->ci_initial_table = NULL;
|
682
|
+
new_cie->ci_length = (Dwarf_Word) prefix->cf_length;
|
683
|
+
new_cie->ci_length_size = prefix->cf_local_length_size;
|
684
|
+
new_cie->ci_extension_size = prefix->cf_local_extension_size;
|
685
|
+
new_cie->ci_augmentation = (char *) augmentation;
|
686
|
+
|
687
|
+
new_cie->ci_data_alignment_factor =
|
688
|
+
(Dwarf_Sbyte) data_alignment_factor;
|
689
|
+
new_cie->ci_code_alignment_factor =
|
690
|
+
(Dwarf_Small) code_alignment_factor;
|
691
|
+
new_cie->ci_return_address_register = return_address_register;
|
692
|
+
new_cie->ci_cie_start = prefix->cf_start_addr;
|
693
|
+
new_cie->ci_cie_instr_start = frame_ptr;
|
694
|
+
new_cie->ci_dbg = dbg;
|
695
|
+
new_cie->ci_augmentation_type = augt;
|
696
|
+
new_cie->ci_gnu_eh_augmentation_len = cie_aug_data_len;
|
697
|
+
new_cie->ci_gnu_eh_augmentation_bytes = cie_aug_data;
|
698
|
+
new_cie->ci_gnu_personality_handler_encoding =
|
699
|
+
gnu_personality_handler_encoding;
|
700
|
+
new_cie->ci_gnu_personality_handler_addr =
|
701
|
+
gnu_personality_handler_addr;
|
702
|
+
new_cie->ci_gnu_lsda_encoding = gnu_lsda_encoding;
|
703
|
+
new_cie->ci_gnu_fde_begin_encoding = gnu_fde_begin_encoding;
|
704
|
+
|
705
|
+
new_cie->ci_index = cie_count;
|
706
|
+
new_cie->ci_section_ptr = prefix->cf_section_ptr;
|
707
|
+
/* The Following new in DWARF4 */
|
708
|
+
new_cie->ci_address_size = address_size;
|
709
|
+
new_cie->ci_segment_size = segment_size;
|
710
|
+
validate_length(dbg,new_cie,new_cie->ci_length,
|
711
|
+
new_cie->ci_length_size, new_cie->ci_extension_size,
|
712
|
+
new_cie->ci_section_ptr,
|
713
|
+
new_cie->ci_cie_start,"cie");
|
714
|
+
|
715
|
+
*cie_ptr_out = new_cie;
|
716
|
+
return DW_DLV_OK;
|
717
|
+
|
718
|
+
}
|
719
|
+
|
720
|
+
|
721
|
+
/* Internal function, not called by consumer code.
|
722
|
+
'prefix' has accumulated the info up thru the cie-id
|
723
|
+
and now we consume the rest and build a Dwarf_Fde_s structure. */
|
724
|
+
|
725
|
+
int
|
726
|
+
dwarf_create_fde_from_after_start(Dwarf_Debug dbg,
|
727
|
+
struct cie_fde_prefix_s *prefix,
|
728
|
+
Dwarf_Small * section_pointer,
|
729
|
+
Dwarf_Small * frame_ptr,
|
730
|
+
Dwarf_Small * section_ptr_end,
|
731
|
+
int use_gnu_cie_calc,
|
732
|
+
Dwarf_Cie cie_ptr_in,
|
733
|
+
Dwarf_Fde * fde_ptr_out,
|
734
|
+
Dwarf_Error * error)
|
735
|
+
{
|
736
|
+
Dwarf_Fde new_fde = 0;
|
737
|
+
Dwarf_Cie cieptr = cie_ptr_in;
|
738
|
+
Dwarf_Small *saved_frame_ptr = 0;
|
739
|
+
|
740
|
+
Dwarf_Small *initloc = frame_ptr;
|
741
|
+
Dwarf_Signed offset_into_exception_tables
|
742
|
+
/* must be min dwarf_sfixed in size */
|
743
|
+
= (Dwarf_Signed) DW_DLX_NO_EH_OFFSET;
|
744
|
+
Dwarf_Small *fde_aug_data = 0;
|
745
|
+
Dwarf_Unsigned fde_aug_data_len = 0;
|
746
|
+
Dwarf_Addr cie_base_offset = prefix->cf_cie_id;
|
747
|
+
Dwarf_Addr initial_location = 0; /* must be min de_pointer_size
|
748
|
+
bytes in size */
|
749
|
+
Dwarf_Addr address_range = 0; /* must be min de_pointer_size
|
750
|
+
bytes in size */
|
751
|
+
Dwarf_Half address_size = cie_ptr_in->ci_address_size;
|
752
|
+
|
753
|
+
enum Dwarf_augmentation_type augt = cieptr->ci_augmentation_type;
|
754
|
+
|
755
|
+
if (augt == aug_gcc_eh_z) {
|
756
|
+
/* If z augmentation this is eh_frame, and initial_location and
|
757
|
+
address_range in the FDE are read according to the CIE
|
758
|
+
augmentation string instructions. */
|
759
|
+
|
760
|
+
{
|
761
|
+
Dwarf_Small *fp_updated = 0;
|
762
|
+
int res = read_encoded_ptr(dbg,
|
763
|
+
section_pointer,
|
764
|
+
frame_ptr,
|
765
|
+
cieptr-> ci_gnu_fde_begin_encoding,
|
766
|
+
address_size,
|
767
|
+
&initial_location,
|
768
|
+
&fp_updated,error);
|
769
|
+
if (res != DW_DLV_OK) {
|
770
|
+
return res;
|
771
|
+
}
|
772
|
+
frame_ptr = fp_updated;
|
773
|
+
/* For the address-range it makes no sense to be
|
774
|
+
pc-relative, so we turn it off with a section_pointer of
|
775
|
+
NULL. Masking off DW_EH_PE_pcrel from the
|
776
|
+
ci_gnu_fde_begin_encoding in this call would also work
|
777
|
+
to turn off DW_EH_PE_pcrel. */
|
778
|
+
res = read_encoded_ptr(dbg, (Dwarf_Small *) NULL,
|
779
|
+
frame_ptr,
|
780
|
+
cieptr->ci_gnu_fde_begin_encoding,
|
781
|
+
address_size,
|
782
|
+
&address_range, &fp_updated,error);
|
783
|
+
if (res != DW_DLV_OK) {
|
784
|
+
return res;
|
785
|
+
}
|
786
|
+
frame_ptr = fp_updated;
|
787
|
+
}
|
788
|
+
{
|
789
|
+
Dwarf_Unsigned adlen = 0;
|
790
|
+
|
791
|
+
DECODE_LEB128_UWORD(frame_ptr, adlen);
|
792
|
+
fde_aug_data_len = adlen;
|
793
|
+
fde_aug_data = frame_ptr;
|
794
|
+
frame_ptr += adlen;
|
795
|
+
}
|
796
|
+
|
797
|
+
} else {
|
798
|
+
READ_UNALIGNED(dbg, initial_location, Dwarf_Addr,
|
799
|
+
frame_ptr, address_size);
|
800
|
+
frame_ptr += address_size;
|
801
|
+
READ_UNALIGNED(dbg, address_range, Dwarf_Addr,
|
802
|
+
frame_ptr, address_size);
|
803
|
+
frame_ptr += address_size;
|
804
|
+
}
|
805
|
+
switch (augt) {
|
806
|
+
case aug_irix_mti_v1:
|
807
|
+
case aug_empty_string:
|
808
|
+
break;
|
809
|
+
case aug_irix_exception_table:{
|
810
|
+
Dwarf_Unsigned lreg = 0;
|
811
|
+
Dwarf_Word length_of_augmented_fields = 0;
|
812
|
+
|
813
|
+
DECODE_LEB128_UWORD(frame_ptr, lreg);
|
814
|
+
length_of_augmented_fields = (Dwarf_Word) lreg;
|
815
|
+
|
816
|
+
saved_frame_ptr = frame_ptr;
|
817
|
+
/* The first word is an offset into exception tables.
|
818
|
+
Defined as a 32bit offset even for CC -64. */
|
819
|
+
READ_UNALIGNED(dbg, offset_into_exception_tables,
|
820
|
+
Dwarf_Addr, frame_ptr, sizeof(Dwarf_sfixed));
|
821
|
+
SIGN_EXTEND(offset_into_exception_tables,
|
822
|
+
sizeof(Dwarf_sfixed));
|
823
|
+
frame_ptr = saved_frame_ptr + length_of_augmented_fields;
|
824
|
+
}
|
825
|
+
break;
|
826
|
+
case aug_eh:{
|
827
|
+
Dwarf_Unsigned eh_table_value = 0;
|
828
|
+
|
829
|
+
if (!use_gnu_cie_calc) {
|
830
|
+
/* This should be impossible. */
|
831
|
+
_dwarf_error(dbg, error,DW_DLE_FRAME_AUGMENTATION_UNKNOWN);
|
832
|
+
return DW_DLV_ERROR;
|
833
|
+
}
|
834
|
+
|
835
|
+
/* gnu eh fde case. we do not need to do anything */
|
836
|
+
/*REFERENCED*/ /* Not used in this instance of the macro */
|
837
|
+
READ_UNALIGNED(dbg, eh_table_value,
|
838
|
+
Dwarf_Unsigned, frame_ptr,
|
839
|
+
address_size);
|
840
|
+
frame_ptr += address_size;
|
841
|
+
}
|
842
|
+
break;
|
843
|
+
|
844
|
+
case aug_gcc_eh_z:{
|
845
|
+
/* The Augmentation Data Length is here, followed by the
|
846
|
+
Augmentation Data bytes themselves. */
|
847
|
+
}
|
848
|
+
break;
|
849
|
+
case aug_armcc:
|
850
|
+
break;
|
851
|
+
case aug_past_last:
|
852
|
+
break;
|
853
|
+
case aug_unknown:
|
854
|
+
_dwarf_error(dbg, error, DW_DLE_FRAME_AUGMENTATION_UNKNOWN);
|
855
|
+
return DW_DLV_ERROR;
|
856
|
+
} /* End switch on augmentation type */
|
857
|
+
new_fde = (Dwarf_Fde) _dwarf_get_alloc(dbg, DW_DLA_FDE, 1);
|
858
|
+
if (new_fde == NULL) {
|
859
|
+
_dwarf_error(dbg, error, DW_DLE_ALLOC_FAIL);
|
860
|
+
return (DW_DLV_ERROR);
|
861
|
+
}
|
862
|
+
|
863
|
+
new_fde->fd_length = prefix->cf_length;
|
864
|
+
new_fde->fd_length_size = prefix->cf_local_length_size;
|
865
|
+
new_fde->fd_extension_size = prefix->cf_local_extension_size;
|
866
|
+
new_fde->fd_is_eh = use_gnu_cie_calc;
|
867
|
+
new_fde->fd_cie_offset = cie_base_offset;
|
868
|
+
new_fde->fd_cie_index = cieptr->ci_index;
|
869
|
+
new_fde->fd_cie = cieptr;
|
870
|
+
new_fde->fd_initial_location = initial_location;
|
871
|
+
new_fde->fd_initial_loc_pos = initloc;
|
872
|
+
new_fde->fd_address_range = address_range;
|
873
|
+
new_fde->fd_fde_start = prefix->cf_start_addr;
|
874
|
+
new_fde->fd_fde_instr_start = frame_ptr;
|
875
|
+
new_fde->fd_dbg = dbg;
|
876
|
+
new_fde->fd_offset_into_exception_tables =
|
877
|
+
offset_into_exception_tables;
|
878
|
+
|
879
|
+
new_fde->fd_section_ptr = prefix->cf_section_ptr;
|
880
|
+
new_fde->fd_section_index = prefix->cf_section_index;
|
881
|
+
new_fde->fd_section_length = prefix->cf_section_length;
|
882
|
+
|
883
|
+
new_fde->fd_gnu_eh_augmentation_bytes = fde_aug_data;
|
884
|
+
new_fde->fd_gnu_eh_augmentation_len = fde_aug_data_len;
|
885
|
+
validate_length(dbg,cieptr,new_fde->fd_length,
|
886
|
+
new_fde->fd_length_size, new_fde->fd_extension_size,
|
887
|
+
new_fde->fd_section_ptr,new_fde->fd_fde_start,"fde");
|
888
|
+
|
889
|
+
|
890
|
+
*fde_ptr_out = new_fde;
|
891
|
+
return DW_DLV_OK;
|
892
|
+
}
|
893
|
+
|
894
|
+
/* Called by qsort to compare FDE entries.
|
895
|
+
Consumer code expects the array of FDE pointers to be
|
896
|
+
in address order.
|
897
|
+
*/
|
898
|
+
static int
|
899
|
+
qsort_compare(const void *elem1, const void *elem2)
|
900
|
+
{
|
901
|
+
const Dwarf_Fde fde1 = *(const Dwarf_Fde *) elem1;
|
902
|
+
const Dwarf_Fde fde2 = *(const Dwarf_Fde *) elem2;
|
903
|
+
Dwarf_Addr addr1 = fde1->fd_initial_location;
|
904
|
+
Dwarf_Addr addr2 = fde2->fd_initial_location;
|
905
|
+
|
906
|
+
if (addr1 < addr2) {
|
907
|
+
return -1;
|
908
|
+
} else if (addr1 > addr2) {
|
909
|
+
return 1;
|
910
|
+
}
|
911
|
+
return 0;
|
912
|
+
}
|
913
|
+
|
914
|
+
|
915
|
+
/* Read in the common cie/fde prefix, including reading
|
916
|
+
the cie-value which shows which this is: cie or fde. */
|
917
|
+
int
|
918
|
+
dwarf_read_cie_fde_prefix(Dwarf_Debug dbg,
|
919
|
+
Dwarf_Small * frame_ptr_in,
|
920
|
+
Dwarf_Small * section_ptr_in,
|
921
|
+
Dwarf_Unsigned section_index_in,
|
922
|
+
Dwarf_Unsigned section_length_in,
|
923
|
+
struct cie_fde_prefix_s *data_out,
|
924
|
+
Dwarf_Error * error)
|
925
|
+
{
|
926
|
+
Dwarf_Unsigned length = 0;
|
927
|
+
int local_length_size = 0;
|
928
|
+
int local_extension_size = 0;
|
929
|
+
Dwarf_Small *frame_ptr = frame_ptr_in;
|
930
|
+
Dwarf_Small *cie_ptr_addr = 0;
|
931
|
+
Dwarf_Unsigned cie_id = 0;
|
932
|
+
|
933
|
+
/* READ_AREA_LENGTH updates frame_ptr for consumed bytes */
|
934
|
+
READ_AREA_LENGTH(dbg, length, Dwarf_Unsigned,
|
935
|
+
frame_ptr, local_length_size,
|
936
|
+
local_extension_size);
|
937
|
+
|
938
|
+
if (length == 0) {
|
939
|
+
/* nul bytes at end of section, seen at end of egcs eh_frame
|
940
|
+
sections (in a.out). Take this as meaning no more CIE/FDE
|
941
|
+
data. We should be very close to end of section. */
|
942
|
+
return DW_DLV_NO_ENTRY;
|
943
|
+
}
|
944
|
+
|
945
|
+
cie_ptr_addr = frame_ptr;
|
946
|
+
READ_UNALIGNED(dbg, cie_id, Dwarf_Unsigned,
|
947
|
+
frame_ptr, local_length_size);
|
948
|
+
SIGN_EXTEND(cie_id, local_length_size);
|
949
|
+
frame_ptr += local_length_size;
|
950
|
+
|
951
|
+
data_out->cf_start_addr = frame_ptr_in;
|
952
|
+
data_out->cf_addr_after_prefix = frame_ptr;
|
953
|
+
|
954
|
+
data_out->cf_length = length;
|
955
|
+
data_out->cf_local_length_size = local_length_size;
|
956
|
+
data_out->cf_local_extension_size = local_extension_size;
|
957
|
+
data_out->cf_cie_id = cie_id;
|
958
|
+
data_out->cf_cie_id_addr = cie_ptr_addr;
|
959
|
+
data_out->cf_section_ptr = section_ptr_in;
|
960
|
+
data_out->cf_section_index = section_index_in;
|
961
|
+
data_out->cf_section_length = section_length_in;
|
962
|
+
return DW_DLV_OK;
|
963
|
+
}
|
964
|
+
|
965
|
+
/* On various errors previously-allocated CIEs and FDEs
|
966
|
+
must be cleaned up.
|
967
|
+
This helps avoid leaks in case of errors.
|
968
|
+
*/
|
969
|
+
static void
|
970
|
+
dealloc_fde_cie_list_internal(Dwarf_Fde head_fde_ptr,
|
971
|
+
Dwarf_Cie head_cie_ptr)
|
972
|
+
{
|
973
|
+
Dwarf_Fde curfde = 0;
|
974
|
+
Dwarf_Cie curcie = 0;
|
975
|
+
Dwarf_Fde nextfde = 0;
|
976
|
+
Dwarf_Cie nextcie = 0;
|
977
|
+
|
978
|
+
for (curfde = head_fde_ptr; curfde; curfde = nextfde) {
|
979
|
+
nextfde = curfde->fd_next;
|
980
|
+
dwarf_dealloc(curfde->fd_dbg, curfde, DW_DLA_FDE);
|
981
|
+
}
|
982
|
+
for (curcie = head_cie_ptr; curcie; curcie = nextcie) {
|
983
|
+
Dwarf_Frame frame = curcie->ci_initial_table;
|
984
|
+
|
985
|
+
nextcie = curcie->ci_next;
|
986
|
+
if (frame)
|
987
|
+
dwarf_dealloc(curcie->ci_dbg, frame, DW_DLA_FRAME);
|
988
|
+
dwarf_dealloc(curcie->ci_dbg, curcie, DW_DLA_CIE);
|
989
|
+
}
|
990
|
+
}
|
991
|
+
|
992
|
+
/* Find the cie whose id value is given: the id
|
993
|
+
value is, per DWARF2/3, an offset in the section.
|
994
|
+
For .debug_frame, zero is a legal offset. For
|
995
|
+
GNU .eh_frame it is not a legal offset.
|
996
|
+
'cie_ptr' is a pointer into our section, not an offset. */
|
997
|
+
static int
|
998
|
+
dwarf_find_existing_cie_ptr(Dwarf_Small * cie_ptr,
|
999
|
+
Dwarf_Cie cur_cie_ptr,
|
1000
|
+
Dwarf_Cie * cie_ptr_to_use_out,
|
1001
|
+
Dwarf_Cie head_cie_ptr)
|
1002
|
+
{
|
1003
|
+
Dwarf_Cie next = 0;
|
1004
|
+
|
1005
|
+
if (cur_cie_ptr && cie_ptr == cur_cie_ptr->ci_cie_start) {
|
1006
|
+
/* Usually, we use the same cie again and again. */
|
1007
|
+
*cie_ptr_to_use_out = cur_cie_ptr;
|
1008
|
+
return DW_DLV_OK;
|
1009
|
+
}
|
1010
|
+
for (next = head_cie_ptr; next; next = next->ci_next) {
|
1011
|
+
if (cie_ptr == next->ci_cie_start) {
|
1012
|
+
*cie_ptr_to_use_out = next;
|
1013
|
+
return DW_DLV_OK;
|
1014
|
+
}
|
1015
|
+
}
|
1016
|
+
return DW_DLV_NO_ENTRY;
|
1017
|
+
}
|
1018
|
+
|
1019
|
+
|
1020
|
+
/* We have a valid cie_ptr_val that has not been
|
1021
|
+
turned into an internal Cie yet. Do so now.
|
1022
|
+
Returns DW_DLV_OK or DW_DLV_ERROR, never
|
1023
|
+
DW_DLV_NO_ENTRY.
|
1024
|
+
|
1025
|
+
'section_ptr' - Points to first byte of section data.
|
1026
|
+
'section_length' - Length of the section, in bytes.
|
1027
|
+
'section_ptr_end' - Points 1-past last byte of section data. */
|
1028
|
+
static int
|
1029
|
+
dwarf_create_cie_from_start(Dwarf_Debug dbg,
|
1030
|
+
Dwarf_Small * cie_ptr_val,
|
1031
|
+
Dwarf_Small * section_ptr,
|
1032
|
+
Dwarf_Unsigned section_index,
|
1033
|
+
Dwarf_Unsigned section_length,
|
1034
|
+
Dwarf_Small * section_ptr_end,
|
1035
|
+
Dwarf_Unsigned cie_id_value,
|
1036
|
+
Dwarf_Unsigned cie_count,
|
1037
|
+
int use_gnu_cie_calc,
|
1038
|
+
Dwarf_Cie * cie_ptr_to_use_out,
|
1039
|
+
Dwarf_Error * error)
|
1040
|
+
{
|
1041
|
+
struct cie_fde_prefix_s prefix;
|
1042
|
+
int res = DW_DLV_ERROR;
|
1043
|
+
Dwarf_Small *frame_ptr = cie_ptr_val;
|
1044
|
+
|
1045
|
+
if (frame_ptr < section_ptr || frame_ptr >= section_ptr_end) {
|
1046
|
+
_dwarf_error(dbg, error, DW_DLE_DEBUG_FRAME_LENGTH_BAD);
|
1047
|
+
return DW_DLV_ERROR;
|
1048
|
+
}
|
1049
|
+
/* First read in the 'common prefix' to figure out what * we are to
|
1050
|
+
do with this entry. If it is not a cie * we are in big trouble. */
|
1051
|
+
memset(&prefix, 0, sizeof(prefix));
|
1052
|
+
res = dwarf_read_cie_fde_prefix(dbg, frame_ptr, section_ptr,
|
1053
|
+
section_index, section_length,
|
1054
|
+
&prefix, error);
|
1055
|
+
if (res == DW_DLV_ERROR) {
|
1056
|
+
return res;
|
1057
|
+
}
|
1058
|
+
if (res == DW_DLV_NO_ENTRY) {
|
1059
|
+
/* error. */
|
1060
|
+
_dwarf_error(dbg, error, DW_DLE_FRAME_CIE_DECODE_ERROR);
|
1061
|
+
return DW_DLV_ERROR;
|
1062
|
+
|
1063
|
+
}
|
1064
|
+
|
1065
|
+
if (prefix.cf_cie_id != cie_id_value) {
|
1066
|
+
_dwarf_error(dbg, error, DW_DLE_FRAME_CIE_DECODE_ERROR);
|
1067
|
+
return DW_DLV_ERROR;
|
1068
|
+
}
|
1069
|
+
frame_ptr = prefix.cf_addr_after_prefix;
|
1070
|
+
res = dwarf_create_cie_from_after_start(dbg,
|
1071
|
+
&prefix,
|
1072
|
+
section_ptr,
|
1073
|
+
frame_ptr,
|
1074
|
+
section_ptr_end,
|
1075
|
+
cie_count,
|
1076
|
+
use_gnu_cie_calc,
|
1077
|
+
cie_ptr_to_use_out, error);
|
1078
|
+
return res;
|
1079
|
+
|
1080
|
+
}
|
1081
|
+
|
1082
|
+
|
1083
|
+
/* This is for gnu eh frames, the 'z' case.
|
1084
|
+
We find the letter involved
|
1085
|
+
Return the augmentation character and, if applicable,
|
1086
|
+
the personality routine address.
|
1087
|
+
|
1088
|
+
personality_routine_out -
|
1089
|
+
if 'P' is augchar, is personality handler addr.
|
1090
|
+
Otherwise is not set.
|
1091
|
+
aug_data - if 'P' points to data space of the
|
1092
|
+
aug_data_len - length of areas aug_data points to.
|
1093
|
+
|
1094
|
+
*/
|
1095
|
+
#if 0 /* FOR DEBUGGING */
|
1096
|
+
/* For debugging only. */
|
1097
|
+
void
|
1098
|
+
dump_bytes(Dwarf_Small * start, long len)
|
1099
|
+
{
|
1100
|
+
Dwarf_Small *end = start + len;
|
1101
|
+
Dwarf_Small *cur = start;
|
1102
|
+
|
1103
|
+
for (; cur < end; cur++) {
|
1104
|
+
printf(" byte %d, data %02x\n", (int) (cur - start), *cur);
|
1105
|
+
}
|
1106
|
+
|
1107
|
+
}
|
1108
|
+
#endif
|
1109
|
+
static int
|
1110
|
+
gnu_aug_encodings(Dwarf_Debug dbg, char *augmentation,
|
1111
|
+
Dwarf_Small * aug_data, Dwarf_Unsigned aug_data_len,
|
1112
|
+
Dwarf_Half address_size,
|
1113
|
+
unsigned char *pers_hand_enc_out,
|
1114
|
+
unsigned char *lsda_enc_out,
|
1115
|
+
unsigned char *fde_begin_enc_out,
|
1116
|
+
Dwarf_Addr * gnu_pers_addr_out,
|
1117
|
+
Dwarf_Error * error)
|
1118
|
+
{
|
1119
|
+
char *nc = 0;
|
1120
|
+
Dwarf_Small *cur_aug_p = aug_data;
|
1121
|
+
Dwarf_Small *end_aug_p = aug_data + aug_data_len;
|
1122
|
+
|
1123
|
+
for (nc = augmentation; *nc; ++nc) {
|
1124
|
+
char c = *nc;
|
1125
|
+
|
1126
|
+
switch (c) {
|
1127
|
+
case 'z':
|
1128
|
+
/* Means that the augmentation data is present. */
|
1129
|
+
continue;
|
1130
|
+
|
1131
|
+
case 'S':
|
1132
|
+
/* Indicates this is a signal stack frame.
|
1133
|
+
Debuggers have to do
|
1134
|
+
special handling. We don't need to do more than
|
1135
|
+
print this flag at the right time, though
|
1136
|
+
(see dwarfdump where it prints the augmentation
|
1137
|
+
string).
|
1138
|
+
A signal stack frame (in some OS's) can only be
|
1139
|
+
unwound (backtraced) by knowing it is a signal
|
1140
|
+
stack frame (perhaps by noticing the name of the
|
1141
|
+
function for the stack frame if the name can be
|
1142
|
+
found somehow) and figuring
|
1143
|
+
out (or knowing) how the kernel and libc
|
1144
|
+
pushed a structure
|
1145
|
+
onto the stack and loading registers from that structure.
|
1146
|
+
Totally different from normal stack unwinding.
|
1147
|
+
This flag gives an unwinder a big leg up by
|
1148
|
+
decoupling the 'hint: this is a stack frame'
|
1149
|
+
from knowledge like
|
1150
|
+
the function name (the name might be
|
1151
|
+
unavailable at unwind time).
|
1152
|
+
*/
|
1153
|
+
break;
|
1154
|
+
|
1155
|
+
case 'L':
|
1156
|
+
if (cur_aug_p > end_aug_p) {
|
1157
|
+
_dwarf_error(dbg, error, DW_DLE_FRAME_AUGMENTATION_UNKNOWN);
|
1158
|
+
return DW_DLV_ERROR;
|
1159
|
+
}
|
1160
|
+
*lsda_enc_out = *(unsigned char *) cur_aug_p;
|
1161
|
+
++cur_aug_p;
|
1162
|
+
break;
|
1163
|
+
case 'R':
|
1164
|
+
/* Followed by a one byte argument giving the
|
1165
|
+
pointer encoding for the address pointers in the fde. */
|
1166
|
+
if (cur_aug_p >= end_aug_p) {
|
1167
|
+
_dwarf_error(dbg, error, DW_DLE_FRAME_AUGMENTATION_UNKNOWN);
|
1168
|
+
return DW_DLV_ERROR;
|
1169
|
+
}
|
1170
|
+
*fde_begin_enc_out = *(unsigned char *) cur_aug_p;
|
1171
|
+
++cur_aug_p;
|
1172
|
+
break;
|
1173
|
+
case 'P':{
|
1174
|
+
int res = DW_DLV_ERROR;
|
1175
|
+
Dwarf_Small *updated_aug_p = 0;
|
1176
|
+
unsigned char encoding = 0;
|
1177
|
+
|
1178
|
+
if (cur_aug_p >= end_aug_p) {
|
1179
|
+
_dwarf_error(dbg, error, DW_DLE_FRAME_AUGMENTATION_UNKNOWN);
|
1180
|
+
return DW_DLV_ERROR;
|
1181
|
+
}
|
1182
|
+
encoding = *(unsigned char *) cur_aug_p;
|
1183
|
+
*pers_hand_enc_out = encoding;
|
1184
|
+
++cur_aug_p;
|
1185
|
+
if (cur_aug_p > end_aug_p) {
|
1186
|
+
_dwarf_error(dbg, error, DW_DLE_FRAME_AUGMENTATION_UNKNOWN);
|
1187
|
+
return DW_DLV_ERROR;
|
1188
|
+
}
|
1189
|
+
/* DW_EH_PE_pcrel makes no sense here, so we turn it
|
1190
|
+
off via a section pointer of NULL. */
|
1191
|
+
res = read_encoded_ptr(dbg,
|
1192
|
+
(Dwarf_Small *) NULL,
|
1193
|
+
cur_aug_p,
|
1194
|
+
encoding,
|
1195
|
+
address_size,
|
1196
|
+
gnu_pers_addr_out,
|
1197
|
+
&updated_aug_p,
|
1198
|
+
error);
|
1199
|
+
if (res != DW_DLV_OK) {
|
1200
|
+
return res;
|
1201
|
+
}
|
1202
|
+
cur_aug_p = updated_aug_p;
|
1203
|
+
if (cur_aug_p > end_aug_p) {
|
1204
|
+
_dwarf_error(dbg, error, DW_DLE_FRAME_AUGMENTATION_UNKNOWN);
|
1205
|
+
return DW_DLV_ERROR;
|
1206
|
+
}
|
1207
|
+
}
|
1208
|
+
break;
|
1209
|
+
default:
|
1210
|
+
_dwarf_error(dbg, error, DW_DLE_FRAME_AUGMENTATION_UNKNOWN);
|
1211
|
+
return DW_DLV_ERROR;
|
1212
|
+
|
1213
|
+
}
|
1214
|
+
}
|
1215
|
+
return DW_DLV_OK;
|
1216
|
+
}
|
1217
|
+
|
1218
|
+
/* Given augmentation character (the encoding) giving the
|
1219
|
+
address format, read the address from input_field
|
1220
|
+
and return an incremented value 1 past the input bytes of the
|
1221
|
+
address.
|
1222
|
+
Push the address read back thru the *addr pointer.
|
1223
|
+
See LSB (Linux Standard Base) exception handling documents. */
|
1224
|
+
static int
|
1225
|
+
read_encoded_ptr(Dwarf_Debug dbg,
|
1226
|
+
Dwarf_Small * section_pointer,
|
1227
|
+
Dwarf_Small * input_field,
|
1228
|
+
int gnu_encoding,
|
1229
|
+
Dwarf_Half address_size,
|
1230
|
+
Dwarf_Unsigned * addr,
|
1231
|
+
Dwarf_Small ** input_field_updated,
|
1232
|
+
Dwarf_Error *error)
|
1233
|
+
{
|
1234
|
+
Dwarf_Word length = 0;
|
1235
|
+
int value_type = gnu_encoding & 0xf;
|
1236
|
+
Dwarf_Small *input_field_original = input_field;
|
1237
|
+
|
1238
|
+
if (gnu_encoding == 0xff) {
|
1239
|
+
/* There is no data here. */
|
1240
|
+
|
1241
|
+
*addr = 0;
|
1242
|
+
*input_field_updated = input_field;
|
1243
|
+
/* Should we return DW_DLV_NO_ENTRY? */
|
1244
|
+
return DW_DLV_OK;
|
1245
|
+
}
|
1246
|
+
switch (value_type) {
|
1247
|
+
case DW_EH_PE_absptr:{
|
1248
|
+
/* value_type is zero. Treat as pointer size of the object.
|
1249
|
+
*/
|
1250
|
+
Dwarf_Unsigned ret_value = 0;
|
1251
|
+
|
1252
|
+
READ_UNALIGNED(dbg, ret_value, Dwarf_Unsigned,
|
1253
|
+
input_field, address_size);
|
1254
|
+
*addr = ret_value;
|
1255
|
+
*input_field_updated = input_field + address_size;
|
1256
|
+
}
|
1257
|
+
break;
|
1258
|
+
case DW_EH_PE_uleb128:{
|
1259
|
+
Dwarf_Unsigned val = _dwarf_decode_u_leb128(input_field,
|
1260
|
+
&length);
|
1261
|
+
|
1262
|
+
*addr = val;
|
1263
|
+
*input_field_updated = input_field + length;
|
1264
|
+
}
|
1265
|
+
break;
|
1266
|
+
case DW_EH_PE_udata2:{
|
1267
|
+
Dwarf_Unsigned ret_value = 0;
|
1268
|
+
|
1269
|
+
READ_UNALIGNED(dbg, ret_value, Dwarf_Unsigned,
|
1270
|
+
input_field, 2);
|
1271
|
+
*addr = ret_value;
|
1272
|
+
*input_field_updated = input_field + 2;
|
1273
|
+
}
|
1274
|
+
break;
|
1275
|
+
|
1276
|
+
case DW_EH_PE_udata4:{
|
1277
|
+
Dwarf_Unsigned ret_value = 0;
|
1278
|
+
|
1279
|
+
/* ASSERT: sizeof(Dwarf_ufixed) == 4 */
|
1280
|
+
READ_UNALIGNED(dbg, ret_value, Dwarf_Unsigned,
|
1281
|
+
input_field, sizeof(Dwarf_ufixed));
|
1282
|
+
*addr = ret_value;
|
1283
|
+
*input_field_updated = input_field + sizeof(Dwarf_ufixed);
|
1284
|
+
}
|
1285
|
+
break;
|
1286
|
+
|
1287
|
+
case DW_EH_PE_udata8:{
|
1288
|
+
Dwarf_Unsigned ret_value = 0;
|
1289
|
+
|
1290
|
+
/* ASSERT: sizeof(Dwarf_Unsigned) == 8 */
|
1291
|
+
READ_UNALIGNED(dbg, ret_value, Dwarf_Unsigned,
|
1292
|
+
input_field, sizeof(Dwarf_Unsigned));
|
1293
|
+
*addr = ret_value;
|
1294
|
+
*input_field_updated = input_field + sizeof(Dwarf_Unsigned);
|
1295
|
+
}
|
1296
|
+
break;
|
1297
|
+
|
1298
|
+
case DW_EH_PE_sleb128:{
|
1299
|
+
Dwarf_Signed val = _dwarf_decode_s_leb128(input_field,
|
1300
|
+
&length);
|
1301
|
+
|
1302
|
+
*addr = (Dwarf_Unsigned) val;
|
1303
|
+
*input_field_updated = input_field + length;
|
1304
|
+
}
|
1305
|
+
break;
|
1306
|
+
case DW_EH_PE_sdata2:{
|
1307
|
+
Dwarf_Unsigned val = 0;
|
1308
|
+
|
1309
|
+
READ_UNALIGNED(dbg, val, Dwarf_Unsigned, input_field, 2);
|
1310
|
+
SIGN_EXTEND(val, 2);
|
1311
|
+
*addr = (Dwarf_Unsigned) val;
|
1312
|
+
*input_field_updated = input_field + 2;
|
1313
|
+
}
|
1314
|
+
break;
|
1315
|
+
|
1316
|
+
case DW_EH_PE_sdata4:{
|
1317
|
+
Dwarf_Unsigned val = 0;
|
1318
|
+
|
1319
|
+
/* ASSERT: sizeof(Dwarf_ufixed) == 4 */
|
1320
|
+
READ_UNALIGNED(dbg, val,
|
1321
|
+
Dwarf_Unsigned, input_field,
|
1322
|
+
sizeof(Dwarf_ufixed));
|
1323
|
+
SIGN_EXTEND(val, sizeof(Dwarf_ufixed));
|
1324
|
+
*addr = (Dwarf_Unsigned) val;
|
1325
|
+
*input_field_updated = input_field + sizeof(Dwarf_ufixed);
|
1326
|
+
}
|
1327
|
+
break;
|
1328
|
+
case DW_EH_PE_sdata8:{
|
1329
|
+
Dwarf_Unsigned val = 0;
|
1330
|
+
|
1331
|
+
/* ASSERT: sizeof(Dwarf_Unsigned) == 8 */
|
1332
|
+
READ_UNALIGNED(dbg, val,
|
1333
|
+
Dwarf_Unsigned, input_field,
|
1334
|
+
sizeof(Dwarf_Unsigned));
|
1335
|
+
*addr = (Dwarf_Unsigned) val;
|
1336
|
+
*input_field_updated = input_field + sizeof(Dwarf_Unsigned);
|
1337
|
+
}
|
1338
|
+
break;
|
1339
|
+
default:
|
1340
|
+
_dwarf_error(dbg, error, DW_DLE_FRAME_AUGMENTATION_UNKNOWN);
|
1341
|
+
return DW_DLV_ERROR;
|
1342
|
+
|
1343
|
+
};
|
1344
|
+
/* The ELF ABI for gnu does not document the meaning of
|
1345
|
+
DW_EH_PE_pcrel, which is awkward. It apparently means the value
|
1346
|
+
we got above is pc-relative (meaning section-relative), so we
|
1347
|
+
adjust the value. Section_pointer may be null if it is known
|
1348
|
+
DW_EH_PE_pcrel cannot apply, such as for .debug_frame or for an
|
1349
|
+
address-range value. */
|
1350
|
+
if (section_pointer && ((gnu_encoding & 0x70) == DW_EH_PE_pcrel)) {
|
1351
|
+
/* Address (*addr) above is pc relative with respect to a
|
1352
|
+
section. Add to the offset the base address (from elf) of
|
1353
|
+
section and the distance of the field we are reading from
|
1354
|
+
the section-beginning to get the actual address. */
|
1355
|
+
/* ASSERT: input_field_original >= section_pointer */
|
1356
|
+
Dwarf_Unsigned distance =
|
1357
|
+
input_field_original - section_pointer;
|
1358
|
+
*addr += dbg->de_debug_frame_eh_gnu.dss_addr + distance;
|
1359
|
+
}
|
1360
|
+
return DW_DLV_OK;
|
1361
|
+
}
|
1362
|
+
|
1363
|
+
|
1364
|
+
|
1365
|
+
|
1366
|
+
/* All augmentation string checking done here now.
|
1367
|
+
|
1368
|
+
For .eh_frame, gcc from 3.3 uses the z style, earlier used
|
1369
|
+
only "eh" as augmentation. We don't yet handle
|
1370
|
+
decoding .eh_frame with the z style extensions like L P.
|
1371
|
+
|
1372
|
+
These are nasty heuristics, but then that's life
|
1373
|
+
as augmentations are implementation specific. */
|
1374
|
+
/* ARGSUSED */
|
1375
|
+
enum Dwarf_augmentation_type
|
1376
|
+
_dwarf_get_augmentation_type(Dwarf_Debug dbg,
|
1377
|
+
Dwarf_Small * augmentation_string,
|
1378
|
+
int is_gcc_eh_frame)
|
1379
|
+
{
|
1380
|
+
enum Dwarf_augmentation_type t = aug_unknown;
|
1381
|
+
char *ag_string = (char *) augmentation_string;
|
1382
|
+
|
1383
|
+
if (ag_string[0] == 0) {
|
1384
|
+
/* Empty string. We'll just guess that we know what this means:
|
1385
|
+
standard dwarf2/3 with no implementation-defined fields. */
|
1386
|
+
t = aug_empty_string;
|
1387
|
+
} else if (strcmp(ag_string, DW_DEBUG_FRAME_AUGMENTER_STRING) == 0) {
|
1388
|
+
/* The string is "mti v1". Used internally at SGI, probably
|
1389
|
+
never shipped. Replaced by "z". Treat like 'nothing
|
1390
|
+
special'. */
|
1391
|
+
t = aug_irix_mti_v1;
|
1392
|
+
} else if (ag_string[0] == 'z') {
|
1393
|
+
/* If it's IRIX cc, z means aug_irix_exception_table. z1 z2
|
1394
|
+
were designed as for IRIX CC, but never implemented */
|
1395
|
+
/* If it's gcc, z may be any of several things. "z" or z
|
1396
|
+
followed optionally followed by one or more of L R P, each
|
1397
|
+
of which means a value may be present. Should be in eh_frame
|
1398
|
+
only, I think. */
|
1399
|
+
if (is_gcc_eh_frame) {
|
1400
|
+
t = aug_gcc_eh_z;
|
1401
|
+
} else if (ag_string[1] == 0) {
|
1402
|
+
/* This is the normal IRIX C++ case, where there is an
|
1403
|
+
offset into a table in each fde. The table being for
|
1404
|
+
IRIX CC exception handling. */
|
1405
|
+
/* DW_CIE_AUGMENTER_STRING_V0 "z" */
|
1406
|
+
t = aug_irix_exception_table;
|
1407
|
+
} /* Else unknown. */
|
1408
|
+
} else if (strncmp(ag_string, "eh", 2) == 0) {
|
1409
|
+
/* gcc .eh_frame augmentation for egcs and gcc 2.x, at least
|
1410
|
+
for x86. */
|
1411
|
+
t = aug_eh;
|
1412
|
+
} else if (strcmp(ag_string, "armcc+") == 0) {
|
1413
|
+
/* Arm uses this string to mean a bug in
|
1414
|
+
in Arm compilers was fixed, changing to the standard
|
1415
|
+
calculation of the CFA. See
|
1416
|
+
http://sourceware.org/ml/gdb-patches/2006-12/msg00249.html
|
1417
|
+
for details. */
|
1418
|
+
t = aug_armcc;
|
1419
|
+
} else {
|
1420
|
+
|
1421
|
+
}
|
1422
|
+
return t;
|
1423
|
+
}
|
1424
|
+
|
1425
|
+
/* Using augmentation, and version
|
1426
|
+
read in the augmentation data for GNU eh.
|
1427
|
+
|
1428
|
+
Return DW_DLV_OK if we succeeded,
|
1429
|
+
DW_DLV_ERR if we fail.
|
1430
|
+
|
1431
|
+
On success, update 'size_of_augmentation_data' with
|
1432
|
+
the length of the fields that are part of augmentation (so the
|
1433
|
+
caller can increment frame_ptr appropriately).
|
1434
|
+
|
1435
|
+
'frame_ptr' points within section.
|
1436
|
+
'section_pointer' points to section base address in memory.
|
1437
|
+
*/
|
1438
|
+
/* ARGSUSED */
|
1439
|
+
static int
|
1440
|
+
get_gcc_eh_augmentation(Dwarf_Debug dbg, Dwarf_Small * frame_ptr,
|
1441
|
+
unsigned long *size_of_augmentation_data,
|
1442
|
+
enum Dwarf_augmentation_type augtype,
|
1443
|
+
Dwarf_Small * section_pointer,
|
1444
|
+
Dwarf_Small * fde_eh_encoding_out,
|
1445
|
+
char *augmentation,
|
1446
|
+
Dwarf_Error *error)
|
1447
|
+
{
|
1448
|
+
char *suffix = 0;
|
1449
|
+
unsigned long augdata_size = 0;
|
1450
|
+
|
1451
|
+
if (augtype == aug_gcc_eh_z) {
|
1452
|
+
/* Has leading 'z'. */
|
1453
|
+
Dwarf_Word leb128_length = 0;
|
1454
|
+
|
1455
|
+
/* Dwarf_Unsigned eh_value = */
|
1456
|
+
_dwarf_decode_u_leb128(frame_ptr, &leb128_length);
|
1457
|
+
augdata_size += leb128_length;
|
1458
|
+
frame_ptr += leb128_length;
|
1459
|
+
suffix = augmentation + 1;
|
1460
|
+
} else {
|
1461
|
+
/* Prefix is 'eh'. As in gcc 3.2. No suffix present
|
1462
|
+
apparently. */
|
1463
|
+
suffix = augmentation + 2;
|
1464
|
+
}
|
1465
|
+
for (; *suffix; ++suffix) {
|
1466
|
+
/* We have no idea what this is as yet. Some extensions beyond
|
1467
|
+
dwarf exist which we do not yet handle. */
|
1468
|
+
_dwarf_error(dbg, error, DW_DLE_FRAME_AUGMENTATION_UNKNOWN);
|
1469
|
+
return DW_DLV_ERROR;
|
1470
|
+
|
1471
|
+
}
|
1472
|
+
|
1473
|
+
*size_of_augmentation_data = augdata_size;
|
1474
|
+
return DW_DLV_OK;
|
1475
|
+
}
|
1476
|
+
|
1477
|
+
|
1478
|
+
/* Make the 'cie_id_addr' consistent across .debug_frame and .eh_frame.
|
1479
|
+
Calculate a pointer into section bytes given a cie_id, which is
|
1480
|
+
trivial for .debug_frame, but a bit more work for .eh_frame.
|
1481
|
+
*/
|
1482
|
+
static Dwarf_Small *
|
1483
|
+
get_cieptr_given_offset(Dwarf_Unsigned cie_id_value,
|
1484
|
+
int use_gnu_cie_calc,
|
1485
|
+
Dwarf_Small * section_ptr,
|
1486
|
+
Dwarf_Small * cie_id_addr)
|
1487
|
+
{
|
1488
|
+
Dwarf_Small *cieptr = 0;
|
1489
|
+
|
1490
|
+
if (use_gnu_cie_calc) {
|
1491
|
+
/* cie_id value is offset, in section, of the cie_id itself, to
|
1492
|
+
use vm ptr of the value, less the value, to get to the cie
|
1493
|
+
itself. In addition, munge *cie_id_addr to look *as if* it
|
1494
|
+
was from real dwarf. */
|
1495
|
+
cieptr = (Dwarf_Small *) ((Dwarf_Unsigned) cie_id_addr) -
|
1496
|
+
((Dwarf_Unsigned) cie_id_value);
|
1497
|
+
} else {
|
1498
|
+
/* Traditional dwarf section offset is in cie_id */
|
1499
|
+
cieptr = (section_ptr + cie_id_value);
|
1500
|
+
}
|
1501
|
+
return cieptr;
|
1502
|
+
}
|
1503
|
+
|
1504
|
+
/* To properly release all spaced used.
|
1505
|
+
Earlier approaches (before July 15, 2005)
|
1506
|
+
letting client do the dealloc directly left
|
1507
|
+
some data allocated.
|
1508
|
+
This is directly called by consumer code.
|
1509
|
+
*/
|
1510
|
+
void
|
1511
|
+
dwarf_fde_cie_list_dealloc(Dwarf_Debug dbg,
|
1512
|
+
Dwarf_Cie * cie_data,
|
1513
|
+
Dwarf_Signed cie_element_count,
|
1514
|
+
Dwarf_Fde * fde_data,
|
1515
|
+
Dwarf_Signed fde_element_count)
|
1516
|
+
{
|
1517
|
+
Dwarf_Signed i = 0;
|
1518
|
+
|
1519
|
+
for (i = 0; i < cie_element_count; ++i) {
|
1520
|
+
Dwarf_Frame frame = cie_data[i]->ci_initial_table;
|
1521
|
+
|
1522
|
+
if (frame)
|
1523
|
+
dwarf_dealloc(dbg, frame, DW_DLA_FRAME);
|
1524
|
+
dwarf_dealloc(dbg, cie_data[i], DW_DLA_CIE);
|
1525
|
+
}
|
1526
|
+
for (i = 0; i < fde_element_count; ++i) {
|
1527
|
+
dwarf_dealloc(dbg, fde_data[i], DW_DLA_FDE);
|
1528
|
+
}
|
1529
|
+
if (cie_data)
|
1530
|
+
dwarf_dealloc(dbg, cie_data, DW_DLA_LIST);
|
1531
|
+
if (fde_data)
|
1532
|
+
dwarf_dealloc(dbg, fde_data, DW_DLA_LIST);
|
1533
|
+
}
|