blob: 70ab16d67ad57800ada40b409eb0cb060c6b58e3 [file] [log] [blame]
sewardj5d616df2013-07-02 08:07:15 +00001/* -*- mode: C; c-basic-offset: 3; -*- */
njnea27e462005-05-31 02:38:09 +00002
njn4bbdc972003-10-16 10:10:55 +00003/*--------------------------------------------------------------------*/
tomfba428c2010-04-28 08:09:30 +00004/*--- Read DWARF1/2/3/4 debug info. readdwarf.c ---*/
njn4bbdc972003-10-16 10:10:55 +00005/*--------------------------------------------------------------------*/
6
7/*
njnb9c427c2004-12-01 14:14:42 +00008 This file is part of Valgrind, a dynamic binary instrumentation
9 framework.
njn4bbdc972003-10-16 10:10:55 +000010
Elliott Hughesed398002017-06-21 14:41:24 -070011 Copyright (C) 2000-2017 Julian Seward
njn4bbdc972003-10-16 10:10:55 +000012 jseward@acm.org
13
14 This program is free software; you can redistribute it and/or
15 modify it under the terms of the GNU General Public License as
16 published by the Free Software Foundation; either version 2 of the
17 License, or (at your option) any later version.
18
19 This program is distributed in the hope that it will be useful, but
20 WITHOUT ANY WARRANTY; without even the implied warranty of
21 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
22 General Public License for more details.
23
24 You should have received a copy of the GNU General Public License
25 along with this program; if not, write to the Free Software
26 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
27 02111-1307, USA.
28
29 The GNU General Public License is contained in the file COPYING.
30*/
njn8b68b642009-06-24 00:37:09 +000031
sewardj8eb8bab2015-07-21 14:44:28 +000032#if defined(VGO_linux) || defined(VGO_darwin) || defined(VGO_solaris)
jsgfcb1d1c02003-10-14 21:55:10 +000033
njnc7561b92005-06-19 01:24:32 +000034#include "pub_core_basics.h"
tom588658b2009-01-22 13:40:12 +000035#include "pub_core_debuginfo.h"
njn97405b22005-06-02 03:39:33 +000036#include "pub_core_libcbase.h"
njn132bfcc2005-06-04 19:16:06 +000037#include "pub_core_libcassert.h"
njn36a20fa2005-06-03 03:08:39 +000038#include "pub_core_libcprint.h"
njn20242342005-05-16 23:31:24 +000039#include "pub_core_options.h"
sewardj72427fa2007-02-27 16:52:23 +000040#include "pub_core_xarray.h"
tom3c9cf342009-11-12 13:28:34 +000041#include "pub_core_tooliface.h" /* VG_(needs) */
sewardjb8b79ad2008-03-03 01:35:41 +000042#include "priv_misc.h" /* dinfo_zalloc/free/strdup */
sewardj5d616df2013-07-02 08:07:15 +000043#include "priv_image.h"
sewardjb8b79ad2008-03-03 01:35:41 +000044#include "priv_d3basics.h"
45#include "priv_tytypes.h"
sewardjeadcd862006-04-04 15:12:44 +000046#include "priv_storage.h"
47#include "priv_readdwarf.h" /* self */
njnf4c50162005-06-20 14:18:12 +000048
jsgfcb1d1c02003-10-14 21:55:10 +000049
sewardjeadcd862006-04-04 15:12:44 +000050/*------------------------------------------------------------*/
51/*--- ---*/
52/*--- Read line number and CFI info from DWARF1, DWARF2 ---*/
53/*--- and to some extent DWARF3 sections. ---*/
54/*--- ---*/
55/*------------------------------------------------------------*/
sewardjc613dff2005-06-13 17:33:27 +000056
philippe59e1f3c2014-07-14 21:20:57 +000057/* The below "safe_*ix" functions allow to resist to malformed dwarf info:
58 if dwarf info contains wrong file or dirname indexes, these are (silently!)
59 ignored. */
sewardjc613dff2005-06-13 17:33:27 +000060
philippe59e1f3c2014-07-14 21:20:57 +000061/* if xa_ix is a valid index in fndn_ix_xa,
62 return the element (i.e. the UInt indexing in fndnpool).
63 If xa_ix is invalid, return 0 (i.e. the "null" element in fndnpool). */
64static UInt safe_fndn_ix (XArray* fndn_ix_xa, Int xa_ix)
sewardjc613dff2005-06-13 17:33:27 +000065{
philippe59e1f3c2014-07-14 21:20:57 +000066 if (xa_ix < 0) return 0;
67 if (xa_ix >= VG_(sizeXA) (fndn_ix_xa)) return 0;
68 return *(UInt*)VG_(indexXA) ( fndn_ix_xa, xa_ix );
sewardjc613dff2005-06-13 17:33:27 +000069}
70
philippe59e1f3c2014-07-14 21:20:57 +000071/* if xa_ix is a valid index in dirname_xa,
72 return the element (i.e. the HChar*).
73 If xa_ix is invalid, return NULL. */
florian1ef70c62014-10-22 17:42:37 +000074static const HChar* safe_dirname_ix (XArray* dirname_xa, Int xa_ix)
sewardjc613dff2005-06-13 17:33:27 +000075{
philippe59e1f3c2014-07-14 21:20:57 +000076 if (xa_ix < 0) return NULL;
77 if (xa_ix >= VG_(sizeXA) (dirname_xa)) return NULL;
78 return *(HChar**)VG_(indexXA) ( dirname_xa, xa_ix );
sewardjc613dff2005-06-13 17:33:27 +000079}
80
sewardjc613dff2005-06-13 17:33:27 +000081/*------------------------------------------------------------*/
82/*--- Read DWARF2 format line number info. ---*/
83/*------------------------------------------------------------*/
84
sewardj11624912006-02-09 23:35:11 +000085/* Structure holding info extracted from the a .debug_line
86 section. */
jsgfcb1d1c02003-10-14 21:55:10 +000087typedef struct
88{
sewardj11624912006-02-09 23:35:11 +000089 ULong li_length;
jsgfcb1d1c02003-10-14 21:55:10 +000090 UShort li_version;
sewardj11624912006-02-09 23:35:11 +000091 ULong li_header_length;
jsgfcb1d1c02003-10-14 21:55:10 +000092 UChar li_min_insn_length;
tomfba428c2010-04-28 08:09:30 +000093 UChar li_max_ops_per_insn;
jsgfcb1d1c02003-10-14 21:55:10 +000094 Int li_line_base;
95 UChar li_line_range;
96 UChar li_opcode_base;
97}
sewardj11624912006-02-09 23:35:11 +000098DebugLineInfo;
jsgfcb1d1c02003-10-14 21:55:10 +000099
sewardj022bf2f2005-06-14 21:51:14 +0000100/* Structure holding additional infos found from a .debug_info
101 * compilation unit block */
102typedef struct
103{
104 /* Feel free to add more members here if you need ! */
sewardj5d616df2013-07-02 08:07:15 +0000105 DiCursor compdir; /* Compilation directory - points to .debug_info */
106 DiCursor name; /* Main file name - points to .debug_info */
107 ULong stmt_list; /* Offset in .debug_line */
108 Bool dw64; /* 64-bit Dwarf? */
sewardj022bf2f2005-06-14 21:51:14 +0000109}
110UnitInfo;
111
jsgfcb1d1c02003-10-14 21:55:10 +0000112/* Line number opcodes. */
113enum dwarf_line_number_ops
114 {
115 DW_LNS_extended_op = 0,
116 DW_LNS_copy = 1,
117 DW_LNS_advance_pc = 2,
118 DW_LNS_advance_line = 3,
119 DW_LNS_set_file = 4,
120 DW_LNS_set_column = 5,
121 DW_LNS_negate_stmt = 6,
122 DW_LNS_set_basic_block = 7,
123 DW_LNS_const_add_pc = 8,
124 DW_LNS_fixed_advance_pc = 9,
125 /* DWARF 3. */
126 DW_LNS_set_prologue_end = 10,
127 DW_LNS_set_epilogue_begin = 11,
128 DW_LNS_set_isa = 12
129 };
130
131/* Line number extended opcodes. */
132enum dwarf_line_number_x_ops
133 {
134 DW_LNE_end_sequence = 1,
135 DW_LNE_set_address = 2,
tomfba428c2010-04-28 08:09:30 +0000136 DW_LNE_define_file = 3,
137 DW_LNE_set_discriminator = 4
jsgfcb1d1c02003-10-14 21:55:10 +0000138 };
139
sewardj3646a492007-02-16 14:17:10 +0000140typedef struct
jsgfcb1d1c02003-10-14 21:55:10 +0000141{
142 /* Information for the last statement boundary.
143 * Needed to calculate statement lengths. */
144 Addr last_address;
145 UInt last_file;
146 UInt last_line;
147
148 Addr address;
149 UInt file;
150 UInt line;
151 UInt column;
jsgfcb1d1c02003-10-14 21:55:10 +0000152 Int basic_block;
tomfba428c2010-04-28 08:09:30 +0000153 UChar end_sequence;
sewardj3646a492007-02-16 14:17:10 +0000154} LineSMR;
jsgfcb1d1c02003-10-14 21:55:10 +0000155
156
sewardjb8b79ad2008-03-03 01:35:41 +0000157/* FIXME: duplicated in readdwarf3.c */
sewardj5d616df2013-07-02 08:07:15 +0000158/* Read a 'leb128' and advance *data accordingly. */
159static ULong step_leb128 ( DiCursor* data, Int sign )
jsgfcb1d1c02003-10-14 21:55:10 +0000160{
sewardj5d616df2013-07-02 08:07:15 +0000161 ULong result = 0;
162 Int shift = 0;
163 UChar byte;
jsgfcb1d1c02003-10-14 21:55:10 +0000164
sewardj5d616df2013-07-02 08:07:15 +0000165 vg_assert(sign == 0 || sign == 1);
sewardj72427fa2007-02-27 16:52:23 +0000166
sewardj5d616df2013-07-02 08:07:15 +0000167 do {
168 byte = ML_(cur_step_UChar)(data);
sewardjc4217cd2007-02-27 17:43:43 +0000169 result |= ((ULong)(byte & 0x7f)) << shift;
jsgfcb1d1c02003-10-14 21:55:10 +0000170 shift += 7;
sewardj5d616df2013-07-02 08:07:15 +0000171 }
172 while (byte & 0x80);
jsgfcb1d1c02003-10-14 21:55:10 +0000173
sewardj5d616df2013-07-02 08:07:15 +0000174 if (sign && (shift < 64) && (byte & 0x40))
175 result |= -(1ULL << shift);
jsgfcb1d1c02003-10-14 21:55:10 +0000176
sewardj5d616df2013-07-02 08:07:15 +0000177 return result;
jsgfcb1d1c02003-10-14 21:55:10 +0000178}
179
sewardjb8b79ad2008-03-03 01:35:41 +0000180/* FIXME: duplicated in readdwarf3.c */
sewardj5d616df2013-07-02 08:07:15 +0000181static ULong step_leb128U( DiCursor* data ) {
182 return step_leb128( data, 0 );
sewardj022bf2f2005-06-14 21:51:14 +0000183}
184
sewardjb8b79ad2008-03-03 01:35:41 +0000185/* FIXME: duplicated in readdwarf3.c */
sewardj5d616df2013-07-02 08:07:15 +0000186static Long step_leb128S( DiCursor* data ) {
187 return step_leb128( data, 1 );
sewardj022bf2f2005-06-14 21:51:14 +0000188}
189
sewardj11624912006-02-09 23:35:11 +0000190/* Read what the DWARF3 spec calls an "initial length field". This
191 uses up either 4 or 12 bytes of the input and produces a 32-bit or
192 64-bit number respectively.
193
194 Read 32-bit value from p. If it is 0xFFFFFFFF, instead read a
195 64-bit bit value from p+4. This is used in 64-bit dwarf to encode
sewardj5d616df2013-07-02 08:07:15 +0000196 some table lengths. Advance the cursor (p) accordingly.
sewardjc4217cd2007-02-27 17:43:43 +0000197
198 XXX this is a hack: the endianness of the initial length field is
199 specified by the DWARF we're reading. This happens to work only
200 because we don't do cross-arch jitting, hence this code runs on a
201 platform of the same endianness as the DWARF it is reading. Same
202 applies for initial lengths for CIE/FDEs and probably in zillions
203 of other places -- to be precise, exactly the places where
204 binutils/dwarf.c calls byte_get().
205*/
sewardj5d616df2013-07-02 08:07:15 +0000206static
207ULong step_initial_length_field ( DiCursor* p_img, /*OUT*/Bool* is64 )
sewardj11624912006-02-09 23:35:11 +0000208{
sewardj5d616df2013-07-02 08:07:15 +0000209 UInt w32 = ML_(cur_step_UInt)(p_img);
sewardj11624912006-02-09 23:35:11 +0000210 if (w32 == 0xFFFFFFFF) {
211 *is64 = True;
sewardj5d616df2013-07-02 08:07:15 +0000212 return ML_(cur_step_ULong)(p_img);
sewardj11624912006-02-09 23:35:11 +0000213 } else {
214 *is64 = False;
215 return (ULong)w32;
216 }
217}
218
sewardj5d616df2013-07-02 08:07:15 +0000219static
220ULong read_initial_length_field ( DiCursor p_img, /*OUT*/Bool* is64 )
221{
222 /* Something of a roundabout approach .. the modification to p_img
223 is abandoned. */
224 return step_initial_length_field( &p_img, is64 );
225}
226
sewardj022bf2f2005-06-14 21:51:14 +0000227
sewardj3646a492007-02-16 14:17:10 +0000228static LineSMR state_machine_regs;
jsgfcb1d1c02003-10-14 21:55:10 +0000229
230static
Elliott Hughesa0664b92017-04-18 17:46:52 -0700231void reset_state_machine ( void )
jsgfcb1d1c02003-10-14 21:55:10 +0000232{
barta0b6b2c2008-07-07 06:49:24 +0000233 if (0) VG_(printf)("smr.a := %p (reset)\n", NULL );
sewardj022bf2f2005-06-14 21:51:14 +0000234 state_machine_regs.last_address = 0;
235 state_machine_regs.last_file = 1;
236 state_machine_regs.last_line = 1;
237 state_machine_regs.address = 0;
238 state_machine_regs.file = 1;
239 state_machine_regs.line = 1;
240 state_machine_regs.column = 0;
sewardj022bf2f2005-06-14 21:51:14 +0000241 state_machine_regs.basic_block = 0;
242 state_machine_regs.end_sequence = 0;
jsgfcb1d1c02003-10-14 21:55:10 +0000243}
244
sewardj022bf2f2005-06-14 21:51:14 +0000245////////////////////////////////////////////////////////////////////
246////////////////////////////////////////////////////////////////////
sewardjc613dff2005-06-13 17:33:27 +0000247
sewardj5d616df2013-07-02 08:07:15 +0000248/* Handled an extended line op starting at *data, and advance *data
249 accordingly. */
jsgfcb1d1c02003-10-14 21:55:10 +0000250static
sewardj5d616df2013-07-02 08:07:15 +0000251void process_extended_line_op( struct _DebugInfo* di,
philippe59e1f3c2014-07-14 21:20:57 +0000252 XArray* fndn_ix_xa,
Elliott Hughesa0664b92017-04-18 17:46:52 -0700253 DiCursor* data )
jsgfcb1d1c02003-10-14 21:55:10 +0000254{
sewardj5d616df2013-07-02 08:07:15 +0000255 UInt len = step_leb128U(data);
sewardj022bf2f2005-06-14 21:51:14 +0000256 if (len == 0) {
jsgfcb1d1c02003-10-14 21:55:10 +0000257 VG_(message)(Vg_UserMsg,
sewardj1ff57e62007-11-20 08:46:05 +0000258 "Warning: DWARF2 reader: "
sewardj738856f2009-07-15 14:48:32 +0000259 "Badly formed extended line op encountered\n");
sewardj5d616df2013-07-02 08:07:15 +0000260 return;
sewardj022bf2f2005-06-14 21:51:14 +0000261 }
jsgfcb1d1c02003-10-14 21:55:10 +0000262
sewardj5d616df2013-07-02 08:07:15 +0000263 UChar op_code = ML_(cur_step_UChar)(data);
sewardj022bf2f2005-06-14 21:51:14 +0000264 if (0) VG_(printf)("dwarf2: ext OPC: %d\n", op_code);
jsgfcb1d1c02003-10-14 21:55:10 +0000265
sewardj022bf2f2005-06-14 21:51:14 +0000266 switch (op_code) {
267 case DW_LNE_end_sequence:
barta0b6b2c2008-07-07 06:49:24 +0000268 if (0) VG_(printf)("1001: si->o %#lx, smr.a %#lx\n",
florianc6e5d762015-08-05 22:27:24 +0000269 (UWord)di->text_debug_bias,
270 state_machine_regs.address );
sewardj022bf2f2005-06-14 21:51:14 +0000271 /* JRS: added for compliance with spec; is pointless due to
272 reset_state_machine below */
273 state_machine_regs.end_sequence = 1;
jsgfcb1d1c02003-10-14 21:55:10 +0000274
Elliott Hughesa0664b92017-04-18 17:46:52 -0700275 if (state_machine_regs.last_address) {
276 ML_(addLineInfo)(
277 di,
278 safe_fndn_ix(fndn_ix_xa,
279 state_machine_regs.last_file),
280 di->text_debug_bias + state_machine_regs.last_address,
281 di->text_debug_bias + state_machine_regs.address,
282 state_machine_regs.last_line, 0
283 );
sewardj022bf2f2005-06-14 21:51:14 +0000284 }
Elliott Hughesa0664b92017-04-18 17:46:52 -0700285 reset_state_machine();
sewardjb8b79ad2008-03-03 01:35:41 +0000286 if (di->ddump_line)
sewardj3646a492007-02-16 14:17:10 +0000287 VG_(printf)(" Extended opcode %d: End of Sequence\n\n",
288 (Int)op_code);
sewardj022bf2f2005-06-14 21:51:14 +0000289 break;
jsgfcb1d1c02003-10-14 21:55:10 +0000290
sewardj5d616df2013-07-02 08:07:15 +0000291 case DW_LNE_set_address: {
292 Addr adr = ML_(cur_step_Addr)(data);
sewardj022bf2f2005-06-14 21:51:14 +0000293 state_machine_regs.address = adr;
sewardjb8b79ad2008-03-03 01:35:41 +0000294 if (di->ddump_line)
sewardj3646a492007-02-16 14:17:10 +0000295 VG_(printf)(" Extended opcode %d: set Address to 0x%lx\n",
296 (Int)op_code, (Addr)adr);
sewardj022bf2f2005-06-14 21:51:14 +0000297 break;
sewardj5d616df2013-07-02 08:07:15 +0000298 }
jsgfcb1d1c02003-10-14 21:55:10 +0000299
sewardj5d616df2013-07-02 08:07:15 +0000300 case DW_LNE_define_file: {
301 HChar* name = ML_(cur_step_strdup)(data, "di.pelo.1");
philippe59e1f3c2014-07-14 21:20:57 +0000302 UInt fndn_ix = ML_(addFnDn) (di, name, NULL);
303 VG_(addToXA) (fndn_ix_xa, &fndn_ix);
sewardj5d616df2013-07-02 08:07:15 +0000304 ML_(dinfo_free)(name);
305 (void)step_leb128U(data); // ignored: dir index
306 (void)step_leb128U(data); // ignored: mod time
307 (void)step_leb128U(data); // ignored: file size
sewardjb8b79ad2008-03-03 01:35:41 +0000308 if (di->ddump_line)
sewardj3646a492007-02-16 14:17:10 +0000309 VG_(printf)(" DWARF2-line: set_address\n");
sewardj022bf2f2005-06-14 21:51:14 +0000310 break;
sewardj5d616df2013-07-02 08:07:15 +0000311 }
jsgfcb1d1c02003-10-14 21:55:10 +0000312
tomfba428c2010-04-28 08:09:30 +0000313 case DW_LNE_set_discriminator:
sewardj5d616df2013-07-02 08:07:15 +0000314 (void)step_leb128U(data); // ignored: new 'discriminator' value
tomfba428c2010-04-28 08:09:30 +0000315 break;
316
sewardj022bf2f2005-06-14 21:51:14 +0000317 default:
sewardjb8b79ad2008-03-03 01:35:41 +0000318 if (di->ddump_line)
sewardj3646a492007-02-16 14:17:10 +0000319 VG_(printf)("process_extended_line_op:default\n");
sewardj022bf2f2005-06-14 21:51:14 +0000320 break;
321 }
jsgfcb1d1c02003-10-14 21:55:10 +0000322}
njn4bbdc972003-10-16 10:10:55 +0000323
sewardj022bf2f2005-06-14 21:51:14 +0000324////////////////////////////////////////////////////////////////////
325////////////////////////////////////////////////////////////////////
326
327/* read a .debug_line section block for a compilation unit
328 *
329 * Input: - theBlock must point to the start of the block
330 * for the given compilation unit
331 * - ui contains additional info like the compilation dir
332 * for this unit
333 *
334 * Output: - si debug info structures get updated
335 */
336static
sewardjb8b79ad2008-03-03 01:35:41 +0000337void read_dwarf2_lineblock ( struct _DebugInfo* di,
florian518850b2014-10-22 22:25:30 +0000338 const UnitInfo* ui,
sewardj5d616df2013-07-02 08:07:15 +0000339 DiCursor theBlock, /* IMAGE */
sewardj022bf2f2005-06-14 21:51:14 +0000340 Int noLargerThan )
341{
sewardj3646a492007-02-16 14:17:10 +0000342 Int i;
sewardj11624912006-02-09 23:35:11 +0000343 DebugLineInfo info;
sewardj11624912006-02-09 23:35:11 +0000344 Bool is64;
philippe59e1f3c2014-07-14 21:20:57 +0000345 XArray* fndn_ix_xa; /* xarray of UInt fndn_ix */
346 UInt fndn_ix;
florian1ef70c62014-10-22 17:42:37 +0000347 XArray* dirname_xa; /* xarray of const HChar* dirname */
348 const HChar* dirname;
sewardj11624912006-02-09 23:35:11 +0000349
sewardj5d616df2013-07-02 08:07:15 +0000350 DiCursor external = theBlock;
351 DiCursor data = theBlock;
sewardj022bf2f2005-06-14 21:51:14 +0000352
philippe59e1f3c2014-07-14 21:20:57 +0000353 /* fndn_ix_xa is an xarray of fndn_ix (indexes in di->fndnpool) which
354 are build from file names harvested from the DWARF2
355 info. Entry [0] is the "null" pool index and is never referred to
356 by the state machine.
sewardj022bf2f2005-06-14 21:51:14 +0000357
philippe59e1f3c2014-07-14 21:20:57 +0000358 Similarly, dirname_xa is an xarray of directory names. Entry [0]
sewardj022bf2f2005-06-14 21:51:14 +0000359 is also NULL and denotes "we don't know what the path is", since
360 that is different from "the path is the empty string". Unlike
philippe59e1f3c2014-07-14 21:20:57 +0000361 the fndn_ix_xa table, the state machine does refer to entry [0],
sewardj022bf2f2005-06-14 21:51:14 +0000362 which basically means "." ("the current directory of the
363 compilation", whatever that means, according to the DWARF3
364 spec.)
philippe59e1f3c2014-07-14 21:20:57 +0000365 */
sewardj022bf2f2005-06-14 21:51:14 +0000366
367 /* Fails due to gcc padding ...
368 vg_assert(sizeof(DWARF2_External_LineInfo)
369 == sizeof(DWARF2_Internal_LineInfo));
370 */
371
philippe59e1f3c2014-07-14 21:20:57 +0000372 dirname_xa = VG_(newXA) (ML_(dinfo_zalloc), "di.rd2l.1", ML_(dinfo_free),
373 sizeof(HChar*) );
374 fndn_ix_xa = VG_(newXA) (ML_(dinfo_zalloc), "di.rd2l.2", ML_(dinfo_free),
375 sizeof(UInt) );
sewardj022bf2f2005-06-14 21:51:14 +0000376
377 /* DWARF2 starts numbering filename entries at 1, so we need to
philippe59e1f3c2014-07-14 21:20:57 +0000378 add a dummy zeroth entry to the table. */
379 fndn_ix = 0; // 0 is the "null" index in a fixed pool.
380 VG_(addToXA) (fndn_ix_xa, &fndn_ix);
sewardj022bf2f2005-06-14 21:51:14 +0000381
sewardj5d616df2013-07-02 08:07:15 +0000382 if (ML_(cur_is_valid)(ui->compdir))
philippe59e1f3c2014-07-14 21:20:57 +0000383 dirname = ML_(addStrFromCursor)(di, ui->compdir);
sewardj022bf2f2005-06-14 21:51:14 +0000384 else
philippe59e1f3c2014-07-14 21:20:57 +0000385 dirname = ML_(addStr)(di, ".", -1);
386 VG_(addToXA) (dirname_xa, &dirname);
sewardj022bf2f2005-06-14 21:51:14 +0000387
sewardj5d616df2013-07-02 08:07:15 +0000388 info.li_length = step_initial_length_field( &external, &is64 );
sewardjb8b79ad2008-03-03 01:35:41 +0000389 if (di->ddump_line)
sewardj3646a492007-02-16 14:17:10 +0000390 VG_(printf)(" Length: %llu\n",
391 info.li_length);
392
sewardj022bf2f2005-06-14 21:51:14 +0000393 /* Check the length of the block. */
sewardj11624912006-02-09 23:35:11 +0000394 if (info.li_length > noLargerThan) {
sewardjb8b79ad2008-03-03 01:35:41 +0000395 ML_(symerr)(di, True,
396 "DWARF line info appears to be corrupt "
sewardj022bf2f2005-06-14 21:51:14 +0000397 "- the section is too small");
398 goto out;
399 }
400
401 /* Check its version number. */
sewardj5d616df2013-07-02 08:07:15 +0000402 info.li_version = ML_(cur_step_UShort)(&external);
sewardjb8b79ad2008-03-03 01:35:41 +0000403 if (di->ddump_line)
sewardj3646a492007-02-16 14:17:10 +0000404 VG_(printf)(" DWARF Version: %d\n",
405 (Int)info.li_version);
406
tomfba428c2010-04-28 08:09:30 +0000407 if (info.li_version != 2 && info.li_version != 3 && info.li_version != 4) {
sewardjb8b79ad2008-03-03 01:35:41 +0000408 ML_(symerr)(di, True,
tomfba428c2010-04-28 08:09:30 +0000409 "Only DWARF version 2, 3 and 4 line info "
sewardj022bf2f2005-06-14 21:51:14 +0000410 "is currently supported.");
411 goto out;
412 }
413
sewardj5d616df2013-07-02 08:07:15 +0000414 info.li_header_length = is64 ? ML_(cur_step_ULong)(&external)
415 : (ULong)(ML_(cur_step_UInt)(&external));
sewardjb8b79ad2008-03-03 01:35:41 +0000416 if (di->ddump_line)
sewardj3646a492007-02-16 14:17:10 +0000417 VG_(printf)(" Prologue Length: %llu\n",
418 info.li_header_length);
sewardj11624912006-02-09 23:35:11 +0000419
sewardj5d616df2013-07-02 08:07:15 +0000420 info.li_min_insn_length = ML_(cur_step_UChar)(&external);
sewardjb8b79ad2008-03-03 01:35:41 +0000421 if (di->ddump_line)
sewardj3646a492007-02-16 14:17:10 +0000422 VG_(printf)(" Minimum Instruction Length: %d\n",
423 (Int)info.li_min_insn_length);
sewardj022bf2f2005-06-14 21:51:14 +0000424
tomfba428c2010-04-28 08:09:30 +0000425 /* We only support machines with one opcode per instruction
426 for now. If we ever want to support VLIW machines there is
427 code to handle multiple opcodes per instruction in the
428 patch attached to BZ#233595.
429 */
430 if (info.li_version >= 4) {
sewardj5d616df2013-07-02 08:07:15 +0000431 info.li_max_ops_per_insn = ML_(cur_step_UChar)(&external);
tomfba428c2010-04-28 08:09:30 +0000432 if (info.li_max_ops_per_insn != 1) {
433 ML_(symerr)(di, True,
434 "Invalid Maximum Ops Per Insn in line info.");
435 goto out;
436 }
tomfba428c2010-04-28 08:09:30 +0000437 if (di->ddump_line)
438 VG_(printf)(" Maximum Ops Per Insn: %d\n",
439 (Int)info.li_max_ops_per_insn);
440 } else {
441 info.li_max_ops_per_insn = 1;
442 }
443
Elliott Hughesa0664b92017-04-18 17:46:52 -0700444 /* Register is_stmt is not tracked as we are interested only
445 in pc -> line info mapping and not other debugger features. */
446 /* default_is_stmt = */ ML_(cur_step_UChar)(&external);
sewardj022bf2f2005-06-14 21:51:14 +0000447
448 /* JRS: changed (UInt*) to (UChar*) */
sewardj5d616df2013-07-02 08:07:15 +0000449 info.li_line_base = ML_(cur_step_UChar)(&external);
450 info.li_line_base = (Int)(Char)info.li_line_base;
sewardjb8b79ad2008-03-03 01:35:41 +0000451 if (di->ddump_line)
sewardj3646a492007-02-16 14:17:10 +0000452 VG_(printf)(" Line Base: %d\n",
453 info.li_line_base);
sewardj022bf2f2005-06-14 21:51:14 +0000454
sewardj5d616df2013-07-02 08:07:15 +0000455 info.li_line_range = ML_(cur_step_UChar)(&external);
sewardjb8b79ad2008-03-03 01:35:41 +0000456 if (di->ddump_line)
sewardj3646a492007-02-16 14:17:10 +0000457 VG_(printf)(" Line Range: %d\n",
458 (Int)info.li_line_range);
sewardj11624912006-02-09 23:35:11 +0000459
sewardj5d616df2013-07-02 08:07:15 +0000460 info.li_opcode_base = ML_(cur_step_UChar)(&external);
sewardjb8b79ad2008-03-03 01:35:41 +0000461 if (di->ddump_line)
sewardj3646a492007-02-16 14:17:10 +0000462 VG_(printf)(" Opcode Base: %d\n\n",
463 info.li_opcode_base);
sewardj022bf2f2005-06-14 21:51:14 +0000464
465 if (0) VG_(printf)("dwarf2: line base: %d, range %d, opc base: %d\n",
sewardj11624912006-02-09 23:35:11 +0000466 (Int)info.li_line_base,
467 (Int)info.li_line_range,
468 (Int)info.li_opcode_base);
sewardj022bf2f2005-06-14 21:51:14 +0000469
sewardj5d616df2013-07-02 08:07:15 +0000470 DiCursor end_of_sequence
471 = ML_(cur_plus)(data, info.li_length + (is64 ? 12 : 4));
sewardj022bf2f2005-06-14 21:51:14 +0000472
Elliott Hughesa0664b92017-04-18 17:46:52 -0700473 reset_state_machine();
sewardj022bf2f2005-06-14 21:51:14 +0000474
475 /* Read the contents of the Opcodes table. */
sewardj5d616df2013-07-02 08:07:15 +0000476 DiCursor standard_opcodes = external;
sewardjb8b79ad2008-03-03 01:35:41 +0000477 if (di->ddump_line) {
sewardj3646a492007-02-16 14:17:10 +0000478 VG_(printf)(" Opcodes:\n");
479 for (i = 1; i < (Int)info.li_opcode_base; i++) {
480 VG_(printf)(" Opcode %d has %d args\n",
sewardj5d616df2013-07-02 08:07:15 +0000481 i, (Int)ML_(cur_read_UChar)(
482 ML_(cur_plus)(standard_opcodes,
483 (i-1) * sizeof(UChar)) ));
sewardj3646a492007-02-16 14:17:10 +0000484 }
485 VG_(printf)("\n");
486 }
philippe666ee9d2014-08-08 22:11:41 +0000487 /* skip over "standard_opcode_lengths" */
sewardj5d616df2013-07-02 08:07:15 +0000488 data = ML_(cur_plus)(standard_opcodes, info.li_opcode_base - 1);
sewardj022bf2f2005-06-14 21:51:14 +0000489
philippe666ee9d2014-08-08 22:11:41 +0000490 /* Read the contents of the Directory table. */
sewardjb8b79ad2008-03-03 01:35:41 +0000491 if (di->ddump_line)
sewardj3646a492007-02-16 14:17:10 +0000492 VG_(printf)(" The Directory Table%s\n",
sewardj5d616df2013-07-02 08:07:15 +0000493 ML_(cur_read_UChar)(data) == 0 ? " is empty." : ":" );
sewardj3646a492007-02-16 14:17:10 +0000494
sewardj5d616df2013-07-02 08:07:15 +0000495 while (ML_(cur_read_UChar)(data) != 0) {
sewardj022bf2f2005-06-14 21:51:14 +0000496
sewardj5d616df2013-07-02 08:07:15 +0000497 HChar* data_str = ML_(cur_read_strdup)(data, "di.rd2l.1");
sewardjb8b79ad2008-03-03 01:35:41 +0000498 if (di->ddump_line)
sewardj5d616df2013-07-02 08:07:15 +0000499 VG_(printf)(" %s\n", data_str);
sewardj3646a492007-02-16 14:17:10 +0000500
sewardj022bf2f2005-06-14 21:51:14 +0000501 /* If data[0] is '/', then 'data' is an absolute path and we
florianc5058202014-12-17 19:52:25 +0000502 don't mess with it. Otherwise, construct the
sewardj5d616df2013-07-02 08:07:15 +0000503 path 'ui->compdir' ++ "/" ++ 'data'. */
sewardj022bf2f2005-06-14 21:51:14 +0000504
sewardj5d616df2013-07-02 08:07:15 +0000505 if (data_str[0] != '/'
sewardj022bf2f2005-06-14 21:51:14 +0000506 /* not an absolute path */
sewardj5d616df2013-07-02 08:07:15 +0000507 && ML_(cur_is_valid)(ui->compdir)
sewardj3c540212005-06-17 13:06:53 +0000508 /* actually got something sensible for compdir */
florianc5058202014-12-17 19:52:25 +0000509 && ML_(cur_strlen)(ui->compdir))
sewardj022bf2f2005-06-14 21:51:14 +0000510 {
sewardj5d616df2013-07-02 08:07:15 +0000511 HChar* compdir_str = ML_(cur_read_strdup)(ui->compdir, "di.rd2l.1b");
florianc5058202014-12-17 19:52:25 +0000512 SizeT len = VG_(strlen)(compdir_str) + 1 + VG_(strlen)(data_str);
513 HChar *buf = ML_(dinfo_zalloc)("di.rd2l.1c", len + 1);
514
515 VG_(strcpy)(buf, compdir_str);
sewardj022bf2f2005-06-14 21:51:14 +0000516 VG_(strcat)(buf, "/");
sewardj5d616df2013-07-02 08:07:15 +0000517 VG_(strcat)(buf, data_str);
florianc5058202014-12-17 19:52:25 +0000518
519 dirname = ML_(addStr)(di, buf, len);
philippe59e1f3c2014-07-14 21:20:57 +0000520 VG_(addToXA) (dirname_xa, &dirname);
sewardj022bf2f2005-06-14 21:51:14 +0000521 if (0) VG_(printf)("rel path %s\n", buf);
sewardj5d616df2013-07-02 08:07:15 +0000522 ML_(dinfo_free)(compdir_str);
florianc5058202014-12-17 19:52:25 +0000523 ML_(dinfo_free)(buf);
sewardj022bf2f2005-06-14 21:51:14 +0000524 } else {
525 /* just use 'data'. */
philippe59e1f3c2014-07-14 21:20:57 +0000526 dirname = ML_(addStr)(di,data_str,-1);
527 VG_(addToXA) (dirname_xa, &dirname);
sewardj5d616df2013-07-02 08:07:15 +0000528 if (0) VG_(printf)("abs path %s\n", data_str);
sewardj022bf2f2005-06-14 21:51:14 +0000529 }
530
sewardj5d616df2013-07-02 08:07:15 +0000531 data = ML_(cur_plus)(data, VG_(strlen)(data_str) + 1);
532 ML_(dinfo_free)(data_str);
sewardj022bf2f2005-06-14 21:51:14 +0000533 }
sewardj3646a492007-02-16 14:17:10 +0000534
sewardjb8b79ad2008-03-03 01:35:41 +0000535 if (di->ddump_line)
sewardj3646a492007-02-16 14:17:10 +0000536 VG_(printf)("\n");
537
sewardj5d616df2013-07-02 08:07:15 +0000538 if (ML_(cur_read_UChar)(data) != 0) {
sewardjb8b79ad2008-03-03 01:35:41 +0000539 ML_(symerr)(di, True,
540 "can't find NUL at end of DWARF2 directory table");
sewardj022bf2f2005-06-14 21:51:14 +0000541 goto out;
542 }
sewardj5d616df2013-07-02 08:07:15 +0000543 data = ML_(cur_plus)(data, 1);
sewardj022bf2f2005-06-14 21:51:14 +0000544
545 /* Read the contents of the File Name table. This produces a bunch
philippe59e1f3c2014-07-14 21:20:57 +0000546 of fndn_ix in fndn_ix_xa. */
sewardjb8b79ad2008-03-03 01:35:41 +0000547 if (di->ddump_line) {
sewardj3646a492007-02-16 14:17:10 +0000548 VG_(printf)(" The File Name Table:\n");
549 VG_(printf)(" Entry Dir Time Size Name\n");
550 }
551
552 i = 1;
sewardj5d616df2013-07-02 08:07:15 +0000553 while (ML_(cur_read_UChar)(data) != 0) {
554 HChar* name = ML_(cur_step_strdup)(&data, "di.rd2l.2");
555 Int diridx = step_leb128U(&data);
556 Int uu_time = step_leb128U(&data); /* unused */
557 Int uu_size = step_leb128U(&data); /* unused */
philippe59e1f3c2014-07-14 21:20:57 +0000558
559 dirname = safe_dirname_ix( dirname_xa, diridx );
560 fndn_ix = ML_(addFnDn) (di, name, dirname);
561 VG_(addToXA) (fndn_ix_xa, &fndn_ix);
sewardj022bf2f2005-06-14 21:51:14 +0000562 if (0) VG_(printf)("file %s diridx %d\n", name, diridx );
sewardjb8b79ad2008-03-03 01:35:41 +0000563 if (di->ddump_line)
sewardj3646a492007-02-16 14:17:10 +0000564 VG_(printf)(" %d\t%d\t%d\t%d\t%s\n",
565 i, diridx, uu_time, uu_size, name);
566 i++;
sewardj5d616df2013-07-02 08:07:15 +0000567 ML_(dinfo_free)(name);
sewardj022bf2f2005-06-14 21:51:14 +0000568 }
sewardj3646a492007-02-16 14:17:10 +0000569
sewardjb8b79ad2008-03-03 01:35:41 +0000570 if (di->ddump_line)
sewardj3646a492007-02-16 14:17:10 +0000571 VG_(printf)("\n");
572
sewardj5d616df2013-07-02 08:07:15 +0000573 if (ML_(cur_read_UChar)(data) != 0) {
sewardjb8b79ad2008-03-03 01:35:41 +0000574 ML_(symerr)(di, True,
575 "can't find NUL at end of DWARF2 file name table");
sewardj022bf2f2005-06-14 21:51:14 +0000576 goto out;
577 }
sewardj5d616df2013-07-02 08:07:15 +0000578 data = ML_(cur_plus)(data, 1);
sewardj022bf2f2005-06-14 21:51:14 +0000579
sewardjb8b79ad2008-03-03 01:35:41 +0000580 if (di->ddump_line)
sewardj3646a492007-02-16 14:17:10 +0000581 VG_(printf)(" Line Number Statements:\n");
582
sewardj022bf2f2005-06-14 21:51:14 +0000583 /* Now display the statements. */
584
sewardj5d616df2013-07-02 08:07:15 +0000585 while (ML_(cur_cmpLT)(data, end_of_sequence)) {
586 UChar op_code = ML_(cur_step_UChar)(&data);
sewardj022bf2f2005-06-14 21:51:14 +0000587
588 if (0) VG_(printf)("dwarf2: OPC: %d\n", op_code);
589
590 if (op_code >= info.li_opcode_base) {
sewardj022bf2f2005-06-14 21:51:14 +0000591 op_code -= info.li_opcode_base;
sewardj5d616df2013-07-02 08:07:15 +0000592 Word adv = (op_code / info.li_line_range)
sewardj022bf2f2005-06-14 21:51:14 +0000593 * info.li_min_insn_length;
sewardj5d616df2013-07-02 08:07:15 +0000594 Int advAddr = adv;
sewardj022bf2f2005-06-14 21:51:14 +0000595 state_machine_regs.address += adv;
sewardj3646a492007-02-16 14:17:10 +0000596
florianc6e5d762015-08-05 22:27:24 +0000597 if (0) VG_(printf)("smr.a += %#lx\n", (UWord)adv );
sewardj022bf2f2005-06-14 21:51:14 +0000598 adv = (op_code % info.li_line_range) + info.li_line_base;
barta0b6b2c2008-07-07 06:49:24 +0000599 if (0) VG_(printf)("1002: di->o %#lx, smr.a %#lx\n",
florianc6e5d762015-08-05 22:27:24 +0000600 (UWord)di->text_debug_bias,
601 state_machine_regs.address );
sewardj022bf2f2005-06-14 21:51:14 +0000602 state_machine_regs.line += adv;
603
sewardjb8b79ad2008-03-03 01:35:41 +0000604 if (di->ddump_line)
sewardj3646a492007-02-16 14:17:10 +0000605 VG_(printf)(" Special opcode %d: advance Address by %d "
606 "to 0x%lx and Line by %d to %d\n",
607 (Int)op_code, advAddr, state_machine_regs.address,
608 (Int)adv, (Int)state_machine_regs.line );
609
Elliott Hughesa0664b92017-04-18 17:46:52 -0700610 /* only add a statement if there was a previous boundary */
611 if (state_machine_regs.last_address) {
612 ML_(addLineInfo)(
613 di,
614 safe_fndn_ix(fndn_ix_xa,
615 state_machine_regs.last_file),
616 di->text_debug_bias + state_machine_regs.last_address,
617 di->text_debug_bias + state_machine_regs.address,
618 state_machine_regs.last_line,
619 0
620 );
621 }
622 state_machine_regs.last_address = state_machine_regs.address;
623 state_machine_regs.last_file = state_machine_regs.file;
624 state_machine_regs.last_line = state_machine_regs.line;
625 }
626
627 else { /* ! (op_code >= info.li_opcode_base) */
628
629 switch (op_code) {
630 case DW_LNS_extended_op:
631 process_extended_line_op(di, fndn_ix_xa, &data);
632 break;
633
634 case DW_LNS_copy:
635 if (0) VG_(printf)("1002: di->o %#lx, smr.a %#lx\n",
636 (UWord)di->text_debug_bias,
637 state_machine_regs.address );
sewardj022bf2f2005-06-14 21:51:14 +0000638 /* only add a statement if there was a previous boundary */
sewardj1ff57e62007-11-20 08:46:05 +0000639 if (state_machine_regs.last_address) {
sewardj7eb7c582005-06-23 01:02:53 +0000640 ML_(addLineInfo)(
philippe59e1f3c2014-07-14 21:20:57 +0000641 di,
Elliott Hughesa0664b92017-04-18 17:46:52 -0700642 safe_fndn_ix(fndn_ix_xa,
643 state_machine_regs.last_file),
tom402c9ee2009-03-09 09:19:03 +0000644 di->text_debug_bias + state_machine_regs.last_address,
Elliott Hughesa0664b92017-04-18 17:46:52 -0700645 di->text_debug_bias + state_machine_regs.address,
sewardj022bf2f2005-06-14 21:51:14 +0000646 state_machine_regs.last_line,
647 0
648 );
sewardj1ff57e62007-11-20 08:46:05 +0000649 }
sewardj022bf2f2005-06-14 21:51:14 +0000650 state_machine_regs.last_address = state_machine_regs.address;
651 state_machine_regs.last_file = state_machine_regs.file;
652 state_machine_regs.last_line = state_machine_regs.line;
sewardj022bf2f2005-06-14 21:51:14 +0000653 state_machine_regs.basic_block = 0; /* JRS added */
sewardjb8b79ad2008-03-03 01:35:41 +0000654 if (di->ddump_line)
sewardj3646a492007-02-16 14:17:10 +0000655 VG_(printf)(" Copy\n");
sewardj022bf2f2005-06-14 21:51:14 +0000656 break;
657
sewardj5d616df2013-07-02 08:07:15 +0000658 case DW_LNS_advance_pc: {
florianc6e5d762015-08-05 22:27:24 +0000659 UWord adv = info.li_min_insn_length * step_leb128U(&data);
sewardj022bf2f2005-06-14 21:51:14 +0000660 state_machine_regs.address += adv;
sewardj5d616df2013-07-02 08:07:15 +0000661 if (0) VG_(printf)("smr.a += %#lx\n", adv );
sewardjb8b79ad2008-03-03 01:35:41 +0000662 if (di->ddump_line)
florianc6e5d762015-08-05 22:27:24 +0000663 VG_(printf)(" Advance PC by %lu to 0x%lx\n",
sewardj5d616df2013-07-02 08:07:15 +0000664 adv, state_machine_regs.address);
sewardj022bf2f2005-06-14 21:51:14 +0000665 break;
sewardj5d616df2013-07-02 08:07:15 +0000666 }
667 case DW_LNS_advance_line: {
668 Word adv = step_leb128S(&data);
sewardj022bf2f2005-06-14 21:51:14 +0000669 state_machine_regs.line += adv;
sewardjb8b79ad2008-03-03 01:35:41 +0000670 if (di->ddump_line)
sewardj5d616df2013-07-02 08:07:15 +0000671 VG_(printf)(" Advance Line by %ld to %d\n",
672 adv, (Int)state_machine_regs.line);
sewardj022bf2f2005-06-14 21:51:14 +0000673 break;
sewardj5d616df2013-07-02 08:07:15 +0000674 }
675 case DW_LNS_set_file: {
676 Word adv = step_leb128U(&data);
sewardj022bf2f2005-06-14 21:51:14 +0000677 state_machine_regs.file = adv;
sewardjb8b79ad2008-03-03 01:35:41 +0000678 if (di->ddump_line)
sewardj5d616df2013-07-02 08:07:15 +0000679 VG_(printf)(" Set File Name to entry %ld in the "
680 "File Name Table\n", adv);
sewardj022bf2f2005-06-14 21:51:14 +0000681 break;
sewardj5d616df2013-07-02 08:07:15 +0000682 }
683 case DW_LNS_set_column: {
684 Word adv = step_leb128U(&data);
sewardj022bf2f2005-06-14 21:51:14 +0000685 state_machine_regs.column = adv;
sewardjb8b79ad2008-03-03 01:35:41 +0000686 if (di->ddump_line)
sewardj5d616df2013-07-02 08:07:15 +0000687 VG_(printf)(" Set column to %ld\n", adv);
sewardj022bf2f2005-06-14 21:51:14 +0000688 break;
sewardj5d616df2013-07-02 08:07:15 +0000689 }
690 case DW_LNS_negate_stmt: {
sewardjb8b79ad2008-03-03 01:35:41 +0000691 if (di->ddump_line)
sewardj3646a492007-02-16 14:17:10 +0000692 VG_(printf)(" DWARF2-line: negate_stmt\n");
sewardj022bf2f2005-06-14 21:51:14 +0000693 break;
sewardj5d616df2013-07-02 08:07:15 +0000694 }
695 case DW_LNS_set_basic_block: {
sewardj022bf2f2005-06-14 21:51:14 +0000696 state_machine_regs.basic_block = 1;
sewardjb8b79ad2008-03-03 01:35:41 +0000697 if (di->ddump_line)
sewardj3646a492007-02-16 14:17:10 +0000698 VG_(printf)(" DWARF2-line: set_basic_block\n");
sewardj022bf2f2005-06-14 21:51:14 +0000699 break;
sewardj5d616df2013-07-02 08:07:15 +0000700 }
701 case DW_LNS_const_add_pc: {
702 Word adv = (((255 - info.li_opcode_base) / info.li_line_range)
703 * info.li_min_insn_length);
sewardj022bf2f2005-06-14 21:51:14 +0000704 state_machine_regs.address += adv;
florianc6e5d762015-08-05 22:27:24 +0000705 if (0) VG_(printf)("smr.a += %#lx\n", (UWord)adv );
sewardjb8b79ad2008-03-03 01:35:41 +0000706 if (di->ddump_line)
sewardj5d616df2013-07-02 08:07:15 +0000707 VG_(printf)(" Advance PC by constant %ld to 0x%lx\n",
708 adv, (Addr)state_machine_regs.address);
sewardj022bf2f2005-06-14 21:51:14 +0000709 break;
sewardj5d616df2013-07-02 08:07:15 +0000710 }
711 case DW_LNS_fixed_advance_pc: {
sewardj022bf2f2005-06-14 21:51:14 +0000712 /* XXX: Need something to get 2 bytes */
florianc6e5d762015-08-05 22:27:24 +0000713 UWord adv = ML_(cur_step_UShort)(&data);
sewardj022bf2f2005-06-14 21:51:14 +0000714 state_machine_regs.address += adv;
sewardj5d616df2013-07-02 08:07:15 +0000715 if (0) VG_(printf)("smr.a += %#lx\n", adv );
sewardjb8b79ad2008-03-03 01:35:41 +0000716 if (di->ddump_line)
sewardj3646a492007-02-16 14:17:10 +0000717 VG_(printf)(" DWARF2-line: fixed_advance_pc\n");
sewardj022bf2f2005-06-14 21:51:14 +0000718 break;
sewardj5d616df2013-07-02 08:07:15 +0000719 }
sewardj022bf2f2005-06-14 21:51:14 +0000720 case DW_LNS_set_prologue_end:
sewardjb8b79ad2008-03-03 01:35:41 +0000721 if (di->ddump_line)
sewardj3646a492007-02-16 14:17:10 +0000722 VG_(printf)(" DWARF2-line: set_prologue_end\n");
sewardj022bf2f2005-06-14 21:51:14 +0000723 break;
724
725 case DW_LNS_set_epilogue_begin:
sewardjb8b79ad2008-03-03 01:35:41 +0000726 if (di->ddump_line)
sewardj3646a492007-02-16 14:17:10 +0000727 VG_(printf)(" DWARF2-line: set_epilogue_begin\n");
sewardj022bf2f2005-06-14 21:51:14 +0000728 break;
729
730 case DW_LNS_set_isa:
sewardj5d616df2013-07-02 08:07:15 +0000731 (void)step_leb128U(&data);
sewardjb8b79ad2008-03-03 01:35:41 +0000732 if (di->ddump_line)
sewardj3646a492007-02-16 14:17:10 +0000733 VG_(printf)(" DWARF2-line: set_isa\n");
sewardj022bf2f2005-06-14 21:51:14 +0000734 break;
735
736 default: {
737 Int j;
sewardj5d616df2013-07-02 08:07:15 +0000738 for (j = (Int)ML_(cur_read_UChar)(
739 ML_(cur_plus)(standard_opcodes,
740 (op_code-1) * sizeof(UChar)));
741 j > 0 ; --j) {
742 step_leb128U(&data);
sewardj022bf2f2005-06-14 21:51:14 +0000743 }
sewardjb8b79ad2008-03-03 01:35:41 +0000744 if (di->ddump_line)
sewardj3646a492007-02-16 14:17:10 +0000745 VG_(printf)(" Unknown opcode %d\n", (Int)op_code);
746 break;
sewardj022bf2f2005-06-14 21:51:14 +0000747 }
sewardj022bf2f2005-06-14 21:51:14 +0000748 } /* switch (op_code) */
749
sewardj3646a492007-02-16 14:17:10 +0000750 } /* if (op_code >= info.li_opcode_base) */
751
sewardj022bf2f2005-06-14 21:51:14 +0000752 } /* while (data < end_of_sequence) */
753
sewardjb8b79ad2008-03-03 01:35:41 +0000754 if (di->ddump_line)
sewardj3646a492007-02-16 14:17:10 +0000755 VG_(printf)("\n");
756
sewardj022bf2f2005-06-14 21:51:14 +0000757 out:
philippe59e1f3c2014-07-14 21:20:57 +0000758 VG_(deleteXA)(dirname_xa);
759 VG_(deleteXA)(fndn_ix_xa);
sewardj022bf2f2005-06-14 21:51:14 +0000760}
761
762////////////////////////////////////////////////////////////////////
763////////////////////////////////////////////////////////////////////
764
765/* Return abbrev for given code
sewardj5d616df2013-07-02 08:07:15 +0000766 * Returned cursor points to the tag
sewardj022bf2f2005-06-14 21:51:14 +0000767 * */
sewardj5d616df2013-07-02 08:07:15 +0000768static DiCursor lookup_abbrev( DiCursor p, ULong acode )
sewardj022bf2f2005-06-14 21:51:14 +0000769{
sewardj5d616df2013-07-02 08:07:15 +0000770 while (1) {
771 ULong code = step_leb128U(&p);
772 if (code == acode)
sewardj022bf2f2005-06-14 21:51:14 +0000773 return p;
sewardj5d616df2013-07-02 08:07:15 +0000774 (void)step_leb128U(&p); /* skip tag */
775 p = ML_(cur_plus)(p,1); /* skip has_children flag */
776 ULong name;
sewardj022bf2f2005-06-14 21:51:14 +0000777 do {
sewardj5d616df2013-07-02 08:07:15 +0000778 name = step_leb128U(&p); /* name */
779 (void)step_leb128U(&p); /* form */
sewardj022bf2f2005-06-14 21:51:14 +0000780 }
sewardj5d616df2013-07-02 08:07:15 +0000781 while (name != 0); /* until name == form == 0 */
sewardj022bf2f2005-06-14 21:51:14 +0000782 }
sewardj022bf2f2005-06-14 21:51:14 +0000783}
784
785/* Read general information for a particular compile unit block in
mjw4c3b2372013-04-17 13:48:29 +0000786 * the .debug_info section. In particular read the name, compdir and
787 * stmt_list needed to parse the line number information.
sewardj022bf2f2005-06-14 21:51:14 +0000788 *
789 * Input: - unitblock is the start of a compilation
790 * unit block in .debuginfo section
791 * - debugabbrev is start of .debug_abbrev section
792 * - debugstr is start of .debug_str section
mjw4c3b2372013-04-17 13:48:29 +0000793 * - debugstr_alt_img is start of .debug_str section in alt debug file
sewardj022bf2f2005-06-14 21:51:14 +0000794 *
795 * Output: Fill members of ui pertaining to the compilation unit:
796 * - ui->name is the name of the compilation unit
797 * - ui->compdir is the compilation unit directory
798 * - ui->stmt_list is the offset in .debug_line section
799 * for the dbginfos of this compilation unit
800 *
801 * Note : the output strings are not allocated and point
802 * directly to the memory-mapped section.
803 */
804static
805void read_unitinfo_dwarf2( /*OUT*/UnitInfo* ui,
sewardj5d616df2013-07-02 08:07:15 +0000806 DiCursor unitblock_img,
807 DiCursor debugabbrev_img,
808 DiCursor debugstr_img,
809 DiCursor debugstr_alt_img )
sewardj022bf2f2005-06-14 21:51:14 +0000810{
sewardj11624912006-02-09 23:35:11 +0000811 UInt acode, abcode;
812 ULong atoffs, blklen;
mjw58d9ce42013-04-11 17:55:39 +0000813 UShort ver;
sewardj022bf2f2005-06-14 21:51:14 +0000814
sewardj5d616df2013-07-02 08:07:15 +0000815 UChar addr_size;
816 DiCursor p = unitblock_img;
817 DiCursor end_img;
818 DiCursor abbrev_img;
sewardj022bf2f2005-06-14 21:51:14 +0000819
820 VG_(memset)( ui, 0, sizeof( UnitInfo ) );
sewardj11624912006-02-09 23:35:11 +0000821 ui->stmt_list = -1LL;
sewardj022bf2f2005-06-14 21:51:14 +0000822
sewardj11624912006-02-09 23:35:11 +0000823 /* Read the compilation unit header in .debug_info section - See p 70 */
sewardj022bf2f2005-06-14 21:51:14 +0000824
sewardj11624912006-02-09 23:35:11 +0000825 /* This block length */
sewardj5d616df2013-07-02 08:07:15 +0000826 blklen = step_initial_length_field( &p, &ui->dw64 );
sewardj11624912006-02-09 23:35:11 +0000827
tomfba428c2010-04-28 08:09:30 +0000828 /* version should be 2, 3 or 4 */
sewardj5d616df2013-07-02 08:07:15 +0000829 ver = ML_(cur_step_UShort)(&p);
sewardj11624912006-02-09 23:35:11 +0000830
831 /* get offset in abbrev */
sewardj5d616df2013-07-02 08:07:15 +0000832 atoffs = ui->dw64 ? ML_(cur_step_ULong)(&p)
833 : (ULong)(ML_(cur_step_UInt)(&p));
sewardj11624912006-02-09 23:35:11 +0000834
835 /* Address size */
sewardj5d616df2013-07-02 08:07:15 +0000836 addr_size = ML_(cur_step_UChar)(&p);
sewardj11624912006-02-09 23:35:11 +0000837
sewardj5d616df2013-07-02 08:07:15 +0000838 /* End of this block */
839 end_img = ML_(cur_plus)(unitblock_img, blklen + (ui->dw64 ? 12 : 4));
840
841 /* Abbreviation data for this block */
842 abbrev_img = ML_(cur_plus)(debugabbrev_img, atoffs);
sewardj022bf2f2005-06-14 21:51:14 +0000843
mjw4c3b2372013-04-17 13:48:29 +0000844 /* Read the compilation unit entry - this is always the first DIE.
845 * See DWARF4 para 7.5. */
sewardj5d616df2013-07-02 08:07:15 +0000846 if (ML_(cur_cmpLT)(p, end_img)) {
sewardj022bf2f2005-06-14 21:51:14 +0000847 UInt tag;
848
sewardj5d616df2013-07-02 08:07:15 +0000849 acode = step_leb128U( &p ); /* abbreviation code */
sewardj022bf2f2005-06-14 21:51:14 +0000850
851 /* Read abbreviation header */
sewardj5d616df2013-07-02 08:07:15 +0000852 abcode = step_leb128U( &abbrev_img ); /* abbreviation code */
sewardj022bf2f2005-06-14 21:51:14 +0000853 if ( acode != abcode ) {
mjw4c3b2372013-04-17 13:48:29 +0000854 /* This isn't illegal, but somewhat unlikely. Normally the
855 * first abbrev describes the first DIE, the compile_unit.
Elliott Hughesed398002017-06-21 14:41:24 -0700856 * But maybe this abbreviation data is shared with another
mjw4c3b2372013-04-17 13:48:29 +0000857 * or it is a NULL entry used for padding. See para 7.5.3. */
sewardj5d616df2013-07-02 08:07:15 +0000858 abbrev_img = lookup_abbrev( ML_(cur_plus)(debugabbrev_img, atoffs),
859 acode );
sewardj022bf2f2005-06-14 21:51:14 +0000860 }
861
sewardj5d616df2013-07-02 08:07:15 +0000862 tag = step_leb128U( &abbrev_img );
sewardj022bf2f2005-06-14 21:51:14 +0000863
mjw4c3b2372013-04-17 13:48:29 +0000864 if ( tag != 0x0011 /*TAG_compile_unit*/ )
865 return; /* Not a compile unit (might be partial) or broken DWARF. */
866
sewardj5d616df2013-07-02 08:07:15 +0000867 /* DW_CHILDREN_yes or DW_CHILDREN_no */
868 abbrev_img = ML_(cur_plus)(abbrev_img, 1);
sewardj022bf2f2005-06-14 21:51:14 +0000869
870 /* And loop on entries */
871 for ( ; ; ) {
872 /* Read entry definition */
sewardj5d616df2013-07-02 08:07:15 +0000873 ULong cval = -1LL; /* Constant value read */
874 DiCursor sval = DiCursor_INVALID; /* String value read */
875 UInt name = step_leb128U( &abbrev_img );
876 UInt form = step_leb128U( &abbrev_img );
877 if (name == 0)
sewardj022bf2f2005-06-14 21:51:14 +0000878 break;
879
880 /* Read data */
881 /* Attributes encoding explained p 71 */
882 if ( form == 0x16 /* FORM_indirect */ )
sewardj5d616df2013-07-02 08:07:15 +0000883 form = step_leb128U( &p );
sewardj022bf2f2005-06-14 21:51:14 +0000884 /* Decode form. For most kinds, Just skip the amount of data since
885 we don't use it for now */
sewardj11624912006-02-09 23:35:11 +0000886 /* JRS 9 Feb 06: This now handles 64-bit DWARF too. In
887 64-bit DWARF, lineptr (and loclistptr,macptr,rangelistptr
888 classes) use FORM_data8, not FORM_data4. Also,
889 FORM_ref_addr and FORM_strp are 64-bit values, not 32-bit
890 values. */
tomfba428c2010-04-28 08:09:30 +0000891 /* TJH 27 Apr 10: in DWARF 4 lineptr (and loclistptr,macptr,
892 rangelistptr classes) use FORM_sec_offset which is 64 bits
893 in 64 bit DWARF and 32 bits in 32 bit DWARF. */
sewardj06938af2011-04-21 08:55:51 +0000894 /* JRS 20 Apr 11: LLVM-2.9 encodes DW_AT_stmt_list using
895 FORM_addr rather than the FORM_data4 that GCC uses. Hence
896 handle FORM_addr too. */
sewardj022bf2f2005-06-14 21:51:14 +0000897 switch( form ) {
898 /* Those cases extract the data properly */
sewardj5d616df2013-07-02 08:07:15 +0000899 case 0x05: /* FORM_data2 */
900 cval = ML_(cur_step_UShort)(&p);
901 break;
902 case 0x06: /* FORM_data4 */
903 cval = ML_(cur_step_UInt)(&p);
904 break;
sewardj1a0e39f2006-01-01 23:00:49 +0000905 case 0x0e: /* FORM_strp */ /* pointer in .debug_str */
sewardj5d616df2013-07-02 08:07:15 +0000906 /* 2006-01-01: only generate a value if a debug_str
907 section was found) */
908 if (ML_(cur_is_valid)(debugstr_img) && !ui->dw64)
909 sval = ML_(cur_plus)(debugstr_img, ML_(cur_read_UInt)(p));
910 if (ML_(cur_is_valid)(debugstr_img) && ui->dw64)
911 sval = ML_(cur_plus)(debugstr_img, ML_(cur_read_ULong)(p));
912 p = ML_(cur_plus)(p, ui->dw64 ? 8 : 4);
913 break;
914 case 0x08: /* FORM_string */
915 sval = p;
916 p = ML_(cur_plus)(p, ML_(cur_strlen)(p) + 1);
917 break;
918 case 0x0b: /* FORM_data1 */
919 cval = ML_(cur_step_UChar)(&p);
920 break;
921 case 0x17: /* FORM_sec_offset */
922 if (ui->dw64) {
923 cval = ML_(cur_step_ULong)(&p);
924 } else {
925 cval = ML_(cur_step_UInt)(&p);
926 };
927 break;
928 case 0x07: /* FORM_data8 */
929 if (ui->dw64) cval = ML_(cur_read_ULong)(p);
930 p = ML_(cur_plus)(p, 8);
931 /* perhaps should assign unconditionally to cval? */
932 break;
sewardj06938af2011-04-21 08:55:51 +0000933 /* TODO : Following ones just skip data - implement if you need */
sewardj5d616df2013-07-02 08:07:15 +0000934 case 0x01: /* FORM_addr */
935 p = ML_(cur_plus)(p, addr_size);
936 break;
937 case 0x03: /* FORM_block2 */
938 p = ML_(cur_plus)(p, ML_(cur_read_UShort)(p) + 2);
939 break;
940 case 0x04: /* FORM_block4 */
941 p = ML_(cur_plus)(p, ML_(cur_read_UInt)(p) + 4);
942 break;
943 case 0x09: /* FORM_block */ /* fallthrough */
944 case 0x18: { /* FORM_exprloc */
945 ULong block_len = step_leb128U(&p);
946 p = ML_(cur_plus)(p, block_len);
947 break;
948 }
949 case 0x0a: /* FORM_block1 */
950 p = ML_(cur_plus)(p, ML_(cur_read_UChar)(p) + 1);
951 break;
952 case 0x0c: /* FORM_flag */
953 p = ML_(cur_plus)(p, 1);
954 break;
955 case 0x0d: /* FORM_sdata */
956 (void)step_leb128S(&p);
957 break;
958 case 0x0f: /* FORM_udata */
959 (void)step_leb128U(&p);
960 break;
961 case 0x10: /* FORM_ref_addr */
962 p = ML_(cur_plus)(p, (ver == 2) ? addr_size
963 : (ui->dw64 ? 8 : 4));
964 break;
965 case 0x11: /* FORM_ref1 */
966 p = ML_(cur_plus)(p, 1);
967 break;
968 case 0x12: /* FORM_ref2 */
969 p = ML_(cur_plus)(p, 2);
970 break;
971 case 0x13: /* FORM_ref4 */
972 p = ML_(cur_plus)(p, 4);
973 break;
974 case 0x14: /* FORM_ref8 */
975 p = ML_(cur_plus)(p, 8);
976 break;
977 case 0x15: /* FORM_ref_udata */
978 (void)step_leb128U(&p);
979 break;
980 case 0x19: /* FORM_flag_present */
981 break;
982 case 0x20: /* FORM_ref_sig8 */
983 p = ML_(cur_plus)(p, 8);
984 break;
985 case 0x1f20: /* FORM_GNU_ref_alt */
986 p = ML_(cur_plus)(p, ui->dw64 ? 8 : 4);
987 break;
sewardjf7c97142012-07-14 09:59:01 +0000988 case 0x1f21: /* FORM_GNU_strp_alt */
sewardj5d616df2013-07-02 08:07:15 +0000989 if (ML_(cur_is_valid)(debugstr_alt_img) && !ui->dw64)
990 sval = ML_(cur_plus)(debugstr_alt_img,
991 ML_(cur_read_UInt)(p));
992 if (ML_(cur_is_valid)(debugstr_alt_img) && ui->dw64)
993 sval = ML_(cur_plus)(debugstr_alt_img,
994 ML_(cur_read_ULong)(p));
995 p = ML_(cur_plus)(p, ui->dw64 ? 8 : 4);
996 break;
tomfba428c2010-04-28 08:09:30 +0000997
sewardj022bf2f2005-06-14 21:51:14 +0000998 default:
sewardj5d616df2013-07-02 08:07:15 +0000999 VG_(printf)( "### unhandled dwarf2 abbrev form code 0x%x\n",
1000 form );
sewardj022bf2f2005-06-14 21:51:14 +00001001 break;
1002 }
1003
1004 /* Now store the members we need in the UnitInfo structure */
1005 if ( tag == 0x0011 /*TAG_compile_unit*/ ) {
1006 if ( name == 0x03 ) ui->name = sval; /* DW_AT_name */
1007 else if ( name == 0x1b ) ui->compdir = sval; /* DW_AT_compdir */
1008 else if ( name == 0x10 ) ui->stmt_list = cval; /* DW_AT_stmt_list */
1009 }
1010 }
mjw4c3b2372013-04-17 13:48:29 +00001011 } /* Just read the first DIE, if that wasn't the compile_unit then
1012 * this might have been a partial unit or broken DWARF info.
1013 * That's enough info for us, and we are not gdb ! */
sewardj022bf2f2005-06-14 21:51:14 +00001014}
1015
1016
1017////////////////////////////////////////////////////////////////////
1018////////////////////////////////////////////////////////////////////
1019
sewardjb8b79ad2008-03-03 01:35:41 +00001020/* Collect the debug info from DWARF3 debugging sections
sewardj022bf2f2005-06-14 21:51:14 +00001021 * of a given module.
1022 *
1023 * Inputs: given .debug_xxx sections
sewardjb8b79ad2008-03-03 01:35:41 +00001024 * Output: update di to contain all the DWARF3 debug infos
sewardj022bf2f2005-06-14 21:51:14 +00001025 */
sewardjb8b79ad2008-03-03 01:35:41 +00001026void ML_(read_debuginfo_dwarf3)
1027 ( struct _DebugInfo* di,
sewardj5d616df2013-07-02 08:07:15 +00001028 DiSlice escn_debug_info, /* .debug_info */
1029 DiSlice escn_debug_types, /* .debug_types */
1030 DiSlice escn_debug_abbv, /* .debug_abbrev */
1031 DiSlice escn_debug_line, /* .debug_line */
1032 DiSlice escn_debug_str, /* .debug_str */
1033 DiSlice escn_debug_str_alt ) /* .debug_str */
sewardj022bf2f2005-06-14 21:51:14 +00001034{
1035 UnitInfo ui;
sewardj11624912006-02-09 23:35:11 +00001036 UShort ver;
sewardj11624912006-02-09 23:35:11 +00001037 ULong blklen;
1038 Bool blklen_is_64;
sewardj022bf2f2005-06-14 21:51:14 +00001039
tom50d01ab2005-10-04 16:54:54 +00001040 /* Make sure we at least have a header for the first block */
sewardj5d616df2013-07-02 08:07:15 +00001041 if (escn_debug_info.szB < 4) {
sewardjb8b79ad2008-03-03 01:35:41 +00001042 ML_(symerr)( di, True,
1043 "Last block truncated in .debug_info; ignoring" );
tom50d01ab2005-10-04 16:54:54 +00001044 return;
1045 }
1046
sewardj5d616df2013-07-02 08:07:15 +00001047 DiCursor block_img = DiCursor_INVALID;
1048 DiCursor end1_img = ML_(cur_plus)( ML_(cur_from_sli)(escn_debug_info),
1049 escn_debug_info.szB );
1050 Int blklen_len = 0;
1051
sewardj022bf2f2005-06-14 21:51:14 +00001052 /* Iterate on all the blocks we find in .debug_info */
sewardj5d616df2013-07-02 08:07:15 +00001053 for ( block_img = ML_(cur_from_sli)(escn_debug_info);
1054 ML_(cur_cmpLT)(block_img, ML_(cur_plus)(end1_img, -(DiOffT)4));
1055 block_img = ML_(cur_plus)(block_img, blklen + blklen_len) ) {
sewardj022bf2f2005-06-14 21:51:14 +00001056
1057 /* Read the compilation unit header in .debug_info section - See
1058 p 70 */
sewardj11624912006-02-09 23:35:11 +00001059 /* This block length */
sewardjf767d962007-02-12 17:47:14 +00001060 blklen = read_initial_length_field( block_img, &blklen_is_64 );
sewardj11624912006-02-09 23:35:11 +00001061 blklen_len = blklen_is_64 ? 12 : 4;
sewardj5d616df2013-07-02 08:07:15 +00001062
1063 if (ML_(cur_cmpGT)( ML_(cur_plus)(block_img, blklen + blklen_len),
1064 end1_img )) {
sewardjb8b79ad2008-03-03 01:35:41 +00001065 ML_(symerr)( di, True,
1066 "Last block truncated in .debug_info; ignoring" );
sewardj022bf2f2005-06-14 21:51:14 +00001067 return;
1068 }
sewardj11624912006-02-09 23:35:11 +00001069
1070 /* version should be 2 */
sewardj5d616df2013-07-02 08:07:15 +00001071 ver = ML_(cur_read_UShort)( ML_(cur_plus)(block_img, blklen_len) );
tomfba428c2010-04-28 08:09:30 +00001072 if ( ver != 2 && ver != 3 && ver != 4 ) {
sewardjb8b79ad2008-03-03 01:35:41 +00001073 ML_(symerr)( di, True,
tomfba428c2010-04-28 08:09:30 +00001074 "Ignoring non-Dwarf2/3/4 block in .debug_info" );
sewardj022bf2f2005-06-14 21:51:14 +00001075 continue;
1076 }
1077
1078 /* Fill ui with offset in .debug_line and compdir */
sewardj11624912006-02-09 23:35:11 +00001079 if (0)
sewardj5d616df2013-07-02 08:07:15 +00001080 VG_(printf)(
1081 "Reading UnitInfo at 0x%llx.....\n",
1082 (ULong)ML_(cur_minus)( block_img,
1083 ML_(cur_from_sli)(escn_debug_info)) );
sewardjb8b79ad2008-03-03 01:35:41 +00001084 read_unitinfo_dwarf2( &ui, block_img,
sewardj5d616df2013-07-02 08:07:15 +00001085 ML_(cur_from_sli)(escn_debug_abbv),
1086 ML_(cur_from_sli)(escn_debug_str),
1087 ML_(cur_from_sli)(escn_debug_str_alt) );
1088 if (0) {
1089 HChar* str_name = ML_(cur_read_strdup)(ui.name, "di.rdd3.1");
1090 HChar* str_compdir = ML_(cur_read_strdup)(ui.compdir, "di.rdd3.2");
sewardj11624912006-02-09 23:35:11 +00001091 VG_(printf)( " => LINES=0x%llx NAME=%s DIR=%s\n",
sewardj5d616df2013-07-02 08:07:15 +00001092 ui.stmt_list, str_name, str_compdir );
1093 ML_(dinfo_free)(str_name);
1094 ML_(dinfo_free)(str_compdir);
1095 }
1096
sewardj022bf2f2005-06-14 21:51:14 +00001097 /* Ignore blocks with no .debug_line associated block */
sewardj11624912006-02-09 23:35:11 +00001098 if ( ui.stmt_list == -1LL )
sewardj022bf2f2005-06-14 21:51:14 +00001099 continue;
1100
sewardj5d616df2013-07-02 08:07:15 +00001101 if (0) {
1102 HChar* str_name = ML_(cur_read_strdup)(ui.name, "di.rdd3.3");
florianc6e5d762015-08-05 22:27:24 +00001103 VG_(printf)("debug_line_sz %llu, ui.stmt_list %llu %s\n",
sewardj5d616df2013-07-02 08:07:15 +00001104 escn_debug_line.szB, ui.stmt_list, str_name );
1105 ML_(dinfo_free)(str_name);
1106 }
1107
sewardj022bf2f2005-06-14 21:51:14 +00001108 /* Read the .debug_line block for this compile unit */
sewardj5d616df2013-07-02 08:07:15 +00001109 read_dwarf2_lineblock(
1110 di, &ui,
1111 ML_(cur_plus)(ML_(cur_from_sli)(escn_debug_line), ui.stmt_list),
1112 escn_debug_line.szB - ui.stmt_list
1113 );
sewardj022bf2f2005-06-14 21:51:14 +00001114 }
1115}
1116
1117
1118////////////////////////////////////////////////////////////////////
1119////////////////////////////////////////////////////////////////////
jseward8b3131a2003-12-13 23:16:26 +00001120
1121/*------------------------------------------------------------*/
1122/*--- Read DWARF1 format line number info. ---*/
1123/*------------------------------------------------------------*/
1124
1125/* DWARF1 appears to be redundant, but nevertheless the Lahey Fortran
1126 compiler generates it.
1127*/
1128
1129/* The following three enums (dwarf_tag, dwarf_form, dwarf_attribute)
1130 are taken from the file include/elf/dwarf.h in the GNU gdb-6.0
1131 sources, which are Copyright 1992, 1993, 1995, 1999 Free Software
1132 Foundation, Inc and naturally licensed under the GNU General Public
1133 License version 2 or later.
1134*/
1135
1136/* Tag names and codes. */
1137
1138enum dwarf_tag {
1139 TAG_padding = 0x0000,
1140 TAG_array_type = 0x0001,
1141 TAG_class_type = 0x0002,
1142 TAG_entry_point = 0x0003,
1143 TAG_enumeration_type = 0x0004,
1144 TAG_formal_parameter = 0x0005,
1145 TAG_global_subroutine = 0x0006,
1146 TAG_global_variable = 0x0007,
1147 /* 0x0008 -- reserved */
1148 /* 0x0009 -- reserved */
1149 TAG_label = 0x000a,
1150 TAG_lexical_block = 0x000b,
1151 TAG_local_variable = 0x000c,
1152 TAG_member = 0x000d,
1153 /* 0x000e -- reserved */
1154 TAG_pointer_type = 0x000f,
1155 TAG_reference_type = 0x0010,
1156 TAG_compile_unit = 0x0011,
1157 TAG_string_type = 0x0012,
1158 TAG_structure_type = 0x0013,
1159 TAG_subroutine = 0x0014,
1160 TAG_subroutine_type = 0x0015,
1161 TAG_typedef = 0x0016,
1162 TAG_union_type = 0x0017,
1163 TAG_unspecified_parameters = 0x0018,
1164 TAG_variant = 0x0019,
1165 TAG_common_block = 0x001a,
1166 TAG_common_inclusion = 0x001b,
1167 TAG_inheritance = 0x001c,
1168 TAG_inlined_subroutine = 0x001d,
1169 TAG_module = 0x001e,
1170 TAG_ptr_to_member_type = 0x001f,
1171 TAG_set_type = 0x0020,
1172 TAG_subrange_type = 0x0021,
1173 TAG_with_stmt = 0x0022,
1174
1175 /* GNU extensions */
1176
1177 TAG_format_label = 0x8000, /* for FORTRAN 77 and Fortran 90 */
1178 TAG_namelist = 0x8001, /* For Fortran 90 */
1179 TAG_function_template = 0x8002, /* for C++ */
1180 TAG_class_template = 0x8003 /* for C++ */
1181};
1182
1183/* Form names and codes. */
1184
1185enum dwarf_form {
1186 FORM_ADDR = 0x1,
1187 FORM_REF = 0x2,
1188 FORM_BLOCK2 = 0x3,
1189 FORM_BLOCK4 = 0x4,
1190 FORM_DATA2 = 0x5,
1191 FORM_DATA4 = 0x6,
1192 FORM_DATA8 = 0x7,
1193 FORM_STRING = 0x8
1194};
1195
1196/* Attribute names and codes. */
1197
1198enum dwarf_attribute {
1199 AT_sibling = (0x0010|FORM_REF),
1200 AT_location = (0x0020|FORM_BLOCK2),
1201 AT_name = (0x0030|FORM_STRING),
1202 AT_fund_type = (0x0050|FORM_DATA2),
1203 AT_mod_fund_type = (0x0060|FORM_BLOCK2),
1204 AT_user_def_type = (0x0070|FORM_REF),
1205 AT_mod_u_d_type = (0x0080|FORM_BLOCK2),
1206 AT_ordering = (0x0090|FORM_DATA2),
1207 AT_subscr_data = (0x00a0|FORM_BLOCK2),
1208 AT_byte_size = (0x00b0|FORM_DATA4),
1209 AT_bit_offset = (0x00c0|FORM_DATA2),
1210 AT_bit_size = (0x00d0|FORM_DATA4),
1211 /* (0x00e0|FORM_xxxx) -- reserved */
1212 AT_element_list = (0x00f0|FORM_BLOCK4),
1213 AT_stmt_list = (0x0100|FORM_DATA4),
1214 AT_low_pc = (0x0110|FORM_ADDR),
1215 AT_high_pc = (0x0120|FORM_ADDR),
1216 AT_language = (0x0130|FORM_DATA4),
1217 AT_member = (0x0140|FORM_REF),
1218 AT_discr = (0x0150|FORM_REF),
1219 AT_discr_value = (0x0160|FORM_BLOCK2),
1220 /* (0x0170|FORM_xxxx) -- reserved */
1221 /* (0x0180|FORM_xxxx) -- reserved */
1222 AT_string_length = (0x0190|FORM_BLOCK2),
1223 AT_common_reference = (0x01a0|FORM_REF),
1224 AT_comp_dir = (0x01b0|FORM_STRING),
1225 AT_const_value_string = (0x01c0|FORM_STRING),
1226 AT_const_value_data2 = (0x01c0|FORM_DATA2),
1227 AT_const_value_data4 = (0x01c0|FORM_DATA4),
1228 AT_const_value_data8 = (0x01c0|FORM_DATA8),
1229 AT_const_value_block2 = (0x01c0|FORM_BLOCK2),
1230 AT_const_value_block4 = (0x01c0|FORM_BLOCK4),
1231 AT_containing_type = (0x01d0|FORM_REF),
1232 AT_default_value_addr = (0x01e0|FORM_ADDR),
1233 AT_default_value_data2 = (0x01e0|FORM_DATA2),
1234 AT_default_value_data4 = (0x01e0|FORM_DATA4),
1235 AT_default_value_data8 = (0x01e0|FORM_DATA8),
1236 AT_default_value_string = (0x01e0|FORM_STRING),
1237 AT_friends = (0x01f0|FORM_BLOCK2),
1238 AT_inline = (0x0200|FORM_STRING),
1239 AT_is_optional = (0x0210|FORM_STRING),
1240 AT_lower_bound_ref = (0x0220|FORM_REF),
1241 AT_lower_bound_data2 = (0x0220|FORM_DATA2),
1242 AT_lower_bound_data4 = (0x0220|FORM_DATA4),
1243 AT_lower_bound_data8 = (0x0220|FORM_DATA8),
1244 AT_private = (0x0240|FORM_STRING),
1245 AT_producer = (0x0250|FORM_STRING),
1246 AT_program = (0x0230|FORM_STRING),
1247 AT_protected = (0x0260|FORM_STRING),
1248 AT_prototyped = (0x0270|FORM_STRING),
1249 AT_public = (0x0280|FORM_STRING),
1250 AT_pure_virtual = (0x0290|FORM_STRING),
1251 AT_return_addr = (0x02a0|FORM_BLOCK2),
1252 AT_abstract_origin = (0x02b0|FORM_REF),
1253 AT_start_scope = (0x02c0|FORM_DATA4),
1254 AT_stride_size = (0x02e0|FORM_DATA4),
1255 AT_upper_bound_ref = (0x02f0|FORM_REF),
1256 AT_upper_bound_data2 = (0x02f0|FORM_DATA2),
1257 AT_upper_bound_data4 = (0x02f0|FORM_DATA4),
1258 AT_upper_bound_data8 = (0x02f0|FORM_DATA8),
1259 AT_virtual = (0x0300|FORM_STRING),
1260
1261 /* GNU extensions. */
1262
1263 AT_sf_names = (0x8000|FORM_DATA4),
1264 AT_src_info = (0x8010|FORM_DATA4),
1265 AT_mac_info = (0x8020|FORM_DATA4),
1266 AT_src_coords = (0x8030|FORM_DATA4),
1267 AT_body_begin = (0x8040|FORM_ADDR),
1268 AT_body_end = (0x8050|FORM_ADDR)
1269};
1270
1271/* end of enums taken from gdb-6.0 sources */
sewardj5d616df2013-07-02 08:07:15 +00001272#if 0
sewardj7eb7c582005-06-23 01:02:53 +00001273void ML_(read_debuginfo_dwarf1) (
sewardjb8b79ad2008-03-03 01:35:41 +00001274 struct _DebugInfo* di,
jseward8b3131a2003-12-13 23:16:26 +00001275 UChar* dwarf1d, Int dwarf1d_sz,
1276 UChar* dwarf1l, Int dwarf1l_sz )
1277{
1278 UInt stmt_list;
1279 Bool stmt_list_found;
1280 Int die_offset, die_szb, at_offset;
1281 UShort die_kind, at_kind;
1282 UChar* at_base;
florian1636d332012-11-15 04:27:04 +00001283 HChar* src_filename;
jseward8b3131a2003-12-13 23:16:26 +00001284
1285 if (0)
1286 VG_(printf)("read_debuginfo_dwarf1 ( %p, %d, %p, %d )\n",
1287 dwarf1d, dwarf1d_sz, dwarf1l, dwarf1l_sz );
1288
1289 /* This loop scans the DIEs. */
1290 die_offset = 0;
1291 while (True) {
1292 if (die_offset >= dwarf1d_sz) break;
1293
tomb4dd5b42011-10-02 10:49:35 +00001294 die_szb = ML_(read_Int)(dwarf1d + die_offset);
1295 die_kind = ML_(read_UShort)(dwarf1d + die_offset + 4);
jseward8b3131a2003-12-13 23:16:26 +00001296
1297 /* We're only interested in compile_unit DIEs; ignore others. */
1298 if (die_kind != TAG_compile_unit) {
1299 die_offset += die_szb;
1300 continue;
1301 }
1302
1303 if (0)
1304 VG_(printf)("compile-unit DIE: offset %d, tag 0x%x, size %d\n",
1305 die_offset, (Int)die_kind, die_szb );
1306
1307 /* We've got a compile_unit DIE starting at (dwarf1d +
1308 die_offset+6). Try and find the AT_name and AT_stmt_list
1309 attributes. Then, finally, we can read the line number info
1310 for this source file. */
1311
1312 /* The next 3 are set as we find the relevant attrs. */
1313 src_filename = NULL;
1314 stmt_list_found = False;
1315 stmt_list = 0;
1316
1317 /* This loop scans the Attrs inside compile_unit DIEs. */
1318 at_base = dwarf1d + die_offset + 6;
1319 at_offset = 0;
1320 while (True) {
1321 if (at_offset >= die_szb-6) break;
1322
tomb4dd5b42011-10-02 10:49:35 +00001323 at_kind = ML_(read_UShort)(at_base + at_offset);
jseward8b3131a2003-12-13 23:16:26 +00001324 if (0) VG_(printf)("atoffset %d, attag 0x%x\n",
1325 at_offset, (Int)at_kind );
1326 at_offset += 2; /* step over the attribute itself */
1327 /* We have to examine the attribute to figure out its
1328 length. */
1329 switch (at_kind) {
1330 case AT_stmt_list:
1331 case AT_language:
1332 case AT_sibling:
1333 if (at_kind == AT_stmt_list) {
1334 stmt_list_found = True;
tomb4dd5b42011-10-02 10:49:35 +00001335 stmt_list = ML_(read_Int)(at_base+at_offset);
jseward8b3131a2003-12-13 23:16:26 +00001336 }
1337 at_offset += 4; break;
1338 case AT_high_pc:
1339 case AT_low_pc:
1340 at_offset += sizeof(void*); break;
1341 case AT_name:
1342 case AT_producer:
1343 case AT_comp_dir:
1344 /* Zero terminated string, step over it. */
1345 if (at_kind == AT_name)
florian1636d332012-11-15 04:27:04 +00001346 src_filename = (HChar *)(at_base + at_offset);
jseward8b3131a2003-12-13 23:16:26 +00001347 while (at_offset < die_szb-6 && at_base[at_offset] != 0)
1348 at_offset++;
1349 at_offset++;
1350 break;
1351 default:
1352 VG_(printf)("Unhandled DWARF-1 attribute 0x%x\n",
1353 (Int)at_kind );
1354 VG_(core_panic)("Unhandled DWARF-1 attribute");
1355 } /* switch (at_kind) */
1356 } /* looping over attributes */
1357
1358 /* So, did we find the required stuff for a line number table in
1359 this DIE? If yes, read it. */
1360 if (stmt_list_found /* there is a line number table */
1361 && src_filename != NULL /* we know the source filename */
1362 ) {
1363 /* Table starts:
1364 Length:
1365 4 bytes, includes the entire table
1366 Base address:
1367 unclear (4? 8?), assuming native pointer size here.
1368 Then a sequence of triples
1369 (source line number -- 32 bits
1370 source line column -- 16 bits
1371 address delta -- 32 bits)
1372 */
1373 Addr base;
1374 Int len;
florian1636d332012-11-15 04:27:04 +00001375 HChar* curr_filenm;
jseward8b3131a2003-12-13 23:16:26 +00001376 UChar* ptr;
1377 UInt prev_line, prev_delta;
1378
sewardjb8b79ad2008-03-03 01:35:41 +00001379 curr_filenm = ML_(addStr) ( di, src_filename, -1 );
jseward8b3131a2003-12-13 23:16:26 +00001380 prev_line = prev_delta = 0;
1381
1382 ptr = dwarf1l + stmt_list;
tomb4dd5b42011-10-02 10:49:35 +00001383 len = ML_(read_Int)(ptr); ptr += sizeof(Int);
tomba4ce2f2011-10-03 17:01:57 +00001384 base = ML_(read_Addr)(ptr); ptr += sizeof(void*);
jseward8b3131a2003-12-13 23:16:26 +00001385 len -= (sizeof(Int) + sizeof(void*));
1386 while (len > 0) {
1387 UInt line;
1388 UShort col;
1389 UInt delta;
tomb4dd5b42011-10-02 10:49:35 +00001390 line = ML_(read_UInt)(ptr); ptr += sizeof(UInt);
1391 col = ML_(read_UShort)(ptr); ptr += sizeof(UShort);
1392 delta = ML_(read_UInt)(ptr); ptr += sizeof(UInt);
jseward8b3131a2003-12-13 23:16:26 +00001393 if (0) VG_(printf)("line %d, col %d, delta %d\n",
1394 line, (Int)col, delta );
1395 len -= (sizeof(UInt) + sizeof(UShort) + sizeof(UInt));
1396
1397 if (delta > 0 && prev_line > 0) {
1398 if (0) VG_(printf) (" %d %d-%d\n",
1399 prev_line, prev_delta, delta-1);
sewardjb8b79ad2008-03-03 01:35:41 +00001400 ML_(addLineInfo) ( di, curr_filenm, NULL,
jseward8b3131a2003-12-13 23:16:26 +00001401 base + prev_delta, base + delta,
1402 prev_line, 0 );
1403 }
1404 prev_line = line;
1405 prev_delta = delta;
1406 }
1407 }
1408
florianad4e9792015-07-05 21:53:33 +00001409 /* Move on the next DIE. */
jseward8b3131a2003-12-13 23:16:26 +00001410 die_offset += die_szb;
1411
1412 } /* Looping over DIEs */
1413
1414}
sewardj5d616df2013-07-02 08:07:15 +00001415#endif
jseward8b3131a2003-12-13 23:16:26 +00001416
sewardj5c638c22005-04-30 07:55:58 +00001417/*------------------------------------------------------------*/
1418/*--- Read call-frame info from an .eh_frame section ---*/
1419/*------------------------------------------------------------*/
1420
sewardj461d6c62007-02-23 10:10:02 +00001421/* Sources of info:
1422
1423 The DWARF3 spec, available from http://www.dwarfstd.org/Download.php
1424
1425 This describes how to read CFA data from .debug_frame sections.
1426 So as to maximise everybody's annoyance and confusion, .eh_frame
1427 sections are almost the same as .debug_frame sections, but differ
1428 in a few subtle and ill documented but important aspects.
1429
1430 Generic ELF Specification, sections 7.5 (DWARF Extensions) and 7.6
1431 (Exception Frames), available from
1432
1433 http://www.linux-foundation.org/spec/book/ELF-generic/ELF-generic.html
1434
1435 This really does describe .eh_frame, at least the aspects that
1436 differ from standard DWARF3. It's better than guessing, and
1437 (marginally) more fun than reading the gdb source code.
1438*/
1439
sewardj55022aa2005-05-03 16:05:00 +00001440/* Useful info ..
1441
1442 In general:
1443 gdb-6.3/gdb/dwarf2-frame.c
1444
1445 gdb-6.3/gdb/i386-tdep.c:
1446
1447 DWARF2/GCC uses the stack address *before* the function call as a
1448 frame's CFA. [jrs: I presume this means %esp before the call as
1449 the CFA].
1450
1451 JRS: on amd64, the dwarf register numbering is, as per
sewardjb8b79ad2008-03-03 01:35:41 +00001452 gdb-6.3/gdb/amd64-tdep.c and also amd64-abi-0.98.pdf:
sewardj55022aa2005-05-03 16:05:00 +00001453
1454 0 1 2 3 4 5 6 7
1455 RAX RDX RCX RBX RSI RDI RBP RSP
1456
1457 8 ... 15
1458 R8 ... R15
1459
1460 16 is the return address (RIP)
sewardj94ef4a42007-02-25 17:13:19 +00001461 "The table defines Return Address to have a register number,
1462 even though the address is stored in 0(%rsp) and not in a
1463 physical register."
sewardj55022aa2005-05-03 16:05:00 +00001464
sewardj94ef4a42007-02-25 17:13:19 +00001465 17 ... 24
1466 XMM0 ... XMM7
1467
1468 25 ... 32
1469 XMM8 ... XMM15
1470
1471 33 ... 40
1472 ST0 ... ST7
1473
1474 41 ... 48
1475 MM0 ... MM7
1476
1477 49 RFLAGS
1478 50,51,52,53,54,55 ES,CS,SS,DS,FS,GS
1479 58 FS.BASE (what's that?)
1480 59 GS.BASE (what's that?)
1481 62 TR (task register)
1482 63 LDTR (LDT register)
1483 64 MXCSR
1484 65 FCW (x87 control word)
1485 66 FSW (x86 status word)
sewardj55022aa2005-05-03 16:05:00 +00001486
1487 On x86 I cannot find any documentation. It _appears_ to be the
1488 actual instruction encoding, viz:
1489
1490 0 1 2 3 4 5 6 7
1491 EAX ECX EDX EBX ESP EBP ESI EDI
1492
1493 8 is the return address (EIP) */
1494
1495
sewardj1936f8b2006-11-16 12:21:52 +00001496/* Comments re DW_CFA_set_loc, 16 Nov 06.
1497
1498 JRS:
1499 Someone recently sent me a libcrypto.so.0.9.8 as distributed with
1500 Ubuntu of some flavour, compiled with gcc 4.1.2 on amd64. It
1501 causes V's CF reader to complain a lot:
1502
1503 >> --19976-- DWARF2 CFI reader: unhandled CFI instruction 0:24
1504 >> --19976-- DWARF2 CFI reader: unhandled CFI instruction 0:24
1505 >> --19976-- DWARF2 CFI reader: unhandled CFI instruction 0:24
1506 >> --19976-- DWARF2 CFI reader: unhandled CFI instruction 0:24
1507 >> --19976-- DWARF2 CFI reader: unhandled CFI instruction 0:48
1508 >> --19976-- DWARF2 CFI reader: unhandled CFI instruction 0:24
1509
1510 After chasing this around a bit it seems that the CF bytecode
1511 parser lost sync at a DW_CFA_set_loc, which has a single argument
1512 denoting an address.
1513
1514 As it stands that address is extracted by read_Addr(). On amd64
1515 that just fetches 8 bytes regardless of anything else.
1516
1517 read_encoded_Addr() is more sophisticated. This appears to take
1518 into account some kind of encoding flag. When I replace the uses
1519 of read_Addr by read_encoded_Addr for DW_CFA_set_loc, the
1520 complaints go away, there is no loss of sync, and the parsed CF
1521 instructions are the same as shown by readelf --debug-dump=frames.
1522
1523 So it seems a plausible fix. The problem is I looked in the DWARF3
1524 spec and completely failed to figure out whether or not the arg to
1525 DW_CFA_set_loc is supposed to be encoded in a way suitable for
1526 read_encoded_Addr, nor for that matter any description of what it
1527 is that read_encoded_Addr is really decoding.
1528
1529 TomH:
1530 The problem is that the encoding is not standard - the eh_frame
1531 section uses the same encoding as the dwarf_frame section except
1532 for a few small changes, and this is one of them. So this is not
1533 something the DWARF standard covers.
1534
1535 There is an augmentation string to indicate what is going on though
1536 so that programs can recognise it.
1537
1538 What we are doing seems to match what gdb 6.5 and libdwarf 20060614
1539 do though. I'm not sure about readelf though.
1540
1541 (later): Well dwarfdump barfs on it:
1542
1543 dwarfdump ERROR: dwarf_get_fde_info_for_reg:
1544 DW_DLE_DF_FRAME_DECODING_ERROR(193) (193)
1545
1546 I've looked at binutils as well now, and the code in readelf agrees
1547 with your patch - ie it treats set_loc as having an encoded address
1548 if there is a zR augmentation indicating an encoding.
1549
1550 Quite why gdb and libdwarf don't understand this is an interesting
1551 question...
1552
1553 Final outcome: all uses of read_Addr were replaced by
1554 read_encoded_Addr. A new type AddressDecodingInfo was added to
1555 make it relatively clean to plumb through the extra info needed by
1556 read_encoded_Addr.
1557*/
1558
sewardj3891dd42007-01-12 19:03:19 +00001559/* More badness re address encoding, 12 Jan 07.
1560
1561 Most gcc provided CIEs have a "zR" augmentation, which means they
1562 supply their own address encoding, and that works fine. However,
1563 some icc9 supplied CIEs have no augmentation, which means they use
1564 the default_Addr_encoding(). That says to use a machine-word sized
1565 value, literally unmodified.
1566
1567 Since .so's are, in general, relocated when loaded, having absolute
1568 addresses in the CFI data makes no sense when read_encoded_Addr is
1569 used to find the initial location for a FDE. The resulting saga:
1570
1571 TomH:
1572 > I'm chasing a stack backtrace failure for an amd64 .so which was
1573 > created I believe by icc 9.1. After a while I wound up looking at
1574 > this: (readdwarf.c)
1575 >
1576 > 5083 tom static UChar default_Addr_encoding ( void )
1577 > 3584 tom {
1578 > 3584 tom switch (sizeof(Addr)) {
1579 > 3584 tom case 4: return DW_EH_PE_udata4;
1580 > 3584 tom case 8: return DW_EH_PE_udata8;
1581 > 3584 tom default: vg_assert(0);
1582 > 3584 tom }
1583 > 3584 tom }
1584 >
1585 > If a CIE does not have an "augmentation string" (typically "zR") then
1586 > addresses are decoded as described by default_Addr_encoding. If there
1587 > is an 'R' in the augmentation string then the encoding to use
1588 > is specified by the CIE itself, which works fine with GCC compiled code
1589 > since that always appears to specify zR.
1590
1591 Correct.
1592
1593 > Problem is this .so has no augmentation string and so uses the
1594 > default encoding, viz DW_EH_PE_udata8. That appears to mean
1595 > "read a 64 bit number" and use that as-is (for the starting value
1596 > of the program counter when running the CFA program).
1597
1598 Strictly speaking the default is DW_EH_PE_absptr, but that amounts
1599 to either udata4 or udata8 depending on the platform's pointer size
1600 which is a shortcut I used.
1601
1602 > For this .so that gives nonsense (very small) PCs which are later
1603 > rejected by the sanity check which ensures PC ranges fall inside
1604 > the mapped text segment. It seems like the .so expects to have the
1605 > start VMA of the text segment added on. This would correspond to
1606 >
1607 > static UChar default_Addr_encoding ( void )
1608 > {
1609 > switch (sizeof(Addr)) {
1610 > case 4: return DW_EH_PE_textrel + DW_EH_PE_udata4;
1611 > case 8: return DW_EH_PE_textrel + DW_EH_PE_udata8;
1612 > default: vg_assert(0);
1613 > }
1614 > }
1615
1616 The problem you're seeing is that you have absolute pointers inside
1617 a shared library, which obviously makes little sense on the face of
1618 things as how would the linker know where the library will be
1619 loaded?
1620
1621 The answer of course is that it doesn't, so if it points absolute
1622 pointers in the frame unwind data is has to include relocations for
1623 them, and I'm betting that if you look at the relocations in the
1624 library you will there are some for that data.
1625
1626 That is fine of course when ld.so maps the library - it will
1627 relocate the eh_frame data as it maps it (or prelinking will
1628 already have done so) and when the g++ exception code kicks in and
1629 unwinds the stack it will see relocated data.
1630
1631 We of course are mapping the section from the ELF file ourselves
1632 and are not applying the relocations, hence the problem you are
1633 seeing.
1634
1635 Strictly speaking we should apply the relocations but the cheap
1636 solution is essentially to do what you've done - strictly speaking
1637 you should adjust by the difference between the address the library
1638 was linked for and the address it has been loaded at, but a shared
1639 library will normally be linked for address zero I believe. It's
1640 possible that prelinking might change that though?
1641
1642 JRS:
1643 That all syncs with what I am seeing.
1644
1645 So what I am inclined to do is:
1646
1647 - Leave default_Addr_encoding as it is
1648
1649 - Change read_encoded_Addr's handling of "case DW_EH_PE_absptr" so
1650 it sets base to, as you say, the difference between the address
1651 the library was linked for and the address it has been loaded at
1652 (== the SegInfo's text_bias)
1653
1654 Does that sound sane? I think it should even handle the prelinked
1655 case.
1656
1657 (JRS, later)
1658
1659 Hmm. Plausible as it sounds, it doesn't work. It now produces
1660 bogus backtraces for locations inside the (statically linked)
1661 memcheck executable.
1662
1663 Besides, there are a couple of other places where read_encoded_Addr
1664 is used -- one of which is used to establish the length of the
1665 address range covered by the current FDE:
1666
1667 fde_arange = read_encoded_Addr(&nbytes, &adi, data);
1668
1669 and it doesn't seem to make any sense for read_encoded_Addr to add
1670 on the text segment bias in that context. The DWARF3 spec says
1671 that both the initial_location and address_range (length) fields
1672 are encoded the same way ("target address"), so it is unclear at
1673 what stage in the process it would be appropriate to relocate the
1674 former but not the latter.
1675
1676 One unprincipled kludge that does work is the following: just
1677 before handing one of the address range fragments off to
1678 ML_(addDiCfSI) for permanent storage, check its start address. If
1679 that is very low (less than 2 M), and is far below the mapped text
1680 segment, and adding the text bias would move the fragment entirely
1681 inside the mapped text segment, then do so. A kind of kludged
1682 last-minute relocation, if you like.
1683
1684 12 Jan 07: committing said kludge (see kludge_then_addDiCfSI). If
1685 the situation clarifies, it can easily enough be backed out and
1686 replaced by a better fix.
1687*/
1688
sewardj55022aa2005-05-03 16:05:00 +00001689/* --------------- Decls --------------- */
sewardj35165532005-04-30 18:47:48 +00001690
sewardj8eb8bab2015-07-21 14:44:28 +00001691#if defined(VGP_x86_linux) || defined(VGP_x86_solaris)
njn14b278b2005-05-15 18:51:47 +00001692# define FP_REG 5
1693# define SP_REG 4
1694# define RA_REG_DEFAULT 8
sewardj8eb8bab2015-07-21 14:44:28 +00001695#elif defined(VGP_amd64_linux) || defined(VGP_amd64_solaris)
njn14b278b2005-05-15 18:51:47 +00001696# define FP_REG 6
1697# define SP_REG 7
1698# define RA_REG_DEFAULT 16
cerion85665ca2005-06-20 15:51:07 +00001699#elif defined(VGP_ppc32_linux)
1700# define FP_REG 1
1701# define SP_REG 1
tom3c9cf342009-11-12 13:28:34 +00001702# define RA_REG_DEFAULT 65
carllcae0cc22014-08-07 23:17:29 +00001703#elif defined(VGP_ppc64be_linux) || defined(VGP_ppc64le_linux)
sewardj2c48c7b2005-11-29 13:05:56 +00001704# define FP_REG 1
1705# define SP_REG 1
tom3c9cf342009-11-12 13:28:34 +00001706# define RA_REG_DEFAULT 65
sewardj3026f712010-01-01 18:46:41 +00001707#elif defined(VGP_arm_linux)
1708# define FP_REG 12
1709# define SP_REG 13
sewardj821283b2014-01-13 00:21:09 +00001710# define RA_REG_DEFAULT 14
sewardjf0c12502014-01-12 12:54:00 +00001711#elif defined(VGP_arm64_linux)
sewardj821283b2014-01-13 00:21:09 +00001712# define FP_REG 29
1713# define SP_REG 31
1714# define RA_REG_DEFAULT 30
njnf76d27a2009-05-28 01:53:07 +00001715#elif defined(VGP_x86_darwin)
1716# define FP_REG 5
1717# define SP_REG 4
1718# define RA_REG_DEFAULT 8
1719#elif defined(VGP_amd64_darwin)
1720# define FP_REG 6
1721# define SP_REG 7
1722# define RA_REG_DEFAULT 16
sewardjb5b87402011-03-07 16:05:35 +00001723#elif defined(VGP_s390x_linux)
1724# define FP_REG 11 // sometimes s390 has a frame pointer in r11
1725# define SP_REG 15 // stack is always r15
1726# define RA_REG_DEFAULT 14 // the return address is in r14
sewardj5db15402012-06-07 09:13:21 +00001727#elif defined(VGP_mips32_linux)
1728# define FP_REG 30
1729# define SP_REG 29
1730# define RA_REG_DEFAULT 31
petarj4df0bfc2013-02-27 23:17:33 +00001731#elif defined(VGP_mips64_linux)
1732# define FP_REG 30
1733# define SP_REG 29
1734# define RA_REG_DEFAULT 31
njn14b278b2005-05-15 18:51:47 +00001735#else
sewardjb8b79ad2008-03-03 01:35:41 +00001736# error "Unknown platform"
tom2fd38902005-05-01 15:14:01 +00001737#endif
sewardj35165532005-04-30 18:47:48 +00001738
sewardj87a1fa52012-02-20 15:33:24 +00001739/* The number of regs we are prepared to unwind. The number for
1740 arm-linux (320) seems ludicrously high, but the ARM IHI 0040A page
1741 7 (DWARF for the ARM Architecture) specifies that values up to 320
1742 might exist, for Neon/VFP-v3. */
carllcae0cc22014-08-07 23:17:29 +00001743#if defined(VGP_ppc32_linux) || defined(VGP_ppc64be_linux) \
1744 || defined(VGP_ppc64le_linux) || defined(VGP_mips32_linux) \
1745 || defined(VGP_mips64_linux)
tom3c9cf342009-11-12 13:28:34 +00001746# define N_CFI_REGS 72
Elliott Hughesed398002017-06-21 14:41:24 -07001747#elif defined(VGP_arm_linux)
sewardj87a1fa52012-02-20 15:33:24 +00001748# define N_CFI_REGS 320
sewardj821283b2014-01-13 00:21:09 +00001749#elif defined(VGP_arm64_linux)
1750# define N_CFI_REGS 128
tom3c9cf342009-11-12 13:28:34 +00001751#else
1752# define N_CFI_REGS 20
1753#endif
sewardj5c638c22005-04-30 07:55:58 +00001754
1755/* Instructions for the automaton */
1756enum dwarf_cfa_primary_ops
1757 {
1758 DW_CFA_use_secondary = 0,
1759 DW_CFA_advance_loc = 1,
1760 DW_CFA_offset = 2,
1761 DW_CFA_restore = 3
1762 };
1763
1764enum dwarf_cfa_secondary_ops
1765 {
sewardj325ec872005-05-01 20:24:06 +00001766 DW_CFA_nop = 0x00,
1767 DW_CFA_set_loc = 0x01,
1768 DW_CFA_advance_loc1 = 0x02,
1769 DW_CFA_advance_loc2 = 0x03,
1770 DW_CFA_advance_loc4 = 0x04,
1771 DW_CFA_offset_extended = 0x05,
1772 DW_CFA_restore_extended = 0x06,
1773 DW_CFA_undefined = 0x07,
1774 DW_CFA_same_value = 0x08,
1775 DW_CFA_register = 0x09,
1776 DW_CFA_remember_state = 0x0a,
1777 DW_CFA_restore_state = 0x0b,
1778 DW_CFA_def_cfa = 0x0c,
1779 DW_CFA_def_cfa_register = 0x0d,
1780 DW_CFA_def_cfa_offset = 0x0e,
sewardj1e601fe2005-05-16 11:48:34 +00001781 DW_CFA_def_cfa_expression = 0x0f, /* DWARF3 only */
1782 DW_CFA_expression = 0x10, /* DWARF3 only */
sewardj325ec872005-05-01 20:24:06 +00001783 DW_CFA_offset_extended_sf = 0x11, /* DWARF3 only */
sewardjd69222c2006-04-08 16:22:53 +00001784 DW_CFA_def_cfa_sf = 0x12, /* DWARF3 only */
sewardjab30d202005-05-15 17:14:28 +00001785 DW_CFA_def_cfa_offset_sf = 0x13, /* DWARF3 only */
sewardjd69222c2006-04-08 16:22:53 +00001786 DW_CFA_val_offset = 0x14, /* DWARF3 only */
1787 DW_CFA_val_offset_sf = 0x15, /* DWARF3 only */
1788 DW_CFA_val_expression = 0x16, /* DWARF3 only */
sewardj325ec872005-05-01 20:24:06 +00001789 DW_CFA_lo_user = 0x1c,
sewardj0cd71772005-05-16 18:25:09 +00001790 DW_CFA_GNU_window_save = 0x2d, /* GNU extension */
1791 DW_CFA_GNU_args_size = 0x2e, /* GNU extension */
sewardjd69222c2006-04-08 16:22:53 +00001792 DW_CFA_GNU_negative_offset_extended = 0x2f, /* GNU extension */
sewardj8eb8bab2015-07-21 14:44:28 +00001793 DW_CFA_ORCL_arg_loc = 0x30, /* Oracle extension */
sewardj325ec872005-05-01 20:24:06 +00001794 DW_CFA_hi_user = 0x3f
sewardj5c638c22005-04-30 07:55:58 +00001795 };
1796
tom2fd38902005-05-01 15:14:01 +00001797#define DW_EH_PE_absptr 0x00
1798#define DW_EH_PE_omit 0xff
1799
1800#define DW_EH_PE_uleb128 0x01
1801#define DW_EH_PE_udata2 0x02
1802#define DW_EH_PE_udata4 0x03
1803#define DW_EH_PE_udata8 0x04
1804#define DW_EH_PE_sleb128 0x09
1805#define DW_EH_PE_sdata2 0x0A
1806#define DW_EH_PE_sdata4 0x0B
1807#define DW_EH_PE_sdata8 0x0C
1808#define DW_EH_PE_signed 0x08
1809
1810#define DW_EH_PE_pcrel 0x10
1811#define DW_EH_PE_textrel 0x20
1812#define DW_EH_PE_datarel 0x30
1813#define DW_EH_PE_funcrel 0x40
1814#define DW_EH_PE_aligned 0x50
1815
1816#define DW_EH_PE_indirect 0x80
1817
sewardj5c638c22005-04-30 07:55:58 +00001818
sewardj55022aa2005-05-03 16:05:00 +00001819/* RegRule and UnwindContext are used temporarily to do the unwinding.
sewardj726baec2005-06-09 19:27:25 +00001820 The result is then summarised into a sequence of CfiSIs, if
1821 possible. UnwindContext effectively holds the state of the
1822 abstract machine whilst it is running.
sewardj72427fa2007-02-27 16:52:23 +00001823
1824 The CFA can either be a signed offset from a register,
1825 or an expression:
1826
1827 CFA = cfa_reg + cfa_off when UnwindContext.cfa_is_regoff==True
1828 | [[ cfa_expr_id ]]
1829
1830 When .cfa_is_regoff == True, cfa_expr_id must be zero
1831 When .cfa_is_regoff == False, cfa_reg must be zero
1832 and cfa_off must be zero
1833
1834 RegRule describes, for each register, how to get its
1835 value in the previous frame, where 'cfa' denotes the cfa
1836 for the frame as a whole:
1837
1838 RegRule = RR_Undef -- undefined
1839 | RR_Same -- same as in previous frame
1840 | RR_CFAOff arg -- is at * ( cfa + arg )
1841 | RR_CFAValOff arg -- is ( cfa + arg )
1842 | RR_Reg arg -- is in register 'arg'
1843 | RR_Expr arg -- is at * [[ arg ]]
1844 | RR_ValExpr arg -- is [[ arg ]]
1845 | RR_Arch -- dunno
1846
sewardj19dc88f2007-02-28 01:46:30 +00001847 Note that RR_Expr is redundant since the same can be represented
1848 using RR_ValExpr with an explicit dereference (CfiExpr_Deref) at
1849 the outermost level.
1850
sewardj72427fa2007-02-27 16:52:23 +00001851 All expressions are stored in exprs in the containing
1852 UnwindContext. Since the UnwindContext gets reinitialised for each
1853 new FDE, summarise_context needs to copy out any expressions it
1854 wants to keep into the cfsi_exprs field of the containing SegInfo.
sewardj726baec2005-06-09 19:27:25 +00001855*/
sewardj5c638c22005-04-30 07:55:58 +00001856typedef
1857 struct {
sewardj72427fa2007-02-27 16:52:23 +00001858 enum { RR_Undef, RR_Same, RR_CFAOff, RR_CFAValOff,
sewardj19dc88f2007-02-28 01:46:30 +00001859 RR_Reg, /*RR_Expr,*/ RR_ValExpr, RR_Arch } tag;
sewardj72427fa2007-02-27 16:52:23 +00001860 /* meaning: int offset for CFAoff/CFAValOff
1861 reg # for Reg
1862 expr index for Expr/ValExpr */
1863 Int arg;
sewardj5c638c22005-04-30 07:55:58 +00001864 }
1865 RegRule;
1866
florian32971242014-10-23 17:47:15 +00001867static void ppRegRule ( const XArray* exprs, const RegRule* rrule )
sewardj55022aa2005-05-03 16:05:00 +00001868{
sewardj72427fa2007-02-27 16:52:23 +00001869 vg_assert(exprs);
1870 switch (rrule->tag) {
1871 case RR_Undef: VG_(printf)("u "); break;
1872 case RR_Same: VG_(printf)("s "); break;
1873 case RR_CFAOff: VG_(printf)("c%d ", rrule->arg); break;
1874 case RR_CFAValOff: VG_(printf)("v%d ", rrule->arg); break;
1875 case RR_Reg: VG_(printf)("r%d ", rrule->arg); break;
sewardj72427fa2007-02-27 16:52:23 +00001876 case RR_ValExpr: VG_(printf)("ve{");
1877 ML_(ppCfiExpr)( exprs, rrule->arg );
1878 VG_(printf)("} ");
1879 break;
1880 case RR_Arch: VG_(printf)("a "); break;
1881 default: VG_(core_panic)("ppRegRule");
sewardj55022aa2005-05-03 16:05:00 +00001882 }
1883}
1884
1885
sewardj3d026b12009-05-21 15:33:36 +00001886/* Size of the stack of register unwind rules. This is only
1887 exceedingly rarely used, so a stack of size 1 should actually work
1888 with almost all compiler-generated CFA. */
1889#define N_RR_STACK 4
1890
sewardj5c638c22005-04-30 07:55:58 +00001891typedef
1892 struct {
sewardj5410cfd2005-05-13 12:17:33 +00001893 /* Read-only fields (set by the CIE) */
sewardj72427fa2007-02-27 16:52:23 +00001894 Int code_a_f;
1895 Int data_a_f;
1896 Addr initloc;
1897 Int ra_reg;
Elliott Hughesed398002017-06-21 14:41:24 -07001898 /* The rest of these fields can be modified by
sewardj5c638c22005-04-30 07:55:58 +00001899 run_CF_instruction. */
1900 /* The LOC entry */
sewardj72427fa2007-02-27 16:52:23 +00001901 Addr loc;
sewardjde1b03d2009-08-03 13:47:04 +00001902 /* We need a stack of these in order to handle
sewardj3d026b12009-05-21 15:33:36 +00001903 DW_CFA_{remember,restore}_state. */
sewardjde1b03d2009-08-03 13:47:04 +00001904 struct UnwindContextState {
1905 /* The CFA entry. This can be either reg+/-offset or an expr. */
1906 Bool cfa_is_regoff; /* True=>is reg+offset; False=>is expr */
1907 Int cfa_reg;
1908 Int cfa_off; /* in bytes */
1909 Int cfa_expr_ix; /* index into cfa_exprs */
1910 /* Register unwind rules. */
1911 RegRule reg[N_CFI_REGS];
1912 }
1913 state[N_RR_STACK];
1914 Int state_sp; /* 0 <= state_sp < N_RR_STACK; points at the
1915 currently-in-use rule set. */
sewardj72427fa2007-02-27 16:52:23 +00001916 /* array of CfiExpr, shared by reg[] and cfa_expr_ix */
1917 XArray* exprs;
sewardj5c638c22005-04-30 07:55:58 +00001918 }
1919 UnwindContext;
1920
florian518850b2014-10-22 22:25:30 +00001921static void ppUnwindContext ( const UnwindContext* ctx )
sewardj55022aa2005-05-03 16:05:00 +00001922{
sewardj3d026b12009-05-21 15:33:36 +00001923 Int j, i;
sewardj55022aa2005-05-03 16:05:00 +00001924 VG_(printf)("0x%llx: ", (ULong)ctx->loc);
sewardjde1b03d2009-08-03 13:47:04 +00001925 for (j = 0; j <= ctx->state_sp; j++) {
florian518850b2014-10-22 22:25:30 +00001926 const struct UnwindContextState* ctxs = &ctx->state[j];
sewardj3d026b12009-05-21 15:33:36 +00001927 VG_(printf)("%s[%d]={ ", j > 0 ? " " : "", j);
sewardjde1b03d2009-08-03 13:47:04 +00001928 if (ctxs->cfa_is_regoff) {
1929 VG_(printf)("%d(r%d) ", ctxs->cfa_off, ctxs->cfa_reg);
1930 } else {
1931 vg_assert(ctx->exprs);
1932 VG_(printf)("{");
1933 ML_(ppCfiExpr)( ctx->exprs, ctxs->cfa_expr_ix );
1934 VG_(printf)("} ");
1935 }
1936 VG_(printf)("{ ");
sewardj3d026b12009-05-21 15:33:36 +00001937 for (i = 0; i < N_CFI_REGS; i++)
sewardjde1b03d2009-08-03 13:47:04 +00001938 ppRegRule(ctx->exprs, &ctxs->reg[i]);
sewardj3d026b12009-05-21 15:33:36 +00001939 VG_(printf)("}");
1940 }
sewardj55022aa2005-05-03 16:05:00 +00001941 VG_(printf)("\n");
1942}
1943
sewardj5c638c22005-04-30 07:55:58 +00001944static void initUnwindContext ( /*OUT*/UnwindContext* ctx )
1945{
sewardj3d026b12009-05-21 15:33:36 +00001946 Int j, i;
1947 VG_(memset)(ctx, 0, sizeof(*ctx));
sewardjde1b03d2009-08-03 13:47:04 +00001948 /* ctx->code_a_f = 0;
sewardj72427fa2007-02-27 16:52:23 +00001949 ctx->data_a_f = 0;
sewardjde1b03d2009-08-03 13:47:04 +00001950 ctx->initloc = 0; */
sewardj72427fa2007-02-27 16:52:23 +00001951 ctx->ra_reg = RA_REG_DEFAULT;
sewardjde1b03d2009-08-03 13:47:04 +00001952 /* ctx->loc = 0;
sewardj72427fa2007-02-27 16:52:23 +00001953 ctx->exprs = NULL;
sewardjde1b03d2009-08-03 13:47:04 +00001954 ctx->state_sp = 0; */
sewardj3d026b12009-05-21 15:33:36 +00001955 for (j = 0; j < N_RR_STACK; j++) {
sewardjde1b03d2009-08-03 13:47:04 +00001956 ctx->state[j].cfa_is_regoff = True;
1957 /* ctx->state[j].cfa_reg = 0;
1958 ctx->state[j].cfa_off = 0;
1959 ctx->state[j].cfa_expr_ix = 0; */
sewardj3d026b12009-05-21 15:33:36 +00001960 for (i = 0; i < N_CFI_REGS; i++) {
sewardjde1b03d2009-08-03 13:47:04 +00001961 if (RR_Undef != 0)
1962 ctx->state[j].reg[i].tag = RR_Undef;
1963 /* ctx->state[j].reg[i].arg = 0; */
sewardj3d026b12009-05-21 15:33:36 +00001964 }
sewardjd2aac892010-01-01 20:56:13 +00001965# if defined(VGA_arm)
1966 /* All callee-saved registers (or at least the ones we are
1967 summarising for) should start out as RR_Same, on ARM. */
1968 ctx->state[j].reg[11].tag = RR_Same;
1969 /* ctx->state[j].reg[13].tag = RR_Same; */
1970 ctx->state[j].reg[14].tag = RR_Same;
1971 ctx->state[j].reg[12].tag = RR_Same;
sewardjfa5ce562010-09-23 22:05:59 +00001972 ctx->state[j].reg[7].tag = RR_Same;
sewardjd2aac892010-01-01 20:56:13 +00001973 /* this can't be right though: R12 (IP) isn't callee saved. */
sewardj821283b2014-01-13 00:21:09 +00001974# elif defined(VGA_arm64)
1975 /* Callee-saved registers (that we are interested in) should
1976 start out as RR_Same. */
1977 ctx->state[j].reg[29/*FP*/].tag = RR_Same;
1978 ctx->state[j].reg[30/*LR*/].tag = RR_Same;
sewardjd2aac892010-01-01 20:56:13 +00001979# endif
sewardj5c638c22005-04-30 07:55:58 +00001980 }
1981}
1982
sewardj35165532005-04-30 18:47:48 +00001983
sewardjc6d3f6f2007-01-11 19:42:11 +00001984/* A structure which holds information needed by read_encoded_Addr().
sewardj1936f8b2006-11-16 12:21:52 +00001985*/
1986typedef
1987 struct {
sewardj5d616df2013-07-02 08:07:15 +00001988 UChar encoding;
1989 DiCursor ehframe_image;
1990 Addr ehframe_avma;
1991 Addr text_bias;
sewardj8eb8bab2015-07-21 14:44:28 +00001992 Addr got_avma;
sewardj1936f8b2006-11-16 12:21:52 +00001993 }
1994 AddressDecodingInfo;
1995
1996
njn9ce110d2005-05-16 00:04:02 +00001997/* ------------ Deal with summary-info records ------------ */
1998
sewardj55022aa2005-05-03 16:05:00 +00001999/* --------------- Summarisation --------------- */
sewardj35165532005-04-30 18:47:48 +00002000
sewardj72427fa2007-02-27 16:52:23 +00002001/* Forward */
2002static
florian518850b2014-10-22 22:25:30 +00002003Int copy_convert_CfiExpr_tree ( XArray* dst, const UnwindContext* srcuc,
2004 Int nd );
sewardj72427fa2007-02-27 16:52:23 +00002005
sewardj35165532005-04-30 18:47:48 +00002006/* Summarise ctx into si, if possible. Returns True if successful.
2007 This is taken to be just after ctx's loc advances; hence the
sewardj8eb41322005-05-01 23:50:08 +00002008 summary is up to but not including the current loc. This works
2009 on both x86 and amd64.
sewardj35165532005-04-30 18:47:48 +00002010*/
philippe5c3dba22014-07-04 22:36:38 +00002011static Bool summarise_context(/*OUT*/Addr* base,
2012 /*OUT*/UInt* len,
2013 /*OUT*/DiCfSI_m* si_m,
tom2fd38902005-05-01 15:14:01 +00002014 Addr loc_start,
florian518850b2014-10-22 22:25:30 +00002015 const UnwindContext* ctx,
2016 DebugInfo* debuginfo )
sewardj35165532005-04-30 18:47:48 +00002017{
sewardj8eb41322005-05-01 23:50:08 +00002018 Int why = 0;
florian518850b2014-10-22 22:25:30 +00002019 const struct UnwindContextState* ctxs;
philippe5c3dba22014-07-04 22:36:38 +00002020
2021 *base = 0;
2022 *len = 0;
2023 VG_(bzero_inline)(si_m, sizeof(*si_m));
2024
sewardj35165532005-04-30 18:47:48 +00002025
sewardjde1b03d2009-08-03 13:47:04 +00002026 /* Guard against obviously stupid settings of the reg-rule stack
2027 pointer. */
2028 if (ctx->state_sp < 0) { why = 8; goto failed; }
2029 if (ctx->state_sp >= N_RR_STACK) { why = 9; goto failed; }
2030 ctxs = &ctx->state[ctx->state_sp];
2031
sewardj3026f712010-01-01 18:46:41 +00002032 /* First, summarise the method for generating the CFA */
sewardjde1b03d2009-08-03 13:47:04 +00002033 if (!ctxs->cfa_is_regoff) {
sewardj7888e222007-02-28 13:03:27 +00002034 /* it was set by DW_CFA_def_cfa_expression; try to convert */
2035 XArray *src, *dst;
2036 Int conv;
2037 src = ctx->exprs;
sewardjb8b79ad2008-03-03 01:35:41 +00002038 dst = debuginfo->cfsi_exprs;
sewardj7888e222007-02-28 13:03:27 +00002039 if (src && (VG_(sizeXA)(src) > 0) && (!dst)) {
sewardj9c606bd2008-09-18 18:12:50 +00002040 dst = VG_(newXA)( ML_(dinfo_zalloc), "di.ccCt.1", ML_(dinfo_free),
sewardj7888e222007-02-28 13:03:27 +00002041 sizeof(CfiExpr) );
sewardjb8b79ad2008-03-03 01:35:41 +00002042 debuginfo->cfsi_exprs = dst;
sewardj7888e222007-02-28 13:03:27 +00002043 }
2044 conv = copy_convert_CfiExpr_tree
sewardjde1b03d2009-08-03 13:47:04 +00002045 ( dst, ctx, ctxs->cfa_expr_ix );
sewardj7888e222007-02-28 13:03:27 +00002046 vg_assert(conv >= -1);
2047 if (conv == -1) { why = 6; goto failed; }
philippe5c3dba22014-07-04 22:36:38 +00002048 si_m->cfa_how = CFIC_EXPR;
2049 si_m->cfa_off = conv;
sewardjb8b79ad2008-03-03 01:35:41 +00002050 if (0 && debuginfo->ddump_frames)
sewardj7888e222007-02-28 13:03:27 +00002051 ML_(ppCfiExpr)(dst, conv);
sewardj3026f712010-01-01 18:46:41 +00002052 }
2053 else
sewardjde1b03d2009-08-03 13:47:04 +00002054 if (ctxs->cfa_is_regoff && ctxs->cfa_reg == SP_REG) {
philippe5c3dba22014-07-04 22:36:38 +00002055 si_m->cfa_off = ctxs->cfa_off;
sewardj5db15402012-06-07 09:13:21 +00002056# if defined(VGA_x86) || defined(VGA_amd64) || defined(VGA_s390x) \
Elliott Hughesed398002017-06-21 14:41:24 -07002057 || defined(VGA_mips32) || defined(VGA_mips64)
philippe5c3dba22014-07-04 22:36:38 +00002058 si_m->cfa_how = CFIC_IA_SPREL;
sewardj3026f712010-01-01 18:46:41 +00002059# elif defined(VGA_arm)
philippe5c3dba22014-07-04 22:36:38 +00002060 si_m->cfa_how = CFIC_ARM_R13REL;
sewardjf0c12502014-01-12 12:54:00 +00002061# elif defined(VGA_arm64)
philippe5c3dba22014-07-04 22:36:38 +00002062 si_m->cfa_how = CFIC_ARM64_SPREL;
sewardj3026f712010-01-01 18:46:41 +00002063# else
philippe5c3dba22014-07-04 22:36:38 +00002064 si_m->cfa_how = 0; /* invalid */
sewardj3026f712010-01-01 18:46:41 +00002065# endif
2066 }
2067 else
sewardjde1b03d2009-08-03 13:47:04 +00002068 if (ctxs->cfa_is_regoff && ctxs->cfa_reg == FP_REG) {
philippe5c3dba22014-07-04 22:36:38 +00002069 si_m->cfa_off = ctxs->cfa_off;
sewardj5db15402012-06-07 09:13:21 +00002070# if defined(VGA_x86) || defined(VGA_amd64) || defined(VGA_s390x) \
Elliott Hughesed398002017-06-21 14:41:24 -07002071 || defined(VGA_mips32) || defined(VGA_mips64)
philippe5c3dba22014-07-04 22:36:38 +00002072 si_m->cfa_how = CFIC_IA_BPREL;
sewardj3026f712010-01-01 18:46:41 +00002073# elif defined(VGA_arm)
philippe5c3dba22014-07-04 22:36:38 +00002074 si_m->cfa_how = CFIC_ARM_R12REL;
sewardj821283b2014-01-13 00:21:09 +00002075# elif defined(VGA_arm64)
philippe5c3dba22014-07-04 22:36:38 +00002076 si_m->cfa_how = CFIC_ARM64_X29REL;
sewardj3026f712010-01-01 18:46:41 +00002077# else
philippe5c3dba22014-07-04 22:36:38 +00002078 si_m->cfa_how = 0; /* invalid */
sewardj3026f712010-01-01 18:46:41 +00002079# endif
2080 }
2081# if defined(VGA_arm)
2082 else
2083 if (ctxs->cfa_is_regoff && ctxs->cfa_reg == 11/*??_REG*/) {
philippe5c3dba22014-07-04 22:36:38 +00002084 si_m->cfa_how = CFIC_ARM_R11REL;
2085 si_m->cfa_off = ctxs->cfa_off;
sewardj3026f712010-01-01 18:46:41 +00002086 }
sewardjfa5ce562010-09-23 22:05:59 +00002087 else
2088 if (ctxs->cfa_is_regoff && ctxs->cfa_reg == 7/*??_REG*/) {
philippe5c3dba22014-07-04 22:36:38 +00002089 si_m->cfa_how = CFIC_ARM_R7REL;
2090 si_m->cfa_off = ctxs->cfa_off;
sewardjfa5ce562010-09-23 22:05:59 +00002091 }
sewardjf0c12502014-01-12 12:54:00 +00002092# elif defined(VGA_arm64)
sewardj821283b2014-01-13 00:21:09 +00002093 // do we need any arm64 specifics here?
sewardj3026f712010-01-01 18:46:41 +00002094# endif
2095 else {
sewardj8eb41322005-05-01 23:50:08 +00002096 why = 1;
sewardj35165532005-04-30 18:47:48 +00002097 goto failed;
sewardj5c638c22005-04-30 07:55:58 +00002098 }
sewardj35165532005-04-30 18:47:48 +00002099
sewardj72427fa2007-02-27 16:52:23 +00002100# define SUMMARISE_HOW(_how, _off, _ctxreg) \
2101 switch (_ctxreg.tag) { \
2102 case RR_Undef: \
2103 _how = CFIR_UNKNOWN; _off = 0; break; \
2104 case RR_Same: \
2105 _how = CFIR_SAME; _off = 0; break; \
2106 case RR_CFAOff: \
2107 _how = CFIR_MEMCFAREL; _off = _ctxreg.arg; break; \
2108 case RR_CFAValOff: \
2109 _how = CFIR_CFAREL; _off = _ctxreg.arg; break; \
2110 case RR_ValExpr: { \
2111 XArray *src, *dst; \
2112 Int conv; \
2113 src = ctx->exprs; \
sewardjb8b79ad2008-03-03 01:35:41 +00002114 dst = debuginfo->cfsi_exprs; \
sewardj72427fa2007-02-27 16:52:23 +00002115 if (src && (VG_(sizeXA)(src) > 0) && (!dst)) { \
sewardjb8b79ad2008-03-03 01:35:41 +00002116 dst = VG_(newXA)( ML_(dinfo_zalloc), \
sewardj9c606bd2008-09-18 18:12:50 +00002117 "di.ccCt.2", \
sewardjb8b79ad2008-03-03 01:35:41 +00002118 ML_(dinfo_free), \
sewardj72427fa2007-02-27 16:52:23 +00002119 sizeof(CfiExpr) ); \
sewardjb8b79ad2008-03-03 01:35:41 +00002120 debuginfo->cfsi_exprs = dst; \
sewardj72427fa2007-02-27 16:52:23 +00002121 } \
2122 conv = copy_convert_CfiExpr_tree \
2123 ( dst, ctx, _ctxreg.arg ); \
2124 vg_assert(conv >= -1); \
2125 if (conv == -1) { why = 7; goto failed; } \
2126 _how = CFIR_EXPR; \
2127 _off = conv; \
sewardjb8b79ad2008-03-03 01:35:41 +00002128 if (0 && debuginfo->ddump_frames) \
sewardj72427fa2007-02-27 16:52:23 +00002129 ML_(ppCfiExpr)(dst, conv); \
2130 break; \
2131 } \
2132 default: \
2133 why = 2; goto failed; /* otherwise give up */ \
sewardj35165532005-04-30 18:47:48 +00002134 }
2135
sewardjf0c12502014-01-12 12:54:00 +00002136
sewardj3026f712010-01-01 18:46:41 +00002137# if defined(VGA_x86) || defined(VGA_amd64)
2138
2139 /* --- entire tail of this fn specialised for x86/amd64 --- */
2140
philippe5c3dba22014-07-04 22:36:38 +00002141 SUMMARISE_HOW(si_m->ra_how, si_m->ra_off,
2142 ctxs->reg[ctx->ra_reg] );
2143 SUMMARISE_HOW(si_m->bp_how, si_m->bp_off,
2144 ctxs->reg[FP_REG] );
sewardj35165532005-04-30 18:47:48 +00002145
sewardj8eb41322005-05-01 23:50:08 +00002146 /* on x86/amd64, it seems the old %{e,r}sp value before the call is
2147 always the same as the CFA. Therefore ... */
philippe5c3dba22014-07-04 22:36:38 +00002148 si_m->sp_how = CFIR_CFAREL;
2149 si_m->sp_off = 0;
sewardj35165532005-04-30 18:47:48 +00002150
sewardj8eb41322005-05-01 23:50:08 +00002151 /* also, gcc says "Undef" for %{e,r}bp when it is unchanged. So
2152 .. */
sewardjde1b03d2009-08-03 13:47:04 +00002153 if (ctxs->reg[FP_REG].tag == RR_Undef)
philippe5c3dba22014-07-04 22:36:38 +00002154 si_m->bp_how = CFIR_SAME;
sewardj35165532005-04-30 18:47:48 +00002155
2156 /* knock out some obviously stupid cases */
philippe5c3dba22014-07-04 22:36:38 +00002157 if (si_m->ra_how == CFIR_SAME)
sewardj8eb41322005-05-01 23:50:08 +00002158 { why = 3; goto failed; }
sewardj35165532005-04-30 18:47:48 +00002159
2160 /* bogus looking range? Note, we require that the difference is
2161 representable in 32 bits. */
sewardj8eb41322005-05-01 23:50:08 +00002162 if (loc_start >= ctx->loc)
2163 { why = 4; goto failed; }
sewardj35165532005-04-30 18:47:48 +00002164 if (ctx->loc - loc_start > 10000000 /* let's say */)
sewardj8eb41322005-05-01 23:50:08 +00002165 { why = 5; goto failed; }
sewardj35165532005-04-30 18:47:48 +00002166
philippe5c3dba22014-07-04 22:36:38 +00002167 *base = loc_start + ctx->initloc;
2168 *len = (UInt)(ctx->loc - loc_start);
sewardj35165532005-04-30 18:47:48 +00002169
2170 return True;
2171
sewardj3026f712010-01-01 18:46:41 +00002172# elif defined(VGA_arm)
2173
2174 /* ---- entire tail of this fn specialised for arm ---- */
2175
philippe5c3dba22014-07-04 22:36:38 +00002176 SUMMARISE_HOW(si_m->r14_how, si_m->r14_off,
2177 ctxs->reg[14] );
sewardj3026f712010-01-01 18:46:41 +00002178
philippe5c3dba22014-07-04 22:36:38 +00002179 //SUMMARISE_HOW(si_m->r13_how, si_m->r13_off,
2180 // ctxs->reg[13] );
sewardj3026f712010-01-01 18:46:41 +00002181
philippe5c3dba22014-07-04 22:36:38 +00002182 SUMMARISE_HOW(si_m->r12_how, si_m->r12_off,
2183 ctxs->reg[FP_REG] );
sewardj3026f712010-01-01 18:46:41 +00002184
philippe5c3dba22014-07-04 22:36:38 +00002185 SUMMARISE_HOW(si_m->r11_how, si_m->r11_off,
2186 ctxs->reg[11/*FP_REG*/] );
sewardj3026f712010-01-01 18:46:41 +00002187
philippe5c3dba22014-07-04 22:36:38 +00002188 SUMMARISE_HOW(si_m->r7_how, si_m->r7_off,
2189 ctxs->reg[7] );
sewardjfa5ce562010-09-23 22:05:59 +00002190
sewardj3026f712010-01-01 18:46:41 +00002191 if (ctxs->reg[14/*LR*/].tag == RR_Same
2192 && ctx->ra_reg == 14/*as we expect it always to be*/) {
2193 /* Generate a trivial CfiExpr, which merely says "r14". First
2194 ensure this DebugInfo has a cfsi_expr array in which to park
2195 it. */
2196 if (!debuginfo->cfsi_exprs)
2197 debuginfo->cfsi_exprs = VG_(newXA)( ML_(dinfo_zalloc),
2198 "di.ccCt.2a",
2199 ML_(dinfo_free),
2200 sizeof(CfiExpr) );
philippe5c3dba22014-07-04 22:36:38 +00002201 si_m->ra_off = ML_(CfiExpr_CfiReg)( debuginfo->cfsi_exprs,
2202 Creg_ARM_R14);
2203 si_m->ra_how = CFIR_EXPR;
sewardj3026f712010-01-01 18:46:41 +00002204 } else {
2205 /* Just summarise it in the normal way */
philippe5c3dba22014-07-04 22:36:38 +00002206 SUMMARISE_HOW(si_m->ra_how, si_m->ra_off,
2207 ctxs->reg[ctx->ra_reg] );
sewardj3026f712010-01-01 18:46:41 +00002208 }
2209
2210 /* on arm, it seems the old r13 (SP) value before the call is
2211 always the same as the CFA. Therefore ... */
philippe5c3dba22014-07-04 22:36:38 +00002212 si_m->r13_how = CFIR_CFAREL;
2213 si_m->r13_off = 0;
sewardj3026f712010-01-01 18:46:41 +00002214
2215 /* bogus looking range? Note, we require that the difference is
2216 representable in 32 bits. */
2217 if (loc_start >= ctx->loc)
2218 { why = 4; goto failed; }
2219 if (ctx->loc - loc_start > 10000000 /* let's say */)
2220 { why = 5; goto failed; }
2221
philippe5c3dba22014-07-04 22:36:38 +00002222 *base = loc_start + ctx->initloc;
2223 *len = (UInt)(ctx->loc - loc_start);
sewardj3026f712010-01-01 18:46:41 +00002224
2225 return True;
2226
sewardj821283b2014-01-13 00:21:09 +00002227# elif defined(VGA_arm64)
2228
2229 /* --- entire tail of this fn specialised for arm64 --- */
2230
philippe5c3dba22014-07-04 22:36:38 +00002231 SUMMARISE_HOW(si_m->x30_how, si_m->x30_off, ctxs->reg[30/*LR*/]);
2232 SUMMARISE_HOW(si_m->x29_how, si_m->x29_off, ctxs->reg[29/*FP*/]);
sewardj821283b2014-01-13 00:21:09 +00002233
2234 if (ctxs->reg[30/*LR*/].tag == RR_Same
2235 && ctx->ra_reg == 30/*as we expect it always to be*/) {
2236 /* Generate a trivial CfiExpr, which merely says "x30". First
2237 ensure this DebugInfo has a cfsi_expr array in which to park
2238 it. */
2239 if (!debuginfo->cfsi_exprs)
2240 debuginfo->cfsi_exprs = VG_(newXA)( ML_(dinfo_zalloc),
2241 "di.ccCt.2a-arm64",
2242 ML_(dinfo_free),
2243 sizeof(CfiExpr) );
philippe5c3dba22014-07-04 22:36:38 +00002244 si_m->ra_off = ML_(CfiExpr_CfiReg)( debuginfo->cfsi_exprs,
2245 Creg_ARM64_X30);
2246 si_m->ra_how = CFIR_EXPR;
sewardj821283b2014-01-13 00:21:09 +00002247 } else {
2248 /* Just summarise it in the normal way */
philippe5c3dba22014-07-04 22:36:38 +00002249 SUMMARISE_HOW(si_m->ra_how, si_m->ra_off, ctxs->reg[ctx->ra_reg]);
sewardj821283b2014-01-13 00:21:09 +00002250 }
2251
2252 /* on arm64, it seems the old SP value before the call is always
2253 the same as the CFA. Therefore ... */
philippe5c3dba22014-07-04 22:36:38 +00002254 si_m->sp_how = CFIR_CFAREL;
2255 si_m->sp_off = 0;
sewardj821283b2014-01-13 00:21:09 +00002256
2257 /* bogus looking range? Note, we require that the difference is
2258 representable in 32 bits. */
2259 if (loc_start >= ctx->loc)
2260 { why = 4; goto failed; }
2261 if (ctx->loc - loc_start > 10000000 /* let's say */)
2262 { why = 5; goto failed; }
2263
philippe5c3dba22014-07-04 22:36:38 +00002264 *base = loc_start + ctx->initloc;
2265 *len = (UInt)(ctx->loc - loc_start);
sewardj821283b2014-01-13 00:21:09 +00002266
2267 return True;
2268
sewardjb5b87402011-03-07 16:05:35 +00002269# elif defined(VGA_s390x)
2270
sewardjf0c12502014-01-12 12:54:00 +00002271 /* --- entire tail of this fn specialised for s390 --- */
2272
philippe5c3dba22014-07-04 22:36:38 +00002273 SUMMARISE_HOW(si_m->ra_how, si_m->ra_off,
2274 ctxs->reg[ctx->ra_reg] );
2275 SUMMARISE_HOW(si_m->fp_how, si_m->fp_off,
2276 ctxs->reg[FP_REG] );
2277 SUMMARISE_HOW(si_m->sp_how, si_m->sp_off,
2278 ctxs->reg[SP_REG] );
sewardjb5b87402011-03-07 16:05:35 +00002279
2280 /* change some defaults to consumable values */
philippe5c3dba22014-07-04 22:36:38 +00002281 if (si_m->sp_how == CFIR_UNKNOWN)
2282 si_m->sp_how = CFIR_SAME;
sewardjb5b87402011-03-07 16:05:35 +00002283
philippe5c3dba22014-07-04 22:36:38 +00002284 if (si_m->fp_how == CFIR_UNKNOWN)
2285 si_m->fp_how = CFIR_SAME;
sewardjb5b87402011-03-07 16:05:35 +00002286
philippe5c3dba22014-07-04 22:36:38 +00002287 if (si_m->cfa_how == CFIR_UNKNOWN) {
2288 si_m->cfa_how = CFIC_IA_SPREL;
2289 si_m->cfa_off = 160;
sewardjb5b87402011-03-07 16:05:35 +00002290 }
philippe5c3dba22014-07-04 22:36:38 +00002291 if (si_m->ra_how == CFIR_UNKNOWN) {
sewardjb5b87402011-03-07 16:05:35 +00002292 if (!debuginfo->cfsi_exprs)
2293 debuginfo->cfsi_exprs = VG_(newXA)( ML_(dinfo_zalloc),
2294 "di.ccCt.2a",
2295 ML_(dinfo_free),
2296 sizeof(CfiExpr) );
philippe5c3dba22014-07-04 22:36:38 +00002297 si_m->ra_how = CFIR_EXPR;
2298 si_m->ra_off = ML_(CfiExpr_CfiReg)( debuginfo->cfsi_exprs,
florianb6ba6d22015-03-20 09:38:58 +00002299 Creg_S390_LR);
sewardjb5b87402011-03-07 16:05:35 +00002300 }
2301
2302 /* knock out some obviously stupid cases */
philippe5c3dba22014-07-04 22:36:38 +00002303 if (si_m->ra_how == CFIR_SAME)
sewardjb5b87402011-03-07 16:05:35 +00002304 { why = 3; goto failed; }
2305
2306 /* bogus looking range? Note, we require that the difference is
2307 representable in 32 bits. */
2308 if (loc_start >= ctx->loc)
2309 { why = 4; goto failed; }
2310 if (ctx->loc - loc_start > 10000000 /* let's say */)
2311 { why = 5; goto failed; }
2312
philippe5c3dba22014-07-04 22:36:38 +00002313 *base = loc_start + ctx->initloc;
2314 *len = (UInt)(ctx->loc - loc_start);
sewardjb5b87402011-03-07 16:05:35 +00002315
2316 return True;
2317
petarj4df0bfc2013-02-27 23:17:33 +00002318# elif defined(VGA_mips32) || defined(VGA_mips64)
sewardj112711a2015-04-10 12:30:09 +00002319
sewardj5db15402012-06-07 09:13:21 +00002320 /* --- entire tail of this fn specialised for mips --- */
sewardj112711a2015-04-10 12:30:09 +00002321
philippe5c3dba22014-07-04 22:36:38 +00002322 SUMMARISE_HOW(si_m->ra_how, si_m->ra_off,
2323 ctxs->reg[ctx->ra_reg] );
2324 SUMMARISE_HOW(si_m->fp_how, si_m->fp_off,
2325 ctxs->reg[FP_REG] );
2326 SUMMARISE_HOW(si_m->sp_how, si_m->sp_off,
2327 ctxs->reg[SP_REG] );
2328 si_m->sp_how = CFIR_CFAREL;
2329 si_m->sp_off = 0;
sewardj5db15402012-06-07 09:13:21 +00002330
philippe5c3dba22014-07-04 22:36:38 +00002331 if (si_m->fp_how == CFIR_UNKNOWN)
2332 si_m->fp_how = CFIR_SAME;
2333 if (si_m->cfa_how == CFIR_UNKNOWN) {
2334 si_m->cfa_how = CFIC_IA_SPREL;
2335 si_m->cfa_off = 160;
sewardj5db15402012-06-07 09:13:21 +00002336 }
philippe5c3dba22014-07-04 22:36:38 +00002337 if (si_m->ra_how == CFIR_UNKNOWN) {
sewardj5db15402012-06-07 09:13:21 +00002338 if (!debuginfo->cfsi_exprs)
2339 debuginfo->cfsi_exprs = VG_(newXA)( ML_(dinfo_zalloc),
2340 "di.ccCt.2a",
2341 ML_(dinfo_free),
2342 sizeof(CfiExpr) );
philippe5c3dba22014-07-04 22:36:38 +00002343 si_m->ra_how = CFIR_EXPR;
2344 si_m->ra_off = ML_(CfiExpr_CfiReg)( debuginfo->cfsi_exprs,
2345 Creg_MIPS_RA);
sewardj5db15402012-06-07 09:13:21 +00002346 }
2347
philippe5c3dba22014-07-04 22:36:38 +00002348 if (si_m->ra_how == CFIR_SAME)
sewardj5db15402012-06-07 09:13:21 +00002349 { why = 3; goto failed; }
2350
2351 if (loc_start >= ctx->loc)
2352 { why = 4; goto failed; }
2353 if (ctx->loc - loc_start > 10000000 /* let's say */)
2354 { why = 5; goto failed; }
2355
philippe5c3dba22014-07-04 22:36:38 +00002356 *base = loc_start + ctx->initloc;
2357 *len = (UInt)(ctx->loc - loc_start);
sewardj5db15402012-06-07 09:13:21 +00002358
2359 return True;
carllcae0cc22014-08-07 23:17:29 +00002360# elif defined(VGA_ppc32) || defined(VGA_ppc64be) || defined(VGA_ppc64le)
sewardjf0c12502014-01-12 12:54:00 +00002361 /* These don't use CFI based unwinding (is that really true?) */
2362
sewardj3026f712010-01-01 18:46:41 +00002363# else
2364# error "Unknown arch"
2365# endif
2366
sewardj821283b2014-01-13 00:21:09 +00002367 /* --- non-specialised code after this point --- */
2368
sewardj3026f712010-01-01 18:46:41 +00002369# undef SUMMARISE_HOW
2370
sewardj35165532005-04-30 18:47:48 +00002371 failed:
sewardjb8b79ad2008-03-03 01:35:41 +00002372 if (VG_(clo_verbosity) > 2 || debuginfo->trace_cfi) {
sewardj55022aa2005-05-03 16:05:00 +00002373 VG_(message)(Vg_DebugMsg,
barta0b6b2c2008-07-07 06:49:24 +00002374 "summarise_context(loc_start = %#lx)"
sewardj738856f2009-07-15 14:48:32 +00002375 ": cannot summarise(why=%d): \n", loc_start, why);
sewardj55022aa2005-05-03 16:05:00 +00002376 ppUnwindContext(ctx);
2377 }
sewardj35165532005-04-30 18:47:48 +00002378 return False;
2379}
2380
sewardj72427fa2007-02-27 16:52:23 +00002381/* Copy the tree rooted at srcuc->exprs node srcix to dstxa, on the
2382 way converting any DwReg regs (regs numbered using the Dwarf scheme
2383 defined by each architecture's ABI) into CfiRegs, which are
2384 platform independent. If the conversion isn't possible because
2385 there is no equivalent register, return -1. This has the
2386 undesirable side effect of de-dagifying the input; oh well. */
2387static Int copy_convert_CfiExpr_tree ( XArray* dstxa,
florian518850b2014-10-22 22:25:30 +00002388 const UnwindContext* srcuc,
sewardj72427fa2007-02-27 16:52:23 +00002389 Int srcix )
2390{
2391 CfiExpr* src;
sewardjd2be8cc2011-03-28 20:33:52 +00002392 Int cpL, cpR, cpA;
sewardj72427fa2007-02-27 16:52:23 +00002393 XArray* srcxa = srcuc->exprs;
2394 vg_assert(srcxa);
2395 vg_assert(dstxa);
2396 vg_assert(srcix >= 0 && srcix < VG_(sizeXA)(srcxa));
2397
2398 src = VG_(indexXA)( srcxa, srcix );
2399 switch (src->tag) {
2400 case Cex_Undef:
2401 return ML_(CfiExpr_Undef)( dstxa );
2402 case Cex_Deref:
sewardjbd7aca62007-08-31 23:08:39 +00002403 cpA = copy_convert_CfiExpr_tree( dstxa, srcuc, src->Cex.Deref.ixAddr );
2404 if (cpA == -1)
2405 return -1; /* propagate failure */
2406 return ML_(CfiExpr_Deref)( dstxa, cpA );
sewardj72427fa2007-02-27 16:52:23 +00002407 case Cex_Const:
2408 return ML_(CfiExpr_Const)( dstxa, src->Cex.Const.con );
2409 case Cex_Binop:
2410 cpL = copy_convert_CfiExpr_tree( dstxa, srcuc, src->Cex.Binop.ixL );
2411 cpR = copy_convert_CfiExpr_tree( dstxa, srcuc, src->Cex.Binop.ixR );
2412 vg_assert(cpL >= -1 && cpR >= -1);
2413 if (cpL == -1 || cpR == -1)
2414 return -1; /* propagate failure */
2415 return ML_(CfiExpr_Binop)( dstxa, src->Cex.Binop.op, cpL, cpR );
2416 case Cex_CfiReg:
2417 /* should not see these in input (are created only by this
2418 conversion step!) */
2419 VG_(core_panic)("copy_convert_CfiExpr_tree: CfiReg in input");
sewardjd2be8cc2011-03-28 20:33:52 +00002420 case Cex_DwReg: {
sewardj72427fa2007-02-27 16:52:23 +00002421 /* This is the only place where the conversion can fail. */
sewardjd2be8cc2011-03-28 20:33:52 +00002422 Int dwreg __attribute__((unused));
sewardj72427fa2007-02-27 16:52:23 +00002423 dwreg = src->Cex.DwReg.reg;
sewardj3026f712010-01-01 18:46:41 +00002424# if defined(VGA_x86) || defined(VGA_amd64)
sewardj72427fa2007-02-27 16:52:23 +00002425 if (dwreg == SP_REG)
sewardj9365e3f2010-01-01 19:55:17 +00002426 return ML_(CfiExpr_CfiReg)( dstxa, Creg_IA_SP );
sewardj72427fa2007-02-27 16:52:23 +00002427 if (dwreg == FP_REG)
sewardj9365e3f2010-01-01 19:55:17 +00002428 return ML_(CfiExpr_CfiReg)( dstxa, Creg_IA_BP );
sewardj72427fa2007-02-27 16:52:23 +00002429 if (dwreg == srcuc->ra_reg)
sewardj9365e3f2010-01-01 19:55:17 +00002430 return ML_(CfiExpr_CfiReg)( dstxa, Creg_IA_IP ); /* correct? */
sewardj3026f712010-01-01 18:46:41 +00002431# elif defined(VGA_arm)
2432 if (dwreg == SP_REG)
2433 return ML_(CfiExpr_CfiReg)( dstxa, Creg_ARM_R13 );
2434 if (dwreg == FP_REG)
2435 return ML_(CfiExpr_CfiReg)( dstxa, Creg_ARM_R12 );
2436 if (dwreg == srcuc->ra_reg)
2437 return ML_(CfiExpr_CfiReg)( dstxa, Creg_ARM_R15 ); /* correct? */
sewardjb5b87402011-03-07 16:05:35 +00002438# elif defined(VGA_s390x)
2439 if (dwreg == SP_REG)
florianb6ba6d22015-03-20 09:38:58 +00002440 return ML_(CfiExpr_CfiReg)( dstxa, Creg_S390_SP );
sewardjb5b87402011-03-07 16:05:35 +00002441 if (dwreg == FP_REG)
florianb6ba6d22015-03-20 09:38:58 +00002442 return ML_(CfiExpr_CfiReg)( dstxa, Creg_S390_FP );
sewardjb5b87402011-03-07 16:05:35 +00002443 if (dwreg == srcuc->ra_reg)
florianb6ba6d22015-03-20 09:38:58 +00002444 return ML_(CfiExpr_CfiReg)( dstxa, Creg_S390_IA );
petarj4df0bfc2013-02-27 23:17:33 +00002445# elif defined(VGA_mips32) || defined(VGA_mips64)
sewardj5db15402012-06-07 09:13:21 +00002446 if (dwreg == SP_REG)
2447 return ML_(CfiExpr_CfiReg)( dstxa, Creg_IA_SP );
2448 if (dwreg == FP_REG)
2449 return ML_(CfiExpr_CfiReg)( dstxa, Creg_IA_BP );
2450 if (dwreg == srcuc->ra_reg)
2451 return ML_(CfiExpr_CfiReg)( dstxa, Creg_IA_IP );
sewardjf0c12502014-01-12 12:54:00 +00002452# elif defined(VGA_arm64)
2453 I_die_here;
carllcae0cc22014-08-07 23:17:29 +00002454# elif defined(VGA_ppc32) || defined(VGA_ppc64be) \
2455 || defined(VGA_ppc64le)
sewardj3026f712010-01-01 18:46:41 +00002456# else
2457# error "Unknown arch"
2458# endif
sewardj72427fa2007-02-27 16:52:23 +00002459 /* else we must fail - can't represent the reg */
2460 return -1;
sewardjd2be8cc2011-03-28 20:33:52 +00002461 }
sewardj72427fa2007-02-27 16:52:23 +00002462 default:
2463 VG_(core_panic)("copy_convert_CfiExpr_tree: default");
2464 }
2465}
2466
2467
florian518850b2014-10-22 22:25:30 +00002468static void ppUnwindContext_summary ( const UnwindContext* ctx )
sewardj35165532005-04-30 18:47:48 +00002469{
florian518850b2014-10-22 22:25:30 +00002470 const struct UnwindContextState* ctxs = &ctx->state[ctx->state_sp];
sewardjde1b03d2009-08-03 13:47:04 +00002471
sewardj35165532005-04-30 18:47:48 +00002472 VG_(printf)("0x%llx-1: ", (ULong)ctx->loc);
2473
sewardjde1b03d2009-08-03 13:47:04 +00002474 if (ctxs->cfa_reg == SP_REG) {
2475 VG_(printf)("SP/CFA=%d+SP ", ctxs->cfa_off);
sewardj35165532005-04-30 18:47:48 +00002476 } else
sewardjde1b03d2009-08-03 13:47:04 +00002477 if (ctxs->cfa_reg == FP_REG) {
2478 VG_(printf)("SP/CFA=%d+FP ", ctxs->cfa_off);
sewardj35165532005-04-30 18:47:48 +00002479 } else {
barta0b6b2c2008-07-07 06:49:24 +00002480 VG_(printf)("SP/CFA=unknown ");
sewardj35165532005-04-30 18:47:48 +00002481 }
2482
2483 VG_(printf)("RA=");
sewardjde1b03d2009-08-03 13:47:04 +00002484 ppRegRule( ctx->exprs, &ctxs->reg[ctx->ra_reg] );
sewardj35165532005-04-30 18:47:48 +00002485
2486 VG_(printf)("FP=");
sewardjde1b03d2009-08-03 13:47:04 +00002487 ppRegRule( ctx->exprs, &ctxs->reg[FP_REG] );
sewardj5c638c22005-04-30 07:55:58 +00002488 VG_(printf)("\n");
2489}
2490
sewardj55022aa2005-05-03 16:05:00 +00002491
2492/* ------------ Pick apart DWARF2 byte streams ------------ */
2493
sewardj5d616df2013-07-02 08:07:15 +00002494static ULong step_le_u_encoded_literal ( DiCursor* data, UInt size )
sewardjddf006d2007-02-24 23:29:31 +00002495{
2496 switch (size) {
sewardj5d616df2013-07-02 08:07:15 +00002497 case 8: return (ULong)ML_(cur_step_ULong)( data );
2498 case 4: return (ULong)ML_(cur_step_UInt)( data );
2499 case 2: return (ULong)ML_(cur_step_UShort)( data );
2500 case 1: return (ULong)ML_(cur_step_UChar)( data );
sewardjddf006d2007-02-24 23:29:31 +00002501 default: vg_assert(0); /*NOTREACHED*/ return 0;
2502 }
2503}
2504
sewardj5d616df2013-07-02 08:07:15 +00002505static Long step_le_s_encoded_literal ( DiCursor* data, UInt size )
sewardj72427fa2007-02-27 16:52:23 +00002506{
florian45ee0362015-02-06 20:32:15 +00002507 ULong u64 = step_le_u_encoded_literal( data, size );
2508 Long s64;
sewardj72427fa2007-02-27 16:52:23 +00002509 switch (size) {
florian237fd432015-02-09 21:59:00 +00002510 case 8: s64 = u64; break;
florian45ee0362015-02-06 20:32:15 +00002511 case 4: s64 = u64 << 32; s64 >>= 32; break;
2512 case 2: s64 = u64 << 48; s64 >>= 48; break;
2513 case 1: s64 = u64 << 56; s64 >>= 56; break;
sewardj72427fa2007-02-27 16:52:23 +00002514 default: vg_assert(0); /*NOTREACHED*/ return 0;
2515 }
2516 return s64;
2517}
sewardjddf006d2007-02-24 23:29:31 +00002518
tom151a6392005-11-11 12:30:36 +00002519static UChar default_Addr_encoding ( void )
tom2fd38902005-05-01 15:14:01 +00002520{
2521 switch (sizeof(Addr)) {
2522 case 4: return DW_EH_PE_udata4;
2523 case 8: return DW_EH_PE_udata8;
2524 default: vg_assert(0);
2525 }
2526}
2527
sewardj8eb41322005-05-01 23:50:08 +00002528static UInt size_of_encoded_Addr ( UChar encoding )
tom2fd38902005-05-01 15:14:01 +00002529{
2530 if (encoding == DW_EH_PE_omit)
2531 return 0;
2532
2533 switch (encoding & 0x07) {
2534 case DW_EH_PE_absptr: return sizeof(Addr);
2535 case DW_EH_PE_udata2: return sizeof(UShort);
2536 case DW_EH_PE_udata4: return sizeof(UInt);
2537 case DW_EH_PE_udata8: return sizeof(ULong);
2538 default: vg_assert(0);
2539 }
2540}
2541
florian518850b2014-10-22 22:25:30 +00002542static Addr step_encoded_Addr ( const AddressDecodingInfo* adi,
sewardj5d616df2013-07-02 08:07:15 +00002543 /*MOD*/DiCursor* data )
tom2fd38902005-05-01 15:14:01 +00002544{
sewardjddf006d2007-02-24 23:29:31 +00002545 /* Regarding the handling of DW_EH_PE_absptr. DWARF3 says this
2546 denotes an absolute address, hence you would think 'base' is
2547 zero. However, that is nonsensical (unless relocations are to
2548 be applied to the unwind data before reading it, which sounds
2549 unlikely). My interpretation is that DW_EH_PE_absptr indicates
2550 an address relative to where the object was loaded (technically,
2551 relative to its stated load VMA, hence the use of text_bias
2552 rather than text_avma). Hmm, should we use text_bias or
2553 text_avma here? Not sure.
2554
2555 This view appears to be supported by DWARF3 spec sec 7.3
2556 "Executable Objects and Shared Objects":
2557
2558 This requirement makes the debugging information for shared
2559 objects position independent. Virtual addresses in a shared
2560 object may be calculated by adding the offset to the base
2561 address at which the object was attached. This offset is
2562 available in the run-time linker's data structures.
2563 */
sewardj5d616df2013-07-02 08:07:15 +00002564 Addr base;
2565 Word offset;
2566 UChar encoding = adi->encoding;
2567 DiCursor ehframe_image = adi->ehframe_image;
2568 Addr ehframe_avma = adi->ehframe_avma;
sewardj8eb8bab2015-07-21 14:44:28 +00002569 Addr got_avma = adi->got_avma;
tom2fd38902005-05-01 15:14:01 +00002570
2571 vg_assert((encoding & DW_EH_PE_indirect) == 0);
2572
tom2fd38902005-05-01 15:14:01 +00002573 switch (encoding & 0x70) {
2574 case DW_EH_PE_absptr:
sewardjddf006d2007-02-24 23:29:31 +00002575 base = adi->text_bias;
tom2fd38902005-05-01 15:14:01 +00002576 break;
2577 case DW_EH_PE_pcrel:
sewardj5d616df2013-07-02 08:07:15 +00002578 base = ehframe_avma + ML_(cur_minus)(*data, ehframe_image);
tom2fd38902005-05-01 15:14:01 +00002579 break;
2580 case DW_EH_PE_datarel:
sewardj8eb8bab2015-07-21 14:44:28 +00002581 base = got_avma;
tom2fd38902005-05-01 15:14:01 +00002582 break;
2583 case DW_EH_PE_textrel:
2584 vg_assert(0);
2585 base = /* text base address */ 0;
2586 break;
2587 case DW_EH_PE_funcrel:
2588 base = 0;
2589 break;
2590 case DW_EH_PE_aligned:
2591 base = 0;
sewardj5d616df2013-07-02 08:07:15 +00002592 offset = ML_(cur_minus)(*data, ehframe_image);
tom2fd38902005-05-01 15:14:01 +00002593 if ((offset % sizeof(Addr)) != 0) {
sewardj5d616df2013-07-02 08:07:15 +00002594 Word nbytes = sizeof(Addr) - (offset % sizeof(Addr));
2595 *data = ML_(cur_plus)(*data, nbytes);
tom2fd38902005-05-01 15:14:01 +00002596 }
2597 break;
2598 default:
2599 vg_assert(0);
2600 }
2601
sewardj325ec872005-05-01 20:24:06 +00002602 if ((encoding & 0x07) == 0x00)
sewardj8eb41322005-05-01 23:50:08 +00002603 encoding |= default_Addr_encoding();
tom2fd38902005-05-01 15:14:01 +00002604
2605 switch (encoding & 0x0f) {
2606 case DW_EH_PE_udata2:
sewardj5d616df2013-07-02 08:07:15 +00002607 return base + ML_(cur_step_UShort)(data);
tom2fd38902005-05-01 15:14:01 +00002608 case DW_EH_PE_udata4:
sewardj5d616df2013-07-02 08:07:15 +00002609 return base + ML_(cur_step_UInt)(data);
tom2fd38902005-05-01 15:14:01 +00002610 case DW_EH_PE_udata8:
sewardj5d616df2013-07-02 08:07:15 +00002611 return base + ML_(cur_step_ULong)(data);
tom2fd38902005-05-01 15:14:01 +00002612 case DW_EH_PE_sdata2:
sewardj5d616df2013-07-02 08:07:15 +00002613 return base + ML_(cur_step_Short)(data);
tom2fd38902005-05-01 15:14:01 +00002614 case DW_EH_PE_sdata4:
sewardj5d616df2013-07-02 08:07:15 +00002615 return base + ML_(cur_step_Int)(data);
tom2fd38902005-05-01 15:14:01 +00002616 case DW_EH_PE_sdata8:
sewardj5d616df2013-07-02 08:07:15 +00002617 return base + ML_(cur_step_Long)(data);
tom2fd38902005-05-01 15:14:01 +00002618 default:
sewardj325ec872005-05-01 20:24:06 +00002619 vg_assert2(0, "read encoded address %d\n", encoding & 0x0f);
tom2fd38902005-05-01 15:14:01 +00002620 }
2621}
2622
sewardj5c638c22005-04-30 07:55:58 +00002623
sewardj72427fa2007-02-27 16:52:23 +00002624/* ------------ Run/show DWARF3 expressions ---------- */
2625
sewardj72427fa2007-02-27 16:52:23 +00002626/* Convert the DWARF3 expression in expr[0 .. exprlen-1] into a dag
2627 (of CfiExprs) stored in ctx->exprs, and return the index in
2628 ctx->exprs of the root node. Or fail in which case return -1. */
sewardj7888e222007-02-28 13:03:27 +00002629/* IMPORTANT: when adding expression forms here, also remember to
2630 add suitable evaluation code in evalCfiExpr in debuginfo.c. */
florian518850b2014-10-22 22:25:30 +00002631static Int dwarfexpr_to_dag ( const UnwindContext* ctx,
sewardj5d616df2013-07-02 08:07:15 +00002632 DiCursor expr, Int exprlen,
sewardj72427fa2007-02-27 16:52:23 +00002633 Bool push_cfa_at_start,
2634 Bool ddump_frames )
2635{
2636# define N_EXPR_STACK 20
2637
2638# define PUSH(_arg) \
2639 do { \
2640 vg_assert(sp >= -1 && sp < N_EXPR_STACK); \
2641 if (sp == N_EXPR_STACK-1) \
2642 return -1; \
2643 sp++; \
2644 stack[sp] = (_arg); \
2645 } while (0)
2646
2647# define POP(_lval) \
2648 do { \
2649 vg_assert(sp >= -1 && sp < N_EXPR_STACK); \
2650 if (sp == -1) \
2651 return -1; \
2652 _lval = stack[sp]; \
2653 sp--; \
2654 } while (0)
2655
tomf6716dd2012-09-21 09:04:27 +00002656 Int ix, ix2, reg;
2657 UChar opcode;
2658 Word sw;
2659 UWord uw;
tom40628fa2012-09-21 09:12:30 +00002660 CfiUnop uop;
tomf6716dd2012-09-21 09:04:27 +00002661 CfiBinop bop;
florian6bd9dc12012-11-23 16:17:43 +00002662 const HChar* opname;
sewardj72427fa2007-02-27 16:52:23 +00002663
2664 Int sp; /* # of top element: valid is -1 .. N_EXPR_STACK-1 */
2665 Int stack[N_EXPR_STACK]; /* indices into ctx->exprs */
florian518850b2014-10-22 22:25:30 +00002666 const struct UnwindContextState* ctxs = &ctx->state[ctx->state_sp];
sewardj72427fa2007-02-27 16:52:23 +00002667
sewardj5d616df2013-07-02 08:07:15 +00002668 XArray* dst = ctx->exprs;
2669 DiCursor limit = ML_(cur_plus)(expr, exprlen);
sewardj72427fa2007-02-27 16:52:23 +00002670
2671 vg_assert(dst);
2672 vg_assert(exprlen >= 0);
2673
2674 sp = -1; /* empty */
2675
2676 /* Synthesise the CFA as a CfiExpr */
2677 if (push_cfa_at_start) {
sewardjde1b03d2009-08-03 13:47:04 +00002678 if (ctxs->cfa_is_regoff) {
sewardj72427fa2007-02-27 16:52:23 +00002679 /* cfa is reg +/- offset */
2680 ix = ML_(CfiExpr_Binop)( dst,
tomf6716dd2012-09-21 09:04:27 +00002681 Cbinop_Add,
sewardjde1b03d2009-08-03 13:47:04 +00002682 ML_(CfiExpr_DwReg)( dst, ctxs->cfa_reg ),
2683 ML_(CfiExpr_Const)( dst, (UWord)(Word)ctxs->cfa_off )
sewardj72427fa2007-02-27 16:52:23 +00002684 );
2685 PUSH(ix);
2686 } else {
2687 /* CFA is already an expr; use its root node */
sewardjde1b03d2009-08-03 13:47:04 +00002688 PUSH(ctxs->cfa_expr_ix);
sewardj72427fa2007-02-27 16:52:23 +00002689 }
2690 }
2691
2692 while (True) {
2693
2694 vg_assert(sp >= -1 && sp < N_EXPR_STACK);
2695
sewardj5d616df2013-07-02 08:07:15 +00002696 if (ML_(cur_cmpGT)(expr, limit)) /* "expr > limit" */
sewardj72427fa2007-02-27 16:52:23 +00002697 return -1; /* overrun - something's wrong */
2698
sewardj5d616df2013-07-02 08:07:15 +00002699 if (ML_(cur_cmpEQ)(expr, limit)) { /* "expr == limit" */
sewardj72427fa2007-02-27 16:52:23 +00002700 /* end of expr - return expr on the top of stack. */
2701 if (sp == -1)
2702 return -1; /* stack empty. Bad. */
2703 else
2704 break;
2705 }
2706
tom40628fa2012-09-21 09:12:30 +00002707 uop = 0; bop = 0; opname = NULL; /* excessively conservative */
sewardj19dc88f2007-02-28 01:46:30 +00002708
sewardj5d616df2013-07-02 08:07:15 +00002709 opcode = ML_(cur_step_UChar)(&expr);
sewardj72427fa2007-02-27 16:52:23 +00002710 switch (opcode) {
2711
sewardj19dc88f2007-02-28 01:46:30 +00002712 case DW_OP_lit0 ... DW_OP_lit31:
2713 /* push: literal 0 .. 31 */
2714 sw = (Word)opcode - (Word)DW_OP_lit0;
2715 vg_assert(sw >= 0 && sw <= 31);
2716 PUSH( ML_(CfiExpr_Const)( dst, (UWord)sw ) );
2717 if (ddump_frames)
2718 VG_(printf)("DW_OP_lit%ld", sw);
2719 break;
2720
sewardj72427fa2007-02-27 16:52:23 +00002721 case DW_OP_breg0 ... DW_OP_breg31:
2722 /* push: reg + sleb128 */
2723 reg = (Int)opcode - (Int)DW_OP_breg0;
2724 vg_assert(reg >= 0 && reg <= 31);
sewardj5d616df2013-07-02 08:07:15 +00002725 sw = step_leb128S( &expr );
sewardj72427fa2007-02-27 16:52:23 +00002726 ix = ML_(CfiExpr_Binop)( dst,
tomf6716dd2012-09-21 09:04:27 +00002727 Cbinop_Add,
sewardj72427fa2007-02-27 16:52:23 +00002728 ML_(CfiExpr_DwReg)( dst, reg ),
2729 ML_(CfiExpr_Const)( dst, (UWord)sw )
2730 );
2731 PUSH(ix);
2732 if (ddump_frames)
2733 VG_(printf)("DW_OP_breg%d: %ld", reg, sw);
2734 break;
2735
sewardj13596ff2009-01-25 23:48:31 +00002736 case DW_OP_reg0 ... DW_OP_reg31:
2737 /* push: reg */
2738 reg = (Int)opcode - (Int)DW_OP_reg0;
2739 vg_assert(reg >= 0 && reg <= 31);
2740 ix = ML_(CfiExpr_DwReg)( dst, reg );
2741 PUSH(ix);
2742 if (ddump_frames)
2743 VG_(printf)("DW_OP_reg%d", reg);
2744 break;
2745
sewardjc153bf62008-01-14 12:04:11 +00002746 case DW_OP_plus_uconst:
sewardj5d616df2013-07-02 08:07:15 +00002747 uw = step_leb128U( &expr );
sewardjc153bf62008-01-14 12:04:11 +00002748 PUSH( ML_(CfiExpr_Const)( dst, uw ) );
2749 POP( ix );
2750 POP( ix2 );
tomf6716dd2012-09-21 09:04:27 +00002751 PUSH( ML_(CfiExpr_Binop)( dst, Cbinop_Add, ix2, ix ) );
sewardjc153bf62008-01-14 12:04:11 +00002752 if (ddump_frames)
2753 VG_(printf)("DW_OP_plus_uconst: %lu", uw);
2754 break;
2755
sewardj72427fa2007-02-27 16:52:23 +00002756 case DW_OP_const4s:
2757 /* push: 32-bit signed immediate */
sewardj5d616df2013-07-02 08:07:15 +00002758 sw = step_le_s_encoded_literal( &expr, 4 );
sewardj72427fa2007-02-27 16:52:23 +00002759 PUSH( ML_(CfiExpr_Const)( dst, (UWord)sw ) );
2760 if (ddump_frames)
2761 VG_(printf)("DW_OP_const4s: %ld", sw);
2762 break;
2763
tom40628fa2012-09-21 09:12:30 +00002764 case DW_OP_const2s:
2765 /* push: 16-bit signed immediate */
sewardj5d616df2013-07-02 08:07:15 +00002766 sw = step_le_s_encoded_literal( &expr, 2 );
tom40628fa2012-09-21 09:12:30 +00002767 PUSH( ML_(CfiExpr_Const)( dst, (UWord)sw ) );
2768 if (ddump_frames)
2769 VG_(printf)("DW_OP_const2s: %ld", sw);
2770 break;
2771
sewardj13596ff2009-01-25 23:48:31 +00002772 case DW_OP_const1s:
2773 /* push: 8-bit signed immediate */
sewardj5d616df2013-07-02 08:07:15 +00002774 sw = step_le_s_encoded_literal( &expr, 1 );
sewardj13596ff2009-01-25 23:48:31 +00002775 PUSH( ML_(CfiExpr_Const)( dst, (UWord)sw ) );
2776 if (ddump_frames)
2777 VG_(printf)("DW_OP_const1s: %ld", sw);
2778 break;
2779
tom40628fa2012-09-21 09:12:30 +00002780 case DW_OP_const1u:
2781 /* push: 8-bit unsigned immediate */
sewardj5d616df2013-07-02 08:07:15 +00002782 uw = step_le_u_encoded_literal( &expr, 1 );
tom40628fa2012-09-21 09:12:30 +00002783 PUSH( ML_(CfiExpr_Const)( dst, uw ) );
2784 if (ddump_frames)
2785 VG_(printf)("DW_OP_const1: %lu", uw);
2786 break;
2787
2788 case DW_OP_const2u:
2789 /* push: 16-bit unsigned immediate */
sewardj5d616df2013-07-02 08:07:15 +00002790 uw = step_le_u_encoded_literal( &expr, 2 );
tom40628fa2012-09-21 09:12:30 +00002791 PUSH( ML_(CfiExpr_Const)( dst, uw ) );
2792 if (ddump_frames)
2793 VG_(printf)("DW_OP_const2: %lu", uw);
2794 break;
2795
2796 case DW_OP_const4u:
2797 /* push: 32-bit unsigned immediate */
sewardj5d616df2013-07-02 08:07:15 +00002798 uw = step_le_u_encoded_literal( &expr, 4 );
tom40628fa2012-09-21 09:12:30 +00002799 PUSH( ML_(CfiExpr_Const)( dst, uw ) );
2800 if (ddump_frames)
2801 VG_(printf)("DW_OP_const4: %lu", uw);
2802 break;
2803
2804 case DW_OP_abs:
2805 uop = Cunop_Abs; opname = "abs"; goto unop;
2806 case DW_OP_neg:
2807 uop = Cunop_Neg; opname = "neg"; goto unop;
2808 case DW_OP_not:
2809 uop = Cunop_Not; opname = "not"; goto unop;
2810 unop:
2811 POP( ix );
2812 PUSH( ML_(CfiExpr_Unop)( dst, uop, ix ) );
2813 if (ddump_frames)
2814 VG_(printf)("DW_OP_%s", opname);
2815 break;
2816
sewardj72427fa2007-02-27 16:52:23 +00002817 case DW_OP_minus:
tomf6716dd2012-09-21 09:04:27 +00002818 bop = Cbinop_Sub; opname = "minus"; goto binop;
sewardj72427fa2007-02-27 16:52:23 +00002819 case DW_OP_plus:
tomf6716dd2012-09-21 09:04:27 +00002820 bop = Cbinop_Add; opname = "plus"; goto binop;
sewardj19dc88f2007-02-28 01:46:30 +00002821 case DW_OP_and:
tomf6716dd2012-09-21 09:04:27 +00002822 bop = Cbinop_And; opname = "and"; goto binop;
sewardj7888e222007-02-28 13:03:27 +00002823 case DW_OP_mul:
tomf6716dd2012-09-21 09:04:27 +00002824 bop = Cbinop_Mul; opname = "mul"; goto binop;
tom0b982392011-07-05 09:22:32 +00002825 case DW_OP_shl:
tomf6716dd2012-09-21 09:04:27 +00002826 bop = Cbinop_Shl; opname = "shl"; goto binop;
tom0b982392011-07-05 09:22:32 +00002827 case DW_OP_shr:
tomf6716dd2012-09-21 09:04:27 +00002828 bop = Cbinop_Shr; opname = "shr"; goto binop;
tom0b982392011-07-05 09:22:32 +00002829 case DW_OP_eq:
tomf6716dd2012-09-21 09:04:27 +00002830 bop = Cbinop_Eq; opname = "eq"; goto binop;
tom0b982392011-07-05 09:22:32 +00002831 case DW_OP_ge:
tomf6716dd2012-09-21 09:04:27 +00002832 bop = Cbinop_Ge; opname = "ge"; goto binop;
tom0b982392011-07-05 09:22:32 +00002833 case DW_OP_gt:
tomf6716dd2012-09-21 09:04:27 +00002834 bop = Cbinop_Gt; opname = "gt"; goto binop;
tom0b982392011-07-05 09:22:32 +00002835 case DW_OP_le:
tomf6716dd2012-09-21 09:04:27 +00002836 bop = Cbinop_Le; opname = "le"; goto binop;
tom0b982392011-07-05 09:22:32 +00002837 case DW_OP_lt:
tomf6716dd2012-09-21 09:04:27 +00002838 bop = Cbinop_Lt; opname = "lt"; goto binop;
tom0b982392011-07-05 09:22:32 +00002839 case DW_OP_ne:
tomf6716dd2012-09-21 09:04:27 +00002840 bop = Cbinop_Ne; opname = "ne"; goto binop;
sewardj19dc88f2007-02-28 01:46:30 +00002841 binop:
sewardj72427fa2007-02-27 16:52:23 +00002842 POP( ix );
2843 POP( ix2 );
tomf6716dd2012-09-21 09:04:27 +00002844 PUSH( ML_(CfiExpr_Binop)( dst, bop, ix2, ix ) );
sewardj72427fa2007-02-27 16:52:23 +00002845 if (ddump_frames)
sewardj19dc88f2007-02-28 01:46:30 +00002846 VG_(printf)("DW_OP_%s", opname);
sewardj72427fa2007-02-27 16:52:23 +00002847 break;
2848
sewardjbd7aca62007-08-31 23:08:39 +00002849 case DW_OP_deref:
2850 POP( ix );
2851 PUSH( ML_(CfiExpr_Deref)( dst, ix ) );
2852 if (ddump_frames)
2853 VG_(printf)("DW_OP_deref");
2854 break;
2855
sewardj72427fa2007-02-27 16:52:23 +00002856 default:
sewardj7888e222007-02-28 13:03:27 +00002857 if (!VG_(clo_xml))
2858 VG_(message)(Vg_DebugMsg,
sewardj1ff57e62007-11-20 08:46:05 +00002859 "Warning: DWARF2 CFI reader: unhandled DW_OP_ "
sewardj738856f2009-07-15 14:48:32 +00002860 "opcode 0x%x\n", (Int)opcode);
sewardj72427fa2007-02-27 16:52:23 +00002861 return -1;
2862 }
2863
sewardj5d616df2013-07-02 08:07:15 +00002864 if (ML_(cur_cmpLT)(expr, limit) && ddump_frames)
sewardj72427fa2007-02-27 16:52:23 +00002865 VG_(printf)("; ");
2866
2867 }
2868
2869 vg_assert(sp >= -1 && sp < N_EXPR_STACK);
2870 if (sp == -1)
2871 return -1;
2872
2873 if (0 && ddump_frames)
2874 ML_(ppCfiExpr)( dst, stack[sp] );
2875 return stack[sp];
2876
2877# undef POP
2878# undef PUSH
2879# undef N_EXPR_STACK
2880}
2881
2882
sewardj55022aa2005-05-03 16:05:00 +00002883/* ------------ Run/show CFI instructions ------------ */
2884
sewardj5c638c22005-04-30 07:55:58 +00002885/* Run a CFI instruction, and also return its length.
2886 Returns 0 if the instruction could not be executed.
2887*/
2888static Int run_CF_instruction ( /*MOD*/UnwindContext* ctx,
sewardj5d616df2013-07-02 08:07:15 +00002889 DiCursor instrIN,
florian518850b2014-10-22 22:25:30 +00002890 const UnwindContext* restore_ctx,
2891 const AddressDecodingInfo* adi,
2892 const DebugInfo* di )
sewardj5c638c22005-04-30 07:55:58 +00002893{
sewardj5d616df2013-07-02 08:07:15 +00002894 Int off, reg, reg2, len, j;
2895 UInt delta;
2896 Addr printing_bias = ((Addr)ctx->initloc) - ((Addr)di->text_bias);
sewardjde1b03d2009-08-03 13:47:04 +00002897 struct UnwindContextState* ctxs;
sewardj5d616df2013-07-02 08:07:15 +00002898
2899 DiCursor instr = instrIN;
2900 UChar instr_0 = ML_(cur_step_UChar)(&instr);
2901 UChar hi2 = (instr_0 >> 6) & 3;
2902 UChar lo6 = instr_0 & 0x3F;
sewardj5c638c22005-04-30 07:55:58 +00002903
sewardjde1b03d2009-08-03 13:47:04 +00002904 if (ctx->state_sp < 0 || ctx->state_sp >= N_RR_STACK)
sewardj3d026b12009-05-21 15:33:36 +00002905 return 0; /* bogus reg-rule stack pointer */
2906
sewardjde1b03d2009-08-03 13:47:04 +00002907 ctxs = &ctx->state[ctx->state_sp];
sewardj5c638c22005-04-30 07:55:58 +00002908 if (hi2 == DW_CFA_advance_loc) {
2909 delta = (UInt)lo6;
sewardj987a7652010-09-23 13:24:48 +00002910 delta *= ctx->code_a_f;
sewardj5c638c22005-04-30 07:55:58 +00002911 ctx->loc += delta;
sewardjb8b79ad2008-03-03 01:35:41 +00002912 if (di->ddump_frames)
sewardj3646a492007-02-16 14:17:10 +00002913 VG_(printf)(" DW_CFA_advance_loc: %d to %08lx\n",
2914 (Int)delta, (Addr)ctx->loc + printing_bias);
sewardj5d616df2013-07-02 08:07:15 +00002915 return ML_(cur_minus)(instr, instrIN);
sewardj5c638c22005-04-30 07:55:58 +00002916 }
2917
2918 if (hi2 == DW_CFA_offset) {
sewardj72427fa2007-02-27 16:52:23 +00002919 /* Set rule for reg 'lo6' to CFAOff(off * data_af) */
sewardj5d616df2013-07-02 08:07:15 +00002920 off = step_leb128( &instr, 0 );
sewardj5c638c22005-04-30 07:55:58 +00002921 reg = (Int)lo6;
2922 if (reg < 0 || reg >= N_CFI_REGS)
2923 return 0; /* fail */
sewardjde1b03d2009-08-03 13:47:04 +00002924 ctxs->reg[reg].tag = RR_CFAOff;
2925 ctxs->reg[reg].arg = off * ctx->data_a_f;
sewardjb8b79ad2008-03-03 01:35:41 +00002926 if (di->ddump_frames)
sewardj3646a492007-02-16 14:17:10 +00002927 VG_(printf)(" DW_CFA_offset: r%d at cfa%s%d\n",
sewardj3d026b12009-05-21 15:33:36 +00002928 (Int)reg,
sewardjde1b03d2009-08-03 13:47:04 +00002929 ctxs->reg[reg].arg < 0 ? "" : "+",
2930 (Int)ctxs->reg[reg].arg );
sewardj5d616df2013-07-02 08:07:15 +00002931 return ML_(cur_minus)(instr, instrIN);
sewardj5c638c22005-04-30 07:55:58 +00002932 }
2933
2934 if (hi2 == DW_CFA_restore) {
sewardj8eb41322005-05-01 23:50:08 +00002935 reg = (Int)lo6;
2936 if (reg < 0 || reg >= N_CFI_REGS)
2937 return 0; /* fail */
2938 if (restore_ctx == NULL)
2939 return 0; /* fail */
sewardjde1b03d2009-08-03 13:47:04 +00002940 ctxs->reg[reg] = restore_ctx->state[restore_ctx->state_sp].reg[reg];
sewardjb8b79ad2008-03-03 01:35:41 +00002941 if (di->ddump_frames)
sewardj687bbf62007-02-16 20:11:27 +00002942 VG_(printf)(" DW_CFA_restore: r%d\n", (Int)reg);
sewardj5d616df2013-07-02 08:07:15 +00002943 return ML_(cur_minus)(instr, instrIN);
sewardj5c638c22005-04-30 07:55:58 +00002944 }
2945
2946 vg_assert(hi2 == DW_CFA_use_secondary);
2947
2948 switch (lo6) {
2949 case DW_CFA_nop:
sewardjb8b79ad2008-03-03 01:35:41 +00002950 if (di->ddump_frames)
sewardj3646a492007-02-16 14:17:10 +00002951 VG_(printf)(" DW_CFA_nop\n");
sewardj5c638c22005-04-30 07:55:58 +00002952 break;
tom2fd38902005-05-01 15:14:01 +00002953 case DW_CFA_set_loc:
sewardj1936f8b2006-11-16 12:21:52 +00002954 /* WAS:
2955 ctx->loc = read_Addr(&instr[i]) - ctx->initloc; i+= sizeof(Addr);
2956 Was this ever right? */
sewardjddf006d2007-02-24 23:29:31 +00002957 /* 2007 Feb 23: No. binutils/dwarf.c treats it as an encoded
2958 address and that appears to be in accordance with the
2959 DWARF3 spec. */
sewardj5d616df2013-07-02 08:07:15 +00002960 ctx->loc = step_encoded_Addr(adi, &instr);
sewardjb8b79ad2008-03-03 01:35:41 +00002961 if (di->ddump_frames)
sewardj3646a492007-02-16 14:17:10 +00002962 VG_(printf)(" rci:DW_CFA_set_loc\n");
tom2fd38902005-05-01 15:14:01 +00002963 break;
sewardj5c638c22005-04-30 07:55:58 +00002964 case DW_CFA_advance_loc1:
sewardj5d616df2013-07-02 08:07:15 +00002965 delta = (UInt)ML_(cur_step_UChar)(&instr);
sewardj987a7652010-09-23 13:24:48 +00002966 delta *= ctx->code_a_f;
tom2fd38902005-05-01 15:14:01 +00002967 ctx->loc += delta;
sewardjb8b79ad2008-03-03 01:35:41 +00002968 if (di->ddump_frames)
sewardj687bbf62007-02-16 20:11:27 +00002969 VG_(printf)(" DW_CFA_advance_loc1: %d to %08lx\n",
2970 (Int)delta, (Addr)ctx->loc + printing_bias);
tom2fd38902005-05-01 15:14:01 +00002971 break;
2972 case DW_CFA_advance_loc2:
sewardj5d616df2013-07-02 08:07:15 +00002973 delta = (UInt)ML_(cur_step_UShort)(&instr);
sewardj987a7652010-09-23 13:24:48 +00002974 delta *= ctx->code_a_f;
tom2fd38902005-05-01 15:14:01 +00002975 ctx->loc += delta;
sewardjb8b79ad2008-03-03 01:35:41 +00002976 if (di->ddump_frames)
sewardj687bbf62007-02-16 20:11:27 +00002977 VG_(printf)(" DW_CFA_advance_loc2: %d to %08lx\n",
2978 (Int)delta, (Addr)ctx->loc + printing_bias);
tom2fd38902005-05-01 15:14:01 +00002979 break;
2980 case DW_CFA_advance_loc4:
sewardj5d616df2013-07-02 08:07:15 +00002981 delta = (UInt)ML_(cur_step_UInt)(&instr);
sewardj987a7652010-09-23 13:24:48 +00002982 delta *= ctx->code_a_f;
tom2fd38902005-05-01 15:14:01 +00002983 ctx->loc += delta;
sewardjb8b79ad2008-03-03 01:35:41 +00002984 if (di->ddump_frames)
sewardj687bbf62007-02-16 20:11:27 +00002985 VG_(printf)(" DW_CFA_advance_loc4: %d to %08lx\n",
2986 (Int)delta, (Addr)ctx->loc + printing_bias);
sewardj5c638c22005-04-30 07:55:58 +00002987 break;
2988
2989 case DW_CFA_def_cfa:
sewardj5d616df2013-07-02 08:07:15 +00002990 reg = step_leb128( &instr, 0 );
2991 off = step_leb128( &instr, 0 );
sewardj5c638c22005-04-30 07:55:58 +00002992 if (reg < 0 || reg >= N_CFI_REGS)
2993 return 0; /* fail */
sewardjde1b03d2009-08-03 13:47:04 +00002994 ctxs->cfa_is_regoff = True;
2995 ctxs->cfa_expr_ix = 0;
2996 ctxs->cfa_reg = reg;
2997 ctxs->cfa_off = off;
sewardjb8b79ad2008-03-03 01:35:41 +00002998 if (di->ddump_frames)
sewardj3646a492007-02-16 14:17:10 +00002999 VG_(printf)(" DW_CFA_def_cfa: r%d ofs %d\n", (Int)reg, (Int)off);
sewardj5c638c22005-04-30 07:55:58 +00003000 break;
3001
sewardjd69222c2006-04-08 16:22:53 +00003002 case DW_CFA_def_cfa_sf:
sewardj5d616df2013-07-02 08:07:15 +00003003 reg = step_leb128( &instr, 0 );
3004 off = step_leb128( &instr, 1 );
sewardjd69222c2006-04-08 16:22:53 +00003005 if (reg < 0 || reg >= N_CFI_REGS)
3006 return 0; /* fail */
sewardjde1b03d2009-08-03 13:47:04 +00003007 ctxs->cfa_is_regoff = True;
3008 ctxs->cfa_expr_ix = 0;
3009 ctxs->cfa_reg = reg;
3010 ctxs->cfa_off = off * ctx->data_a_f;
sewardjb8b79ad2008-03-03 01:35:41 +00003011 if (di->ddump_frames)
sewardj3646a492007-02-16 14:17:10 +00003012 VG_(printf)(" rci:DW_CFA_def_cfa_sf\n");
sewardjd69222c2006-04-08 16:22:53 +00003013 break;
3014
sewardje0707a62005-05-02 12:25:13 +00003015 case DW_CFA_register:
sewardj5d616df2013-07-02 08:07:15 +00003016 reg = step_leb128( &instr, 0 );
3017 reg2 = step_leb128( &instr, 0 );
sewardje0707a62005-05-02 12:25:13 +00003018 if (reg < 0 || reg >= N_CFI_REGS)
3019 return 0; /* fail */
3020 if (reg2 < 0 || reg2 >= N_CFI_REGS)
3021 return 0; /* fail */
sewardjde1b03d2009-08-03 13:47:04 +00003022 ctxs->reg[reg].tag = RR_Reg;
3023 ctxs->reg[reg].arg = reg2;
sewardjb8b79ad2008-03-03 01:35:41 +00003024 if (di->ddump_frames)
sewardj72427fa2007-02-27 16:52:23 +00003025 VG_(printf)(" DW_CFA_register: r%d in r%d\n",
3026 (Int)reg, (Int)reg2);
sewardje0707a62005-05-02 12:25:13 +00003027 break;
3028
sewardjd69222c2006-04-08 16:22:53 +00003029 case DW_CFA_offset_extended:
sewardj5d616df2013-07-02 08:07:15 +00003030 reg = step_leb128( &instr, 0 );
3031 off = step_leb128( &instr, 0 );
sewardjd69222c2006-04-08 16:22:53 +00003032 if (reg < 0 || reg >= N_CFI_REGS)
3033 return 0; /* fail */
sewardjde1b03d2009-08-03 13:47:04 +00003034 ctxs->reg[reg].tag = RR_CFAOff;
3035 ctxs->reg[reg].arg = off * ctx->data_a_f;
sewardjb8b79ad2008-03-03 01:35:41 +00003036 if (di->ddump_frames)
sewardj3646a492007-02-16 14:17:10 +00003037 VG_(printf)(" rci:DW_CFA_offset_extended\n");
sewardjd69222c2006-04-08 16:22:53 +00003038 break;
3039
sewardj325ec872005-05-01 20:24:06 +00003040 case DW_CFA_offset_extended_sf:
sewardj5d616df2013-07-02 08:07:15 +00003041 reg = step_leb128( &instr, 0 );
3042 off = step_leb128( &instr, 1 );
sewardj325ec872005-05-01 20:24:06 +00003043 if (reg < 0 || reg >= N_CFI_REGS)
3044 return 0; /* fail */
sewardjde1b03d2009-08-03 13:47:04 +00003045 ctxs->reg[reg].tag = RR_CFAOff;
3046 ctxs->reg[reg].arg = off * ctx->data_a_f;
sewardjb8b79ad2008-03-03 01:35:41 +00003047 if (di->ddump_frames)
sewardjddf006d2007-02-24 23:29:31 +00003048 VG_(printf)(" DW_CFA_offset_extended_sf: r%d at cfa%s%d\n",
sewardj3d026b12009-05-21 15:33:36 +00003049 reg,
sewardjde1b03d2009-08-03 13:47:04 +00003050 ctxs->reg[reg].arg < 0 ? "" : "+",
3051 (Int)ctxs->reg[reg].arg);
sewardjddf006d2007-02-24 23:29:31 +00003052 break;
sewardj325ec872005-05-01 20:24:06 +00003053
sewardjd69222c2006-04-08 16:22:53 +00003054 case DW_CFA_GNU_negative_offset_extended:
sewardj5d616df2013-07-02 08:07:15 +00003055 reg = step_leb128( &instr, 0 );
3056 off = step_leb128( &instr, 0 );
sewardjd69222c2006-04-08 16:22:53 +00003057 if (reg < 0 || reg >= N_CFI_REGS)
3058 return 0; /* fail */
sewardjde1b03d2009-08-03 13:47:04 +00003059 ctxs->reg[reg].tag = RR_CFAOff;
3060 ctxs->reg[reg].arg = (-off) * ctx->data_a_f;
sewardjb8b79ad2008-03-03 01:35:41 +00003061 if (di->ddump_frames)
sewardj3646a492007-02-16 14:17:10 +00003062 VG_(printf)(" rci:DW_CFA_GNU_negative_offset_extended\n");
sewardjd69222c2006-04-08 16:22:53 +00003063 break;
3064
3065 case DW_CFA_restore_extended:
sewardj5d616df2013-07-02 08:07:15 +00003066 reg = step_leb128( &instr, 0 );
sewardjd69222c2006-04-08 16:22:53 +00003067 if (reg < 0 || reg >= N_CFI_REGS)
3068 return 0; /* fail */
3069 if (restore_ctx == NULL)
3070 return 0; /* fail */
sewardjde1b03d2009-08-03 13:47:04 +00003071 ctxs->reg[reg] = restore_ctx->state[restore_ctx->state_sp].reg[reg];
sewardjb8b79ad2008-03-03 01:35:41 +00003072 if (di->ddump_frames)
sewardj3646a492007-02-16 14:17:10 +00003073 VG_(printf)(" rci:DW_CFA_restore_extended\n");
sewardjd69222c2006-04-08 16:22:53 +00003074 break;
3075
3076 case DW_CFA_val_offset:
sewardj5d616df2013-07-02 08:07:15 +00003077 reg = step_leb128( &instr, 0 );
3078 off = step_leb128( &instr, 0 );
sewardjd69222c2006-04-08 16:22:53 +00003079 if (reg < 0 || reg >= N_CFI_REGS)
3080 return 0; /* fail */
sewardjde1b03d2009-08-03 13:47:04 +00003081 ctxs->reg[reg].tag = RR_CFAValOff;
3082 ctxs->reg[reg].arg = off * ctx->data_a_f;
sewardjb8b79ad2008-03-03 01:35:41 +00003083 if (di->ddump_frames)
sewardj3646a492007-02-16 14:17:10 +00003084 VG_(printf)(" rci:DW_CFA_val_offset\n");
sewardjd69222c2006-04-08 16:22:53 +00003085 break;
3086
3087 case DW_CFA_val_offset_sf:
sewardj5d616df2013-07-02 08:07:15 +00003088 reg = step_leb128( &instr, 0 );
3089 off = step_leb128( &instr, 1 );
sewardjd69222c2006-04-08 16:22:53 +00003090 if (reg < 0 || reg >= N_CFI_REGS)
3091 return 0; /* fail */
sewardjde1b03d2009-08-03 13:47:04 +00003092 ctxs->reg[reg].tag = RR_CFAValOff;
3093 ctxs->reg[reg].arg = off * ctx->data_a_f;
sewardjb8b79ad2008-03-03 01:35:41 +00003094 if (di->ddump_frames)
sewardj3646a492007-02-16 14:17:10 +00003095 VG_(printf)(" rci:DW_CFA_val_offset_sf\n");
sewardjd69222c2006-04-08 16:22:53 +00003096 break;
3097
sewardj325ec872005-05-01 20:24:06 +00003098 case DW_CFA_def_cfa_register:
sewardj5d616df2013-07-02 08:07:15 +00003099 reg = step_leb128( &instr, 0);
sewardj5c638c22005-04-30 07:55:58 +00003100 if (reg < 0 || reg >= N_CFI_REGS)
3101 return 0; /* fail */
sewardjde1b03d2009-08-03 13:47:04 +00003102 ctxs->cfa_is_regoff = True;
3103 ctxs->cfa_expr_ix = 0;
3104 ctxs->cfa_reg = reg;
sewardj72427fa2007-02-27 16:52:23 +00003105 /* ->cfa_off unchanged */
sewardjb8b79ad2008-03-03 01:35:41 +00003106 if (di->ddump_frames)
sewardj987a7652010-09-23 13:24:48 +00003107 VG_(printf)(" DW_CFA_def_cfa_register: r%d\n", (Int)reg );
sewardj5c638c22005-04-30 07:55:58 +00003108 break;
sewardj325ec872005-05-01 20:24:06 +00003109
3110 case DW_CFA_def_cfa_offset:
sewardj5d616df2013-07-02 08:07:15 +00003111 off = step_leb128( &instr, 0);
sewardjde1b03d2009-08-03 13:47:04 +00003112 ctxs->cfa_is_regoff = True;
3113 ctxs->cfa_expr_ix = 0;
sewardj72427fa2007-02-27 16:52:23 +00003114 /* ->reg is unchanged */
sewardjde1b03d2009-08-03 13:47:04 +00003115 ctxs->cfa_off = off;
sewardjb8b79ad2008-03-03 01:35:41 +00003116 if (di->ddump_frames)
sewardj3646a492007-02-16 14:17:10 +00003117 VG_(printf)(" DW_CFA_def_cfa_offset: %d\n", (Int)off);
sewardj5c638c22005-04-30 07:55:58 +00003118 break;
sewardj325ec872005-05-01 20:24:06 +00003119
sewardjab30d202005-05-15 17:14:28 +00003120 case DW_CFA_def_cfa_offset_sf:
sewardj5d616df2013-07-02 08:07:15 +00003121 off = step_leb128( &instr, 1);
sewardjde1b03d2009-08-03 13:47:04 +00003122 ctxs->cfa_is_regoff = True;
3123 ctxs->cfa_expr_ix = 0;
sewardj72427fa2007-02-27 16:52:23 +00003124 /* ->reg is unchanged */
sewardjde1b03d2009-08-03 13:47:04 +00003125 ctxs->cfa_off = off * ctx->data_a_f;
sewardjb8b79ad2008-03-03 01:35:41 +00003126 if (di->ddump_frames)
sewardjde1b03d2009-08-03 13:47:04 +00003127 VG_(printf)(" DW_CFA_def_cfa_offset_sf: %d\n", ctxs->cfa_off);
sewardjab30d202005-05-15 17:14:28 +00003128 break;
3129
sewardj301901f2007-01-12 19:21:22 +00003130 case DW_CFA_undefined:
sewardj5d616df2013-07-02 08:07:15 +00003131 reg = step_leb128( &instr, 0);
sewardj301901f2007-01-12 19:21:22 +00003132 if (reg < 0 || reg >= N_CFI_REGS)
3133 return 0; /* fail */
sewardjde1b03d2009-08-03 13:47:04 +00003134 ctxs->reg[reg].tag = RR_Undef;
3135 ctxs->reg[reg].arg = 0;
sewardjb8b79ad2008-03-03 01:35:41 +00003136 if (di->ddump_frames)
sewardj3646a492007-02-16 14:17:10 +00003137 VG_(printf)(" rci:DW_CFA_undefined\n");
sewardj301901f2007-01-12 19:21:22 +00003138 break;
3139
tom80b8b092009-04-08 15:06:34 +00003140 case DW_CFA_same_value:
sewardj5d616df2013-07-02 08:07:15 +00003141 reg = step_leb128( &instr, 0);
tom80b8b092009-04-08 15:06:34 +00003142 if (reg < 0 || reg >= N_CFI_REGS)
3143 return 0; /* fail */
sewardjde1b03d2009-08-03 13:47:04 +00003144 ctxs->reg[reg].tag = RR_Same;
3145 ctxs->reg[reg].arg = 0;
tom80b8b092009-04-08 15:06:34 +00003146 if (di->ddump_frames)
3147 VG_(printf)(" rci:DW_CFA_same_value\n");
3148 break;
3149
sewardj325ec872005-05-01 20:24:06 +00003150 case DW_CFA_GNU_args_size:
sewardj5c638c22005-04-30 07:55:58 +00003151 /* No idea what is supposed to happen. gdb-6.3 simply
3152 ignores these. */
sewardj5d616df2013-07-02 08:07:15 +00003153 /*off = */ (void)step_leb128( &instr, 0 );
sewardjb8b79ad2008-03-03 01:35:41 +00003154 if (di->ddump_frames)
sewardj3646a492007-02-16 14:17:10 +00003155 VG_(printf)(" rci:DW_CFA_GNU_args_size (ignored)\n");
sewardj5c638c22005-04-30 07:55:58 +00003156 break;
sewardj325ec872005-05-01 20:24:06 +00003157
sewardj5d616df2013-07-02 08:07:15 +00003158 case DW_CFA_expression: {
sewardj19dc88f2007-02-28 01:46:30 +00003159 /* Identical to DW_CFA_val_expression except that the value
3160 computed is an address and so needs one final
3161 dereference. */
sewardj5d616df2013-07-02 08:07:15 +00003162 DiCursor expr;
3163 reg = step_leb128( &instr, 0 );
3164 len = step_leb128( &instr, 0 );
3165 expr = instr;
3166 instr = ML_(cur_plus)(instr, len);
sewardj19dc88f2007-02-28 01:46:30 +00003167 if (reg < 0 || reg >= N_CFI_REGS)
sewardj1e601fe2005-05-16 11:48:34 +00003168 return 0; /* fail */
sewardjb8b79ad2008-03-03 01:35:41 +00003169 if (di->ddump_frames)
sewardj19dc88f2007-02-28 01:46:30 +00003170 VG_(printf)(" DW_CFA_expression: r%d (",
3171 (Int)reg);
3172 /* Convert the expression into a dag rooted at ctx->exprs index j,
3173 or fail. */
3174 j = dwarfexpr_to_dag ( ctx, expr, len, True/*push CFA at start*/,
sewardjb8b79ad2008-03-03 01:35:41 +00003175 di->ddump_frames);
3176 if (di->ddump_frames)
sewardj19dc88f2007-02-28 01:46:30 +00003177 VG_(printf)(")\n");
3178 vg_assert(j >= -1);
3179 if (j >= 0) {
3180 vg_assert(ctx->exprs);
3181 vg_assert( j < VG_(sizeXA)(ctx->exprs) );
3182 }
3183 if (j == -1)
3184 return 0; /* fail */
3185 /* Add an extra dereference */
3186 j = ML_(CfiExpr_Deref)( ctx->exprs, j );
sewardjde1b03d2009-08-03 13:47:04 +00003187 ctxs->reg[reg].tag = RR_ValExpr;
3188 ctxs->reg[reg].arg = j;
sewardj1e601fe2005-05-16 11:48:34 +00003189 break;
sewardj5d616df2013-07-02 08:07:15 +00003190 }
sewardj1e601fe2005-05-16 11:48:34 +00003191
sewardj5d616df2013-07-02 08:07:15 +00003192 case DW_CFA_val_expression: {
3193 DiCursor expr;
3194 reg = step_leb128( &instr, 0 );
3195 len = step_leb128( &instr, 0 );
3196 expr = instr;
3197 instr = ML_(cur_plus)(instr, len);
sewardjd69222c2006-04-08 16:22:53 +00003198 if (reg < 0 || reg >= N_CFI_REGS)
3199 return 0; /* fail */
sewardjb8b79ad2008-03-03 01:35:41 +00003200 if (di->ddump_frames)
sewardj72427fa2007-02-27 16:52:23 +00003201 VG_(printf)(" DW_CFA_val_expression: r%d (",
sewardj687bbf62007-02-16 20:11:27 +00003202 (Int)reg);
sewardj72427fa2007-02-27 16:52:23 +00003203 /* Convert the expression into a dag rooted at ctx->exprs index j,
3204 or fail. */
3205 j = dwarfexpr_to_dag ( ctx, expr, len, True/*push CFA at start*/,
sewardjb8b79ad2008-03-03 01:35:41 +00003206 di->ddump_frames);
3207 if (di->ddump_frames)
sewardj72427fa2007-02-27 16:52:23 +00003208 VG_(printf)(")\n");
3209 vg_assert(j >= -1);
3210 if (j >= 0) {
3211 vg_assert(ctx->exprs);
3212 vg_assert( j < VG_(sizeXA)(ctx->exprs) );
3213 }
3214 if (j == -1)
3215 return 0; /* fail */
sewardjde1b03d2009-08-03 13:47:04 +00003216 ctxs->reg[reg].tag = RR_ValExpr;
3217 ctxs->reg[reg].arg = j;
sewardjd69222c2006-04-08 16:22:53 +00003218 break;
sewardj5d616df2013-07-02 08:07:15 +00003219 }
sewardjd69222c2006-04-08 16:22:53 +00003220
sewardj5d616df2013-07-02 08:07:15 +00003221 case DW_CFA_def_cfa_expression: {
3222 DiCursor expr;
3223 len = step_leb128( &instr, 0 );
3224 expr = instr;
3225 instr = ML_(cur_plus)(instr, len);
sewardjb8b79ad2008-03-03 01:35:41 +00003226 if (di->ddump_frames)
sewardj7888e222007-02-28 13:03:27 +00003227 VG_(printf)(" DW_CFA_def_cfa_expression (");
3228 /* Convert the expression into a dag rooted at ctx->exprs index j,
3229 or fail. */
sewardj56908242015-04-30 11:45:13 +00003230 j = dwarfexpr_to_dag ( ctx, expr, len, False/*!push CFA at start*/,
sewardjb8b79ad2008-03-03 01:35:41 +00003231 di->ddump_frames);
3232 if (di->ddump_frames)
sewardj7888e222007-02-28 13:03:27 +00003233 VG_(printf)(")\n");
sewardjde1b03d2009-08-03 13:47:04 +00003234 ctxs->cfa_is_regoff = False;
3235 ctxs->cfa_reg = 0;
3236 ctxs->cfa_off = 0;
3237 ctxs->cfa_expr_ix = j;
sewardj1e601fe2005-05-16 11:48:34 +00003238 break;
sewardj5d616df2013-07-02 08:07:15 +00003239 }
sewardj1e601fe2005-05-16 11:48:34 +00003240
sewardj0cd71772005-05-16 18:25:09 +00003241 case DW_CFA_GNU_window_save:
3242 /* Ignored. This appears to be sparc-specific; quite why it
3243 turns up in SuSE-supplied x86 .so's beats me. */
sewardjb8b79ad2008-03-03 01:35:41 +00003244 if (di->ddump_frames)
sewardj3d026b12009-05-21 15:33:36 +00003245 VG_(printf)(" DW_CFA_GNU_window_save\n");
3246 break;
3247
3248 case DW_CFA_remember_state:
3249 if (di->ddump_frames)
3250 VG_(printf)(" DW_CFA_remember_state\n");
3251 /* we just checked this at entry, so: */
sewardjde1b03d2009-08-03 13:47:04 +00003252 vg_assert(ctx->state_sp >= 0 && ctx->state_sp < N_RR_STACK);
3253 ctx->state_sp++;
3254 if (ctx->state_sp == N_RR_STACK) {
sewardj3d026b12009-05-21 15:33:36 +00003255 /* stack overflow. We're hosed. */
3256 VG_(message)(Vg_DebugMsg, "DWARF2 CFI reader: N_RR_STACK is "
3257 "too low; increase and recompile.");
sewardj5d616df2013-07-02 08:07:15 +00003258 return 0; /* indicate failure */
sewardj3d026b12009-05-21 15:33:36 +00003259 } else {
sewardjde1b03d2009-08-03 13:47:04 +00003260 VG_(memcpy)(/*dst*/&ctx->state[ctx->state_sp],
3261 /*src*/&ctx->state[ctx->state_sp - 1],
3262 sizeof(ctx->state[ctx->state_sp]) );
sewardj3d026b12009-05-21 15:33:36 +00003263 }
3264 break;
3265
3266 case DW_CFA_restore_state:
3267 if (di->ddump_frames)
3268 VG_(printf)(" DW_CFA_restore_state\n");
3269 /* we just checked this at entry, so: */
sewardjde1b03d2009-08-03 13:47:04 +00003270 vg_assert(ctx->state_sp >= 0 && ctx->state_sp < N_RR_STACK);
3271 if (ctx->state_sp == 0) {
sewardj5d616df2013-07-02 08:07:15 +00003272 /* stack undefflow. Give up. */
3273 return 0; /* indicate failure */
sewardj3d026b12009-05-21 15:33:36 +00003274 } else {
3275 /* simply fall back to previous entry */
sewardjde1b03d2009-08-03 13:47:04 +00003276 ctx->state_sp--;
sewardj3d026b12009-05-21 15:33:36 +00003277 }
sewardj0cd71772005-05-16 18:25:09 +00003278 break;
3279
sewardj8eb8bab2015-07-21 14:44:28 +00003280 case DW_CFA_ORCL_arg_loc:
3281 if (di->ddump_frames)
3282 VG_(printf)(" DW_CFA_ORCL_arg_loc\n");
3283 break;
3284
sewardj5c638c22005-04-30 07:55:58 +00003285 default:
sewardj55022aa2005-05-03 16:05:00 +00003286 VG_(message)(Vg_DebugMsg, "DWARF2 CFI reader: unhandled CFI "
sewardj738856f2009-07-15 14:48:32 +00003287 "instruction 0:%d\n", (Int)lo6);
sewardjb8b79ad2008-03-03 01:35:41 +00003288 if (di->ddump_frames)
sewardj3646a492007-02-16 14:17:10 +00003289 VG_(printf)(" rci:run_CF_instruction:default\n");
sewardj5d616df2013-07-02 08:07:15 +00003290 return 0; /* failure */
3291 /*NOTREACHED*/
sewardj5c638c22005-04-30 07:55:58 +00003292 }
3293
sewardj5d616df2013-07-02 08:07:15 +00003294 return ML_(cur_minus)(instr, instrIN);
sewardj5c638c22005-04-30 07:55:58 +00003295}
3296
3297
sewardj3646a492007-02-16 14:17:10 +00003298/* Show a CFI instruction, and also return its length. Show it as
3299 close as possible (preferably identical) to how GNU binutils
3300 readelf --debug-dump=frames would. */
sewardj55022aa2005-05-03 16:05:00 +00003301
sewardj5d616df2013-07-02 08:07:15 +00003302static Int show_CF_instruction ( DiCursor instrIN,
florian518850b2014-10-22 22:25:30 +00003303 const AddressDecodingInfo* adi,
sewardj3646a492007-02-16 14:17:10 +00003304 Int code_a_f, Int data_a_f )
sewardj5c638c22005-04-30 07:55:58 +00003305{
sewardj5d616df2013-07-02 08:07:15 +00003306 Int off, coff, reg, reg2, len;
3307 UInt delta;
3308 Addr loc;
3309 DiCursor instr = instrIN;
3310 UChar instr_0 = ML_(cur_step_UChar)(&instr);
3311 UChar hi2 = (instr_0 >> 6) & 3;
3312 UChar lo6 = instr_0 & 0x3F;
sewardj5c638c22005-04-30 07:55:58 +00003313
sewardj5d616df2013-07-02 08:07:15 +00003314 if (0) {
3315 DiCursor tmpi = instrIN;
3316 UInt i_0 = ML_(cur_step_UChar)(&tmpi);
3317 UInt i_1 = ML_(cur_step_UChar)(&tmpi);
3318 UInt i_2 = ML_(cur_step_UChar)(&tmpi);
3319 UInt i_3 = ML_(cur_step_UChar)(&tmpi);
3320 UInt i_4 = ML_(cur_step_UChar)(&tmpi);
3321 UInt i_5 = ML_(cur_step_UChar)(&tmpi);
3322 UInt i_6 = ML_(cur_step_UChar)(&tmpi);
3323 UInt i_7 = ML_(cur_step_UChar)(&tmpi);
3324 VG_(printf)("raw:%x/%x:%x:%x:%x:%x:%x:%x:%x:%x\n",
3325 hi2, lo6, i_0, i_1, i_2, i_3, i_4, i_5, i_6, i_7);
3326 }
tom2fd38902005-05-01 15:14:01 +00003327
sewardj5c638c22005-04-30 07:55:58 +00003328 if (hi2 == DW_CFA_advance_loc) {
sewardj3646a492007-02-16 14:17:10 +00003329 VG_(printf)(" sci:DW_CFA_advance_loc(%d)\n", (Int)lo6);
sewardj5d616df2013-07-02 08:07:15 +00003330 return ML_(cur_minus)(instr, instrIN);
sewardj5c638c22005-04-30 07:55:58 +00003331 }
3332
3333 if (hi2 == DW_CFA_offset) {
sewardj5d616df2013-07-02 08:07:15 +00003334 off = step_leb128( &instr, 0 );
sewardj3646a492007-02-16 14:17:10 +00003335 coff = off * data_a_f;
3336 VG_(printf)(" DW_CFA_offset: r%d at cfa%s%d\n",
3337 (Int)lo6, coff < 0 ? "" : "+", (Int)coff );
sewardj5d616df2013-07-02 08:07:15 +00003338 return ML_(cur_minus)(instr, instrIN);
sewardj5c638c22005-04-30 07:55:58 +00003339 }
3340
3341 if (hi2 == DW_CFA_restore) {
sewardj3646a492007-02-16 14:17:10 +00003342 VG_(printf)(" sci:DW_CFA_restore(r%d)\n", (Int)lo6);
sewardj5d616df2013-07-02 08:07:15 +00003343 return ML_(cur_minus)(instr, instrIN);
sewardj5c638c22005-04-30 07:55:58 +00003344 }
3345
3346 vg_assert(hi2 == DW_CFA_use_secondary);
3347
3348 switch (lo6) {
3349
3350 case DW_CFA_nop:
sewardj3646a492007-02-16 14:17:10 +00003351 VG_(printf)(" DW_CFA_nop\n");
sewardj5c638c22005-04-30 07:55:58 +00003352 break;
3353
tom2fd38902005-05-01 15:14:01 +00003354 case DW_CFA_set_loc:
sewardjddf006d2007-02-24 23:29:31 +00003355 /* WAS: loc = read_Addr(&instr[i]); i+= sizeof(Addr);
3356 (now known to be incorrect -- the address is encoded) */
sewardj5d616df2013-07-02 08:07:15 +00003357 loc = step_encoded_Addr(adi, &instr);
barta0b6b2c2008-07-07 06:49:24 +00003358 VG_(printf)(" sci:DW_CFA_set_loc(%#lx)\n", loc);
tom2fd38902005-05-01 15:14:01 +00003359 break;
3360
sewardj5c638c22005-04-30 07:55:58 +00003361 case DW_CFA_advance_loc1:
sewardj5d616df2013-07-02 08:07:15 +00003362 delta = (UInt)ML_(cur_step_UChar)(&instr);
florianc6e5d762015-08-05 22:27:24 +00003363 VG_(printf)(" sci:DW_CFA_advance_loc1(%u)\n", delta);
sewardj5c638c22005-04-30 07:55:58 +00003364 break;
3365
tom2fd38902005-05-01 15:14:01 +00003366 case DW_CFA_advance_loc2:
sewardj5d616df2013-07-02 08:07:15 +00003367 delta = (UInt)ML_(cur_step_UShort)(&instr);
florianc6e5d762015-08-05 22:27:24 +00003368 VG_(printf)(" sci:DW_CFA_advance_loc2(%u)\n", delta);
tom2fd38902005-05-01 15:14:01 +00003369 break;
3370
3371 case DW_CFA_advance_loc4:
sewardj5d616df2013-07-02 08:07:15 +00003372 delta = (UInt)ML_(cur_step_UInt)(&instr);
florianc6e5d762015-08-05 22:27:24 +00003373 VG_(printf)(" DW_CFA_advance_loc4(%u)\n", delta);
tom2fd38902005-05-01 15:14:01 +00003374 break;
3375
sewardj5c638c22005-04-30 07:55:58 +00003376 case DW_CFA_def_cfa:
sewardj5d616df2013-07-02 08:07:15 +00003377 reg = step_leb128( &instr, 0 );
3378 off = step_leb128( &instr, 0 );
florianc6e5d762015-08-05 22:27:24 +00003379 VG_(printf)(" DW_CFA_def_cfa: r%d ofs %d\n", reg, off);
sewardj5c638c22005-04-30 07:55:58 +00003380 break;
3381
sewardjd69222c2006-04-08 16:22:53 +00003382 case DW_CFA_def_cfa_sf:
sewardj5d616df2013-07-02 08:07:15 +00003383 reg = step_leb128( &instr, 0 );
3384 off = step_leb128( &instr, 1 );
sewardj8c90d272007-02-16 19:20:28 +00003385 VG_(printf)(" DW_CFA_def_cfa_sf: r%d ofs %d\n",
florianc6e5d762015-08-05 22:27:24 +00003386 reg, off * data_a_f);
sewardjd69222c2006-04-08 16:22:53 +00003387 break;
3388
sewardje0707a62005-05-02 12:25:13 +00003389 case DW_CFA_register:
sewardj5d616df2013-07-02 08:07:15 +00003390 reg = step_leb128( &instr, 0);
3391 reg2 = step_leb128( &instr, 0);
sewardj3646a492007-02-16 14:17:10 +00003392 VG_(printf)(" sci:DW_CFA_register(r%d, r%d)\n", reg, reg2);
sewardje0707a62005-05-02 12:25:13 +00003393 break;
3394
sewardj5c638c22005-04-30 07:55:58 +00003395 case DW_CFA_def_cfa_register:
sewardj5d616df2013-07-02 08:07:15 +00003396 reg = step_leb128( &instr, 0);
sewardj3646a492007-02-16 14:17:10 +00003397 VG_(printf)(" sci:DW_CFA_def_cfa_register(r%d)\n", reg);
sewardj5c638c22005-04-30 07:55:58 +00003398 break;
3399
3400 case DW_CFA_def_cfa_offset:
sewardj5d616df2013-07-02 08:07:15 +00003401 off = step_leb128( &instr, 0);
sewardj3646a492007-02-16 14:17:10 +00003402 VG_(printf)(" sci:DW_CFA_def_cfa_offset(%d)\n", off);
sewardj5c638c22005-04-30 07:55:58 +00003403 break;
3404
sewardjd69222c2006-04-08 16:22:53 +00003405 case DW_CFA_def_cfa_offset_sf:
sewardj5d616df2013-07-02 08:07:15 +00003406 off = step_leb128( &instr, 1);
sewardj3646a492007-02-16 14:17:10 +00003407 VG_(printf)(" sci:DW_CFA_def_cfa_offset_sf(%d)\n", off);
sewardjd69222c2006-04-08 16:22:53 +00003408 break;
3409
3410 case DW_CFA_restore_extended:
sewardj5d616df2013-07-02 08:07:15 +00003411 reg = step_leb128( &instr, 0);
sewardj3646a492007-02-16 14:17:10 +00003412 VG_(printf)(" sci:DW_CFA_restore_extended(r%d)\n", reg);
sewardjd69222c2006-04-08 16:22:53 +00003413 break;
3414
3415 case DW_CFA_undefined:
sewardj5d616df2013-07-02 08:07:15 +00003416 reg = step_leb128( &instr, 0);
sewardj3646a492007-02-16 14:17:10 +00003417 VG_(printf)(" sci:DW_CFA_undefined(r%d)\n", reg);
sewardjd69222c2006-04-08 16:22:53 +00003418 break;
3419
3420 case DW_CFA_same_value:
sewardj5d616df2013-07-02 08:07:15 +00003421 reg = step_leb128( &instr, 0);
sewardj3646a492007-02-16 14:17:10 +00003422 VG_(printf)(" sci:DW_CFA_same_value(r%d)\n", reg);
sewardjd69222c2006-04-08 16:22:53 +00003423 break;
3424
3425 case DW_CFA_remember_state:
sewardj3646a492007-02-16 14:17:10 +00003426 VG_(printf)(" sci:DW_CFA_remember_state\n");
sewardjd69222c2006-04-08 16:22:53 +00003427 break;
3428
3429 case DW_CFA_restore_state:
sewardj3646a492007-02-16 14:17:10 +00003430 VG_(printf)(" sci:DW_CFA_restore_state\n");
sewardjd69222c2006-04-08 16:22:53 +00003431 break;
3432
sewardj5c638c22005-04-30 07:55:58 +00003433 case DW_CFA_GNU_args_size:
sewardj5d616df2013-07-02 08:07:15 +00003434 off = step_leb128( &instr, 0 );
sewardj3646a492007-02-16 14:17:10 +00003435 VG_(printf)(" sci:DW_CFA_GNU_args_size(%d)\n", off );
sewardj5c638c22005-04-30 07:55:58 +00003436 break;
3437
sewardj1e601fe2005-05-16 11:48:34 +00003438 case DW_CFA_def_cfa_expression:
sewardj5d616df2013-07-02 08:07:15 +00003439 len = step_leb128( &instr, 0 );
3440 instr = ML_(cur_plus)(instr, len);
sewardj3646a492007-02-16 14:17:10 +00003441 VG_(printf)(" sci:DW_CFA_def_cfa_expression(length %d)\n", len);
sewardj1e601fe2005-05-16 11:48:34 +00003442 break;
3443
3444 case DW_CFA_expression:
sewardj5d616df2013-07-02 08:07:15 +00003445 reg = step_leb128( &instr, 0 );
3446 len = step_leb128( &instr, 0 );
3447 instr = ML_(cur_plus)(instr, len);
sewardj3646a492007-02-16 14:17:10 +00003448 VG_(printf)(" sci:DW_CFA_expression(r%d, length %d)\n", reg, len);
sewardj1e601fe2005-05-16 11:48:34 +00003449 break;
3450
sewardjd69222c2006-04-08 16:22:53 +00003451 case DW_CFA_val_expression:
sewardj5d616df2013-07-02 08:07:15 +00003452 reg = step_leb128( &instr, 0 );
3453 len = step_leb128( &instr, 0 );
3454 instr = ML_(cur_plus)(instr, len);
sewardj3646a492007-02-16 14:17:10 +00003455 VG_(printf)(" sci:DW_CFA_val_expression(r%d, length %d)\n", reg, len);
sewardjd69222c2006-04-08 16:22:53 +00003456 break;
3457
3458 case DW_CFA_offset_extended:
sewardj5d616df2013-07-02 08:07:15 +00003459 reg = step_leb128( &instr, 0 );
3460 off = step_leb128( &instr, 0 );
sewardj3646a492007-02-16 14:17:10 +00003461 VG_(printf)(" sci:DW_CFA_offset_extended(r%d, "
3462 "off %d x data_af)\n", reg, off);
sewardjd69222c2006-04-08 16:22:53 +00003463 break;
3464
sewardjddf006d2007-02-24 23:29:31 +00003465 case DW_CFA_offset_extended_sf:
sewardj5d616df2013-07-02 08:07:15 +00003466 reg = step_leb128( &instr, 0 );
3467 off = step_leb128( &instr, 1 );
sewardjddf006d2007-02-24 23:29:31 +00003468 coff = (Int)(off * data_a_f);
3469 VG_(printf)(" DW_CFA_offset_extended_sf: r%d at cfa%s%d\n",
3470 reg, coff < 0 ? "" : "+", coff);
sewardjd69222c2006-04-08 16:22:53 +00003471 break;
3472
3473 case DW_CFA_GNU_negative_offset_extended:
sewardj5d616df2013-07-02 08:07:15 +00003474 reg = step_leb128( &instr, 0 );
3475 off = step_leb128( &instr, 0 );
sewardj3646a492007-02-16 14:17:10 +00003476 VG_(printf)(" sci:DW_CFA_GNU_negative_offset_extended"
3477 "(r%d, off %d x data_af)\n", reg, -off);
sewardjd69222c2006-04-08 16:22:53 +00003478 break;
3479
3480 case DW_CFA_val_offset:
sewardj5d616df2013-07-02 08:07:15 +00003481 reg = step_leb128( &instr, 0 );
3482 off = step_leb128( &instr, 0 );
sewardj3646a492007-02-16 14:17:10 +00003483 VG_(printf)(" sci:DW_CFA_val_offset(r%d, off %d x data_af)\n",
3484 reg, off);
sewardjd69222c2006-04-08 16:22:53 +00003485 break;
3486
3487 case DW_CFA_val_offset_sf:
sewardj5d616df2013-07-02 08:07:15 +00003488 reg = step_leb128( &instr, 0 );
3489 off = step_leb128( &instr, 1 );
sewardj3646a492007-02-16 14:17:10 +00003490 VG_(printf)(" sci:DW_CFA_val_offset_sf(r%d, off %d x data_af)\n",
3491 reg, off);
sewardjd69222c2006-04-08 16:22:53 +00003492 break;
3493
sewardj0cd71772005-05-16 18:25:09 +00003494 case DW_CFA_GNU_window_save:
sewardj3646a492007-02-16 14:17:10 +00003495 VG_(printf)(" sci:DW_CFA_GNU_window_save\n");
sewardj0cd71772005-05-16 18:25:09 +00003496 break;
3497
sewardj8eb8bab2015-07-21 14:44:28 +00003498 case DW_CFA_ORCL_arg_loc:
Elliott Hughesa0664b92017-04-18 17:46:52 -07003499 reg = step_leb128( &instr, 0 );
3500 len = step_leb128( &instr, 0 );
3501 VG_(printf)(" sci:DW_CFA_ORCL_arg_loc(%d, length %d)\n", reg, len);
sewardj8eb8bab2015-07-21 14:44:28 +00003502 break;
3503
sewardj5c638c22005-04-30 07:55:58 +00003504 default:
sewardj3646a492007-02-16 14:17:10 +00003505 VG_(printf)(" sci:0:%d\n", (Int)lo6);
sewardj5c638c22005-04-30 07:55:58 +00003506 break;
3507 }
3508
sewardj5d616df2013-07-02 08:07:15 +00003509 return ML_(cur_minus)(instr, instrIN);
sewardj5c638c22005-04-30 07:55:58 +00003510}
3511
3512
sewardj3646a492007-02-16 14:17:10 +00003513/* Show the instructions in instrs[0 .. ilen-1]. */
sewardj5d616df2013-07-02 08:07:15 +00003514static void show_CF_instructions ( DiCursor instrs, Int ilen,
florian518850b2014-10-22 22:25:30 +00003515 const AddressDecodingInfo* adi,
sewardj3646a492007-02-16 14:17:10 +00003516 Int code_a_f, Int data_a_f )
sewardj5c638c22005-04-30 07:55:58 +00003517{
3518 Int i = 0;
3519 while (True) {
3520 if (i >= ilen) break;
sewardj5d616df2013-07-02 08:07:15 +00003521 i += show_CF_instruction( ML_(cur_plus)(instrs, i),
3522 adi, code_a_f, data_a_f );
sewardj5c638c22005-04-30 07:55:58 +00003523 }
3524}
3525
sewardj3891dd42007-01-12 19:03:19 +00003526
sewardj5c638c22005-04-30 07:55:58 +00003527/* Run the CF instructions in instrs[0 .. ilen-1], until the end is
3528 reached, or until there is a failure. Return True iff success.
3529*/
3530static
florian518850b2014-10-22 22:25:30 +00003531Bool run_CF_instructions ( DebugInfo* di,
sewardj3646a492007-02-16 14:17:10 +00003532 Bool record,
sewardj5d616df2013-07-02 08:07:15 +00003533 UnwindContext* ctx, DiCursor instrs, Int ilen,
sewardj8eb41322005-05-01 23:50:08 +00003534 UWord fde_arange,
florian518850b2014-10-22 22:25:30 +00003535 const UnwindContext* restore_ctx,
3536 const AddressDecodingInfo* adi )
sewardj5c638c22005-04-30 07:55:58 +00003537{
philippe5c3dba22014-07-04 22:36:38 +00003538 Addr base;
3539 UInt len;
3540 DiCfSI_m cfsi_m;
sewardj3a7cb972005-05-02 00:34:19 +00003541 Bool summ_ok;
sewardj5c638c22005-04-30 07:55:58 +00003542 Int j, i = 0;
sewardj35165532005-04-30 18:47:48 +00003543 Addr loc_prev;
3544 if (0) ppUnwindContext(ctx);
tom2fd38902005-05-01 15:14:01 +00003545 if (0) ppUnwindContext_summary(ctx);
sewardj5c638c22005-04-30 07:55:58 +00003546 while (True) {
sewardj35165532005-04-30 18:47:48 +00003547 loc_prev = ctx->loc;
sewardj5c638c22005-04-30 07:55:58 +00003548 if (i >= ilen) break;
sewardj5d616df2013-07-02 08:07:15 +00003549 if (0) (void)show_CF_instruction( ML_(cur_plus)(instrs,i), adi,
sewardj3646a492007-02-16 14:17:10 +00003550 ctx->code_a_f, ctx->data_a_f );
sewardj5d616df2013-07-02 08:07:15 +00003551 j = run_CF_instruction( ctx, ML_(cur_plus)(instrs,i),
3552 restore_ctx, adi, di );
sewardj5c638c22005-04-30 07:55:58 +00003553 if (j == 0)
3554 return False; /* execution failed */
3555 i += j;
sewardj35165532005-04-30 18:47:48 +00003556 if (0) ppUnwindContext(ctx);
sewardj3646a492007-02-16 14:17:10 +00003557 if (record && loc_prev != ctx->loc) {
philippe5c3dba22014-07-04 22:36:38 +00003558 summ_ok = summarise_context ( &base, &len, &cfsi_m,
3559 loc_prev, ctx, di );
sewardj3a7cb972005-05-02 00:34:19 +00003560 if (summ_ok) {
philippe5c3dba22014-07-04 22:36:38 +00003561 ML_(addDiCfSI)(di, base, len, &cfsi_m);
sewardjb8b79ad2008-03-03 01:35:41 +00003562 if (di->trace_cfi)
philippe5c3dba22014-07-04 22:36:38 +00003563 ML_(ppDiCfSI)(di->cfsi_exprs, base, len, &cfsi_m);
sewardj3a7cb972005-05-02 00:34:19 +00003564 }
sewardj35165532005-04-30 18:47:48 +00003565 }
3566 }
3567 if (ctx->loc < fde_arange) {
3568 loc_prev = ctx->loc;
3569 ctx->loc = fde_arange;
sewardj3646a492007-02-16 14:17:10 +00003570 if (record) {
philippe5c3dba22014-07-04 22:36:38 +00003571 summ_ok = summarise_context ( &base, &len, &cfsi_m,
3572 loc_prev, ctx, di );
sewardj3a7cb972005-05-02 00:34:19 +00003573 if (summ_ok) {
philippe5c3dba22014-07-04 22:36:38 +00003574 ML_(addDiCfSI)(di, base, len, &cfsi_m);
sewardjb8b79ad2008-03-03 01:35:41 +00003575 if (di->trace_cfi)
philippe5c3dba22014-07-04 22:36:38 +00003576 ML_(ppDiCfSI)(di->cfsi_exprs, base, len, &cfsi_m);
sewardj3a7cb972005-05-02 00:34:19 +00003577 }
sewardj35165532005-04-30 18:47:48 +00003578 }
sewardj5c638c22005-04-30 07:55:58 +00003579 }
3580 return True;
3581}
3582
3583
sewardj55022aa2005-05-03 16:05:00 +00003584/* ------------ Main entry point for CFI reading ------------ */
3585
sewardj726baec2005-06-09 19:27:25 +00003586typedef
3587 struct {
3588 /* This gives the CIE an identity to which FDEs will refer. */
sewardj5d616df2013-07-02 08:07:15 +00003589 ULong offset;
sewardj726baec2005-06-09 19:27:25 +00003590 /* Code, data factors. */
sewardj5d616df2013-07-02 08:07:15 +00003591 Int code_a_f;
3592 Int data_a_f;
sewardj726baec2005-06-09 19:27:25 +00003593 /* Return-address pseudo-register. */
sewardj5d616df2013-07-02 08:07:15 +00003594 Int ra_reg;
3595 UChar address_encoding;
3596 /* Where are the instrs? */
3597 DiCursor instrs;
3598 Int ilen;
sewardj726baec2005-06-09 19:27:25 +00003599 /* God knows .. don't ask */
sewardj5d616df2013-07-02 08:07:15 +00003600 Bool saw_z_augmentation;
sewardj726baec2005-06-09 19:27:25 +00003601 }
3602 CIE;
3603
3604static void init_CIE ( CIE* cie )
3605{
3606 cie->offset = 0;
3607 cie->code_a_f = 0;
3608 cie->data_a_f = 0;
3609 cie->ra_reg = 0;
3610 cie->address_encoding = 0;
sewardj5d616df2013-07-02 08:07:15 +00003611 cie->instrs = DiCursor_INVALID;
sewardj726baec2005-06-09 19:27:25 +00003612 cie->ilen = 0;
3613 cie->saw_z_augmentation = False;
3614}
3615
florian5f9db7f2014-12-06 21:58:50 +00003616static CIE *the_CIEs = NULL;
3617static SizeT N_CIEs = 0;
sewardj726baec2005-06-09 19:27:25 +00003618
sewardj452e89a2011-05-30 10:18:59 +00003619/* Read, summarise and store CFA unwind info from .eh_frame and
3620 .debug_frame sections. is_ehframe tells us which kind we are
3621 dealing with -- they are slightly different. */
sewardj461d6c62007-02-23 10:10:02 +00003622void ML_(read_callframe_info_dwarf3)
sewardj452e89a2011-05-30 10:18:59 +00003623 ( /*OUT*/struct _DebugInfo* di,
sewardj5d616df2013-07-02 08:07:15 +00003624 DiSlice escn_frame, Addr frame_avma, Bool is_ehframe )
sewardj5c638c22005-04-30 07:55:58 +00003625{
florian6bd9dc12012-11-23 16:17:43 +00003626 const HChar* how = NULL;
sewardj5d616df2013-07-02 08:07:15 +00003627 Int n_CIEs = 0;
3628 DiCursor frame_image = ML_(cur_from_sli)(escn_frame); /* fixed */
3629 DiOffT frame_size = escn_frame.szB;
3630 DiCursor data = frame_image;
3631 UWord cfsi_used_orig;
sewardj452e89a2011-05-30 10:18:59 +00003632
3633 /* If we're dealing with a .debug_frame, assume zero frame_avma. */
3634 if (!is_ehframe)
3635 vg_assert(frame_avma == 0);
sewardj5c638c22005-04-30 07:55:58 +00003636
carllcae0cc22014-08-07 23:17:29 +00003637# if defined(VGP_ppc32_linux) || defined(VGP_ppc64be_linux) \
3638 || defined(VGP_ppc64le_linux)
tom3c9cf342009-11-12 13:28:34 +00003639 /* These targets don't use CFI-based stack unwinding. */
cerion85665ca2005-06-20 15:51:07 +00003640 return;
sewardj1936f8b2006-11-16 12:21:52 +00003641# endif
cerion85665ca2005-06-20 15:51:07 +00003642
sewardj452e89a2011-05-30 10:18:59 +00003643 /* If we read more than one .debug_frame or .eh_frame for this
3644 DebugInfo*, the second and subsequent reads should only add FDEs
3645 for address ranges not already covered by the FDEs already
3646 present. To be able to quickly check which address ranges are
3647 already present, any existing records (DiCFSIs) must be sorted,
3648 so we can binary-search them in the code below. We also record
3649 di->cfsi_used so that we know where the boundary is between
3650 existing and new records. */
3651 if (di->cfsi_used > 0) {
tom3c9cf342009-11-12 13:28:34 +00003652 ML_(canonicaliseCFI) ( di );
tom3c9cf342009-11-12 13:28:34 +00003653 }
sewardj452e89a2011-05-30 10:18:59 +00003654 cfsi_used_orig = di->cfsi_used;
tom3c9cf342009-11-12 13:28:34 +00003655
sewardjb8b79ad2008-03-03 01:35:41 +00003656 if (di->trace_cfi) {
sewardj325ec872005-05-01 20:24:06 +00003657 VG_(printf)("\n-----------------------------------------------\n");
florianc6e5d762015-08-05 22:27:24 +00003658 VG_(printf)("CFI info: szB %llu, _avma %#lx\n",
sewardj5d616df2013-07-02 08:07:15 +00003659 escn_frame.szB, frame_avma );
3660 VG_(printf)("CFI info: name %s\n", di->fsm.filename );
sewardj325ec872005-05-01 20:24:06 +00003661 }
3662
sewardj5c638c22005-04-30 07:55:58 +00003663 /* Loop over CIEs/FDEs */
3664
sewardj726baec2005-06-09 19:27:25 +00003665 /* Conceptually, the frame info is a sequence of FDEs, one for each
3666 function. Inside an FDE is a miniature program for a special
3667 state machine, which, when run, produces the stack-unwinding
3668 info for that function.
3669
3670 Because the FDEs typically have much in common, and because the
3671 DWARF designers appear to have been fanatical about space
3672 saving, the common parts are factored out into so-called CIEs.
3673 That means that what we traverse is a sequence of structs, each
3674 of which is either a FDE (usually) or a CIE (occasionally).
3675 Each FDE has a field indicating which CIE is the one pertaining
3676 to it.
3677
3678 The following loop traverses the sequence. FDEs are dealt with
3679 immediately; once we harvest the useful info in an FDE, it is
3680 then forgotten about. By contrast, CIEs are validated and
3681 dumped into an array, because later FDEs may refer to any
3682 previously-seen CIE.
3683 */
sewardj5c638c22005-04-30 07:55:58 +00003684 while (True) {
sewardj5d616df2013-07-02 08:07:15 +00003685 DiCursor ciefde_start;
3686 ULong ciefde_len;
3687 ULong cie_pointer;
3688 Bool dw64;
sewardj5c638c22005-04-30 07:55:58 +00003689
sewardj325ec872005-05-01 20:24:06 +00003690 /* Are we done? */
sewardj5d616df2013-07-02 08:07:15 +00003691 if (ML_(cur_cmpEQ)(data, ML_(cur_plus)(frame_image, frame_size)))
sewardj325ec872005-05-01 20:24:06 +00003692 return;
sewardj5c638c22005-04-30 07:55:58 +00003693
sewardj325ec872005-05-01 20:24:06 +00003694 /* Overshot the end? Means something is wrong */
sewardj5d616df2013-07-02 08:07:15 +00003695 if (ML_(cur_cmpGT)(data, ML_(cur_plus)(frame_image, frame_size))) {
sewardj325ec872005-05-01 20:24:06 +00003696 how = "overran the end of .eh_frame";
3697 goto bad;
3698 }
sewardj5c638c22005-04-30 07:55:58 +00003699
sewardj325ec872005-05-01 20:24:06 +00003700 /* Ok, we must be looking at the start of a new CIE or FDE.
3701 Figure out which it is. */
sewardj5c638c22005-04-30 07:55:58 +00003702
tom60a4b0b2005-10-12 10:45:27 +00003703 ciefde_start = data;
sewardjb8b79ad2008-03-03 01:35:41 +00003704 if (di->trace_cfi)
sewardj5d616df2013-07-02 08:07:15 +00003705 VG_(printf)("\ncie/fde.start = (frame_image + 0x%llx)\n",
florianc6e5d762015-08-05 22:27:24 +00003706 (ULong)ML_(cur_minus)(ciefde_start, frame_image));
sewardj5c638c22005-04-30 07:55:58 +00003707
sewardj5d616df2013-07-02 08:07:15 +00003708 ciefde_len = (ULong)ML_(cur_step_UInt)(&data);
sewardjb8b79ad2008-03-03 01:35:41 +00003709 if (di->trace_cfi)
florianc6e5d762015-08-05 22:27:24 +00003710 VG_(printf)("cie/fde.length = %llu\n", ciefde_len);
sewardj5c638c22005-04-30 07:55:58 +00003711
3712 /* Apparently, if the .length field is zero, we are at the end
sewardj461d6c62007-02-23 10:10:02 +00003713 of the sequence. This is stated in the Generic Elf
3714 Specification (see comments far above here) and is one of the
3715 places where .eh_frame and .debug_frame data differ. */
sewardj5c638c22005-04-30 07:55:58 +00003716 if (ciefde_len == 0) {
sewardjb8b79ad2008-03-03 01:35:41 +00003717 if (di->ddump_frames)
sewardj5d616df2013-07-02 08:07:15 +00003718 VG_(printf)("%08llx ZERO terminator\n\n",
florianc6e5d762015-08-05 22:27:24 +00003719 (ULong)ML_(cur_minus)(ciefde_start, frame_image));
sewardj461d6c62007-02-23 10:10:02 +00003720 return;
sewardj5c638c22005-04-30 07:55:58 +00003721 }
3722
sewardj461d6c62007-02-23 10:10:02 +00003723 /* If the .length field is 0xFFFFFFFF then we're dealing with
3724 64-bit DWARF, and the real length is stored as a 64-bit
3725 number immediately following it. */
3726 dw64 = False;
3727 if (ciefde_len == 0xFFFFFFFFUL) {
3728 dw64 = True;
sewardj5d616df2013-07-02 08:07:15 +00003729 ciefde_len = ML_(cur_step_ULong)(&data);
sewardj461d6c62007-02-23 10:10:02 +00003730 }
3731
3732 /* Now get the CIE ID, whose size depends on the DWARF 32 vs
3733 64-ness. */
3734 if (dw64) {
sewardj5d616df2013-07-02 08:07:15 +00003735 /* see XXX below */
3736 cie_pointer = ML_(cur_step_ULong)(&data);
sewardj461d6c62007-02-23 10:10:02 +00003737 } else {
sewardj5d616df2013-07-02 08:07:15 +00003738 /* see XXX below */
3739 cie_pointer = (ULong)ML_(cur_step_UInt)(&data);
sewardj461d6c62007-02-23 10:10:02 +00003740 }
3741
sewardjb8b79ad2008-03-03 01:35:41 +00003742 if (di->trace_cfi)
florianc6e5d762015-08-05 22:27:24 +00003743 VG_(printf)("cie.pointer = %llu\n", cie_pointer);
sewardj5c638c22005-04-30 07:55:58 +00003744
tom3c9cf342009-11-12 13:28:34 +00003745 /* If cie_pointer is zero for .eh_frame or all ones for .debug_frame,
3746 we've got a CIE; else it's an FDE. */
sewardj452e89a2011-05-30 10:18:59 +00003747 if (cie_pointer == (is_ehframe ? 0ULL
tom3c9cf342009-11-12 13:28:34 +00003748 : dw64 ? 0xFFFFFFFFFFFFFFFFULL : 0xFFFFFFFFULL)) {
sewardj5c638c22005-04-30 07:55:58 +00003749
sewardj5d616df2013-07-02 08:07:15 +00003750 Int this_CIE;
3751 UChar cie_version;
3752 DiCursor cie_augmentation;
sewardj5c638c22005-04-30 07:55:58 +00003753
3754 /* --------- CIE --------- */
sewardjb8b79ad2008-03-03 01:35:41 +00003755 if (di->trace_cfi)
florian5f9db7f2014-12-06 21:58:50 +00003756 VG_(printf)("------ new CIE #%d ------\n", n_CIEs);
sewardj726baec2005-06-09 19:27:25 +00003757
3758 /* Allocate a new CIE record. */
florian5f9db7f2014-12-06 21:58:50 +00003759 vg_assert(n_CIEs >= 0);
sewardj726baec2005-06-09 19:27:25 +00003760 if (n_CIEs == N_CIEs) {
florian5f9db7f2014-12-06 21:58:50 +00003761 N_CIEs += 1000;
3762 the_CIEs = ML_(dinfo_realloc)("di.rcid3.2", the_CIEs,
3763 N_CIEs * sizeof the_CIEs[0]);
sewardj726baec2005-06-09 19:27:25 +00003764 }
3765
3766 this_CIE = n_CIEs;
3767 n_CIEs++;
3768 init_CIE( &the_CIEs[this_CIE] );
3769
3770 /* Record its offset. This is how we will find it again
3771 later when looking at an FDE. */
sewardj5d616df2013-07-02 08:07:15 +00003772 the_CIEs[this_CIE].offset
3773 = (ULong)ML_(cur_minus)(ciefde_start, frame_image);
sewardj325ec872005-05-01 20:24:06 +00003774
sewardjb8b79ad2008-03-03 01:35:41 +00003775 if (di->ddump_frames)
sewardj3646a492007-02-16 14:17:10 +00003776 VG_(printf)("%08lx %08lx %08lx CIE\n",
sewardj5d616df2013-07-02 08:07:15 +00003777 (Addr)ML_(cur_minus)(ciefde_start, frame_image),
sewardj3646a492007-02-16 14:17:10 +00003778 (Addr)ciefde_len,
sewardj461d6c62007-02-23 10:10:02 +00003779 (Addr)(UWord)cie_pointer );
sewardj3646a492007-02-16 14:17:10 +00003780
sewardj5d616df2013-07-02 08:07:15 +00003781 cie_version = ML_(cur_step_UChar)(&data);
sewardjb8b79ad2008-03-03 01:35:41 +00003782 if (di->trace_cfi)
sewardj325ec872005-05-01 20:24:06 +00003783 VG_(printf)("cie.version = %d\n", (Int)cie_version);
sewardjb8b79ad2008-03-03 01:35:41 +00003784 if (di->ddump_frames)
sewardj3646a492007-02-16 14:17:10 +00003785 VG_(printf)(" Version: %d\n", (Int)cie_version);
tomfba428c2010-04-28 08:09:30 +00003786 if (cie_version != 1 && cie_version != 3 && cie_version != 4) {
3787 how = "unexpected CIE version (not 1 nor 3 nor 4)";
sewardj325ec872005-05-01 20:24:06 +00003788 goto bad;
3789 }
sewardj5c638c22005-04-30 07:55:58 +00003790
tom60a4b0b2005-10-12 10:45:27 +00003791 cie_augmentation = data;
sewardj5d616df2013-07-02 08:07:15 +00003792 data = ML_(cur_plus)(data, 1 + ML_(cur_strlen)(cie_augmentation));
sewardj5c638c22005-04-30 07:55:58 +00003793
sewardj5d616df2013-07-02 08:07:15 +00003794 if (di->trace_cfi || di->ddump_frames) {
3795 HChar* str = ML_(cur_read_strdup)(cie_augmentation, "di.rcid3.1");
3796 if (di->trace_cfi)
3797 VG_(printf)("cie.augment = \"%s\"\n", str);
3798 if (di->ddump_frames)
3799 VG_(printf)(" Augmentation: \"%s\"\n", str);
3800 ML_(dinfo_free)(str);
3801 }
3802
3803 if (ML_(cur_read_UChar)(cie_augmentation) == 'e'
3804 && ML_(cur_read_UChar)
3805 (ML_(cur_plus)(cie_augmentation, 1)) == 'h') {
3806 data = ML_(cur_plus)(data, sizeof(Addr));
3807 cie_augmentation = ML_(cur_plus)(cie_augmentation, 2);
sewardj5c638c22005-04-30 07:55:58 +00003808 }
3809
tomfba428c2010-04-28 08:09:30 +00003810 if (cie_version >= 4) {
sewardj5d616df2013-07-02 08:07:15 +00003811 if (ML_(cur_step_UChar)(&data) != sizeof(Addr)) {
tomfba428c2010-04-28 08:09:30 +00003812 how = "unexpected address size";
3813 goto bad;
3814 }
sewardj5d616df2013-07-02 08:07:15 +00003815 if (ML_(cur_step_UChar)(&data) != 0) {
tomfba428c2010-04-28 08:09:30 +00003816 how = "unexpected non-zero segment size";
3817 goto bad;
3818 }
tomfba428c2010-04-28 08:09:30 +00003819 }
3820
sewardj5d616df2013-07-02 08:07:15 +00003821 the_CIEs[this_CIE].code_a_f = step_leb128( &data, 0);
sewardjb8b79ad2008-03-03 01:35:41 +00003822 if (di->trace_cfi)
sewardj726baec2005-06-09 19:27:25 +00003823 VG_(printf)("cie.code_af = %d\n",
3824 the_CIEs[this_CIE].code_a_f);
sewardjb8b79ad2008-03-03 01:35:41 +00003825 if (di->ddump_frames)
sewardj3646a492007-02-16 14:17:10 +00003826 VG_(printf)(" Code alignment factor: %d\n",
3827 (Int)the_CIEs[this_CIE].code_a_f);
sewardj5c638c22005-04-30 07:55:58 +00003828
sewardj5d616df2013-07-02 08:07:15 +00003829 the_CIEs[this_CIE].data_a_f = step_leb128( &data, 1);
sewardjb8b79ad2008-03-03 01:35:41 +00003830 if (di->trace_cfi)
sewardj726baec2005-06-09 19:27:25 +00003831 VG_(printf)("cie.data_af = %d\n",
3832 the_CIEs[this_CIE].data_a_f);
sewardjb8b79ad2008-03-03 01:35:41 +00003833 if (di->ddump_frames)
sewardj3646a492007-02-16 14:17:10 +00003834 VG_(printf)(" Data alignment factor: %d\n",
3835 (Int)the_CIEs[this_CIE].data_a_f);
sewardj5c638c22005-04-30 07:55:58 +00003836
tom3c9cf342009-11-12 13:28:34 +00003837 if (cie_version == 1) {
sewardj5d616df2013-07-02 08:07:15 +00003838 the_CIEs[this_CIE].ra_reg = (Int)ML_(cur_step_UChar)(&data);
tom3c9cf342009-11-12 13:28:34 +00003839 } else {
sewardj5d616df2013-07-02 08:07:15 +00003840 the_CIEs[this_CIE].ra_reg = step_leb128( &data, 0);
tom3c9cf342009-11-12 13:28:34 +00003841 }
sewardjb8b79ad2008-03-03 01:35:41 +00003842 if (di->trace_cfi)
sewardj726baec2005-06-09 19:27:25 +00003843 VG_(printf)("cie.ra_reg = %d\n",
3844 the_CIEs[this_CIE].ra_reg);
sewardjb8b79ad2008-03-03 01:35:41 +00003845 if (di->ddump_frames)
sewardj3646a492007-02-16 14:17:10 +00003846 VG_(printf)(" Return address column: %d\n",
3847 (Int)the_CIEs[this_CIE].ra_reg);
3848
sewardj726baec2005-06-09 19:27:25 +00003849 if (the_CIEs[this_CIE].ra_reg < 0
3850 || the_CIEs[this_CIE].ra_reg >= N_CFI_REGS) {
sewardj5410cfd2005-05-13 12:17:33 +00003851 how = "cie.ra_reg has implausible value";
sewardj55022aa2005-05-03 16:05:00 +00003852 goto bad;
3853 }
sewardj5c638c22005-04-30 07:55:58 +00003854
sewardj726baec2005-06-09 19:27:25 +00003855 the_CIEs[this_CIE].saw_z_augmentation
sewardj5d616df2013-07-02 08:07:15 +00003856 = ML_(cur_read_UChar)(cie_augmentation) == 'z';
sewardj726baec2005-06-09 19:27:25 +00003857 if (the_CIEs[this_CIE].saw_z_augmentation) {
sewardj5d616df2013-07-02 08:07:15 +00003858 UInt length = step_leb128( &data, 0);
3859 the_CIEs[this_CIE].instrs = ML_(cur_plus)(data, length);
3860 cie_augmentation = ML_(cur_plus)(cie_augmentation, 1);
sewardjb8b79ad2008-03-03 01:35:41 +00003861 if (di->ddump_frames) {
sewardj3646a492007-02-16 14:17:10 +00003862 UInt i;
sewardj687bbf62007-02-16 20:11:27 +00003863 VG_(printf)(" Augmentation data: ");
sewardj3646a492007-02-16 14:17:10 +00003864 for (i = 0; i < length; i++)
sewardj5d616df2013-07-02 08:07:15 +00003865 VG_(printf)(" %02x", (UInt)ML_(cur_read_UChar)
3866 (ML_(cur_plus)(data, i)));
sewardj3646a492007-02-16 14:17:10 +00003867 VG_(printf)("\n");
3868 }
tom2fd38902005-05-01 15:14:01 +00003869 } else {
sewardj5d616df2013-07-02 08:07:15 +00003870 the_CIEs[this_CIE].instrs = DiCursor_INVALID;
tom2fd38902005-05-01 15:14:01 +00003871 }
3872
sewardj726baec2005-06-09 19:27:25 +00003873 the_CIEs[this_CIE].address_encoding = default_Addr_encoding();
tomf04fd622005-05-03 09:30:04 +00003874
sewardj5d616df2013-07-02 08:07:15 +00003875 while (ML_(cur_read_UChar)(cie_augmentation)) {
3876 switch (ML_(cur_read_UChar)(cie_augmentation)) {
tom2fd38902005-05-01 15:14:01 +00003877 case 'L':
sewardj5d616df2013-07-02 08:07:15 +00003878 data = ML_(cur_plus)(data, 1);
3879 cie_augmentation = ML_(cur_plus)(cie_augmentation, 1);
tom2fd38902005-05-01 15:14:01 +00003880 break;
3881 case 'R':
sewardj726baec2005-06-09 19:27:25 +00003882 the_CIEs[this_CIE].address_encoding
sewardj5d616df2013-07-02 08:07:15 +00003883 = ML_(cur_step_UChar)(&data);
3884 cie_augmentation = ML_(cur_plus)(cie_augmentation, 1);
tom2fd38902005-05-01 15:14:01 +00003885 break;
3886 case 'P':
sewardj5d616df2013-07-02 08:07:15 +00003887 data = ML_(cur_plus)(data, size_of_encoded_Addr(
3888 ML_(cur_read_UChar)(data) ));
3889 data = ML_(cur_plus)(data, 1);
3890 cie_augmentation = ML_(cur_plus)(cie_augmentation, 1);
tom2fd38902005-05-01 15:14:01 +00003891 break;
sewardjd69222c2006-04-08 16:22:53 +00003892 case 'S':
sewardj5d616df2013-07-02 08:07:15 +00003893 cie_augmentation = ML_(cur_plus)(cie_augmentation, 1);
sewardjd69222c2006-04-08 16:22:53 +00003894 break;
tom2fd38902005-05-01 15:14:01 +00003895 default:
sewardj5d616df2013-07-02 08:07:15 +00003896 if (!ML_(cur_is_valid)(the_CIEs[this_CIE].instrs)) {
tom2fd38902005-05-01 15:14:01 +00003897 how = "unhandled cie.augmentation";
3898 goto bad;
3899 }
sewardj726baec2005-06-09 19:27:25 +00003900 data = the_CIEs[this_CIE].instrs;
tom2fd38902005-05-01 15:14:01 +00003901 goto done_augmentation;
3902 }
3903 }
3904
3905 done_augmentation:
3906
sewardjb8b79ad2008-03-03 01:35:41 +00003907 if (di->trace_cfi)
sewardj726baec2005-06-09 19:27:25 +00003908 VG_(printf)("cie.encoding = 0x%x\n",
3909 the_CIEs[this_CIE].address_encoding);
tom2fd38902005-05-01 15:14:01 +00003910
sewardj726baec2005-06-09 19:27:25 +00003911 the_CIEs[this_CIE].instrs = data;
sewardj5d616df2013-07-02 08:07:15 +00003912 the_CIEs[this_CIE].ilen = ML_(cur_minus)(ciefde_start, data)
3913 + (Long)ciefde_len + (Long)sizeof(UInt);
sewardjb8b79ad2008-03-03 01:35:41 +00003914 if (di->trace_cfi) {
sewardj5d616df2013-07-02 08:07:15 +00003915 //VG_(printf)("cie.instrs = %p\n", the_CIEs[this_CIE].instrs);
sewardj726baec2005-06-09 19:27:25 +00003916 VG_(printf)("cie.ilen = %d\n", the_CIEs[this_CIE].ilen);
sewardj325ec872005-05-01 20:24:06 +00003917 }
sewardj5c638c22005-04-30 07:55:58 +00003918
sewardj726baec2005-06-09 19:27:25 +00003919 if (the_CIEs[this_CIE].ilen < 0
tom3c9cf342009-11-12 13:28:34 +00003920 || the_CIEs[this_CIE].ilen > frame_size) {
sewardj5c638c22005-04-30 07:55:58 +00003921 how = "implausible # cie initial insns";
3922 goto bad;
3923 }
3924
sewardj5d616df2013-07-02 08:07:15 +00003925 data = ML_(cur_plus)(data, the_CIEs[this_CIE].ilen);
sewardj5c638c22005-04-30 07:55:58 +00003926
sewardj3646a492007-02-16 14:17:10 +00003927 /* Show the CIE's instructions (the preamble for each FDE
3928 that uses this CIE). */
sewardjb8b79ad2008-03-03 01:35:41 +00003929 if (di->ddump_frames)
sewardj3646a492007-02-16 14:17:10 +00003930 VG_(printf)("\n");
3931
sewardjb8b79ad2008-03-03 01:35:41 +00003932 if (di->trace_cfi || di->ddump_frames) {
sewardj1936f8b2006-11-16 12:21:52 +00003933 AddressDecodingInfo adi;
sewardjc6d3f6f2007-01-11 19:42:11 +00003934 adi.encoding = the_CIEs[this_CIE].address_encoding;
tom3c9cf342009-11-12 13:28:34 +00003935 adi.ehframe_image = frame_image;
3936 adi.ehframe_avma = frame_avma;
tom402c9ee2009-03-09 09:19:03 +00003937 adi.text_bias = di->text_debug_bias;
sewardj8eb8bab2015-07-21 14:44:28 +00003938 adi.got_avma = di->got_avma;
sewardj3646a492007-02-16 14:17:10 +00003939 show_CF_instructions( the_CIEs[this_CIE].instrs,
3940 the_CIEs[this_CIE].ilen, &adi,
3941 the_CIEs[this_CIE].code_a_f,
3942 the_CIEs[this_CIE].data_a_f );
sewardj1936f8b2006-11-16 12:21:52 +00003943 }
sewardj5c638c22005-04-30 07:55:58 +00003944
sewardjb8b79ad2008-03-03 01:35:41 +00003945 if (di->ddump_frames)
sewardj3646a492007-02-16 14:17:10 +00003946 VG_(printf)("\n");
3947
sewardj5c638c22005-04-30 07:55:58 +00003948 } else {
3949
sewardj1936f8b2006-11-16 12:21:52 +00003950 AddressDecodingInfo adi;
sewardj726baec2005-06-09 19:27:25 +00003951 UnwindContext ctx, restore_ctx;
sewardj5d616df2013-07-02 08:07:15 +00003952 Int cie;
3953 ULong look_for;
3954 Bool ok;
3955 Addr fde_initloc;
3956 UWord fde_arange;
3957 DiCursor fde_instrs;
3958 Int fde_ilen;
sewardj726baec2005-06-09 19:27:25 +00003959
sewardj5c638c22005-04-30 07:55:58 +00003960 /* --------- FDE --------- */
3961
sewardj726baec2005-06-09 19:27:25 +00003962 /* Find the relevant CIE. The CIE we want is located
3963 cie_pointer bytes back from here. */
3964
sewardj461d6c62007-02-23 10:10:02 +00003965 /* re sizeof(UInt) / sizeof(ULong), matches XXX above. */
sewardj452e89a2011-05-30 10:18:59 +00003966 if (is_ehframe)
sewardj5d616df2013-07-02 08:07:15 +00003967 look_for = ML_(cur_minus)(data, frame_image)
3968 - (dw64 ? sizeof(ULong) : sizeof(UInt))
tom3c9cf342009-11-12 13:28:34 +00003969 - cie_pointer;
3970 else
3971 look_for = cie_pointer;
sewardj726baec2005-06-09 19:27:25 +00003972
3973 for (cie = 0; cie < n_CIEs; cie++) {
florianc6e5d762015-08-05 22:27:24 +00003974 if (0) VG_(printf)("look for %llu %llu\n",
sewardj726baec2005-06-09 19:27:25 +00003975 look_for, the_CIEs[cie].offset );
3976 if (the_CIEs[cie].offset == look_for)
3977 break;
3978 }
3979 vg_assert(cie >= 0 && cie <= n_CIEs);
3980 if (cie == n_CIEs) {
3981 how = "FDE refers to not-findable CIE";
sewardj35165532005-04-30 18:47:48 +00003982 goto bad;
sewardj726baec2005-06-09 19:27:25 +00003983 }
sewardj5c638c22005-04-30 07:55:58 +00003984
sewardjc6d3f6f2007-01-11 19:42:11 +00003985 adi.encoding = the_CIEs[cie].address_encoding;
tom3c9cf342009-11-12 13:28:34 +00003986 adi.ehframe_image = frame_image;
3987 adi.ehframe_avma = frame_avma;
tom402c9ee2009-03-09 09:19:03 +00003988 adi.text_bias = di->text_debug_bias;
sewardj8eb8bab2015-07-21 14:44:28 +00003989 adi.got_avma = di->got_avma;
sewardj5d616df2013-07-02 08:07:15 +00003990 fde_initloc = step_encoded_Addr(&adi, &data);
sewardjb8b79ad2008-03-03 01:35:41 +00003991 if (di->trace_cfi)
barta0b6b2c2008-07-07 06:49:24 +00003992 VG_(printf)("fde.initloc = %#lx\n", fde_initloc);
sewardj5c638c22005-04-30 07:55:58 +00003993
sewardjc6d3f6f2007-01-11 19:42:11 +00003994 adi.encoding = the_CIEs[cie].address_encoding & 0xf;
tom3c9cf342009-11-12 13:28:34 +00003995 adi.ehframe_image = frame_image;
3996 adi.ehframe_avma = frame_avma;
tom402c9ee2009-03-09 09:19:03 +00003997 adi.text_bias = di->text_debug_bias;
sewardj8eb8bab2015-07-21 14:44:28 +00003998 adi.got_avma = di->got_avma;
sewardjddf006d2007-02-24 23:29:31 +00003999
4000 /* WAS (incorrectly):
4001 fde_arange = read_encoded_Addr(&nbytes, &adi, data);
4002 data += nbytes;
4003 The following corresponds to what binutils/dwarf.c does:
4004 */
4005 { UInt ptr_size = size_of_encoded_Addr( adi.encoding );
4006 switch (ptr_size) {
4007 case 8: case 4: case 2: case 1:
4008 fde_arange
sewardj5d616df2013-07-02 08:07:15 +00004009 = (UWord)step_le_u_encoded_literal(&data, ptr_size);
sewardjddf006d2007-02-24 23:29:31 +00004010 break;
4011 default:
4012 how = "unknown arange field encoding in FDE";
4013 goto bad;
4014 }
4015 }
4016
sewardjb8b79ad2008-03-03 01:35:41 +00004017 if (di->trace_cfi)
barta0b6b2c2008-07-07 06:49:24 +00004018 VG_(printf)("fde.arangec = %#lx\n", fde_arange);
sewardj5c638c22005-04-30 07:55:58 +00004019
sewardjb8b79ad2008-03-03 01:35:41 +00004020 if (di->ddump_frames)
sewardj3646a492007-02-16 14:17:10 +00004021 VG_(printf)("%08lx %08lx %08lx FDE cie=%08lx pc=%08lx..%08lx\n",
sewardj5d616df2013-07-02 08:07:15 +00004022 (Addr)ML_(cur_minus)(ciefde_start, frame_image),
sewardj3646a492007-02-16 14:17:10 +00004023 (Addr)ciefde_len,
sewardj461d6c62007-02-23 10:10:02 +00004024 (Addr)(UWord)cie_pointer,
sewardj3646a492007-02-16 14:17:10 +00004025 (Addr)look_for,
tom402c9ee2009-03-09 09:19:03 +00004026 ((Addr)fde_initloc) - di->text_debug_bias,
4027 ((Addr)fde_initloc) - di->text_debug_bias + fde_arange);
sewardj3646a492007-02-16 14:17:10 +00004028
sewardj726baec2005-06-09 19:27:25 +00004029 if (the_CIEs[cie].saw_z_augmentation) {
sewardj5d616df2013-07-02 08:07:15 +00004030 UInt length = step_leb128( &data, 0);
sewardjb8b79ad2008-03-03 01:35:41 +00004031 if (di->ddump_frames && (length > 0)) {
sewardj687bbf62007-02-16 20:11:27 +00004032 UInt i;
4033 VG_(printf)(" Augmentation data: ");
4034 for (i = 0; i < length; i++)
sewardj5d616df2013-07-02 08:07:15 +00004035 VG_(printf)(" %02x", (UInt)ML_(cur_read_UChar)
4036 (ML_(cur_plus)(data, i)));
sewardj687bbf62007-02-16 20:11:27 +00004037 VG_(printf)("\n\n");
4038 }
sewardj5d616df2013-07-02 08:07:15 +00004039 data = ML_(cur_plus)(data, length);
tom2fd38902005-05-01 15:14:01 +00004040 }
4041
tom60a4b0b2005-10-12 10:45:27 +00004042 fde_instrs = data;
sewardj5d616df2013-07-02 08:07:15 +00004043 fde_ilen = ML_(cur_minus)(ciefde_start, data)
4044 + (Long)ciefde_len + (Long)sizeof(UInt);
sewardjb8b79ad2008-03-03 01:35:41 +00004045 if (di->trace_cfi) {
sewardj5d616df2013-07-02 08:07:15 +00004046 //VG_(printf)("fde.instrs = %p\n", fde_instrs);
sewardj8eb41322005-05-01 23:50:08 +00004047 VG_(printf)("fde.ilen = %d\n", (Int)fde_ilen);
4048 }
sewardj5c638c22005-04-30 07:55:58 +00004049
tom3c9cf342009-11-12 13:28:34 +00004050 if (fde_ilen < 0 || fde_ilen > frame_size) {
sewardj325ec872005-05-01 20:24:06 +00004051 how = "implausible # fde insns";
sewardj5c638c22005-04-30 07:55:58 +00004052 goto bad;
4053 }
4054
sewardj5d616df2013-07-02 08:07:15 +00004055 data = ML_(cur_plus)(data, fde_ilen);
sewardj5c638c22005-04-30 07:55:58 +00004056
sewardj452e89a2011-05-30 10:18:59 +00004057 /* If this object's DebugInfo* had some DiCFSIs from a
4058 previous .eh_frame or .debug_frame read, we must check
4059 that we're not adding a duplicate. */
4060 if (cfsi_used_orig > 0) {
tom3c9cf342009-11-12 13:28:34 +00004061 Addr a_mid_lo, a_mid_hi;
4062 Word mid, size,
4063 lo = 0,
sewardj452e89a2011-05-30 10:18:59 +00004064 hi = cfsi_used_orig-1;
tom3c9cf342009-11-12 13:28:34 +00004065 while (True) {
4066 /* current unsearched space is from lo to hi, inclusive. */
4067 if (lo > hi) break; /* not found */
4068 mid = (lo + hi) / 2;
philippe5c3dba22014-07-04 22:36:38 +00004069 a_mid_lo = di->cfsi_rd[mid].base;
4070 size = di->cfsi_rd[mid].len;
tom3c9cf342009-11-12 13:28:34 +00004071 a_mid_hi = a_mid_lo + size - 1;
4072 vg_assert(a_mid_hi >= a_mid_lo);
4073 if (fde_initloc + fde_arange <= a_mid_lo) {
4074 hi = mid-1; continue;
4075 }
4076 if (fde_initloc > a_mid_hi) { lo = mid+1; continue; }
4077 break;
4078 }
4079
4080 /* The range this .debug_frame FDE covers has been already
4081 covered in .eh_frame section. Don't add it from .debug_frame
4082 section again. */
4083 if (lo <= hi)
4084 continue;
4085 }
4086
sewardjc6d3f6f2007-01-11 19:42:11 +00004087 adi.encoding = the_CIEs[cie].address_encoding;
tom3c9cf342009-11-12 13:28:34 +00004088 adi.ehframe_image = frame_image;
4089 adi.ehframe_avma = frame_avma;
tom402c9ee2009-03-09 09:19:03 +00004090 adi.text_bias = di->text_debug_bias;
sewardj8eb8bab2015-07-21 14:44:28 +00004091 adi.got_avma = di->got_avma;
sewardj1936f8b2006-11-16 12:21:52 +00004092
sewardjb8b79ad2008-03-03 01:35:41 +00004093 if (di->trace_cfi)
sewardj3646a492007-02-16 14:17:10 +00004094 show_CF_instructions( fde_instrs, fde_ilen, &adi,
4095 the_CIEs[cie].code_a_f,
4096 the_CIEs[cie].data_a_f );
sewardj325ec872005-05-01 20:24:06 +00004097
sewardj5c638c22005-04-30 07:55:58 +00004098 initUnwindContext(&ctx);
sewardj726baec2005-06-09 19:27:25 +00004099 ctx.code_a_f = the_CIEs[cie].code_a_f;
4100 ctx.data_a_f = the_CIEs[cie].data_a_f;
sewardj35165532005-04-30 18:47:48 +00004101 ctx.initloc = fde_initloc;
sewardj726baec2005-06-09 19:27:25 +00004102 ctx.ra_reg = the_CIEs[cie].ra_reg;
sewardj9c606bd2008-09-18 18:12:50 +00004103 ctx.exprs = VG_(newXA)( ML_(dinfo_zalloc), "di.rcid.1",
4104 ML_(dinfo_free),
sewardj72427fa2007-02-27 16:52:23 +00004105 sizeof(CfiExpr) );
sewardj8eb41322005-05-01 23:50:08 +00004106
sewardj3646a492007-02-16 14:17:10 +00004107 /* Run the CIE's instructions. Ugly hack: if
4108 --debug-dump=frames is in effect, suppress output for
4109 these instructions since they will already have been shown
4110 at the time the CIE was first encountered. Note, not
4111 thread safe - if this reader is ever made threaded, should
4112 fix properly. */
sewardjb8b79ad2008-03-03 01:35:41 +00004113 { Bool hack = di->ddump_frames;
4114 di->ddump_frames = False;
sewardj3646a492007-02-16 14:17:10 +00004115 initUnwindContext(&restore_ctx);
4116 ok = run_CF_instructions(
sewardjb8b79ad2008-03-03 01:35:41 +00004117 di, False, &ctx, the_CIEs[cie].instrs,
sewardj3646a492007-02-16 14:17:10 +00004118 the_CIEs[cie].ilen, 0, NULL, &adi
4119 );
sewardjb8b79ad2008-03-03 01:35:41 +00004120 di->ddump_frames = hack;
sewardj3646a492007-02-16 14:17:10 +00004121 }
4122 /* And now run the instructions for the FDE, starting from
4123 the state created by running the CIE preamble
4124 instructions. */
sewardj8eb41322005-05-01 23:50:08 +00004125 if (ok) {
4126 restore_ctx = ctx;
4127 ok = run_CF_instructions(
sewardjb8b79ad2008-03-03 01:35:41 +00004128 di, True, &ctx, fde_instrs, fde_ilen, fde_arange,
sewardj1936f8b2006-11-16 12:21:52 +00004129 &restore_ctx, &adi
4130 );
sewardjb8b79ad2008-03-03 01:35:41 +00004131 if (di->ddump_frames)
sewardj3646a492007-02-16 14:17:10 +00004132 VG_(printf)("\n");
sewardj8eb41322005-05-01 23:50:08 +00004133 }
sewardj72427fa2007-02-27 16:52:23 +00004134
4135 VG_(deleteXA)( ctx.exprs );
sewardj5c638c22005-04-30 07:55:58 +00004136 }
4137 }
4138
sewardj5c638c22005-04-30 07:55:58 +00004139 return;
4140
4141 bad:
sewardjcbd2f032005-08-01 14:12:17 +00004142 if (!VG_(clo_xml) && VG_(clo_verbosity) > 1)
sewardj738856f2009-07-15 14:48:32 +00004143 VG_(message)(Vg_UserMsg,
4144 "Warning: %s in DWARF2 CFI reading\n", how);
sewardj5c638c22005-04-30 07:55:58 +00004145 return;
4146}
4147
sewardj8eb8bab2015-07-21 14:44:28 +00004148#endif // defined(VGO_linux) || defined(VGO_darwin) || defined(VGO_solaris)
sewardj5c638c22005-04-30 07:55:58 +00004149
njn4bbdc972003-10-16 10:10:55 +00004150/*--------------------------------------------------------------------*/
njnea27e462005-05-31 02:38:09 +00004151/*--- end ---*/
njn4bbdc972003-10-16 10:10:55 +00004152/*--------------------------------------------------------------------*/