1ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--------------------------------------------------------------------*/
3ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--- Read DWARF1/2/3/4 debug info.                    readdwarf.c ---*/
4ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--------------------------------------------------------------------*/
5ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
6ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*
7ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   This file is part of Valgrind, a dynamic binary instrumentation
8ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   framework.
9ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
10b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   Copyright (C) 2000-2011 Julian Seward
11ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      jseward@acm.org
12ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
13ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   This program is free software; you can redistribute it and/or
14ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   modify it under the terms of the GNU General Public License as
15ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   published by the Free Software Foundation; either version 2 of the
16ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   License, or (at your option) any later version.
17ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
18ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   This program is distributed in the hope that it will be useful, but
19ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   WITHOUT ANY WARRANTY; without even the implied warranty of
20ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
21ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   General Public License for more details.
22ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
23ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   You should have received a copy of the GNU General Public License
24ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   along with this program; if not, write to the Free Software
25ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
26ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   02111-1307, USA.
27ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
28ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   The GNU General Public License is contained in the file COPYING.
29ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown*/
30ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
31ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#if defined(VGO_linux) || defined(VGO_darwin)
32ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
33ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "pub_core_basics.h"
34ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "pub_core_debuginfo.h"
35ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "pub_core_libcbase.h"
36ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "pub_core_libcassert.h"
37ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "pub_core_libcprint.h"
38ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "pub_core_options.h"
39ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "pub_core_xarray.h"
40ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "pub_core_tooliface.h"    /* VG_(needs) */
41ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "priv_misc.h"             /* dinfo_zalloc/free/strdup */
42ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "priv_d3basics.h"
43ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "priv_tytypes.h"
44ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "priv_storage.h"
45ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "priv_readdwarf.h"        /* self */
46ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
47ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
48ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*------------------------------------------------------------*/
49ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*---                                                      ---*/
50ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--- Read line number and CFI info from DWARF1, DWARF2    ---*/
51ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--- and to some extent DWARF3 sections.                  ---*/
52ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*---                                                      ---*/
53ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*------------------------------------------------------------*/
54ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
55ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*------------------------------------------------------------*/
56ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--- Expanding arrays of words, for holding file name and ---*/
57ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--- directory name arrays.                               ---*/
58ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*------------------------------------------------------------*/
59ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
60ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Browntypedef
61ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   struct {
62ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      Word* tab;
63ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      UInt  tab_size;
64ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      UInt  tab_used;
65ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
66ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   WordArray;
67ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
68ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic void init_WordArray ( WordArray* wa )
69ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
70ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   wa->tab      = NULL;
71ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   wa->tab_size = 0;
72ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   wa->tab_used = 0;
73ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
74ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
75ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic void free_WordArray ( WordArray* wa )
76ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
77ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (wa->tab) {
78ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      vg_assert(wa->tab_size > 0);
79ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      ML_(dinfo_free)(wa->tab);
80ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
81ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   init_WordArray(wa);
82ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
83ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
84ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic void addto_WordArray ( WordArray* wa, Word w )
85ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
86ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   UInt  new_size, i;
87ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Word* new_tab;
88ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
89ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (0) VG_(printf)("<<ADD %p (new sz = %d) >>\n",
90ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                      (HChar*)w, wa->tab_used+1);
91ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
92ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (wa->tab_used < wa->tab_size) {
93ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* fine */
94ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   } else {
95ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* expand array */
96ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (0) VG_(printf)("EXPAND ARRAY from %d\n", wa->tab_size);
97ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      vg_assert(wa->tab_used == wa->tab_size);
98ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      vg_assert( (wa->tab_size == 0 && wa->tab == NULL)
99ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                 || (wa->tab_size != 0 && wa->tab != NULL) );
100ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      new_size = wa->tab_size == 0 ? 8 : 2 * wa->tab_size;
101ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      new_tab  = ML_(dinfo_zalloc)("di.aWA.1", new_size * sizeof(Word));
102ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      vg_assert(new_tab != NULL);
103ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      for (i = 0; i < wa->tab_used; i++)
104ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         new_tab[i] = wa->tab[i];
105ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      wa->tab_size = new_size;
106ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (wa->tab)
107ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         ML_(dinfo_free)(wa->tab);
108ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      wa->tab = new_tab;
109ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
110ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
111ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vg_assert(wa->tab_used < wa->tab_size);
112ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vg_assert(wa->tab_size > 0);
113ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   wa->tab[wa->tab_used] = w;
114ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   wa->tab_used++;
115ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
116ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
117ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic Word index_WordArray ( /*OUT*/Bool* inRange, WordArray* wa, Int i )
118ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
119ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vg_assert(inRange);
120ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (i >= 0 && i < wa->tab_used) {
121ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      *inRange = True;
122ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return wa->tab[i];
123ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   } else {
124ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      *inRange = False;
125ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return 0;
126ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
127ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
128ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
129ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
130ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*------------------------------------------------------------*/
131ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--- Read DWARF2 format line number info.                 ---*/
132ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*------------------------------------------------------------*/
133ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
134ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Structure holding info extracted from the a .debug_line
135ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   section.  */
136ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Browntypedef struct
137ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
138ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  ULong  li_length;
139ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  UShort li_version;
140ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  ULong  li_header_length;
141ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  UChar  li_min_insn_length;
142ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  UChar  li_max_ops_per_insn;
143ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  UChar  li_default_is_stmt;
144ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  Int    li_line_base;
145ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  UChar  li_line_range;
146ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  UChar  li_opcode_base;
147ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
148ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownDebugLineInfo;
149ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
150ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Structure holding additional infos found from a .debug_info
151ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown * compilation unit block */
152ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Browntypedef struct
153ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
154ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  /* Feel free to add more members here if you need ! */
155ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  Char* compdir;   /* Compilation directory - points to .debug_info */
156ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  Char* name;      /* Main file name - points to .debug_info */
157ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  ULong stmt_list; /* Offset in .debug_line */
158ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  Bool  dw64;      /* 64-bit Dwarf? */
159ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
160ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownUnitInfo;
161ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
162ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Line number opcodes.  */
163ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownenum dwarf_line_number_ops
164ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  {
165ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DW_LNS_extended_op = 0,
166ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DW_LNS_copy = 1,
167ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DW_LNS_advance_pc = 2,
168ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DW_LNS_advance_line = 3,
169ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DW_LNS_set_file = 4,
170ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DW_LNS_set_column = 5,
171ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DW_LNS_negate_stmt = 6,
172ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DW_LNS_set_basic_block = 7,
173ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DW_LNS_const_add_pc = 8,
174ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DW_LNS_fixed_advance_pc = 9,
175ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    /* DWARF 3.  */
176ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DW_LNS_set_prologue_end = 10,
177ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DW_LNS_set_epilogue_begin = 11,
178ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DW_LNS_set_isa = 12
179ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  };
180ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
181ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Line number extended opcodes.  */
182ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownenum dwarf_line_number_x_ops
183ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  {
184ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DW_LNE_end_sequence = 1,
185ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DW_LNE_set_address = 2,
186ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DW_LNE_define_file = 3,
187ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DW_LNE_set_discriminator = 4
188ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  };
189ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
190ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Browntypedef struct
191ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
192ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  /* Information for the last statement boundary.
193ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   * Needed to calculate statement lengths. */
194ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  Addr  last_address;
195ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  UInt  last_file;
196ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  UInt  last_line;
197ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
198ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  Addr  address;
199ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  UInt  file;
200ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  UInt  line;
201ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  UInt  column;
202ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  Int   is_stmt;
203ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  Int   basic_block;
204ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  UChar end_sequence;
205ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} LineSMR;
206ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
207ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
208ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* FIXME: duplicated in readdwarf3.c */
209ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic
210ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownULong read_leb128 ( UChar* data, Int* length_return, Int sign )
211ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
212ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  ULong  result = 0;
213ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  UInt   num_read = 0;
214ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  Int    shift = 0;
215ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  UChar  byte;
216ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
217ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  vg_assert(sign == 0 || sign == 1);
218ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
219ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  do
220ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    {
221ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      byte = * data ++;
222ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      num_read ++;
223ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
224ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      result |= ((ULong)(byte & 0x7f)) << shift;
225ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
226ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      shift += 7;
227ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
228ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    }
229ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  while (byte & 0x80);
230ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
231ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  if (length_return != NULL)
232ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    * length_return = num_read;
233ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
234ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  if (sign && (shift < 64) && (byte & 0x40))
235ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    result |= -(1ULL << shift);
236ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
237ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  return result;
238ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
239ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
240ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Small helper functions easier to use
241ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown * value is returned and the given pointer is
242ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown * moved past end of leb128 data */
243ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* FIXME: duplicated in readdwarf3.c */
244ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic ULong read_leb128U( UChar **data )
245ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
246ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  Int len;
247ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  ULong val = read_leb128( *data, &len, 0 );
248ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  *data += len;
249ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  return val;
250ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
251ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
252ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Same for signed data */
253ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* FIXME: duplicated in readdwarf3.c */
254ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic Long read_leb128S( UChar **data )
255ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
256ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Int len;
257ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   ULong val = read_leb128( *data, &len, 1 );
258ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   *data += len;
259ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return (Long)val;
260ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
261ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
262ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Read what the DWARF3 spec calls an "initial length field".  This
263ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   uses up either 4 or 12 bytes of the input and produces a 32-bit or
264ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   64-bit number respectively.
265ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
266ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Read 32-bit value from p.  If it is 0xFFFFFFFF, instead read a
267ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   64-bit bit value from p+4.  This is used in 64-bit dwarf to encode
268ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   some table lengths.
269ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
270ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   XXX this is a hack: the endianness of the initial length field is
271ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   specified by the DWARF we're reading.  This happens to work only
272ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   because we don't do cross-arch jitting, hence this code runs on a
273ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   platform of the same endianness as the DWARF it is reading.  Same
274ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   applies for initial lengths for CIE/FDEs and probably in zillions
275ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   of other places -- to be precise, exactly the places where
276ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   binutils/dwarf.c calls byte_get().
277ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown*/
278ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic ULong read_initial_length_field ( UChar* p_img, /*OUT*/Bool* is64 )
279ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
280b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   UInt w32 = ML_(read_UInt)(p_img);
281ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (w32 == 0xFFFFFFFF) {
282ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      *is64 = True;
283b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      return ML_(read_ULong)(p_img+4);
284ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   } else {
285ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      *is64 = False;
286ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return (ULong)w32;
287ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
288ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
289ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
290ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
291ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic LineSMR state_machine_regs;
292ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
293ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic
294ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid reset_state_machine ( Int is_stmt )
295ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
296ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (0) VG_(printf)("smr.a := %p (reset)\n", NULL );
297ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   state_machine_regs.last_address = 0;
298ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   state_machine_regs.last_file = 1;
299ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   state_machine_regs.last_line = 1;
300ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   state_machine_regs.address = 0;
301ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   state_machine_regs.file = 1;
302ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   state_machine_regs.line = 1;
303ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   state_machine_regs.column = 0;
304ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   state_machine_regs.is_stmt = is_stmt;
305ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   state_machine_regs.basic_block = 0;
306ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   state_machine_regs.end_sequence = 0;
307ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
308ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
309ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Look up a directory name, or return NULL if unknown. */
310ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic
311ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownChar* lookupDir ( Int filename_index,
312ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  WordArray* fnidx2dir,
313ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  WordArray* dirnames )
314ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
315ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Bool inRange;
316ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Word diridx, dirname;
317ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
318ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   diridx = index_WordArray( &inRange, fnidx2dir, filename_index );
319ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (!inRange) goto bad;
320ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
321ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   dirname = index_WordArray( &inRange, dirnames, (Int)diridx );
322ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (!inRange) goto bad;
323ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
324ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return (Char*)dirname;
325ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  bad:
326ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return NULL;
327ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
328ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
329ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown////////////////////////////////////////////////////////////////////
330ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown////////////////////////////////////////////////////////////////////
331ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
332ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Handled an extended line op starting at 'data'.  Returns the number
333ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   of bytes that 'data' should be advanced by. */
334ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic
335ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownWord process_extended_line_op( struct _DebugInfo* di,
336ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                               WordArray* filenames,
337ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                               WordArray* dirnames,
338ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                               WordArray* fnidx2dir,
339ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                               UChar* data, Int is_stmt)
340ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
341ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   UChar  op_code;
342ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Int    bytes_read;
343ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   UInt   len;
344ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   UChar* name;
345ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Addr   adr;
346ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
347ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   len = read_leb128 (data, & bytes_read, 0);
348ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   data += bytes_read;
349ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
350ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (len == 0) {
351ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      VG_(message)(Vg_UserMsg,
352ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                   "Warning: DWARF2 reader: "
353ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                   "Badly formed extended line op encountered\n");
354ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return (Word)bytes_read;
355ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
356ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
357ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   len += bytes_read;
358ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   op_code = * data ++;
359ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
360ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (0) VG_(printf)("dwarf2: ext OPC: %d\n", op_code);
361ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
362ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   switch (op_code) {
363ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case DW_LNE_end_sequence:
364ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (0) VG_(printf)("1001: si->o %#lx, smr.a %#lx\n",
365ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                            di->text_debug_bias, state_machine_regs.address );
366ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* JRS: added for compliance with spec; is pointless due to
367ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            reset_state_machine below */
368ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         state_machine_regs.end_sequence = 1;
369ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
370ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (state_machine_regs.is_stmt) {
371ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            if (state_machine_regs.last_address) {
372ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               Bool inRange = False;
373ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               Char* filename
374ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  = (Char*)index_WordArray( &inRange, filenames,
375ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                            state_machine_regs.last_file);
376ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               if (!inRange || !filename)
377ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  filename = "???";
378ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               ML_(addLineInfo) (
379ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  di,
380ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  filename,
381ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  lookupDir( state_machine_regs.last_file,
382ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                             fnidx2dir, dirnames ),
383ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  di->text_debug_bias + state_machine_regs.last_address,
384ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  di->text_debug_bias + state_machine_regs.address,
385ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  state_machine_regs.last_line, 0
386ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               );
387ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            }
388ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
389ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         reset_state_machine (is_stmt);
390ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (di->ddump_line)
391ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            VG_(printf)("  Extended opcode %d: End of Sequence\n\n",
392ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        (Int)op_code);
393ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         break;
394ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
395ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case DW_LNE_set_address:
396b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         adr = ML_(read_Addr)(data);
397ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         state_machine_regs.address = adr;
398ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (di->ddump_line)
399ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            VG_(printf)("  Extended opcode %d: set Address to 0x%lx\n",
400ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        (Int)op_code, (Addr)adr);
401ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         break;
402ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
403ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case DW_LNE_define_file:
404ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         name = data;
405ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addto_WordArray( filenames, (Word)ML_(addStr)(di,name,-1) );
406ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         data += VG_(strlen) ((char *) data) + 1;
407ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         read_leb128 (data, & bytes_read, 0);
408ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         data += bytes_read;
409ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         read_leb128 (data, & bytes_read, 0);
410ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         data += bytes_read;
411ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         read_leb128 (data, & bytes_read, 0);
412ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (di->ddump_line)
413ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            VG_(printf)("  DWARF2-line: set_address\n");
414ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         break;
415ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
416ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case DW_LNE_set_discriminator:
417ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         read_leb128 (data, & bytes_read, 0);
418ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         data += bytes_read;
419ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         break;
420ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
421ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      default:
422ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (di->ddump_line)
423ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            VG_(printf)("process_extended_line_op:default\n");
424ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         break;
425ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
426ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
427ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return (Word)len;
428ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
429ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
430ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown////////////////////////////////////////////////////////////////////
431ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown////////////////////////////////////////////////////////////////////
432ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
433ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* read a .debug_line section block for a compilation unit
434ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown *
435ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown * Input:   - theBlock must point to the start of the block
436ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown *            for the given compilation unit
437ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown *          - ui contains additional info like the compilation dir
438ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown *            for this unit
439ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown *
440ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown * Output: - si debug info structures get updated
441ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown */
442ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic
443ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid read_dwarf2_lineblock ( struct _DebugInfo* di,
444ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                             UnitInfo* ui,
445ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                             UChar*    theBlock, /* IMAGE */
446ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                             Int       noLargerThan )
447ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
448ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Int            i;
449ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   DebugLineInfo  info;
450ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   UChar*         standard_opcodes;
451ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   UChar*         end_of_sequence;
452ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Bool           is64;
453ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   WordArray      filenames;
454ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   WordArray      dirnames;
455ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   WordArray      fnidx2dir;
456ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
457ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   UChar*         external = theBlock;
458ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   UChar*         data = theBlock;
459ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
460ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* filenames is an array of file names harvested from the DWARF2
461ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      info.  Entry [0] is NULL and is never referred to by the state
462ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      machine.
463ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
464ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      Similarly, dirnames is an array of directory names.  Entry [0]
465ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      is also NULL and denotes "we don't know what the path is", since
466ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      that is different from "the path is the empty string".  Unlike
467ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      the file name table, the state machine does refer to entry [0],
468ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      which basically means "." ("the current directory of the
469ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      compilation", whatever that means, according to the DWARF3
470ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      spec.)
471ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
472ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      fnidx2dir is an array of indexes into the dirnames table.
473ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      (confused yet?)  filenames[] and fnidx2dir[] are indexed
474ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      together.  That is, for some index i in the filename table, then
475ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
476ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         the filename  is filenames[i]
477ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         the directory is dirnames[ fnidx2dir[i] ] */
478ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
479ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* Fails due to gcc padding ...
480ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vg_assert(sizeof(DWARF2_External_LineInfo)
481ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown             == sizeof(DWARF2_Internal_LineInfo));
482ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   */
483ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
484ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   init_WordArray(&filenames);
485ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   init_WordArray(&dirnames);
486ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   init_WordArray(&fnidx2dir);
487ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
488ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* DWARF2 starts numbering filename entries at 1, so we need to
489ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      add a dummy zeroth entry to the table.  The zeroth dirnames
490ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      entry denotes 'current directory of compilation' so we might
491ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      as well make the fnidx2dir zeroth entry denote that.
492ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   */
493ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   addto_WordArray( &filenames, (Word)NULL );
494ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
495ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (ui->compdir)
496ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      addto_WordArray( &dirnames, (Word)ML_(addStr)(di, ui->compdir, -1) );
497ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   else
498ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      addto_WordArray( &dirnames, (Word)ML_(addStr)(di, ".", -1) );
499ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
500ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   addto_WordArray( &fnidx2dir, (Word)0 );  /* compilation dir */
501ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
502ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   info.li_length = read_initial_length_field( external, &is64 );
503ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   external += is64 ? 12 : 4;
504ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (di->ddump_line)
505ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      VG_(printf)("  Length:                      %llu\n",
506ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  info.li_length);
507ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
508ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* Check the length of the block.  */
509ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (info.li_length > noLargerThan) {
510ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      ML_(symerr)(di, True,
511ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  "DWARF line info appears to be corrupt "
512ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  "- the section is too small");
513ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      goto out;
514ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
515ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
516ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* Check its version number.  */
517b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   info.li_version = ML_(read_UShort)(external);
518ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   external += 2;
519ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (di->ddump_line)
520ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      VG_(printf)("  DWARF Version:               %d\n",
521ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  (Int)info.li_version);
522ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
523ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (info.li_version != 2 && info.li_version != 3 && info.li_version != 4) {
524ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      ML_(symerr)(di, True,
525ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  "Only DWARF version 2, 3 and 4 line info "
526ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  "is currently supported.");
527ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      goto out;
528ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
529ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
530b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   info.li_header_length = ui->dw64 ? ML_(read_ULong)(external)
531b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                                    : (ULong)(ML_(read_UInt)(external));
532ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   external += ui->dw64 ? 8 : 4;
533ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (di->ddump_line)
534ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      VG_(printf)("  Prologue Length:             %llu\n",
535ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  info.li_header_length);
536ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
537ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   info.li_min_insn_length = * ((UChar *)external);
538ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   external += 1;
539ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (di->ddump_line)
540ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      VG_(printf)("  Minimum Instruction Length:  %d\n",
541ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  (Int)info.li_min_insn_length);
542ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
543ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* We only support machines with one opcode per instruction
544ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      for now. If we ever want to support VLIW machines there is
545ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      code to handle multiple opcodes per instruction in the
546ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      patch attached to BZ#233595.
547ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   */
548ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (info.li_version >= 4) {
549ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      info.li_max_ops_per_insn = * ((UChar *)external);
550ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (info.li_max_ops_per_insn != 1) {
551ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         ML_(symerr)(di, True,
552ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     "Invalid Maximum Ops Per Insn in line info.");
553ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         goto out;
554ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
555ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      external += 1;
556ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (di->ddump_line)
557ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         VG_(printf)("  Maximum Ops Per Insn:        %d\n",
558ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  (Int)info.li_max_ops_per_insn);
559ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   } else {
560ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      info.li_max_ops_per_insn = 1;
561ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
562ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
563ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   info.li_default_is_stmt = * ((UChar *)external);
564ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   external += 1;
565ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (di->ddump_line)
566ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      VG_(printf)("  Initial value of 'is_stmt':  %d\n",
567ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  (Int)info.li_default_is_stmt);
568ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
569ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* Josef Weidendorfer (20021021) writes:
570ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
571ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      It seems to me that the Intel Fortran compiler generates bad
572ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      DWARF2 line info code: It sets "is_stmt" of the state machine in
573ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      the the line info reader to be always false. Thus, there is
574ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      never a statement boundary generated and therefore never a
575ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      instruction range/line number mapping generated for valgrind.
576ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
577ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      Please have a look at the DWARF2 specification, Ch. 6.2
578ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      (x86.ddj.com/ftp/manuals/tools/dwarf.pdf).  Perhaps I understand
579ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      this wrong, but I don't think so.
580ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
581ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      I just had a look at the GDB DWARF2 reader...  They completely
582ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      ignore "is_stmt" when recording line info ;-) That's the reason
583ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      "objdump -S" works on files from the the intel fortran compiler.
584ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
585ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      Therefore: */
586ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   info.li_default_is_stmt = True;
587ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
588ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* JRS: changed (UInt*) to (UChar*) */
589ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   info.li_line_base = * ((UChar *)external);
590ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   info.li_line_base = (Int)(signed char)info.li_line_base;
591ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   external += 1;
592ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (di->ddump_line)
593ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      VG_(printf)("  Line Base:                   %d\n",
594ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  info.li_line_base);
595ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
596ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   info.li_line_range = * ((UChar *)external);
597ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   external += 1;
598ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (di->ddump_line)
599ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      VG_(printf)("  Line Range:                  %d\n",
600ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  (Int)info.li_line_range);
601ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
602ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   info.li_opcode_base = * ((UChar *)external);
603ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   external += 1;
604ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (di->ddump_line)
605ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      VG_(printf)("  Opcode Base:                 %d\n\n",
606ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  info.li_opcode_base);
607ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
608ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (0) VG_(printf)("dwarf2: line base: %d, range %d, opc base: %d\n",
609ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                      (Int)info.li_line_base,
610ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                      (Int)info.li_line_range,
611ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                      (Int)info.li_opcode_base);
612ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
613ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   end_of_sequence = data + info.li_length
614ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                          + (is64 ? 12 : 4);
615ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
616ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   reset_state_machine (info.li_default_is_stmt);
617ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
618ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* Read the contents of the Opcodes table.  */
619ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   standard_opcodes = external;
620ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (di->ddump_line) {
621ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      VG_(printf)(" Opcodes:\n");
622ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      for (i = 1; i < (Int)info.li_opcode_base; i++) {
623ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         VG_(printf)("  Opcode %d has %d args\n",
624ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     i, (Int)standard_opcodes[i-1]);
625ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
626ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      VG_(printf)("\n");
627ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
628ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
629ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* Read the contents of the Directory table.  */
630ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   data = standard_opcodes + info.li_opcode_base - 1;
631ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
632ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (di->ddump_line)
633ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      VG_(printf)(" The Directory Table%s\n",
634ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  *data == 0 ? " is empty." : ":" );
635ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
636ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   while (* data != 0) {
637ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
638ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#     define NBUF 4096
639ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      static Char buf[NBUF];
640ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
641ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (di->ddump_line)
642ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         VG_(printf)("  %s\n", data);
643ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
644ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* If data[0] is '/', then 'data' is an absolute path and we
645ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         don't mess with it.  Otherwise, if we can, construct the
646ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         'path ui->compdir' ++ "/" ++ 'data'. */
647ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
648ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (*data != '/'
649ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown          /* not an absolute path */
650ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown          && ui->compdir != NULL
651ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown          /* actually got something sensible for compdir */
652ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown          && VG_(strlen)(ui->compdir) + VG_(strlen)(data) + 5/*paranoia*/ < NBUF
653ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown          /* it's short enough to concatenate */)
654ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      {
655ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         buf[0] = 0;
656ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         VG_(strcat)(buf, ui->compdir);
657ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         VG_(strcat)(buf, "/");
658ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         VG_(strcat)(buf, data);
659ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         vg_assert(VG_(strlen)(buf) < NBUF);
660ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addto_WordArray( &dirnames, (Word)ML_(addStr)(di,buf,-1) );
661ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (0) VG_(printf)("rel path  %s\n", buf);
662ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      } else {
663ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* just use 'data'. */
664ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addto_WordArray( &dirnames, (Word)ML_(addStr)(di,data,-1) );
665ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (0) VG_(printf)("abs path  %s\n", data);
666ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
667ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
668ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      data += VG_(strlen)(data) + 1;
669ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
670ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#     undef NBUF
671ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
672ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
673ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (di->ddump_line)
674ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      VG_(printf)("\n");
675ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
676ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (*data != 0) {
677ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      ML_(symerr)(di, True,
678ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  "can't find NUL at end of DWARF2 directory table");
679ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      goto out;
680ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
681ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   data ++;
682ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
683ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* Read the contents of the File Name table.  This produces a bunch
684ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      of file names, and for each, an index to the corresponding
685ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      directory name entry. */
686ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (di->ddump_line) {
687ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      VG_(printf)(" The File Name Table:\n");
688ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      VG_(printf)("  Entry	Dir	Time	Size	Name\n");
689ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
690ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
691ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   i = 1;
692ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   while (* data != 0) {
693ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      UChar* name;
694ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      Int    bytes_read, diridx;
695ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      Int    uu_time, uu_size; /* unused, and a guess */
696ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      name = data;
697ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      data += VG_(strlen) ((Char *) data) + 1;
698ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
699ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      diridx = read_leb128 (data, & bytes_read, 0);
700ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      data += bytes_read;
701ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      uu_time = read_leb128 (data, & bytes_read, 0);
702ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      data += bytes_read;
703ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      uu_size = read_leb128 (data, & bytes_read, 0);
704ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      data += bytes_read;
705ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
706ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      addto_WordArray( &filenames, (Word)ML_(addStr)(di,name,-1) );
707ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      addto_WordArray( &fnidx2dir, (Word)diridx );
708ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (0) VG_(printf)("file %s diridx %d\n", name, diridx );
709ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (di->ddump_line)
710ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         VG_(printf)("  %d\t%d\t%d\t%d\t%s\n",
711ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     i, diridx, uu_time, uu_size, name);
712ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      i++;
713ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
714ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
715ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (di->ddump_line)
716ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      VG_(printf)("\n");
717ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
718ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (*data != 0) {
719ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      ML_(symerr)(di, True,
720ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  "can't find NUL at end of DWARF2 file name table");
721ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      goto out;
722ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
723ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   data ++;
724ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
725ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (di->ddump_line)
726ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      VG_(printf)(" Line Number Statements:\n");
727ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
728ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* Now display the statements.  */
729ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
730ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   while (data < end_of_sequence) {
731ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
732ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      UChar op_code;
733ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      Int           adv;
734ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      Int           bytes_read;
735ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
736ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      op_code = * data ++;
737ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
738ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (0) VG_(printf)("dwarf2: OPC: %d\n", op_code);
739ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
740ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (op_code >= info.li_opcode_base) {
741ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
742ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         Int advAddr;
743ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         op_code -= info.li_opcode_base;
744ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         adv      = (op_code / info.li_line_range)
745ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                       * info.li_min_insn_length;
746ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         advAddr = adv;
747ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         state_machine_regs.address += adv;
748ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
749ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (0) VG_(printf)("smr.a += %#x\n", adv );
750ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         adv = (op_code % info.li_line_range) + info.li_line_base;
751ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (0) VG_(printf)("1002: di->o %#lx, smr.a %#lx\n",
752ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                            di->text_debug_bias, state_machine_regs.address );
753ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         state_machine_regs.line += adv;
754ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
755ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (di->ddump_line)
756ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            VG_(printf)("  Special opcode %d: advance Address by %d "
757ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        "to 0x%lx and Line by %d to %d\n",
758ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        (Int)op_code, advAddr, state_machine_regs.address,
759ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        (Int)adv, (Int)state_machine_regs.line );
760ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
761ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (state_machine_regs.is_stmt) {
762ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            /* only add a statement if there was a previous boundary */
763ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            if (state_machine_regs.last_address) {
764ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               Bool inRange = False;
765ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               Char* filename
766ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  = (Char*)index_WordArray( &inRange, &filenames,
767ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                            state_machine_regs.last_file);
768ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               if (!inRange || !filename)
769ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  filename = "???";
770ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               ML_(addLineInfo)(
771ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  di,
772ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  filename,
773ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  lookupDir( state_machine_regs.last_file,
774ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                             &fnidx2dir, &dirnames ),
775ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  di->text_debug_bias + state_machine_regs.last_address,
776ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  di->text_debug_bias + state_machine_regs.address,
777ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  state_machine_regs.last_line,
778ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  0
779ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               );
780ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            }
781ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            state_machine_regs.last_address = state_machine_regs.address;
782ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            state_machine_regs.last_file = state_machine_regs.file;
783ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            state_machine_regs.last_line = state_machine_regs.line;
784ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
785ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
786ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
787ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
788ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      else { /* ! (op_code >= info.li_opcode_base) */
789ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
790ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      switch (op_code) {
791ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case DW_LNS_extended_op:
792ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            data += process_extended_line_op (
793ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                       di, &filenames, &dirnames, &fnidx2dir,
794ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                       data, info.li_default_is_stmt);
795ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            break;
796ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
797ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case DW_LNS_copy:
798ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            if (0) VG_(printf)("1002: di->o %#lx, smr.a %#lx\n",
799ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                               di->text_debug_bias, state_machine_regs.address );
800ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            if (state_machine_regs.is_stmt) {
801ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               /* only add a statement if there was a previous boundary */
802ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               if (state_machine_regs.last_address) {
803ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  Bool inRange = False;
804ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  Char* filename
805ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     = (Char*)index_WordArray( &inRange, &filenames,
806ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                               state_machine_regs.last_file );
807ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  if (!inRange || !filename)
808ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     filename = "???";
809ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  ML_(addLineInfo)(
810ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     di,
811ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     filename,
812ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     lookupDir( state_machine_regs.last_file,
813ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                &fnidx2dir, &dirnames ),
814ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     di->text_debug_bias + state_machine_regs.last_address,
815ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     di->text_debug_bias + state_machine_regs.address,
816ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     state_machine_regs.last_line,
817ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     0
818ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  );
819ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               }
820ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               state_machine_regs.last_address = state_machine_regs.address;
821ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               state_machine_regs.last_file = state_machine_regs.file;
822ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               state_machine_regs.last_line = state_machine_regs.line;
823ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            }
824ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            state_machine_regs.basic_block = 0; /* JRS added */
825ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            if (di->ddump_line)
826ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               VG_(printf)("  Copy\n");
827ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            break;
828ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
829ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case DW_LNS_advance_pc:
830ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            adv = info.li_min_insn_length
831ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     * read_leb128 (data, & bytes_read, 0);
832ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            data += bytes_read;
833ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            state_machine_regs.address += adv;
834ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            if (0) VG_(printf)("smr.a += %#x\n", adv );
835ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            if (di->ddump_line)
836ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               VG_(printf)("  Advance PC by %d to 0x%lx\n",
837ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                           (Int)adv, state_machine_regs.address);
838ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            break;
839ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
840ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case DW_LNS_advance_line:
841ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            adv = read_leb128 (data, & bytes_read, 1);
842ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            data += bytes_read;
843ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            state_machine_regs.line += adv;
844ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            if (di->ddump_line)
845ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               VG_(printf)("  Advance Line by %d to %d\n",
846ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                           (Int)adv, (Int)state_machine_regs.line);
847ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            break;
848ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
849ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case DW_LNS_set_file:
850ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            adv = read_leb128 (data, & bytes_read, 0);
851ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            data += bytes_read;
852ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            state_machine_regs.file = adv;
853ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            if (di->ddump_line)
854ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               VG_(printf)("  Set File Name to entry %d in the File Name Table\n",
855ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                           (Int)adv);
856ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            break;
857ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
858ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case DW_LNS_set_column:
859ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            adv = read_leb128 (data, & bytes_read, 0);
860ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            data += bytes_read;
861ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            state_machine_regs.column = adv;
862ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            if (di->ddump_line)
863b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov               VG_(printf)("  Set column to %d\n", (Int)adv);
864ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            break;
865ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
866ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case DW_LNS_negate_stmt:
867ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            adv = state_machine_regs.is_stmt;
868ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            adv = ! adv;
869ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            state_machine_regs.is_stmt = adv;
870ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            if (di->ddump_line)
871ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               VG_(printf)("  DWARF2-line: negate_stmt\n");
872ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            break;
873ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
874ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case DW_LNS_set_basic_block:
875ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            state_machine_regs.basic_block = 1;
876ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            if (di->ddump_line)
877ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               VG_(printf)("  DWARF2-line: set_basic_block\n");
878ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            break;
879ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
880ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case DW_LNS_const_add_pc:
881ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            adv = (((255 - info.li_opcode_base) / info.li_line_range)
882ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                   * info.li_min_insn_length);
883ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            state_machine_regs.address += adv;
884ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            if (0) VG_(printf)("smr.a += %#x\n", adv );
885ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            if (di->ddump_line)
886ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               VG_(printf)("  Advance PC by constant %d to 0x%lx\n",
887ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                           (Int)adv, (Addr)state_machine_regs.address);
888ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            break;
889ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
890ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case DW_LNS_fixed_advance_pc:
891ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            /* XXX: Need something to get 2 bytes */
892b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov            adv = ML_(read_UShort)(data);
893ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            data += 2;
894ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            state_machine_regs.address += adv;
895ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            if (0) VG_(printf)("smr.a += %#x\n", adv );
896ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            if (di->ddump_line)
897ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               VG_(printf)("  DWARF2-line: fixed_advance_pc\n");
898ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            break;
899ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
900ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case DW_LNS_set_prologue_end:
901ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            if (di->ddump_line)
902ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               VG_(printf)("  DWARF2-line: set_prologue_end\n");
903ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            break;
904ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
905ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case DW_LNS_set_epilogue_begin:
906ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            if (di->ddump_line)
907ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               VG_(printf)("  DWARF2-line: set_epilogue_begin\n");
908ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            break;
909ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
910ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case DW_LNS_set_isa:
911ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            /*adv =*/ read_leb128 (data, & bytes_read, 0);
912ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            data += bytes_read;
913ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            if (di->ddump_line)
914ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               VG_(printf)("  DWARF2-line: set_isa\n");
915ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            break;
916ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
917ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         default: {
918ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            Int j;
919ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            for (j = standard_opcodes[op_code - 1]; j > 0 ; --j) {
920ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               read_leb128 (data, &bytes_read, 0);
921ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               data += bytes_read;
922ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            }
923ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            if (di->ddump_line)
924ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               VG_(printf)("  Unknown opcode %d\n", (Int)op_code);
925ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            break;
926ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
927ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      } /* switch (op_code) */
928ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
929ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      } /* if (op_code >= info.li_opcode_base) */
930ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
931ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   } /* while (data < end_of_sequence) */
932ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
933ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (di->ddump_line)
934ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      VG_(printf)("\n");
935ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
936ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  out:
937ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   free_WordArray(&filenames);
938ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   free_WordArray(&dirnames);
939ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   free_WordArray(&fnidx2dir);
940ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
941ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
942ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown////////////////////////////////////////////////////////////////////
943ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown////////////////////////////////////////////////////////////////////
944ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
945ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Return abbrev for given code
946ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown * Returned pointer points to the tag
947ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown * */
948ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic UChar* lookup_abbrev( UChar* p, UInt acode )
949ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
950ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   UInt code;
951ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   UInt name;
952ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   for( ; ; ) {
953ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      code = read_leb128U( &p );
954ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if ( code == acode )
955ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return p;
956ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      read_leb128U( &p ); /* skip tag */
957ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      p++;                /* skip has_children flag */
958ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      do {
959ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         name = read_leb128U( &p ); /* name */
960ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         read_leb128U( &p );   /* form */
961ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
962ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      while( name != 0 ); /* until name == form == 0 */
963ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
964ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return NULL;
965ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
966ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
967ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Read general information for a particular compile unit block in
968ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown * the .debug_info section.
969ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown *
970ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown * Input: - unitblock is the start of a compilation
971ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown *          unit block in .debuginfo section
972ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown *        - debugabbrev is start of .debug_abbrev section
973ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown *        - debugstr is start of .debug_str section
974ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown *
975ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown * Output: Fill members of ui pertaining to the compilation unit:
976ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown *         - ui->name is the name of the compilation unit
977ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown *         - ui->compdir is the compilation unit directory
978ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown *         - ui->stmt_list is the offset in .debug_line section
979ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown *                for the dbginfos of this compilation unit
980ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown *
981ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown * Note : the output strings are not allocated and point
982ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown * directly to the memory-mapped section.
983ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown */
984ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic
985ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid read_unitinfo_dwarf2( /*OUT*/UnitInfo* ui,
986ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                  UChar*    unitblock_img,
987ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                  UChar*    debugabbrev_img,
988ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                  UChar*    debugstr_img )
989ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
990ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   UInt   acode, abcode;
991ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   ULong  atoffs, blklen;
992ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Int    level;
993b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   /* UShort ver; */
994ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
995ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   UChar addr_size;
996ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   UChar* p = unitblock_img;
997ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   UChar* end_img;
998ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   UChar* abbrev_img;
999ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1000ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   VG_(memset)( ui, 0, sizeof( UnitInfo ) );
1001ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   ui->stmt_list = -1LL;
1002ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1003ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* Read the compilation unit header in .debug_info section - See p 70 */
1004ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1005ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* This block length */
1006ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   blklen = read_initial_length_field( p, &ui->dw64 );
1007ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   p += ui->dw64 ? 12 : 4;
1008ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1009ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* version should be 2, 3 or 4 */
1010b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   /* ver = ML_(read_UShort)(p); */
1011ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   p += 2;
1012ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1013ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* get offset in abbrev */
1014b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   atoffs = ui->dw64 ? ML_(read_ULong)(p) : (ULong)(ML_(read_UInt)(p));
1015ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   p += ui->dw64 ? 8 : 4;
1016ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1017ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* Address size */
1018ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   addr_size = *p;
1019ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   p += 1;
1020ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1021ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   end_img     = unitblock_img
1022ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                 + blklen + (ui->dw64 ? 12 : 4); /* End of this block */
1023ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   level       = 0;                        /* Level in the abbrev tree */
1024ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   abbrev_img  = debugabbrev_img
1025ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                 + atoffs; /* Abbreviation data for this block */
1026ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1027ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* Read the compilation unit entries */
1028ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   while ( p < end_img ) {
1029ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      Bool has_child;
1030ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      UInt tag;
1031ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1032ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      acode = read_leb128U( &p ); /* abbreviation code */
1033ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if ( acode == 0 ) {
1034ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* NULL entry used for padding - or last child for a sequence
1035ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            - see para 7.5.3 */
1036ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         level--;
1037ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         continue;
1038ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
1039ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1040ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* Read abbreviation header */
1041ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      abcode = read_leb128U( &abbrev_img ); /* abbreviation code */
1042ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if ( acode != abcode ) {
1043ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* We are in in children list, and must rewind to a
1044ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown          * previously declared abbrev code.  This code works but is
1045ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown          * not triggered since we shortcut the parsing once we have
1046ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown          * read the compile_unit block.  This should only occur when
1047ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown          * level > 0 */
1048ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         abbrev_img = lookup_abbrev( debugabbrev_img + atoffs, acode );
1049ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
1050ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1051ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      tag = read_leb128U( &abbrev_img );
1052ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      has_child = *(abbrev_img++) == 1; /* DW_CHILDREN_yes */
1053ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1054ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if ( has_child )
1055ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         level++;
1056ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1057ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* And loop on entries */
1058ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      for ( ; ; ) {
1059ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* Read entry definition */
1060ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         UInt  name, form;
1061ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         ULong cval = -1LL;  /* Constant value read */
1062ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         Char  *sval = NULL; /* String value read */
1063ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         name = read_leb128U( &abbrev_img );
1064ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         form = read_leb128U( &abbrev_img );
1065ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if ( name == 0 )
1066ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            break;
1067ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1068ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* Read data */
1069ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* Attributes encoding explained p 71 */
1070ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if ( form == 0x16 /* FORM_indirect */ )
1071ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            form = read_leb128U( &p );
1072ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* Decode form. For most kinds, Just skip the amount of data since
1073ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            we don't use it for now */
1074ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* JRS 9 Feb 06: This now handles 64-bit DWARF too.  In
1075ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            64-bit DWARF, lineptr (and loclistptr,macptr,rangelistptr
1076ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            classes) use FORM_data8, not FORM_data4.  Also,
1077ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            FORM_ref_addr and FORM_strp are 64-bit values, not 32-bit
1078ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            values. */
1079ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* TJH 27 Apr 10: in DWARF 4 lineptr (and loclistptr,macptr,
1080ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            rangelistptr classes) use FORM_sec_offset which is 64 bits
1081ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            in 64 bit DWARF and 32 bits in 32 bit DWARF. */
1082b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         /* JRS 20 Apr 11: LLVM-2.9 encodes DW_AT_stmt_list using
1083b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov            FORM_addr rather than the FORM_data4 that GCC uses.  Hence
1084b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov            handle FORM_addr too. */
1085ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         switch( form ) {
1086ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            /* Those cases extract the data properly */
1087b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov            case 0x05: /* FORM_data2 */     cval = ML_(read_UShort)(p); p +=2; break;
1088b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov            case 0x06: /* FORM_data4 */     cval = ML_(read_UInt)(p);   p +=4; break;
1089ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            case 0x0e: /* FORM_strp */      /* pointer in .debug_str */
1090ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                       /* 2006-01-01: only generate a value if
1091ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                          debugstr is non-NULL (which means that a
1092ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                          debug_str section was found) */
1093ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                            if (debugstr_img && !ui->dw64)
1094b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                                               sval = debugstr_img + ML_(read_UInt)(p);
1095ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                            if (debugstr_img && ui->dw64)
1096b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                                               sval = debugstr_img + ML_(read_ULong)(p);
1097ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                            p += ui->dw64 ? 8 : 4;
1098ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                            break;
1099ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            case 0x08: /* FORM_string */    sval = (Char*)p;
1100ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                            p += VG_(strlen)((Char*)p) + 1; break;
1101ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            case 0x0b: /* FORM_data1 */     cval = *p; p++; break;
1102ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            case 0x17: /* FORM_sec_offset */if (ui->dw64) {
1103b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                                               cval = ML_(read_ULong)(p); p += 8;
1104ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                            } else {
1105b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                                               cval = ML_(read_UInt)(p); p += 4;
1106ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                            }; break;
1107b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
1108b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov            case 0x07: /* FORM_data8 */     if (ui->dw64) cval = ML_(read_ULong)(p);
1109b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                                            p += 8; break;
1110b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                                            /* perhaps should assign
1111b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                                               unconditionally to cval? */
1112b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
1113ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            /* TODO : Following ones just skip data - implement if you need */
1114ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            case 0x01: /* FORM_addr */      p += addr_size; break;
1115b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov            case 0x03: /* FORM_block2 */    p += ML_(read_UShort)(p) + 2; break;
1116b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov            case 0x04: /* FORM_block4 */    p += ML_(read_UInt)(p) + 4; break;
1117ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            case 0x09: /* FORM_block */     p += read_leb128U( &p ); break;
1118ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            case 0x0a: /* FORM_block1 */    p += *p + 1; break;
1119ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            case 0x0c: /* FORM_flag */      p++; break;
1120ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            case 0x0d: /* FORM_sdata */     read_leb128S( &p ); break;
1121ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            case 0x0f: /* FORM_udata */     read_leb128U( &p ); break;
1122ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            case 0x10: /* FORM_ref_addr */  p += ui->dw64 ? 8 : 4; break;
1123ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            case 0x11: /* FORM_ref1 */      p++; break;
1124ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            case 0x12: /* FORM_ref2 */      p += 2; break;
1125ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            case 0x13: /* FORM_ref4 */      p += 4; break;
1126ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            case 0x14: /* FORM_ref8 */      p += 8; break;
1127ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            case 0x15: /* FORM_ref_udata */ read_leb128U( &p ); break;
1128ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            case 0x18: /* FORM_exprloc */   p += read_leb128U( &p ); break;
1129ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            case 0x19: /* FORM_flag_present */break;
1130ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            case 0x20: /* FORM_ref_sig8 */  p += 8; break;
1131ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1132ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            default:
1133ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               VG_(printf)( "### unhandled dwarf2 abbrev form code 0x%x\n", form );
1134ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               break;
1135ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
1136ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1137ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* Now store the members we need in the UnitInfo structure */
1138ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if ( tag == 0x0011 /*TAG_compile_unit*/ ) {
1139ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                 if ( name == 0x03 ) ui->name = sval;      /* DW_AT_name */
1140ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            else if ( name == 0x1b ) ui->compdir = sval;   /* DW_AT_compdir */
1141ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            else if ( name == 0x10 ) ui->stmt_list = cval; /* DW_AT_stmt_list */
1142ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
1143ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
1144ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* Shortcut the parsing once we have read the compile_unit block
1145ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown       * That's enough info for us, and we are not gdb ! */
1146ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if ( tag == 0x0011 /*TAG_compile_unit*/ )
1147ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         break;
1148ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   } /* Loop on each sub block */
1149ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1150ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* This test would be valid if we were not shortcutting the parsing
1151ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (level != 0)
1152ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      VG_(printf)( "#### Exiting debuginfo block at level %d !!!\n", level );
1153ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   */
1154ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
1155ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1156ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1157ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown////////////////////////////////////////////////////////////////////
1158ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown////////////////////////////////////////////////////////////////////
1159ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1160ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Collect the debug info from DWARF3 debugging sections
1161ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown * of a given module.
1162ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown *
1163ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown * Inputs: given .debug_xxx sections
1164ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown * Output: update di to contain all the DWARF3 debug infos
1165ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown */
1166ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid ML_(read_debuginfo_dwarf3)
1167ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        ( struct _DebugInfo* di,
1168ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown          UChar* debug_info_img, Word debug_info_sz, /* .debug_info */
1169ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown          UChar* debug_abbv_img, Word debug_abbv_sz, /* .debug_abbrev */
1170ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown          UChar* debug_line_img, Word debug_line_sz, /* .debug_line */
1171ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown          UChar* debug_str_img,  Word debug_str_sz ) /* .debug_str */
1172ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
1173ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   UnitInfo ui;
1174ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   UShort   ver;
1175ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   UChar*   block_img;
1176ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   UChar*   end1_img;
1177ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   ULong    blklen;
1178ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Bool     blklen_is_64;
1179ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Int      blklen_len;
1180ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1181ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   end1_img  = debug_info_img + debug_info_sz;
1182ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   blklen_len = 0;
1183ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1184ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* Make sure we at least have a header for the first block */
1185ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (debug_info_sz < 4) {
1186ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      ML_(symerr)( di, True,
1187ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                   "Last block truncated in .debug_info; ignoring" );
1188ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return;
1189ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
1190ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1191ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* Iterate on all the blocks we find in .debug_info */
1192ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   for ( block_img = debug_info_img;
1193ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         block_img < end1_img - 4;
1194ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         block_img += blklen + blklen_len ) {
1195ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1196ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* Read the compilation unit header in .debug_info section - See
1197ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         p 70 */
1198ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* This block length */
1199ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      blklen     = read_initial_length_field( block_img, &blklen_is_64 );
1200ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      blklen_len = blklen_is_64 ? 12 : 4;
1201ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if ( block_img + blklen + blklen_len > end1_img ) {
1202ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         ML_(symerr)( di, True,
1203ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                      "Last block truncated in .debug_info; ignoring" );
1204ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return;
1205ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
1206ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1207ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* version should be 2 */
1208b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      ver = ML_(read_UShort)( block_img + blklen_len );
1209ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if ( ver != 2 && ver != 3 && ver != 4 ) {
1210ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         ML_(symerr)( di, True,
1211ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                      "Ignoring non-Dwarf2/3/4 block in .debug_info" );
1212ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         continue;
1213ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
1214ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1215ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* Fill ui with offset in .debug_line and compdir */
1216ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (0)
1217ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         VG_(printf)( "Reading UnitInfo at 0x%lx.....\n",
1218ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                      block_img - debug_info_img + 0UL );
1219ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      read_unitinfo_dwarf2( &ui, block_img,
1220ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                 debug_abbv_img, debug_str_img );
1221ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (0)
1222ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         VG_(printf)( "   => LINES=0x%llx    NAME=%s     DIR=%s\n",
1223ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                      ui.stmt_list, ui.name, ui.compdir );
1224ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1225ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* Ignore blocks with no .debug_line associated block */
1226ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if ( ui.stmt_list == -1LL )
1227ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         continue;
1228ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1229ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (0)
1230ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         VG_(printf)("debug_line_sz %ld, ui.stmt_list %lld  %s\n",
1231ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     debug_line_sz, ui.stmt_list, ui.name );
1232ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* Read the .debug_line block for this compile unit */
1233ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      read_dwarf2_lineblock(
1234ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         di, &ui, debug_line_img + ui.stmt_list,
1235ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  debug_line_sz  - ui.stmt_list );
1236ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
1237ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
1238ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1239ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1240ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown////////////////////////////////////////////////////////////////////
1241ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown////////////////////////////////////////////////////////////////////
1242ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1243ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*------------------------------------------------------------*/
1244ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--- Read DWARF1 format line number info.                 ---*/
1245ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*------------------------------------------------------------*/
1246ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1247ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* DWARF1 appears to be redundant, but nevertheless the Lahey Fortran
1248ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   compiler generates it.
1249ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown*/
1250ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1251ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* The following three enums (dwarf_tag, dwarf_form, dwarf_attribute)
1252ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   are taken from the file include/elf/dwarf.h in the GNU gdb-6.0
1253ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   sources, which are Copyright 1992, 1993, 1995, 1999 Free Software
1254ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Foundation, Inc and naturally licensed under the GNU General Public
1255ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   License version 2 or later.
1256ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown*/
1257ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1258ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Tag names and codes.  */
1259ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1260ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownenum dwarf_tag {
1261ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    TAG_padding			= 0x0000,
1262ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    TAG_array_type		= 0x0001,
1263ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    TAG_class_type		= 0x0002,
1264ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    TAG_entry_point		= 0x0003,
1265ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    TAG_enumeration_type	= 0x0004,
1266ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    TAG_formal_parameter	= 0x0005,
1267ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    TAG_global_subroutine	= 0x0006,
1268ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    TAG_global_variable		= 0x0007,
1269ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    				/* 0x0008 -- reserved */
1270ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown				/* 0x0009 -- reserved */
1271ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    TAG_label			= 0x000a,
1272ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    TAG_lexical_block		= 0x000b,
1273ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    TAG_local_variable		= 0x000c,
1274ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    TAG_member			= 0x000d,
1275ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown				/* 0x000e -- reserved */
1276ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    TAG_pointer_type		= 0x000f,
1277ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    TAG_reference_type		= 0x0010,
1278ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    TAG_compile_unit		= 0x0011,
1279ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    TAG_string_type		= 0x0012,
1280ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    TAG_structure_type		= 0x0013,
1281ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    TAG_subroutine		= 0x0014,
1282ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    TAG_subroutine_type		= 0x0015,
1283ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    TAG_typedef			= 0x0016,
1284ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    TAG_union_type		= 0x0017,
1285ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    TAG_unspecified_parameters	= 0x0018,
1286ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    TAG_variant			= 0x0019,
1287ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    TAG_common_block		= 0x001a,
1288ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    TAG_common_inclusion	= 0x001b,
1289ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    TAG_inheritance		= 0x001c,
1290ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    TAG_inlined_subroutine	= 0x001d,
1291ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    TAG_module			= 0x001e,
1292ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    TAG_ptr_to_member_type	= 0x001f,
1293ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    TAG_set_type		= 0x0020,
1294ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    TAG_subrange_type		= 0x0021,
1295ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    TAG_with_stmt		= 0x0022,
1296ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1297ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    /* GNU extensions */
1298ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1299ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    TAG_format_label		= 0x8000,  /* for FORTRAN 77 and Fortran 90 */
1300ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    TAG_namelist		= 0x8001,  /* For Fortran 90 */
1301ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    TAG_function_template	= 0x8002,  /* for C++ */
1302ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    TAG_class_template		= 0x8003   /* for C++ */
1303ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown};
1304ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1305ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Form names and codes.  */
1306ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1307ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownenum dwarf_form {
1308ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    FORM_ADDR	= 0x1,
1309ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    FORM_REF	= 0x2,
1310ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    FORM_BLOCK2	= 0x3,
1311ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    FORM_BLOCK4	= 0x4,
1312ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    FORM_DATA2	= 0x5,
1313ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    FORM_DATA4	= 0x6,
1314ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    FORM_DATA8	= 0x7,
1315ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    FORM_STRING	= 0x8
1316ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown};
1317ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1318ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Attribute names and codes.  */
1319ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1320ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownenum dwarf_attribute {
1321ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    AT_sibling			= (0x0010|FORM_REF),
1322ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    AT_location			= (0x0020|FORM_BLOCK2),
1323ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    AT_name			= (0x0030|FORM_STRING),
1324ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    AT_fund_type		= (0x0050|FORM_DATA2),
1325ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    AT_mod_fund_type		= (0x0060|FORM_BLOCK2),
1326ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    AT_user_def_type		= (0x0070|FORM_REF),
1327ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    AT_mod_u_d_type		= (0x0080|FORM_BLOCK2),
1328ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    AT_ordering			= (0x0090|FORM_DATA2),
1329ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    AT_subscr_data		= (0x00a0|FORM_BLOCK2),
1330ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    AT_byte_size		= (0x00b0|FORM_DATA4),
1331ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    AT_bit_offset		= (0x00c0|FORM_DATA2),
1332ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    AT_bit_size			= (0x00d0|FORM_DATA4),
1333ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown				/* (0x00e0|FORM_xxxx) -- reserved */
1334ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    AT_element_list		= (0x00f0|FORM_BLOCK4),
1335ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    AT_stmt_list		= (0x0100|FORM_DATA4),
1336ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    AT_low_pc			= (0x0110|FORM_ADDR),
1337ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    AT_high_pc			= (0x0120|FORM_ADDR),
1338ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    AT_language			= (0x0130|FORM_DATA4),
1339ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    AT_member			= (0x0140|FORM_REF),
1340ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    AT_discr			= (0x0150|FORM_REF),
1341ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    AT_discr_value		= (0x0160|FORM_BLOCK2),
1342ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown				/* (0x0170|FORM_xxxx) -- reserved */
1343ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown				/* (0x0180|FORM_xxxx) -- reserved */
1344ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    AT_string_length		= (0x0190|FORM_BLOCK2),
1345ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    AT_common_reference		= (0x01a0|FORM_REF),
1346ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    AT_comp_dir			= (0x01b0|FORM_STRING),
1347ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        AT_const_value_string	= (0x01c0|FORM_STRING),
1348ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        AT_const_value_data2	= (0x01c0|FORM_DATA2),
1349ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        AT_const_value_data4	= (0x01c0|FORM_DATA4),
1350ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        AT_const_value_data8	= (0x01c0|FORM_DATA8),
1351ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        AT_const_value_block2	= (0x01c0|FORM_BLOCK2),
1352ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        AT_const_value_block4	= (0x01c0|FORM_BLOCK4),
1353ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    AT_containing_type		= (0x01d0|FORM_REF),
1354ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        AT_default_value_addr	= (0x01e0|FORM_ADDR),
1355ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        AT_default_value_data2	= (0x01e0|FORM_DATA2),
1356ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        AT_default_value_data4	= (0x01e0|FORM_DATA4),
1357ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        AT_default_value_data8	= (0x01e0|FORM_DATA8),
1358ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        AT_default_value_string	= (0x01e0|FORM_STRING),
1359ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    AT_friends			= (0x01f0|FORM_BLOCK2),
1360ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    AT_inline			= (0x0200|FORM_STRING),
1361ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    AT_is_optional		= (0x0210|FORM_STRING),
1362ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        AT_lower_bound_ref	= (0x0220|FORM_REF),
1363ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        AT_lower_bound_data2	= (0x0220|FORM_DATA2),
1364ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        AT_lower_bound_data4	= (0x0220|FORM_DATA4),
1365ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        AT_lower_bound_data8	= (0x0220|FORM_DATA8),
1366ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    AT_private			= (0x0240|FORM_STRING),
1367ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    AT_producer			= (0x0250|FORM_STRING),
1368ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    AT_program			= (0x0230|FORM_STRING),
1369ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    AT_protected		= (0x0260|FORM_STRING),
1370ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    AT_prototyped		= (0x0270|FORM_STRING),
1371ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    AT_public			= (0x0280|FORM_STRING),
1372ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    AT_pure_virtual		= (0x0290|FORM_STRING),
1373ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    AT_return_addr		= (0x02a0|FORM_BLOCK2),
1374ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    AT_abstract_origin		= (0x02b0|FORM_REF),
1375ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    AT_start_scope		= (0x02c0|FORM_DATA4),
1376ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    AT_stride_size		= (0x02e0|FORM_DATA4),
1377ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        AT_upper_bound_ref	= (0x02f0|FORM_REF),
1378ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        AT_upper_bound_data2	= (0x02f0|FORM_DATA2),
1379ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        AT_upper_bound_data4	= (0x02f0|FORM_DATA4),
1380ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        AT_upper_bound_data8	= (0x02f0|FORM_DATA8),
1381ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    AT_virtual			= (0x0300|FORM_STRING),
1382ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1383ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    /* GNU extensions.  */
1384ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1385ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    AT_sf_names			= (0x8000|FORM_DATA4),
1386ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    AT_src_info			= (0x8010|FORM_DATA4),
1387ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    AT_mac_info			= (0x8020|FORM_DATA4),
1388ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    AT_src_coords		= (0x8030|FORM_DATA4),
1389ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    AT_body_begin		= (0x8040|FORM_ADDR),
1390ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    AT_body_end			= (0x8050|FORM_ADDR)
1391ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown};
1392ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1393ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* end of enums taken from gdb-6.0 sources */
1394ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1395ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid ML_(read_debuginfo_dwarf1) (
1396ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        struct _DebugInfo* di,
1397ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        UChar* dwarf1d, Int dwarf1d_sz,
1398ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        UChar* dwarf1l, Int dwarf1l_sz )
1399ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
1400ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   UInt   stmt_list;
1401ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Bool   stmt_list_found;
1402ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Int    die_offset, die_szb, at_offset;
1403ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   UShort die_kind, at_kind;
1404ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   UChar* at_base;
1405ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   UChar* src_filename;
1406ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1407ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (0)
1408ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      VG_(printf)("read_debuginfo_dwarf1 ( %p, %d, %p, %d )\n",
1409ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	          dwarf1d, dwarf1d_sz, dwarf1l, dwarf1l_sz );
1410ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1411ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* This loop scans the DIEs. */
1412ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   die_offset = 0;
1413ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   while (True) {
1414ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (die_offset >= dwarf1d_sz) break;
1415ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1416b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      die_szb  = ML_(read_Int)(dwarf1d + die_offset);
1417b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      die_kind = ML_(read_UShort)(dwarf1d + die_offset + 4);
1418ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1419ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* We're only interested in compile_unit DIEs; ignore others. */
1420ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (die_kind != TAG_compile_unit) {
1421ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         die_offset += die_szb;
1422ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         continue;
1423ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
1424ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1425ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (0)
1426ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         VG_(printf)("compile-unit DIE: offset %d, tag 0x%x, size %d\n",
1427ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     die_offset, (Int)die_kind, die_szb );
1428ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1429ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* We've got a compile_unit DIE starting at (dwarf1d +
1430ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         die_offset+6).  Try and find the AT_name and AT_stmt_list
1431ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         attributes.  Then, finally, we can read the line number info
1432ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         for this source file. */
1433ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1434ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* The next 3 are set as we find the relevant attrs. */
1435ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      src_filename    = NULL;
1436ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      stmt_list_found = False;
1437ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      stmt_list       = 0;
1438ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1439ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* This loop scans the Attrs inside compile_unit DIEs. */
1440ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      at_base = dwarf1d + die_offset + 6;
1441ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      at_offset = 0;
1442ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      while (True) {
1443ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (at_offset >= die_szb-6) break;
1444ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1445b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         at_kind = ML_(read_UShort)(at_base + at_offset);
1446ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (0) VG_(printf)("atoffset %d, attag 0x%x\n",
1447ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                            at_offset, (Int)at_kind );
1448ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         at_offset += 2; /* step over the attribute itself */
1449ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	 /* We have to examine the attribute to figure out its
1450ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            length. */
1451ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         switch (at_kind) {
1452ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            case AT_stmt_list:
1453ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            case AT_language:
1454ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            case AT_sibling:
1455ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               if (at_kind == AT_stmt_list) {
1456ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  stmt_list_found = True;
1457b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                  stmt_list = ML_(read_Int)(at_base+at_offset);
1458ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               }
1459ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               at_offset += 4; break;
1460ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            case AT_high_pc:
1461ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            case AT_low_pc:
1462ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               at_offset += sizeof(void*); break;
1463ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            case AT_name:
1464ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            case AT_producer:
1465ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            case AT_comp_dir:
1466ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               /* Zero terminated string, step over it. */
1467ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               if (at_kind == AT_name)
1468ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  src_filename = at_base + at_offset;
1469ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               while (at_offset < die_szb-6 && at_base[at_offset] != 0)
1470ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  at_offset++;
1471ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               at_offset++;
1472ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               break;
1473ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            default:
1474ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               VG_(printf)("Unhandled DWARF-1 attribute 0x%x\n",
1475ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                           (Int)at_kind );
1476ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               VG_(core_panic)("Unhandled DWARF-1 attribute");
1477ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         } /* switch (at_kind) */
1478ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      } /* looping over attributes */
1479ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1480ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* So, did we find the required stuff for a line number table in
1481ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         this DIE?  If yes, read it. */
1482ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (stmt_list_found /* there is a line number table */
1483ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown          && src_filename != NULL /* we know the source filename */
1484ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         ) {
1485ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* Table starts:
1486ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               Length:
1487ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  4 bytes, includes the entire table
1488ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               Base address:
1489ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  unclear (4? 8?), assuming native pointer size here.
1490ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            Then a sequence of triples
1491ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               (source line number -- 32 bits
1492ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                source line column -- 16 bits
1493ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                address delta -- 32 bits)
1494ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	 */
1495ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         Addr   base;
1496ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	 Int    len;
1497ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         Char*  curr_filenm;
1498ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         UChar* ptr;
1499ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         UInt   prev_line, prev_delta;
1500ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1501ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         curr_filenm = ML_(addStr) ( di, src_filename, -1 );
1502ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         prev_line = prev_delta = 0;
1503ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1504ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         ptr = dwarf1l + stmt_list;
1505b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         len  = ML_(read_Int)(ptr);  ptr += sizeof(Int);
1506b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         base = ML_(read_Addr)(ptr); ptr += sizeof(void*);
1507ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         len -= (sizeof(Int) + sizeof(void*));
1508ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         while (len > 0) {
1509ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            UInt   line;
1510ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            UShort col;
1511ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            UInt   delta;
1512b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov            line = ML_(read_UInt)(ptr);    ptr += sizeof(UInt);
1513b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov            col  = ML_(read_UShort)(ptr);  ptr += sizeof(UShort);
1514b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov            delta = ML_(read_UInt)(ptr);   ptr += sizeof(UInt);
1515ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	    if (0) VG_(printf)("line %d, col %d, delta %d\n",
1516ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                               line, (Int)col, delta );
1517ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            len -= (sizeof(UInt) + sizeof(UShort) + sizeof(UInt));
1518ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1519ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	    if (delta > 0 && prev_line > 0) {
1520ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	       if (0) VG_(printf) ("     %d  %d-%d\n",
1521ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                   prev_line, prev_delta, delta-1);
1522ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	       ML_(addLineInfo) ( di, curr_filenm, NULL,
1523ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown		 	          base + prev_delta, base + delta,
1524ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown			          prev_line, 0 );
1525ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	    }
1526ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	    prev_line = line;
1527ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	    prev_delta = delta;
1528ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	 }
1529ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
1530ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1531ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* Move on the the next DIE. */
1532ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      die_offset += die_szb;
1533ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1534ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   } /* Looping over DIEs */
1535ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1536ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
1537ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1538ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1539ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*------------------------------------------------------------*/
1540ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--- Read call-frame info from an .eh_frame section       ---*/
1541ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*------------------------------------------------------------*/
1542ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1543ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Sources of info:
1544ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1545ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   The DWARF3 spec, available from http://www.dwarfstd.org/Download.php
1546ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1547ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   This describes how to read CFA data from .debug_frame sections.
1548ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   So as to maximise everybody's annoyance and confusion, .eh_frame
1549ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   sections are almost the same as .debug_frame sections, but differ
1550ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   in a few subtle and ill documented but important aspects.
1551ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1552ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Generic ELF Specification, sections 7.5 (DWARF Extensions) and 7.6
1553ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   (Exception Frames), available from
1554ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1555ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   http://www.linux-foundation.org/spec/book/ELF-generic/ELF-generic.html
1556ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1557ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   This really does describe .eh_frame, at least the aspects that
1558ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   differ from standard DWARF3.  It's better than guessing, and
1559ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   (marginally) more fun than reading the gdb source code.
1560ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown*/
1561ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1562ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Useful info ..
1563ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1564ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   In general:
1565ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   gdb-6.3/gdb/dwarf2-frame.c
1566ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1567ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   gdb-6.3/gdb/i386-tdep.c:
1568ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1569ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   DWARF2/GCC uses the stack address *before* the function call as a
1570ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   frame's CFA.  [jrs: I presume this means %esp before the call as
1571ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   the CFA].
1572ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1573ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   JRS: on amd64, the dwarf register numbering is, as per
1574ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   gdb-6.3/gdb/amd64-tdep.c and also amd64-abi-0.98.pdf:
1575ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1576ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      0    1    2    3    4    5    6    7
1577ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      RAX  RDX  RCX  RBX  RSI  RDI  RBP  RSP
1578ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1579ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      8  ...  15
1580ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      R8 ... R15
1581ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1582ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      16 is the return address (RIP)
1583ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      "The table defines Return Address to have a register number,
1584ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      even though the address is stored in 0(%rsp) and not in a
1585ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      physical register."
1586ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1587ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      17   ...   24
1588ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      XMM0 ... XMM7
1589ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1590ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      25   ...    32
1591ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      XMM8 ... XMM15
1592ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1593ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      33   ...   40
1594ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      ST0  ...  ST7
1595ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1596ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      41   ...   48
1597ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      MM0  ...  MM7
1598ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1599ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      49                  RFLAGS
1600ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      50,51,52,53,54,55   ES,CS,SS,DS,FS,GS
1601ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      58                  FS.BASE  (what's that?)
1602ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      59                  GS.BASE  (what's that?)
1603ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      62                  TR (task register)
1604ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      63                  LDTR (LDT register)
1605ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      64                  MXCSR
1606ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      65                  FCW (x87 control word)
1607ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      66                  FSW (x86 status word)
1608ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1609ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   On x86 I cannot find any documentation.  It _appears_ to be the
1610ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   actual instruction encoding, viz:
1611ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1612ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      0    1    2    3    4    5    6    7
1613ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      EAX  ECX  EDX  EBX  ESP  EBP  ESI  EDI
1614ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1615ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      8 is the return address (EIP) */
1616ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1617ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1618ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Comments re DW_CFA_set_loc, 16 Nov 06.
1619ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1620ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   JRS:
1621ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Someone recently sent me a libcrypto.so.0.9.8 as distributed with
1622ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Ubuntu of some flavour, compiled with gcc 4.1.2 on amd64.  It
1623ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   causes V's CF reader to complain a lot:
1624ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1625ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   >> --19976-- DWARF2 CFI reader: unhandled CFI instruction 0:24
1626ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   >> --19976-- DWARF2 CFI reader: unhandled CFI instruction 0:24
1627ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   >> --19976-- DWARF2 CFI reader: unhandled CFI instruction 0:24
1628ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   >> --19976-- DWARF2 CFI reader: unhandled CFI instruction 0:24
1629ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   >> --19976-- DWARF2 CFI reader: unhandled CFI instruction 0:48
1630ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   >> --19976-- DWARF2 CFI reader: unhandled CFI instruction 0:24
1631ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1632ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   After chasing this around a bit it seems that the CF bytecode
1633ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   parser lost sync at a DW_CFA_set_loc, which has a single argument
1634ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   denoting an address.
1635ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1636ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   As it stands that address is extracted by read_Addr().  On amd64
1637ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   that just fetches 8 bytes regardless of anything else.
1638ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1639ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   read_encoded_Addr() is more sophisticated.  This appears to take
1640ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   into account some kind of encoding flag.  When I replace the uses
1641ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   of read_Addr by read_encoded_Addr for DW_CFA_set_loc, the
1642ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   complaints go away, there is no loss of sync, and the parsed CF
1643ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   instructions are the same as shown by readelf --debug-dump=frames.
1644ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1645ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   So it seems a plausible fix.  The problem is I looked in the DWARF3
1646ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   spec and completely failed to figure out whether or not the arg to
1647ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   DW_CFA_set_loc is supposed to be encoded in a way suitable for
1648ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   read_encoded_Addr, nor for that matter any description of what it
1649ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   is that read_encoded_Addr is really decoding.
1650ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1651ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   TomH:
1652ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   The problem is that the encoding is not standard - the eh_frame
1653ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   section uses the same encoding as the dwarf_frame section except
1654ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   for a few small changes, and this is one of them. So this is not
1655ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   something the DWARF standard covers.
1656ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1657ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   There is an augmentation string to indicate what is going on though
1658ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   so that programs can recognise it.
1659ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1660ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   What we are doing seems to match what gdb 6.5 and libdwarf 20060614
1661ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   do though. I'm not sure about readelf though.
1662ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1663ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   (later): Well dwarfdump barfs on it:
1664ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1665ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      dwarfdump ERROR:  dwarf_get_fde_info_for_reg:
1666ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        DW_DLE_DF_FRAME_DECODING_ERROR(193) (193)
1667ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1668ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   I've looked at binutils as well now, and the code in readelf agrees
1669ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   with your patch - ie it treats set_loc as having an encoded address
1670ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if there is a zR augmentation indicating an encoding.
1671ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1672ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Quite why gdb and libdwarf don't understand this is an interesting
1673ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   question...
1674ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1675ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Final outcome: all uses of read_Addr were replaced by
1676ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   read_encoded_Addr.  A new type AddressDecodingInfo was added to
1677ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   make it relatively clean to plumb through the extra info needed by
1678ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   read_encoded_Addr.
1679ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown*/
1680ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1681ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* More badness re address encoding, 12 Jan 07.
1682ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1683ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Most gcc provided CIEs have a "zR" augmentation, which means they
1684ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   supply their own address encoding, and that works fine.  However,
1685ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   some icc9 supplied CIEs have no augmentation, which means they use
1686ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   the default_Addr_encoding().  That says to use a machine-word sized
1687ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   value, literally unmodified.
1688ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1689ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Since .so's are, in general, relocated when loaded, having absolute
1690ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   addresses in the CFI data makes no sense when read_encoded_Addr is
1691ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   used to find the initial location for a FDE.  The resulting saga:
1692ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1693ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   TomH:
1694ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   > I'm chasing a stack backtrace failure for an amd64 .so which was
1695ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   > created I believe by icc 9.1.  After a while I wound up looking at
1696ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   > this: (readdwarf.c)
1697ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   >
1698ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   >   5083        tom static UChar default_Addr_encoding ( void )
1699ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   >   3584        tom {
1700ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   >   3584        tom    switch (sizeof(Addr)) {
1701ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   >   3584        tom       case 4: return DW_EH_PE_udata4;
1702ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   >   3584        tom       case 8: return DW_EH_PE_udata8;
1703ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   >   3584        tom       default: vg_assert(0);
1704ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   >   3584        tom    }
1705ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   >   3584        tom }
1706ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   >
1707ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   > If a CIE does not have an "augmentation string" (typically "zR") then
1708ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   > addresses are decoded as described by default_Addr_encoding.  If there
1709ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   > is an 'R' in the augmentation string then the encoding to use
1710ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   > is specified by the CIE itself, which works fine with GCC compiled code
1711ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   > since that always appears to specify zR.
1712ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1713ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Correct.
1714ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1715ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   > Problem is this .so has no augmentation string and so uses the
1716ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   > default encoding, viz DW_EH_PE_udata8.  That appears to mean
1717ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   > "read a 64 bit number" and use that as-is (for the starting value
1718ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   > of the program counter when running the CFA program).
1719ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1720ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Strictly speaking the default is DW_EH_PE_absptr, but that amounts
1721ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   to either udata4 or udata8 depending on the platform's pointer size
1722ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   which is a shortcut I used.
1723ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1724ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   > For this .so that gives nonsense (very small) PCs which are later
1725ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   > rejected by the sanity check which ensures PC ranges fall inside
1726ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   > the mapped text segment.  It seems like the .so expects to have the
1727ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   > start VMA of the text segment added on.  This would correspond to
1728ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   >
1729ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   >   static UChar default_Addr_encoding ( void )
1730ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   >   {
1731ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   >      switch (sizeof(Addr)) {
1732ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   >         case 4: return DW_EH_PE_textrel + DW_EH_PE_udata4;
1733ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   >         case 8: return DW_EH_PE_textrel + DW_EH_PE_udata8;
1734ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   >         default: vg_assert(0);
1735ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   >      }
1736ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   >   }
1737ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1738ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   The problem you're seeing is that you have absolute pointers inside
1739ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   a shared library, which obviously makes little sense on the face of
1740ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   things as how would the linker know where the library will be
1741ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   loaded?
1742ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1743ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   The answer of course is that it doesn't, so if it points absolute
1744ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   pointers in the frame unwind data is has to include relocations for
1745ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   them, and I'm betting that if you look at the relocations in the
1746ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   library you will there are some for that data.
1747ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1748ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   That is fine of course when ld.so maps the library - it will
1749ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   relocate the eh_frame data as it maps it (or prelinking will
1750ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   already have done so) and when the g++ exception code kicks in and
1751ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   unwinds the stack it will see relocated data.
1752ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1753ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   We of course are mapping the section from the ELF file ourselves
1754ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   and are not applying the relocations, hence the problem you are
1755ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   seeing.
1756ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1757ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Strictly speaking we should apply the relocations but the cheap
1758ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   solution is essentially to do what you've done - strictly speaking
1759ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   you should adjust by the difference between the address the library
1760ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   was linked for and the address it has been loaded at, but a shared
1761ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   library will normally be linked for address zero I believe. It's
1762ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   possible that prelinking might change that though?
1763ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1764ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   JRS:
1765ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   That all syncs with what I am seeing.
1766ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1767ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   So what I am inclined to do is:
1768ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1769ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   - Leave default_Addr_encoding as it is
1770ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1771ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   - Change read_encoded_Addr's handling of "case DW_EH_PE_absptr" so
1772ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     it sets base to, as you say, the difference between the address
1773ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     the library was linked for and the address it has been loaded at
1774ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     (== the SegInfo's text_bias)
1775ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1776ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Does that sound sane?  I think it should even handle the prelinked
1777ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case.
1778ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1779ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   (JRS, later)
1780ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1781ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Hmm.  Plausible as it sounds, it doesn't work.  It now produces
1782ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   bogus backtraces for locations inside the (statically linked)
1783ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   memcheck executable.
1784ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1785ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Besides, there are a couple of other places where read_encoded_Addr
1786ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   is used -- one of which is used to establish the length of the
1787ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   address range covered by the current FDE:
1788ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1789ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         fde_arange = read_encoded_Addr(&nbytes, &adi, data);
1790ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1791ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   and it doesn't seem to make any sense for read_encoded_Addr to add
1792ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   on the text segment bias in that context.  The DWARF3 spec says
1793ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   that both the initial_location and address_range (length) fields
1794ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   are encoded the same way ("target address"), so it is unclear at
1795ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   what stage in the process it would be appropriate to relocate the
1796ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   former but not the latter.
1797ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1798ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   One unprincipled kludge that does work is the following: just
1799ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   before handing one of the address range fragments off to
1800ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   ML_(addDiCfSI) for permanent storage, check its start address.  If
1801ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   that is very low (less than 2 M), and is far below the mapped text
1802ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   segment, and adding the text bias would move the fragment entirely
1803ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   inside the mapped text segment, then do so.  A kind of kludged
1804ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   last-minute relocation, if you like.
1805ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1806ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   12 Jan 07: committing said kludge (see kludge_then_addDiCfSI).  If
1807ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   the situation clarifies, it can easily enough be backed out and
1808ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   replaced by a better fix.
1809ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown*/
1810ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1811ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* --------------- Decls --------------- */
1812ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1813ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#if defined(VGP_x86_linux)
1814ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#  define FP_REG         5
1815ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#  define SP_REG         4
1816ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#  define RA_REG_DEFAULT 8
1817ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#elif defined(VGP_amd64_linux)
1818ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#  define FP_REG         6
1819ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#  define SP_REG         7
1820ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#  define RA_REG_DEFAULT 16
1821ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#elif defined(VGP_ppc32_linux)
1822ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#  define FP_REG         1
1823ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#  define SP_REG         1
1824ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#  define RA_REG_DEFAULT 65
1825ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#elif defined(VGP_ppc64_linux)
1826ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#  define FP_REG         1
1827ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#  define SP_REG         1
1828ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#  define RA_REG_DEFAULT 65
1829ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#elif defined(VGP_arm_linux)
1830ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#  define FP_REG         12
1831ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#  define SP_REG         13
1832ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#  define RA_REG_DEFAULT 14    //???
1833ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#elif defined(VGP_x86_darwin)
1834ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#  define FP_REG         5
1835ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#  define SP_REG         4
1836ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#  define RA_REG_DEFAULT 8
1837ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#elif defined(VGP_amd64_darwin)
1838ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#  define FP_REG         6
1839ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#  define SP_REG         7
1840ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#  define RA_REG_DEFAULT 16
1841b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov#elif defined(VGP_s390x_linux)
1842b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov#  define FP_REG         11    // sometimes s390 has a frame pointer in r11
1843b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov#  define SP_REG         15    // stack is always r15
1844b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov#  define RA_REG_DEFAULT 14    // the return address is in r14
1845ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#else
1846ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#  error "Unknown platform"
1847ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#endif
1848ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1849ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* the number of regs we are prepared to unwind */
1850ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#if defined(VGP_ppc32_linux) || defined(VGP_ppc64_linux)
1851ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# define N_CFI_REGS 72
1852212d1b2f0a4276a4402f049b5f8806cf2bbd39beEvgeniy Stepanov#elif defined (VGP_arm_linux)
1853212d1b2f0a4276a4402f049b5f8806cf2bbd39beEvgeniy Stepanov/* 287 is the highest allocated DWARF register name as of 27.07.2011
1854212d1b2f0a4276a4402f049b5f8806cf2bbd39beEvgeniy Stepanov  http://infocenter.arm.com/help/topic/com.arm.doc.ihi0040a/IHI0040A_aadwarf.pdf
1855212d1b2f0a4276a4402f049b5f8806cf2bbd39beEvgeniy Stepanov*/
1856212d1b2f0a4276a4402f049b5f8806cf2bbd39beEvgeniy Stepanov# define N_CFI_REGS 287
1857ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#else
1858ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# define N_CFI_REGS 20
1859ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#endif
1860ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1861ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Instructions for the automaton */
1862ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownenum dwarf_cfa_primary_ops
1863ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  {
1864ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DW_CFA_use_secondary = 0,
1865ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DW_CFA_advance_loc   = 1,
1866ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DW_CFA_offset        = 2,
1867ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DW_CFA_restore       = 3
1868ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  };
1869ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1870ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownenum dwarf_cfa_secondary_ops
1871ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  {
1872ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DW_CFA_nop                = 0x00,
1873ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DW_CFA_set_loc            = 0x01,
1874ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DW_CFA_advance_loc1       = 0x02,
1875ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DW_CFA_advance_loc2       = 0x03,
1876ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DW_CFA_advance_loc4       = 0x04,
1877ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DW_CFA_offset_extended    = 0x05,
1878ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DW_CFA_restore_extended   = 0x06,
1879ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DW_CFA_undefined          = 0x07,
1880ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DW_CFA_same_value         = 0x08,
1881ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DW_CFA_register           = 0x09,
1882ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DW_CFA_remember_state     = 0x0a,
1883ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DW_CFA_restore_state      = 0x0b,
1884ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DW_CFA_def_cfa            = 0x0c,
1885ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DW_CFA_def_cfa_register   = 0x0d,
1886ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DW_CFA_def_cfa_offset     = 0x0e,
1887ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DW_CFA_def_cfa_expression = 0x0f, /* DWARF3 only */
1888ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DW_CFA_expression         = 0x10, /* DWARF3 only */
1889ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DW_CFA_offset_extended_sf = 0x11, /* DWARF3 only */
1890ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DW_CFA_def_cfa_sf         = 0x12, /* DWARF3 only */
1891ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DW_CFA_def_cfa_offset_sf  = 0x13, /* DWARF3 only */
1892ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DW_CFA_val_offset         = 0x14, /* DWARF3 only */
1893ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DW_CFA_val_offset_sf      = 0x15, /* DWARF3 only */
1894ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DW_CFA_val_expression     = 0x16, /* DWARF3 only */
1895ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DW_CFA_lo_user            = 0x1c,
1896ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DW_CFA_GNU_window_save    = 0x2d, /* GNU extension */
1897ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DW_CFA_GNU_args_size      = 0x2e, /* GNU extension */
1898ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DW_CFA_GNU_negative_offset_extended = 0x2f, /* GNU extension */
1899ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DW_CFA_hi_user            = 0x3f
1900ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  };
1901ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1902ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define DW_EH_PE_absptr		0x00
1903ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define DW_EH_PE_omit		0xff
1904ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1905ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define DW_EH_PE_uleb128	0x01
1906ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define DW_EH_PE_udata2		0x02
1907ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define DW_EH_PE_udata4		0x03
1908ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define DW_EH_PE_udata8		0x04
1909ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define DW_EH_PE_sleb128	0x09
1910ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define DW_EH_PE_sdata2		0x0A
1911ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define DW_EH_PE_sdata4		0x0B
1912ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define DW_EH_PE_sdata8		0x0C
1913ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define DW_EH_PE_signed		0x08
1914ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1915ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define DW_EH_PE_pcrel		0x10
1916ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define DW_EH_PE_textrel	0x20
1917ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define DW_EH_PE_datarel	0x30
1918ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define DW_EH_PE_funcrel	0x40
1919ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define DW_EH_PE_aligned	0x50
1920ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1921ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define DW_EH_PE_indirect	0x80
1922ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1923ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1924ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* RegRule and UnwindContext are used temporarily to do the unwinding.
1925ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   The result is then summarised into a sequence of CfiSIs, if
1926ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   possible.  UnwindContext effectively holds the state of the
1927ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   abstract machine whilst it is running.
1928ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1929ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   The CFA can either be a signed offset from a register,
1930ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   or an expression:
1931ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1932ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   CFA = cfa_reg + cfa_off   when UnwindContext.cfa_is_regoff==True
1933ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown       | [[ cfa_expr_id ]]
1934ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1935ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   When .cfa_is_regoff == True,  cfa_expr_id must be zero
1936ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   When .cfa_is_regoff == False, cfa_reg must be zero
1937ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                 and cfa_off must be zero
1938ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1939ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   RegRule describes, for each register, how to get its
1940ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   value in the previous frame, where 'cfa' denotes the cfa
1941ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   for the frame as a whole:
1942ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1943ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   RegRule = RR_Undef          -- undefined
1944ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           | RR_Same           -- same as in previous frame
1945ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           | RR_CFAOff    arg  -- is at * ( cfa + arg )
1946ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           | RR_CFAValOff arg  -- is ( cfa + arg )
1947ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           | RR_Reg       arg  -- is in register 'arg'
1948ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           | RR_Expr      arg  -- is at * [[ arg ]]
1949ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           | RR_ValExpr   arg  -- is [[ arg ]]
1950ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           | RR_Arch           -- dunno
1951ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1952ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Note that RR_Expr is redundant since the same can be represented
1953ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   using RR_ValExpr with an explicit dereference (CfiExpr_Deref) at
1954ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   the outermost level.
1955ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1956ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   All expressions are stored in exprs in the containing
1957ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   UnwindContext.  Since the UnwindContext gets reinitialised for each
1958ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   new FDE, summarise_context needs to copy out any expressions it
1959ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   wants to keep into the cfsi_exprs field of the containing SegInfo.
1960ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown*/
1961ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Browntypedef
1962ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   struct {
1963ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      enum { RR_Undef, RR_Same, RR_CFAOff, RR_CFAValOff,
1964ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown             RR_Reg, /*RR_Expr,*/ RR_ValExpr, RR_Arch } tag;
1965ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* meaning:  int offset for CFAoff/CFAValOff
1966ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                   reg # for Reg
1967ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                   expr index for Expr/ValExpr */
1968ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      Int arg;
1969ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
1970ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   RegRule;
1971ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1972ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic void ppRegRule ( XArray* exprs, RegRule* rrule )
1973ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
1974ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vg_assert(exprs);
1975ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   switch (rrule->tag) {
1976ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case RR_Undef:     VG_(printf)("u  "); break;
1977ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case RR_Same:      VG_(printf)("s  "); break;
1978ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case RR_CFAOff:    VG_(printf)("c%d ", rrule->arg); break;
1979ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case RR_CFAValOff: VG_(printf)("v%d ", rrule->arg); break;
1980ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case RR_Reg:       VG_(printf)("r%d ", rrule->arg); break;
1981ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case RR_ValExpr:   VG_(printf)("ve{");
1982ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                         ML_(ppCfiExpr)( exprs, rrule->arg );
1983ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                         VG_(printf)("} ");
1984ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                         break;
1985ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case RR_Arch:      VG_(printf)("a  "); break;
1986ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      default:           VG_(core_panic)("ppRegRule");
1987ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
1988ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
1989ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1990ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1991ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Size of the stack of register unwind rules.  This is only
1992ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   exceedingly rarely used, so a stack of size 1 should actually work
1993ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   with almost all compiler-generated CFA. */
1994ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define N_RR_STACK 4
1995ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1996ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Browntypedef
1997ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   struct {
1998ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* Read-only fields (set by the CIE) */
1999ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      Int     code_a_f;
2000ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      Int     data_a_f;
2001ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      Addr    initloc;
2002ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      Int     ra_reg;
2003ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* The rest of these fields can be modifed by
2004ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         run_CF_instruction. */
2005ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* The LOC entry */
2006ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      Addr    loc;
2007ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* We need a stack of these in order to handle
2008ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         DW_CFA_{remember,restore}_state. */
2009ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      struct UnwindContextState {
2010ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown          /* The CFA entry.  This can be either reg+/-offset or an expr. */
2011ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown          Bool    cfa_is_regoff; /* True=>is reg+offset; False=>is expr */
2012ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown          Int     cfa_reg;
2013ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown          Int     cfa_off;  /* in bytes */
2014ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown          Int     cfa_expr_ix; /* index into cfa_exprs */
2015ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown          /* Register unwind rules.  */
2016ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown          RegRule reg[N_CFI_REGS];
2017ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
2018ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      state[N_RR_STACK];
2019ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      Int     state_sp; /* 0 <= state_sp < N_RR_STACK; points at the
2020ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                           currently-in-use rule set. */
2021ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* array of CfiExpr, shared by reg[] and cfa_expr_ix */
2022ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      XArray* exprs;
2023ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
2024ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   UnwindContext;
2025ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2026ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic void ppUnwindContext ( UnwindContext* ctx )
2027ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
2028ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Int j, i;
2029ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   VG_(printf)("0x%llx: ", (ULong)ctx->loc);
2030ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   for (j = 0; j <= ctx->state_sp; j++) {
2031ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      struct UnwindContextState* ctxs = &ctx->state[j];
2032ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      VG_(printf)("%s[%d]={ ", j > 0 ? " " : "", j);
2033ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (ctxs->cfa_is_regoff) {
2034ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         VG_(printf)("%d(r%d) ", ctxs->cfa_off, ctxs->cfa_reg);
2035ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      } else {
2036ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         vg_assert(ctx->exprs);
2037ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         VG_(printf)("{");
2038ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         ML_(ppCfiExpr)( ctx->exprs, ctxs->cfa_expr_ix );
2039ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         VG_(printf)("} ");
2040ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
2041ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      VG_(printf)("{ ");
2042ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      for (i = 0; i < N_CFI_REGS; i++)
2043ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         ppRegRule(ctx->exprs, &ctxs->reg[i]);
2044ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      VG_(printf)("}");
2045ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
2046ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   VG_(printf)("\n");
2047ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
2048ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2049ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic void initUnwindContext ( /*OUT*/UnwindContext* ctx )
2050ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
2051ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Int j, i;
2052ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   VG_(memset)(ctx, 0, sizeof(*ctx));
2053ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* ctx->code_a_f   = 0;
2054ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   ctx->data_a_f      = 0;
2055ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   ctx->initloc       = 0; */
2056ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   ctx->ra_reg        = RA_REG_DEFAULT;
2057ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* ctx->loc        = 0;
2058ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   ctx->exprs         = NULL;
2059ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   ctx->state_sp        = 0; */
2060ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   for (j = 0; j < N_RR_STACK; j++) {
2061ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      ctx->state[j].cfa_is_regoff = True;
2062ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* ctx->state[j].cfa_reg    = 0;
2063ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      ctx->state[j].cfa_off       = 0;
2064ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      ctx->state[j].cfa_expr_ix   = 0; */
2065ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      for (i = 0; i < N_CFI_REGS; i++) {
2066ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (RR_Undef != 0)
2067ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           ctx->state[j].reg[i].tag = RR_Undef;
2068ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* ctx->state[j].reg[i].arg = 0; */
2069ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
2070ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#     if defined(VGA_arm)
2071ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* All callee-saved registers (or at least the ones we are
2072ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         summarising for) should start out as RR_Same, on ARM. */
2073ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      ctx->state[j].reg[11].tag = RR_Same;
2074ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* ctx->state[j].reg[13].tag = RR_Same; */
2075ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      ctx->state[j].reg[14].tag = RR_Same;
2076ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      ctx->state[j].reg[12].tag = RR_Same;
2077ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      ctx->state[j].reg[7].tag  = RR_Same;
2078ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* this can't be right though: R12 (IP) isn't callee saved. */
2079ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#     endif
2080ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
2081ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
2082ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2083ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2084ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* A structure which holds information needed by read_encoded_Addr().
2085ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown*/
2086ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Browntypedef
2087ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   struct {
2088ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      UChar  encoding;
2089ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      UChar* ehframe_image;
2090ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      Addr   ehframe_avma;
2091ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      Addr   text_bias;
2092ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
2093ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   AddressDecodingInfo;
2094ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2095ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2096ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* ------------ Deal with summary-info records ------------ */
2097ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2098ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic void initCfiSI ( DiCfSI* si )
2099ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
2100ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   VG_(memset)(si, 0, sizeof(*si));
2101ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
2102ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2103ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2104ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* --------------- Summarisation --------------- */
2105ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2106ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Forward */
2107ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic
2108ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownInt copy_convert_CfiExpr_tree ( XArray*        dst,
2109ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                UnwindContext* srcuc,
2110ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                Int            nd );
2111ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2112ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Summarise ctx into si, if possible.  Returns True if successful.
2113ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   This is taken to be just after ctx's loc advances; hence the
2114ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   summary is up to but not including the current loc.  This works
2115ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   on both x86 and amd64.
2116ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown*/
2117ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic Bool summarise_context( /*OUT*/DiCfSI* si,
2118ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                               Addr loc_start,
2119ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	                       UnwindContext* ctx,
2120ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                               struct _DebugInfo* debuginfo )
2121ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
2122ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Int why = 0;
2123ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   struct UnwindContextState* ctxs;
2124ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   initCfiSI(si);
2125ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2126ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* Guard against obviously stupid settings of the reg-rule stack
2127ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      pointer. */
2128ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (ctx->state_sp < 0)           { why = 8; goto failed; }
2129ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (ctx->state_sp >= N_RR_STACK) { why = 9; goto failed; }
2130ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   ctxs = &ctx->state[ctx->state_sp];
2131ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2132ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* First, summarise the method for generating the CFA */
2133ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (!ctxs->cfa_is_regoff) {
2134ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* it was set by DW_CFA_def_cfa_expression; try to convert */
2135ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      XArray *src, *dst;
2136ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      Int    conv;
2137ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      src = ctx->exprs;
2138ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      dst = debuginfo->cfsi_exprs;
2139ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (src && (VG_(sizeXA)(src) > 0) && (!dst)) {
2140ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         dst = VG_(newXA)( ML_(dinfo_zalloc), "di.ccCt.1", ML_(dinfo_free),
2141ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                           sizeof(CfiExpr) );
2142ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         vg_assert(dst);
2143ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         debuginfo->cfsi_exprs = dst;
2144ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
2145ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      conv = copy_convert_CfiExpr_tree
2146ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    ( dst, ctx, ctxs->cfa_expr_ix );
2147ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      vg_assert(conv >= -1);
2148ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (conv == -1) { why = 6; goto failed; }
2149ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      si->cfa_how = CFIC_EXPR;
2150ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      si->cfa_off = conv;
2151ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (0 && debuginfo->ddump_frames)
2152ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         ML_(ppCfiExpr)(dst, conv);
2153ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
2154ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   else
2155ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (ctxs->cfa_is_regoff && ctxs->cfa_reg == SP_REG) {
2156ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      si->cfa_off = ctxs->cfa_off;
2157b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov#     if defined(VGA_x86) || defined(VGA_amd64) || defined(VGA_s390x)
2158ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      si->cfa_how = CFIC_IA_SPREL;
2159ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#     elif defined(VGA_arm)
2160ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      si->cfa_how = CFIC_ARM_R13REL;
2161ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#     else
2162ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      si->cfa_how = 0; /* invalid */
2163ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#     endif
2164ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
2165ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   else
2166ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (ctxs->cfa_is_regoff && ctxs->cfa_reg == FP_REG) {
2167ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      si->cfa_off = ctxs->cfa_off;
2168b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov#     if defined(VGA_x86) || defined(VGA_amd64) || defined(VGA_s390x)
2169ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      si->cfa_how = CFIC_IA_BPREL;
2170ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#     elif defined(VGA_arm)
2171ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      si->cfa_how = CFIC_ARM_R12REL;
2172ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#     else
2173ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      si->cfa_how = 0; /* invalid */
2174ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#     endif
2175ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
2176ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#  if defined(VGA_arm)
2177ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   else
2178ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (ctxs->cfa_is_regoff && ctxs->cfa_reg == 11/*??_REG*/) {
2179ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      si->cfa_how = CFIC_ARM_R11REL;
2180ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      si->cfa_off = ctxs->cfa_off;
2181ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
2182ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   else
2183ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (ctxs->cfa_is_regoff && ctxs->cfa_reg == 7/*??_REG*/) {
2184ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      si->cfa_how = CFIC_ARM_R7REL;
2185ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      si->cfa_off = ctxs->cfa_off;
2186ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
2187ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#  endif
2188ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   else {
2189ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      why = 1;
2190ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      goto failed;
2191ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
2192ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2193ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#  define SUMMARISE_HOW(_how, _off, _ctxreg)                  \
2194ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   switch (_ctxreg.tag) {                                     \
2195ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case RR_Undef:                                          \
2196ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         _how = CFIR_UNKNOWN;   _off = 0; break;              \
2197ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case RR_Same:                                           \
2198ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         _how = CFIR_SAME;      _off = 0; break;              \
2199ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case RR_CFAOff:                                         \
2200ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         _how = CFIR_MEMCFAREL; _off = _ctxreg.arg; break;    \
2201ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case RR_CFAValOff:                                      \
2202ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         _how = CFIR_CFAREL;    _off = _ctxreg.arg; break;    \
2203ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case RR_ValExpr: {                                      \
2204ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         XArray *src, *dst;                                   \
2205ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         Int    conv;                                         \
2206ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         src = ctx->exprs;                                    \
2207ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         dst = debuginfo->cfsi_exprs;                         \
2208ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (src && (VG_(sizeXA)(src) > 0) && (!dst)) {       \
2209ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            dst = VG_(newXA)( ML_(dinfo_zalloc),              \
2210ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                              "di.ccCt.2",                    \
2211ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                              ML_(dinfo_free),                \
2212ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                              sizeof(CfiExpr) );              \
2213ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            vg_assert(dst);                                   \
2214ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            debuginfo->cfsi_exprs = dst;                      \
2215ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }                                                    \
2216ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         conv = copy_convert_CfiExpr_tree                     \
2217ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                       ( dst, ctx, _ctxreg.arg );             \
2218ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         vg_assert(conv >= -1);                               \
2219ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (conv == -1) { why = 7; goto failed; }            \
2220ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         _how = CFIR_EXPR;                                    \
2221ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         _off = conv;                                         \
2222ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (0 && debuginfo->ddump_frames)                    \
2223ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            ML_(ppCfiExpr)(dst, conv);                        \
2224ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         break;                                               \
2225ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }                                                       \
2226ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      default:                                                \
2227ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         why = 2; goto failed; /* otherwise give up */        \
2228ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
2229ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2230ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#  if defined(VGA_x86) || defined(VGA_amd64)
2231ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2232ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* --- entire tail of this fn specialised for x86/amd64 --- */
2233ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2234ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   SUMMARISE_HOW(si->ra_how, si->ra_off,
2235ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                             ctxs->reg[ctx->ra_reg] );
2236ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   SUMMARISE_HOW(si->bp_how, si->bp_off,
2237ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                             ctxs->reg[FP_REG] );
2238ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2239ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* on x86/amd64, it seems the old %{e,r}sp value before the call is
2240ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      always the same as the CFA.  Therefore ... */
2241ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   si->sp_how = CFIR_CFAREL;
2242ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   si->sp_off = 0;
2243ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2244ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* also, gcc says "Undef" for %{e,r}bp when it is unchanged.  So
2245ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      .. */
2246ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (ctxs->reg[FP_REG].tag == RR_Undef)
2247ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      si->bp_how = CFIR_SAME;
2248ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2249ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* knock out some obviously stupid cases */
2250ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (si->ra_how == CFIR_SAME)
2251ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      { why = 3; goto failed; }
2252ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2253ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* bogus looking range?  Note, we require that the difference is
2254ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      representable in 32 bits. */
2255ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (loc_start >= ctx->loc)
2256ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      { why = 4; goto failed; }
2257ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (ctx->loc - loc_start > 10000000 /* let's say */)
2258ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      { why = 5; goto failed; }
2259ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2260ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   si->base = loc_start + ctx->initloc;
2261ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   si->len  = (UInt)(ctx->loc - loc_start);
2262ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2263ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return True;
2264ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2265ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#  elif defined(VGA_arm)
2266ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2267ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* ---- entire tail of this fn specialised for arm ---- */
2268ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2269ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   SUMMARISE_HOW(si->r14_how, si->r14_off,
2270ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                              ctxs->reg[14] );
2271ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2272ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   //SUMMARISE_HOW(si->r13_how, si->r13_off,
2273ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   //                           ctxs->reg[13] );
2274ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2275ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   SUMMARISE_HOW(si->r12_how, si->r12_off,
2276ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                              ctxs->reg[FP_REG] );
2277ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2278ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   SUMMARISE_HOW(si->r11_how, si->r11_off,
2279ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                              ctxs->reg[11/*FP_REG*/] );
2280ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2281ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   SUMMARISE_HOW(si->r7_how, si->r7_off,
2282ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                             ctxs->reg[7] );
2283ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2284ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (ctxs->reg[14/*LR*/].tag == RR_Same
2285ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown       && ctx->ra_reg == 14/*as we expect it always to be*/) {
2286ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* Generate a trivial CfiExpr, which merely says "r14".  First
2287ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         ensure this DebugInfo has a cfsi_expr array in which to park
2288ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         it. */
2289ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (!debuginfo->cfsi_exprs)
2290ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         debuginfo->cfsi_exprs = VG_(newXA)( ML_(dinfo_zalloc),
2291ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                             "di.ccCt.2a",
2292ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                             ML_(dinfo_free),
2293ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                             sizeof(CfiExpr) );
2294ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      si->ra_off = ML_(CfiExpr_CfiReg)( debuginfo->cfsi_exprs,
2295ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                        Creg_ARM_R14);
2296ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      si->ra_how = CFIR_EXPR;
2297ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   } else {
2298ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* Just summarise it in the normal way */
2299ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      SUMMARISE_HOW(si->ra_how, si->ra_off,
2300ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                ctxs->reg[ctx->ra_reg] );
2301ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
2302ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2303ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* on arm, it seems the old r13 (SP) value before the call is
2304ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      always the same as the CFA.  Therefore ... */
2305ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   si->r13_how = CFIR_CFAREL;
2306ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   si->r13_off = 0;
2307ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2308ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* bogus looking range?  Note, we require that the difference is
2309ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      representable in 32 bits. */
2310ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (loc_start >= ctx->loc)
2311ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      { why = 4; goto failed; }
2312ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (ctx->loc - loc_start > 10000000 /* let's say */)
2313ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      { why = 5; goto failed; }
2314ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2315ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   si->base = loc_start + ctx->initloc;
2316ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   si->len  = (UInt)(ctx->loc - loc_start);
2317ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2318ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return True;
2319ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2320ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2321b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov#  elif defined(VGA_s390x)
2322b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
2323b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   SUMMARISE_HOW(si->ra_how, si->ra_off,
2324b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                             ctxs->reg[ctx->ra_reg] );
2325b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   SUMMARISE_HOW(si->fp_how, si->fp_off,
2326b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                             ctxs->reg[FP_REG] );
2327b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   SUMMARISE_HOW(si->sp_how, si->sp_off,
2328b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                             ctxs->reg[SP_REG] );
2329b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
2330b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   /* change some defaults to consumable values */
2331b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   if (si->sp_how == CFIR_UNKNOWN)
2332b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      si->sp_how = CFIR_SAME;
2333b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
2334b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   if (si->fp_how == CFIR_UNKNOWN)
2335b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      si->fp_how = CFIR_SAME;
2336b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
2337b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   if (si->cfa_how == CFIR_UNKNOWN) {
2338b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      si->cfa_how = CFIC_IA_SPREL;
2339b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      si->cfa_off = 160;
2340b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   }
2341b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   if (si->ra_how == CFIR_UNKNOWN) {
2342b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      if (!debuginfo->cfsi_exprs)
2343b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         debuginfo->cfsi_exprs = VG_(newXA)( ML_(dinfo_zalloc),
2344b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                                             "di.ccCt.2a",
2345b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                                             ML_(dinfo_free),
2346b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                                             sizeof(CfiExpr) );
2347b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      si->ra_how = CFIR_EXPR;
2348b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      si->ra_off = ML_(CfiExpr_CfiReg)( debuginfo->cfsi_exprs,
2349b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                                        Creg_S390_R14);
2350b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   }
2351b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
2352b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   /* knock out some obviously stupid cases */
2353b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   if (si->ra_how == CFIR_SAME)
2354b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      { why = 3; goto failed; }
2355b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
2356b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   /* bogus looking range?  Note, we require that the difference is
2357b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      representable in 32 bits. */
2358b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   if (loc_start >= ctx->loc)
2359b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      { why = 4; goto failed; }
2360b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   if (ctx->loc - loc_start > 10000000 /* let's say */)
2361b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      { why = 5; goto failed; }
2362b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
2363b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   si->base = loc_start + ctx->initloc;
2364b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   si->len  = (UInt)(ctx->loc - loc_start);
2365b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
2366b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   return True;
2367b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
2368b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
2369b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
2370ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#  elif defined(VGA_ppc32) || defined(VGA_ppc64)
2371ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#  else
2372ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#    error "Unknown arch"
2373ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#  endif
2374ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2375ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#  undef SUMMARISE_HOW
2376ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2377ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  failed:
2378ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (VG_(clo_verbosity) > 2 || debuginfo->trace_cfi) {
2379ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      VG_(message)(Vg_DebugMsg,
2380ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  "summarise_context(loc_start = %#lx)"
2381ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  ": cannot summarise(why=%d):   \n", loc_start, why);
2382ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      ppUnwindContext(ctx);
2383ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
2384ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return False;
2385ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
2386ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2387ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Copy the tree rooted at srcuc->exprs node srcix to dstxa, on the
2388ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   way converting any DwReg regs (regs numbered using the Dwarf scheme
2389ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   defined by each architecture's ABI) into CfiRegs, which are
2390ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   platform independent.  If the conversion isn't possible because
2391ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   there is no equivalent register, return -1.  This has the
2392ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   undesirable side effect of de-dagifying the input; oh well. */
2393ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic Int copy_convert_CfiExpr_tree ( XArray*        dstxa,
2394ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                       UnwindContext* srcuc,
2395ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                       Int            srcix )
2396ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
2397ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   CfiExpr* src;
2398b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   Int      cpL, cpR, cpA;
2399ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   XArray*  srcxa = srcuc->exprs;
2400ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vg_assert(srcxa);
2401ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vg_assert(dstxa);
2402ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vg_assert(srcix >= 0 && srcix < VG_(sizeXA)(srcxa));
2403ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2404ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   src = VG_(indexXA)( srcxa, srcix );
2405ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   switch (src->tag) {
2406ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Cex_Undef:
2407ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return ML_(CfiExpr_Undef)( dstxa );
2408ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Cex_Deref:
2409ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         cpA = copy_convert_CfiExpr_tree( dstxa, srcuc, src->Cex.Deref.ixAddr );
2410ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (cpA == -1)
2411ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            return -1; /* propagate failure */
2412ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return ML_(CfiExpr_Deref)( dstxa, cpA );
2413ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Cex_Const:
2414ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return ML_(CfiExpr_Const)( dstxa, src->Cex.Const.con );
2415ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Cex_Binop:
2416ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         cpL = copy_convert_CfiExpr_tree( dstxa, srcuc, src->Cex.Binop.ixL );
2417ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         cpR = copy_convert_CfiExpr_tree( dstxa, srcuc, src->Cex.Binop.ixR );
2418ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         vg_assert(cpL >= -1 && cpR >= -1);
2419ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (cpL == -1 || cpR == -1)
2420ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            return -1; /* propagate failure */
2421ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return ML_(CfiExpr_Binop)( dstxa, src->Cex.Binop.op, cpL, cpR );
2422ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Cex_CfiReg:
2423ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* should not see these in input (are created only by this
2424ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            conversion step!) */
2425ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         VG_(core_panic)("copy_convert_CfiExpr_tree: CfiReg in input");
2426b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      case Cex_DwReg: {
2427ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* This is the only place where the conversion can fail. */
2428b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         Int dwreg __attribute__((unused));
2429ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         dwreg = src->Cex.DwReg.reg;
2430ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#        if defined(VGA_x86) || defined(VGA_amd64)
2431ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (dwreg == SP_REG)
2432ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            return ML_(CfiExpr_CfiReg)( dstxa, Creg_IA_SP );
2433ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (dwreg == FP_REG)
2434ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            return ML_(CfiExpr_CfiReg)( dstxa, Creg_IA_BP );
2435ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (dwreg == srcuc->ra_reg)
2436ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            return ML_(CfiExpr_CfiReg)( dstxa, Creg_IA_IP ); /* correct? */
2437ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#        elif defined(VGA_arm)
2438ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (dwreg == SP_REG)
2439ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            return ML_(CfiExpr_CfiReg)( dstxa, Creg_ARM_R13 );
2440ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (dwreg == FP_REG)
2441ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            return ML_(CfiExpr_CfiReg)( dstxa, Creg_ARM_R12 );
2442ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (dwreg == srcuc->ra_reg)
2443ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           return ML_(CfiExpr_CfiReg)( dstxa, Creg_ARM_R15 ); /* correct? */
2444b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov#        elif defined(VGA_s390x)
2445b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         if (dwreg == SP_REG)
2446b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov            return ML_(CfiExpr_CfiReg)( dstxa, Creg_IA_SP );
2447b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         if (dwreg == FP_REG)
2448b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov            return ML_(CfiExpr_CfiReg)( dstxa, Creg_IA_BP );
2449b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         if (dwreg == srcuc->ra_reg)
2450b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov            return ML_(CfiExpr_CfiReg)( dstxa, Creg_IA_IP ); /* correct? */
2451ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#        elif defined(VGA_ppc32) || defined(VGA_ppc64)
2452ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#        else
2453ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#           error "Unknown arch"
2454ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#        endif
2455ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* else we must fail - can't represent the reg */
2456ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return -1;
2457b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      }
2458ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      default:
2459ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         VG_(core_panic)("copy_convert_CfiExpr_tree: default");
2460ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
2461ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
2462ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2463ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2464ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic void ppUnwindContext_summary ( UnwindContext* ctx )
2465ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
2466ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   struct UnwindContextState* ctxs = &ctx->state[ctx->state_sp];
2467ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2468ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   VG_(printf)("0x%llx-1: ", (ULong)ctx->loc);
2469ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2470ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (ctxs->cfa_reg == SP_REG) {
2471ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      VG_(printf)("SP/CFA=%d+SP   ", ctxs->cfa_off);
2472ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   } else
2473ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (ctxs->cfa_reg == FP_REG) {
2474ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      VG_(printf)("SP/CFA=%d+FP   ", ctxs->cfa_off);
2475ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   } else {
2476ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      VG_(printf)("SP/CFA=unknown  ");
2477ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
2478ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2479ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   VG_(printf)("RA=");
2480ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   ppRegRule( ctx->exprs, &ctxs->reg[ctx->ra_reg] );
2481ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2482ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   VG_(printf)("FP=");
2483ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   ppRegRule( ctx->exprs, &ctxs->reg[FP_REG] );
2484ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   VG_(printf)("\n");
2485ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
2486ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2487ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2488ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* ------------ Pick apart DWARF2 byte streams ------------ */
2489ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2490ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic ULong read_le_u_encoded_literal ( UChar* data, UInt size )
2491ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
2492ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   switch (size) {
2493b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      case 8:  return (ULong)ML_(read_ULong)( data );
2494b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      case 4:  return (ULong)ML_(read_UInt)( data );
2495b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      case 2:  return (ULong)ML_(read_UShort)( data );
2496b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      case 1:  return (ULong)ML_(read_UChar)( data );
2497ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      default: vg_assert(0); /*NOTREACHED*/ return 0;
2498ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
2499ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
2500ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2501ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic Long read_le_s_encoded_literal ( UChar* data, UInt size )
2502ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
2503ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Long s64 = read_le_u_encoded_literal( data, size );
2504ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   switch (size) {
2505ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 8:  break;
2506ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 4:  s64 <<= 32; s64 >>= 32; break;
2507ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 2:  s64 <<= 48; s64 >>= 48; break;
2508ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 1:  s64 <<= 56; s64 >>= 56; break;
2509ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      default: vg_assert(0); /*NOTREACHED*/ return 0;
2510ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
2511ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return s64;
2512ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
2513ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2514ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic UChar default_Addr_encoding ( void )
2515ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
2516ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   switch (sizeof(Addr)) {
2517ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 4: return DW_EH_PE_udata4;
2518ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 8: return DW_EH_PE_udata8;
2519ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      default: vg_assert(0);
2520ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
2521ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
2522ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2523ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic UInt size_of_encoded_Addr ( UChar encoding )
2524ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
2525ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (encoding == DW_EH_PE_omit)
2526ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return 0;
2527ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2528ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   switch (encoding & 0x07) {
2529ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case DW_EH_PE_absptr: return sizeof(Addr);
2530ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case DW_EH_PE_udata2: return sizeof(UShort);
2531ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case DW_EH_PE_udata4: return sizeof(UInt);
2532ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case DW_EH_PE_udata8: return sizeof(ULong);
2533ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      default: vg_assert(0);
2534ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
2535ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
2536ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2537ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic Addr read_encoded_Addr ( /*OUT*/Int* nbytes,
2538ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                AddressDecodingInfo* adi,
2539ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                UChar* data )
2540ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
2541ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* Regarding the handling of DW_EH_PE_absptr.  DWARF3 says this
2542ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      denotes an absolute address, hence you would think 'base' is
2543ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      zero.  However, that is nonsensical (unless relocations are to
2544ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      be applied to the unwind data before reading it, which sounds
2545ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      unlikely).  My interpretation is that DW_EH_PE_absptr indicates
2546ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      an address relative to where the object was loaded (technically,
2547ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      relative to its stated load VMA, hence the use of text_bias
2548ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      rather than text_avma).  Hmm, should we use text_bias or
2549ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      text_avma here?  Not sure.
2550ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2551ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      This view appears to be supported by DWARF3 spec sec 7.3
2552ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      "Executable Objects and Shared Objects":
2553ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2554ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         This requirement makes the debugging information for shared
2555ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         objects position independent.  Virtual addresses in a shared
2556ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         object may be calculated by adding the offset to the base
2557ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         address at which the object was attached.  This offset is
2558ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         available in the run-time linker's data structures.
2559ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   */
2560ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Addr   base;
2561ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Word   offset;
2562ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   UChar  encoding      = adi->encoding;
2563ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   UChar* ehframe_image = adi->ehframe_image;
2564ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Addr   ehframe_avma  = adi->ehframe_avma;
2565ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2566ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vg_assert((encoding & DW_EH_PE_indirect) == 0);
2567ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2568ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   *nbytes = 0;
2569ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2570ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   switch (encoding & 0x70) {
2571ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case DW_EH_PE_absptr:
2572ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         base = adi->text_bias;
2573ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         break;
2574ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case DW_EH_PE_pcrel:
2575ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         base = ehframe_avma + ( data - ehframe_image );
2576ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         break;
2577ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case DW_EH_PE_datarel:
2578ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         vg_assert(0);
2579ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         base = /* data base address */ 0;
2580ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         break;
2581ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case DW_EH_PE_textrel:
2582ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         vg_assert(0);
2583ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         base = /* text base address */ 0;
2584ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         break;
2585ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case DW_EH_PE_funcrel:
2586ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         base = 0;
2587ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         break;
2588ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case DW_EH_PE_aligned:
2589ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         base = 0;
2590ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         offset = data - ehframe_image;
2591ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if ((offset % sizeof(Addr)) != 0) {
2592ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            *nbytes = sizeof(Addr) - (offset % sizeof(Addr));
2593ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            data += *nbytes;
2594ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
2595ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         break;
2596ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      default:
2597ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         vg_assert(0);
2598ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
2599ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2600ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if ((encoding & 0x07) == 0x00)
2601ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      encoding |= default_Addr_encoding();
2602ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2603ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   switch (encoding & 0x0f) {
2604ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case DW_EH_PE_udata2:
2605ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         *nbytes += sizeof(UShort);
2606b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         return base + ML_(read_UShort)(data);
2607ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case DW_EH_PE_udata4:
2608ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         *nbytes += sizeof(UInt);
2609b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         return base + ML_(read_UInt)(data);
2610ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case DW_EH_PE_udata8:
2611ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         *nbytes += sizeof(ULong);
2612b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         return base + ML_(read_ULong)(data);
2613ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case DW_EH_PE_sdata2:
2614ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         *nbytes += sizeof(Short);
2615b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         return base + ML_(read_Short)(data);
2616ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case DW_EH_PE_sdata4:
2617ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         *nbytes += sizeof(Int);
2618b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         return base + ML_(read_Int)(data);
2619ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case DW_EH_PE_sdata8:
2620ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         *nbytes += sizeof(Long);
2621b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         return base + ML_(read_Long)(data);
2622ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      default:
2623ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         vg_assert2(0, "read encoded address %d\n", encoding & 0x0f);
2624ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
2625ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
2626ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2627ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2628ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* ------------ Run/show DWARF3 expressions ---------- */
2629ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2630ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Convert the DWARF3 expression in expr[0 .. exprlen-1] into a dag
2631ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   (of CfiExprs) stored in ctx->exprs, and return the index in
2632ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   ctx->exprs of the root node.  Or fail in which case return -1. */
2633ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* IMPORTANT: when adding expression forms here, also remember to
2634ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   add suitable evaluation code in evalCfiExpr in debuginfo.c. */
2635ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic Int dwarfexpr_to_dag ( UnwindContext* ctx,
2636ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                              UChar* expr, Int exprlen,
2637ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                              Bool push_cfa_at_start,
2638ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                              Bool ddump_frames )
2639ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
2640ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#  define N_EXPR_STACK 20
2641ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2642ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#  define PUSH(_arg)                               \
2643ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      do {                                         \
2644ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         vg_assert(sp >= -1 && sp < N_EXPR_STACK); \
2645ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (sp == N_EXPR_STACK-1)                 \
2646ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            return -1;                             \
2647ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         sp++;                                     \
2648ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         stack[sp] = (_arg);                       \
2649ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      } while (0)
2650ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2651ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#  define POP(_lval)                               \
2652ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      do {                                         \
2653ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         vg_assert(sp >= -1 && sp < N_EXPR_STACK); \
2654ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (sp == -1)                             \
2655ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            return -1;                             \
2656ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         _lval = stack[sp];                        \
2657ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         sp--;                                     \
2658ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      } while (0)
2659ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2660ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Int    ix, ix2, reg;
2661ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   UChar  opcode;
2662ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Word   sw;
2663ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   UWord  uw;
2664ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   CfiOp  op;
2665ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   HChar* opname;
2666ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2667ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Int sp; /* # of top element: valid is -1 .. N_EXPR_STACK-1 */
2668ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Int stack[N_EXPR_STACK];  /* indices into ctx->exprs */
2669ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   struct UnwindContextState* ctxs = &ctx->state[ctx->state_sp];
2670ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2671ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   XArray* dst   = ctx->exprs;
2672ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   UChar*  limit = expr + exprlen;
2673ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2674ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vg_assert(dst);
2675ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vg_assert(exprlen >= 0);
2676ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2677ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   sp = -1; /* empty */
2678ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2679ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* Synthesise the CFA as a CfiExpr */
2680ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (push_cfa_at_start) {
2681ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (ctxs->cfa_is_regoff) {
2682ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* cfa is reg +/- offset */
2683ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         ix = ML_(CfiExpr_Binop)( dst,
2684ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                 Cop_Add,
2685ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                 ML_(CfiExpr_DwReg)( dst, ctxs->cfa_reg ),
2686ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                 ML_(CfiExpr_Const)( dst, (UWord)(Word)ctxs->cfa_off )
2687ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown              );
2688ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         PUSH(ix);
2689ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      } else {
2690ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* CFA is already an expr; use its root node */
2691ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         PUSH(ctxs->cfa_expr_ix);
2692ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
2693ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
2694ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2695ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   while (True) {
2696ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2697ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      vg_assert(sp >= -1 && sp < N_EXPR_STACK);
2698ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2699ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (expr > limit)
2700ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return -1;  /* overrun - something's wrong */
2701ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2702ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (expr == limit) {
2703ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        /* end of expr - return expr on the top of stack. */
2704ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        if (sp == -1)
2705ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           return -1; /* stack empty.  Bad. */
2706ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        else
2707ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           break;
2708ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
2709ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2710ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      op = 0; opname = NULL; /* excessively conservative */
2711ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2712ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      opcode = *expr++;
2713ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      switch (opcode) {
2714ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2715ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case DW_OP_lit0 ... DW_OP_lit31:
2716ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            /* push: literal 0 .. 31 */
2717ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            sw = (Word)opcode - (Word)DW_OP_lit0;
2718ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            vg_assert(sw >= 0 && sw <= 31);
2719ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            PUSH( ML_(CfiExpr_Const)( dst, (UWord)sw ) );
2720ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            if (ddump_frames)
2721ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               VG_(printf)("DW_OP_lit%ld", sw);
2722ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            break;
2723ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2724ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case DW_OP_breg0 ... DW_OP_breg31:
2725ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            /* push: reg + sleb128 */
2726ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            reg = (Int)opcode - (Int)DW_OP_breg0;
2727ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            vg_assert(reg >= 0 && reg <= 31);
2728ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            sw = read_leb128S( &expr );
2729ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            ix = ML_(CfiExpr_Binop)( dst,
2730ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    Cop_Add,
2731ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    ML_(CfiExpr_DwReg)( dst, reg ),
2732ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    ML_(CfiExpr_Const)( dst, (UWord)sw )
2733ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                 );
2734ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            PUSH(ix);
2735ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            if (ddump_frames)
2736ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               VG_(printf)("DW_OP_breg%d: %ld", reg, sw);
2737ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            break;
2738ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2739ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case DW_OP_reg0 ... DW_OP_reg31:
2740ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            /* push: reg */
2741ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            reg = (Int)opcode - (Int)DW_OP_reg0;
2742ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            vg_assert(reg >= 0 && reg <= 31);
2743ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            ix = ML_(CfiExpr_DwReg)( dst, reg );
2744ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            PUSH(ix);
2745ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            if (ddump_frames)
2746ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               VG_(printf)("DW_OP_reg%d", reg);
2747ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            break;
2748ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2749ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case DW_OP_plus_uconst:
2750ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            uw = read_leb128U( &expr );
2751ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            PUSH( ML_(CfiExpr_Const)( dst, uw ) );
2752ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            POP( ix );
2753ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            POP( ix2 );
2754ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            PUSH( ML_(CfiExpr_Binop)( dst, op, ix2, ix ) );
2755ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            if (ddump_frames)
2756ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               VG_(printf)("DW_OP_plus_uconst: %lu", uw);
2757ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            break;
2758ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2759ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case DW_OP_const4s:
2760ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            /* push: 32-bit signed immediate */
2761ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            sw = read_le_s_encoded_literal( expr, 4 );
2762ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            expr += 4;
2763ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            PUSH( ML_(CfiExpr_Const)( dst, (UWord)sw ) );
2764ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            if (ddump_frames)
2765ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               VG_(printf)("DW_OP_const4s: %ld", sw);
2766ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            break;
2767ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2768ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case DW_OP_const1s:
2769ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            /* push: 8-bit signed immediate */
2770ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            sw = read_le_s_encoded_literal( expr, 1 );
2771ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            expr += 1;
2772ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            PUSH( ML_(CfiExpr_Const)( dst, (UWord)sw ) );
2773ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            if (ddump_frames)
2774ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               VG_(printf)("DW_OP_const1s: %ld", sw);
2775ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            break;
2776ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2777ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case DW_OP_minus:
2778ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            op = Cop_Sub; opname = "minus"; goto binop;
2779ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case DW_OP_plus:
2780ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            op = Cop_Add; opname = "plus"; goto binop;
2781ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case DW_OP_and:
2782ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            op = Cop_And; opname = "and"; goto binop;
2783ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case DW_OP_mul:
2784ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            op = Cop_Mul; opname = "mul"; goto binop;
2785b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         case DW_OP_shl:
2786b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov            op = Cop_Shl; opname = "shl"; goto binop;
2787b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         case DW_OP_shr:
2788b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov            op = Cop_Shr; opname = "shr"; goto binop;
2789b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         case DW_OP_eq:
2790b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov            op = Cop_Eq; opname = "eq"; goto binop;
2791b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         case DW_OP_ge:
2792b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov            op = Cop_Ge; opname = "ge"; goto binop;
2793b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         case DW_OP_gt:
2794b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov            op = Cop_Gt; opname = "gt"; goto binop;
2795b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         case DW_OP_le:
2796b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov            op = Cop_Le; opname = "le"; goto binop;
2797b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         case DW_OP_lt:
2798b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov            op = Cop_Lt; opname = "lt"; goto binop;
2799b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         case DW_OP_ne:
2800b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov            op = Cop_Ne; opname = "ne"; goto binop;
2801ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         binop:
2802ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            POP( ix );
2803ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            POP( ix2 );
2804ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            PUSH( ML_(CfiExpr_Binop)( dst, op, ix2, ix ) );
2805ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            if (ddump_frames)
2806ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               VG_(printf)("DW_OP_%s", opname);
2807ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            break;
2808ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2809ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case DW_OP_deref:
2810ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            POP( ix );
2811ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            PUSH( ML_(CfiExpr_Deref)( dst, ix ) );
2812ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            if (ddump_frames)
2813ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               VG_(printf)("DW_OP_deref");
2814ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            break;
2815ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2816ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         default:
2817ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            if (!VG_(clo_xml))
2818ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               VG_(message)(Vg_DebugMsg,
2819ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                            "Warning: DWARF2 CFI reader: unhandled DW_OP_ "
2820ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                            "opcode 0x%x\n", (Int)opcode);
2821ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            return -1;
2822ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
2823ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2824ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (expr < limit && ddump_frames)
2825ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         VG_(printf)("; ");
2826ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2827ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
2828ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2829ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vg_assert(sp >= -1 && sp < N_EXPR_STACK);
2830ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (sp == -1)
2831ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return -1;
2832ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2833ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (0 && ddump_frames)
2834ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      ML_(ppCfiExpr)( dst, stack[sp] );
2835ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return stack[sp];
2836ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2837ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#  undef POP
2838ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#  undef PUSH
2839ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#  undef N_EXPR_STACK
2840ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
2841ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2842ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2843ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* ------------ Run/show CFI instructions ------------ */
2844ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2845ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Run a CFI instruction, and also return its length.
2846ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Returns 0 if the instruction could not be executed.
2847ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown*/
2848ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic Int run_CF_instruction ( /*MOD*/UnwindContext* ctx,
2849ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                UChar* instr,
2850ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                UnwindContext* restore_ctx,
2851ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                AddressDecodingInfo* adi,
2852ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                struct _DebugInfo* di )
2853ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
2854ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Int    off, reg, reg2, nleb, len;
2855ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   UInt   delta;
2856ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   UChar* expr;
2857ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Int    j;
2858ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Int    i   = 0;
2859ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   UChar  hi2 = (instr[i] >> 6) & 3;
2860ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   UChar  lo6 = instr[i] & 0x3F;
2861ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Addr   printing_bias = ((Addr)ctx->initloc) - ((Addr)di->text_bias);
2862ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   struct UnwindContextState* ctxs;
2863ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   i++;
2864ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2865ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (ctx->state_sp < 0 || ctx->state_sp >= N_RR_STACK)
2866ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return 0; /* bogus reg-rule stack pointer */
2867ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2868ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   ctxs = &ctx->state[ctx->state_sp];
2869ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (hi2 == DW_CFA_advance_loc) {
2870ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      delta = (UInt)lo6;
2871ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      delta *= ctx->code_a_f;
2872ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      ctx->loc += delta;
2873ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (di->ddump_frames)
2874ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         VG_(printf)("  DW_CFA_advance_loc: %d to %08lx\n",
2875ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     (Int)delta, (Addr)ctx->loc + printing_bias);
2876ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return i;
2877ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
2878ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2879ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (hi2 == DW_CFA_offset) {
2880ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* Set rule for reg 'lo6' to CFAOff(off * data_af) */
2881ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      off = read_leb128( &instr[i], &nleb, 0 );
2882ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      i += nleb;
2883ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      reg = (Int)lo6;
2884ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (reg < 0 || reg >= N_CFI_REGS)
2885ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return 0; /* fail */
2886ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      ctxs->reg[reg].tag = RR_CFAOff;
2887ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      ctxs->reg[reg].arg = off * ctx->data_a_f;
2888ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (di->ddump_frames)
2889ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         VG_(printf)("  DW_CFA_offset: r%d at cfa%s%d\n",
2890ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     (Int)reg,
2891ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     ctxs->reg[reg].arg < 0 ? "" : "+",
2892ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     (Int)ctxs->reg[reg].arg );
2893ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return i;
2894ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
2895ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2896ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (hi2 == DW_CFA_restore) {
2897ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      reg = (Int)lo6;
2898ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (reg < 0 || reg >= N_CFI_REGS)
2899ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return 0; /* fail */
2900ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (restore_ctx == NULL)
2901ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return 0; /* fail */
2902ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      ctxs->reg[reg] = restore_ctx->state[restore_ctx->state_sp].reg[reg];
2903ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (di->ddump_frames)
2904ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         VG_(printf)("  DW_CFA_restore: r%d\n", (Int)reg);
2905ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return i;
2906ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
2907ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2908ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vg_assert(hi2 == DW_CFA_use_secondary);
2909ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2910ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   switch (lo6) {
2911ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case DW_CFA_nop:
2912ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (di->ddump_frames)
2913ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            VG_(printf)("  DW_CFA_nop\n");
2914ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         break;
2915ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case DW_CFA_set_loc:
2916ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* WAS:
2917ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            ctx->loc = read_Addr(&instr[i]) - ctx->initloc; i+= sizeof(Addr);
2918ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            Was this ever right? */
2919ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* 2007 Feb 23: No.  binutils/dwarf.c treats it as an encoded
2920ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            address and that appears to be in accordance with the
2921ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            DWARF3 spec. */
2922ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         ctx->loc = read_encoded_Addr(&len, adi, &instr[i]);
2923ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         i += len;
2924ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (di->ddump_frames)
2925ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            VG_(printf)("  rci:DW_CFA_set_loc\n");
2926ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         break;
2927ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case DW_CFA_advance_loc1:
2928b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         delta = (UInt)ML_(read_UChar)(&instr[i]); i+= sizeof(UChar);
2929ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         delta *= ctx->code_a_f;
2930ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         ctx->loc += delta;
2931ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (di->ddump_frames)
2932ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            VG_(printf)("  DW_CFA_advance_loc1: %d to %08lx\n",
2933ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        (Int)delta, (Addr)ctx->loc + printing_bias);
2934ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         break;
2935ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case DW_CFA_advance_loc2:
2936b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         delta = (UInt)ML_(read_UShort)(&instr[i]); i+= sizeof(UShort);
2937ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         delta *= ctx->code_a_f;
2938ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         ctx->loc += delta;
2939ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (di->ddump_frames)
2940ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            VG_(printf)("  DW_CFA_advance_loc2: %d to %08lx\n",
2941ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        (Int)delta, (Addr)ctx->loc + printing_bias);
2942ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         break;
2943ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case DW_CFA_advance_loc4:
2944b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         delta = (UInt)ML_(read_UInt)(&instr[i]); i+= sizeof(UInt);
2945ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         delta *= ctx->code_a_f;
2946ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         ctx->loc += delta;
2947ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (di->ddump_frames)
2948ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            VG_(printf)("  DW_CFA_advance_loc4: %d to %08lx\n",
2949ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        (Int)delta, (Addr)ctx->loc + printing_bias);
2950ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         break;
2951ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2952ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case DW_CFA_def_cfa:
2953ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         reg = read_leb128( &instr[i], &nleb, 0 );
2954ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         i += nleb;
2955ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         off = read_leb128( &instr[i], &nleb, 0 );
2956ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         i += nleb;
2957ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (reg < 0 || reg >= N_CFI_REGS)
2958ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            return 0; /* fail */
2959ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         ctxs->cfa_is_regoff = True;
2960ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         ctxs->cfa_expr_ix   = 0;
2961ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         ctxs->cfa_reg       = reg;
2962ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         ctxs->cfa_off       = off;
2963ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (di->ddump_frames)
2964ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            VG_(printf)("  DW_CFA_def_cfa: r%d ofs %d\n", (Int)reg, (Int)off);
2965ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         break;
2966ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2967ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case DW_CFA_def_cfa_sf:
2968ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         reg = read_leb128( &instr[i], &nleb, 0 );
2969ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         i += nleb;
2970ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         off = read_leb128( &instr[i], &nleb, 1 );
2971ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         i += nleb;
2972ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (reg < 0 || reg >= N_CFI_REGS)
2973ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            return 0; /* fail */
2974ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         ctxs->cfa_is_regoff = True;
2975ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         ctxs->cfa_expr_ix   = 0;
2976ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         ctxs->cfa_reg       = reg;
2977ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         ctxs->cfa_off       = off * ctx->data_a_f;
2978ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (di->ddump_frames)
2979ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            VG_(printf)("  rci:DW_CFA_def_cfa_sf\n");
2980ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         break;
2981ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2982ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case DW_CFA_register:
2983ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         reg = read_leb128( &instr[i], &nleb, 0);
2984ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         i += nleb;
2985ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         reg2 = read_leb128( &instr[i], &nleb, 0);
2986ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         i += nleb;
2987ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (reg < 0 || reg >= N_CFI_REGS)
2988ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            return 0; /* fail */
2989ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (reg2 < 0 || reg2 >= N_CFI_REGS)
2990ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            return 0; /* fail */
2991ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         ctxs->reg[reg].tag = RR_Reg;
2992ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         ctxs->reg[reg].arg = reg2;
2993ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (di->ddump_frames)
2994ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            VG_(printf)("  DW_CFA_register: r%d in r%d\n",
2995ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        (Int)reg, (Int)reg2);
2996ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         break;
2997ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2998ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case DW_CFA_offset_extended:
2999ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         reg = read_leb128( &instr[i], &nleb, 0 );
3000ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         i += nleb;
3001ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         off = read_leb128( &instr[i], &nleb, 0 );
3002ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         i += nleb;
3003ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (reg < 0 || reg >= N_CFI_REGS)
3004ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            return 0; /* fail */
3005ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         ctxs->reg[reg].tag = RR_CFAOff;
3006ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         ctxs->reg[reg].arg = off * ctx->data_a_f;
3007ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (di->ddump_frames)
3008ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            VG_(printf)("  rci:DW_CFA_offset_extended\n");
3009ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         break;
3010ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3011ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case DW_CFA_offset_extended_sf:
3012ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         reg = read_leb128( &instr[i], &nleb, 0 );
3013ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         i += nleb;
3014ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         off = read_leb128( &instr[i], &nleb, 1 );
3015ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         i += nleb;
3016ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (reg < 0 || reg >= N_CFI_REGS)
3017ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            return 0; /* fail */
3018ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         ctxs->reg[reg].tag = RR_CFAOff;
3019ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         ctxs->reg[reg].arg = off * ctx->data_a_f;
3020ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (di->ddump_frames)
3021ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            VG_(printf)("  DW_CFA_offset_extended_sf: r%d at cfa%s%d\n",
3022ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        reg,
3023ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        ctxs->reg[reg].arg < 0 ? "" : "+",
3024ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        (Int)ctxs->reg[reg].arg);
3025ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         break;
3026ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3027ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case DW_CFA_GNU_negative_offset_extended:
3028ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         reg = read_leb128( &instr[i], &nleb, 0 );
3029ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         i += nleb;
3030ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         off = read_leb128( &instr[i], &nleb, 0 );
3031ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         i += nleb;
3032ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (reg < 0 || reg >= N_CFI_REGS)
3033ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            return 0; /* fail */
3034ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         ctxs->reg[reg].tag = RR_CFAOff;
3035ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         ctxs->reg[reg].arg = (-off) * ctx->data_a_f;
3036ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (di->ddump_frames)
3037ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            VG_(printf)("  rci:DW_CFA_GNU_negative_offset_extended\n");
3038ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         break;
3039ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3040ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case DW_CFA_restore_extended:
3041ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         reg = read_leb128( &instr[i], &nleb, 0 );
3042ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         i += nleb;
3043ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (reg < 0 || reg >= N_CFI_REGS)
3044ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            return 0; /* fail */
3045ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	 if (restore_ctx == NULL)
3046ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	    return 0; /* fail */
3047ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	 ctxs->reg[reg] = restore_ctx->state[restore_ctx->state_sp].reg[reg];
3048ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (di->ddump_frames)
3049ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            VG_(printf)("  rci:DW_CFA_restore_extended\n");
3050ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         break;
3051ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3052ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case DW_CFA_val_offset:
3053ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         reg = read_leb128( &instr[i], &nleb, 0 );
3054ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         i += nleb;
3055ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         off = read_leb128( &instr[i], &nleb, 0 );
3056ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         i += nleb;
3057ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (reg < 0 || reg >= N_CFI_REGS)
3058ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            return 0; /* fail */
3059ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         ctxs->reg[reg].tag = RR_CFAValOff;
3060ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         ctxs->reg[reg].arg = off * ctx->data_a_f;
3061ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (di->ddump_frames)
3062ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            VG_(printf)("  rci:DW_CFA_val_offset\n");
3063ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         break;
3064ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3065ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case DW_CFA_val_offset_sf:
3066ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         reg = read_leb128( &instr[i], &nleb, 0 );
3067ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         i += nleb;
3068ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         off = read_leb128( &instr[i], &nleb, 1 );
3069ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         i += nleb;
3070ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (reg < 0 || reg >= N_CFI_REGS)
3071ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            return 0; /* fail */
3072ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         ctxs->reg[reg].tag = RR_CFAValOff;
3073ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         ctxs->reg[reg].arg = off * ctx->data_a_f;
3074ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (di->ddump_frames)
3075ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            VG_(printf)("  rci:DW_CFA_val_offset_sf\n");
3076ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         break;
3077ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3078ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case DW_CFA_def_cfa_register:
3079ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         reg = read_leb128( &instr[i], &nleb, 0);
3080ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         i += nleb;
3081ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (reg < 0 || reg >= N_CFI_REGS)
3082ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            return 0; /* fail */
3083ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         ctxs->cfa_is_regoff = True;
3084ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         ctxs->cfa_expr_ix   = 0;
3085ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         ctxs->cfa_reg       = reg;
3086ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* ->cfa_off unchanged */
3087ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (di->ddump_frames)
3088ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            VG_(printf)("  DW_CFA_def_cfa_register: r%d\n", (Int)reg );
3089ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         break;
3090ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3091ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case DW_CFA_def_cfa_offset:
3092ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         off = read_leb128( &instr[i], &nleb, 0);
3093ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         i += nleb;
3094ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         ctxs->cfa_is_regoff = True;
3095ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         ctxs->cfa_expr_ix   = 0;
3096ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* ->reg is unchanged */
3097ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         ctxs->cfa_off       = off;
3098ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (di->ddump_frames)
3099ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            VG_(printf)("  DW_CFA_def_cfa_offset: %d\n", (Int)off);
3100ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         break;
3101ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3102ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case DW_CFA_def_cfa_offset_sf:
3103ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         off = read_leb128( &instr[i], &nleb, 1);
3104ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         i += nleb;
3105ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         ctxs->cfa_is_regoff = True;
3106ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         ctxs->cfa_expr_ix   = 0;
3107ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* ->reg is unchanged */
3108ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         ctxs->cfa_off       = off * ctx->data_a_f;
3109ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (di->ddump_frames)
3110ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            VG_(printf)("  DW_CFA_def_cfa_offset_sf: %d\n", ctxs->cfa_off);
3111ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         break;
3112ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3113ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case DW_CFA_undefined:
3114ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         reg = read_leb128( &instr[i], &nleb, 0);
3115ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         i += nleb;
3116ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (reg < 0 || reg >= N_CFI_REGS)
3117ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            return 0; /* fail */
3118ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         ctxs->reg[reg].tag = RR_Undef;
3119ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         ctxs->reg[reg].arg = 0;
3120ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (di->ddump_frames)
3121ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            VG_(printf)("  rci:DW_CFA_undefined\n");
3122ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         break;
3123ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3124ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case DW_CFA_same_value:
3125ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         reg = read_leb128( &instr[i], &nleb, 0);
3126ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         i += nleb;
3127ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (reg < 0 || reg >= N_CFI_REGS)
3128ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            return 0; /* fail */
3129ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         ctxs->reg[reg].tag = RR_Same;
3130ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         ctxs->reg[reg].arg = 0;
3131ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (di->ddump_frames)
3132ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            VG_(printf)("  rci:DW_CFA_same_value\n");
3133ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         break;
3134ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3135ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case DW_CFA_GNU_args_size:
3136ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* No idea what is supposed to happen.  gdb-6.3 simply
3137ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            ignores these. */
3138ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /*off = */ read_leb128( &instr[i], &nleb, 0 );
3139ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         i += nleb;
3140ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (di->ddump_frames)
3141ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            VG_(printf)("  rci:DW_CFA_GNU_args_size (ignored)\n");
3142ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         break;
3143ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3144ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case DW_CFA_expression:
3145ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* Identical to DW_CFA_val_expression except that the value
3146ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            computed is an address and so needs one final
3147ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            dereference. */
3148ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         reg = read_leb128( &instr[i], &nleb, 0 );
3149ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         i += nleb;
3150ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         len = read_leb128( &instr[i], &nleb, 0 );
3151ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         i += nleb;
3152ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         expr = &instr[i];
3153ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         i += len;
3154ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (reg < 0 || reg >= N_CFI_REGS)
3155ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            return 0; /* fail */
3156ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (di->ddump_frames)
3157ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            VG_(printf)("  DW_CFA_expression: r%d (",
3158ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        (Int)reg);
3159ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* Convert the expression into a dag rooted at ctx->exprs index j,
3160ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            or fail. */
3161ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         j = dwarfexpr_to_dag ( ctx, expr, len, True/*push CFA at start*/,
3162ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                di->ddump_frames);
3163ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (di->ddump_frames)
3164ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            VG_(printf)(")\n");
3165ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         vg_assert(j >= -1);
3166ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (j >= 0) {
3167ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            vg_assert(ctx->exprs);
3168ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            vg_assert( j < VG_(sizeXA)(ctx->exprs) );
3169ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
3170ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (j == -1)
3171ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            return 0; /* fail */
3172ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* Add an extra dereference */
3173ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         j = ML_(CfiExpr_Deref)( ctx->exprs, j );
3174ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         ctxs->reg[reg].tag = RR_ValExpr;
3175ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         ctxs->reg[reg].arg = j;
3176ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         break;
3177ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3178ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case DW_CFA_val_expression:
3179ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         reg = read_leb128( &instr[i], &nleb, 0 );
3180ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         i += nleb;
3181ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         len = read_leb128( &instr[i], &nleb, 0 );
3182ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         i += nleb;
3183ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         expr = &instr[i];
3184ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         i += len;
3185ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (reg < 0 || reg >= N_CFI_REGS)
3186ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            return 0; /* fail */
3187ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (di->ddump_frames)
3188ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            VG_(printf)("  DW_CFA_val_expression: r%d (",
3189ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        (Int)reg);
3190ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* Convert the expression into a dag rooted at ctx->exprs index j,
3191ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            or fail. */
3192ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         j = dwarfexpr_to_dag ( ctx, expr, len, True/*push CFA at start*/,
3193ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                di->ddump_frames);
3194ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (di->ddump_frames)
3195ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            VG_(printf)(")\n");
3196ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         vg_assert(j >= -1);
3197ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (j >= 0) {
3198ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            vg_assert(ctx->exprs);
3199ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            vg_assert( j < VG_(sizeXA)(ctx->exprs) );
3200ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
3201ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (j == -1)
3202ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            return 0; /* fail */
3203ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         ctxs->reg[reg].tag = RR_ValExpr;
3204ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         ctxs->reg[reg].arg = j;
3205ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         break;
3206ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3207ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case DW_CFA_def_cfa_expression:
3208ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         len = read_leb128( &instr[i], &nleb, 0 );
3209ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         i += nleb;
3210ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         expr = &instr[i];
3211ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         i += len;
3212ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (di->ddump_frames)
3213ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            VG_(printf)("  DW_CFA_def_cfa_expression (");
3214ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* Convert the expression into a dag rooted at ctx->exprs index j,
3215ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            or fail. */
3216ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         j = dwarfexpr_to_dag ( ctx, expr, len, True/*push CFA at start*/,
3217ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                di->ddump_frames);
3218ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (di->ddump_frames)
3219ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            VG_(printf)(")\n");
3220ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         ctxs->cfa_is_regoff = False;
3221ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         ctxs->cfa_reg       = 0;
3222ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         ctxs->cfa_off       = 0;
3223ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         ctxs->cfa_expr_ix   = j;
3224ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         break;
3225ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3226ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case DW_CFA_GNU_window_save:
3227ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* Ignored.  This appears to be sparc-specific; quite why it
3228ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            turns up in SuSE-supplied x86 .so's beats me. */
3229ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (di->ddump_frames)
3230ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            VG_(printf)("  DW_CFA_GNU_window_save\n");
3231ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         break;
3232ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3233ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case DW_CFA_remember_state:
3234ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (di->ddump_frames)
3235ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            VG_(printf)("  DW_CFA_remember_state\n");
3236ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* we just checked this at entry, so: */
3237ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         vg_assert(ctx->state_sp >= 0 && ctx->state_sp < N_RR_STACK);
3238ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         ctx->state_sp++;
3239ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (ctx->state_sp == N_RR_STACK) {
3240ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            /* stack overflow.  We're hosed. */
3241ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            VG_(message)(Vg_DebugMsg, "DWARF2 CFI reader: N_RR_STACK is "
3242ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                      "too low; increase and recompile.");
3243ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            i = 0; /* indicate failure */
3244ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         } else {
3245ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            VG_(memcpy)(/*dst*/&ctx->state[ctx->state_sp],
3246ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        /*src*/&ctx->state[ctx->state_sp - 1],
3247ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        sizeof(ctx->state[ctx->state_sp]) );
3248ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
3249ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         break;
3250ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3251ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case DW_CFA_restore_state:
3252ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (di->ddump_frames)
3253ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            VG_(printf)("  DW_CFA_restore_state\n");
3254ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* we just checked this at entry, so: */
3255ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         vg_assert(ctx->state_sp >= 0 && ctx->state_sp < N_RR_STACK);
3256ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (ctx->state_sp == 0) {
3257ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            /* stack overflow.  Give up. */
3258ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            i = 0; /* indicate failure */
3259ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         } else {
3260ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            /* simply fall back to previous entry */
3261ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            ctx->state_sp--;
3262ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
3263ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         break;
3264ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3265ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      default:
3266ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         VG_(message)(Vg_DebugMsg, "DWARF2 CFI reader: unhandled CFI "
3267ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                   "instruction 0:%d\n", (Int)lo6);
3268ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (di->ddump_frames)
3269ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            VG_(printf)("  rci:run_CF_instruction:default\n");
3270ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         i = 0;
3271ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         break;
3272ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
3273ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3274ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return i;
3275ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
3276ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3277ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3278ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Show a CFI instruction, and also return its length.  Show it as
3279ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   close as possible (preferably identical) to how GNU binutils
3280ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   readelf --debug-dump=frames would. */
3281ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3282ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic Int show_CF_instruction ( UChar* instr,
3283ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                 AddressDecodingInfo* adi,
3284ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                 Int code_a_f, Int data_a_f )
3285ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
3286ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   UInt  delta;
3287ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Int   off, coff, reg, reg2, nleb, len;
3288ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Addr  loc;
3289ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Int   i   = 0;
3290ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   UChar hi2 = (instr[i] >> 6) & 3;
3291ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   UChar lo6 = instr[i] & 0x3F;
3292ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   i++;
3293ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3294ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (0) VG_(printf)("raw:%x/%x:%x:%x:%x:%x:%x:%x:%x:%x\n",
3295ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                      hi2, lo6,
3296ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                      instr[i+0], instr[i+1], instr[i+2], instr[i+3],
3297ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                      instr[i+4], instr[i+5], instr[i+6], instr[i+7] );
3298ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3299ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (hi2 == DW_CFA_advance_loc) {
3300ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      VG_(printf)("  sci:DW_CFA_advance_loc(%d)\n", (Int)lo6);
3301ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return i;
3302ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
3303ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3304ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (hi2 == DW_CFA_offset) {
3305ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      off = read_leb128( &instr[i], &nleb, 0 );
3306ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      i += nleb;
3307ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      coff = off * data_a_f;
3308ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      VG_(printf)("  DW_CFA_offset: r%d at cfa%s%d\n",
3309ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  (Int)lo6, coff < 0 ? "" : "+", (Int)coff );
3310ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return i;
3311ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
3312ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3313ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (hi2 == DW_CFA_restore) {
3314ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      VG_(printf)("  sci:DW_CFA_restore(r%d)\n", (Int)lo6);
3315ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return i;
3316ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
3317ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3318ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vg_assert(hi2 == DW_CFA_use_secondary);
3319ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3320ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   switch (lo6) {
3321ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3322ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case DW_CFA_nop:
3323ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         VG_(printf)("  DW_CFA_nop\n");
3324ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         break;
3325ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3326ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case DW_CFA_set_loc:
3327ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* WAS: loc = read_Addr(&instr[i]); i+= sizeof(Addr);
3328ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            (now known to be incorrect -- the address is encoded) */
3329ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         loc = read_encoded_Addr(&len, adi, &instr[i]);
3330ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         i += len;
3331ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         VG_(printf)("  sci:DW_CFA_set_loc(%#lx)\n", loc);
3332ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         break;
3333ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3334ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case DW_CFA_advance_loc1:
3335b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         delta = (UInt)ML_(read_UChar)(&instr[i]); i+= sizeof(UChar);
3336ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         VG_(printf)("  sci:DW_CFA_advance_loc1(%d)\n", delta);
3337ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         break;
3338ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3339ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case DW_CFA_advance_loc2:
3340b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         delta = (UInt)ML_(read_UShort)(&instr[i]); i+= sizeof(UShort);
3341ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         VG_(printf)("  sci:DW_CFA_advance_loc2(%d)\n", delta);
3342ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         break;
3343ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3344ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case DW_CFA_advance_loc4:
3345b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         delta = (UInt)ML_(read_UInt)(&instr[i]); i+= sizeof(UInt);
3346ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         VG_(printf)("  DW_CFA_advance_loc4(%d)\n", delta);
3347ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         break;
3348ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3349ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case DW_CFA_def_cfa:
3350ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         reg = read_leb128( &instr[i], &nleb, 0 );
3351ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         i += nleb;
3352ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         off = read_leb128( &instr[i], &nleb, 0 );
3353ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         i += nleb;
3354ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         VG_(printf)("  DW_CFA_def_cfa: r%d ofs %d\n", (Int)reg, (Int)off);
3355ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         break;
3356ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3357ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case DW_CFA_def_cfa_sf:
3358ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         reg = read_leb128( &instr[i], &nleb, 0 );
3359ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         i += nleb;
3360ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         off = read_leb128( &instr[i], &nleb, 1 );
3361ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         i += nleb;
3362ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         VG_(printf)("  DW_CFA_def_cfa_sf: r%d ofs %d\n",
3363ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     (Int)reg, (Int)(off * data_a_f));
3364ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         break;
3365ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3366ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case DW_CFA_register:
3367ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         reg = read_leb128( &instr[i], &nleb, 0);
3368ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         i += nleb;
3369ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         reg2 = read_leb128( &instr[i], &nleb, 0);
3370ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         i += nleb;
3371ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         VG_(printf)("  sci:DW_CFA_register(r%d, r%d)\n", reg, reg2);
3372ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         break;
3373ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3374ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case DW_CFA_def_cfa_register:
3375ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         reg = read_leb128( &instr[i], &nleb, 0);
3376ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         i += nleb;
3377ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         VG_(printf)("  sci:DW_CFA_def_cfa_register(r%d)\n", reg);
3378ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         break;
3379ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3380ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case DW_CFA_def_cfa_offset:
3381ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         off = read_leb128( &instr[i], &nleb, 0);
3382ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         i += nleb;
3383ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         VG_(printf)("  sci:DW_CFA_def_cfa_offset(%d)\n", off);
3384ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         break;
3385ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3386ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case DW_CFA_def_cfa_offset_sf:
3387ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         off = read_leb128( &instr[i], &nleb, 1);
3388ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         i += nleb;
3389ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         VG_(printf)("  sci:DW_CFA_def_cfa_offset_sf(%d)\n", off);
3390ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         break;
3391ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3392ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case DW_CFA_restore_extended:
3393ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         reg = read_leb128( &instr[i], &nleb, 0);
3394ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         i += nleb;
3395ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         VG_(printf)("  sci:DW_CFA_restore_extended(r%d)\n", reg);
3396ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         break;
3397ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3398ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case DW_CFA_undefined:
3399ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         reg = read_leb128( &instr[i], &nleb, 0);
3400ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         i += nleb;
3401ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         VG_(printf)("  sci:DW_CFA_undefined(r%d)\n", reg);
3402ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         break;
3403ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3404ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case DW_CFA_same_value:
3405ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         reg = read_leb128( &instr[i], &nleb, 0);
3406ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         i += nleb;
3407ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         VG_(printf)("  sci:DW_CFA_same_value(r%d)\n", reg);
3408ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         break;
3409ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3410ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case DW_CFA_remember_state:
3411ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         VG_(printf)("  sci:DW_CFA_remember_state\n");
3412ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         break;
3413ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3414ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case DW_CFA_restore_state:
3415ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         VG_(printf)("  sci:DW_CFA_restore_state\n");
3416ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         break;
3417ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3418ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case DW_CFA_GNU_args_size:
3419ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         off = read_leb128( &instr[i], &nleb, 0 );
3420ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         i += nleb;
3421ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         VG_(printf)("  sci:DW_CFA_GNU_args_size(%d)\n", off );
3422ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         break;
3423ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3424ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case DW_CFA_def_cfa_expression:
3425ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         len = read_leb128( &instr[i], &nleb, 0 );
3426ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         i += nleb;
3427ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         i += len;
3428ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         VG_(printf)("  sci:DW_CFA_def_cfa_expression(length %d)\n", len);
3429ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         break;
3430ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3431ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case DW_CFA_expression:
3432ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         reg = read_leb128( &instr[i], &nleb, 0 );
3433ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         i += nleb;
3434ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         len = read_leb128( &instr[i], &nleb, 0 );
3435ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         i += nleb;
3436ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         i += len;
3437ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         VG_(printf)("  sci:DW_CFA_expression(r%d, length %d)\n", reg, len);
3438ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         break;
3439ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3440ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case DW_CFA_val_expression:
3441ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         reg = read_leb128( &instr[i], &nleb, 0 );
3442ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         i += nleb;
3443ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         len = read_leb128( &instr[i], &nleb, 0 );
3444ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         i += nleb;
3445ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         i += len;
3446ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         VG_(printf)("  sci:DW_CFA_val_expression(r%d, length %d)\n", reg, len);
3447ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         break;
3448ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3449ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case DW_CFA_offset_extended:
3450ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         reg = read_leb128( &instr[i], &nleb, 0 );
3451ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         i += nleb;
3452ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         off = read_leb128( &instr[i], &nleb, 0 );
3453ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         i += nleb;
3454ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         VG_(printf)("  sci:DW_CFA_offset_extended(r%d, "
3455ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     "off %d x data_af)\n", reg, off);
3456ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         break;
3457ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3458ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case DW_CFA_offset_extended_sf:
3459ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         reg = read_leb128( &instr[i], &nleb, 0 );
3460ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         i += nleb;
3461ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         off = read_leb128( &instr[i], &nleb, 1 );
3462ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         i += nleb;
3463ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	 coff = (Int)(off * data_a_f);
3464ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         VG_(printf)("  DW_CFA_offset_extended_sf: r%d at cfa%s%d\n",
3465ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        reg, coff < 0 ? "" : "+", coff);
3466ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         break;
3467ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3468ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case DW_CFA_GNU_negative_offset_extended:
3469ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         reg = read_leb128( &instr[i], &nleb, 0 );
3470ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         i += nleb;
3471ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         off = read_leb128( &instr[i], &nleb, 0 );
3472ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         i += nleb;
3473ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         VG_(printf)("  sci:DW_CFA_GNU_negative_offset_extended"
3474ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     "(r%d, off %d x data_af)\n", reg, -off);
3475ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         break;
3476ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3477ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case DW_CFA_val_offset:
3478ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         reg = read_leb128( &instr[i], &nleb, 0 );
3479ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         i += nleb;
3480ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         off = read_leb128( &instr[i], &nleb, 0 );
3481ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         i += nleb;
3482ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         VG_(printf)("  sci:DW_CFA_val_offset(r%d, off %d x data_af)\n",
3483ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     reg, off);
3484ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         break;
3485ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3486ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown       case DW_CFA_val_offset_sf:
3487ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         reg = read_leb128( &instr[i], &nleb, 0 );
3488ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         i += nleb;
3489ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         off = read_leb128( &instr[i], &nleb, 1 );
3490ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         i += nleb;
3491ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         VG_(printf)("  sci:DW_CFA_val_offset_sf(r%d, off %d x data_af)\n",
3492ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     reg, off);
3493ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         break;
3494ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3495ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case DW_CFA_GNU_window_save:
3496ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         VG_(printf)("  sci:DW_CFA_GNU_window_save\n");
3497ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         break;
3498ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3499ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      default:
3500ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         VG_(printf)("  sci:0:%d\n", (Int)lo6);
3501ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         break;
3502ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
3503ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3504ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return i;
3505ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
3506ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3507ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3508ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Show the instructions in instrs[0 .. ilen-1]. */
3509ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic void show_CF_instructions ( UChar* instrs, Int ilen,
3510ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                   AddressDecodingInfo* adi,
3511ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                   Int code_a_f, Int data_a_f )
3512ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
3513ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Int i = 0;
3514ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   while (True) {
3515ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (i >= ilen) break;
3516ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      i += show_CF_instruction( &instrs[i], adi, code_a_f, data_a_f );
3517ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
3518ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
3519ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3520ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3521ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Run the CF instructions in instrs[0 .. ilen-1], until the end is
3522ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   reached, or until there is a failure.  Return True iff success.
3523ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown*/
3524ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic
3525ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownBool run_CF_instructions ( struct _DebugInfo* di,
3526ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                           Bool record,
3527ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                           UnwindContext* ctx, UChar* instrs, Int ilen,
3528ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                           UWord fde_arange,
3529ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                           UnwindContext* restore_ctx,
3530ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                           AddressDecodingInfo* adi )
3531ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
3532ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   DiCfSI cfsi;
3533ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Bool summ_ok;
3534ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Int j, i = 0;
3535ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Addr loc_prev;
3536ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (0) ppUnwindContext(ctx);
3537ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (0) ppUnwindContext_summary(ctx);
3538ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   while (True) {
3539ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      loc_prev = ctx->loc;
3540ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (i >= ilen) break;
3541ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (0) (void)show_CF_instruction( &instrs[i], adi,
3542ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                        ctx->code_a_f, ctx->data_a_f );
3543ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      j = run_CF_instruction( ctx, &instrs[i], restore_ctx, adi, di );
3544ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (j == 0)
3545ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return False; /* execution failed */
3546ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      i += j;
3547ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (0) ppUnwindContext(ctx);
3548ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (record && loc_prev != ctx->loc) {
3549ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         summ_ok = summarise_context ( &cfsi, loc_prev, ctx, di );
3550ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (summ_ok) {
3551ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            ML_(addDiCfSI)(di, &cfsi);
3552ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            if (di->trace_cfi)
3553ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               ML_(ppDiCfSI)(di->cfsi_exprs, &cfsi);
3554ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
3555ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
3556ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
3557ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (ctx->loc < fde_arange) {
3558ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      loc_prev = ctx->loc;
3559ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      ctx->loc = fde_arange;
3560ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (record) {
3561ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         summ_ok = summarise_context ( &cfsi, loc_prev, ctx, di );
3562ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (summ_ok) {
3563ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            ML_(addDiCfSI)(di, &cfsi);
3564ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            if (di->trace_cfi)
3565ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               ML_(ppDiCfSI)(di->cfsi_exprs, &cfsi);
3566ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
3567ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
3568ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
3569ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return True;
3570ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
3571ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3572ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3573ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* ------------ Main entry point for CFI reading ------------ */
3574ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3575ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Browntypedef
3576ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   struct {
3577ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* This gives the CIE an identity to which FDEs will refer. */
3578ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      ULong  offset;
3579ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* Code, data factors. */
3580ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      Int    code_a_f;
3581ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      Int    data_a_f;
3582ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* Return-address pseudo-register. */
3583ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      Int    ra_reg;
3584ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      UChar  address_encoding;
3585ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* Where are the instrs?  Note, this are simply pointers back to
3586ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         the transiently-mapped-in section. */
3587ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      UChar* instrs;
3588ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      Int    ilen;
3589ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* God knows .. don't ask */
3590ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      Bool   saw_z_augmentation;
3591ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
3592ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   CIE;
3593ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3594ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic void init_CIE ( CIE* cie )
3595ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
3596ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   cie->offset             = 0;
3597ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   cie->code_a_f           = 0;
3598ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   cie->data_a_f           = 0;
3599ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   cie->ra_reg             = 0;
3600ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   cie->address_encoding   = 0;
3601ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   cie->instrs             = NULL;
3602ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   cie->ilen               = 0;
3603ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   cie->saw_z_augmentation = False;
3604ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
3605ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3606b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov#ifdef VGP_arm_linux_android
3607e65ebf8dbfc46f7bd75d00c0e822fb9e2b3ab5aaEvgeniy Stepanov#define N_CIEs 8000
3608b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov#else
3609b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov#define N_CIEs 4000
3610b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov#endif
3611ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic CIE the_CIEs[N_CIEs];
3612ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3613ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3614b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov/* Read, summarise and store CFA unwind info from .eh_frame and
3615b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   .debug_frame sections.  is_ehframe tells us which kind we are
3616b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   dealing with -- they are slightly different. */
3617ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid ML_(read_callframe_info_dwarf3)
3618b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov        ( /*OUT*/struct _DebugInfo* di,
3619b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov          UChar* frame_image, SizeT frame_size, Addr frame_avma,
3620b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov          Bool is_ehframe )
3621ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
3622ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Int    nbytes;
3623ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   HChar* how = NULL;
3624ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Int    n_CIEs = 0;
3625ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   UChar* data = frame_image;
3626b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   UWord  cfsi_used_orig;
3627b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
3628b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   /* If we're dealing with a .debug_frame, assume zero frame_avma. */
3629b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   if (!is_ehframe)
3630b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      vg_assert(frame_avma == 0);
3631ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3632ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#  if defined(VGP_ppc32_linux) || defined(VGP_ppc64_linux)
3633ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* These targets don't use CFI-based stack unwinding.  */
3634ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return;
3635ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#  endif
3636ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3637b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   /* If we read more than one .debug_frame or .eh_frame for this
3638b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      DebugInfo*, the second and subsequent reads should only add FDEs
3639b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      for address ranges not already covered by the FDEs already
3640b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      present.  To be able to quickly check which address ranges are
3641b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      already present, any existing records (DiCFSIs) must be sorted,
3642b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      so we can binary-search them in the code below.  We also record
3643b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      di->cfsi_used so that we know where the boundary is between
3644b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      existing and new records. */
3645b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   if (di->cfsi_used > 0) {
3646ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      ML_(canonicaliseCFI) ( di );
3647ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
3648b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   cfsi_used_orig = di->cfsi_used;
3649ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3650ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (di->trace_cfi) {
3651ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      VG_(printf)("\n-----------------------------------------------\n");
3652ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      VG_(printf)("CFI info: szB %ld, _avma %#lx, _image %p\n",
3653ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  frame_size, frame_avma, frame_image );
3654ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      VG_(printf)("CFI info: name %s\n",
3655b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                  di->fsm.filename );
3656ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
3657ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3658ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* Loop over CIEs/FDEs */
3659ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3660ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* Conceptually, the frame info is a sequence of FDEs, one for each
3661ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      function.  Inside an FDE is a miniature program for a special
3662ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      state machine, which, when run, produces the stack-unwinding
3663ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      info for that function.
3664ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3665ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      Because the FDEs typically have much in common, and because the
3666ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      DWARF designers appear to have been fanatical about space
3667ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      saving, the common parts are factored out into so-called CIEs.
3668ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      That means that what we traverse is a sequence of structs, each
3669ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      of which is either a FDE (usually) or a CIE (occasionally).
3670ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      Each FDE has a field indicating which CIE is the one pertaining
3671ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      to it.
3672ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3673ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      The following loop traverses the sequence.  FDEs are dealt with
3674ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      immediately; once we harvest the useful info in an FDE, it is
3675ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      then forgotten about.  By contrast, CIEs are validated and
3676ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      dumped into an array, because later FDEs may refer to any
3677ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      previously-seen CIE.
3678ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   */
3679ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   while (True) {
3680ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      UChar* ciefde_start;
3681ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      ULong  ciefde_len;
3682ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      ULong  cie_pointer;
3683ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      Bool   dw64;
3684ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3685ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* Are we done? */
3686ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (data == frame_image + frame_size)
3687ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return;
3688ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3689ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* Overshot the end?  Means something is wrong */
3690ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (data > frame_image + frame_size) {
3691ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         how = "overran the end of .eh_frame";
3692ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         goto bad;
3693ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
3694ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3695ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* Ok, we must be looking at the start of a new CIE or FDE.
3696ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         Figure out which it is. */
3697ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3698ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      ciefde_start = data;
3699ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (di->trace_cfi)
3700ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         VG_(printf)("\ncie/fde.start   = %p (frame_image + 0x%lx)\n",
3701ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     ciefde_start,
3702ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     ciefde_start - frame_image + 0UL);
3703ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3704b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      ciefde_len = (ULong)ML_(read_UInt)(data); data += sizeof(UInt);
3705ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (di->trace_cfi)
3706ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         VG_(printf)("cie/fde.length  = %lld\n", ciefde_len);
3707ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3708ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* Apparently, if the .length field is zero, we are at the end
3709ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         of the sequence.  This is stated in the Generic Elf
3710ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         Specification (see comments far above here) and is one of the
3711ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         places where .eh_frame and .debug_frame data differ. */
3712ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (ciefde_len == 0) {
3713ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (di->ddump_frames)
3714ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            VG_(printf)("%08lx ZERO terminator\n\n",
3715ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        ((Addr)ciefde_start) - ((Addr)frame_image));
3716ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return;
3717ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
3718ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3719ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* If the .length field is 0xFFFFFFFF then we're dealing with
3720ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         64-bit DWARF, and the real length is stored as a 64-bit
3721ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         number immediately following it. */
3722ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      dw64 = False;
3723ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (ciefde_len == 0xFFFFFFFFUL) {
3724ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         dw64 = True;
3725b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         ciefde_len = ML_(read_ULong)(data); data += sizeof(ULong);
3726ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
3727ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3728ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* Now get the CIE ID, whose size depends on the DWARF 32 vs
3729ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	 64-ness. */
3730ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (dw64) {
3731b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         cie_pointer = ML_(read_ULong)(data);
3732ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         data += sizeof(ULong); /* XXX see XXX below */
3733ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      } else {
3734b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         cie_pointer = (ULong)ML_(read_UInt)(data);
3735ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         data += sizeof(UInt); /* XXX see XXX below */
3736ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
3737ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3738ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (di->trace_cfi)
3739ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         VG_(printf)("cie.pointer     = %lld\n", cie_pointer);
3740ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3741ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* If cie_pointer is zero for .eh_frame or all ones for .debug_frame,
3742ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         we've got a CIE; else it's an FDE. */
3743b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      if (cie_pointer == (is_ehframe ? 0ULL
3744ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                          : dw64 ? 0xFFFFFFFFFFFFFFFFULL : 0xFFFFFFFFULL)) {
3745ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3746ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         Int    this_CIE;
3747ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         UChar  cie_version;
3748ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         UChar* cie_augmentation;
3749ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3750ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* --------- CIE --------- */
3751ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	 if (di->trace_cfi)
3752ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            VG_(printf)("------ new CIE (#%d of 0 .. %d) ------\n",
3753ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        n_CIEs, N_CIEs - 1);
3754ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3755ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	 /* Allocate a new CIE record. */
3756ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         vg_assert(n_CIEs >= 0 && n_CIEs <= N_CIEs);
3757ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (n_CIEs == N_CIEs) {
3758ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            how = "N_CIEs is too low.  Increase and recompile.";
3759ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            goto bad;
3760ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
3761ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3762ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         this_CIE = n_CIEs;
3763ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         n_CIEs++;
3764ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         init_CIE( &the_CIEs[this_CIE] );
3765ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3766ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	 /* Record its offset.  This is how we will find it again
3767ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            later when looking at an FDE. */
3768ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         the_CIEs[this_CIE].offset = (ULong)(ciefde_start - frame_image);
3769ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3770ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (di->ddump_frames)
3771ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            VG_(printf)("%08lx %08lx %08lx CIE\n",
3772ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        ((Addr)ciefde_start) - ((Addr)frame_image),
3773ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        (Addr)ciefde_len,
3774ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        (Addr)(UWord)cie_pointer );
3775ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3776b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         cie_version = ML_(read_UChar)(data); data += sizeof(UChar);
3777ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (di->trace_cfi)
3778ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            VG_(printf)("cie.version     = %d\n", (Int)cie_version);
3779ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (di->ddump_frames)
3780ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            VG_(printf)("  Version:               %d\n", (Int)cie_version);
3781ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (cie_version != 1 && cie_version != 3 && cie_version != 4) {
3782ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            how = "unexpected CIE version (not 1 nor 3 nor 4)";
3783ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            goto bad;
3784ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
3785ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3786ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         cie_augmentation = data;
3787ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         data += 1 + VG_(strlen)(cie_augmentation);
3788ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (di->trace_cfi)
3789ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            VG_(printf)("cie.augment     = \"%s\"\n", cie_augmentation);
3790ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (di->ddump_frames)
3791ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            VG_(printf)("  Augmentation:          \"%s\"\n", cie_augmentation);
3792ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3793ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (cie_augmentation[0] == 'e' && cie_augmentation[1] == 'h') {
3794ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            data += sizeof(Addr);
3795ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            cie_augmentation += 2;
3796ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
3797ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3798ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (cie_version >= 4) {
3799b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov            if (ML_(read_UChar)(data) != sizeof(Addr)) {
3800ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               how = "unexpected address size";
3801ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               goto bad;
3802ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            }
3803ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            data += sizeof(UChar);
3804b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov            if (ML_(read_UChar)(data) != 0) {
3805ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               how = "unexpected non-zero segment size";
3806ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               goto bad;
3807ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            }
3808ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            data += sizeof(UChar);
3809ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
3810ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3811ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         the_CIEs[this_CIE].code_a_f = read_leb128( data, &nbytes, 0);
3812ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         data += nbytes;
3813ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (di->trace_cfi)
3814ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            VG_(printf)("cie.code_af     = %d\n",
3815ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        the_CIEs[this_CIE].code_a_f);
3816ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (di->ddump_frames)
3817ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            VG_(printf)("  Code alignment factor: %d\n",
3818ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        (Int)the_CIEs[this_CIE].code_a_f);
3819ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3820ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         the_CIEs[this_CIE].data_a_f = read_leb128( data, &nbytes, 1);
3821ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         data += nbytes;
3822ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (di->trace_cfi)
3823ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            VG_(printf)("cie.data_af     = %d\n",
3824ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        the_CIEs[this_CIE].data_a_f);
3825ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (di->ddump_frames)
3826ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            VG_(printf)("  Data alignment factor: %d\n",
3827ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        (Int)the_CIEs[this_CIE].data_a_f);
3828ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3829ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (cie_version == 1) {
3830b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov            the_CIEs[this_CIE].ra_reg = (Int)ML_(read_UChar)(data);
3831ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            data += sizeof(UChar);
3832ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         } else {
3833ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            the_CIEs[this_CIE].ra_reg = read_leb128( data, &nbytes, 0);
3834ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            data += nbytes;
3835ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
3836ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (di->trace_cfi)
3837ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            VG_(printf)("cie.ra_reg      = %d\n",
3838ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        the_CIEs[this_CIE].ra_reg);
3839ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (di->ddump_frames)
3840ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            VG_(printf)("  Return address column: %d\n",
3841ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        (Int)the_CIEs[this_CIE].ra_reg);
3842ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3843ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (the_CIEs[this_CIE].ra_reg < 0
3844ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown             || the_CIEs[this_CIE].ra_reg >= N_CFI_REGS) {
3845ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            how = "cie.ra_reg has implausible value";
3846ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            goto bad;
3847ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
3848ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3849ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         the_CIEs[this_CIE].saw_z_augmentation
3850ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            = *cie_augmentation == 'z';
3851ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (the_CIEs[this_CIE].saw_z_augmentation) {
3852ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            UInt length = read_leb128( data, &nbytes, 0);
3853ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            data += nbytes;
3854ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            the_CIEs[this_CIE].instrs = data + length;
3855ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            cie_augmentation++;
3856ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            if (di->ddump_frames) {
3857ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               UInt i;
3858ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               VG_(printf)("  Augmentation data:    ");
3859ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               for (i = 0; i < length; i++)
3860ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  VG_(printf)(" %02x", (UInt)data[i]);
3861ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               VG_(printf)("\n");
3862ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            }
3863ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         } else {
3864ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            the_CIEs[this_CIE].instrs = NULL;
3865ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
3866ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3867ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         the_CIEs[this_CIE].address_encoding = default_Addr_encoding();
3868ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3869ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         while (*cie_augmentation) {
3870ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            switch (*cie_augmentation) {
3871ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               case 'L':
3872ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  data++;
3873ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  cie_augmentation++;
3874ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  break;
3875ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               case 'R':
3876ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  the_CIEs[this_CIE].address_encoding
3877b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                     = ML_(read_UChar)(data); data += sizeof(UChar);
3878ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  cie_augmentation++;
3879ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  break;
3880ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               case 'P':
3881b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                  data += size_of_encoded_Addr( ML_(read_UChar)(data) );
3882ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  data++;
3883ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  cie_augmentation++;
3884ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  break;
3885ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               case 'S':
3886ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  cie_augmentation++;
3887ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  break;
3888ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               default:
3889ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  if (the_CIEs[this_CIE].instrs == NULL) {
3890ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     how = "unhandled cie.augmentation";
3891ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     goto bad;
3892ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  }
3893ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  data = the_CIEs[this_CIE].instrs;
3894ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  goto done_augmentation;
3895ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            }
3896ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
3897ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3898ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        done_augmentation:
3899ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3900ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (di->trace_cfi)
3901ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            VG_(printf)("cie.encoding    = 0x%x\n",
3902ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        the_CIEs[this_CIE].address_encoding);
3903ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3904ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         the_CIEs[this_CIE].instrs = data;
3905ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         the_CIEs[this_CIE].ilen
3906ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            = ciefde_start + ciefde_len + sizeof(UInt) - data;
3907ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (di->trace_cfi) {
3908ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            VG_(printf)("cie.instrs      = %p\n", the_CIEs[this_CIE].instrs);
3909ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            VG_(printf)("cie.ilen        = %d\n", the_CIEs[this_CIE].ilen);
3910ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	 }
3911ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3912ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (the_CIEs[this_CIE].ilen < 0
3913ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown             || the_CIEs[this_CIE].ilen > frame_size) {
3914ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            how = "implausible # cie initial insns";
3915ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            goto bad;
3916ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
3917ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3918ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         data += the_CIEs[this_CIE].ilen;
3919ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3920ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* Show the CIE's instructions (the preamble for each FDE
3921ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            that uses this CIE). */
3922ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (di->ddump_frames)
3923ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            VG_(printf)("\n");
3924ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3925ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (di->trace_cfi || di->ddump_frames) {
3926ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            AddressDecodingInfo adi;
3927ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            adi.encoding      = the_CIEs[this_CIE].address_encoding;
3928ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            adi.ehframe_image = frame_image;
3929ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            adi.ehframe_avma  = frame_avma;
3930ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            adi.text_bias     = di->text_debug_bias;
3931ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            show_CF_instructions( the_CIEs[this_CIE].instrs,
3932ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                  the_CIEs[this_CIE].ilen, &adi,
3933ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                  the_CIEs[this_CIE].code_a_f,
3934ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                  the_CIEs[this_CIE].data_a_f );
3935ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
3936ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3937ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (di->ddump_frames)
3938ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            VG_(printf)("\n");
3939ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3940ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      } else {
3941ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3942ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         AddressDecodingInfo adi;
3943ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         UnwindContext ctx, restore_ctx;
3944ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         Int    cie;
3945ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         ULong  look_for;
3946ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         Bool   ok;
3947ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         Addr   fde_initloc;
3948ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         UWord  fde_arange;
3949ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         UChar* fde_instrs;
3950ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         Int    fde_ilen;
3951ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3952ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* --------- FDE --------- */
3953ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3954ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* Find the relevant CIE.  The CIE we want is located
3955ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            cie_pointer bytes back from here. */
3956ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3957ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* re sizeof(UInt) / sizeof(ULong), matches XXX above. */
3958b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         if (is_ehframe)
3959ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            look_for = (data - (dw64 ? sizeof(ULong) : sizeof(UInt))
3960ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                             - frame_image)
3961ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                       - cie_pointer;
3962ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         else
3963ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            look_for = cie_pointer;
3964ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3965ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         for (cie = 0; cie < n_CIEs; cie++) {
3966ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            if (0) VG_(printf)("look for %lld   %lld\n",
3967ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                               look_for, the_CIEs[cie].offset );
3968ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            if (the_CIEs[cie].offset == look_for)
3969ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               break;
3970ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	 }
3971ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         vg_assert(cie >= 0 && cie <= n_CIEs);
3972ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (cie == n_CIEs) {
3973ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            how = "FDE refers to not-findable CIE";
3974ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            goto bad;
3975ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	 }
3976ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3977ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         adi.encoding      = the_CIEs[cie].address_encoding;
3978ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         adi.ehframe_image = frame_image;
3979ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         adi.ehframe_avma  = frame_avma;
3980ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         adi.text_bias     = di->text_debug_bias;
3981ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         fde_initloc = read_encoded_Addr(&nbytes, &adi, data);
3982ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         data += nbytes;
3983ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (di->trace_cfi)
3984ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            VG_(printf)("fde.initloc     = %#lx\n", fde_initloc);
3985ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3986ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         adi.encoding      = the_CIEs[cie].address_encoding & 0xf;
3987ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         adi.ehframe_image = frame_image;
3988ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         adi.ehframe_avma  = frame_avma;
3989ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         adi.text_bias     = di->text_debug_bias;
3990ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3991ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* WAS (incorrectly):
3992ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            fde_arange = read_encoded_Addr(&nbytes, &adi, data);
3993ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            data += nbytes;
3994ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            The following corresponds to what binutils/dwarf.c does:
3995ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         */
3996ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         { UInt ptr_size = size_of_encoded_Addr( adi.encoding );
3997ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           switch (ptr_size) {
3998ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown              case 8: case 4: case 2: case 1:
3999ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                 fde_arange
4000ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    = (UWord)read_le_u_encoded_literal(data, ptr_size);
4001ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                 data += ptr_size;
4002ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                 break;
4003ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown              default:
4004ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                 how = "unknown arange field encoding in FDE";
4005ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                 goto bad;
4006ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           }
4007ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
4008ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4009ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (di->trace_cfi)
4010ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            VG_(printf)("fde.arangec     = %#lx\n", fde_arange);
4011ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4012ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (di->ddump_frames)
4013ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            VG_(printf)("%08lx %08lx %08lx FDE cie=%08lx pc=%08lx..%08lx\n",
4014ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        ((Addr)ciefde_start) - ((Addr)frame_image),
4015ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        (Addr)ciefde_len,
4016ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        (Addr)(UWord)cie_pointer,
4017ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        (Addr)look_for,
4018ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        ((Addr)fde_initloc) - di->text_debug_bias,
4019ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        ((Addr)fde_initloc) - di->text_debug_bias + fde_arange);
4020ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4021ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (the_CIEs[cie].saw_z_augmentation) {
4022ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            UInt length = read_leb128( data, &nbytes, 0);
4023ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            data += nbytes;
4024ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            if (di->ddump_frames && (length > 0)) {
4025ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               UInt i;
4026ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               VG_(printf)("  Augmentation data:    ");
4027ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               for (i = 0; i < length; i++)
4028ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  VG_(printf)(" %02x", (UInt)data[i]);
4029ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               VG_(printf)("\n\n");
4030ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            }
4031ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            data += length;
4032ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
4033ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4034ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         fde_instrs = data;
4035ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         fde_ilen   = ciefde_start + ciefde_len + sizeof(UInt) - data;
4036ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (di->trace_cfi) {
4037ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            VG_(printf)("fde.instrs      = %p\n", fde_instrs);
4038ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            VG_(printf)("fde.ilen        = %d\n", (Int)fde_ilen);
4039ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	 }
4040ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4041ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (fde_ilen < 0 || fde_ilen > frame_size) {
4042ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            how = "implausible # fde insns";
4043ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            goto bad;
4044ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
4045ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4046ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	 data += fde_ilen;
4047ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4048b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         /* If this object's DebugInfo* had some DiCFSIs from a
4049b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov            previous .eh_frame or .debug_frame read, we must check
4050b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov            that we're not adding a duplicate. */
4051b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         if (cfsi_used_orig > 0) {
4052ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            Addr a_mid_lo, a_mid_hi;
4053ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            Word mid, size,
4054ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                 lo = 0,
4055b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                 hi = cfsi_used_orig-1;
4056ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            while (True) {
4057ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               /* current unsearched space is from lo to hi, inclusive. */
4058ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               if (lo > hi) break; /* not found */
4059ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               mid      = (lo + hi) / 2;
4060ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               a_mid_lo = di->cfsi[mid].base;
4061ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               size     = di->cfsi[mid].len;
4062ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               a_mid_hi = a_mid_lo + size - 1;
4063ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               vg_assert(a_mid_hi >= a_mid_lo);
4064ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               if (fde_initloc + fde_arange <= a_mid_lo) {
4065ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  hi = mid-1; continue;
4066ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               }
4067ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               if (fde_initloc > a_mid_hi) { lo = mid+1; continue; }
4068ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               break;
4069ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            }
4070ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4071ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            /* The range this .debug_frame FDE covers has been already
4072ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               covered in .eh_frame section.  Don't add it from .debug_frame
4073ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               section again.  */
4074ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            if (lo <= hi)
4075ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               continue;
4076ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
4077ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4078ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         adi.encoding      = the_CIEs[cie].address_encoding;
4079ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         adi.ehframe_image = frame_image;
4080ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         adi.ehframe_avma  = frame_avma;
4081ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         adi.text_bias     = di->text_debug_bias;
4082ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4083ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (di->trace_cfi)
4084ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            show_CF_instructions( fde_instrs, fde_ilen, &adi,
4085ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                  the_CIEs[cie].code_a_f,
4086ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                  the_CIEs[cie].data_a_f );
4087ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4088ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	 initUnwindContext(&ctx);
4089ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         ctx.code_a_f = the_CIEs[cie].code_a_f;
4090ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         ctx.data_a_f = the_CIEs[cie].data_a_f;
4091ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         ctx.initloc  = fde_initloc;
4092ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         ctx.ra_reg   = the_CIEs[cie].ra_reg;
4093ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         ctx.exprs    = VG_(newXA)( ML_(dinfo_zalloc), "di.rcid.1",
4094ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                    ML_(dinfo_free),
4095ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                    sizeof(CfiExpr) );
4096ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         vg_assert(ctx.exprs);
4097ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4098ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	 /* Run the CIE's instructions.  Ugly hack: if
4099ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            --debug-dump=frames is in effect, suppress output for
4100ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            these instructions since they will already have been shown
4101ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            at the time the CIE was first encountered.  Note, not
4102ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            thread safe - if this reader is ever made threaded, should
4103ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            fix properly. */
4104ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	 { Bool hack = di->ddump_frames;
4105ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           di->ddump_frames = False;
4106ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           initUnwindContext(&restore_ctx);
4107ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           ok = run_CF_instructions(
4108ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                   di, False, &ctx, the_CIEs[cie].instrs,
4109ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                   the_CIEs[cie].ilen, 0, NULL, &adi
4110ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                );
4111ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           di->ddump_frames = hack;
4112ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
4113ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* And now run the instructions for the FDE, starting from
4114ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            the state created by running the CIE preamble
4115ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            instructions. */
4116ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (ok) {
4117ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            restore_ctx = ctx;
4118ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	    ok = run_CF_instructions(
4119ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    di, True, &ctx, fde_instrs, fde_ilen, fde_arange,
4120ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    &restore_ctx, &adi
4121ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                 );
4122ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            if (di->ddump_frames)
4123ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               VG_(printf)("\n");
4124ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	 }
4125ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4126ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         VG_(deleteXA)( ctx.exprs );
4127ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
4128ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
4129ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4130ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return;
4131ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4132ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   bad:
4133ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    if (!VG_(clo_xml) && VG_(clo_verbosity) > 1)
4134ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown       VG_(message)(Vg_UserMsg,
4135ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    "Warning: %s in DWARF2 CFI reading\n", how);
4136ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    return;
4137ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
4138ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4139ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#endif // defined(VGO_linux) || defined(VGO_darwin)
4140ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4141ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--------------------------------------------------------------------*/
4142ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--- end                                                          ---*/
4143ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--------------------------------------------------------------------*/
4144