blob: 1036856532137fe3bb578e163a17b6c2d882d49d [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
sewardj0f157dd2013-10-18 14:27:36 +000011 Copyright (C) 2000-2013 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
32#if defined(VGO_linux) || defined(VGO_darwin)
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
57/*------------------------------------------------------------*/
58/*--- Expanding arrays of words, for holding file name and ---*/
59/*--- directory name arrays. ---*/
60/*------------------------------------------------------------*/
61
62typedef
63 struct {
64 Word* tab;
65 UInt tab_size;
66 UInt tab_used;
67 }
68 WordArray;
69
70static void init_WordArray ( WordArray* wa )
71{
72 wa->tab = NULL;
73 wa->tab_size = 0;
74 wa->tab_used = 0;
75}
76
77static void free_WordArray ( WordArray* wa )
78{
79 if (wa->tab) {
80 vg_assert(wa->tab_size > 0);
sewardjb8b79ad2008-03-03 01:35:41 +000081 ML_(dinfo_free)(wa->tab);
sewardjc613dff2005-06-13 17:33:27 +000082 }
83 init_WordArray(wa);
84}
85
86static void addto_WordArray ( WordArray* wa, Word w )
87{
88 UInt new_size, i;
89 Word* new_tab;
90
91 if (0) VG_(printf)("<<ADD %p (new sz = %d) >>\n",
92 (HChar*)w, wa->tab_used+1);
93
94 if (wa->tab_used < wa->tab_size) {
95 /* fine */
96 } else {
97 /* expand array */
98 if (0) VG_(printf)("EXPAND ARRAY from %d\n", wa->tab_size);
99 vg_assert(wa->tab_used == wa->tab_size);
100 vg_assert( (wa->tab_size == 0 && wa->tab == NULL)
101 || (wa->tab_size != 0 && wa->tab != NULL) );
102 new_size = wa->tab_size == 0 ? 8 : 2 * wa->tab_size;
sewardj9c606bd2008-09-18 18:12:50 +0000103 new_tab = ML_(dinfo_zalloc)("di.aWA.1", new_size * sizeof(Word));
sewardjc613dff2005-06-13 17:33:27 +0000104 vg_assert(new_tab != NULL);
105 for (i = 0; i < wa->tab_used; i++)
106 new_tab[i] = wa->tab[i];
107 wa->tab_size = new_size;
108 if (wa->tab)
sewardjb8b79ad2008-03-03 01:35:41 +0000109 ML_(dinfo_free)(wa->tab);
sewardjc613dff2005-06-13 17:33:27 +0000110 wa->tab = new_tab;
111 }
112
113 vg_assert(wa->tab_used < wa->tab_size);
114 vg_assert(wa->tab_size > 0);
115 wa->tab[wa->tab_used] = w;
116 wa->tab_used++;
117}
118
sewardj1ff57e62007-11-20 08:46:05 +0000119static Word index_WordArray ( /*OUT*/Bool* inRange, WordArray* wa, Int i )
sewardjc613dff2005-06-13 17:33:27 +0000120{
sewardj1ff57e62007-11-20 08:46:05 +0000121 vg_assert(inRange);
122 if (i >= 0 && i < wa->tab_used) {
123 *inRange = True;
124 return wa->tab[i];
125 } else {
126 *inRange = False;
127 return 0;
128 }
sewardjc613dff2005-06-13 17:33:27 +0000129}
130
131
132/*------------------------------------------------------------*/
133/*--- Read DWARF2 format line number info. ---*/
134/*------------------------------------------------------------*/
135
sewardj11624912006-02-09 23:35:11 +0000136/* Structure holding info extracted from the a .debug_line
137 section. */
jsgfcb1d1c02003-10-14 21:55:10 +0000138typedef struct
139{
sewardj11624912006-02-09 23:35:11 +0000140 ULong li_length;
jsgfcb1d1c02003-10-14 21:55:10 +0000141 UShort li_version;
sewardj11624912006-02-09 23:35:11 +0000142 ULong li_header_length;
jsgfcb1d1c02003-10-14 21:55:10 +0000143 UChar li_min_insn_length;
tomfba428c2010-04-28 08:09:30 +0000144 UChar li_max_ops_per_insn;
jsgfcb1d1c02003-10-14 21:55:10 +0000145 UChar li_default_is_stmt;
146 Int li_line_base;
147 UChar li_line_range;
148 UChar li_opcode_base;
149}
sewardj11624912006-02-09 23:35:11 +0000150DebugLineInfo;
jsgfcb1d1c02003-10-14 21:55:10 +0000151
sewardj022bf2f2005-06-14 21:51:14 +0000152/* Structure holding additional infos found from a .debug_info
153 * compilation unit block */
154typedef struct
155{
156 /* Feel free to add more members here if you need ! */
sewardj5d616df2013-07-02 08:07:15 +0000157 DiCursor compdir; /* Compilation directory - points to .debug_info */
158 DiCursor name; /* Main file name - points to .debug_info */
159 ULong stmt_list; /* Offset in .debug_line */
160 Bool dw64; /* 64-bit Dwarf? */
sewardj022bf2f2005-06-14 21:51:14 +0000161}
162UnitInfo;
163
jsgfcb1d1c02003-10-14 21:55:10 +0000164/* Line number opcodes. */
165enum dwarf_line_number_ops
166 {
167 DW_LNS_extended_op = 0,
168 DW_LNS_copy = 1,
169 DW_LNS_advance_pc = 2,
170 DW_LNS_advance_line = 3,
171 DW_LNS_set_file = 4,
172 DW_LNS_set_column = 5,
173 DW_LNS_negate_stmt = 6,
174 DW_LNS_set_basic_block = 7,
175 DW_LNS_const_add_pc = 8,
176 DW_LNS_fixed_advance_pc = 9,
177 /* DWARF 3. */
178 DW_LNS_set_prologue_end = 10,
179 DW_LNS_set_epilogue_begin = 11,
180 DW_LNS_set_isa = 12
181 };
182
183/* Line number extended opcodes. */
184enum dwarf_line_number_x_ops
185 {
186 DW_LNE_end_sequence = 1,
187 DW_LNE_set_address = 2,
tomfba428c2010-04-28 08:09:30 +0000188 DW_LNE_define_file = 3,
189 DW_LNE_set_discriminator = 4
jsgfcb1d1c02003-10-14 21:55:10 +0000190 };
191
sewardj3646a492007-02-16 14:17:10 +0000192typedef struct
jsgfcb1d1c02003-10-14 21:55:10 +0000193{
194 /* Information for the last statement boundary.
195 * Needed to calculate statement lengths. */
196 Addr last_address;
197 UInt last_file;
198 UInt last_line;
199
200 Addr address;
201 UInt file;
202 UInt line;
203 UInt column;
204 Int is_stmt;
205 Int basic_block;
tomfba428c2010-04-28 08:09:30 +0000206 UChar end_sequence;
sewardj3646a492007-02-16 14:17:10 +0000207} LineSMR;
jsgfcb1d1c02003-10-14 21:55:10 +0000208
209
sewardjb8b79ad2008-03-03 01:35:41 +0000210/* FIXME: duplicated in readdwarf3.c */
sewardj5d616df2013-07-02 08:07:15 +0000211/* Read a 'leb128' and advance *data accordingly. */
212static ULong step_leb128 ( DiCursor* data, Int sign )
jsgfcb1d1c02003-10-14 21:55:10 +0000213{
sewardj5d616df2013-07-02 08:07:15 +0000214 ULong result = 0;
215 Int shift = 0;
216 UChar byte;
jsgfcb1d1c02003-10-14 21:55:10 +0000217
sewardj5d616df2013-07-02 08:07:15 +0000218 vg_assert(sign == 0 || sign == 1);
sewardj72427fa2007-02-27 16:52:23 +0000219
sewardj5d616df2013-07-02 08:07:15 +0000220 do {
221 byte = ML_(cur_step_UChar)(data);
sewardjc4217cd2007-02-27 17:43:43 +0000222 result |= ((ULong)(byte & 0x7f)) << shift;
jsgfcb1d1c02003-10-14 21:55:10 +0000223 shift += 7;
sewardj5d616df2013-07-02 08:07:15 +0000224 }
225 while (byte & 0x80);
jsgfcb1d1c02003-10-14 21:55:10 +0000226
sewardj5d616df2013-07-02 08:07:15 +0000227 if (sign && (shift < 64) && (byte & 0x40))
228 result |= -(1ULL << shift);
jsgfcb1d1c02003-10-14 21:55:10 +0000229
sewardj5d616df2013-07-02 08:07:15 +0000230 return result;
jsgfcb1d1c02003-10-14 21:55:10 +0000231}
232
sewardjb8b79ad2008-03-03 01:35:41 +0000233/* FIXME: duplicated in readdwarf3.c */
sewardj5d616df2013-07-02 08:07:15 +0000234static ULong step_leb128U( DiCursor* data ) {
235 return step_leb128( data, 0 );
sewardj022bf2f2005-06-14 21:51:14 +0000236}
237
sewardjb8b79ad2008-03-03 01:35:41 +0000238/* FIXME: duplicated in readdwarf3.c */
sewardj5d616df2013-07-02 08:07:15 +0000239static Long step_leb128S( DiCursor* data ) {
240 return step_leb128( data, 1 );
sewardj022bf2f2005-06-14 21:51:14 +0000241}
242
sewardj11624912006-02-09 23:35:11 +0000243/* Read what the DWARF3 spec calls an "initial length field". This
244 uses up either 4 or 12 bytes of the input and produces a 32-bit or
245 64-bit number respectively.
246
247 Read 32-bit value from p. If it is 0xFFFFFFFF, instead read a
248 64-bit bit value from p+4. This is used in 64-bit dwarf to encode
sewardj5d616df2013-07-02 08:07:15 +0000249 some table lengths. Advance the cursor (p) accordingly.
sewardjc4217cd2007-02-27 17:43:43 +0000250
251 XXX this is a hack: the endianness of the initial length field is
252 specified by the DWARF we're reading. This happens to work only
253 because we don't do cross-arch jitting, hence this code runs on a
254 platform of the same endianness as the DWARF it is reading. Same
255 applies for initial lengths for CIE/FDEs and probably in zillions
256 of other places -- to be precise, exactly the places where
257 binutils/dwarf.c calls byte_get().
258*/
sewardj5d616df2013-07-02 08:07:15 +0000259static
260ULong step_initial_length_field ( DiCursor* p_img, /*OUT*/Bool* is64 )
sewardj11624912006-02-09 23:35:11 +0000261{
sewardj5d616df2013-07-02 08:07:15 +0000262 UInt w32 = ML_(cur_step_UInt)(p_img);
sewardj11624912006-02-09 23:35:11 +0000263 if (w32 == 0xFFFFFFFF) {
264 *is64 = True;
sewardj5d616df2013-07-02 08:07:15 +0000265 return ML_(cur_step_ULong)(p_img);
sewardj11624912006-02-09 23:35:11 +0000266 } else {
267 *is64 = False;
268 return (ULong)w32;
269 }
270}
271
sewardj5d616df2013-07-02 08:07:15 +0000272static
273ULong read_initial_length_field ( DiCursor p_img, /*OUT*/Bool* is64 )
274{
275 /* Something of a roundabout approach .. the modification to p_img
276 is abandoned. */
277 return step_initial_length_field( &p_img, is64 );
278}
279
sewardj022bf2f2005-06-14 21:51:14 +0000280
sewardj3646a492007-02-16 14:17:10 +0000281static LineSMR state_machine_regs;
jsgfcb1d1c02003-10-14 21:55:10 +0000282
283static
284void reset_state_machine ( Int is_stmt )
285{
barta0b6b2c2008-07-07 06:49:24 +0000286 if (0) VG_(printf)("smr.a := %p (reset)\n", NULL );
sewardj022bf2f2005-06-14 21:51:14 +0000287 state_machine_regs.last_address = 0;
288 state_machine_regs.last_file = 1;
289 state_machine_regs.last_line = 1;
290 state_machine_regs.address = 0;
291 state_machine_regs.file = 1;
292 state_machine_regs.line = 1;
293 state_machine_regs.column = 0;
294 state_machine_regs.is_stmt = is_stmt;
295 state_machine_regs.basic_block = 0;
296 state_machine_regs.end_sequence = 0;
jsgfcb1d1c02003-10-14 21:55:10 +0000297}
298
sewardjc613dff2005-06-13 17:33:27 +0000299/* Look up a directory name, or return NULL if unknown. */
300static
florian1636d332012-11-15 04:27:04 +0000301HChar* lookupDir ( Int filename_index,
302 WordArray* fnidx2dir,
303 WordArray* dirnames )
sewardjc613dff2005-06-13 17:33:27 +0000304{
sewardj1ff57e62007-11-20 08:46:05 +0000305 Bool inRange;
306 Word diridx, dirname;
307
308 diridx = index_WordArray( &inRange, fnidx2dir, filename_index );
309 if (!inRange) goto bad;
310
311 dirname = index_WordArray( &inRange, dirnames, (Int)diridx );
312 if (!inRange) goto bad;
313
florian1636d332012-11-15 04:27:04 +0000314 return (HChar*)dirname;
sewardj1ff57e62007-11-20 08:46:05 +0000315 bad:
316 return NULL;
sewardjc613dff2005-06-13 17:33:27 +0000317}
318
sewardj022bf2f2005-06-14 21:51:14 +0000319////////////////////////////////////////////////////////////////////
320////////////////////////////////////////////////////////////////////
sewardjc613dff2005-06-13 17:33:27 +0000321
sewardj5d616df2013-07-02 08:07:15 +0000322/* Handled an extended line op starting at *data, and advance *data
323 accordingly. */
jsgfcb1d1c02003-10-14 21:55:10 +0000324static
sewardj5d616df2013-07-02 08:07:15 +0000325void process_extended_line_op( struct _DebugInfo* di,
sewardj1ff57e62007-11-20 08:46:05 +0000326 WordArray* filenames,
327 WordArray* dirnames,
328 WordArray* fnidx2dir,
sewardj5d616df2013-07-02 08:07:15 +0000329 DiCursor* data, Int is_stmt)
jsgfcb1d1c02003-10-14 21:55:10 +0000330{
sewardj5d616df2013-07-02 08:07:15 +0000331 UInt len = step_leb128U(data);
sewardj022bf2f2005-06-14 21:51:14 +0000332 if (len == 0) {
jsgfcb1d1c02003-10-14 21:55:10 +0000333 VG_(message)(Vg_UserMsg,
sewardj1ff57e62007-11-20 08:46:05 +0000334 "Warning: DWARF2 reader: "
sewardj738856f2009-07-15 14:48:32 +0000335 "Badly formed extended line op encountered\n");
sewardj5d616df2013-07-02 08:07:15 +0000336 return;
sewardj022bf2f2005-06-14 21:51:14 +0000337 }
jsgfcb1d1c02003-10-14 21:55:10 +0000338
sewardj5d616df2013-07-02 08:07:15 +0000339 UChar op_code = ML_(cur_step_UChar)(data);
sewardj022bf2f2005-06-14 21:51:14 +0000340 if (0) VG_(printf)("dwarf2: ext OPC: %d\n", op_code);
jsgfcb1d1c02003-10-14 21:55:10 +0000341
sewardj022bf2f2005-06-14 21:51:14 +0000342 switch (op_code) {
343 case DW_LNE_end_sequence:
barta0b6b2c2008-07-07 06:49:24 +0000344 if (0) VG_(printf)("1001: si->o %#lx, smr.a %#lx\n",
tom402c9ee2009-03-09 09:19:03 +0000345 di->text_debug_bias, state_machine_regs.address );
sewardj022bf2f2005-06-14 21:51:14 +0000346 /* JRS: added for compliance with spec; is pointless due to
347 reset_state_machine below */
348 state_machine_regs.end_sequence = 1;
jsgfcb1d1c02003-10-14 21:55:10 +0000349
sewardj022bf2f2005-06-14 21:51:14 +0000350 if (state_machine_regs.is_stmt) {
sewardj1ff57e62007-11-20 08:46:05 +0000351 if (state_machine_regs.last_address) {
352 Bool inRange = False;
florian6bd9dc12012-11-23 16:17:43 +0000353 const HChar* filename
florian1636d332012-11-15 04:27:04 +0000354 = (HChar*)index_WordArray( &inRange, filenames,
355 state_machine_regs.last_file);
sewardj1ff57e62007-11-20 08:46:05 +0000356 if (!inRange || !filename)
357 filename = "???";
sewardj7eb7c582005-06-23 01:02:53 +0000358 ML_(addLineInfo) (
sewardjb8b79ad2008-03-03 01:35:41 +0000359 di,
sewardj1ff57e62007-11-20 08:46:05 +0000360 filename,
sewardj022bf2f2005-06-14 21:51:14 +0000361 lookupDir( state_machine_regs.last_file,
362 fnidx2dir, dirnames ),
tom402c9ee2009-03-09 09:19:03 +0000363 di->text_debug_bias + state_machine_regs.last_address,
364 di->text_debug_bias + state_machine_regs.address,
sewardj022bf2f2005-06-14 21:51:14 +0000365 state_machine_regs.last_line, 0
366 );
sewardj1ff57e62007-11-20 08:46:05 +0000367 }
sewardj022bf2f2005-06-14 21:51:14 +0000368 }
369 reset_state_machine (is_stmt);
sewardjb8b79ad2008-03-03 01:35:41 +0000370 if (di->ddump_line)
sewardj3646a492007-02-16 14:17:10 +0000371 VG_(printf)(" Extended opcode %d: End of Sequence\n\n",
372 (Int)op_code);
sewardj022bf2f2005-06-14 21:51:14 +0000373 break;
jsgfcb1d1c02003-10-14 21:55:10 +0000374
sewardj5d616df2013-07-02 08:07:15 +0000375 case DW_LNE_set_address: {
376 Addr adr = ML_(cur_step_Addr)(data);
sewardj022bf2f2005-06-14 21:51:14 +0000377 state_machine_regs.address = adr;
sewardjb8b79ad2008-03-03 01:35:41 +0000378 if (di->ddump_line)
sewardj3646a492007-02-16 14:17:10 +0000379 VG_(printf)(" Extended opcode %d: set Address to 0x%lx\n",
380 (Int)op_code, (Addr)adr);
sewardj022bf2f2005-06-14 21:51:14 +0000381 break;
sewardj5d616df2013-07-02 08:07:15 +0000382 }
jsgfcb1d1c02003-10-14 21:55:10 +0000383
sewardj5d616df2013-07-02 08:07:15 +0000384 case DW_LNE_define_file: {
385 HChar* name = ML_(cur_step_strdup)(data, "di.pelo.1");
sewardjb8b79ad2008-03-03 01:35:41 +0000386 addto_WordArray( filenames, (Word)ML_(addStr)(di,name,-1) );
sewardj5d616df2013-07-02 08:07:15 +0000387 ML_(dinfo_free)(name);
388 (void)step_leb128U(data); // ignored: dir index
389 (void)step_leb128U(data); // ignored: mod time
390 (void)step_leb128U(data); // ignored: file size
sewardjb8b79ad2008-03-03 01:35:41 +0000391 if (di->ddump_line)
sewardj3646a492007-02-16 14:17:10 +0000392 VG_(printf)(" DWARF2-line: set_address\n");
sewardj022bf2f2005-06-14 21:51:14 +0000393 break;
sewardj5d616df2013-07-02 08:07:15 +0000394 }
jsgfcb1d1c02003-10-14 21:55:10 +0000395
tomfba428c2010-04-28 08:09:30 +0000396 case DW_LNE_set_discriminator:
sewardj5d616df2013-07-02 08:07:15 +0000397 (void)step_leb128U(data); // ignored: new 'discriminator' value
tomfba428c2010-04-28 08:09:30 +0000398 break;
399
sewardj022bf2f2005-06-14 21:51:14 +0000400 default:
sewardjb8b79ad2008-03-03 01:35:41 +0000401 if (di->ddump_line)
sewardj3646a492007-02-16 14:17:10 +0000402 VG_(printf)("process_extended_line_op:default\n");
sewardj022bf2f2005-06-14 21:51:14 +0000403 break;
404 }
jsgfcb1d1c02003-10-14 21:55:10 +0000405}
njn4bbdc972003-10-16 10:10:55 +0000406
sewardj022bf2f2005-06-14 21:51:14 +0000407////////////////////////////////////////////////////////////////////
408////////////////////////////////////////////////////////////////////
409
410/* read a .debug_line section block for a compilation unit
411 *
412 * Input: - theBlock must point to the start of the block
413 * for the given compilation unit
414 * - ui contains additional info like the compilation dir
415 * for this unit
416 *
417 * Output: - si debug info structures get updated
418 */
419static
sewardjb8b79ad2008-03-03 01:35:41 +0000420void read_dwarf2_lineblock ( struct _DebugInfo* di,
sewardj022bf2f2005-06-14 21:51:14 +0000421 UnitInfo* ui,
sewardj5d616df2013-07-02 08:07:15 +0000422 DiCursor theBlock, /* IMAGE */
sewardj022bf2f2005-06-14 21:51:14 +0000423 Int noLargerThan )
424{
sewardj3646a492007-02-16 14:17:10 +0000425 Int i;
sewardj11624912006-02-09 23:35:11 +0000426 DebugLineInfo info;
sewardj11624912006-02-09 23:35:11 +0000427 Bool is64;
428 WordArray filenames;
429 WordArray dirnames;
430 WordArray fnidx2dir;
431
sewardj5d616df2013-07-02 08:07:15 +0000432 DiCursor external = theBlock;
433 DiCursor data = theBlock;
sewardj022bf2f2005-06-14 21:51:14 +0000434
435 /* filenames is an array of file names harvested from the DWARF2
436 info. Entry [0] is NULL and is never referred to by the state
437 machine.
438
439 Similarly, dirnames is an array of directory names. Entry [0]
440 is also NULL and denotes "we don't know what the path is", since
441 that is different from "the path is the empty string". Unlike
442 the file name table, the state machine does refer to entry [0],
443 which basically means "." ("the current directory of the
444 compilation", whatever that means, according to the DWARF3
445 spec.)
446
447 fnidx2dir is an array of indexes into the dirnames table.
448 (confused yet?) filenames[] and fnidx2dir[] are indexed
449 together. That is, for some index i in the filename table, then
450
451 the filename is filenames[i]
452 the directory is dirnames[ fnidx2dir[i] ] */
453
454 /* Fails due to gcc padding ...
455 vg_assert(sizeof(DWARF2_External_LineInfo)
456 == sizeof(DWARF2_Internal_LineInfo));
457 */
458
sewardj022bf2f2005-06-14 21:51:14 +0000459 init_WordArray(&filenames);
460 init_WordArray(&dirnames);
461 init_WordArray(&fnidx2dir);
462
463 /* DWARF2 starts numbering filename entries at 1, so we need to
464 add a dummy zeroth entry to the table. The zeroth dirnames
465 entry denotes 'current directory of compilation' so we might
466 as well make the fnidx2dir zeroth entry denote that.
467 */
468 addto_WordArray( &filenames, (Word)NULL );
469
sewardj5d616df2013-07-02 08:07:15 +0000470 if (ML_(cur_is_valid)(ui->compdir))
471 addto_WordArray( &dirnames,
472 (Word)ML_(addStrFromCursor)(di, ui->compdir) );
sewardj022bf2f2005-06-14 21:51:14 +0000473 else
sewardjb8b79ad2008-03-03 01:35:41 +0000474 addto_WordArray( &dirnames, (Word)ML_(addStr)(di, ".", -1) );
sewardj022bf2f2005-06-14 21:51:14 +0000475
476 addto_WordArray( &fnidx2dir, (Word)0 ); /* compilation dir */
477
sewardj5d616df2013-07-02 08:07:15 +0000478 info.li_length = step_initial_length_field( &external, &is64 );
sewardjb8b79ad2008-03-03 01:35:41 +0000479 if (di->ddump_line)
sewardj3646a492007-02-16 14:17:10 +0000480 VG_(printf)(" Length: %llu\n",
481 info.li_length);
482
sewardj022bf2f2005-06-14 21:51:14 +0000483 /* Check the length of the block. */
sewardj11624912006-02-09 23:35:11 +0000484 if (info.li_length > noLargerThan) {
sewardjb8b79ad2008-03-03 01:35:41 +0000485 ML_(symerr)(di, True,
486 "DWARF line info appears to be corrupt "
sewardj022bf2f2005-06-14 21:51:14 +0000487 "- the section is too small");
488 goto out;
489 }
490
491 /* Check its version number. */
sewardj5d616df2013-07-02 08:07:15 +0000492 info.li_version = ML_(cur_step_UShort)(&external);
sewardjb8b79ad2008-03-03 01:35:41 +0000493 if (di->ddump_line)
sewardj3646a492007-02-16 14:17:10 +0000494 VG_(printf)(" DWARF Version: %d\n",
495 (Int)info.li_version);
496
tomfba428c2010-04-28 08:09:30 +0000497 if (info.li_version != 2 && info.li_version != 3 && info.li_version != 4) {
sewardjb8b79ad2008-03-03 01:35:41 +0000498 ML_(symerr)(di, True,
tomfba428c2010-04-28 08:09:30 +0000499 "Only DWARF version 2, 3 and 4 line info "
sewardj022bf2f2005-06-14 21:51:14 +0000500 "is currently supported.");
501 goto out;
502 }
503
sewardj5d616df2013-07-02 08:07:15 +0000504 info.li_header_length = is64 ? ML_(cur_step_ULong)(&external)
505 : (ULong)(ML_(cur_step_UInt)(&external));
sewardjb8b79ad2008-03-03 01:35:41 +0000506 if (di->ddump_line)
sewardj3646a492007-02-16 14:17:10 +0000507 VG_(printf)(" Prologue Length: %llu\n",
508 info.li_header_length);
sewardj11624912006-02-09 23:35:11 +0000509
sewardj5d616df2013-07-02 08:07:15 +0000510 info.li_min_insn_length = ML_(cur_step_UChar)(&external);
sewardjb8b79ad2008-03-03 01:35:41 +0000511 if (di->ddump_line)
sewardj3646a492007-02-16 14:17:10 +0000512 VG_(printf)(" Minimum Instruction Length: %d\n",
513 (Int)info.li_min_insn_length);
sewardj022bf2f2005-06-14 21:51:14 +0000514
tomfba428c2010-04-28 08:09:30 +0000515 /* We only support machines with one opcode per instruction
516 for now. If we ever want to support VLIW machines there is
517 code to handle multiple opcodes per instruction in the
518 patch attached to BZ#233595.
519 */
520 if (info.li_version >= 4) {
sewardj5d616df2013-07-02 08:07:15 +0000521 info.li_max_ops_per_insn = ML_(cur_step_UChar)(&external);
tomfba428c2010-04-28 08:09:30 +0000522 if (info.li_max_ops_per_insn != 1) {
523 ML_(symerr)(di, True,
524 "Invalid Maximum Ops Per Insn in line info.");
525 goto out;
526 }
tomfba428c2010-04-28 08:09:30 +0000527 if (di->ddump_line)
528 VG_(printf)(" Maximum Ops Per Insn: %d\n",
529 (Int)info.li_max_ops_per_insn);
530 } else {
531 info.li_max_ops_per_insn = 1;
532 }
533
sewardj5d616df2013-07-02 08:07:15 +0000534 info.li_default_is_stmt = ML_(cur_step_UChar)(&external);
sewardjb8b79ad2008-03-03 01:35:41 +0000535 if (di->ddump_line)
sewardj3646a492007-02-16 14:17:10 +0000536 VG_(printf)(" Initial value of 'is_stmt': %d\n",
537 (Int)info.li_default_is_stmt);
538
sewardj022bf2f2005-06-14 21:51:14 +0000539 /* Josef Weidendorfer (20021021) writes:
540
541 It seems to me that the Intel Fortran compiler generates bad
542 DWARF2 line info code: It sets "is_stmt" of the state machine in
543 the the line info reader to be always false. Thus, there is
544 never a statement boundary generated and therefore never a
545 instruction range/line number mapping generated for valgrind.
546
547 Please have a look at the DWARF2 specification, Ch. 6.2
548 (x86.ddj.com/ftp/manuals/tools/dwarf.pdf). Perhaps I understand
549 this wrong, but I don't think so.
550
551 I just had a look at the GDB DWARF2 reader... They completely
552 ignore "is_stmt" when recording line info ;-) That's the reason
553 "objdump -S" works on files from the the intel fortran compiler.
sewardj3646a492007-02-16 14:17:10 +0000554
555 Therefore: */
556 info.li_default_is_stmt = True;
sewardj022bf2f2005-06-14 21:51:14 +0000557
558 /* JRS: changed (UInt*) to (UChar*) */
sewardj5d616df2013-07-02 08:07:15 +0000559 info.li_line_base = ML_(cur_step_UChar)(&external);
560 info.li_line_base = (Int)(Char)info.li_line_base;
sewardjb8b79ad2008-03-03 01:35:41 +0000561 if (di->ddump_line)
sewardj3646a492007-02-16 14:17:10 +0000562 VG_(printf)(" Line Base: %d\n",
563 info.li_line_base);
sewardj022bf2f2005-06-14 21:51:14 +0000564
sewardj5d616df2013-07-02 08:07:15 +0000565 info.li_line_range = ML_(cur_step_UChar)(&external);
sewardjb8b79ad2008-03-03 01:35:41 +0000566 if (di->ddump_line)
sewardj3646a492007-02-16 14:17:10 +0000567 VG_(printf)(" Line Range: %d\n",
568 (Int)info.li_line_range);
sewardj11624912006-02-09 23:35:11 +0000569
sewardj5d616df2013-07-02 08:07:15 +0000570 info.li_opcode_base = ML_(cur_step_UChar)(&external);
sewardjb8b79ad2008-03-03 01:35:41 +0000571 if (di->ddump_line)
sewardj3646a492007-02-16 14:17:10 +0000572 VG_(printf)(" Opcode Base: %d\n\n",
573 info.li_opcode_base);
sewardj022bf2f2005-06-14 21:51:14 +0000574
575 if (0) VG_(printf)("dwarf2: line base: %d, range %d, opc base: %d\n",
sewardj11624912006-02-09 23:35:11 +0000576 (Int)info.li_line_base,
577 (Int)info.li_line_range,
578 (Int)info.li_opcode_base);
sewardj022bf2f2005-06-14 21:51:14 +0000579
sewardj5d616df2013-07-02 08:07:15 +0000580 DiCursor end_of_sequence
581 = ML_(cur_plus)(data, info.li_length + (is64 ? 12 : 4));
sewardj022bf2f2005-06-14 21:51:14 +0000582
583 reset_state_machine (info.li_default_is_stmt);
584
585 /* Read the contents of the Opcodes table. */
sewardj5d616df2013-07-02 08:07:15 +0000586 DiCursor standard_opcodes = external;
sewardjb8b79ad2008-03-03 01:35:41 +0000587 if (di->ddump_line) {
sewardj3646a492007-02-16 14:17:10 +0000588 VG_(printf)(" Opcodes:\n");
589 for (i = 1; i < (Int)info.li_opcode_base; i++) {
590 VG_(printf)(" Opcode %d has %d args\n",
sewardj5d616df2013-07-02 08:07:15 +0000591 i, (Int)ML_(cur_read_UChar)(
592 ML_(cur_plus)(standard_opcodes,
593 (i-1) * sizeof(UChar)) ));
sewardj3646a492007-02-16 14:17:10 +0000594 }
595 VG_(printf)("\n");
596 }
sewardj022bf2f2005-06-14 21:51:14 +0000597
598 /* Read the contents of the Directory table. */
sewardj5d616df2013-07-02 08:07:15 +0000599 data = ML_(cur_plus)(standard_opcodes, info.li_opcode_base - 1);
sewardj022bf2f2005-06-14 21:51:14 +0000600
sewardjb8b79ad2008-03-03 01:35:41 +0000601 if (di->ddump_line)
sewardj3646a492007-02-16 14:17:10 +0000602 VG_(printf)(" The Directory Table%s\n",
sewardj5d616df2013-07-02 08:07:15 +0000603 ML_(cur_read_UChar)(data) == 0 ? " is empty." : ":" );
sewardj3646a492007-02-16 14:17:10 +0000604
sewardj5d616df2013-07-02 08:07:15 +0000605 while (ML_(cur_read_UChar)(data) != 0) {
sewardj022bf2f2005-06-14 21:51:14 +0000606
607# define NBUF 4096
florian1636d332012-11-15 04:27:04 +0000608 static HChar buf[NBUF];
sewardj022bf2f2005-06-14 21:51:14 +0000609
sewardj5d616df2013-07-02 08:07:15 +0000610 HChar* data_str = ML_(cur_read_strdup)(data, "di.rd2l.1");
sewardjb8b79ad2008-03-03 01:35:41 +0000611 if (di->ddump_line)
sewardj5d616df2013-07-02 08:07:15 +0000612 VG_(printf)(" %s\n", data_str);
sewardj3646a492007-02-16 14:17:10 +0000613
sewardj022bf2f2005-06-14 21:51:14 +0000614 /* If data[0] is '/', then 'data' is an absolute path and we
615 don't mess with it. Otherwise, if we can, construct the
sewardj5d616df2013-07-02 08:07:15 +0000616 path 'ui->compdir' ++ "/" ++ 'data'. */
sewardj022bf2f2005-06-14 21:51:14 +0000617
sewardj5d616df2013-07-02 08:07:15 +0000618 if (data_str[0] != '/'
sewardj022bf2f2005-06-14 21:51:14 +0000619 /* not an absolute path */
sewardj5d616df2013-07-02 08:07:15 +0000620 && ML_(cur_is_valid)(ui->compdir)
sewardj3c540212005-06-17 13:06:53 +0000621 /* actually got something sensible for compdir */
sewardj5d616df2013-07-02 08:07:15 +0000622 && ML_(cur_strlen)(ui->compdir)
623 + VG_(strlen)(data_str) + 5/*paranoia*/ < NBUF
sewardj022bf2f2005-06-14 21:51:14 +0000624 /* it's short enough to concatenate */)
625 {
626 buf[0] = 0;
sewardj5d616df2013-07-02 08:07:15 +0000627 HChar* compdir_str = ML_(cur_read_strdup)(ui->compdir, "di.rd2l.1b");
628 VG_(strcat)(buf, compdir_str);
sewardj022bf2f2005-06-14 21:51:14 +0000629 VG_(strcat)(buf, "/");
sewardj5d616df2013-07-02 08:07:15 +0000630 VG_(strcat)(buf, data_str);
sewardj022bf2f2005-06-14 21:51:14 +0000631 vg_assert(VG_(strlen)(buf) < NBUF);
sewardjb8b79ad2008-03-03 01:35:41 +0000632 addto_WordArray( &dirnames, (Word)ML_(addStr)(di,buf,-1) );
sewardj022bf2f2005-06-14 21:51:14 +0000633 if (0) VG_(printf)("rel path %s\n", buf);
sewardj5d616df2013-07-02 08:07:15 +0000634 ML_(dinfo_free)(compdir_str);
sewardj022bf2f2005-06-14 21:51:14 +0000635 } else {
636 /* just use 'data'. */
sewardj5d616df2013-07-02 08:07:15 +0000637 addto_WordArray( &dirnames, (Word)ML_(addStr)(di,data_str,-1) );
638 if (0) VG_(printf)("abs path %s\n", data_str);
sewardj022bf2f2005-06-14 21:51:14 +0000639 }
640
sewardj5d616df2013-07-02 08:07:15 +0000641 data = ML_(cur_plus)(data, VG_(strlen)(data_str) + 1);
642 ML_(dinfo_free)(data_str);
sewardj022bf2f2005-06-14 21:51:14 +0000643
644# undef NBUF
645 }
sewardj3646a492007-02-16 14:17:10 +0000646
sewardjb8b79ad2008-03-03 01:35:41 +0000647 if (di->ddump_line)
sewardj3646a492007-02-16 14:17:10 +0000648 VG_(printf)("\n");
649
sewardj5d616df2013-07-02 08:07:15 +0000650 if (ML_(cur_read_UChar)(data) != 0) {
sewardjb8b79ad2008-03-03 01:35:41 +0000651 ML_(symerr)(di, True,
652 "can't find NUL at end of DWARF2 directory table");
sewardj022bf2f2005-06-14 21:51:14 +0000653 goto out;
654 }
sewardj5d616df2013-07-02 08:07:15 +0000655 data = ML_(cur_plus)(data, 1);
sewardj022bf2f2005-06-14 21:51:14 +0000656
657 /* Read the contents of the File Name table. This produces a bunch
658 of file names, and for each, an index to the corresponding
sewardj3646a492007-02-16 14:17:10 +0000659 directory name entry. */
sewardjb8b79ad2008-03-03 01:35:41 +0000660 if (di->ddump_line) {
sewardj3646a492007-02-16 14:17:10 +0000661 VG_(printf)(" The File Name Table:\n");
662 VG_(printf)(" Entry Dir Time Size Name\n");
663 }
664
665 i = 1;
sewardj5d616df2013-07-02 08:07:15 +0000666 while (ML_(cur_read_UChar)(data) != 0) {
667 HChar* name = ML_(cur_step_strdup)(&data, "di.rd2l.2");
668 Int diridx = step_leb128U(&data);
669 Int uu_time = step_leb128U(&data); /* unused */
670 Int uu_size = step_leb128U(&data); /* unused */
sewardjb8b79ad2008-03-03 01:35:41 +0000671 addto_WordArray( &filenames, (Word)ML_(addStr)(di,name,-1) );
sewardj022bf2f2005-06-14 21:51:14 +0000672 addto_WordArray( &fnidx2dir, (Word)diridx );
673 if (0) VG_(printf)("file %s diridx %d\n", name, diridx );
sewardjb8b79ad2008-03-03 01:35:41 +0000674 if (di->ddump_line)
sewardj3646a492007-02-16 14:17:10 +0000675 VG_(printf)(" %d\t%d\t%d\t%d\t%s\n",
676 i, diridx, uu_time, uu_size, name);
677 i++;
sewardj5d616df2013-07-02 08:07:15 +0000678 ML_(dinfo_free)(name);
sewardj022bf2f2005-06-14 21:51:14 +0000679 }
sewardj3646a492007-02-16 14:17:10 +0000680
sewardjb8b79ad2008-03-03 01:35:41 +0000681 if (di->ddump_line)
sewardj3646a492007-02-16 14:17:10 +0000682 VG_(printf)("\n");
683
sewardj5d616df2013-07-02 08:07:15 +0000684 if (ML_(cur_read_UChar)(data) != 0) {
sewardjb8b79ad2008-03-03 01:35:41 +0000685 ML_(symerr)(di, True,
686 "can't find NUL at end of DWARF2 file name table");
sewardj022bf2f2005-06-14 21:51:14 +0000687 goto out;
688 }
sewardj5d616df2013-07-02 08:07:15 +0000689 data = ML_(cur_plus)(data, 1);
sewardj022bf2f2005-06-14 21:51:14 +0000690
sewardjb8b79ad2008-03-03 01:35:41 +0000691 if (di->ddump_line)
sewardj3646a492007-02-16 14:17:10 +0000692 VG_(printf)(" Line Number Statements:\n");
693
sewardj022bf2f2005-06-14 21:51:14 +0000694 /* Now display the statements. */
695
sewardj5d616df2013-07-02 08:07:15 +0000696 while (ML_(cur_cmpLT)(data, end_of_sequence)) {
697 UChar op_code = ML_(cur_step_UChar)(&data);
sewardj022bf2f2005-06-14 21:51:14 +0000698
699 if (0) VG_(printf)("dwarf2: OPC: %d\n", op_code);
700
701 if (op_code >= info.li_opcode_base) {
sewardj022bf2f2005-06-14 21:51:14 +0000702 op_code -= info.li_opcode_base;
sewardj5d616df2013-07-02 08:07:15 +0000703 Word adv = (op_code / info.li_line_range)
sewardj022bf2f2005-06-14 21:51:14 +0000704 * info.li_min_insn_length;
sewardj5d616df2013-07-02 08:07:15 +0000705 Int advAddr = adv;
sewardj022bf2f2005-06-14 21:51:14 +0000706 state_machine_regs.address += adv;
sewardj3646a492007-02-16 14:17:10 +0000707
sewardj5d616df2013-07-02 08:07:15 +0000708 if (0) VG_(printf)("smr.a += %#lx\n", adv );
sewardj022bf2f2005-06-14 21:51:14 +0000709 adv = (op_code % info.li_line_range) + info.li_line_base;
barta0b6b2c2008-07-07 06:49:24 +0000710 if (0) VG_(printf)("1002: di->o %#lx, smr.a %#lx\n",
tom402c9ee2009-03-09 09:19:03 +0000711 di->text_debug_bias, state_machine_regs.address );
sewardj022bf2f2005-06-14 21:51:14 +0000712 state_machine_regs.line += adv;
713
sewardjb8b79ad2008-03-03 01:35:41 +0000714 if (di->ddump_line)
sewardj3646a492007-02-16 14:17:10 +0000715 VG_(printf)(" Special opcode %d: advance Address by %d "
716 "to 0x%lx and Line by %d to %d\n",
717 (Int)op_code, advAddr, state_machine_regs.address,
718 (Int)adv, (Int)state_machine_regs.line );
719
sewardj022bf2f2005-06-14 21:51:14 +0000720 if (state_machine_regs.is_stmt) {
721 /* only add a statement if there was a previous boundary */
sewardj1ff57e62007-11-20 08:46:05 +0000722 if (state_machine_regs.last_address) {
723 Bool inRange = False;
florian1636d332012-11-15 04:27:04 +0000724 const HChar* filename
725 = (HChar*)index_WordArray( &inRange, &filenames,
726 state_machine_regs.last_file);
sewardj1ff57e62007-11-20 08:46:05 +0000727 if (!inRange || !filename)
728 filename = "???";
sewardj7eb7c582005-06-23 01:02:53 +0000729 ML_(addLineInfo)(
sewardjb8b79ad2008-03-03 01:35:41 +0000730 di,
sewardj1ff57e62007-11-20 08:46:05 +0000731 filename,
sewardj022bf2f2005-06-14 21:51:14 +0000732 lookupDir( state_machine_regs.last_file,
733 &fnidx2dir, &dirnames ),
tom402c9ee2009-03-09 09:19:03 +0000734 di->text_debug_bias + state_machine_regs.last_address,
735 di->text_debug_bias + state_machine_regs.address,
sewardj022bf2f2005-06-14 21:51:14 +0000736 state_machine_regs.last_line,
737 0
738 );
sewardj1ff57e62007-11-20 08:46:05 +0000739 }
sewardj022bf2f2005-06-14 21:51:14 +0000740 state_machine_regs.last_address = state_machine_regs.address;
741 state_machine_regs.last_file = state_machine_regs.file;
742 state_machine_regs.last_line = state_machine_regs.line;
743 }
sewardj022bf2f2005-06-14 21:51:14 +0000744 }
745
sewardj3646a492007-02-16 14:17:10 +0000746 else { /* ! (op_code >= info.li_opcode_base) */
747
sewardj022bf2f2005-06-14 21:51:14 +0000748 switch (op_code) {
749 case DW_LNS_extended_op:
sewardj5d616df2013-07-02 08:07:15 +0000750 process_extended_line_op (
sewardjb8b79ad2008-03-03 01:35:41 +0000751 di, &filenames, &dirnames, &fnidx2dir,
sewardj5d616df2013-07-02 08:07:15 +0000752 &data, info.li_default_is_stmt);
sewardj022bf2f2005-06-14 21:51:14 +0000753 break;
754
755 case DW_LNS_copy:
barta0b6b2c2008-07-07 06:49:24 +0000756 if (0) VG_(printf)("1002: di->o %#lx, smr.a %#lx\n",
tom402c9ee2009-03-09 09:19:03 +0000757 di->text_debug_bias, state_machine_regs.address );
sewardj022bf2f2005-06-14 21:51:14 +0000758 if (state_machine_regs.is_stmt) {
759 /* only add a statement if there was a previous boundary */
sewardj1ff57e62007-11-20 08:46:05 +0000760 if (state_machine_regs.last_address) {
761 Bool inRange = False;
florian1636d332012-11-15 04:27:04 +0000762 const HChar* filename
763 = (HChar*)index_WordArray( &inRange, &filenames,
764 state_machine_regs.last_file );
sewardj1ff57e62007-11-20 08:46:05 +0000765 if (!inRange || !filename)
766 filename = "???";
sewardj7eb7c582005-06-23 01:02:53 +0000767 ML_(addLineInfo)(
sewardjb8b79ad2008-03-03 01:35:41 +0000768 di,
sewardj1ff57e62007-11-20 08:46:05 +0000769 filename,
sewardj022bf2f2005-06-14 21:51:14 +0000770 lookupDir( state_machine_regs.last_file,
771 &fnidx2dir, &dirnames ),
tom402c9ee2009-03-09 09:19:03 +0000772 di->text_debug_bias + state_machine_regs.last_address,
773 di->text_debug_bias + state_machine_regs.address,
sewardj022bf2f2005-06-14 21:51:14 +0000774 state_machine_regs.last_line,
775 0
776 );
sewardj1ff57e62007-11-20 08:46:05 +0000777 }
sewardj022bf2f2005-06-14 21:51:14 +0000778 state_machine_regs.last_address = state_machine_regs.address;
779 state_machine_regs.last_file = state_machine_regs.file;
780 state_machine_regs.last_line = state_machine_regs.line;
781 }
782 state_machine_regs.basic_block = 0; /* JRS added */
sewardjb8b79ad2008-03-03 01:35:41 +0000783 if (di->ddump_line)
sewardj3646a492007-02-16 14:17:10 +0000784 VG_(printf)(" Copy\n");
sewardj022bf2f2005-06-14 21:51:14 +0000785 break;
786
sewardj5d616df2013-07-02 08:07:15 +0000787 case DW_LNS_advance_pc: {
788 Word adv = info.li_min_insn_length * step_leb128U(&data);
sewardj022bf2f2005-06-14 21:51:14 +0000789 state_machine_regs.address += adv;
sewardj5d616df2013-07-02 08:07:15 +0000790 if (0) VG_(printf)("smr.a += %#lx\n", adv );
sewardjb8b79ad2008-03-03 01:35:41 +0000791 if (di->ddump_line)
sewardj5d616df2013-07-02 08:07:15 +0000792 VG_(printf)(" Advance PC by %ld to 0x%lx\n",
793 adv, state_machine_regs.address);
sewardj022bf2f2005-06-14 21:51:14 +0000794 break;
sewardj5d616df2013-07-02 08:07:15 +0000795 }
796 case DW_LNS_advance_line: {
797 Word adv = step_leb128S(&data);
sewardj022bf2f2005-06-14 21:51:14 +0000798 state_machine_regs.line += adv;
sewardjb8b79ad2008-03-03 01:35:41 +0000799 if (di->ddump_line)
sewardj5d616df2013-07-02 08:07:15 +0000800 VG_(printf)(" Advance Line by %ld to %d\n",
801 adv, (Int)state_machine_regs.line);
sewardj022bf2f2005-06-14 21:51:14 +0000802 break;
sewardj5d616df2013-07-02 08:07:15 +0000803 }
804 case DW_LNS_set_file: {
805 Word adv = step_leb128U(&data);
sewardj022bf2f2005-06-14 21:51:14 +0000806 state_machine_regs.file = adv;
sewardjb8b79ad2008-03-03 01:35:41 +0000807 if (di->ddump_line)
sewardj5d616df2013-07-02 08:07:15 +0000808 VG_(printf)(" Set File Name to entry %ld in the "
809 "File Name Table\n", adv);
sewardj022bf2f2005-06-14 21:51:14 +0000810 break;
sewardj5d616df2013-07-02 08:07:15 +0000811 }
812 case DW_LNS_set_column: {
813 Word adv = step_leb128U(&data);
sewardj022bf2f2005-06-14 21:51:14 +0000814 state_machine_regs.column = adv;
sewardjb8b79ad2008-03-03 01:35:41 +0000815 if (di->ddump_line)
sewardj5d616df2013-07-02 08:07:15 +0000816 VG_(printf)(" Set column to %ld\n", adv);
sewardj022bf2f2005-06-14 21:51:14 +0000817 break;
sewardj5d616df2013-07-02 08:07:15 +0000818 }
819 case DW_LNS_negate_stmt: {
820 Int adv = state_machine_regs.is_stmt;
sewardj022bf2f2005-06-14 21:51:14 +0000821 adv = ! adv;
822 state_machine_regs.is_stmt = adv;
sewardjb8b79ad2008-03-03 01:35:41 +0000823 if (di->ddump_line)
sewardj3646a492007-02-16 14:17:10 +0000824 VG_(printf)(" DWARF2-line: negate_stmt\n");
sewardj022bf2f2005-06-14 21:51:14 +0000825 break;
sewardj5d616df2013-07-02 08:07:15 +0000826 }
827 case DW_LNS_set_basic_block: {
sewardj022bf2f2005-06-14 21:51:14 +0000828 state_machine_regs.basic_block = 1;
sewardjb8b79ad2008-03-03 01:35:41 +0000829 if (di->ddump_line)
sewardj3646a492007-02-16 14:17:10 +0000830 VG_(printf)(" DWARF2-line: set_basic_block\n");
sewardj022bf2f2005-06-14 21:51:14 +0000831 break;
sewardj5d616df2013-07-02 08:07:15 +0000832 }
833 case DW_LNS_const_add_pc: {
834 Word adv = (((255 - info.li_opcode_base) / info.li_line_range)
835 * info.li_min_insn_length);
sewardj022bf2f2005-06-14 21:51:14 +0000836 state_machine_regs.address += adv;
sewardj5d616df2013-07-02 08:07:15 +0000837 if (0) VG_(printf)("smr.a += %#lx\n", adv );
sewardjb8b79ad2008-03-03 01:35:41 +0000838 if (di->ddump_line)
sewardj5d616df2013-07-02 08:07:15 +0000839 VG_(printf)(" Advance PC by constant %ld to 0x%lx\n",
840 adv, (Addr)state_machine_regs.address);
sewardj022bf2f2005-06-14 21:51:14 +0000841 break;
sewardj5d616df2013-07-02 08:07:15 +0000842 }
843 case DW_LNS_fixed_advance_pc: {
sewardj022bf2f2005-06-14 21:51:14 +0000844 /* XXX: Need something to get 2 bytes */
sewardj5d616df2013-07-02 08:07:15 +0000845 Word adv = ML_(cur_step_UShort)(&data);
sewardj022bf2f2005-06-14 21:51:14 +0000846 state_machine_regs.address += adv;
sewardj5d616df2013-07-02 08:07:15 +0000847 if (0) VG_(printf)("smr.a += %#lx\n", adv );
sewardjb8b79ad2008-03-03 01:35:41 +0000848 if (di->ddump_line)
sewardj3646a492007-02-16 14:17:10 +0000849 VG_(printf)(" DWARF2-line: fixed_advance_pc\n");
sewardj022bf2f2005-06-14 21:51:14 +0000850 break;
sewardj5d616df2013-07-02 08:07:15 +0000851 }
sewardj022bf2f2005-06-14 21:51:14 +0000852 case DW_LNS_set_prologue_end:
sewardjb8b79ad2008-03-03 01:35:41 +0000853 if (di->ddump_line)
sewardj3646a492007-02-16 14:17:10 +0000854 VG_(printf)(" DWARF2-line: set_prologue_end\n");
sewardj022bf2f2005-06-14 21:51:14 +0000855 break;
856
857 case DW_LNS_set_epilogue_begin:
sewardjb8b79ad2008-03-03 01:35:41 +0000858 if (di->ddump_line)
sewardj3646a492007-02-16 14:17:10 +0000859 VG_(printf)(" DWARF2-line: set_epilogue_begin\n");
sewardj022bf2f2005-06-14 21:51:14 +0000860 break;
861
862 case DW_LNS_set_isa:
sewardj5d616df2013-07-02 08:07:15 +0000863 (void)step_leb128U(&data);
sewardjb8b79ad2008-03-03 01:35:41 +0000864 if (di->ddump_line)
sewardj3646a492007-02-16 14:17:10 +0000865 VG_(printf)(" DWARF2-line: set_isa\n");
sewardj022bf2f2005-06-14 21:51:14 +0000866 break;
867
868 default: {
869 Int j;
sewardj5d616df2013-07-02 08:07:15 +0000870 for (j = (Int)ML_(cur_read_UChar)(
871 ML_(cur_plus)(standard_opcodes,
872 (op_code-1) * sizeof(UChar)));
873 j > 0 ; --j) {
874 step_leb128U(&data);
sewardj022bf2f2005-06-14 21:51:14 +0000875 }
sewardjb8b79ad2008-03-03 01:35:41 +0000876 if (di->ddump_line)
sewardj3646a492007-02-16 14:17:10 +0000877 VG_(printf)(" Unknown opcode %d\n", (Int)op_code);
878 break;
sewardj022bf2f2005-06-14 21:51:14 +0000879 }
sewardj022bf2f2005-06-14 21:51:14 +0000880 } /* switch (op_code) */
881
sewardj3646a492007-02-16 14:17:10 +0000882 } /* if (op_code >= info.li_opcode_base) */
883
sewardj022bf2f2005-06-14 21:51:14 +0000884 } /* while (data < end_of_sequence) */
885
sewardjb8b79ad2008-03-03 01:35:41 +0000886 if (di->ddump_line)
sewardj3646a492007-02-16 14:17:10 +0000887 VG_(printf)("\n");
888
sewardj022bf2f2005-06-14 21:51:14 +0000889 out:
890 free_WordArray(&filenames);
891 free_WordArray(&dirnames);
892 free_WordArray(&fnidx2dir);
893}
894
895////////////////////////////////////////////////////////////////////
896////////////////////////////////////////////////////////////////////
897
898/* Return abbrev for given code
sewardj5d616df2013-07-02 08:07:15 +0000899 * Returned cursor points to the tag
sewardj022bf2f2005-06-14 21:51:14 +0000900 * */
sewardj5d616df2013-07-02 08:07:15 +0000901static DiCursor lookup_abbrev( DiCursor p, ULong acode )
sewardj022bf2f2005-06-14 21:51:14 +0000902{
sewardj5d616df2013-07-02 08:07:15 +0000903 while (1) {
904 ULong code = step_leb128U(&p);
905 if (code == acode)
sewardj022bf2f2005-06-14 21:51:14 +0000906 return p;
sewardj5d616df2013-07-02 08:07:15 +0000907 (void)step_leb128U(&p); /* skip tag */
908 p = ML_(cur_plus)(p,1); /* skip has_children flag */
909 ULong name;
sewardj022bf2f2005-06-14 21:51:14 +0000910 do {
sewardj5d616df2013-07-02 08:07:15 +0000911 name = step_leb128U(&p); /* name */
912 (void)step_leb128U(&p); /* form */
sewardj022bf2f2005-06-14 21:51:14 +0000913 }
sewardj5d616df2013-07-02 08:07:15 +0000914 while (name != 0); /* until name == form == 0 */
sewardj022bf2f2005-06-14 21:51:14 +0000915 }
sewardj022bf2f2005-06-14 21:51:14 +0000916}
917
918/* Read general information for a particular compile unit block in
mjw4c3b2372013-04-17 13:48:29 +0000919 * the .debug_info section. In particular read the name, compdir and
920 * stmt_list needed to parse the line number information.
sewardj022bf2f2005-06-14 21:51:14 +0000921 *
922 * Input: - unitblock is the start of a compilation
923 * unit block in .debuginfo section
924 * - debugabbrev is start of .debug_abbrev section
925 * - debugstr is start of .debug_str section
mjw4c3b2372013-04-17 13:48:29 +0000926 * - debugstr_alt_img is start of .debug_str section in alt debug file
sewardj022bf2f2005-06-14 21:51:14 +0000927 *
928 * Output: Fill members of ui pertaining to the compilation unit:
929 * - ui->name is the name of the compilation unit
930 * - ui->compdir is the compilation unit directory
931 * - ui->stmt_list is the offset in .debug_line section
932 * for the dbginfos of this compilation unit
933 *
934 * Note : the output strings are not allocated and point
935 * directly to the memory-mapped section.
936 */
937static
938void read_unitinfo_dwarf2( /*OUT*/UnitInfo* ui,
sewardj5d616df2013-07-02 08:07:15 +0000939 DiCursor unitblock_img,
940 DiCursor debugabbrev_img,
941 DiCursor debugstr_img,
942 DiCursor debugstr_alt_img )
sewardj022bf2f2005-06-14 21:51:14 +0000943{
sewardj11624912006-02-09 23:35:11 +0000944 UInt acode, abcode;
945 ULong atoffs, blklen;
mjw58d9ce42013-04-11 17:55:39 +0000946 UShort ver;
sewardj022bf2f2005-06-14 21:51:14 +0000947
sewardj5d616df2013-07-02 08:07:15 +0000948 UChar addr_size;
949 DiCursor p = unitblock_img;
950 DiCursor end_img;
951 DiCursor abbrev_img;
sewardj022bf2f2005-06-14 21:51:14 +0000952
953 VG_(memset)( ui, 0, sizeof( UnitInfo ) );
sewardj11624912006-02-09 23:35:11 +0000954 ui->stmt_list = -1LL;
sewardj022bf2f2005-06-14 21:51:14 +0000955
sewardj11624912006-02-09 23:35:11 +0000956 /* Read the compilation unit header in .debug_info section - See p 70 */
sewardj022bf2f2005-06-14 21:51:14 +0000957
sewardj11624912006-02-09 23:35:11 +0000958 /* This block length */
sewardj5d616df2013-07-02 08:07:15 +0000959 blklen = step_initial_length_field( &p, &ui->dw64 );
sewardj11624912006-02-09 23:35:11 +0000960
tomfba428c2010-04-28 08:09:30 +0000961 /* version should be 2, 3 or 4 */
sewardj5d616df2013-07-02 08:07:15 +0000962 ver = ML_(cur_step_UShort)(&p);
sewardj11624912006-02-09 23:35:11 +0000963
964 /* get offset in abbrev */
sewardj5d616df2013-07-02 08:07:15 +0000965 atoffs = ui->dw64 ? ML_(cur_step_ULong)(&p)
966 : (ULong)(ML_(cur_step_UInt)(&p));
sewardj11624912006-02-09 23:35:11 +0000967
968 /* Address size */
sewardj5d616df2013-07-02 08:07:15 +0000969 addr_size = ML_(cur_step_UChar)(&p);
sewardj11624912006-02-09 23:35:11 +0000970
sewardj5d616df2013-07-02 08:07:15 +0000971 /* End of this block */
972 end_img = ML_(cur_plus)(unitblock_img, blklen + (ui->dw64 ? 12 : 4));
973
974 /* Abbreviation data for this block */
975 abbrev_img = ML_(cur_plus)(debugabbrev_img, atoffs);
sewardj022bf2f2005-06-14 21:51:14 +0000976
mjw4c3b2372013-04-17 13:48:29 +0000977 /* Read the compilation unit entry - this is always the first DIE.
978 * See DWARF4 para 7.5. */
sewardj5d616df2013-07-02 08:07:15 +0000979 if (ML_(cur_cmpLT)(p, end_img)) {
sewardj022bf2f2005-06-14 21:51:14 +0000980 UInt tag;
981
sewardj5d616df2013-07-02 08:07:15 +0000982 acode = step_leb128U( &p ); /* abbreviation code */
sewardj022bf2f2005-06-14 21:51:14 +0000983
984 /* Read abbreviation header */
sewardj5d616df2013-07-02 08:07:15 +0000985 abcode = step_leb128U( &abbrev_img ); /* abbreviation code */
sewardj022bf2f2005-06-14 21:51:14 +0000986 if ( acode != abcode ) {
mjw4c3b2372013-04-17 13:48:29 +0000987 /* This isn't illegal, but somewhat unlikely. Normally the
988 * first abbrev describes the first DIE, the compile_unit.
989 * But maybe this abbrevation data is shared with another
990 * or it is a NULL entry used for padding. See para 7.5.3. */
sewardj5d616df2013-07-02 08:07:15 +0000991 abbrev_img = lookup_abbrev( ML_(cur_plus)(debugabbrev_img, atoffs),
992 acode );
sewardj022bf2f2005-06-14 21:51:14 +0000993 }
994
sewardj5d616df2013-07-02 08:07:15 +0000995 tag = step_leb128U( &abbrev_img );
sewardj022bf2f2005-06-14 21:51:14 +0000996
mjw4c3b2372013-04-17 13:48:29 +0000997 if ( tag != 0x0011 /*TAG_compile_unit*/ )
998 return; /* Not a compile unit (might be partial) or broken DWARF. */
999
sewardj5d616df2013-07-02 08:07:15 +00001000 /* DW_CHILDREN_yes or DW_CHILDREN_no */
1001 abbrev_img = ML_(cur_plus)(abbrev_img, 1);
sewardj022bf2f2005-06-14 21:51:14 +00001002
1003 /* And loop on entries */
1004 for ( ; ; ) {
1005 /* Read entry definition */
sewardj5d616df2013-07-02 08:07:15 +00001006 ULong cval = -1LL; /* Constant value read */
1007 DiCursor sval = DiCursor_INVALID; /* String value read */
1008 UInt name = step_leb128U( &abbrev_img );
1009 UInt form = step_leb128U( &abbrev_img );
1010 if (name == 0)
sewardj022bf2f2005-06-14 21:51:14 +00001011 break;
1012
1013 /* Read data */
1014 /* Attributes encoding explained p 71 */
1015 if ( form == 0x16 /* FORM_indirect */ )
sewardj5d616df2013-07-02 08:07:15 +00001016 form = step_leb128U( &p );
sewardj022bf2f2005-06-14 21:51:14 +00001017 /* Decode form. For most kinds, Just skip the amount of data since
1018 we don't use it for now */
sewardj11624912006-02-09 23:35:11 +00001019 /* JRS 9 Feb 06: This now handles 64-bit DWARF too. In
1020 64-bit DWARF, lineptr (and loclistptr,macptr,rangelistptr
1021 classes) use FORM_data8, not FORM_data4. Also,
1022 FORM_ref_addr and FORM_strp are 64-bit values, not 32-bit
1023 values. */
tomfba428c2010-04-28 08:09:30 +00001024 /* TJH 27 Apr 10: in DWARF 4 lineptr (and loclistptr,macptr,
1025 rangelistptr classes) use FORM_sec_offset which is 64 bits
1026 in 64 bit DWARF and 32 bits in 32 bit DWARF. */
sewardj06938af2011-04-21 08:55:51 +00001027 /* JRS 20 Apr 11: LLVM-2.9 encodes DW_AT_stmt_list using
1028 FORM_addr rather than the FORM_data4 that GCC uses. Hence
1029 handle FORM_addr too. */
sewardj022bf2f2005-06-14 21:51:14 +00001030 switch( form ) {
1031 /* Those cases extract the data properly */
sewardj5d616df2013-07-02 08:07:15 +00001032 case 0x05: /* FORM_data2 */
1033 cval = ML_(cur_step_UShort)(&p);
1034 break;
1035 case 0x06: /* FORM_data4 */
1036 cval = ML_(cur_step_UInt)(&p);
1037 break;
sewardj1a0e39f2006-01-01 23:00:49 +00001038 case 0x0e: /* FORM_strp */ /* pointer in .debug_str */
sewardj5d616df2013-07-02 08:07:15 +00001039 /* 2006-01-01: only generate a value if a debug_str
1040 section was found) */
1041 if (ML_(cur_is_valid)(debugstr_img) && !ui->dw64)
1042 sval = ML_(cur_plus)(debugstr_img, ML_(cur_read_UInt)(p));
1043 if (ML_(cur_is_valid)(debugstr_img) && ui->dw64)
1044 sval = ML_(cur_plus)(debugstr_img, ML_(cur_read_ULong)(p));
1045 p = ML_(cur_plus)(p, ui->dw64 ? 8 : 4);
1046 break;
1047 case 0x08: /* FORM_string */
1048 sval = p;
1049 p = ML_(cur_plus)(p, ML_(cur_strlen)(p) + 1);
1050 break;
1051 case 0x0b: /* FORM_data1 */
1052 cval = ML_(cur_step_UChar)(&p);
1053 break;
1054 case 0x17: /* FORM_sec_offset */
1055 if (ui->dw64) {
1056 cval = ML_(cur_step_ULong)(&p);
1057 } else {
1058 cval = ML_(cur_step_UInt)(&p);
1059 };
1060 break;
1061 case 0x07: /* FORM_data8 */
1062 if (ui->dw64) cval = ML_(cur_read_ULong)(p);
1063 p = ML_(cur_plus)(p, 8);
1064 /* perhaps should assign unconditionally to cval? */
1065 break;
sewardj06938af2011-04-21 08:55:51 +00001066 /* TODO : Following ones just skip data - implement if you need */
sewardj5d616df2013-07-02 08:07:15 +00001067 case 0x01: /* FORM_addr */
1068 p = ML_(cur_plus)(p, addr_size);
1069 break;
1070 case 0x03: /* FORM_block2 */
1071 p = ML_(cur_plus)(p, ML_(cur_read_UShort)(p) + 2);
1072 break;
1073 case 0x04: /* FORM_block4 */
1074 p = ML_(cur_plus)(p, ML_(cur_read_UInt)(p) + 4);
1075 break;
1076 case 0x09: /* FORM_block */ /* fallthrough */
1077 case 0x18: { /* FORM_exprloc */
1078 ULong block_len = step_leb128U(&p);
1079 p = ML_(cur_plus)(p, block_len);
1080 break;
1081 }
1082 case 0x0a: /* FORM_block1 */
1083 p = ML_(cur_plus)(p, ML_(cur_read_UChar)(p) + 1);
1084 break;
1085 case 0x0c: /* FORM_flag */
1086 p = ML_(cur_plus)(p, 1);
1087 break;
1088 case 0x0d: /* FORM_sdata */
1089 (void)step_leb128S(&p);
1090 break;
1091 case 0x0f: /* FORM_udata */
1092 (void)step_leb128U(&p);
1093 break;
1094 case 0x10: /* FORM_ref_addr */
1095 p = ML_(cur_plus)(p, (ver == 2) ? addr_size
1096 : (ui->dw64 ? 8 : 4));
1097 break;
1098 case 0x11: /* FORM_ref1 */
1099 p = ML_(cur_plus)(p, 1);
1100 break;
1101 case 0x12: /* FORM_ref2 */
1102 p = ML_(cur_plus)(p, 2);
1103 break;
1104 case 0x13: /* FORM_ref4 */
1105 p = ML_(cur_plus)(p, 4);
1106 break;
1107 case 0x14: /* FORM_ref8 */
1108 p = ML_(cur_plus)(p, 8);
1109 break;
1110 case 0x15: /* FORM_ref_udata */
1111 (void)step_leb128U(&p);
1112 break;
1113 case 0x19: /* FORM_flag_present */
1114 break;
1115 case 0x20: /* FORM_ref_sig8 */
1116 p = ML_(cur_plus)(p, 8);
1117 break;
1118 case 0x1f20: /* FORM_GNU_ref_alt */
1119 p = ML_(cur_plus)(p, ui->dw64 ? 8 : 4);
1120 break;
sewardjf7c97142012-07-14 09:59:01 +00001121 case 0x1f21: /* FORM_GNU_strp_alt */
sewardj5d616df2013-07-02 08:07:15 +00001122 if (ML_(cur_is_valid)(debugstr_alt_img) && !ui->dw64)
1123 sval = ML_(cur_plus)(debugstr_alt_img,
1124 ML_(cur_read_UInt)(p));
1125 if (ML_(cur_is_valid)(debugstr_alt_img) && ui->dw64)
1126 sval = ML_(cur_plus)(debugstr_alt_img,
1127 ML_(cur_read_ULong)(p));
1128 p = ML_(cur_plus)(p, ui->dw64 ? 8 : 4);
1129 break;
tomfba428c2010-04-28 08:09:30 +00001130
sewardj022bf2f2005-06-14 21:51:14 +00001131 default:
sewardj5d616df2013-07-02 08:07:15 +00001132 VG_(printf)( "### unhandled dwarf2 abbrev form code 0x%x\n",
1133 form );
sewardj022bf2f2005-06-14 21:51:14 +00001134 break;
1135 }
1136
1137 /* Now store the members we need in the UnitInfo structure */
1138 if ( tag == 0x0011 /*TAG_compile_unit*/ ) {
1139 if ( name == 0x03 ) ui->name = sval; /* DW_AT_name */
1140 else if ( name == 0x1b ) ui->compdir = sval; /* DW_AT_compdir */
1141 else if ( name == 0x10 ) ui->stmt_list = cval; /* DW_AT_stmt_list */
1142 }
1143 }
mjw4c3b2372013-04-17 13:48:29 +00001144 } /* Just read the first DIE, if that wasn't the compile_unit then
1145 * this might have been a partial unit or broken DWARF info.
1146 * That's enough info for us, and we are not gdb ! */
sewardj022bf2f2005-06-14 21:51:14 +00001147}
1148
1149
1150////////////////////////////////////////////////////////////////////
1151////////////////////////////////////////////////////////////////////
1152
sewardjb8b79ad2008-03-03 01:35:41 +00001153/* Collect the debug info from DWARF3 debugging sections
sewardj022bf2f2005-06-14 21:51:14 +00001154 * of a given module.
1155 *
1156 * Inputs: given .debug_xxx sections
sewardjb8b79ad2008-03-03 01:35:41 +00001157 * Output: update di to contain all the DWARF3 debug infos
sewardj022bf2f2005-06-14 21:51:14 +00001158 */
sewardjb8b79ad2008-03-03 01:35:41 +00001159void ML_(read_debuginfo_dwarf3)
1160 ( struct _DebugInfo* di,
sewardj5d616df2013-07-02 08:07:15 +00001161 DiSlice escn_debug_info, /* .debug_info */
1162 DiSlice escn_debug_types, /* .debug_types */
1163 DiSlice escn_debug_abbv, /* .debug_abbrev */
1164 DiSlice escn_debug_line, /* .debug_line */
1165 DiSlice escn_debug_str, /* .debug_str */
1166 DiSlice escn_debug_str_alt ) /* .debug_str */
sewardj022bf2f2005-06-14 21:51:14 +00001167{
1168 UnitInfo ui;
sewardj11624912006-02-09 23:35:11 +00001169 UShort ver;
sewardj11624912006-02-09 23:35:11 +00001170 ULong blklen;
1171 Bool blklen_is_64;
sewardj022bf2f2005-06-14 21:51:14 +00001172
tom50d01ab2005-10-04 16:54:54 +00001173 /* Make sure we at least have a header for the first block */
sewardj5d616df2013-07-02 08:07:15 +00001174 if (escn_debug_info.szB < 4) {
sewardjb8b79ad2008-03-03 01:35:41 +00001175 ML_(symerr)( di, True,
1176 "Last block truncated in .debug_info; ignoring" );
tom50d01ab2005-10-04 16:54:54 +00001177 return;
1178 }
1179
sewardj5d616df2013-07-02 08:07:15 +00001180 DiCursor block_img = DiCursor_INVALID;
1181 DiCursor end1_img = ML_(cur_plus)( ML_(cur_from_sli)(escn_debug_info),
1182 escn_debug_info.szB );
1183 Int blklen_len = 0;
1184
sewardj022bf2f2005-06-14 21:51:14 +00001185 /* Iterate on all the blocks we find in .debug_info */
sewardj5d616df2013-07-02 08:07:15 +00001186 for ( block_img = ML_(cur_from_sli)(escn_debug_info);
1187 ML_(cur_cmpLT)(block_img, ML_(cur_plus)(end1_img, -(DiOffT)4));
1188 block_img = ML_(cur_plus)(block_img, blklen + blklen_len) ) {
sewardj022bf2f2005-06-14 21:51:14 +00001189
1190 /* Read the compilation unit header in .debug_info section - See
1191 p 70 */
sewardj11624912006-02-09 23:35:11 +00001192 /* This block length */
sewardjf767d962007-02-12 17:47:14 +00001193 blklen = read_initial_length_field( block_img, &blklen_is_64 );
sewardj11624912006-02-09 23:35:11 +00001194 blklen_len = blklen_is_64 ? 12 : 4;
sewardj5d616df2013-07-02 08:07:15 +00001195
1196 if (ML_(cur_cmpGT)( ML_(cur_plus)(block_img, blklen + blklen_len),
1197 end1_img )) {
sewardjb8b79ad2008-03-03 01:35:41 +00001198 ML_(symerr)( di, True,
1199 "Last block truncated in .debug_info; ignoring" );
sewardj022bf2f2005-06-14 21:51:14 +00001200 return;
1201 }
sewardj11624912006-02-09 23:35:11 +00001202
1203 /* version should be 2 */
sewardj5d616df2013-07-02 08:07:15 +00001204 ver = ML_(cur_read_UShort)( ML_(cur_plus)(block_img, blklen_len) );
tomfba428c2010-04-28 08:09:30 +00001205 if ( ver != 2 && ver != 3 && ver != 4 ) {
sewardjb8b79ad2008-03-03 01:35:41 +00001206 ML_(symerr)( di, True,
tomfba428c2010-04-28 08:09:30 +00001207 "Ignoring non-Dwarf2/3/4 block in .debug_info" );
sewardj022bf2f2005-06-14 21:51:14 +00001208 continue;
1209 }
1210
1211 /* Fill ui with offset in .debug_line and compdir */
sewardj11624912006-02-09 23:35:11 +00001212 if (0)
sewardj5d616df2013-07-02 08:07:15 +00001213 VG_(printf)(
1214 "Reading UnitInfo at 0x%llx.....\n",
1215 (ULong)ML_(cur_minus)( block_img,
1216 ML_(cur_from_sli)(escn_debug_info)) );
sewardjb8b79ad2008-03-03 01:35:41 +00001217 read_unitinfo_dwarf2( &ui, block_img,
sewardj5d616df2013-07-02 08:07:15 +00001218 ML_(cur_from_sli)(escn_debug_abbv),
1219 ML_(cur_from_sli)(escn_debug_str),
1220 ML_(cur_from_sli)(escn_debug_str_alt) );
1221 if (0) {
1222 HChar* str_name = ML_(cur_read_strdup)(ui.name, "di.rdd3.1");
1223 HChar* str_compdir = ML_(cur_read_strdup)(ui.compdir, "di.rdd3.2");
sewardj11624912006-02-09 23:35:11 +00001224 VG_(printf)( " => LINES=0x%llx NAME=%s DIR=%s\n",
sewardj5d616df2013-07-02 08:07:15 +00001225 ui.stmt_list, str_name, str_compdir );
1226 ML_(dinfo_free)(str_name);
1227 ML_(dinfo_free)(str_compdir);
1228 }
1229
sewardj022bf2f2005-06-14 21:51:14 +00001230 /* Ignore blocks with no .debug_line associated block */
sewardj11624912006-02-09 23:35:11 +00001231 if ( ui.stmt_list == -1LL )
sewardj022bf2f2005-06-14 21:51:14 +00001232 continue;
1233
sewardj5d616df2013-07-02 08:07:15 +00001234 if (0) {
1235 HChar* str_name = ML_(cur_read_strdup)(ui.name, "di.rdd3.3");
1236 VG_(printf)("debug_line_sz %lld, ui.stmt_list %lld %s\n",
1237 escn_debug_line.szB, ui.stmt_list, str_name );
1238 ML_(dinfo_free)(str_name);
1239 }
1240
sewardj022bf2f2005-06-14 21:51:14 +00001241 /* Read the .debug_line block for this compile unit */
sewardj5d616df2013-07-02 08:07:15 +00001242 read_dwarf2_lineblock(
1243 di, &ui,
1244 ML_(cur_plus)(ML_(cur_from_sli)(escn_debug_line), ui.stmt_list),
1245 escn_debug_line.szB - ui.stmt_list
1246 );
sewardj022bf2f2005-06-14 21:51:14 +00001247 }
1248}
1249
1250
1251////////////////////////////////////////////////////////////////////
1252////////////////////////////////////////////////////////////////////
jseward8b3131a2003-12-13 23:16:26 +00001253
1254/*------------------------------------------------------------*/
1255/*--- Read DWARF1 format line number info. ---*/
1256/*------------------------------------------------------------*/
1257
1258/* DWARF1 appears to be redundant, but nevertheless the Lahey Fortran
1259 compiler generates it.
1260*/
1261
1262/* The following three enums (dwarf_tag, dwarf_form, dwarf_attribute)
1263 are taken from the file include/elf/dwarf.h in the GNU gdb-6.0
1264 sources, which are Copyright 1992, 1993, 1995, 1999 Free Software
1265 Foundation, Inc and naturally licensed under the GNU General Public
1266 License version 2 or later.
1267*/
1268
1269/* Tag names and codes. */
1270
1271enum dwarf_tag {
1272 TAG_padding = 0x0000,
1273 TAG_array_type = 0x0001,
1274 TAG_class_type = 0x0002,
1275 TAG_entry_point = 0x0003,
1276 TAG_enumeration_type = 0x0004,
1277 TAG_formal_parameter = 0x0005,
1278 TAG_global_subroutine = 0x0006,
1279 TAG_global_variable = 0x0007,
1280 /* 0x0008 -- reserved */
1281 /* 0x0009 -- reserved */
1282 TAG_label = 0x000a,
1283 TAG_lexical_block = 0x000b,
1284 TAG_local_variable = 0x000c,
1285 TAG_member = 0x000d,
1286 /* 0x000e -- reserved */
1287 TAG_pointer_type = 0x000f,
1288 TAG_reference_type = 0x0010,
1289 TAG_compile_unit = 0x0011,
1290 TAG_string_type = 0x0012,
1291 TAG_structure_type = 0x0013,
1292 TAG_subroutine = 0x0014,
1293 TAG_subroutine_type = 0x0015,
1294 TAG_typedef = 0x0016,
1295 TAG_union_type = 0x0017,
1296 TAG_unspecified_parameters = 0x0018,
1297 TAG_variant = 0x0019,
1298 TAG_common_block = 0x001a,
1299 TAG_common_inclusion = 0x001b,
1300 TAG_inheritance = 0x001c,
1301 TAG_inlined_subroutine = 0x001d,
1302 TAG_module = 0x001e,
1303 TAG_ptr_to_member_type = 0x001f,
1304 TAG_set_type = 0x0020,
1305 TAG_subrange_type = 0x0021,
1306 TAG_with_stmt = 0x0022,
1307
1308 /* GNU extensions */
1309
1310 TAG_format_label = 0x8000, /* for FORTRAN 77 and Fortran 90 */
1311 TAG_namelist = 0x8001, /* For Fortran 90 */
1312 TAG_function_template = 0x8002, /* for C++ */
1313 TAG_class_template = 0x8003 /* for C++ */
1314};
1315
1316/* Form names and codes. */
1317
1318enum dwarf_form {
1319 FORM_ADDR = 0x1,
1320 FORM_REF = 0x2,
1321 FORM_BLOCK2 = 0x3,
1322 FORM_BLOCK4 = 0x4,
1323 FORM_DATA2 = 0x5,
1324 FORM_DATA4 = 0x6,
1325 FORM_DATA8 = 0x7,
1326 FORM_STRING = 0x8
1327};
1328
1329/* Attribute names and codes. */
1330
1331enum dwarf_attribute {
1332 AT_sibling = (0x0010|FORM_REF),
1333 AT_location = (0x0020|FORM_BLOCK2),
1334 AT_name = (0x0030|FORM_STRING),
1335 AT_fund_type = (0x0050|FORM_DATA2),
1336 AT_mod_fund_type = (0x0060|FORM_BLOCK2),
1337 AT_user_def_type = (0x0070|FORM_REF),
1338 AT_mod_u_d_type = (0x0080|FORM_BLOCK2),
1339 AT_ordering = (0x0090|FORM_DATA2),
1340 AT_subscr_data = (0x00a0|FORM_BLOCK2),
1341 AT_byte_size = (0x00b0|FORM_DATA4),
1342 AT_bit_offset = (0x00c0|FORM_DATA2),
1343 AT_bit_size = (0x00d0|FORM_DATA4),
1344 /* (0x00e0|FORM_xxxx) -- reserved */
1345 AT_element_list = (0x00f0|FORM_BLOCK4),
1346 AT_stmt_list = (0x0100|FORM_DATA4),
1347 AT_low_pc = (0x0110|FORM_ADDR),
1348 AT_high_pc = (0x0120|FORM_ADDR),
1349 AT_language = (0x0130|FORM_DATA4),
1350 AT_member = (0x0140|FORM_REF),
1351 AT_discr = (0x0150|FORM_REF),
1352 AT_discr_value = (0x0160|FORM_BLOCK2),
1353 /* (0x0170|FORM_xxxx) -- reserved */
1354 /* (0x0180|FORM_xxxx) -- reserved */
1355 AT_string_length = (0x0190|FORM_BLOCK2),
1356 AT_common_reference = (0x01a0|FORM_REF),
1357 AT_comp_dir = (0x01b0|FORM_STRING),
1358 AT_const_value_string = (0x01c0|FORM_STRING),
1359 AT_const_value_data2 = (0x01c0|FORM_DATA2),
1360 AT_const_value_data4 = (0x01c0|FORM_DATA4),
1361 AT_const_value_data8 = (0x01c0|FORM_DATA8),
1362 AT_const_value_block2 = (0x01c0|FORM_BLOCK2),
1363 AT_const_value_block4 = (0x01c0|FORM_BLOCK4),
1364 AT_containing_type = (0x01d0|FORM_REF),
1365 AT_default_value_addr = (0x01e0|FORM_ADDR),
1366 AT_default_value_data2 = (0x01e0|FORM_DATA2),
1367 AT_default_value_data4 = (0x01e0|FORM_DATA4),
1368 AT_default_value_data8 = (0x01e0|FORM_DATA8),
1369 AT_default_value_string = (0x01e0|FORM_STRING),
1370 AT_friends = (0x01f0|FORM_BLOCK2),
1371 AT_inline = (0x0200|FORM_STRING),
1372 AT_is_optional = (0x0210|FORM_STRING),
1373 AT_lower_bound_ref = (0x0220|FORM_REF),
1374 AT_lower_bound_data2 = (0x0220|FORM_DATA2),
1375 AT_lower_bound_data4 = (0x0220|FORM_DATA4),
1376 AT_lower_bound_data8 = (0x0220|FORM_DATA8),
1377 AT_private = (0x0240|FORM_STRING),
1378 AT_producer = (0x0250|FORM_STRING),
1379 AT_program = (0x0230|FORM_STRING),
1380 AT_protected = (0x0260|FORM_STRING),
1381 AT_prototyped = (0x0270|FORM_STRING),
1382 AT_public = (0x0280|FORM_STRING),
1383 AT_pure_virtual = (0x0290|FORM_STRING),
1384 AT_return_addr = (0x02a0|FORM_BLOCK2),
1385 AT_abstract_origin = (0x02b0|FORM_REF),
1386 AT_start_scope = (0x02c0|FORM_DATA4),
1387 AT_stride_size = (0x02e0|FORM_DATA4),
1388 AT_upper_bound_ref = (0x02f0|FORM_REF),
1389 AT_upper_bound_data2 = (0x02f0|FORM_DATA2),
1390 AT_upper_bound_data4 = (0x02f0|FORM_DATA4),
1391 AT_upper_bound_data8 = (0x02f0|FORM_DATA8),
1392 AT_virtual = (0x0300|FORM_STRING),
1393
1394 /* GNU extensions. */
1395
1396 AT_sf_names = (0x8000|FORM_DATA4),
1397 AT_src_info = (0x8010|FORM_DATA4),
1398 AT_mac_info = (0x8020|FORM_DATA4),
1399 AT_src_coords = (0x8030|FORM_DATA4),
1400 AT_body_begin = (0x8040|FORM_ADDR),
1401 AT_body_end = (0x8050|FORM_ADDR)
1402};
1403
1404/* end of enums taken from gdb-6.0 sources */
sewardj5d616df2013-07-02 08:07:15 +00001405#if 0
sewardj7eb7c582005-06-23 01:02:53 +00001406void ML_(read_debuginfo_dwarf1) (
sewardjb8b79ad2008-03-03 01:35:41 +00001407 struct _DebugInfo* di,
jseward8b3131a2003-12-13 23:16:26 +00001408 UChar* dwarf1d, Int dwarf1d_sz,
1409 UChar* dwarf1l, Int dwarf1l_sz )
1410{
1411 UInt stmt_list;
1412 Bool stmt_list_found;
1413 Int die_offset, die_szb, at_offset;
1414 UShort die_kind, at_kind;
1415 UChar* at_base;
florian1636d332012-11-15 04:27:04 +00001416 HChar* src_filename;
jseward8b3131a2003-12-13 23:16:26 +00001417
1418 if (0)
1419 VG_(printf)("read_debuginfo_dwarf1 ( %p, %d, %p, %d )\n",
1420 dwarf1d, dwarf1d_sz, dwarf1l, dwarf1l_sz );
1421
1422 /* This loop scans the DIEs. */
1423 die_offset = 0;
1424 while (True) {
1425 if (die_offset >= dwarf1d_sz) break;
1426
tomb4dd5b42011-10-02 10:49:35 +00001427 die_szb = ML_(read_Int)(dwarf1d + die_offset);
1428 die_kind = ML_(read_UShort)(dwarf1d + die_offset + 4);
jseward8b3131a2003-12-13 23:16:26 +00001429
1430 /* We're only interested in compile_unit DIEs; ignore others. */
1431 if (die_kind != TAG_compile_unit) {
1432 die_offset += die_szb;
1433 continue;
1434 }
1435
1436 if (0)
1437 VG_(printf)("compile-unit DIE: offset %d, tag 0x%x, size %d\n",
1438 die_offset, (Int)die_kind, die_szb );
1439
1440 /* We've got a compile_unit DIE starting at (dwarf1d +
1441 die_offset+6). Try and find the AT_name and AT_stmt_list
1442 attributes. Then, finally, we can read the line number info
1443 for this source file. */
1444
1445 /* The next 3 are set as we find the relevant attrs. */
1446 src_filename = NULL;
1447 stmt_list_found = False;
1448 stmt_list = 0;
1449
1450 /* This loop scans the Attrs inside compile_unit DIEs. */
1451 at_base = dwarf1d + die_offset + 6;
1452 at_offset = 0;
1453 while (True) {
1454 if (at_offset >= die_szb-6) break;
1455
tomb4dd5b42011-10-02 10:49:35 +00001456 at_kind = ML_(read_UShort)(at_base + at_offset);
jseward8b3131a2003-12-13 23:16:26 +00001457 if (0) VG_(printf)("atoffset %d, attag 0x%x\n",
1458 at_offset, (Int)at_kind );
1459 at_offset += 2; /* step over the attribute itself */
1460 /* We have to examine the attribute to figure out its
1461 length. */
1462 switch (at_kind) {
1463 case AT_stmt_list:
1464 case AT_language:
1465 case AT_sibling:
1466 if (at_kind == AT_stmt_list) {
1467 stmt_list_found = True;
tomb4dd5b42011-10-02 10:49:35 +00001468 stmt_list = ML_(read_Int)(at_base+at_offset);
jseward8b3131a2003-12-13 23:16:26 +00001469 }
1470 at_offset += 4; break;
1471 case AT_high_pc:
1472 case AT_low_pc:
1473 at_offset += sizeof(void*); break;
1474 case AT_name:
1475 case AT_producer:
1476 case AT_comp_dir:
1477 /* Zero terminated string, step over it. */
1478 if (at_kind == AT_name)
florian1636d332012-11-15 04:27:04 +00001479 src_filename = (HChar *)(at_base + at_offset);
jseward8b3131a2003-12-13 23:16:26 +00001480 while (at_offset < die_szb-6 && at_base[at_offset] != 0)
1481 at_offset++;
1482 at_offset++;
1483 break;
1484 default:
1485 VG_(printf)("Unhandled DWARF-1 attribute 0x%x\n",
1486 (Int)at_kind );
1487 VG_(core_panic)("Unhandled DWARF-1 attribute");
1488 } /* switch (at_kind) */
1489 } /* looping over attributes */
1490
1491 /* So, did we find the required stuff for a line number table in
1492 this DIE? If yes, read it. */
1493 if (stmt_list_found /* there is a line number table */
1494 && src_filename != NULL /* we know the source filename */
1495 ) {
1496 /* Table starts:
1497 Length:
1498 4 bytes, includes the entire table
1499 Base address:
1500 unclear (4? 8?), assuming native pointer size here.
1501 Then a sequence of triples
1502 (source line number -- 32 bits
1503 source line column -- 16 bits
1504 address delta -- 32 bits)
1505 */
1506 Addr base;
1507 Int len;
florian1636d332012-11-15 04:27:04 +00001508 HChar* curr_filenm;
jseward8b3131a2003-12-13 23:16:26 +00001509 UChar* ptr;
1510 UInt prev_line, prev_delta;
1511
sewardjb8b79ad2008-03-03 01:35:41 +00001512 curr_filenm = ML_(addStr) ( di, src_filename, -1 );
jseward8b3131a2003-12-13 23:16:26 +00001513 prev_line = prev_delta = 0;
1514
1515 ptr = dwarf1l + stmt_list;
tomb4dd5b42011-10-02 10:49:35 +00001516 len = ML_(read_Int)(ptr); ptr += sizeof(Int);
tomba4ce2f2011-10-03 17:01:57 +00001517 base = ML_(read_Addr)(ptr); ptr += sizeof(void*);
jseward8b3131a2003-12-13 23:16:26 +00001518 len -= (sizeof(Int) + sizeof(void*));
1519 while (len > 0) {
1520 UInt line;
1521 UShort col;
1522 UInt delta;
tomb4dd5b42011-10-02 10:49:35 +00001523 line = ML_(read_UInt)(ptr); ptr += sizeof(UInt);
1524 col = ML_(read_UShort)(ptr); ptr += sizeof(UShort);
1525 delta = ML_(read_UInt)(ptr); ptr += sizeof(UInt);
jseward8b3131a2003-12-13 23:16:26 +00001526 if (0) VG_(printf)("line %d, col %d, delta %d\n",
1527 line, (Int)col, delta );
1528 len -= (sizeof(UInt) + sizeof(UShort) + sizeof(UInt));
1529
1530 if (delta > 0 && prev_line > 0) {
1531 if (0) VG_(printf) (" %d %d-%d\n",
1532 prev_line, prev_delta, delta-1);
sewardjb8b79ad2008-03-03 01:35:41 +00001533 ML_(addLineInfo) ( di, curr_filenm, NULL,
jseward8b3131a2003-12-13 23:16:26 +00001534 base + prev_delta, base + delta,
1535 prev_line, 0 );
1536 }
1537 prev_line = line;
1538 prev_delta = delta;
1539 }
1540 }
1541
1542 /* Move on the the next DIE. */
1543 die_offset += die_szb;
1544
1545 } /* Looping over DIEs */
1546
1547}
sewardj5d616df2013-07-02 08:07:15 +00001548#endif
jseward8b3131a2003-12-13 23:16:26 +00001549
sewardj5c638c22005-04-30 07:55:58 +00001550/*------------------------------------------------------------*/
1551/*--- Read call-frame info from an .eh_frame section ---*/
1552/*------------------------------------------------------------*/
1553
sewardj461d6c62007-02-23 10:10:02 +00001554/* Sources of info:
1555
1556 The DWARF3 spec, available from http://www.dwarfstd.org/Download.php
1557
1558 This describes how to read CFA data from .debug_frame sections.
1559 So as to maximise everybody's annoyance and confusion, .eh_frame
1560 sections are almost the same as .debug_frame sections, but differ
1561 in a few subtle and ill documented but important aspects.
1562
1563 Generic ELF Specification, sections 7.5 (DWARF Extensions) and 7.6
1564 (Exception Frames), available from
1565
1566 http://www.linux-foundation.org/spec/book/ELF-generic/ELF-generic.html
1567
1568 This really does describe .eh_frame, at least the aspects that
1569 differ from standard DWARF3. It's better than guessing, and
1570 (marginally) more fun than reading the gdb source code.
1571*/
1572
sewardj55022aa2005-05-03 16:05:00 +00001573/* Useful info ..
1574
1575 In general:
1576 gdb-6.3/gdb/dwarf2-frame.c
1577
1578 gdb-6.3/gdb/i386-tdep.c:
1579
1580 DWARF2/GCC uses the stack address *before* the function call as a
1581 frame's CFA. [jrs: I presume this means %esp before the call as
1582 the CFA].
1583
1584 JRS: on amd64, the dwarf register numbering is, as per
sewardjb8b79ad2008-03-03 01:35:41 +00001585 gdb-6.3/gdb/amd64-tdep.c and also amd64-abi-0.98.pdf:
sewardj55022aa2005-05-03 16:05:00 +00001586
1587 0 1 2 3 4 5 6 7
1588 RAX RDX RCX RBX RSI RDI RBP RSP
1589
1590 8 ... 15
1591 R8 ... R15
1592
1593 16 is the return address (RIP)
sewardj94ef4a42007-02-25 17:13:19 +00001594 "The table defines Return Address to have a register number,
1595 even though the address is stored in 0(%rsp) and not in a
1596 physical register."
sewardj55022aa2005-05-03 16:05:00 +00001597
sewardj94ef4a42007-02-25 17:13:19 +00001598 17 ... 24
1599 XMM0 ... XMM7
1600
1601 25 ... 32
1602 XMM8 ... XMM15
1603
1604 33 ... 40
1605 ST0 ... ST7
1606
1607 41 ... 48
1608 MM0 ... MM7
1609
1610 49 RFLAGS
1611 50,51,52,53,54,55 ES,CS,SS,DS,FS,GS
1612 58 FS.BASE (what's that?)
1613 59 GS.BASE (what's that?)
1614 62 TR (task register)
1615 63 LDTR (LDT register)
1616 64 MXCSR
1617 65 FCW (x87 control word)
1618 66 FSW (x86 status word)
sewardj55022aa2005-05-03 16:05:00 +00001619
1620 On x86 I cannot find any documentation. It _appears_ to be the
1621 actual instruction encoding, viz:
1622
1623 0 1 2 3 4 5 6 7
1624 EAX ECX EDX EBX ESP EBP ESI EDI
1625
1626 8 is the return address (EIP) */
1627
1628
sewardj1936f8b2006-11-16 12:21:52 +00001629/* Comments re DW_CFA_set_loc, 16 Nov 06.
1630
1631 JRS:
1632 Someone recently sent me a libcrypto.so.0.9.8 as distributed with
1633 Ubuntu of some flavour, compiled with gcc 4.1.2 on amd64. It
1634 causes V's CF reader to complain a lot:
1635
1636 >> --19976-- DWARF2 CFI reader: unhandled CFI instruction 0:24
1637 >> --19976-- DWARF2 CFI reader: unhandled CFI instruction 0:24
1638 >> --19976-- DWARF2 CFI reader: unhandled CFI instruction 0:24
1639 >> --19976-- DWARF2 CFI reader: unhandled CFI instruction 0:24
1640 >> --19976-- DWARF2 CFI reader: unhandled CFI instruction 0:48
1641 >> --19976-- DWARF2 CFI reader: unhandled CFI instruction 0:24
1642
1643 After chasing this around a bit it seems that the CF bytecode
1644 parser lost sync at a DW_CFA_set_loc, which has a single argument
1645 denoting an address.
1646
1647 As it stands that address is extracted by read_Addr(). On amd64
1648 that just fetches 8 bytes regardless of anything else.
1649
1650 read_encoded_Addr() is more sophisticated. This appears to take
1651 into account some kind of encoding flag. When I replace the uses
1652 of read_Addr by read_encoded_Addr for DW_CFA_set_loc, the
1653 complaints go away, there is no loss of sync, and the parsed CF
1654 instructions are the same as shown by readelf --debug-dump=frames.
1655
1656 So it seems a plausible fix. The problem is I looked in the DWARF3
1657 spec and completely failed to figure out whether or not the arg to
1658 DW_CFA_set_loc is supposed to be encoded in a way suitable for
1659 read_encoded_Addr, nor for that matter any description of what it
1660 is that read_encoded_Addr is really decoding.
1661
1662 TomH:
1663 The problem is that the encoding is not standard - the eh_frame
1664 section uses the same encoding as the dwarf_frame section except
1665 for a few small changes, and this is one of them. So this is not
1666 something the DWARF standard covers.
1667
1668 There is an augmentation string to indicate what is going on though
1669 so that programs can recognise it.
1670
1671 What we are doing seems to match what gdb 6.5 and libdwarf 20060614
1672 do though. I'm not sure about readelf though.
1673
1674 (later): Well dwarfdump barfs on it:
1675
1676 dwarfdump ERROR: dwarf_get_fde_info_for_reg:
1677 DW_DLE_DF_FRAME_DECODING_ERROR(193) (193)
1678
1679 I've looked at binutils as well now, and the code in readelf agrees
1680 with your patch - ie it treats set_loc as having an encoded address
1681 if there is a zR augmentation indicating an encoding.
1682
1683 Quite why gdb and libdwarf don't understand this is an interesting
1684 question...
1685
1686 Final outcome: all uses of read_Addr were replaced by
1687 read_encoded_Addr. A new type AddressDecodingInfo was added to
1688 make it relatively clean to plumb through the extra info needed by
1689 read_encoded_Addr.
1690*/
1691
sewardj3891dd42007-01-12 19:03:19 +00001692/* More badness re address encoding, 12 Jan 07.
1693
1694 Most gcc provided CIEs have a "zR" augmentation, which means they
1695 supply their own address encoding, and that works fine. However,
1696 some icc9 supplied CIEs have no augmentation, which means they use
1697 the default_Addr_encoding(). That says to use a machine-word sized
1698 value, literally unmodified.
1699
1700 Since .so's are, in general, relocated when loaded, having absolute
1701 addresses in the CFI data makes no sense when read_encoded_Addr is
1702 used to find the initial location for a FDE. The resulting saga:
1703
1704 TomH:
1705 > I'm chasing a stack backtrace failure for an amd64 .so which was
1706 > created I believe by icc 9.1. After a while I wound up looking at
1707 > this: (readdwarf.c)
1708 >
1709 > 5083 tom static UChar default_Addr_encoding ( void )
1710 > 3584 tom {
1711 > 3584 tom switch (sizeof(Addr)) {
1712 > 3584 tom case 4: return DW_EH_PE_udata4;
1713 > 3584 tom case 8: return DW_EH_PE_udata8;
1714 > 3584 tom default: vg_assert(0);
1715 > 3584 tom }
1716 > 3584 tom }
1717 >
1718 > If a CIE does not have an "augmentation string" (typically "zR") then
1719 > addresses are decoded as described by default_Addr_encoding. If there
1720 > is an 'R' in the augmentation string then the encoding to use
1721 > is specified by the CIE itself, which works fine with GCC compiled code
1722 > since that always appears to specify zR.
1723
1724 Correct.
1725
1726 > Problem is this .so has no augmentation string and so uses the
1727 > default encoding, viz DW_EH_PE_udata8. That appears to mean
1728 > "read a 64 bit number" and use that as-is (for the starting value
1729 > of the program counter when running the CFA program).
1730
1731 Strictly speaking the default is DW_EH_PE_absptr, but that amounts
1732 to either udata4 or udata8 depending on the platform's pointer size
1733 which is a shortcut I used.
1734
1735 > For this .so that gives nonsense (very small) PCs which are later
1736 > rejected by the sanity check which ensures PC ranges fall inside
1737 > the mapped text segment. It seems like the .so expects to have the
1738 > start VMA of the text segment added on. This would correspond to
1739 >
1740 > static UChar default_Addr_encoding ( void )
1741 > {
1742 > switch (sizeof(Addr)) {
1743 > case 4: return DW_EH_PE_textrel + DW_EH_PE_udata4;
1744 > case 8: return DW_EH_PE_textrel + DW_EH_PE_udata8;
1745 > default: vg_assert(0);
1746 > }
1747 > }
1748
1749 The problem you're seeing is that you have absolute pointers inside
1750 a shared library, which obviously makes little sense on the face of
1751 things as how would the linker know where the library will be
1752 loaded?
1753
1754 The answer of course is that it doesn't, so if it points absolute
1755 pointers in the frame unwind data is has to include relocations for
1756 them, and I'm betting that if you look at the relocations in the
1757 library you will there are some for that data.
1758
1759 That is fine of course when ld.so maps the library - it will
1760 relocate the eh_frame data as it maps it (or prelinking will
1761 already have done so) and when the g++ exception code kicks in and
1762 unwinds the stack it will see relocated data.
1763
1764 We of course are mapping the section from the ELF file ourselves
1765 and are not applying the relocations, hence the problem you are
1766 seeing.
1767
1768 Strictly speaking we should apply the relocations but the cheap
1769 solution is essentially to do what you've done - strictly speaking
1770 you should adjust by the difference between the address the library
1771 was linked for and the address it has been loaded at, but a shared
1772 library will normally be linked for address zero I believe. It's
1773 possible that prelinking might change that though?
1774
1775 JRS:
1776 That all syncs with what I am seeing.
1777
1778 So what I am inclined to do is:
1779
1780 - Leave default_Addr_encoding as it is
1781
1782 - Change read_encoded_Addr's handling of "case DW_EH_PE_absptr" so
1783 it sets base to, as you say, the difference between the address
1784 the library was linked for and the address it has been loaded at
1785 (== the SegInfo's text_bias)
1786
1787 Does that sound sane? I think it should even handle the prelinked
1788 case.
1789
1790 (JRS, later)
1791
1792 Hmm. Plausible as it sounds, it doesn't work. It now produces
1793 bogus backtraces for locations inside the (statically linked)
1794 memcheck executable.
1795
1796 Besides, there are a couple of other places where read_encoded_Addr
1797 is used -- one of which is used to establish the length of the
1798 address range covered by the current FDE:
1799
1800 fde_arange = read_encoded_Addr(&nbytes, &adi, data);
1801
1802 and it doesn't seem to make any sense for read_encoded_Addr to add
1803 on the text segment bias in that context. The DWARF3 spec says
1804 that both the initial_location and address_range (length) fields
1805 are encoded the same way ("target address"), so it is unclear at
1806 what stage in the process it would be appropriate to relocate the
1807 former but not the latter.
1808
1809 One unprincipled kludge that does work is the following: just
1810 before handing one of the address range fragments off to
1811 ML_(addDiCfSI) for permanent storage, check its start address. If
1812 that is very low (less than 2 M), and is far below the mapped text
1813 segment, and adding the text bias would move the fragment entirely
1814 inside the mapped text segment, then do so. A kind of kludged
1815 last-minute relocation, if you like.
1816
1817 12 Jan 07: committing said kludge (see kludge_then_addDiCfSI). If
1818 the situation clarifies, it can easily enough be backed out and
1819 replaced by a better fix.
1820*/
1821
sewardj55022aa2005-05-03 16:05:00 +00001822/* --------------- Decls --------------- */
sewardj35165532005-04-30 18:47:48 +00001823
sewardje0707a62005-05-02 12:25:13 +00001824#if defined(VGP_x86_linux)
njn14b278b2005-05-15 18:51:47 +00001825# define FP_REG 5
1826# define SP_REG 4
1827# define RA_REG_DEFAULT 8
sewardje0707a62005-05-02 12:25:13 +00001828#elif defined(VGP_amd64_linux)
njn14b278b2005-05-15 18:51:47 +00001829# define FP_REG 6
1830# define SP_REG 7
1831# define RA_REG_DEFAULT 16
cerion85665ca2005-06-20 15:51:07 +00001832#elif defined(VGP_ppc32_linux)
1833# define FP_REG 1
1834# define SP_REG 1
tom3c9cf342009-11-12 13:28:34 +00001835# define RA_REG_DEFAULT 65
sewardj2c48c7b2005-11-29 13:05:56 +00001836#elif defined(VGP_ppc64_linux)
1837# define FP_REG 1
1838# define SP_REG 1
tom3c9cf342009-11-12 13:28:34 +00001839# define RA_REG_DEFAULT 65
sewardj3026f712010-01-01 18:46:41 +00001840#elif defined(VGP_arm_linux)
1841# define FP_REG 12
1842# define SP_REG 13
sewardj821283b2014-01-13 00:21:09 +00001843# define RA_REG_DEFAULT 14
sewardjf0c12502014-01-12 12:54:00 +00001844#elif defined(VGP_arm64_linux)
sewardj821283b2014-01-13 00:21:09 +00001845# define FP_REG 29
1846# define SP_REG 31
1847# define RA_REG_DEFAULT 30
njnf76d27a2009-05-28 01:53:07 +00001848#elif defined(VGP_x86_darwin)
1849# define FP_REG 5
1850# define SP_REG 4
1851# define RA_REG_DEFAULT 8
1852#elif defined(VGP_amd64_darwin)
1853# define FP_REG 6
1854# define SP_REG 7
1855# define RA_REG_DEFAULT 16
sewardjb5b87402011-03-07 16:05:35 +00001856#elif defined(VGP_s390x_linux)
1857# define FP_REG 11 // sometimes s390 has a frame pointer in r11
1858# define SP_REG 15 // stack is always r15
1859# define RA_REG_DEFAULT 14 // the return address is in r14
sewardj5db15402012-06-07 09:13:21 +00001860#elif defined(VGP_mips32_linux)
1861# define FP_REG 30
1862# define SP_REG 29
1863# define RA_REG_DEFAULT 31
petarj4df0bfc2013-02-27 23:17:33 +00001864#elif defined(VGP_mips64_linux)
1865# define FP_REG 30
1866# define SP_REG 29
1867# define RA_REG_DEFAULT 31
njn14b278b2005-05-15 18:51:47 +00001868#else
sewardjb8b79ad2008-03-03 01:35:41 +00001869# error "Unknown platform"
tom2fd38902005-05-01 15:14:01 +00001870#endif
sewardj35165532005-04-30 18:47:48 +00001871
sewardj87a1fa52012-02-20 15:33:24 +00001872/* The number of regs we are prepared to unwind. The number for
1873 arm-linux (320) seems ludicrously high, but the ARM IHI 0040A page
1874 7 (DWARF for the ARM Architecture) specifies that values up to 320
1875 might exist, for Neon/VFP-v3. */
sewardj5db15402012-06-07 09:13:21 +00001876#if defined(VGP_ppc32_linux) || defined(VGP_ppc64_linux) \
petarj4df0bfc2013-02-27 23:17:33 +00001877 || defined(VGP_mips32_linux) || defined(VGP_mips64_linux)
tom3c9cf342009-11-12 13:28:34 +00001878# define N_CFI_REGS 72
sewardj87a1fa52012-02-20 15:33:24 +00001879#elif defined(VGP_arm_linux)
1880# define N_CFI_REGS 320
sewardj821283b2014-01-13 00:21:09 +00001881#elif defined(VGP_arm64_linux)
1882# define N_CFI_REGS 128
tom3c9cf342009-11-12 13:28:34 +00001883#else
1884# define N_CFI_REGS 20
1885#endif
sewardj5c638c22005-04-30 07:55:58 +00001886
1887/* Instructions for the automaton */
1888enum dwarf_cfa_primary_ops
1889 {
1890 DW_CFA_use_secondary = 0,
1891 DW_CFA_advance_loc = 1,
1892 DW_CFA_offset = 2,
1893 DW_CFA_restore = 3
1894 };
1895
1896enum dwarf_cfa_secondary_ops
1897 {
sewardj325ec872005-05-01 20:24:06 +00001898 DW_CFA_nop = 0x00,
1899 DW_CFA_set_loc = 0x01,
1900 DW_CFA_advance_loc1 = 0x02,
1901 DW_CFA_advance_loc2 = 0x03,
1902 DW_CFA_advance_loc4 = 0x04,
1903 DW_CFA_offset_extended = 0x05,
1904 DW_CFA_restore_extended = 0x06,
1905 DW_CFA_undefined = 0x07,
1906 DW_CFA_same_value = 0x08,
1907 DW_CFA_register = 0x09,
1908 DW_CFA_remember_state = 0x0a,
1909 DW_CFA_restore_state = 0x0b,
1910 DW_CFA_def_cfa = 0x0c,
1911 DW_CFA_def_cfa_register = 0x0d,
1912 DW_CFA_def_cfa_offset = 0x0e,
sewardj1e601fe2005-05-16 11:48:34 +00001913 DW_CFA_def_cfa_expression = 0x0f, /* DWARF3 only */
1914 DW_CFA_expression = 0x10, /* DWARF3 only */
sewardj325ec872005-05-01 20:24:06 +00001915 DW_CFA_offset_extended_sf = 0x11, /* DWARF3 only */
sewardjd69222c2006-04-08 16:22:53 +00001916 DW_CFA_def_cfa_sf = 0x12, /* DWARF3 only */
sewardjab30d202005-05-15 17:14:28 +00001917 DW_CFA_def_cfa_offset_sf = 0x13, /* DWARF3 only */
sewardjd69222c2006-04-08 16:22:53 +00001918 DW_CFA_val_offset = 0x14, /* DWARF3 only */
1919 DW_CFA_val_offset_sf = 0x15, /* DWARF3 only */
1920 DW_CFA_val_expression = 0x16, /* DWARF3 only */
sewardj325ec872005-05-01 20:24:06 +00001921 DW_CFA_lo_user = 0x1c,
sewardj0cd71772005-05-16 18:25:09 +00001922 DW_CFA_GNU_window_save = 0x2d, /* GNU extension */
1923 DW_CFA_GNU_args_size = 0x2e, /* GNU extension */
sewardjd69222c2006-04-08 16:22:53 +00001924 DW_CFA_GNU_negative_offset_extended = 0x2f, /* GNU extension */
sewardj325ec872005-05-01 20:24:06 +00001925 DW_CFA_hi_user = 0x3f
sewardj5c638c22005-04-30 07:55:58 +00001926 };
1927
tom2fd38902005-05-01 15:14:01 +00001928#define DW_EH_PE_absptr 0x00
1929#define DW_EH_PE_omit 0xff
1930
1931#define DW_EH_PE_uleb128 0x01
1932#define DW_EH_PE_udata2 0x02
1933#define DW_EH_PE_udata4 0x03
1934#define DW_EH_PE_udata8 0x04
1935#define DW_EH_PE_sleb128 0x09
1936#define DW_EH_PE_sdata2 0x0A
1937#define DW_EH_PE_sdata4 0x0B
1938#define DW_EH_PE_sdata8 0x0C
1939#define DW_EH_PE_signed 0x08
1940
1941#define DW_EH_PE_pcrel 0x10
1942#define DW_EH_PE_textrel 0x20
1943#define DW_EH_PE_datarel 0x30
1944#define DW_EH_PE_funcrel 0x40
1945#define DW_EH_PE_aligned 0x50
1946
1947#define DW_EH_PE_indirect 0x80
1948
sewardj5c638c22005-04-30 07:55:58 +00001949
sewardj55022aa2005-05-03 16:05:00 +00001950/* RegRule and UnwindContext are used temporarily to do the unwinding.
sewardj726baec2005-06-09 19:27:25 +00001951 The result is then summarised into a sequence of CfiSIs, if
1952 possible. UnwindContext effectively holds the state of the
1953 abstract machine whilst it is running.
sewardj72427fa2007-02-27 16:52:23 +00001954
1955 The CFA can either be a signed offset from a register,
1956 or an expression:
1957
1958 CFA = cfa_reg + cfa_off when UnwindContext.cfa_is_regoff==True
1959 | [[ cfa_expr_id ]]
1960
1961 When .cfa_is_regoff == True, cfa_expr_id must be zero
1962 When .cfa_is_regoff == False, cfa_reg must be zero
1963 and cfa_off must be zero
1964
1965 RegRule describes, for each register, how to get its
1966 value in the previous frame, where 'cfa' denotes the cfa
1967 for the frame as a whole:
1968
1969 RegRule = RR_Undef -- undefined
1970 | RR_Same -- same as in previous frame
1971 | RR_CFAOff arg -- is at * ( cfa + arg )
1972 | RR_CFAValOff arg -- is ( cfa + arg )
1973 | RR_Reg arg -- is in register 'arg'
1974 | RR_Expr arg -- is at * [[ arg ]]
1975 | RR_ValExpr arg -- is [[ arg ]]
1976 | RR_Arch -- dunno
1977
sewardj19dc88f2007-02-28 01:46:30 +00001978 Note that RR_Expr is redundant since the same can be represented
1979 using RR_ValExpr with an explicit dereference (CfiExpr_Deref) at
1980 the outermost level.
1981
sewardj72427fa2007-02-27 16:52:23 +00001982 All expressions are stored in exprs in the containing
1983 UnwindContext. Since the UnwindContext gets reinitialised for each
1984 new FDE, summarise_context needs to copy out any expressions it
1985 wants to keep into the cfsi_exprs field of the containing SegInfo.
sewardj726baec2005-06-09 19:27:25 +00001986*/
sewardj5c638c22005-04-30 07:55:58 +00001987typedef
1988 struct {
sewardj72427fa2007-02-27 16:52:23 +00001989 enum { RR_Undef, RR_Same, RR_CFAOff, RR_CFAValOff,
sewardj19dc88f2007-02-28 01:46:30 +00001990 RR_Reg, /*RR_Expr,*/ RR_ValExpr, RR_Arch } tag;
sewardj72427fa2007-02-27 16:52:23 +00001991 /* meaning: int offset for CFAoff/CFAValOff
1992 reg # for Reg
1993 expr index for Expr/ValExpr */
1994 Int arg;
sewardj5c638c22005-04-30 07:55:58 +00001995 }
1996 RegRule;
1997
sewardj72427fa2007-02-27 16:52:23 +00001998static void ppRegRule ( XArray* exprs, RegRule* rrule )
sewardj55022aa2005-05-03 16:05:00 +00001999{
sewardj72427fa2007-02-27 16:52:23 +00002000 vg_assert(exprs);
2001 switch (rrule->tag) {
2002 case RR_Undef: VG_(printf)("u "); break;
2003 case RR_Same: VG_(printf)("s "); break;
2004 case RR_CFAOff: VG_(printf)("c%d ", rrule->arg); break;
2005 case RR_CFAValOff: VG_(printf)("v%d ", rrule->arg); break;
2006 case RR_Reg: VG_(printf)("r%d ", rrule->arg); break;
sewardj72427fa2007-02-27 16:52:23 +00002007 case RR_ValExpr: VG_(printf)("ve{");
2008 ML_(ppCfiExpr)( exprs, rrule->arg );
2009 VG_(printf)("} ");
2010 break;
2011 case RR_Arch: VG_(printf)("a "); break;
2012 default: VG_(core_panic)("ppRegRule");
sewardj55022aa2005-05-03 16:05:00 +00002013 }
2014}
2015
2016
sewardj3d026b12009-05-21 15:33:36 +00002017/* Size of the stack of register unwind rules. This is only
2018 exceedingly rarely used, so a stack of size 1 should actually work
2019 with almost all compiler-generated CFA. */
2020#define N_RR_STACK 4
2021
sewardj5c638c22005-04-30 07:55:58 +00002022typedef
2023 struct {
sewardj5410cfd2005-05-13 12:17:33 +00002024 /* Read-only fields (set by the CIE) */
sewardj72427fa2007-02-27 16:52:23 +00002025 Int code_a_f;
2026 Int data_a_f;
2027 Addr initloc;
2028 Int ra_reg;
sewardj5c638c22005-04-30 07:55:58 +00002029 /* The rest of these fields can be modifed by
2030 run_CF_instruction. */
2031 /* The LOC entry */
sewardj72427fa2007-02-27 16:52:23 +00002032 Addr loc;
sewardjde1b03d2009-08-03 13:47:04 +00002033 /* We need a stack of these in order to handle
sewardj3d026b12009-05-21 15:33:36 +00002034 DW_CFA_{remember,restore}_state. */
sewardjde1b03d2009-08-03 13:47:04 +00002035 struct UnwindContextState {
2036 /* The CFA entry. This can be either reg+/-offset or an expr. */
2037 Bool cfa_is_regoff; /* True=>is reg+offset; False=>is expr */
2038 Int cfa_reg;
2039 Int cfa_off; /* in bytes */
2040 Int cfa_expr_ix; /* index into cfa_exprs */
2041 /* Register unwind rules. */
2042 RegRule reg[N_CFI_REGS];
2043 }
2044 state[N_RR_STACK];
2045 Int state_sp; /* 0 <= state_sp < N_RR_STACK; points at the
2046 currently-in-use rule set. */
sewardj72427fa2007-02-27 16:52:23 +00002047 /* array of CfiExpr, shared by reg[] and cfa_expr_ix */
2048 XArray* exprs;
sewardj5c638c22005-04-30 07:55:58 +00002049 }
2050 UnwindContext;
2051
sewardj55022aa2005-05-03 16:05:00 +00002052static void ppUnwindContext ( UnwindContext* ctx )
2053{
sewardj3d026b12009-05-21 15:33:36 +00002054 Int j, i;
sewardj55022aa2005-05-03 16:05:00 +00002055 VG_(printf)("0x%llx: ", (ULong)ctx->loc);
sewardjde1b03d2009-08-03 13:47:04 +00002056 for (j = 0; j <= ctx->state_sp; j++) {
2057 struct UnwindContextState* ctxs = &ctx->state[j];
sewardj3d026b12009-05-21 15:33:36 +00002058 VG_(printf)("%s[%d]={ ", j > 0 ? " " : "", j);
sewardjde1b03d2009-08-03 13:47:04 +00002059 if (ctxs->cfa_is_regoff) {
2060 VG_(printf)("%d(r%d) ", ctxs->cfa_off, ctxs->cfa_reg);
2061 } else {
2062 vg_assert(ctx->exprs);
2063 VG_(printf)("{");
2064 ML_(ppCfiExpr)( ctx->exprs, ctxs->cfa_expr_ix );
2065 VG_(printf)("} ");
2066 }
2067 VG_(printf)("{ ");
sewardj3d026b12009-05-21 15:33:36 +00002068 for (i = 0; i < N_CFI_REGS; i++)
sewardjde1b03d2009-08-03 13:47:04 +00002069 ppRegRule(ctx->exprs, &ctxs->reg[i]);
sewardj3d026b12009-05-21 15:33:36 +00002070 VG_(printf)("}");
2071 }
sewardj55022aa2005-05-03 16:05:00 +00002072 VG_(printf)("\n");
2073}
2074
sewardj5c638c22005-04-30 07:55:58 +00002075static void initUnwindContext ( /*OUT*/UnwindContext* ctx )
2076{
sewardj3d026b12009-05-21 15:33:36 +00002077 Int j, i;
2078 VG_(memset)(ctx, 0, sizeof(*ctx));
sewardjde1b03d2009-08-03 13:47:04 +00002079 /* ctx->code_a_f = 0;
sewardj72427fa2007-02-27 16:52:23 +00002080 ctx->data_a_f = 0;
sewardjde1b03d2009-08-03 13:47:04 +00002081 ctx->initloc = 0; */
sewardj72427fa2007-02-27 16:52:23 +00002082 ctx->ra_reg = RA_REG_DEFAULT;
sewardjde1b03d2009-08-03 13:47:04 +00002083 /* ctx->loc = 0;
sewardj72427fa2007-02-27 16:52:23 +00002084 ctx->exprs = NULL;
sewardjde1b03d2009-08-03 13:47:04 +00002085 ctx->state_sp = 0; */
sewardj3d026b12009-05-21 15:33:36 +00002086 for (j = 0; j < N_RR_STACK; j++) {
sewardjde1b03d2009-08-03 13:47:04 +00002087 ctx->state[j].cfa_is_regoff = True;
2088 /* ctx->state[j].cfa_reg = 0;
2089 ctx->state[j].cfa_off = 0;
2090 ctx->state[j].cfa_expr_ix = 0; */
sewardj3d026b12009-05-21 15:33:36 +00002091 for (i = 0; i < N_CFI_REGS; i++) {
sewardjde1b03d2009-08-03 13:47:04 +00002092 if (RR_Undef != 0)
2093 ctx->state[j].reg[i].tag = RR_Undef;
2094 /* ctx->state[j].reg[i].arg = 0; */
sewardj3d026b12009-05-21 15:33:36 +00002095 }
sewardjd2aac892010-01-01 20:56:13 +00002096# if defined(VGA_arm)
2097 /* All callee-saved registers (or at least the ones we are
2098 summarising for) should start out as RR_Same, on ARM. */
2099 ctx->state[j].reg[11].tag = RR_Same;
2100 /* ctx->state[j].reg[13].tag = RR_Same; */
2101 ctx->state[j].reg[14].tag = RR_Same;
2102 ctx->state[j].reg[12].tag = RR_Same;
sewardjfa5ce562010-09-23 22:05:59 +00002103 ctx->state[j].reg[7].tag = RR_Same;
sewardjd2aac892010-01-01 20:56:13 +00002104 /* this can't be right though: R12 (IP) isn't callee saved. */
sewardj821283b2014-01-13 00:21:09 +00002105# elif defined(VGA_arm64)
2106 /* Callee-saved registers (that we are interested in) should
2107 start out as RR_Same. */
2108 ctx->state[j].reg[29/*FP*/].tag = RR_Same;
2109 ctx->state[j].reg[30/*LR*/].tag = RR_Same;
sewardjd2aac892010-01-01 20:56:13 +00002110# endif
sewardj5c638c22005-04-30 07:55:58 +00002111 }
2112}
2113
sewardj35165532005-04-30 18:47:48 +00002114
sewardjc6d3f6f2007-01-11 19:42:11 +00002115/* A structure which holds information needed by read_encoded_Addr().
sewardj1936f8b2006-11-16 12:21:52 +00002116*/
2117typedef
2118 struct {
sewardj5d616df2013-07-02 08:07:15 +00002119 UChar encoding;
2120 DiCursor ehframe_image;
2121 Addr ehframe_avma;
2122 Addr text_bias;
sewardj1936f8b2006-11-16 12:21:52 +00002123 }
2124 AddressDecodingInfo;
2125
2126
njn9ce110d2005-05-16 00:04:02 +00002127/* ------------ Deal with summary-info records ------------ */
2128
sewardjeadcd862006-04-04 15:12:44 +00002129static void initCfiSI ( DiCfSI* si )
njn9ce110d2005-05-16 00:04:02 +00002130{
sewardj821283b2014-01-13 00:21:09 +00002131 VG_(bzero_inline)(si, sizeof(*si));
njn9ce110d2005-05-16 00:04:02 +00002132}
2133
2134
sewardj55022aa2005-05-03 16:05:00 +00002135/* --------------- Summarisation --------------- */
sewardj35165532005-04-30 18:47:48 +00002136
sewardj72427fa2007-02-27 16:52:23 +00002137/* Forward */
2138static
2139Int copy_convert_CfiExpr_tree ( XArray* dst,
2140 UnwindContext* srcuc,
2141 Int nd );
2142
sewardj35165532005-04-30 18:47:48 +00002143/* Summarise ctx into si, if possible. Returns True if successful.
2144 This is taken to be just after ctx's loc advances; hence the
sewardj8eb41322005-05-01 23:50:08 +00002145 summary is up to but not including the current loc. This works
2146 on both x86 and amd64.
sewardj35165532005-04-30 18:47:48 +00002147*/
sewardjeadcd862006-04-04 15:12:44 +00002148static Bool summarise_context( /*OUT*/DiCfSI* si,
tom2fd38902005-05-01 15:14:01 +00002149 Addr loc_start,
sewardjf767d962007-02-12 17:47:14 +00002150 UnwindContext* ctx,
sewardjb8b79ad2008-03-03 01:35:41 +00002151 struct _DebugInfo* debuginfo )
sewardj35165532005-04-30 18:47:48 +00002152{
sewardj8eb41322005-05-01 23:50:08 +00002153 Int why = 0;
sewardjde1b03d2009-08-03 13:47:04 +00002154 struct UnwindContextState* ctxs;
sewardj35165532005-04-30 18:47:48 +00002155 initCfiSI(si);
2156
sewardjde1b03d2009-08-03 13:47:04 +00002157 /* Guard against obviously stupid settings of the reg-rule stack
2158 pointer. */
2159 if (ctx->state_sp < 0) { why = 8; goto failed; }
2160 if (ctx->state_sp >= N_RR_STACK) { why = 9; goto failed; }
2161 ctxs = &ctx->state[ctx->state_sp];
2162
sewardj3026f712010-01-01 18:46:41 +00002163 /* First, summarise the method for generating the CFA */
sewardjde1b03d2009-08-03 13:47:04 +00002164 if (!ctxs->cfa_is_regoff) {
sewardj7888e222007-02-28 13:03:27 +00002165 /* it was set by DW_CFA_def_cfa_expression; try to convert */
2166 XArray *src, *dst;
2167 Int conv;
2168 src = ctx->exprs;
sewardjb8b79ad2008-03-03 01:35:41 +00002169 dst = debuginfo->cfsi_exprs;
sewardj7888e222007-02-28 13:03:27 +00002170 if (src && (VG_(sizeXA)(src) > 0) && (!dst)) {
sewardj9c606bd2008-09-18 18:12:50 +00002171 dst = VG_(newXA)( ML_(dinfo_zalloc), "di.ccCt.1", ML_(dinfo_free),
sewardj7888e222007-02-28 13:03:27 +00002172 sizeof(CfiExpr) );
2173 vg_assert(dst);
sewardjb8b79ad2008-03-03 01:35:41 +00002174 debuginfo->cfsi_exprs = dst;
sewardj7888e222007-02-28 13:03:27 +00002175 }
2176 conv = copy_convert_CfiExpr_tree
sewardjde1b03d2009-08-03 13:47:04 +00002177 ( dst, ctx, ctxs->cfa_expr_ix );
sewardj7888e222007-02-28 13:03:27 +00002178 vg_assert(conv >= -1);
2179 if (conv == -1) { why = 6; goto failed; }
2180 si->cfa_how = CFIC_EXPR;
2181 si->cfa_off = conv;
sewardjb8b79ad2008-03-03 01:35:41 +00002182 if (0 && debuginfo->ddump_frames)
sewardj7888e222007-02-28 13:03:27 +00002183 ML_(ppCfiExpr)(dst, conv);
sewardj3026f712010-01-01 18:46:41 +00002184 }
2185 else
sewardjde1b03d2009-08-03 13:47:04 +00002186 if (ctxs->cfa_is_regoff && ctxs->cfa_reg == SP_REG) {
sewardjde1b03d2009-08-03 13:47:04 +00002187 si->cfa_off = ctxs->cfa_off;
sewardj5db15402012-06-07 09:13:21 +00002188# if defined(VGA_x86) || defined(VGA_amd64) || defined(VGA_s390x) \
petarj4df0bfc2013-02-27 23:17:33 +00002189 || defined(VGA_mips32) || defined(VGA_mips64)
sewardj3026f712010-01-01 18:46:41 +00002190 si->cfa_how = CFIC_IA_SPREL;
2191# elif defined(VGA_arm)
2192 si->cfa_how = CFIC_ARM_R13REL;
sewardjf0c12502014-01-12 12:54:00 +00002193# elif defined(VGA_arm64)
sewardj821283b2014-01-13 00:21:09 +00002194 si->cfa_how = CFIC_ARM64_SPREL;
sewardj3026f712010-01-01 18:46:41 +00002195# else
2196 si->cfa_how = 0; /* invalid */
2197# endif
2198 }
2199 else
sewardjde1b03d2009-08-03 13:47:04 +00002200 if (ctxs->cfa_is_regoff && ctxs->cfa_reg == FP_REG) {
sewardjde1b03d2009-08-03 13:47:04 +00002201 si->cfa_off = ctxs->cfa_off;
sewardj5db15402012-06-07 09:13:21 +00002202# if defined(VGA_x86) || defined(VGA_amd64) || defined(VGA_s390x) \
petarj4df0bfc2013-02-27 23:17:33 +00002203 || defined(VGA_mips32) || defined(VGA_mips64)
sewardj3026f712010-01-01 18:46:41 +00002204 si->cfa_how = CFIC_IA_BPREL;
2205# elif defined(VGA_arm)
2206 si->cfa_how = CFIC_ARM_R12REL;
sewardj821283b2014-01-13 00:21:09 +00002207# elif defined(VGA_arm64)
2208 si->cfa_how = CFIC_ARM64_X29REL;
sewardj3026f712010-01-01 18:46:41 +00002209# else
2210 si->cfa_how = 0; /* invalid */
2211# endif
2212 }
2213# if defined(VGA_arm)
2214 else
2215 if (ctxs->cfa_is_regoff && ctxs->cfa_reg == 11/*??_REG*/) {
2216 si->cfa_how = CFIC_ARM_R11REL;
2217 si->cfa_off = ctxs->cfa_off;
2218 }
sewardjfa5ce562010-09-23 22:05:59 +00002219 else
2220 if (ctxs->cfa_is_regoff && ctxs->cfa_reg == 7/*??_REG*/) {
2221 si->cfa_how = CFIC_ARM_R7REL;
2222 si->cfa_off = ctxs->cfa_off;
2223 }
sewardjf0c12502014-01-12 12:54:00 +00002224# elif defined(VGA_arm64)
sewardj821283b2014-01-13 00:21:09 +00002225 // do we need any arm64 specifics here?
sewardj3026f712010-01-01 18:46:41 +00002226# endif
2227 else {
sewardj8eb41322005-05-01 23:50:08 +00002228 why = 1;
sewardj35165532005-04-30 18:47:48 +00002229 goto failed;
sewardj5c638c22005-04-30 07:55:58 +00002230 }
sewardj35165532005-04-30 18:47:48 +00002231
sewardj72427fa2007-02-27 16:52:23 +00002232# define SUMMARISE_HOW(_how, _off, _ctxreg) \
2233 switch (_ctxreg.tag) { \
2234 case RR_Undef: \
2235 _how = CFIR_UNKNOWN; _off = 0; break; \
2236 case RR_Same: \
2237 _how = CFIR_SAME; _off = 0; break; \
2238 case RR_CFAOff: \
2239 _how = CFIR_MEMCFAREL; _off = _ctxreg.arg; break; \
2240 case RR_CFAValOff: \
2241 _how = CFIR_CFAREL; _off = _ctxreg.arg; break; \
2242 case RR_ValExpr: { \
2243 XArray *src, *dst; \
2244 Int conv; \
2245 src = ctx->exprs; \
sewardjb8b79ad2008-03-03 01:35:41 +00002246 dst = debuginfo->cfsi_exprs; \
sewardj72427fa2007-02-27 16:52:23 +00002247 if (src && (VG_(sizeXA)(src) > 0) && (!dst)) { \
sewardjb8b79ad2008-03-03 01:35:41 +00002248 dst = VG_(newXA)( ML_(dinfo_zalloc), \
sewardj9c606bd2008-09-18 18:12:50 +00002249 "di.ccCt.2", \
sewardjb8b79ad2008-03-03 01:35:41 +00002250 ML_(dinfo_free), \
sewardj72427fa2007-02-27 16:52:23 +00002251 sizeof(CfiExpr) ); \
2252 vg_assert(dst); \
sewardjb8b79ad2008-03-03 01:35:41 +00002253 debuginfo->cfsi_exprs = dst; \
sewardj72427fa2007-02-27 16:52:23 +00002254 } \
2255 conv = copy_convert_CfiExpr_tree \
2256 ( dst, ctx, _ctxreg.arg ); \
2257 vg_assert(conv >= -1); \
2258 if (conv == -1) { why = 7; goto failed; } \
2259 _how = CFIR_EXPR; \
2260 _off = conv; \
sewardjb8b79ad2008-03-03 01:35:41 +00002261 if (0 && debuginfo->ddump_frames) \
sewardj72427fa2007-02-27 16:52:23 +00002262 ML_(ppCfiExpr)(dst, conv); \
2263 break; \
2264 } \
2265 default: \
2266 why = 2; goto failed; /* otherwise give up */ \
sewardj35165532005-04-30 18:47:48 +00002267 }
2268
sewardjf0c12502014-01-12 12:54:00 +00002269
sewardj3026f712010-01-01 18:46:41 +00002270# if defined(VGA_x86) || defined(VGA_amd64)
2271
2272 /* --- entire tail of this fn specialised for x86/amd64 --- */
2273
sewardj3d026b12009-05-21 15:33:36 +00002274 SUMMARISE_HOW(si->ra_how, si->ra_off,
sewardjde1b03d2009-08-03 13:47:04 +00002275 ctxs->reg[ctx->ra_reg] );
sewardj9365e3f2010-01-01 19:55:17 +00002276 SUMMARISE_HOW(si->bp_how, si->bp_off,
sewardjde1b03d2009-08-03 13:47:04 +00002277 ctxs->reg[FP_REG] );
sewardj35165532005-04-30 18:47:48 +00002278
sewardj8eb41322005-05-01 23:50:08 +00002279 /* on x86/amd64, it seems the old %{e,r}sp value before the call is
2280 always the same as the CFA. Therefore ... */
sewardj35165532005-04-30 18:47:48 +00002281 si->sp_how = CFIR_CFAREL;
2282 si->sp_off = 0;
2283
sewardj8eb41322005-05-01 23:50:08 +00002284 /* also, gcc says "Undef" for %{e,r}bp when it is unchanged. So
2285 .. */
sewardjde1b03d2009-08-03 13:47:04 +00002286 if (ctxs->reg[FP_REG].tag == RR_Undef)
sewardj9365e3f2010-01-01 19:55:17 +00002287 si->bp_how = CFIR_SAME;
sewardj35165532005-04-30 18:47:48 +00002288
2289 /* knock out some obviously stupid cases */
sewardj8eb41322005-05-01 23:50:08 +00002290 if (si->ra_how == CFIR_SAME)
2291 { why = 3; goto failed; }
sewardj35165532005-04-30 18:47:48 +00002292
2293 /* bogus looking range? Note, we require that the difference is
2294 representable in 32 bits. */
sewardj8eb41322005-05-01 23:50:08 +00002295 if (loc_start >= ctx->loc)
2296 { why = 4; goto failed; }
sewardj35165532005-04-30 18:47:48 +00002297 if (ctx->loc - loc_start > 10000000 /* let's say */)
sewardj8eb41322005-05-01 23:50:08 +00002298 { why = 5; goto failed; }
sewardj35165532005-04-30 18:47:48 +00002299
2300 si->base = loc_start + ctx->initloc;
2301 si->len = (UInt)(ctx->loc - loc_start);
2302
2303 return True;
2304
sewardj3026f712010-01-01 18:46:41 +00002305# elif defined(VGA_arm)
2306
2307 /* ---- entire tail of this fn specialised for arm ---- */
2308
2309 SUMMARISE_HOW(si->r14_how, si->r14_off,
2310 ctxs->reg[14] );
2311
2312 //SUMMARISE_HOW(si->r13_how, si->r13_off,
2313 // ctxs->reg[13] );
2314
2315 SUMMARISE_HOW(si->r12_how, si->r12_off,
2316 ctxs->reg[FP_REG] );
2317
2318 SUMMARISE_HOW(si->r11_how, si->r11_off,
2319 ctxs->reg[11/*FP_REG*/] );
2320
sewardjfa5ce562010-09-23 22:05:59 +00002321 SUMMARISE_HOW(si->r7_how, si->r7_off,
2322 ctxs->reg[7] );
2323
sewardj3026f712010-01-01 18:46:41 +00002324 if (ctxs->reg[14/*LR*/].tag == RR_Same
2325 && ctx->ra_reg == 14/*as we expect it always to be*/) {
2326 /* Generate a trivial CfiExpr, which merely says "r14". First
2327 ensure this DebugInfo has a cfsi_expr array in which to park
2328 it. */
2329 if (!debuginfo->cfsi_exprs)
2330 debuginfo->cfsi_exprs = VG_(newXA)( ML_(dinfo_zalloc),
2331 "di.ccCt.2a",
2332 ML_(dinfo_free),
2333 sizeof(CfiExpr) );
2334 si->ra_off = ML_(CfiExpr_CfiReg)( debuginfo->cfsi_exprs,
2335 Creg_ARM_R14);
2336 si->ra_how = CFIR_EXPR;
2337 } else {
2338 /* Just summarise it in the normal way */
2339 SUMMARISE_HOW(si->ra_how, si->ra_off,
2340 ctxs->reg[ctx->ra_reg] );
2341 }
2342
2343 /* on arm, it seems the old r13 (SP) value before the call is
2344 always the same as the CFA. Therefore ... */
2345 si->r13_how = CFIR_CFAREL;
2346 si->r13_off = 0;
2347
2348 /* bogus looking range? Note, we require that the difference is
2349 representable in 32 bits. */
2350 if (loc_start >= ctx->loc)
2351 { why = 4; goto failed; }
2352 if (ctx->loc - loc_start > 10000000 /* let's say */)
2353 { why = 5; goto failed; }
2354
2355 si->base = loc_start + ctx->initloc;
2356 si->len = (UInt)(ctx->loc - loc_start);
2357
2358 return True;
2359
sewardj821283b2014-01-13 00:21:09 +00002360# elif defined(VGA_arm64)
2361
2362 /* --- entire tail of this fn specialised for arm64 --- */
2363
2364 SUMMARISE_HOW(si->x30_how, si->x30_off, ctxs->reg[30/*LR*/]);
2365 SUMMARISE_HOW(si->x29_how, si->x29_off, ctxs->reg[29/*FP*/]);
2366
2367 if (ctxs->reg[30/*LR*/].tag == RR_Same
2368 && ctx->ra_reg == 30/*as we expect it always to be*/) {
2369 /* Generate a trivial CfiExpr, which merely says "x30". First
2370 ensure this DebugInfo has a cfsi_expr array in which to park
2371 it. */
2372 if (!debuginfo->cfsi_exprs)
2373 debuginfo->cfsi_exprs = VG_(newXA)( ML_(dinfo_zalloc),
2374 "di.ccCt.2a-arm64",
2375 ML_(dinfo_free),
2376 sizeof(CfiExpr) );
2377 si->ra_off = ML_(CfiExpr_CfiReg)( debuginfo->cfsi_exprs,
2378 Creg_ARM64_X30);
2379 si->ra_how = CFIR_EXPR;
2380 } else {
2381 /* Just summarise it in the normal way */
2382 SUMMARISE_HOW(si->ra_how, si->ra_off, ctxs->reg[ctx->ra_reg]);
2383 }
2384
2385 /* on arm64, it seems the old SP value before the call is always
2386 the same as the CFA. Therefore ... */
2387 si->sp_how = CFIR_CFAREL;
2388 si->sp_off = 0;
2389
2390 /* bogus looking range? Note, we require that the difference is
2391 representable in 32 bits. */
2392 if (loc_start >= ctx->loc)
2393 { why = 4; goto failed; }
2394 if (ctx->loc - loc_start > 10000000 /* let's say */)
2395 { why = 5; goto failed; }
2396
2397 si->base = loc_start + ctx->initloc;
2398 si->len = (UInt)(ctx->loc - loc_start);
2399
2400 return True;
2401
sewardjb5b87402011-03-07 16:05:35 +00002402# elif defined(VGA_s390x)
2403
sewardjf0c12502014-01-12 12:54:00 +00002404 /* --- entire tail of this fn specialised for s390 --- */
2405
sewardjb5b87402011-03-07 16:05:35 +00002406 SUMMARISE_HOW(si->ra_how, si->ra_off,
2407 ctxs->reg[ctx->ra_reg] );
2408 SUMMARISE_HOW(si->fp_how, si->fp_off,
2409 ctxs->reg[FP_REG] );
2410 SUMMARISE_HOW(si->sp_how, si->sp_off,
2411 ctxs->reg[SP_REG] );
2412
2413 /* change some defaults to consumable values */
2414 if (si->sp_how == CFIR_UNKNOWN)
2415 si->sp_how = CFIR_SAME;
2416
2417 if (si->fp_how == CFIR_UNKNOWN)
2418 si->fp_how = CFIR_SAME;
2419
2420 if (si->cfa_how == CFIR_UNKNOWN) {
2421 si->cfa_how = CFIC_IA_SPREL;
2422 si->cfa_off = 160;
2423 }
2424 if (si->ra_how == CFIR_UNKNOWN) {
2425 if (!debuginfo->cfsi_exprs)
2426 debuginfo->cfsi_exprs = VG_(newXA)( ML_(dinfo_zalloc),
2427 "di.ccCt.2a",
2428 ML_(dinfo_free),
2429 sizeof(CfiExpr) );
2430 si->ra_how = CFIR_EXPR;
2431 si->ra_off = ML_(CfiExpr_CfiReg)( debuginfo->cfsi_exprs,
2432 Creg_S390_R14);
2433 }
2434
2435 /* knock out some obviously stupid cases */
2436 if (si->ra_how == CFIR_SAME)
2437 { why = 3; goto failed; }
2438
2439 /* bogus looking range? Note, we require that the difference is
2440 representable in 32 bits. */
2441 if (loc_start >= ctx->loc)
2442 { why = 4; goto failed; }
2443 if (ctx->loc - loc_start > 10000000 /* let's say */)
2444 { why = 5; goto failed; }
2445
2446 si->base = loc_start + ctx->initloc;
2447 si->len = (UInt)(ctx->loc - loc_start);
2448
2449 return True;
2450
petarj4df0bfc2013-02-27 23:17:33 +00002451# elif defined(VGA_mips32) || defined(VGA_mips64)
sewardj5db15402012-06-07 09:13:21 +00002452
2453 /* --- entire tail of this fn specialised for mips --- */
2454
2455 SUMMARISE_HOW(si->ra_how, si->ra_off,
2456 ctxs->reg[ctx->ra_reg] );
2457 SUMMARISE_HOW(si->fp_how, si->fp_off,
2458 ctxs->reg[FP_REG] );
2459 SUMMARISE_HOW(si->sp_how, si->sp_off,
2460 ctxs->reg[SP_REG] );
2461 si->sp_how = CFIR_CFAREL;
2462 si->sp_off = 0;
2463
2464 if (si->fp_how == CFIR_UNKNOWN)
2465 si->fp_how = CFIR_SAME;
2466 if (si->cfa_how == CFIR_UNKNOWN) {
2467 si->cfa_how = CFIC_IA_SPREL;
2468 si->cfa_off = 160;
2469 }
2470 if (si->ra_how == CFIR_UNKNOWN) {
2471 if (!debuginfo->cfsi_exprs)
2472 debuginfo->cfsi_exprs = VG_(newXA)( ML_(dinfo_zalloc),
2473 "di.ccCt.2a",
2474 ML_(dinfo_free),
2475 sizeof(CfiExpr) );
2476 si->ra_how = CFIR_EXPR;
2477 si->ra_off = ML_(CfiExpr_CfiReg)( debuginfo->cfsi_exprs,
2478 Creg_MIPS_RA);
2479 }
2480
2481 if (si->ra_how == CFIR_SAME)
2482 { why = 3; goto failed; }
2483
2484 if (loc_start >= ctx->loc)
2485 { why = 4; goto failed; }
2486 if (ctx->loc - loc_start > 10000000 /* let's say */)
2487 { why = 5; goto failed; }
2488
2489 si->base = loc_start + ctx->initloc;
2490 si->len = (UInt)(ctx->loc - loc_start);
2491
2492 return True;
2493
sewardj3026f712010-01-01 18:46:41 +00002494# elif defined(VGA_ppc32) || defined(VGA_ppc64)
sewardjf0c12502014-01-12 12:54:00 +00002495 /* These don't use CFI based unwinding (is that really true?) */
2496
sewardj3026f712010-01-01 18:46:41 +00002497# else
2498# error "Unknown arch"
2499# endif
2500
sewardj821283b2014-01-13 00:21:09 +00002501 /* --- non-specialised code after this point --- */
2502
sewardj3026f712010-01-01 18:46:41 +00002503# undef SUMMARISE_HOW
2504
sewardj35165532005-04-30 18:47:48 +00002505 failed:
sewardjb8b79ad2008-03-03 01:35:41 +00002506 if (VG_(clo_verbosity) > 2 || debuginfo->trace_cfi) {
sewardj55022aa2005-05-03 16:05:00 +00002507 VG_(message)(Vg_DebugMsg,
barta0b6b2c2008-07-07 06:49:24 +00002508 "summarise_context(loc_start = %#lx)"
sewardj738856f2009-07-15 14:48:32 +00002509 ": cannot summarise(why=%d): \n", loc_start, why);
sewardj55022aa2005-05-03 16:05:00 +00002510 ppUnwindContext(ctx);
2511 }
sewardj35165532005-04-30 18:47:48 +00002512 return False;
2513}
2514
sewardj72427fa2007-02-27 16:52:23 +00002515/* Copy the tree rooted at srcuc->exprs node srcix to dstxa, on the
2516 way converting any DwReg regs (regs numbered using the Dwarf scheme
2517 defined by each architecture's ABI) into CfiRegs, which are
2518 platform independent. If the conversion isn't possible because
2519 there is no equivalent register, return -1. This has the
2520 undesirable side effect of de-dagifying the input; oh well. */
2521static Int copy_convert_CfiExpr_tree ( XArray* dstxa,
2522 UnwindContext* srcuc,
2523 Int srcix )
2524{
2525 CfiExpr* src;
sewardjd2be8cc2011-03-28 20:33:52 +00002526 Int cpL, cpR, cpA;
sewardj72427fa2007-02-27 16:52:23 +00002527 XArray* srcxa = srcuc->exprs;
2528 vg_assert(srcxa);
2529 vg_assert(dstxa);
2530 vg_assert(srcix >= 0 && srcix < VG_(sizeXA)(srcxa));
2531
2532 src = VG_(indexXA)( srcxa, srcix );
2533 switch (src->tag) {
2534 case Cex_Undef:
2535 return ML_(CfiExpr_Undef)( dstxa );
2536 case Cex_Deref:
sewardjbd7aca62007-08-31 23:08:39 +00002537 cpA = copy_convert_CfiExpr_tree( dstxa, srcuc, src->Cex.Deref.ixAddr );
2538 if (cpA == -1)
2539 return -1; /* propagate failure */
2540 return ML_(CfiExpr_Deref)( dstxa, cpA );
sewardj72427fa2007-02-27 16:52:23 +00002541 case Cex_Const:
2542 return ML_(CfiExpr_Const)( dstxa, src->Cex.Const.con );
2543 case Cex_Binop:
2544 cpL = copy_convert_CfiExpr_tree( dstxa, srcuc, src->Cex.Binop.ixL );
2545 cpR = copy_convert_CfiExpr_tree( dstxa, srcuc, src->Cex.Binop.ixR );
2546 vg_assert(cpL >= -1 && cpR >= -1);
2547 if (cpL == -1 || cpR == -1)
2548 return -1; /* propagate failure */
2549 return ML_(CfiExpr_Binop)( dstxa, src->Cex.Binop.op, cpL, cpR );
2550 case Cex_CfiReg:
2551 /* should not see these in input (are created only by this
2552 conversion step!) */
2553 VG_(core_panic)("copy_convert_CfiExpr_tree: CfiReg in input");
sewardjd2be8cc2011-03-28 20:33:52 +00002554 case Cex_DwReg: {
sewardj72427fa2007-02-27 16:52:23 +00002555 /* This is the only place where the conversion can fail. */
sewardjd2be8cc2011-03-28 20:33:52 +00002556 Int dwreg __attribute__((unused));
sewardj72427fa2007-02-27 16:52:23 +00002557 dwreg = src->Cex.DwReg.reg;
sewardj3026f712010-01-01 18:46:41 +00002558# if defined(VGA_x86) || defined(VGA_amd64)
sewardj72427fa2007-02-27 16:52:23 +00002559 if (dwreg == SP_REG)
sewardj9365e3f2010-01-01 19:55:17 +00002560 return ML_(CfiExpr_CfiReg)( dstxa, Creg_IA_SP );
sewardj72427fa2007-02-27 16:52:23 +00002561 if (dwreg == FP_REG)
sewardj9365e3f2010-01-01 19:55:17 +00002562 return ML_(CfiExpr_CfiReg)( dstxa, Creg_IA_BP );
sewardj72427fa2007-02-27 16:52:23 +00002563 if (dwreg == srcuc->ra_reg)
sewardj9365e3f2010-01-01 19:55:17 +00002564 return ML_(CfiExpr_CfiReg)( dstxa, Creg_IA_IP ); /* correct? */
sewardj3026f712010-01-01 18:46:41 +00002565# elif defined(VGA_arm)
2566 if (dwreg == SP_REG)
2567 return ML_(CfiExpr_CfiReg)( dstxa, Creg_ARM_R13 );
2568 if (dwreg == FP_REG)
2569 return ML_(CfiExpr_CfiReg)( dstxa, Creg_ARM_R12 );
2570 if (dwreg == srcuc->ra_reg)
2571 return ML_(CfiExpr_CfiReg)( dstxa, Creg_ARM_R15 ); /* correct? */
sewardjb5b87402011-03-07 16:05:35 +00002572# elif defined(VGA_s390x)
2573 if (dwreg == SP_REG)
2574 return ML_(CfiExpr_CfiReg)( dstxa, Creg_IA_SP );
2575 if (dwreg == FP_REG)
2576 return ML_(CfiExpr_CfiReg)( dstxa, Creg_IA_BP );
2577 if (dwreg == srcuc->ra_reg)
2578 return ML_(CfiExpr_CfiReg)( dstxa, Creg_IA_IP ); /* correct? */
petarj4df0bfc2013-02-27 23:17:33 +00002579# elif defined(VGA_mips32) || defined(VGA_mips64)
sewardj5db15402012-06-07 09:13:21 +00002580 if (dwreg == SP_REG)
2581 return ML_(CfiExpr_CfiReg)( dstxa, Creg_IA_SP );
2582 if (dwreg == FP_REG)
2583 return ML_(CfiExpr_CfiReg)( dstxa, Creg_IA_BP );
2584 if (dwreg == srcuc->ra_reg)
2585 return ML_(CfiExpr_CfiReg)( dstxa, Creg_IA_IP );
sewardjf0c12502014-01-12 12:54:00 +00002586# elif defined(VGA_arm64)
2587 I_die_here;
sewardj3026f712010-01-01 18:46:41 +00002588# elif defined(VGA_ppc32) || defined(VGA_ppc64)
2589# else
2590# error "Unknown arch"
2591# endif
sewardj72427fa2007-02-27 16:52:23 +00002592 /* else we must fail - can't represent the reg */
2593 return -1;
sewardjd2be8cc2011-03-28 20:33:52 +00002594 }
sewardj72427fa2007-02-27 16:52:23 +00002595 default:
2596 VG_(core_panic)("copy_convert_CfiExpr_tree: default");
2597 }
2598}
2599
2600
tom2fd38902005-05-01 15:14:01 +00002601static void ppUnwindContext_summary ( UnwindContext* ctx )
sewardj35165532005-04-30 18:47:48 +00002602{
sewardjde1b03d2009-08-03 13:47:04 +00002603 struct UnwindContextState* ctxs = &ctx->state[ctx->state_sp];
2604
sewardj35165532005-04-30 18:47:48 +00002605 VG_(printf)("0x%llx-1: ", (ULong)ctx->loc);
2606
sewardjde1b03d2009-08-03 13:47:04 +00002607 if (ctxs->cfa_reg == SP_REG) {
2608 VG_(printf)("SP/CFA=%d+SP ", ctxs->cfa_off);
sewardj35165532005-04-30 18:47:48 +00002609 } else
sewardjde1b03d2009-08-03 13:47:04 +00002610 if (ctxs->cfa_reg == FP_REG) {
2611 VG_(printf)("SP/CFA=%d+FP ", ctxs->cfa_off);
sewardj35165532005-04-30 18:47:48 +00002612 } else {
barta0b6b2c2008-07-07 06:49:24 +00002613 VG_(printf)("SP/CFA=unknown ");
sewardj35165532005-04-30 18:47:48 +00002614 }
2615
2616 VG_(printf)("RA=");
sewardjde1b03d2009-08-03 13:47:04 +00002617 ppRegRule( ctx->exprs, &ctxs->reg[ctx->ra_reg] );
sewardj35165532005-04-30 18:47:48 +00002618
2619 VG_(printf)("FP=");
sewardjde1b03d2009-08-03 13:47:04 +00002620 ppRegRule( ctx->exprs, &ctxs->reg[FP_REG] );
sewardj5c638c22005-04-30 07:55:58 +00002621 VG_(printf)("\n");
2622}
2623
sewardj55022aa2005-05-03 16:05:00 +00002624
2625/* ------------ Pick apart DWARF2 byte streams ------------ */
2626
sewardj5d616df2013-07-02 08:07:15 +00002627static ULong step_le_u_encoded_literal ( DiCursor* data, UInt size )
sewardjddf006d2007-02-24 23:29:31 +00002628{
2629 switch (size) {
sewardj5d616df2013-07-02 08:07:15 +00002630 case 8: return (ULong)ML_(cur_step_ULong)( data );
2631 case 4: return (ULong)ML_(cur_step_UInt)( data );
2632 case 2: return (ULong)ML_(cur_step_UShort)( data );
2633 case 1: return (ULong)ML_(cur_step_UChar)( data );
sewardjddf006d2007-02-24 23:29:31 +00002634 default: vg_assert(0); /*NOTREACHED*/ return 0;
2635 }
2636}
2637
sewardj5d616df2013-07-02 08:07:15 +00002638static Long step_le_s_encoded_literal ( DiCursor* data, UInt size )
sewardj72427fa2007-02-27 16:52:23 +00002639{
sewardj5d616df2013-07-02 08:07:15 +00002640 Long s64 = step_le_u_encoded_literal( data, size );
sewardj72427fa2007-02-27 16:52:23 +00002641 switch (size) {
2642 case 8: break;
2643 case 4: s64 <<= 32; s64 >>= 32; break;
2644 case 2: s64 <<= 48; s64 >>= 48; break;
2645 case 1: s64 <<= 56; s64 >>= 56; break;
2646 default: vg_assert(0); /*NOTREACHED*/ return 0;
2647 }
2648 return s64;
2649}
sewardjddf006d2007-02-24 23:29:31 +00002650
tom151a6392005-11-11 12:30:36 +00002651static UChar default_Addr_encoding ( void )
tom2fd38902005-05-01 15:14:01 +00002652{
2653 switch (sizeof(Addr)) {
2654 case 4: return DW_EH_PE_udata4;
2655 case 8: return DW_EH_PE_udata8;
2656 default: vg_assert(0);
2657 }
2658}
2659
sewardj8eb41322005-05-01 23:50:08 +00002660static UInt size_of_encoded_Addr ( UChar encoding )
tom2fd38902005-05-01 15:14:01 +00002661{
2662 if (encoding == DW_EH_PE_omit)
2663 return 0;
2664
2665 switch (encoding & 0x07) {
2666 case DW_EH_PE_absptr: return sizeof(Addr);
2667 case DW_EH_PE_udata2: return sizeof(UShort);
2668 case DW_EH_PE_udata4: return sizeof(UInt);
2669 case DW_EH_PE_udata8: return sizeof(ULong);
2670 default: vg_assert(0);
2671 }
2672}
2673
sewardj5d616df2013-07-02 08:07:15 +00002674static Addr step_encoded_Addr ( AddressDecodingInfo* adi,
2675 /*MOD*/DiCursor* data )
tom2fd38902005-05-01 15:14:01 +00002676{
sewardjddf006d2007-02-24 23:29:31 +00002677 /* Regarding the handling of DW_EH_PE_absptr. DWARF3 says this
2678 denotes an absolute address, hence you would think 'base' is
2679 zero. However, that is nonsensical (unless relocations are to
2680 be applied to the unwind data before reading it, which sounds
2681 unlikely). My interpretation is that DW_EH_PE_absptr indicates
2682 an address relative to where the object was loaded (technically,
2683 relative to its stated load VMA, hence the use of text_bias
2684 rather than text_avma). Hmm, should we use text_bias or
2685 text_avma here? Not sure.
2686
2687 This view appears to be supported by DWARF3 spec sec 7.3
2688 "Executable Objects and Shared Objects":
2689
2690 This requirement makes the debugging information for shared
2691 objects position independent. Virtual addresses in a shared
2692 object may be calculated by adding the offset to the base
2693 address at which the object was attached. This offset is
2694 available in the run-time linker's data structures.
2695 */
sewardj5d616df2013-07-02 08:07:15 +00002696 Addr base;
2697 Word offset;
2698 UChar encoding = adi->encoding;
2699 DiCursor ehframe_image = adi->ehframe_image;
2700 Addr ehframe_avma = adi->ehframe_avma;
tom2fd38902005-05-01 15:14:01 +00002701
2702 vg_assert((encoding & DW_EH_PE_indirect) == 0);
2703
tom2fd38902005-05-01 15:14:01 +00002704 switch (encoding & 0x70) {
2705 case DW_EH_PE_absptr:
sewardjddf006d2007-02-24 23:29:31 +00002706 base = adi->text_bias;
tom2fd38902005-05-01 15:14:01 +00002707 break;
2708 case DW_EH_PE_pcrel:
sewardj5d616df2013-07-02 08:07:15 +00002709 base = ehframe_avma + ML_(cur_minus)(*data, ehframe_image);
tom2fd38902005-05-01 15:14:01 +00002710 break;
2711 case DW_EH_PE_datarel:
2712 vg_assert(0);
2713 base = /* data base address */ 0;
2714 break;
2715 case DW_EH_PE_textrel:
2716 vg_assert(0);
2717 base = /* text base address */ 0;
2718 break;
2719 case DW_EH_PE_funcrel:
2720 base = 0;
2721 break;
2722 case DW_EH_PE_aligned:
2723 base = 0;
sewardj5d616df2013-07-02 08:07:15 +00002724 offset = ML_(cur_minus)(*data, ehframe_image);
tom2fd38902005-05-01 15:14:01 +00002725 if ((offset % sizeof(Addr)) != 0) {
sewardj5d616df2013-07-02 08:07:15 +00002726 Word nbytes = sizeof(Addr) - (offset % sizeof(Addr));
2727 *data = ML_(cur_plus)(*data, nbytes);
tom2fd38902005-05-01 15:14:01 +00002728 }
2729 break;
2730 default:
2731 vg_assert(0);
2732 }
2733
sewardj325ec872005-05-01 20:24:06 +00002734 if ((encoding & 0x07) == 0x00)
sewardj8eb41322005-05-01 23:50:08 +00002735 encoding |= default_Addr_encoding();
tom2fd38902005-05-01 15:14:01 +00002736
2737 switch (encoding & 0x0f) {
2738 case DW_EH_PE_udata2:
sewardj5d616df2013-07-02 08:07:15 +00002739 return base + ML_(cur_step_UShort)(data);
tom2fd38902005-05-01 15:14:01 +00002740 case DW_EH_PE_udata4:
sewardj5d616df2013-07-02 08:07:15 +00002741 return base + ML_(cur_step_UInt)(data);
tom2fd38902005-05-01 15:14:01 +00002742 case DW_EH_PE_udata8:
sewardj5d616df2013-07-02 08:07:15 +00002743 return base + ML_(cur_step_ULong)(data);
tom2fd38902005-05-01 15:14:01 +00002744 case DW_EH_PE_sdata2:
sewardj5d616df2013-07-02 08:07:15 +00002745 return base + ML_(cur_step_Short)(data);
tom2fd38902005-05-01 15:14:01 +00002746 case DW_EH_PE_sdata4:
sewardj5d616df2013-07-02 08:07:15 +00002747 return base + ML_(cur_step_Int)(data);
tom2fd38902005-05-01 15:14:01 +00002748 case DW_EH_PE_sdata8:
sewardj5d616df2013-07-02 08:07:15 +00002749 return base + ML_(cur_step_Long)(data);
tom2fd38902005-05-01 15:14:01 +00002750 default:
sewardj325ec872005-05-01 20:24:06 +00002751 vg_assert2(0, "read encoded address %d\n", encoding & 0x0f);
tom2fd38902005-05-01 15:14:01 +00002752 }
2753}
2754
sewardj5c638c22005-04-30 07:55:58 +00002755
sewardj72427fa2007-02-27 16:52:23 +00002756/* ------------ Run/show DWARF3 expressions ---------- */
2757
sewardj72427fa2007-02-27 16:52:23 +00002758/* Convert the DWARF3 expression in expr[0 .. exprlen-1] into a dag
2759 (of CfiExprs) stored in ctx->exprs, and return the index in
2760 ctx->exprs of the root node. Or fail in which case return -1. */
sewardj7888e222007-02-28 13:03:27 +00002761/* IMPORTANT: when adding expression forms here, also remember to
2762 add suitable evaluation code in evalCfiExpr in debuginfo.c. */
sewardj72427fa2007-02-27 16:52:23 +00002763static Int dwarfexpr_to_dag ( UnwindContext* ctx,
sewardj5d616df2013-07-02 08:07:15 +00002764 DiCursor expr, Int exprlen,
sewardj72427fa2007-02-27 16:52:23 +00002765 Bool push_cfa_at_start,
2766 Bool ddump_frames )
2767{
2768# define N_EXPR_STACK 20
2769
2770# define PUSH(_arg) \
2771 do { \
2772 vg_assert(sp >= -1 && sp < N_EXPR_STACK); \
2773 if (sp == N_EXPR_STACK-1) \
2774 return -1; \
2775 sp++; \
2776 stack[sp] = (_arg); \
2777 } while (0)
2778
2779# define POP(_lval) \
2780 do { \
2781 vg_assert(sp >= -1 && sp < N_EXPR_STACK); \
2782 if (sp == -1) \
2783 return -1; \
2784 _lval = stack[sp]; \
2785 sp--; \
2786 } while (0)
2787
tomf6716dd2012-09-21 09:04:27 +00002788 Int ix, ix2, reg;
2789 UChar opcode;
2790 Word sw;
2791 UWord uw;
tom40628fa2012-09-21 09:12:30 +00002792 CfiUnop uop;
tomf6716dd2012-09-21 09:04:27 +00002793 CfiBinop bop;
florian6bd9dc12012-11-23 16:17:43 +00002794 const HChar* opname;
sewardj72427fa2007-02-27 16:52:23 +00002795
2796 Int sp; /* # of top element: valid is -1 .. N_EXPR_STACK-1 */
2797 Int stack[N_EXPR_STACK]; /* indices into ctx->exprs */
sewardjde1b03d2009-08-03 13:47:04 +00002798 struct UnwindContextState* ctxs = &ctx->state[ctx->state_sp];
sewardj72427fa2007-02-27 16:52:23 +00002799
sewardj5d616df2013-07-02 08:07:15 +00002800 XArray* dst = ctx->exprs;
2801 DiCursor limit = ML_(cur_plus)(expr, exprlen);
sewardj72427fa2007-02-27 16:52:23 +00002802
2803 vg_assert(dst);
2804 vg_assert(exprlen >= 0);
2805
2806 sp = -1; /* empty */
2807
2808 /* Synthesise the CFA as a CfiExpr */
2809 if (push_cfa_at_start) {
sewardjde1b03d2009-08-03 13:47:04 +00002810 if (ctxs->cfa_is_regoff) {
sewardj72427fa2007-02-27 16:52:23 +00002811 /* cfa is reg +/- offset */
2812 ix = ML_(CfiExpr_Binop)( dst,
tomf6716dd2012-09-21 09:04:27 +00002813 Cbinop_Add,
sewardjde1b03d2009-08-03 13:47:04 +00002814 ML_(CfiExpr_DwReg)( dst, ctxs->cfa_reg ),
2815 ML_(CfiExpr_Const)( dst, (UWord)(Word)ctxs->cfa_off )
sewardj72427fa2007-02-27 16:52:23 +00002816 );
2817 PUSH(ix);
2818 } else {
2819 /* CFA is already an expr; use its root node */
sewardjde1b03d2009-08-03 13:47:04 +00002820 PUSH(ctxs->cfa_expr_ix);
sewardj72427fa2007-02-27 16:52:23 +00002821 }
2822 }
2823
2824 while (True) {
2825
2826 vg_assert(sp >= -1 && sp < N_EXPR_STACK);
2827
sewardj5d616df2013-07-02 08:07:15 +00002828 if (ML_(cur_cmpGT)(expr, limit)) /* "expr > limit" */
sewardj72427fa2007-02-27 16:52:23 +00002829 return -1; /* overrun - something's wrong */
2830
sewardj5d616df2013-07-02 08:07:15 +00002831 if (ML_(cur_cmpEQ)(expr, limit)) { /* "expr == limit" */
sewardj72427fa2007-02-27 16:52:23 +00002832 /* end of expr - return expr on the top of stack. */
2833 if (sp == -1)
2834 return -1; /* stack empty. Bad. */
2835 else
2836 break;
2837 }
2838
tom40628fa2012-09-21 09:12:30 +00002839 uop = 0; bop = 0; opname = NULL; /* excessively conservative */
sewardj19dc88f2007-02-28 01:46:30 +00002840
sewardj5d616df2013-07-02 08:07:15 +00002841 opcode = ML_(cur_step_UChar)(&expr);
sewardj72427fa2007-02-27 16:52:23 +00002842 switch (opcode) {
2843
sewardj19dc88f2007-02-28 01:46:30 +00002844 case DW_OP_lit0 ... DW_OP_lit31:
2845 /* push: literal 0 .. 31 */
2846 sw = (Word)opcode - (Word)DW_OP_lit0;
2847 vg_assert(sw >= 0 && sw <= 31);
2848 PUSH( ML_(CfiExpr_Const)( dst, (UWord)sw ) );
2849 if (ddump_frames)
2850 VG_(printf)("DW_OP_lit%ld", sw);
2851 break;
2852
sewardj72427fa2007-02-27 16:52:23 +00002853 case DW_OP_breg0 ... DW_OP_breg31:
2854 /* push: reg + sleb128 */
2855 reg = (Int)opcode - (Int)DW_OP_breg0;
2856 vg_assert(reg >= 0 && reg <= 31);
sewardj5d616df2013-07-02 08:07:15 +00002857 sw = step_leb128S( &expr );
sewardj72427fa2007-02-27 16:52:23 +00002858 ix = ML_(CfiExpr_Binop)( dst,
tomf6716dd2012-09-21 09:04:27 +00002859 Cbinop_Add,
sewardj72427fa2007-02-27 16:52:23 +00002860 ML_(CfiExpr_DwReg)( dst, reg ),
2861 ML_(CfiExpr_Const)( dst, (UWord)sw )
2862 );
2863 PUSH(ix);
2864 if (ddump_frames)
2865 VG_(printf)("DW_OP_breg%d: %ld", reg, sw);
2866 break;
2867
sewardj13596ff2009-01-25 23:48:31 +00002868 case DW_OP_reg0 ... DW_OP_reg31:
2869 /* push: reg */
2870 reg = (Int)opcode - (Int)DW_OP_reg0;
2871 vg_assert(reg >= 0 && reg <= 31);
2872 ix = ML_(CfiExpr_DwReg)( dst, reg );
2873 PUSH(ix);
2874 if (ddump_frames)
2875 VG_(printf)("DW_OP_reg%d", reg);
2876 break;
2877
sewardjc153bf62008-01-14 12:04:11 +00002878 case DW_OP_plus_uconst:
sewardj5d616df2013-07-02 08:07:15 +00002879 uw = step_leb128U( &expr );
sewardjc153bf62008-01-14 12:04:11 +00002880 PUSH( ML_(CfiExpr_Const)( dst, uw ) );
2881 POP( ix );
2882 POP( ix2 );
tomf6716dd2012-09-21 09:04:27 +00002883 PUSH( ML_(CfiExpr_Binop)( dst, Cbinop_Add, ix2, ix ) );
sewardjc153bf62008-01-14 12:04:11 +00002884 if (ddump_frames)
2885 VG_(printf)("DW_OP_plus_uconst: %lu", uw);
2886 break;
2887
sewardj72427fa2007-02-27 16:52:23 +00002888 case DW_OP_const4s:
2889 /* push: 32-bit signed immediate */
sewardj5d616df2013-07-02 08:07:15 +00002890 sw = step_le_s_encoded_literal( &expr, 4 );
sewardj72427fa2007-02-27 16:52:23 +00002891 PUSH( ML_(CfiExpr_Const)( dst, (UWord)sw ) );
2892 if (ddump_frames)
2893 VG_(printf)("DW_OP_const4s: %ld", sw);
2894 break;
2895
tom40628fa2012-09-21 09:12:30 +00002896 case DW_OP_const2s:
2897 /* push: 16-bit signed immediate */
sewardj5d616df2013-07-02 08:07:15 +00002898 sw = step_le_s_encoded_literal( &expr, 2 );
tom40628fa2012-09-21 09:12:30 +00002899 PUSH( ML_(CfiExpr_Const)( dst, (UWord)sw ) );
2900 if (ddump_frames)
2901 VG_(printf)("DW_OP_const2s: %ld", sw);
2902 break;
2903
sewardj13596ff2009-01-25 23:48:31 +00002904 case DW_OP_const1s:
2905 /* push: 8-bit signed immediate */
sewardj5d616df2013-07-02 08:07:15 +00002906 sw = step_le_s_encoded_literal( &expr, 1 );
sewardj13596ff2009-01-25 23:48:31 +00002907 PUSH( ML_(CfiExpr_Const)( dst, (UWord)sw ) );
2908 if (ddump_frames)
2909 VG_(printf)("DW_OP_const1s: %ld", sw);
2910 break;
2911
tom40628fa2012-09-21 09:12:30 +00002912 case DW_OP_const1u:
2913 /* push: 8-bit unsigned immediate */
sewardj5d616df2013-07-02 08:07:15 +00002914 uw = step_le_u_encoded_literal( &expr, 1 );
tom40628fa2012-09-21 09:12:30 +00002915 PUSH( ML_(CfiExpr_Const)( dst, uw ) );
2916 if (ddump_frames)
2917 VG_(printf)("DW_OP_const1: %lu", uw);
2918 break;
2919
2920 case DW_OP_const2u:
2921 /* push: 16-bit unsigned immediate */
sewardj5d616df2013-07-02 08:07:15 +00002922 uw = step_le_u_encoded_literal( &expr, 2 );
tom40628fa2012-09-21 09:12:30 +00002923 PUSH( ML_(CfiExpr_Const)( dst, uw ) );
2924 if (ddump_frames)
2925 VG_(printf)("DW_OP_const2: %lu", uw);
2926 break;
2927
2928 case DW_OP_const4u:
2929 /* push: 32-bit unsigned immediate */
sewardj5d616df2013-07-02 08:07:15 +00002930 uw = step_le_u_encoded_literal( &expr, 4 );
tom40628fa2012-09-21 09:12:30 +00002931 PUSH( ML_(CfiExpr_Const)( dst, uw ) );
2932 if (ddump_frames)
2933 VG_(printf)("DW_OP_const4: %lu", uw);
2934 break;
2935
2936 case DW_OP_abs:
2937 uop = Cunop_Abs; opname = "abs"; goto unop;
2938 case DW_OP_neg:
2939 uop = Cunop_Neg; opname = "neg"; goto unop;
2940 case DW_OP_not:
2941 uop = Cunop_Not; opname = "not"; goto unop;
2942 unop:
2943 POP( ix );
2944 PUSH( ML_(CfiExpr_Unop)( dst, uop, ix ) );
2945 if (ddump_frames)
2946 VG_(printf)("DW_OP_%s", opname);
2947 break;
2948
sewardj72427fa2007-02-27 16:52:23 +00002949 case DW_OP_minus:
tomf6716dd2012-09-21 09:04:27 +00002950 bop = Cbinop_Sub; opname = "minus"; goto binop;
sewardj72427fa2007-02-27 16:52:23 +00002951 case DW_OP_plus:
tomf6716dd2012-09-21 09:04:27 +00002952 bop = Cbinop_Add; opname = "plus"; goto binop;
sewardj19dc88f2007-02-28 01:46:30 +00002953 case DW_OP_and:
tomf6716dd2012-09-21 09:04:27 +00002954 bop = Cbinop_And; opname = "and"; goto binop;
sewardj7888e222007-02-28 13:03:27 +00002955 case DW_OP_mul:
tomf6716dd2012-09-21 09:04:27 +00002956 bop = Cbinop_Mul; opname = "mul"; goto binop;
tom0b982392011-07-05 09:22:32 +00002957 case DW_OP_shl:
tomf6716dd2012-09-21 09:04:27 +00002958 bop = Cbinop_Shl; opname = "shl"; goto binop;
tom0b982392011-07-05 09:22:32 +00002959 case DW_OP_shr:
tomf6716dd2012-09-21 09:04:27 +00002960 bop = Cbinop_Shr; opname = "shr"; goto binop;
tom0b982392011-07-05 09:22:32 +00002961 case DW_OP_eq:
tomf6716dd2012-09-21 09:04:27 +00002962 bop = Cbinop_Eq; opname = "eq"; goto binop;
tom0b982392011-07-05 09:22:32 +00002963 case DW_OP_ge:
tomf6716dd2012-09-21 09:04:27 +00002964 bop = Cbinop_Ge; opname = "ge"; goto binop;
tom0b982392011-07-05 09:22:32 +00002965 case DW_OP_gt:
tomf6716dd2012-09-21 09:04:27 +00002966 bop = Cbinop_Gt; opname = "gt"; goto binop;
tom0b982392011-07-05 09:22:32 +00002967 case DW_OP_le:
tomf6716dd2012-09-21 09:04:27 +00002968 bop = Cbinop_Le; opname = "le"; goto binop;
tom0b982392011-07-05 09:22:32 +00002969 case DW_OP_lt:
tomf6716dd2012-09-21 09:04:27 +00002970 bop = Cbinop_Lt; opname = "lt"; goto binop;
tom0b982392011-07-05 09:22:32 +00002971 case DW_OP_ne:
tomf6716dd2012-09-21 09:04:27 +00002972 bop = Cbinop_Ne; opname = "ne"; goto binop;
sewardj19dc88f2007-02-28 01:46:30 +00002973 binop:
sewardj72427fa2007-02-27 16:52:23 +00002974 POP( ix );
2975 POP( ix2 );
tomf6716dd2012-09-21 09:04:27 +00002976 PUSH( ML_(CfiExpr_Binop)( dst, bop, ix2, ix ) );
sewardj72427fa2007-02-27 16:52:23 +00002977 if (ddump_frames)
sewardj19dc88f2007-02-28 01:46:30 +00002978 VG_(printf)("DW_OP_%s", opname);
sewardj72427fa2007-02-27 16:52:23 +00002979 break;
2980
sewardjbd7aca62007-08-31 23:08:39 +00002981 case DW_OP_deref:
2982 POP( ix );
2983 PUSH( ML_(CfiExpr_Deref)( dst, ix ) );
2984 if (ddump_frames)
2985 VG_(printf)("DW_OP_deref");
2986 break;
2987
sewardj72427fa2007-02-27 16:52:23 +00002988 default:
sewardj7888e222007-02-28 13:03:27 +00002989 if (!VG_(clo_xml))
2990 VG_(message)(Vg_DebugMsg,
sewardj1ff57e62007-11-20 08:46:05 +00002991 "Warning: DWARF2 CFI reader: unhandled DW_OP_ "
sewardj738856f2009-07-15 14:48:32 +00002992 "opcode 0x%x\n", (Int)opcode);
sewardj72427fa2007-02-27 16:52:23 +00002993 return -1;
2994 }
2995
sewardj5d616df2013-07-02 08:07:15 +00002996 if (ML_(cur_cmpLT)(expr, limit) && ddump_frames)
sewardj72427fa2007-02-27 16:52:23 +00002997 VG_(printf)("; ");
2998
2999 }
3000
3001 vg_assert(sp >= -1 && sp < N_EXPR_STACK);
3002 if (sp == -1)
3003 return -1;
3004
3005 if (0 && ddump_frames)
3006 ML_(ppCfiExpr)( dst, stack[sp] );
3007 return stack[sp];
3008
3009# undef POP
3010# undef PUSH
3011# undef N_EXPR_STACK
3012}
3013
3014
sewardj55022aa2005-05-03 16:05:00 +00003015/* ------------ Run/show CFI instructions ------------ */
3016
sewardj5c638c22005-04-30 07:55:58 +00003017/* Run a CFI instruction, and also return its length.
3018 Returns 0 if the instruction could not be executed.
3019*/
3020static Int run_CF_instruction ( /*MOD*/UnwindContext* ctx,
sewardj5d616df2013-07-02 08:07:15 +00003021 DiCursor instrIN,
sewardj1936f8b2006-11-16 12:21:52 +00003022 UnwindContext* restore_ctx,
sewardjf767d962007-02-12 17:47:14 +00003023 AddressDecodingInfo* adi,
sewardjb8b79ad2008-03-03 01:35:41 +00003024 struct _DebugInfo* di )
sewardj5c638c22005-04-30 07:55:58 +00003025{
sewardj5d616df2013-07-02 08:07:15 +00003026 Int off, reg, reg2, len, j;
3027 UInt delta;
3028 Addr printing_bias = ((Addr)ctx->initloc) - ((Addr)di->text_bias);
sewardjde1b03d2009-08-03 13:47:04 +00003029 struct UnwindContextState* ctxs;
sewardj5d616df2013-07-02 08:07:15 +00003030
3031 DiCursor instr = instrIN;
3032 UChar instr_0 = ML_(cur_step_UChar)(&instr);
3033 UChar hi2 = (instr_0 >> 6) & 3;
3034 UChar lo6 = instr_0 & 0x3F;
sewardj5c638c22005-04-30 07:55:58 +00003035
sewardjde1b03d2009-08-03 13:47:04 +00003036 if (ctx->state_sp < 0 || ctx->state_sp >= N_RR_STACK)
sewardj3d026b12009-05-21 15:33:36 +00003037 return 0; /* bogus reg-rule stack pointer */
3038
sewardjde1b03d2009-08-03 13:47:04 +00003039 ctxs = &ctx->state[ctx->state_sp];
sewardj5c638c22005-04-30 07:55:58 +00003040 if (hi2 == DW_CFA_advance_loc) {
3041 delta = (UInt)lo6;
sewardj987a7652010-09-23 13:24:48 +00003042 delta *= ctx->code_a_f;
sewardj5c638c22005-04-30 07:55:58 +00003043 ctx->loc += delta;
sewardjb8b79ad2008-03-03 01:35:41 +00003044 if (di->ddump_frames)
sewardj3646a492007-02-16 14:17:10 +00003045 VG_(printf)(" DW_CFA_advance_loc: %d to %08lx\n",
3046 (Int)delta, (Addr)ctx->loc + printing_bias);
sewardj5d616df2013-07-02 08:07:15 +00003047 return ML_(cur_minus)(instr, instrIN);
sewardj5c638c22005-04-30 07:55:58 +00003048 }
3049
3050 if (hi2 == DW_CFA_offset) {
sewardj72427fa2007-02-27 16:52:23 +00003051 /* Set rule for reg 'lo6' to CFAOff(off * data_af) */
sewardj5d616df2013-07-02 08:07:15 +00003052 off = step_leb128( &instr, 0 );
sewardj5c638c22005-04-30 07:55:58 +00003053 reg = (Int)lo6;
3054 if (reg < 0 || reg >= N_CFI_REGS)
3055 return 0; /* fail */
sewardjde1b03d2009-08-03 13:47:04 +00003056 ctxs->reg[reg].tag = RR_CFAOff;
3057 ctxs->reg[reg].arg = off * ctx->data_a_f;
sewardjb8b79ad2008-03-03 01:35:41 +00003058 if (di->ddump_frames)
sewardj3646a492007-02-16 14:17:10 +00003059 VG_(printf)(" DW_CFA_offset: r%d at cfa%s%d\n",
sewardj3d026b12009-05-21 15:33:36 +00003060 (Int)reg,
sewardjde1b03d2009-08-03 13:47:04 +00003061 ctxs->reg[reg].arg < 0 ? "" : "+",
3062 (Int)ctxs->reg[reg].arg );
sewardj5d616df2013-07-02 08:07:15 +00003063 return ML_(cur_minus)(instr, instrIN);
sewardj5c638c22005-04-30 07:55:58 +00003064 }
3065
3066 if (hi2 == DW_CFA_restore) {
sewardj8eb41322005-05-01 23:50:08 +00003067 reg = (Int)lo6;
3068 if (reg < 0 || reg >= N_CFI_REGS)
3069 return 0; /* fail */
3070 if (restore_ctx == NULL)
3071 return 0; /* fail */
sewardjde1b03d2009-08-03 13:47:04 +00003072 ctxs->reg[reg] = restore_ctx->state[restore_ctx->state_sp].reg[reg];
sewardjb8b79ad2008-03-03 01:35:41 +00003073 if (di->ddump_frames)
sewardj687bbf62007-02-16 20:11:27 +00003074 VG_(printf)(" DW_CFA_restore: r%d\n", (Int)reg);
sewardj5d616df2013-07-02 08:07:15 +00003075 return ML_(cur_minus)(instr, instrIN);
sewardj5c638c22005-04-30 07:55:58 +00003076 }
3077
3078 vg_assert(hi2 == DW_CFA_use_secondary);
3079
3080 switch (lo6) {
3081 case DW_CFA_nop:
sewardjb8b79ad2008-03-03 01:35:41 +00003082 if (di->ddump_frames)
sewardj3646a492007-02-16 14:17:10 +00003083 VG_(printf)(" DW_CFA_nop\n");
sewardj5c638c22005-04-30 07:55:58 +00003084 break;
tom2fd38902005-05-01 15:14:01 +00003085 case DW_CFA_set_loc:
sewardj1936f8b2006-11-16 12:21:52 +00003086 /* WAS:
3087 ctx->loc = read_Addr(&instr[i]) - ctx->initloc; i+= sizeof(Addr);
3088 Was this ever right? */
sewardjddf006d2007-02-24 23:29:31 +00003089 /* 2007 Feb 23: No. binutils/dwarf.c treats it as an encoded
3090 address and that appears to be in accordance with the
3091 DWARF3 spec. */
sewardj5d616df2013-07-02 08:07:15 +00003092 ctx->loc = step_encoded_Addr(adi, &instr);
sewardjb8b79ad2008-03-03 01:35:41 +00003093 if (di->ddump_frames)
sewardj3646a492007-02-16 14:17:10 +00003094 VG_(printf)(" rci:DW_CFA_set_loc\n");
tom2fd38902005-05-01 15:14:01 +00003095 break;
sewardj5c638c22005-04-30 07:55:58 +00003096 case DW_CFA_advance_loc1:
sewardj5d616df2013-07-02 08:07:15 +00003097 delta = (UInt)ML_(cur_step_UChar)(&instr);
sewardj987a7652010-09-23 13:24:48 +00003098 delta *= ctx->code_a_f;
tom2fd38902005-05-01 15:14:01 +00003099 ctx->loc += delta;
sewardjb8b79ad2008-03-03 01:35:41 +00003100 if (di->ddump_frames)
sewardj687bbf62007-02-16 20:11:27 +00003101 VG_(printf)(" DW_CFA_advance_loc1: %d to %08lx\n",
3102 (Int)delta, (Addr)ctx->loc + printing_bias);
tom2fd38902005-05-01 15:14:01 +00003103 break;
3104 case DW_CFA_advance_loc2:
sewardj5d616df2013-07-02 08:07:15 +00003105 delta = (UInt)ML_(cur_step_UShort)(&instr);
sewardj987a7652010-09-23 13:24:48 +00003106 delta *= ctx->code_a_f;
tom2fd38902005-05-01 15:14:01 +00003107 ctx->loc += delta;
sewardjb8b79ad2008-03-03 01:35:41 +00003108 if (di->ddump_frames)
sewardj687bbf62007-02-16 20:11:27 +00003109 VG_(printf)(" DW_CFA_advance_loc2: %d to %08lx\n",
3110 (Int)delta, (Addr)ctx->loc + printing_bias);
tom2fd38902005-05-01 15:14:01 +00003111 break;
3112 case DW_CFA_advance_loc4:
sewardj5d616df2013-07-02 08:07:15 +00003113 delta = (UInt)ML_(cur_step_UInt)(&instr);
sewardj987a7652010-09-23 13:24:48 +00003114 delta *= ctx->code_a_f;
tom2fd38902005-05-01 15:14:01 +00003115 ctx->loc += delta;
sewardjb8b79ad2008-03-03 01:35:41 +00003116 if (di->ddump_frames)
sewardj687bbf62007-02-16 20:11:27 +00003117 VG_(printf)(" DW_CFA_advance_loc4: %d to %08lx\n",
3118 (Int)delta, (Addr)ctx->loc + printing_bias);
sewardj5c638c22005-04-30 07:55:58 +00003119 break;
3120
3121 case DW_CFA_def_cfa:
sewardj5d616df2013-07-02 08:07:15 +00003122 reg = step_leb128( &instr, 0 );
3123 off = step_leb128( &instr, 0 );
sewardj5c638c22005-04-30 07:55:58 +00003124 if (reg < 0 || reg >= N_CFI_REGS)
3125 return 0; /* fail */
sewardjde1b03d2009-08-03 13:47:04 +00003126 ctxs->cfa_is_regoff = True;
3127 ctxs->cfa_expr_ix = 0;
3128 ctxs->cfa_reg = reg;
3129 ctxs->cfa_off = off;
sewardjb8b79ad2008-03-03 01:35:41 +00003130 if (di->ddump_frames)
sewardj3646a492007-02-16 14:17:10 +00003131 VG_(printf)(" DW_CFA_def_cfa: r%d ofs %d\n", (Int)reg, (Int)off);
sewardj5c638c22005-04-30 07:55:58 +00003132 break;
3133
sewardjd69222c2006-04-08 16:22:53 +00003134 case DW_CFA_def_cfa_sf:
sewardj5d616df2013-07-02 08:07:15 +00003135 reg = step_leb128( &instr, 0 );
3136 off = step_leb128( &instr, 1 );
sewardjd69222c2006-04-08 16:22:53 +00003137 if (reg < 0 || reg >= N_CFI_REGS)
3138 return 0; /* fail */
sewardjde1b03d2009-08-03 13:47:04 +00003139 ctxs->cfa_is_regoff = True;
3140 ctxs->cfa_expr_ix = 0;
3141 ctxs->cfa_reg = reg;
3142 ctxs->cfa_off = off * ctx->data_a_f;
sewardjb8b79ad2008-03-03 01:35:41 +00003143 if (di->ddump_frames)
sewardj3646a492007-02-16 14:17:10 +00003144 VG_(printf)(" rci:DW_CFA_def_cfa_sf\n");
sewardjd69222c2006-04-08 16:22:53 +00003145 break;
3146
sewardje0707a62005-05-02 12:25:13 +00003147 case DW_CFA_register:
sewardj5d616df2013-07-02 08:07:15 +00003148 reg = step_leb128( &instr, 0 );
3149 reg2 = step_leb128( &instr, 0 );
sewardje0707a62005-05-02 12:25:13 +00003150 if (reg < 0 || reg >= N_CFI_REGS)
3151 return 0; /* fail */
3152 if (reg2 < 0 || reg2 >= N_CFI_REGS)
3153 return 0; /* fail */
sewardjde1b03d2009-08-03 13:47:04 +00003154 ctxs->reg[reg].tag = RR_Reg;
3155 ctxs->reg[reg].arg = reg2;
sewardjb8b79ad2008-03-03 01:35:41 +00003156 if (di->ddump_frames)
sewardj72427fa2007-02-27 16:52:23 +00003157 VG_(printf)(" DW_CFA_register: r%d in r%d\n",
3158 (Int)reg, (Int)reg2);
sewardje0707a62005-05-02 12:25:13 +00003159 break;
3160
sewardjd69222c2006-04-08 16:22:53 +00003161 case DW_CFA_offset_extended:
sewardj5d616df2013-07-02 08:07:15 +00003162 reg = step_leb128( &instr, 0 );
3163 off = step_leb128( &instr, 0 );
sewardjd69222c2006-04-08 16:22:53 +00003164 if (reg < 0 || reg >= N_CFI_REGS)
3165 return 0; /* fail */
sewardjde1b03d2009-08-03 13:47:04 +00003166 ctxs->reg[reg].tag = RR_CFAOff;
3167 ctxs->reg[reg].arg = off * ctx->data_a_f;
sewardjb8b79ad2008-03-03 01:35:41 +00003168 if (di->ddump_frames)
sewardj3646a492007-02-16 14:17:10 +00003169 VG_(printf)(" rci:DW_CFA_offset_extended\n");
sewardjd69222c2006-04-08 16:22:53 +00003170 break;
3171
sewardj325ec872005-05-01 20:24:06 +00003172 case DW_CFA_offset_extended_sf:
sewardj5d616df2013-07-02 08:07:15 +00003173 reg = step_leb128( &instr, 0 );
3174 off = step_leb128( &instr, 1 );
sewardj325ec872005-05-01 20:24:06 +00003175 if (reg < 0 || reg >= N_CFI_REGS)
3176 return 0; /* fail */
sewardjde1b03d2009-08-03 13:47:04 +00003177 ctxs->reg[reg].tag = RR_CFAOff;
3178 ctxs->reg[reg].arg = off * ctx->data_a_f;
sewardjb8b79ad2008-03-03 01:35:41 +00003179 if (di->ddump_frames)
sewardjddf006d2007-02-24 23:29:31 +00003180 VG_(printf)(" DW_CFA_offset_extended_sf: r%d at cfa%s%d\n",
sewardj3d026b12009-05-21 15:33:36 +00003181 reg,
sewardjde1b03d2009-08-03 13:47:04 +00003182 ctxs->reg[reg].arg < 0 ? "" : "+",
3183 (Int)ctxs->reg[reg].arg);
sewardjddf006d2007-02-24 23:29:31 +00003184 break;
sewardj325ec872005-05-01 20:24:06 +00003185
sewardjd69222c2006-04-08 16:22:53 +00003186 case DW_CFA_GNU_negative_offset_extended:
sewardj5d616df2013-07-02 08:07:15 +00003187 reg = step_leb128( &instr, 0 );
3188 off = step_leb128( &instr, 0 );
sewardjd69222c2006-04-08 16:22:53 +00003189 if (reg < 0 || reg >= N_CFI_REGS)
3190 return 0; /* fail */
sewardjde1b03d2009-08-03 13:47:04 +00003191 ctxs->reg[reg].tag = RR_CFAOff;
3192 ctxs->reg[reg].arg = (-off) * ctx->data_a_f;
sewardjb8b79ad2008-03-03 01:35:41 +00003193 if (di->ddump_frames)
sewardj3646a492007-02-16 14:17:10 +00003194 VG_(printf)(" rci:DW_CFA_GNU_negative_offset_extended\n");
sewardjd69222c2006-04-08 16:22:53 +00003195 break;
3196
3197 case DW_CFA_restore_extended:
sewardj5d616df2013-07-02 08:07:15 +00003198 reg = step_leb128( &instr, 0 );
sewardjd69222c2006-04-08 16:22:53 +00003199 if (reg < 0 || reg >= N_CFI_REGS)
3200 return 0; /* fail */
3201 if (restore_ctx == NULL)
3202 return 0; /* fail */
sewardjde1b03d2009-08-03 13:47:04 +00003203 ctxs->reg[reg] = restore_ctx->state[restore_ctx->state_sp].reg[reg];
sewardjb8b79ad2008-03-03 01:35:41 +00003204 if (di->ddump_frames)
sewardj3646a492007-02-16 14:17:10 +00003205 VG_(printf)(" rci:DW_CFA_restore_extended\n");
sewardjd69222c2006-04-08 16:22:53 +00003206 break;
3207
3208 case DW_CFA_val_offset:
sewardj5d616df2013-07-02 08:07:15 +00003209 reg = step_leb128( &instr, 0 );
3210 off = step_leb128( &instr, 0 );
sewardjd69222c2006-04-08 16:22:53 +00003211 if (reg < 0 || reg >= N_CFI_REGS)
3212 return 0; /* fail */
sewardjde1b03d2009-08-03 13:47:04 +00003213 ctxs->reg[reg].tag = RR_CFAValOff;
3214 ctxs->reg[reg].arg = off * ctx->data_a_f;
sewardjb8b79ad2008-03-03 01:35:41 +00003215 if (di->ddump_frames)
sewardj3646a492007-02-16 14:17:10 +00003216 VG_(printf)(" rci:DW_CFA_val_offset\n");
sewardjd69222c2006-04-08 16:22:53 +00003217 break;
3218
3219 case DW_CFA_val_offset_sf:
sewardj5d616df2013-07-02 08:07:15 +00003220 reg = step_leb128( &instr, 0 );
3221 off = step_leb128( &instr, 1 );
sewardjd69222c2006-04-08 16:22:53 +00003222 if (reg < 0 || reg >= N_CFI_REGS)
3223 return 0; /* fail */
sewardjde1b03d2009-08-03 13:47:04 +00003224 ctxs->reg[reg].tag = RR_CFAValOff;
3225 ctxs->reg[reg].arg = off * ctx->data_a_f;
sewardjb8b79ad2008-03-03 01:35:41 +00003226 if (di->ddump_frames)
sewardj3646a492007-02-16 14:17:10 +00003227 VG_(printf)(" rci:DW_CFA_val_offset_sf\n");
sewardjd69222c2006-04-08 16:22:53 +00003228 break;
3229
sewardj325ec872005-05-01 20:24:06 +00003230 case DW_CFA_def_cfa_register:
sewardj5d616df2013-07-02 08:07:15 +00003231 reg = step_leb128( &instr, 0);
sewardj5c638c22005-04-30 07:55:58 +00003232 if (reg < 0 || reg >= N_CFI_REGS)
3233 return 0; /* fail */
sewardjde1b03d2009-08-03 13:47:04 +00003234 ctxs->cfa_is_regoff = True;
3235 ctxs->cfa_expr_ix = 0;
3236 ctxs->cfa_reg = reg;
sewardj72427fa2007-02-27 16:52:23 +00003237 /* ->cfa_off unchanged */
sewardjb8b79ad2008-03-03 01:35:41 +00003238 if (di->ddump_frames)
sewardj987a7652010-09-23 13:24:48 +00003239 VG_(printf)(" DW_CFA_def_cfa_register: r%d\n", (Int)reg );
sewardj5c638c22005-04-30 07:55:58 +00003240 break;
sewardj325ec872005-05-01 20:24:06 +00003241
3242 case DW_CFA_def_cfa_offset:
sewardj5d616df2013-07-02 08:07:15 +00003243 off = step_leb128( &instr, 0);
sewardjde1b03d2009-08-03 13:47:04 +00003244 ctxs->cfa_is_regoff = True;
3245 ctxs->cfa_expr_ix = 0;
sewardj72427fa2007-02-27 16:52:23 +00003246 /* ->reg is unchanged */
sewardjde1b03d2009-08-03 13:47:04 +00003247 ctxs->cfa_off = off;
sewardjb8b79ad2008-03-03 01:35:41 +00003248 if (di->ddump_frames)
sewardj3646a492007-02-16 14:17:10 +00003249 VG_(printf)(" DW_CFA_def_cfa_offset: %d\n", (Int)off);
sewardj5c638c22005-04-30 07:55:58 +00003250 break;
sewardj325ec872005-05-01 20:24:06 +00003251
sewardjab30d202005-05-15 17:14:28 +00003252 case DW_CFA_def_cfa_offset_sf:
sewardj5d616df2013-07-02 08:07:15 +00003253 off = step_leb128( &instr, 1);
sewardjde1b03d2009-08-03 13:47:04 +00003254 ctxs->cfa_is_regoff = True;
3255 ctxs->cfa_expr_ix = 0;
sewardj72427fa2007-02-27 16:52:23 +00003256 /* ->reg is unchanged */
sewardjde1b03d2009-08-03 13:47:04 +00003257 ctxs->cfa_off = off * ctx->data_a_f;
sewardjb8b79ad2008-03-03 01:35:41 +00003258 if (di->ddump_frames)
sewardjde1b03d2009-08-03 13:47:04 +00003259 VG_(printf)(" DW_CFA_def_cfa_offset_sf: %d\n", ctxs->cfa_off);
sewardjab30d202005-05-15 17:14:28 +00003260 break;
3261
sewardj301901f2007-01-12 19:21:22 +00003262 case DW_CFA_undefined:
sewardj5d616df2013-07-02 08:07:15 +00003263 reg = step_leb128( &instr, 0);
sewardj301901f2007-01-12 19:21:22 +00003264 if (reg < 0 || reg >= N_CFI_REGS)
3265 return 0; /* fail */
sewardjde1b03d2009-08-03 13:47:04 +00003266 ctxs->reg[reg].tag = RR_Undef;
3267 ctxs->reg[reg].arg = 0;
sewardjb8b79ad2008-03-03 01:35:41 +00003268 if (di->ddump_frames)
sewardj3646a492007-02-16 14:17:10 +00003269 VG_(printf)(" rci:DW_CFA_undefined\n");
sewardj301901f2007-01-12 19:21:22 +00003270 break;
3271
tom80b8b092009-04-08 15:06:34 +00003272 case DW_CFA_same_value:
sewardj5d616df2013-07-02 08:07:15 +00003273 reg = step_leb128( &instr, 0);
tom80b8b092009-04-08 15:06:34 +00003274 if (reg < 0 || reg >= N_CFI_REGS)
3275 return 0; /* fail */
sewardjde1b03d2009-08-03 13:47:04 +00003276 ctxs->reg[reg].tag = RR_Same;
3277 ctxs->reg[reg].arg = 0;
tom80b8b092009-04-08 15:06:34 +00003278 if (di->ddump_frames)
3279 VG_(printf)(" rci:DW_CFA_same_value\n");
3280 break;
3281
sewardj325ec872005-05-01 20:24:06 +00003282 case DW_CFA_GNU_args_size:
sewardj5c638c22005-04-30 07:55:58 +00003283 /* No idea what is supposed to happen. gdb-6.3 simply
3284 ignores these. */
sewardj5d616df2013-07-02 08:07:15 +00003285 /*off = */ (void)step_leb128( &instr, 0 );
sewardjb8b79ad2008-03-03 01:35:41 +00003286 if (di->ddump_frames)
sewardj3646a492007-02-16 14:17:10 +00003287 VG_(printf)(" rci:DW_CFA_GNU_args_size (ignored)\n");
sewardj5c638c22005-04-30 07:55:58 +00003288 break;
sewardj325ec872005-05-01 20:24:06 +00003289
sewardj5d616df2013-07-02 08:07:15 +00003290 case DW_CFA_expression: {
sewardj19dc88f2007-02-28 01:46:30 +00003291 /* Identical to DW_CFA_val_expression except that the value
3292 computed is an address and so needs one final
3293 dereference. */
sewardj5d616df2013-07-02 08:07:15 +00003294 DiCursor expr;
3295 reg = step_leb128( &instr, 0 );
3296 len = step_leb128( &instr, 0 );
3297 expr = instr;
3298 instr = ML_(cur_plus)(instr, len);
sewardj19dc88f2007-02-28 01:46:30 +00003299 if (reg < 0 || reg >= N_CFI_REGS)
sewardj1e601fe2005-05-16 11:48:34 +00003300 return 0; /* fail */
sewardjb8b79ad2008-03-03 01:35:41 +00003301 if (di->ddump_frames)
sewardj19dc88f2007-02-28 01:46:30 +00003302 VG_(printf)(" DW_CFA_expression: r%d (",
3303 (Int)reg);
3304 /* Convert the expression into a dag rooted at ctx->exprs index j,
3305 or fail. */
3306 j = dwarfexpr_to_dag ( ctx, expr, len, True/*push CFA at start*/,
sewardjb8b79ad2008-03-03 01:35:41 +00003307 di->ddump_frames);
3308 if (di->ddump_frames)
sewardj19dc88f2007-02-28 01:46:30 +00003309 VG_(printf)(")\n");
3310 vg_assert(j >= -1);
3311 if (j >= 0) {
3312 vg_assert(ctx->exprs);
3313 vg_assert( j < VG_(sizeXA)(ctx->exprs) );
3314 }
3315 if (j == -1)
3316 return 0; /* fail */
3317 /* Add an extra dereference */
3318 j = ML_(CfiExpr_Deref)( ctx->exprs, j );
sewardjde1b03d2009-08-03 13:47:04 +00003319 ctxs->reg[reg].tag = RR_ValExpr;
3320 ctxs->reg[reg].arg = j;
sewardj1e601fe2005-05-16 11:48:34 +00003321 break;
sewardj5d616df2013-07-02 08:07:15 +00003322 }
sewardj1e601fe2005-05-16 11:48:34 +00003323
sewardj5d616df2013-07-02 08:07:15 +00003324 case DW_CFA_val_expression: {
3325 DiCursor expr;
3326 reg = step_leb128( &instr, 0 );
3327 len = step_leb128( &instr, 0 );
3328 expr = instr;
3329 instr = ML_(cur_plus)(instr, len);
sewardjd69222c2006-04-08 16:22:53 +00003330 if (reg < 0 || reg >= N_CFI_REGS)
3331 return 0; /* fail */
sewardjb8b79ad2008-03-03 01:35:41 +00003332 if (di->ddump_frames)
sewardj72427fa2007-02-27 16:52:23 +00003333 VG_(printf)(" DW_CFA_val_expression: r%d (",
sewardj687bbf62007-02-16 20:11:27 +00003334 (Int)reg);
sewardj72427fa2007-02-27 16:52:23 +00003335 /* Convert the expression into a dag rooted at ctx->exprs index j,
3336 or fail. */
3337 j = dwarfexpr_to_dag ( ctx, expr, len, True/*push CFA at start*/,
sewardjb8b79ad2008-03-03 01:35:41 +00003338 di->ddump_frames);
3339 if (di->ddump_frames)
sewardj72427fa2007-02-27 16:52:23 +00003340 VG_(printf)(")\n");
3341 vg_assert(j >= -1);
3342 if (j >= 0) {
3343 vg_assert(ctx->exprs);
3344 vg_assert( j < VG_(sizeXA)(ctx->exprs) );
3345 }
3346 if (j == -1)
3347 return 0; /* fail */
sewardjde1b03d2009-08-03 13:47:04 +00003348 ctxs->reg[reg].tag = RR_ValExpr;
3349 ctxs->reg[reg].arg = j;
sewardjd69222c2006-04-08 16:22:53 +00003350 break;
sewardj5d616df2013-07-02 08:07:15 +00003351 }
sewardjd69222c2006-04-08 16:22:53 +00003352
sewardj5d616df2013-07-02 08:07:15 +00003353 case DW_CFA_def_cfa_expression: {
3354 DiCursor expr;
3355 len = step_leb128( &instr, 0 );
3356 expr = instr;
3357 instr = ML_(cur_plus)(instr, len);
sewardjb8b79ad2008-03-03 01:35:41 +00003358 if (di->ddump_frames)
sewardj7888e222007-02-28 13:03:27 +00003359 VG_(printf)(" DW_CFA_def_cfa_expression (");
3360 /* Convert the expression into a dag rooted at ctx->exprs index j,
3361 or fail. */
3362 j = dwarfexpr_to_dag ( ctx, expr, len, True/*push CFA at start*/,
sewardjb8b79ad2008-03-03 01:35:41 +00003363 di->ddump_frames);
3364 if (di->ddump_frames)
sewardj7888e222007-02-28 13:03:27 +00003365 VG_(printf)(")\n");
sewardjde1b03d2009-08-03 13:47:04 +00003366 ctxs->cfa_is_regoff = False;
3367 ctxs->cfa_reg = 0;
3368 ctxs->cfa_off = 0;
3369 ctxs->cfa_expr_ix = j;
sewardj1e601fe2005-05-16 11:48:34 +00003370 break;
sewardj5d616df2013-07-02 08:07:15 +00003371 }
sewardj1e601fe2005-05-16 11:48:34 +00003372
sewardj0cd71772005-05-16 18:25:09 +00003373 case DW_CFA_GNU_window_save:
3374 /* Ignored. This appears to be sparc-specific; quite why it
3375 turns up in SuSE-supplied x86 .so's beats me. */
sewardjb8b79ad2008-03-03 01:35:41 +00003376 if (di->ddump_frames)
sewardj3d026b12009-05-21 15:33:36 +00003377 VG_(printf)(" DW_CFA_GNU_window_save\n");
3378 break;
3379
3380 case DW_CFA_remember_state:
3381 if (di->ddump_frames)
3382 VG_(printf)(" DW_CFA_remember_state\n");
3383 /* we just checked this at entry, so: */
sewardjde1b03d2009-08-03 13:47:04 +00003384 vg_assert(ctx->state_sp >= 0 && ctx->state_sp < N_RR_STACK);
3385 ctx->state_sp++;
3386 if (ctx->state_sp == N_RR_STACK) {
sewardj3d026b12009-05-21 15:33:36 +00003387 /* stack overflow. We're hosed. */
3388 VG_(message)(Vg_DebugMsg, "DWARF2 CFI reader: N_RR_STACK is "
3389 "too low; increase and recompile.");
sewardj5d616df2013-07-02 08:07:15 +00003390 return 0; /* indicate failure */
sewardj3d026b12009-05-21 15:33:36 +00003391 } else {
sewardjde1b03d2009-08-03 13:47:04 +00003392 VG_(memcpy)(/*dst*/&ctx->state[ctx->state_sp],
3393 /*src*/&ctx->state[ctx->state_sp - 1],
3394 sizeof(ctx->state[ctx->state_sp]) );
sewardj3d026b12009-05-21 15:33:36 +00003395 }
3396 break;
3397
3398 case DW_CFA_restore_state:
3399 if (di->ddump_frames)
3400 VG_(printf)(" DW_CFA_restore_state\n");
3401 /* we just checked this at entry, so: */
sewardjde1b03d2009-08-03 13:47:04 +00003402 vg_assert(ctx->state_sp >= 0 && ctx->state_sp < N_RR_STACK);
3403 if (ctx->state_sp == 0) {
sewardj5d616df2013-07-02 08:07:15 +00003404 /* stack undefflow. Give up. */
3405 return 0; /* indicate failure */
sewardj3d026b12009-05-21 15:33:36 +00003406 } else {
3407 /* simply fall back to previous entry */
sewardjde1b03d2009-08-03 13:47:04 +00003408 ctx->state_sp--;
sewardj3d026b12009-05-21 15:33:36 +00003409 }
sewardj0cd71772005-05-16 18:25:09 +00003410 break;
3411
sewardj5c638c22005-04-30 07:55:58 +00003412 default:
sewardj55022aa2005-05-03 16:05:00 +00003413 VG_(message)(Vg_DebugMsg, "DWARF2 CFI reader: unhandled CFI "
sewardj738856f2009-07-15 14:48:32 +00003414 "instruction 0:%d\n", (Int)lo6);
sewardjb8b79ad2008-03-03 01:35:41 +00003415 if (di->ddump_frames)
sewardj3646a492007-02-16 14:17:10 +00003416 VG_(printf)(" rci:run_CF_instruction:default\n");
sewardj5d616df2013-07-02 08:07:15 +00003417 return 0; /* failure */
3418 /*NOTREACHED*/
sewardj5c638c22005-04-30 07:55:58 +00003419 }
3420
sewardj5d616df2013-07-02 08:07:15 +00003421 return ML_(cur_minus)(instr, instrIN);
sewardj5c638c22005-04-30 07:55:58 +00003422}
3423
3424
sewardj3646a492007-02-16 14:17:10 +00003425/* Show a CFI instruction, and also return its length. Show it as
3426 close as possible (preferably identical) to how GNU binutils
3427 readelf --debug-dump=frames would. */
sewardj55022aa2005-05-03 16:05:00 +00003428
sewardj5d616df2013-07-02 08:07:15 +00003429static Int show_CF_instruction ( DiCursor instrIN,
sewardj3646a492007-02-16 14:17:10 +00003430 AddressDecodingInfo* adi,
3431 Int code_a_f, Int data_a_f )
sewardj5c638c22005-04-30 07:55:58 +00003432{
sewardj5d616df2013-07-02 08:07:15 +00003433 Int off, coff, reg, reg2, len;
3434 UInt delta;
3435 Addr loc;
3436 DiCursor instr = instrIN;
3437 UChar instr_0 = ML_(cur_step_UChar)(&instr);
3438 UChar hi2 = (instr_0 >> 6) & 3;
3439 UChar lo6 = instr_0 & 0x3F;
sewardj5c638c22005-04-30 07:55:58 +00003440
sewardj5d616df2013-07-02 08:07:15 +00003441 if (0) {
3442 DiCursor tmpi = instrIN;
3443 UInt i_0 = ML_(cur_step_UChar)(&tmpi);
3444 UInt i_1 = ML_(cur_step_UChar)(&tmpi);
3445 UInt i_2 = ML_(cur_step_UChar)(&tmpi);
3446 UInt i_3 = ML_(cur_step_UChar)(&tmpi);
3447 UInt i_4 = ML_(cur_step_UChar)(&tmpi);
3448 UInt i_5 = ML_(cur_step_UChar)(&tmpi);
3449 UInt i_6 = ML_(cur_step_UChar)(&tmpi);
3450 UInt i_7 = ML_(cur_step_UChar)(&tmpi);
3451 VG_(printf)("raw:%x/%x:%x:%x:%x:%x:%x:%x:%x:%x\n",
3452 hi2, lo6, i_0, i_1, i_2, i_3, i_4, i_5, i_6, i_7);
3453 }
tom2fd38902005-05-01 15:14:01 +00003454
sewardj5c638c22005-04-30 07:55:58 +00003455 if (hi2 == DW_CFA_advance_loc) {
sewardj3646a492007-02-16 14:17:10 +00003456 VG_(printf)(" sci:DW_CFA_advance_loc(%d)\n", (Int)lo6);
sewardj5d616df2013-07-02 08:07:15 +00003457 return ML_(cur_minus)(instr, instrIN);
sewardj5c638c22005-04-30 07:55:58 +00003458 }
3459
3460 if (hi2 == DW_CFA_offset) {
sewardj5d616df2013-07-02 08:07:15 +00003461 off = step_leb128( &instr, 0 );
sewardj3646a492007-02-16 14:17:10 +00003462 coff = off * data_a_f;
3463 VG_(printf)(" DW_CFA_offset: r%d at cfa%s%d\n",
3464 (Int)lo6, coff < 0 ? "" : "+", (Int)coff );
sewardj5d616df2013-07-02 08:07:15 +00003465 return ML_(cur_minus)(instr, instrIN);
sewardj5c638c22005-04-30 07:55:58 +00003466 }
3467
3468 if (hi2 == DW_CFA_restore) {
sewardj3646a492007-02-16 14:17:10 +00003469 VG_(printf)(" sci:DW_CFA_restore(r%d)\n", (Int)lo6);
sewardj5d616df2013-07-02 08:07:15 +00003470 return ML_(cur_minus)(instr, instrIN);
sewardj5c638c22005-04-30 07:55:58 +00003471 }
3472
3473 vg_assert(hi2 == DW_CFA_use_secondary);
3474
3475 switch (lo6) {
3476
3477 case DW_CFA_nop:
sewardj3646a492007-02-16 14:17:10 +00003478 VG_(printf)(" DW_CFA_nop\n");
sewardj5c638c22005-04-30 07:55:58 +00003479 break;
3480
tom2fd38902005-05-01 15:14:01 +00003481 case DW_CFA_set_loc:
sewardjddf006d2007-02-24 23:29:31 +00003482 /* WAS: loc = read_Addr(&instr[i]); i+= sizeof(Addr);
3483 (now known to be incorrect -- the address is encoded) */
sewardj5d616df2013-07-02 08:07:15 +00003484 loc = step_encoded_Addr(adi, &instr);
barta0b6b2c2008-07-07 06:49:24 +00003485 VG_(printf)(" sci:DW_CFA_set_loc(%#lx)\n", loc);
tom2fd38902005-05-01 15:14:01 +00003486 break;
3487
sewardj5c638c22005-04-30 07:55:58 +00003488 case DW_CFA_advance_loc1:
sewardj5d616df2013-07-02 08:07:15 +00003489 delta = (UInt)ML_(cur_step_UChar)(&instr);
sewardj3646a492007-02-16 14:17:10 +00003490 VG_(printf)(" sci:DW_CFA_advance_loc1(%d)\n", delta);
sewardj5c638c22005-04-30 07:55:58 +00003491 break;
3492
tom2fd38902005-05-01 15:14:01 +00003493 case DW_CFA_advance_loc2:
sewardj5d616df2013-07-02 08:07:15 +00003494 delta = (UInt)ML_(cur_step_UShort)(&instr);
sewardj3646a492007-02-16 14:17:10 +00003495 VG_(printf)(" sci:DW_CFA_advance_loc2(%d)\n", delta);
tom2fd38902005-05-01 15:14:01 +00003496 break;
3497
3498 case DW_CFA_advance_loc4:
sewardj5d616df2013-07-02 08:07:15 +00003499 delta = (UInt)ML_(cur_step_UInt)(&instr);
sewardjddf006d2007-02-24 23:29:31 +00003500 VG_(printf)(" DW_CFA_advance_loc4(%d)\n", delta);
tom2fd38902005-05-01 15:14:01 +00003501 break;
3502
sewardj5c638c22005-04-30 07:55:58 +00003503 case DW_CFA_def_cfa:
sewardj5d616df2013-07-02 08:07:15 +00003504 reg = step_leb128( &instr, 0 );
3505 off = step_leb128( &instr, 0 );
sewardj3646a492007-02-16 14:17:10 +00003506 VG_(printf)(" DW_CFA_def_cfa: r%d ofs %d\n", (Int)reg, (Int)off);
sewardj5c638c22005-04-30 07:55:58 +00003507 break;
3508
sewardjd69222c2006-04-08 16:22:53 +00003509 case DW_CFA_def_cfa_sf:
sewardj5d616df2013-07-02 08:07:15 +00003510 reg = step_leb128( &instr, 0 );
3511 off = step_leb128( &instr, 1 );
sewardj8c90d272007-02-16 19:20:28 +00003512 VG_(printf)(" DW_CFA_def_cfa_sf: r%d ofs %d\n",
3513 (Int)reg, (Int)(off * data_a_f));
sewardjd69222c2006-04-08 16:22:53 +00003514 break;
3515
sewardje0707a62005-05-02 12:25:13 +00003516 case DW_CFA_register:
sewardj5d616df2013-07-02 08:07:15 +00003517 reg = step_leb128( &instr, 0);
3518 reg2 = step_leb128( &instr, 0);
sewardj3646a492007-02-16 14:17:10 +00003519 VG_(printf)(" sci:DW_CFA_register(r%d, r%d)\n", reg, reg2);
sewardje0707a62005-05-02 12:25:13 +00003520 break;
3521
sewardj5c638c22005-04-30 07:55:58 +00003522 case DW_CFA_def_cfa_register:
sewardj5d616df2013-07-02 08:07:15 +00003523 reg = step_leb128( &instr, 0);
sewardj3646a492007-02-16 14:17:10 +00003524 VG_(printf)(" sci:DW_CFA_def_cfa_register(r%d)\n", reg);
sewardj5c638c22005-04-30 07:55:58 +00003525 break;
3526
3527 case DW_CFA_def_cfa_offset:
sewardj5d616df2013-07-02 08:07:15 +00003528 off = step_leb128( &instr, 0);
sewardj3646a492007-02-16 14:17:10 +00003529 VG_(printf)(" sci:DW_CFA_def_cfa_offset(%d)\n", off);
sewardj5c638c22005-04-30 07:55:58 +00003530 break;
3531
sewardjd69222c2006-04-08 16:22:53 +00003532 case DW_CFA_def_cfa_offset_sf:
sewardj5d616df2013-07-02 08:07:15 +00003533 off = step_leb128( &instr, 1);
sewardj3646a492007-02-16 14:17:10 +00003534 VG_(printf)(" sci:DW_CFA_def_cfa_offset_sf(%d)\n", off);
sewardjd69222c2006-04-08 16:22:53 +00003535 break;
3536
3537 case DW_CFA_restore_extended:
sewardj5d616df2013-07-02 08:07:15 +00003538 reg = step_leb128( &instr, 0);
sewardj3646a492007-02-16 14:17:10 +00003539 VG_(printf)(" sci:DW_CFA_restore_extended(r%d)\n", reg);
sewardjd69222c2006-04-08 16:22:53 +00003540 break;
3541
3542 case DW_CFA_undefined:
sewardj5d616df2013-07-02 08:07:15 +00003543 reg = step_leb128( &instr, 0);
sewardj3646a492007-02-16 14:17:10 +00003544 VG_(printf)(" sci:DW_CFA_undefined(r%d)\n", reg);
sewardjd69222c2006-04-08 16:22:53 +00003545 break;
3546
3547 case DW_CFA_same_value:
sewardj5d616df2013-07-02 08:07:15 +00003548 reg = step_leb128( &instr, 0);
sewardj3646a492007-02-16 14:17:10 +00003549 VG_(printf)(" sci:DW_CFA_same_value(r%d)\n", reg);
sewardjd69222c2006-04-08 16:22:53 +00003550 break;
3551
3552 case DW_CFA_remember_state:
sewardj3646a492007-02-16 14:17:10 +00003553 VG_(printf)(" sci:DW_CFA_remember_state\n");
sewardjd69222c2006-04-08 16:22:53 +00003554 break;
3555
3556 case DW_CFA_restore_state:
sewardj3646a492007-02-16 14:17:10 +00003557 VG_(printf)(" sci:DW_CFA_restore_state\n");
sewardjd69222c2006-04-08 16:22:53 +00003558 break;
3559
sewardj5c638c22005-04-30 07:55:58 +00003560 case DW_CFA_GNU_args_size:
sewardj5d616df2013-07-02 08:07:15 +00003561 off = step_leb128( &instr, 0 );
sewardj3646a492007-02-16 14:17:10 +00003562 VG_(printf)(" sci:DW_CFA_GNU_args_size(%d)\n", off );
sewardj5c638c22005-04-30 07:55:58 +00003563 break;
3564
sewardj1e601fe2005-05-16 11:48:34 +00003565 case DW_CFA_def_cfa_expression:
sewardj5d616df2013-07-02 08:07:15 +00003566 len = step_leb128( &instr, 0 );
3567 instr = ML_(cur_plus)(instr, len);
sewardj3646a492007-02-16 14:17:10 +00003568 VG_(printf)(" sci:DW_CFA_def_cfa_expression(length %d)\n", len);
sewardj1e601fe2005-05-16 11:48:34 +00003569 break;
3570
3571 case DW_CFA_expression:
sewardj5d616df2013-07-02 08:07:15 +00003572 reg = step_leb128( &instr, 0 );
3573 len = step_leb128( &instr, 0 );
3574 instr = ML_(cur_plus)(instr, len);
sewardj3646a492007-02-16 14:17:10 +00003575 VG_(printf)(" sci:DW_CFA_expression(r%d, length %d)\n", reg, len);
sewardj1e601fe2005-05-16 11:48:34 +00003576 break;
3577
sewardjd69222c2006-04-08 16:22:53 +00003578 case DW_CFA_val_expression:
sewardj5d616df2013-07-02 08:07:15 +00003579 reg = step_leb128( &instr, 0 );
3580 len = step_leb128( &instr, 0 );
3581 instr = ML_(cur_plus)(instr, len);
sewardj3646a492007-02-16 14:17:10 +00003582 VG_(printf)(" sci:DW_CFA_val_expression(r%d, length %d)\n", reg, len);
sewardjd69222c2006-04-08 16:22:53 +00003583 break;
3584
3585 case DW_CFA_offset_extended:
sewardj5d616df2013-07-02 08:07:15 +00003586 reg = step_leb128( &instr, 0 );
3587 off = step_leb128( &instr, 0 );
sewardj3646a492007-02-16 14:17:10 +00003588 VG_(printf)(" sci:DW_CFA_offset_extended(r%d, "
3589 "off %d x data_af)\n", reg, off);
sewardjd69222c2006-04-08 16:22:53 +00003590 break;
3591
sewardjddf006d2007-02-24 23:29:31 +00003592 case DW_CFA_offset_extended_sf:
sewardj5d616df2013-07-02 08:07:15 +00003593 reg = step_leb128( &instr, 0 );
3594 off = step_leb128( &instr, 1 );
sewardjddf006d2007-02-24 23:29:31 +00003595 coff = (Int)(off * data_a_f);
3596 VG_(printf)(" DW_CFA_offset_extended_sf: r%d at cfa%s%d\n",
3597 reg, coff < 0 ? "" : "+", coff);
sewardjd69222c2006-04-08 16:22:53 +00003598 break;
3599
3600 case DW_CFA_GNU_negative_offset_extended:
sewardj5d616df2013-07-02 08:07:15 +00003601 reg = step_leb128( &instr, 0 );
3602 off = step_leb128( &instr, 0 );
sewardj3646a492007-02-16 14:17:10 +00003603 VG_(printf)(" sci:DW_CFA_GNU_negative_offset_extended"
3604 "(r%d, off %d x data_af)\n", reg, -off);
sewardjd69222c2006-04-08 16:22:53 +00003605 break;
3606
3607 case DW_CFA_val_offset:
sewardj5d616df2013-07-02 08:07:15 +00003608 reg = step_leb128( &instr, 0 );
3609 off = step_leb128( &instr, 0 );
sewardj3646a492007-02-16 14:17:10 +00003610 VG_(printf)(" sci:DW_CFA_val_offset(r%d, off %d x data_af)\n",
3611 reg, off);
sewardjd69222c2006-04-08 16:22:53 +00003612 break;
3613
3614 case DW_CFA_val_offset_sf:
sewardj5d616df2013-07-02 08:07:15 +00003615 reg = step_leb128( &instr, 0 );
3616 off = step_leb128( &instr, 1 );
sewardj3646a492007-02-16 14:17:10 +00003617 VG_(printf)(" sci:DW_CFA_val_offset_sf(r%d, off %d x data_af)\n",
3618 reg, off);
sewardjd69222c2006-04-08 16:22:53 +00003619 break;
3620
sewardj0cd71772005-05-16 18:25:09 +00003621 case DW_CFA_GNU_window_save:
sewardj3646a492007-02-16 14:17:10 +00003622 VG_(printf)(" sci:DW_CFA_GNU_window_save\n");
sewardj0cd71772005-05-16 18:25:09 +00003623 break;
3624
sewardj5c638c22005-04-30 07:55:58 +00003625 default:
sewardj3646a492007-02-16 14:17:10 +00003626 VG_(printf)(" sci:0:%d\n", (Int)lo6);
sewardj5c638c22005-04-30 07:55:58 +00003627 break;
3628 }
3629
sewardj5d616df2013-07-02 08:07:15 +00003630 return ML_(cur_minus)(instr, instrIN);
sewardj5c638c22005-04-30 07:55:58 +00003631}
3632
3633
sewardj3646a492007-02-16 14:17:10 +00003634/* Show the instructions in instrs[0 .. ilen-1]. */
sewardj5d616df2013-07-02 08:07:15 +00003635static void show_CF_instructions ( DiCursor instrs, Int ilen,
sewardj3646a492007-02-16 14:17:10 +00003636 AddressDecodingInfo* adi,
3637 Int code_a_f, Int data_a_f )
sewardj5c638c22005-04-30 07:55:58 +00003638{
3639 Int i = 0;
3640 while (True) {
3641 if (i >= ilen) break;
sewardj5d616df2013-07-02 08:07:15 +00003642 i += show_CF_instruction( ML_(cur_plus)(instrs, i),
3643 adi, code_a_f, data_a_f );
sewardj5c638c22005-04-30 07:55:58 +00003644 }
3645}
3646
sewardj3891dd42007-01-12 19:03:19 +00003647
sewardj5c638c22005-04-30 07:55:58 +00003648/* Run the CF instructions in instrs[0 .. ilen-1], until the end is
3649 reached, or until there is a failure. Return True iff success.
3650*/
3651static
sewardjb8b79ad2008-03-03 01:35:41 +00003652Bool run_CF_instructions ( struct _DebugInfo* di,
sewardj3646a492007-02-16 14:17:10 +00003653 Bool record,
sewardj5d616df2013-07-02 08:07:15 +00003654 UnwindContext* ctx, DiCursor instrs, Int ilen,
sewardj8eb41322005-05-01 23:50:08 +00003655 UWord fde_arange,
sewardj1936f8b2006-11-16 12:21:52 +00003656 UnwindContext* restore_ctx,
3657 AddressDecodingInfo* adi )
sewardj5c638c22005-04-30 07:55:58 +00003658{
sewardjeadcd862006-04-04 15:12:44 +00003659 DiCfSI cfsi;
sewardj3a7cb972005-05-02 00:34:19 +00003660 Bool summ_ok;
sewardj5c638c22005-04-30 07:55:58 +00003661 Int j, i = 0;
sewardj35165532005-04-30 18:47:48 +00003662 Addr loc_prev;
3663 if (0) ppUnwindContext(ctx);
tom2fd38902005-05-01 15:14:01 +00003664 if (0) ppUnwindContext_summary(ctx);
sewardj5c638c22005-04-30 07:55:58 +00003665 while (True) {
sewardj35165532005-04-30 18:47:48 +00003666 loc_prev = ctx->loc;
sewardj5c638c22005-04-30 07:55:58 +00003667 if (i >= ilen) break;
sewardj5d616df2013-07-02 08:07:15 +00003668 if (0) (void)show_CF_instruction( ML_(cur_plus)(instrs,i), adi,
sewardj3646a492007-02-16 14:17:10 +00003669 ctx->code_a_f, ctx->data_a_f );
sewardj5d616df2013-07-02 08:07:15 +00003670 j = run_CF_instruction( ctx, ML_(cur_plus)(instrs,i),
3671 restore_ctx, adi, di );
sewardj5c638c22005-04-30 07:55:58 +00003672 if (j == 0)
3673 return False; /* execution failed */
3674 i += j;
sewardj35165532005-04-30 18:47:48 +00003675 if (0) ppUnwindContext(ctx);
sewardj3646a492007-02-16 14:17:10 +00003676 if (record && loc_prev != ctx->loc) {
sewardjb8b79ad2008-03-03 01:35:41 +00003677 summ_ok = summarise_context ( &cfsi, loc_prev, ctx, di );
sewardj3a7cb972005-05-02 00:34:19 +00003678 if (summ_ok) {
sewardjb8b79ad2008-03-03 01:35:41 +00003679 ML_(addDiCfSI)(di, &cfsi);
3680 if (di->trace_cfi)
3681 ML_(ppDiCfSI)(di->cfsi_exprs, &cfsi);
sewardj3a7cb972005-05-02 00:34:19 +00003682 }
sewardj35165532005-04-30 18:47:48 +00003683 }
3684 }
3685 if (ctx->loc < fde_arange) {
3686 loc_prev = ctx->loc;
3687 ctx->loc = fde_arange;
sewardj3646a492007-02-16 14:17:10 +00003688 if (record) {
sewardjb8b79ad2008-03-03 01:35:41 +00003689 summ_ok = summarise_context ( &cfsi, loc_prev, ctx, di );
sewardj3a7cb972005-05-02 00:34:19 +00003690 if (summ_ok) {
sewardjb8b79ad2008-03-03 01:35:41 +00003691 ML_(addDiCfSI)(di, &cfsi);
3692 if (di->trace_cfi)
3693 ML_(ppDiCfSI)(di->cfsi_exprs, &cfsi);
sewardj3a7cb972005-05-02 00:34:19 +00003694 }
sewardj35165532005-04-30 18:47:48 +00003695 }
sewardj5c638c22005-04-30 07:55:58 +00003696 }
3697 return True;
3698}
3699
3700
sewardj55022aa2005-05-03 16:05:00 +00003701/* ------------ Main entry point for CFI reading ------------ */
3702
sewardj726baec2005-06-09 19:27:25 +00003703typedef
3704 struct {
3705 /* This gives the CIE an identity to which FDEs will refer. */
sewardj5d616df2013-07-02 08:07:15 +00003706 ULong offset;
sewardj726baec2005-06-09 19:27:25 +00003707 /* Code, data factors. */
sewardj5d616df2013-07-02 08:07:15 +00003708 Int code_a_f;
3709 Int data_a_f;
sewardj726baec2005-06-09 19:27:25 +00003710 /* Return-address pseudo-register. */
sewardj5d616df2013-07-02 08:07:15 +00003711 Int ra_reg;
3712 UChar address_encoding;
3713 /* Where are the instrs? */
3714 DiCursor instrs;
3715 Int ilen;
sewardj726baec2005-06-09 19:27:25 +00003716 /* God knows .. don't ask */
sewardj5d616df2013-07-02 08:07:15 +00003717 Bool saw_z_augmentation;
sewardj726baec2005-06-09 19:27:25 +00003718 }
3719 CIE;
3720
3721static void init_CIE ( CIE* cie )
3722{
3723 cie->offset = 0;
3724 cie->code_a_f = 0;
3725 cie->data_a_f = 0;
3726 cie->ra_reg = 0;
3727 cie->address_encoding = 0;
sewardj5d616df2013-07-02 08:07:15 +00003728 cie->instrs = DiCursor_INVALID;
sewardj726baec2005-06-09 19:27:25 +00003729 cie->ilen = 0;
3730 cie->saw_z_augmentation = False;
3731}
3732
sewardjb36d3162013-09-19 09:14:56 +00003733#define N_CIEs 8000
sewardj726baec2005-06-09 19:27:25 +00003734static CIE the_CIEs[N_CIEs];
3735
3736
sewardj452e89a2011-05-30 10:18:59 +00003737/* Read, summarise and store CFA unwind info from .eh_frame and
3738 .debug_frame sections. is_ehframe tells us which kind we are
3739 dealing with -- they are slightly different. */
sewardj461d6c62007-02-23 10:10:02 +00003740void ML_(read_callframe_info_dwarf3)
sewardj452e89a2011-05-30 10:18:59 +00003741 ( /*OUT*/struct _DebugInfo* di,
sewardj5d616df2013-07-02 08:07:15 +00003742 DiSlice escn_frame, Addr frame_avma, Bool is_ehframe )
sewardj5c638c22005-04-30 07:55:58 +00003743{
florian6bd9dc12012-11-23 16:17:43 +00003744 const HChar* how = NULL;
sewardj5d616df2013-07-02 08:07:15 +00003745 Int n_CIEs = 0;
3746 DiCursor frame_image = ML_(cur_from_sli)(escn_frame); /* fixed */
3747 DiOffT frame_size = escn_frame.szB;
3748 DiCursor data = frame_image;
3749 UWord cfsi_used_orig;
sewardj452e89a2011-05-30 10:18:59 +00003750
3751 /* If we're dealing with a .debug_frame, assume zero frame_avma. */
3752 if (!is_ehframe)
3753 vg_assert(frame_avma == 0);
sewardj5c638c22005-04-30 07:55:58 +00003754
sewardj1936f8b2006-11-16 12:21:52 +00003755# if defined(VGP_ppc32_linux) || defined(VGP_ppc64_linux)
tom3c9cf342009-11-12 13:28:34 +00003756 /* These targets don't use CFI-based stack unwinding. */
cerion85665ca2005-06-20 15:51:07 +00003757 return;
sewardj1936f8b2006-11-16 12:21:52 +00003758# endif
cerion85665ca2005-06-20 15:51:07 +00003759
sewardj452e89a2011-05-30 10:18:59 +00003760 /* If we read more than one .debug_frame or .eh_frame for this
3761 DebugInfo*, the second and subsequent reads should only add FDEs
3762 for address ranges not already covered by the FDEs already
3763 present. To be able to quickly check which address ranges are
3764 already present, any existing records (DiCFSIs) must be sorted,
3765 so we can binary-search them in the code below. We also record
3766 di->cfsi_used so that we know where the boundary is between
3767 existing and new records. */
3768 if (di->cfsi_used > 0) {
tom3c9cf342009-11-12 13:28:34 +00003769 ML_(canonicaliseCFI) ( di );
tom3c9cf342009-11-12 13:28:34 +00003770 }
sewardj452e89a2011-05-30 10:18:59 +00003771 cfsi_used_orig = di->cfsi_used;
tom3c9cf342009-11-12 13:28:34 +00003772
sewardjb8b79ad2008-03-03 01:35:41 +00003773 if (di->trace_cfi) {
sewardj325ec872005-05-01 20:24:06 +00003774 VG_(printf)("\n-----------------------------------------------\n");
sewardj5d616df2013-07-02 08:07:15 +00003775 VG_(printf)("CFI info: szB %lld, _avma %#lx\n",
3776 escn_frame.szB, frame_avma );
3777 VG_(printf)("CFI info: name %s\n", di->fsm.filename );
sewardj325ec872005-05-01 20:24:06 +00003778 }
3779
sewardj5c638c22005-04-30 07:55:58 +00003780 /* Loop over CIEs/FDEs */
3781
sewardj726baec2005-06-09 19:27:25 +00003782 /* Conceptually, the frame info is a sequence of FDEs, one for each
3783 function. Inside an FDE is a miniature program for a special
3784 state machine, which, when run, produces the stack-unwinding
3785 info for that function.
3786
3787 Because the FDEs typically have much in common, and because the
3788 DWARF designers appear to have been fanatical about space
3789 saving, the common parts are factored out into so-called CIEs.
3790 That means that what we traverse is a sequence of structs, each
3791 of which is either a FDE (usually) or a CIE (occasionally).
3792 Each FDE has a field indicating which CIE is the one pertaining
3793 to it.
3794
3795 The following loop traverses the sequence. FDEs are dealt with
3796 immediately; once we harvest the useful info in an FDE, it is
3797 then forgotten about. By contrast, CIEs are validated and
3798 dumped into an array, because later FDEs may refer to any
3799 previously-seen CIE.
3800 */
sewardj5c638c22005-04-30 07:55:58 +00003801 while (True) {
sewardj5d616df2013-07-02 08:07:15 +00003802 DiCursor ciefde_start;
3803 ULong ciefde_len;
3804 ULong cie_pointer;
3805 Bool dw64;
sewardj5c638c22005-04-30 07:55:58 +00003806
sewardj325ec872005-05-01 20:24:06 +00003807 /* Are we done? */
sewardj5d616df2013-07-02 08:07:15 +00003808 if (ML_(cur_cmpEQ)(data, ML_(cur_plus)(frame_image, frame_size)))
sewardj325ec872005-05-01 20:24:06 +00003809 return;
sewardj5c638c22005-04-30 07:55:58 +00003810
sewardj325ec872005-05-01 20:24:06 +00003811 /* Overshot the end? Means something is wrong */
sewardj5d616df2013-07-02 08:07:15 +00003812 if (ML_(cur_cmpGT)(data, ML_(cur_plus)(frame_image, frame_size))) {
sewardj325ec872005-05-01 20:24:06 +00003813 how = "overran the end of .eh_frame";
3814 goto bad;
3815 }
sewardj5c638c22005-04-30 07:55:58 +00003816
sewardj325ec872005-05-01 20:24:06 +00003817 /* Ok, we must be looking at the start of a new CIE or FDE.
3818 Figure out which it is. */
sewardj5c638c22005-04-30 07:55:58 +00003819
tom60a4b0b2005-10-12 10:45:27 +00003820 ciefde_start = data;
sewardjb8b79ad2008-03-03 01:35:41 +00003821 if (di->trace_cfi)
sewardj5d616df2013-07-02 08:07:15 +00003822 VG_(printf)("\ncie/fde.start = (frame_image + 0x%llx)\n",
3823 ML_(cur_minus)(ciefde_start, frame_image));
sewardj5c638c22005-04-30 07:55:58 +00003824
sewardj5d616df2013-07-02 08:07:15 +00003825 ciefde_len = (ULong)ML_(cur_step_UInt)(&data);
sewardjb8b79ad2008-03-03 01:35:41 +00003826 if (di->trace_cfi)
sewardj461d6c62007-02-23 10:10:02 +00003827 VG_(printf)("cie/fde.length = %lld\n", ciefde_len);
sewardj5c638c22005-04-30 07:55:58 +00003828
3829 /* Apparently, if the .length field is zero, we are at the end
sewardj461d6c62007-02-23 10:10:02 +00003830 of the sequence. This is stated in the Generic Elf
3831 Specification (see comments far above here) and is one of the
3832 places where .eh_frame and .debug_frame data differ. */
sewardj5c638c22005-04-30 07:55:58 +00003833 if (ciefde_len == 0) {
sewardjb8b79ad2008-03-03 01:35:41 +00003834 if (di->ddump_frames)
sewardj5d616df2013-07-02 08:07:15 +00003835 VG_(printf)("%08llx ZERO terminator\n\n",
3836 ML_(cur_minus)(ciefde_start, frame_image));
sewardj461d6c62007-02-23 10:10:02 +00003837 return;
sewardj5c638c22005-04-30 07:55:58 +00003838 }
3839
sewardj461d6c62007-02-23 10:10:02 +00003840 /* If the .length field is 0xFFFFFFFF then we're dealing with
3841 64-bit DWARF, and the real length is stored as a 64-bit
3842 number immediately following it. */
3843 dw64 = False;
3844 if (ciefde_len == 0xFFFFFFFFUL) {
3845 dw64 = True;
sewardj5d616df2013-07-02 08:07:15 +00003846 ciefde_len = ML_(cur_step_ULong)(&data);
sewardj461d6c62007-02-23 10:10:02 +00003847 }
3848
3849 /* Now get the CIE ID, whose size depends on the DWARF 32 vs
3850 64-ness. */
3851 if (dw64) {
sewardj5d616df2013-07-02 08:07:15 +00003852 /* see XXX below */
3853 cie_pointer = ML_(cur_step_ULong)(&data);
sewardj461d6c62007-02-23 10:10:02 +00003854 } else {
sewardj5d616df2013-07-02 08:07:15 +00003855 /* see XXX below */
3856 cie_pointer = (ULong)ML_(cur_step_UInt)(&data);
sewardj461d6c62007-02-23 10:10:02 +00003857 }
3858
sewardjb8b79ad2008-03-03 01:35:41 +00003859 if (di->trace_cfi)
sewardj461d6c62007-02-23 10:10:02 +00003860 VG_(printf)("cie.pointer = %lld\n", cie_pointer);
sewardj5c638c22005-04-30 07:55:58 +00003861
tom3c9cf342009-11-12 13:28:34 +00003862 /* If cie_pointer is zero for .eh_frame or all ones for .debug_frame,
3863 we've got a CIE; else it's an FDE. */
sewardj452e89a2011-05-30 10:18:59 +00003864 if (cie_pointer == (is_ehframe ? 0ULL
tom3c9cf342009-11-12 13:28:34 +00003865 : dw64 ? 0xFFFFFFFFFFFFFFFFULL : 0xFFFFFFFFULL)) {
sewardj5c638c22005-04-30 07:55:58 +00003866
sewardj5d616df2013-07-02 08:07:15 +00003867 Int this_CIE;
3868 UChar cie_version;
3869 DiCursor cie_augmentation;
sewardj5c638c22005-04-30 07:55:58 +00003870
3871 /* --------- CIE --------- */
sewardjb8b79ad2008-03-03 01:35:41 +00003872 if (di->trace_cfi)
sewardj726baec2005-06-09 19:27:25 +00003873 VG_(printf)("------ new CIE (#%d of 0 .. %d) ------\n",
3874 n_CIEs, N_CIEs - 1);
3875
3876 /* Allocate a new CIE record. */
3877 vg_assert(n_CIEs >= 0 && n_CIEs <= N_CIEs);
3878 if (n_CIEs == N_CIEs) {
3879 how = "N_CIEs is too low. Increase and recompile.";
3880 goto bad;
3881 }
3882
3883 this_CIE = n_CIEs;
3884 n_CIEs++;
3885 init_CIE( &the_CIEs[this_CIE] );
3886
3887 /* Record its offset. This is how we will find it again
3888 later when looking at an FDE. */
sewardj5d616df2013-07-02 08:07:15 +00003889 the_CIEs[this_CIE].offset
3890 = (ULong)ML_(cur_minus)(ciefde_start, frame_image);
sewardj325ec872005-05-01 20:24:06 +00003891
sewardjb8b79ad2008-03-03 01:35:41 +00003892 if (di->ddump_frames)
sewardj3646a492007-02-16 14:17:10 +00003893 VG_(printf)("%08lx %08lx %08lx CIE\n",
sewardj5d616df2013-07-02 08:07:15 +00003894 (Addr)ML_(cur_minus)(ciefde_start, frame_image),
sewardj3646a492007-02-16 14:17:10 +00003895 (Addr)ciefde_len,
sewardj461d6c62007-02-23 10:10:02 +00003896 (Addr)(UWord)cie_pointer );
sewardj3646a492007-02-16 14:17:10 +00003897
sewardj5d616df2013-07-02 08:07:15 +00003898 cie_version = ML_(cur_step_UChar)(&data);
sewardjb8b79ad2008-03-03 01:35:41 +00003899 if (di->trace_cfi)
sewardj325ec872005-05-01 20:24:06 +00003900 VG_(printf)("cie.version = %d\n", (Int)cie_version);
sewardjb8b79ad2008-03-03 01:35:41 +00003901 if (di->ddump_frames)
sewardj3646a492007-02-16 14:17:10 +00003902 VG_(printf)(" Version: %d\n", (Int)cie_version);
tomfba428c2010-04-28 08:09:30 +00003903 if (cie_version != 1 && cie_version != 3 && cie_version != 4) {
3904 how = "unexpected CIE version (not 1 nor 3 nor 4)";
sewardj325ec872005-05-01 20:24:06 +00003905 goto bad;
3906 }
sewardj5c638c22005-04-30 07:55:58 +00003907
tom60a4b0b2005-10-12 10:45:27 +00003908 cie_augmentation = data;
sewardj5d616df2013-07-02 08:07:15 +00003909 data = ML_(cur_plus)(data, 1 + ML_(cur_strlen)(cie_augmentation));
sewardj5c638c22005-04-30 07:55:58 +00003910
sewardj5d616df2013-07-02 08:07:15 +00003911 if (di->trace_cfi || di->ddump_frames) {
3912 HChar* str = ML_(cur_read_strdup)(cie_augmentation, "di.rcid3.1");
3913 if (di->trace_cfi)
3914 VG_(printf)("cie.augment = \"%s\"\n", str);
3915 if (di->ddump_frames)
3916 VG_(printf)(" Augmentation: \"%s\"\n", str);
3917 ML_(dinfo_free)(str);
3918 }
3919
3920 if (ML_(cur_read_UChar)(cie_augmentation) == 'e'
3921 && ML_(cur_read_UChar)
3922 (ML_(cur_plus)(cie_augmentation, 1)) == 'h') {
3923 data = ML_(cur_plus)(data, sizeof(Addr));
3924 cie_augmentation = ML_(cur_plus)(cie_augmentation, 2);
sewardj5c638c22005-04-30 07:55:58 +00003925 }
3926
tomfba428c2010-04-28 08:09:30 +00003927 if (cie_version >= 4) {
sewardj5d616df2013-07-02 08:07:15 +00003928 if (ML_(cur_step_UChar)(&data) != sizeof(Addr)) {
tomfba428c2010-04-28 08:09:30 +00003929 how = "unexpected address size";
3930 goto bad;
3931 }
sewardj5d616df2013-07-02 08:07:15 +00003932 if (ML_(cur_step_UChar)(&data) != 0) {
tomfba428c2010-04-28 08:09:30 +00003933 how = "unexpected non-zero segment size";
3934 goto bad;
3935 }
tomfba428c2010-04-28 08:09:30 +00003936 }
3937
sewardj5d616df2013-07-02 08:07:15 +00003938 the_CIEs[this_CIE].code_a_f = step_leb128( &data, 0);
sewardjb8b79ad2008-03-03 01:35:41 +00003939 if (di->trace_cfi)
sewardj726baec2005-06-09 19:27:25 +00003940 VG_(printf)("cie.code_af = %d\n",
3941 the_CIEs[this_CIE].code_a_f);
sewardjb8b79ad2008-03-03 01:35:41 +00003942 if (di->ddump_frames)
sewardj3646a492007-02-16 14:17:10 +00003943 VG_(printf)(" Code alignment factor: %d\n",
3944 (Int)the_CIEs[this_CIE].code_a_f);
sewardj5c638c22005-04-30 07:55:58 +00003945
sewardj5d616df2013-07-02 08:07:15 +00003946 the_CIEs[this_CIE].data_a_f = step_leb128( &data, 1);
sewardjb8b79ad2008-03-03 01:35:41 +00003947 if (di->trace_cfi)
sewardj726baec2005-06-09 19:27:25 +00003948 VG_(printf)("cie.data_af = %d\n",
3949 the_CIEs[this_CIE].data_a_f);
sewardjb8b79ad2008-03-03 01:35:41 +00003950 if (di->ddump_frames)
sewardj3646a492007-02-16 14:17:10 +00003951 VG_(printf)(" Data alignment factor: %d\n",
3952 (Int)the_CIEs[this_CIE].data_a_f);
sewardj5c638c22005-04-30 07:55:58 +00003953
tom3c9cf342009-11-12 13:28:34 +00003954 if (cie_version == 1) {
sewardj5d616df2013-07-02 08:07:15 +00003955 the_CIEs[this_CIE].ra_reg = (Int)ML_(cur_step_UChar)(&data);
tom3c9cf342009-11-12 13:28:34 +00003956 } else {
sewardj5d616df2013-07-02 08:07:15 +00003957 the_CIEs[this_CIE].ra_reg = step_leb128( &data, 0);
tom3c9cf342009-11-12 13:28:34 +00003958 }
sewardjb8b79ad2008-03-03 01:35:41 +00003959 if (di->trace_cfi)
sewardj726baec2005-06-09 19:27:25 +00003960 VG_(printf)("cie.ra_reg = %d\n",
3961 the_CIEs[this_CIE].ra_reg);
sewardjb8b79ad2008-03-03 01:35:41 +00003962 if (di->ddump_frames)
sewardj3646a492007-02-16 14:17:10 +00003963 VG_(printf)(" Return address column: %d\n",
3964 (Int)the_CIEs[this_CIE].ra_reg);
3965
sewardj726baec2005-06-09 19:27:25 +00003966 if (the_CIEs[this_CIE].ra_reg < 0
3967 || the_CIEs[this_CIE].ra_reg >= N_CFI_REGS) {
sewardj5410cfd2005-05-13 12:17:33 +00003968 how = "cie.ra_reg has implausible value";
sewardj55022aa2005-05-03 16:05:00 +00003969 goto bad;
3970 }
sewardj5c638c22005-04-30 07:55:58 +00003971
sewardj726baec2005-06-09 19:27:25 +00003972 the_CIEs[this_CIE].saw_z_augmentation
sewardj5d616df2013-07-02 08:07:15 +00003973 = ML_(cur_read_UChar)(cie_augmentation) == 'z';
sewardj726baec2005-06-09 19:27:25 +00003974 if (the_CIEs[this_CIE].saw_z_augmentation) {
sewardj5d616df2013-07-02 08:07:15 +00003975 UInt length = step_leb128( &data, 0);
3976 the_CIEs[this_CIE].instrs = ML_(cur_plus)(data, length);
3977 cie_augmentation = ML_(cur_plus)(cie_augmentation, 1);
sewardjb8b79ad2008-03-03 01:35:41 +00003978 if (di->ddump_frames) {
sewardj3646a492007-02-16 14:17:10 +00003979 UInt i;
sewardj687bbf62007-02-16 20:11:27 +00003980 VG_(printf)(" Augmentation data: ");
sewardj3646a492007-02-16 14:17:10 +00003981 for (i = 0; i < length; i++)
sewardj5d616df2013-07-02 08:07:15 +00003982 VG_(printf)(" %02x", (UInt)ML_(cur_read_UChar)
3983 (ML_(cur_plus)(data, i)));
sewardj3646a492007-02-16 14:17:10 +00003984 VG_(printf)("\n");
3985 }
tom2fd38902005-05-01 15:14:01 +00003986 } else {
sewardj5d616df2013-07-02 08:07:15 +00003987 the_CIEs[this_CIE].instrs = DiCursor_INVALID;
tom2fd38902005-05-01 15:14:01 +00003988 }
3989
sewardj726baec2005-06-09 19:27:25 +00003990 the_CIEs[this_CIE].address_encoding = default_Addr_encoding();
tomf04fd622005-05-03 09:30:04 +00003991
sewardj5d616df2013-07-02 08:07:15 +00003992 while (ML_(cur_read_UChar)(cie_augmentation)) {
3993 switch (ML_(cur_read_UChar)(cie_augmentation)) {
tom2fd38902005-05-01 15:14:01 +00003994 case 'L':
sewardj5d616df2013-07-02 08:07:15 +00003995 data = ML_(cur_plus)(data, 1);
3996 cie_augmentation = ML_(cur_plus)(cie_augmentation, 1);
tom2fd38902005-05-01 15:14:01 +00003997 break;
3998 case 'R':
sewardj726baec2005-06-09 19:27:25 +00003999 the_CIEs[this_CIE].address_encoding
sewardj5d616df2013-07-02 08:07:15 +00004000 = ML_(cur_step_UChar)(&data);
4001 cie_augmentation = ML_(cur_plus)(cie_augmentation, 1);
tom2fd38902005-05-01 15:14:01 +00004002 break;
4003 case 'P':
sewardj5d616df2013-07-02 08:07:15 +00004004 data = ML_(cur_plus)(data, size_of_encoded_Addr(
4005 ML_(cur_read_UChar)(data) ));
4006 data = ML_(cur_plus)(data, 1);
4007 cie_augmentation = ML_(cur_plus)(cie_augmentation, 1);
tom2fd38902005-05-01 15:14:01 +00004008 break;
sewardjd69222c2006-04-08 16:22:53 +00004009 case 'S':
sewardj5d616df2013-07-02 08:07:15 +00004010 cie_augmentation = ML_(cur_plus)(cie_augmentation, 1);
sewardjd69222c2006-04-08 16:22:53 +00004011 break;
tom2fd38902005-05-01 15:14:01 +00004012 default:
sewardj5d616df2013-07-02 08:07:15 +00004013 if (!ML_(cur_is_valid)(the_CIEs[this_CIE].instrs)) {
tom2fd38902005-05-01 15:14:01 +00004014 how = "unhandled cie.augmentation";
4015 goto bad;
4016 }
sewardj726baec2005-06-09 19:27:25 +00004017 data = the_CIEs[this_CIE].instrs;
tom2fd38902005-05-01 15:14:01 +00004018 goto done_augmentation;
4019 }
4020 }
4021
4022 done_augmentation:
4023
sewardjb8b79ad2008-03-03 01:35:41 +00004024 if (di->trace_cfi)
sewardj726baec2005-06-09 19:27:25 +00004025 VG_(printf)("cie.encoding = 0x%x\n",
4026 the_CIEs[this_CIE].address_encoding);
tom2fd38902005-05-01 15:14:01 +00004027
sewardj726baec2005-06-09 19:27:25 +00004028 the_CIEs[this_CIE].instrs = data;
sewardj5d616df2013-07-02 08:07:15 +00004029 the_CIEs[this_CIE].ilen = ML_(cur_minus)(ciefde_start, data)
4030 + (Long)ciefde_len + (Long)sizeof(UInt);
sewardjb8b79ad2008-03-03 01:35:41 +00004031 if (di->trace_cfi) {
sewardj5d616df2013-07-02 08:07:15 +00004032 //VG_(printf)("cie.instrs = %p\n", the_CIEs[this_CIE].instrs);
sewardj726baec2005-06-09 19:27:25 +00004033 VG_(printf)("cie.ilen = %d\n", the_CIEs[this_CIE].ilen);
sewardj325ec872005-05-01 20:24:06 +00004034 }
sewardj5c638c22005-04-30 07:55:58 +00004035
sewardj726baec2005-06-09 19:27:25 +00004036 if (the_CIEs[this_CIE].ilen < 0
tom3c9cf342009-11-12 13:28:34 +00004037 || the_CIEs[this_CIE].ilen > frame_size) {
sewardj5c638c22005-04-30 07:55:58 +00004038 how = "implausible # cie initial insns";
4039 goto bad;
4040 }
4041
sewardj5d616df2013-07-02 08:07:15 +00004042 data = ML_(cur_plus)(data, the_CIEs[this_CIE].ilen);
sewardj5c638c22005-04-30 07:55:58 +00004043
sewardj3646a492007-02-16 14:17:10 +00004044 /* Show the CIE's instructions (the preamble for each FDE
4045 that uses this CIE). */
sewardjb8b79ad2008-03-03 01:35:41 +00004046 if (di->ddump_frames)
sewardj3646a492007-02-16 14:17:10 +00004047 VG_(printf)("\n");
4048
sewardjb8b79ad2008-03-03 01:35:41 +00004049 if (di->trace_cfi || di->ddump_frames) {
sewardj1936f8b2006-11-16 12:21:52 +00004050 AddressDecodingInfo adi;
sewardjc6d3f6f2007-01-11 19:42:11 +00004051 adi.encoding = the_CIEs[this_CIE].address_encoding;
tom3c9cf342009-11-12 13:28:34 +00004052 adi.ehframe_image = frame_image;
4053 adi.ehframe_avma = frame_avma;
tom402c9ee2009-03-09 09:19:03 +00004054 adi.text_bias = di->text_debug_bias;
sewardj3646a492007-02-16 14:17:10 +00004055 show_CF_instructions( the_CIEs[this_CIE].instrs,
4056 the_CIEs[this_CIE].ilen, &adi,
4057 the_CIEs[this_CIE].code_a_f,
4058 the_CIEs[this_CIE].data_a_f );
sewardj1936f8b2006-11-16 12:21:52 +00004059 }
sewardj5c638c22005-04-30 07:55:58 +00004060
sewardjb8b79ad2008-03-03 01:35:41 +00004061 if (di->ddump_frames)
sewardj3646a492007-02-16 14:17:10 +00004062 VG_(printf)("\n");
4063
sewardj5c638c22005-04-30 07:55:58 +00004064 } else {
4065
sewardj1936f8b2006-11-16 12:21:52 +00004066 AddressDecodingInfo adi;
sewardj726baec2005-06-09 19:27:25 +00004067 UnwindContext ctx, restore_ctx;
sewardj5d616df2013-07-02 08:07:15 +00004068 Int cie;
4069 ULong look_for;
4070 Bool ok;
4071 Addr fde_initloc;
4072 UWord fde_arange;
4073 DiCursor fde_instrs;
4074 Int fde_ilen;
sewardj726baec2005-06-09 19:27:25 +00004075
sewardj5c638c22005-04-30 07:55:58 +00004076 /* --------- FDE --------- */
4077
sewardj726baec2005-06-09 19:27:25 +00004078 /* Find the relevant CIE. The CIE we want is located
4079 cie_pointer bytes back from here. */
4080
sewardj461d6c62007-02-23 10:10:02 +00004081 /* re sizeof(UInt) / sizeof(ULong), matches XXX above. */
sewardj452e89a2011-05-30 10:18:59 +00004082 if (is_ehframe)
sewardj5d616df2013-07-02 08:07:15 +00004083 look_for = ML_(cur_minus)(data, frame_image)
4084 - (dw64 ? sizeof(ULong) : sizeof(UInt))
tom3c9cf342009-11-12 13:28:34 +00004085 - cie_pointer;
4086 else
4087 look_for = cie_pointer;
sewardj726baec2005-06-09 19:27:25 +00004088
4089 for (cie = 0; cie < n_CIEs; cie++) {
sewardj461d6c62007-02-23 10:10:02 +00004090 if (0) VG_(printf)("look for %lld %lld\n",
sewardj726baec2005-06-09 19:27:25 +00004091 look_for, the_CIEs[cie].offset );
4092 if (the_CIEs[cie].offset == look_for)
4093 break;
4094 }
4095 vg_assert(cie >= 0 && cie <= n_CIEs);
4096 if (cie == n_CIEs) {
4097 how = "FDE refers to not-findable CIE";
sewardj35165532005-04-30 18:47:48 +00004098 goto bad;
sewardj726baec2005-06-09 19:27:25 +00004099 }
sewardj5c638c22005-04-30 07:55:58 +00004100
sewardjc6d3f6f2007-01-11 19:42:11 +00004101 adi.encoding = the_CIEs[cie].address_encoding;
tom3c9cf342009-11-12 13:28:34 +00004102 adi.ehframe_image = frame_image;
4103 adi.ehframe_avma = frame_avma;
tom402c9ee2009-03-09 09:19:03 +00004104 adi.text_bias = di->text_debug_bias;
sewardj5d616df2013-07-02 08:07:15 +00004105 fde_initloc = step_encoded_Addr(&adi, &data);
sewardjb8b79ad2008-03-03 01:35:41 +00004106 if (di->trace_cfi)
barta0b6b2c2008-07-07 06:49:24 +00004107 VG_(printf)("fde.initloc = %#lx\n", fde_initloc);
sewardj5c638c22005-04-30 07:55:58 +00004108
sewardjc6d3f6f2007-01-11 19:42:11 +00004109 adi.encoding = the_CIEs[cie].address_encoding & 0xf;
tom3c9cf342009-11-12 13:28:34 +00004110 adi.ehframe_image = frame_image;
4111 adi.ehframe_avma = frame_avma;
tom402c9ee2009-03-09 09:19:03 +00004112 adi.text_bias = di->text_debug_bias;
sewardjddf006d2007-02-24 23:29:31 +00004113
4114 /* WAS (incorrectly):
4115 fde_arange = read_encoded_Addr(&nbytes, &adi, data);
4116 data += nbytes;
4117 The following corresponds to what binutils/dwarf.c does:
4118 */
4119 { UInt ptr_size = size_of_encoded_Addr( adi.encoding );
4120 switch (ptr_size) {
4121 case 8: case 4: case 2: case 1:
4122 fde_arange
sewardj5d616df2013-07-02 08:07:15 +00004123 = (UWord)step_le_u_encoded_literal(&data, ptr_size);
sewardjddf006d2007-02-24 23:29:31 +00004124 break;
4125 default:
4126 how = "unknown arange field encoding in FDE";
4127 goto bad;
4128 }
4129 }
4130
sewardjb8b79ad2008-03-03 01:35:41 +00004131 if (di->trace_cfi)
barta0b6b2c2008-07-07 06:49:24 +00004132 VG_(printf)("fde.arangec = %#lx\n", fde_arange);
sewardj5c638c22005-04-30 07:55:58 +00004133
sewardjb8b79ad2008-03-03 01:35:41 +00004134 if (di->ddump_frames)
sewardj3646a492007-02-16 14:17:10 +00004135 VG_(printf)("%08lx %08lx %08lx FDE cie=%08lx pc=%08lx..%08lx\n",
sewardj5d616df2013-07-02 08:07:15 +00004136 (Addr)ML_(cur_minus)(ciefde_start, frame_image),
sewardj3646a492007-02-16 14:17:10 +00004137 (Addr)ciefde_len,
sewardj461d6c62007-02-23 10:10:02 +00004138 (Addr)(UWord)cie_pointer,
sewardj3646a492007-02-16 14:17:10 +00004139 (Addr)look_for,
tom402c9ee2009-03-09 09:19:03 +00004140 ((Addr)fde_initloc) - di->text_debug_bias,
4141 ((Addr)fde_initloc) - di->text_debug_bias + fde_arange);
sewardj3646a492007-02-16 14:17:10 +00004142
sewardj726baec2005-06-09 19:27:25 +00004143 if (the_CIEs[cie].saw_z_augmentation) {
sewardj5d616df2013-07-02 08:07:15 +00004144 UInt length = step_leb128( &data, 0);
sewardjb8b79ad2008-03-03 01:35:41 +00004145 if (di->ddump_frames && (length > 0)) {
sewardj687bbf62007-02-16 20:11:27 +00004146 UInt i;
4147 VG_(printf)(" Augmentation data: ");
4148 for (i = 0; i < length; i++)
sewardj5d616df2013-07-02 08:07:15 +00004149 VG_(printf)(" %02x", (UInt)ML_(cur_read_UChar)
4150 (ML_(cur_plus)(data, i)));
sewardj687bbf62007-02-16 20:11:27 +00004151 VG_(printf)("\n\n");
4152 }
sewardj5d616df2013-07-02 08:07:15 +00004153 data = ML_(cur_plus)(data, length);
tom2fd38902005-05-01 15:14:01 +00004154 }
4155
tom60a4b0b2005-10-12 10:45:27 +00004156 fde_instrs = data;
sewardj5d616df2013-07-02 08:07:15 +00004157 fde_ilen = ML_(cur_minus)(ciefde_start, data)
4158 + (Long)ciefde_len + (Long)sizeof(UInt);
sewardjb8b79ad2008-03-03 01:35:41 +00004159 if (di->trace_cfi) {
sewardj5d616df2013-07-02 08:07:15 +00004160 //VG_(printf)("fde.instrs = %p\n", fde_instrs);
sewardj8eb41322005-05-01 23:50:08 +00004161 VG_(printf)("fde.ilen = %d\n", (Int)fde_ilen);
4162 }
sewardj5c638c22005-04-30 07:55:58 +00004163
tom3c9cf342009-11-12 13:28:34 +00004164 if (fde_ilen < 0 || fde_ilen > frame_size) {
sewardj325ec872005-05-01 20:24:06 +00004165 how = "implausible # fde insns";
sewardj5c638c22005-04-30 07:55:58 +00004166 goto bad;
4167 }
4168
sewardj5d616df2013-07-02 08:07:15 +00004169 data = ML_(cur_plus)(data, fde_ilen);
sewardj5c638c22005-04-30 07:55:58 +00004170
sewardj452e89a2011-05-30 10:18:59 +00004171 /* If this object's DebugInfo* had some DiCFSIs from a
4172 previous .eh_frame or .debug_frame read, we must check
4173 that we're not adding a duplicate. */
4174 if (cfsi_used_orig > 0) {
tom3c9cf342009-11-12 13:28:34 +00004175 Addr a_mid_lo, a_mid_hi;
4176 Word mid, size,
4177 lo = 0,
sewardj452e89a2011-05-30 10:18:59 +00004178 hi = cfsi_used_orig-1;
tom3c9cf342009-11-12 13:28:34 +00004179 while (True) {
4180 /* current unsearched space is from lo to hi, inclusive. */
4181 if (lo > hi) break; /* not found */
4182 mid = (lo + hi) / 2;
4183 a_mid_lo = di->cfsi[mid].base;
4184 size = di->cfsi[mid].len;
4185 a_mid_hi = a_mid_lo + size - 1;
4186 vg_assert(a_mid_hi >= a_mid_lo);
4187 if (fde_initloc + fde_arange <= a_mid_lo) {
4188 hi = mid-1; continue;
4189 }
4190 if (fde_initloc > a_mid_hi) { lo = mid+1; continue; }
4191 break;
4192 }
4193
4194 /* The range this .debug_frame FDE covers has been already
4195 covered in .eh_frame section. Don't add it from .debug_frame
4196 section again. */
4197 if (lo <= hi)
4198 continue;
4199 }
4200
sewardjc6d3f6f2007-01-11 19:42:11 +00004201 adi.encoding = the_CIEs[cie].address_encoding;
tom3c9cf342009-11-12 13:28:34 +00004202 adi.ehframe_image = frame_image;
4203 adi.ehframe_avma = frame_avma;
tom402c9ee2009-03-09 09:19:03 +00004204 adi.text_bias = di->text_debug_bias;
sewardj1936f8b2006-11-16 12:21:52 +00004205
sewardjb8b79ad2008-03-03 01:35:41 +00004206 if (di->trace_cfi)
sewardj3646a492007-02-16 14:17:10 +00004207 show_CF_instructions( fde_instrs, fde_ilen, &adi,
4208 the_CIEs[cie].code_a_f,
4209 the_CIEs[cie].data_a_f );
sewardj325ec872005-05-01 20:24:06 +00004210
sewardj5c638c22005-04-30 07:55:58 +00004211 initUnwindContext(&ctx);
sewardj726baec2005-06-09 19:27:25 +00004212 ctx.code_a_f = the_CIEs[cie].code_a_f;
4213 ctx.data_a_f = the_CIEs[cie].data_a_f;
sewardj35165532005-04-30 18:47:48 +00004214 ctx.initloc = fde_initloc;
sewardj726baec2005-06-09 19:27:25 +00004215 ctx.ra_reg = the_CIEs[cie].ra_reg;
sewardj9c606bd2008-09-18 18:12:50 +00004216 ctx.exprs = VG_(newXA)( ML_(dinfo_zalloc), "di.rcid.1",
4217 ML_(dinfo_free),
sewardj72427fa2007-02-27 16:52:23 +00004218 sizeof(CfiExpr) );
4219 vg_assert(ctx.exprs);
sewardj8eb41322005-05-01 23:50:08 +00004220
sewardj3646a492007-02-16 14:17:10 +00004221 /* Run the CIE's instructions. Ugly hack: if
4222 --debug-dump=frames is in effect, suppress output for
4223 these instructions since they will already have been shown
4224 at the time the CIE was first encountered. Note, not
4225 thread safe - if this reader is ever made threaded, should
4226 fix properly. */
sewardjb8b79ad2008-03-03 01:35:41 +00004227 { Bool hack = di->ddump_frames;
4228 di->ddump_frames = False;
sewardj3646a492007-02-16 14:17:10 +00004229 initUnwindContext(&restore_ctx);
4230 ok = run_CF_instructions(
sewardjb8b79ad2008-03-03 01:35:41 +00004231 di, False, &ctx, the_CIEs[cie].instrs,
sewardj3646a492007-02-16 14:17:10 +00004232 the_CIEs[cie].ilen, 0, NULL, &adi
4233 );
sewardjb8b79ad2008-03-03 01:35:41 +00004234 di->ddump_frames = hack;
sewardj3646a492007-02-16 14:17:10 +00004235 }
4236 /* And now run the instructions for the FDE, starting from
4237 the state created by running the CIE preamble
4238 instructions. */
sewardj8eb41322005-05-01 23:50:08 +00004239 if (ok) {
4240 restore_ctx = ctx;
4241 ok = run_CF_instructions(
sewardjb8b79ad2008-03-03 01:35:41 +00004242 di, True, &ctx, fde_instrs, fde_ilen, fde_arange,
sewardj1936f8b2006-11-16 12:21:52 +00004243 &restore_ctx, &adi
4244 );
sewardjb8b79ad2008-03-03 01:35:41 +00004245 if (di->ddump_frames)
sewardj3646a492007-02-16 14:17:10 +00004246 VG_(printf)("\n");
sewardj8eb41322005-05-01 23:50:08 +00004247 }
sewardj72427fa2007-02-27 16:52:23 +00004248
4249 VG_(deleteXA)( ctx.exprs );
sewardj5c638c22005-04-30 07:55:58 +00004250 }
4251 }
4252
sewardj5c638c22005-04-30 07:55:58 +00004253 return;
4254
4255 bad:
sewardjcbd2f032005-08-01 14:12:17 +00004256 if (!VG_(clo_xml) && VG_(clo_verbosity) > 1)
sewardj738856f2009-07-15 14:48:32 +00004257 VG_(message)(Vg_UserMsg,
4258 "Warning: %s in DWARF2 CFI reading\n", how);
sewardj5c638c22005-04-30 07:55:58 +00004259 return;
4260}
4261
njn8b68b642009-06-24 00:37:09 +00004262#endif // defined(VGO_linux) || defined(VGO_darwin)
sewardj5c638c22005-04-30 07:55:58 +00004263
njn4bbdc972003-10-16 10:10:55 +00004264/*--------------------------------------------------------------------*/
njnea27e462005-05-31 02:38:09 +00004265/*--- end ---*/
njn4bbdc972003-10-16 10:10:55 +00004266/*--------------------------------------------------------------------*/