1436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov/* -*- mode: C; c-basic-offset: 3; -*- */
2ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--------------------------------------------------------------------*/
4ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--- Read DWARF1/2/3/4 debug info.                    readdwarf.c ---*/
5ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--------------------------------------------------------------------*/
6ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
7ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*
8ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   This file is part of Valgrind, a dynamic binary instrumentation
9ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   framework.
10ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
11436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   Copyright (C) 2000-2013 Julian Seward
12ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      jseward@acm.org
13ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
14ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   This program is free software; you can redistribute it and/or
15ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   modify it under the terms of the GNU General Public License as
16ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   published by the Free Software Foundation; either version 2 of the
17ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   License, or (at your option) any later version.
18ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
19ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   This program is distributed in the hope that it will be useful, but
20ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   WITHOUT ANY WARRANTY; without even the implied warranty of
21ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
22ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   General Public License for more details.
23ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
24ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   You should have received a copy of the GNU General Public License
25ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   along with this program; if not, write to the Free Software
26ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
27ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   02111-1307, USA.
28ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
29ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   The GNU General Public License is contained in the file COPYING.
30ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown*/
31ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
32ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#if defined(VGO_linux) || defined(VGO_darwin)
33ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
34ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "pub_core_basics.h"
35ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "pub_core_debuginfo.h"
36ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "pub_core_libcbase.h"
37ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "pub_core_libcassert.h"
38ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "pub_core_libcprint.h"
39ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "pub_core_options.h"
40ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "pub_core_xarray.h"
41ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "pub_core_tooliface.h"    /* VG_(needs) */
42ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "priv_misc.h"             /* dinfo_zalloc/free/strdup */
43436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov#include "priv_image.h"
44ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "priv_d3basics.h"
45ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "priv_tytypes.h"
46ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "priv_storage.h"
47ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "priv_readdwarf.h"        /* self */
48ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
49ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
50ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*------------------------------------------------------------*/
51ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*---                                                      ---*/
52ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--- Read line number and CFI info from DWARF1, DWARF2    ---*/
53ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--- and to some extent DWARF3 sections.                  ---*/
54ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*---                                                      ---*/
55ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*------------------------------------------------------------*/
56ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
57ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*------------------------------------------------------------*/
58ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--- Expanding arrays of words, for holding file name and ---*/
59ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--- directory name arrays.                               ---*/
60ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*------------------------------------------------------------*/
61ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
62ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Browntypedef
63ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   struct {
64ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      Word* tab;
65ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      UInt  tab_size;
66ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      UInt  tab_used;
67ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
68ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   WordArray;
69ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
70ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic void init_WordArray ( WordArray* wa )
71ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
72ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   wa->tab      = NULL;
73ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   wa->tab_size = 0;
74ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   wa->tab_used = 0;
75ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
76ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
77ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic void free_WordArray ( WordArray* wa )
78ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
79ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (wa->tab) {
80ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      vg_assert(wa->tab_size > 0);
81ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      ML_(dinfo_free)(wa->tab);
82ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
83ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   init_WordArray(wa);
84ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
85ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
86ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic void addto_WordArray ( WordArray* wa, Word w )
87ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
88ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   UInt  new_size, i;
89ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Word* new_tab;
90ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
91ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (0) VG_(printf)("<<ADD %p (new sz = %d) >>\n",
92ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                      (HChar*)w, wa->tab_used+1);
93ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
94ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (wa->tab_used < wa->tab_size) {
95ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* fine */
96ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   } else {
97ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* expand array */
98ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (0) VG_(printf)("EXPAND ARRAY from %d\n", wa->tab_size);
99ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      vg_assert(wa->tab_used == wa->tab_size);
100ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      vg_assert( (wa->tab_size == 0 && wa->tab == NULL)
101ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                 || (wa->tab_size != 0 && wa->tab != NULL) );
102ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      new_size = wa->tab_size == 0 ? 8 : 2 * wa->tab_size;
103ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      new_tab  = ML_(dinfo_zalloc)("di.aWA.1", new_size * sizeof(Word));
104ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      vg_assert(new_tab != NULL);
105ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      for (i = 0; i < wa->tab_used; i++)
106ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         new_tab[i] = wa->tab[i];
107ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      wa->tab_size = new_size;
108ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (wa->tab)
109ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         ML_(dinfo_free)(wa->tab);
110ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      wa->tab = new_tab;
111ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
112ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
113ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vg_assert(wa->tab_used < wa->tab_size);
114ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vg_assert(wa->tab_size > 0);
115ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   wa->tab[wa->tab_used] = w;
116ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   wa->tab_used++;
117ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
118ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
119ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic Word index_WordArray ( /*OUT*/Bool* inRange, WordArray* wa, Int i )
120ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
121ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vg_assert(inRange);
122ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (i >= 0 && i < wa->tab_used) {
123ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      *inRange = True;
124ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return wa->tab[i];
125ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   } else {
126ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      *inRange = False;
127ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return 0;
128ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
129ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
130ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
131ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
132ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*------------------------------------------------------------*/
133ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--- Read DWARF2 format line number info.                 ---*/
134ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*------------------------------------------------------------*/
135ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
136ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Structure holding info extracted from the a .debug_line
137ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   section.  */
138ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Browntypedef struct
139ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
140ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  ULong  li_length;
141ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  UShort li_version;
142ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  ULong  li_header_length;
143ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  UChar  li_min_insn_length;
144ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  UChar  li_max_ops_per_insn;
145ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  UChar  li_default_is_stmt;
146ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  Int    li_line_base;
147ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  UChar  li_line_range;
148ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  UChar  li_opcode_base;
149ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
150ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownDebugLineInfo;
151ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
152ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Structure holding additional infos found from a .debug_info
153ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown * compilation unit block */
154ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Browntypedef struct
155ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
156ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  /* Feel free to add more members here if you need ! */
157436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov  DiCursor compdir;  /* Compilation directory - points to .debug_info */
158436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov  DiCursor name;     /* Main file name - points to .debug_info */
159436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov  ULong    stmt_list; /* Offset in .debug_line */
160436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov  Bool     dw64;      /* 64-bit Dwarf? */
161ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
162ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownUnitInfo;
163ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
164ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Line number opcodes.  */
165ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownenum dwarf_line_number_ops
166ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  {
167ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DW_LNS_extended_op = 0,
168ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DW_LNS_copy = 1,
169ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DW_LNS_advance_pc = 2,
170ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DW_LNS_advance_line = 3,
171ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DW_LNS_set_file = 4,
172ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DW_LNS_set_column = 5,
173ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DW_LNS_negate_stmt = 6,
174ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DW_LNS_set_basic_block = 7,
175ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DW_LNS_const_add_pc = 8,
176ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DW_LNS_fixed_advance_pc = 9,
177ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    /* DWARF 3.  */
178ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DW_LNS_set_prologue_end = 10,
179ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DW_LNS_set_epilogue_begin = 11,
180ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DW_LNS_set_isa = 12
181ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  };
182ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
183ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Line number extended opcodes.  */
184ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownenum dwarf_line_number_x_ops
185ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  {
186ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DW_LNE_end_sequence = 1,
187ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DW_LNE_set_address = 2,
188ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DW_LNE_define_file = 3,
189ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DW_LNE_set_discriminator = 4
190ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  };
191ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
192ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Browntypedef struct
193ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
194ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  /* Information for the last statement boundary.
195ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   * Needed to calculate statement lengths. */
196ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  Addr  last_address;
197ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  UInt  last_file;
198ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  UInt  last_line;
199ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
200ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  Addr  address;
201ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  UInt  file;
202ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  UInt  line;
203ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  UInt  column;
204ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  Int   is_stmt;
205ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  Int   basic_block;
206ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  UChar end_sequence;
207ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} LineSMR;
208ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
209ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
210ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* FIXME: duplicated in readdwarf3.c */
211436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov/* Read a 'leb128' and advance *data accordingly. */
212436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanovstatic ULong step_leb128 ( DiCursor* data, Int sign )
213ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
214436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   ULong  result = 0;
215436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   Int    shift = 0;
216436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   UChar  byte;
217ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
218436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   vg_assert(sign == 0 || sign == 1);
219ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
220436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   do {
221436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      byte = ML_(cur_step_UChar)(data);
222ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      result |= ((ULong)(byte & 0x7f)) << shift;
223ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      shift += 7;
224436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   }
225436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   while (byte & 0x80);
226ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
227436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   if (sign && (shift < 64) && (byte & 0x40))
228436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      result |= -(1ULL << shift);
229ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
230436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   return result;
231ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
232ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
233ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* FIXME: duplicated in readdwarf3.c */
234436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanovstatic ULong step_leb128U( DiCursor* data ) {
235436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   return step_leb128( data, 0 );
236ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
237ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
238ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* FIXME: duplicated in readdwarf3.c */
239436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanovstatic Long step_leb128S( DiCursor* data ) {
240436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   return step_leb128( data, 1 );
241ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
242ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
243ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Read what the DWARF3 spec calls an "initial length field".  This
244ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   uses up either 4 or 12 bytes of the input and produces a 32-bit or
245ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   64-bit number respectively.
246ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
247ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Read 32-bit value from p.  If it is 0xFFFFFFFF, instead read a
248ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   64-bit bit value from p+4.  This is used in 64-bit dwarf to encode
249436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   some table lengths.  Advance the cursor (p) accordingly.
250ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
251ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   XXX this is a hack: the endianness of the initial length field is
252ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   specified by the DWARF we're reading.  This happens to work only
253ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   because we don't do cross-arch jitting, hence this code runs on a
254ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   platform of the same endianness as the DWARF it is reading.  Same
255ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   applies for initial lengths for CIE/FDEs and probably in zillions
256ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   of other places -- to be precise, exactly the places where
257ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   binutils/dwarf.c calls byte_get().
258ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown*/
259436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanovstatic
260436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy IvanovULong step_initial_length_field ( DiCursor* p_img, /*OUT*/Bool* is64 )
261ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
262436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   UInt w32 = ML_(cur_step_UInt)(p_img);
263ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (w32 == 0xFFFFFFFF) {
264ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      *is64 = True;
265436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      return ML_(cur_step_ULong)(p_img);
266ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   } else {
267ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      *is64 = False;
268ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return (ULong)w32;
269ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
270ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
271ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
272436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanovstatic
273436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy IvanovULong read_initial_length_field ( DiCursor p_img, /*OUT*/Bool* is64 )
274436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov{
275436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   /* Something of a roundabout approach .. the modification to p_img
276436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      is abandoned. */
277436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   return step_initial_length_field( &p_img, is64 );
278436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov}
279436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov
280ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
281ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic LineSMR state_machine_regs;
282ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
283ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic
284ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid reset_state_machine ( Int is_stmt )
285ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
286ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (0) VG_(printf)("smr.a := %p (reset)\n", NULL );
287ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   state_machine_regs.last_address = 0;
288ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   state_machine_regs.last_file = 1;
289ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   state_machine_regs.last_line = 1;
290ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   state_machine_regs.address = 0;
291ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   state_machine_regs.file = 1;
292ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   state_machine_regs.line = 1;
293ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   state_machine_regs.column = 0;
294ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   state_machine_regs.is_stmt = is_stmt;
295ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   state_machine_regs.basic_block = 0;
296ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   state_machine_regs.end_sequence = 0;
297ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
298ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
299ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Look up a directory name, or return NULL if unknown. */
300ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic
301436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy IvanovHChar* lookupDir ( Int filename_index,
302436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov                   WordArray* fnidx2dir,
303436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov                   WordArray* dirnames )
304ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
305ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Bool inRange;
306ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Word diridx, dirname;
307ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
308ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   diridx = index_WordArray( &inRange, fnidx2dir, filename_index );
309ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (!inRange) goto bad;
310ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
311ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   dirname = index_WordArray( &inRange, dirnames, (Int)diridx );
312ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (!inRange) goto bad;
313ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
314436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   return (HChar*)dirname;
315ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  bad:
316ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return NULL;
317ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
318ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
319ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown////////////////////////////////////////////////////////////////////
320ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown////////////////////////////////////////////////////////////////////
321ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
322436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov/* Handled an extended line op starting at *data, and advance *data
323436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   accordingly. */
324ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic
325436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanovvoid process_extended_line_op( struct _DebugInfo* di,
326ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                               WordArray* filenames,
327ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                               WordArray* dirnames,
328ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                               WordArray* fnidx2dir,
329436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov                               DiCursor* data, Int is_stmt)
330ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
331436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   UInt len = step_leb128U(data);
332ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (len == 0) {
333ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      VG_(message)(Vg_UserMsg,
334ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                   "Warning: DWARF2 reader: "
335ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                   "Badly formed extended line op encountered\n");
336436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      return;
337ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
338ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
339436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   UChar op_code = ML_(cur_step_UChar)(data);
340ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (0) VG_(printf)("dwarf2: ext OPC: %d\n", op_code);
341ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
342ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   switch (op_code) {
343ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case DW_LNE_end_sequence:
344ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (0) VG_(printf)("1001: si->o %#lx, smr.a %#lx\n",
345ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                            di->text_debug_bias, state_machine_regs.address );
346ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* JRS: added for compliance with spec; is pointless due to
347ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            reset_state_machine below */
348ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         state_machine_regs.end_sequence = 1;
349ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
350ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (state_machine_regs.is_stmt) {
351ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            if (state_machine_regs.last_address) {
352ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               Bool inRange = False;
353436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov               const HChar* filename
354436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov                  = (HChar*)index_WordArray( &inRange, filenames,
355436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov                                             state_machine_regs.last_file);
356ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               if (!inRange || !filename)
357ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  filename = "???";
358ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               ML_(addLineInfo) (
359ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  di,
360ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  filename,
361ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  lookupDir( state_machine_regs.last_file,
362ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                             fnidx2dir, dirnames ),
363ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  di->text_debug_bias + state_machine_regs.last_address,
364ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  di->text_debug_bias + state_machine_regs.address,
365ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  state_machine_regs.last_line, 0
366ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               );
367ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            }
368ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
369ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         reset_state_machine (is_stmt);
370ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (di->ddump_line)
371ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            VG_(printf)("  Extended opcode %d: End of Sequence\n\n",
372ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        (Int)op_code);
373ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         break;
374ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
375436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      case DW_LNE_set_address: {
376436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         Addr adr = ML_(cur_step_Addr)(data);
377ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         state_machine_regs.address = adr;
378ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (di->ddump_line)
379ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            VG_(printf)("  Extended opcode %d: set Address to 0x%lx\n",
380ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        (Int)op_code, (Addr)adr);
381ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         break;
382436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      }
383ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
384436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      case DW_LNE_define_file: {
385436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         HChar* name = ML_(cur_step_strdup)(data, "di.pelo.1");
386ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addto_WordArray( filenames, (Word)ML_(addStr)(di,name,-1) );
387436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         ML_(dinfo_free)(name);
388436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         (void)step_leb128U(data); // ignored: dir index
389436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         (void)step_leb128U(data); // ignored: mod time
390436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         (void)step_leb128U(data); // ignored: file size
391ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (di->ddump_line)
392ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            VG_(printf)("  DWARF2-line: set_address\n");
393ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         break;
394436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      }
395ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
396ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case DW_LNE_set_discriminator:
397436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         (void)step_leb128U(data); // ignored: new 'discriminator' value
398ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         break;
399ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
400ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      default:
401ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (di->ddump_line)
402ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            VG_(printf)("process_extended_line_op:default\n");
403ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         break;
404ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
405ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
406ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
407ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown////////////////////////////////////////////////////////////////////
408ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown////////////////////////////////////////////////////////////////////
409ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
410ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* read a .debug_line section block for a compilation unit
411ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown *
412ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown * Input:   - theBlock must point to the start of the block
413ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown *            for the given compilation unit
414ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown *          - ui contains additional info like the compilation dir
415ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown *            for this unit
416ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown *
417ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown * Output: - si debug info structures get updated
418ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown */
419ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic
420ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid read_dwarf2_lineblock ( struct _DebugInfo* di,
421ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                             UnitInfo* ui,
422436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov                             DiCursor  theBlock, /* IMAGE */
423ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                             Int       noLargerThan )
424ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
425ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Int            i;
426ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   DebugLineInfo  info;
427ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Bool           is64;
428ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   WordArray      filenames;
429ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   WordArray      dirnames;
430ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   WordArray      fnidx2dir;
431ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
432436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   DiCursor       external = theBlock;
433436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   DiCursor       data = theBlock;
434ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
435ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* filenames is an array of file names harvested from the DWARF2
436ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      info.  Entry [0] is NULL and is never referred to by the state
437ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      machine.
438ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
439ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      Similarly, dirnames is an array of directory names.  Entry [0]
440ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      is also NULL and denotes "we don't know what the path is", since
441ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      that is different from "the path is the empty string".  Unlike
442ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      the file name table, the state machine does refer to entry [0],
443ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      which basically means "." ("the current directory of the
444ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      compilation", whatever that means, according to the DWARF3
445ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      spec.)
446ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
447ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      fnidx2dir is an array of indexes into the dirnames table.
448ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      (confused yet?)  filenames[] and fnidx2dir[] are indexed
449ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      together.  That is, for some index i in the filename table, then
450ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
451ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         the filename  is filenames[i]
452ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         the directory is dirnames[ fnidx2dir[i] ] */
453ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
454ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* Fails due to gcc padding ...
455ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vg_assert(sizeof(DWARF2_External_LineInfo)
456ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown             == sizeof(DWARF2_Internal_LineInfo));
457ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   */
458ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
459ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   init_WordArray(&filenames);
460ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   init_WordArray(&dirnames);
461ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   init_WordArray(&fnidx2dir);
462ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
463ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* DWARF2 starts numbering filename entries at 1, so we need to
464ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      add a dummy zeroth entry to the table.  The zeroth dirnames
465ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      entry denotes 'current directory of compilation' so we might
466ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      as well make the fnidx2dir zeroth entry denote that.
467ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   */
468ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   addto_WordArray( &filenames, (Word)NULL );
469ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
470436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   if (ML_(cur_is_valid)(ui->compdir))
471436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      addto_WordArray( &dirnames,
472436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov                       (Word)ML_(addStrFromCursor)(di, ui->compdir) );
473ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   else
474ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      addto_WordArray( &dirnames, (Word)ML_(addStr)(di, ".", -1) );
475ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
476ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   addto_WordArray( &fnidx2dir, (Word)0 );  /* compilation dir */
477ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
478436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   info.li_length = step_initial_length_field( &external, &is64 );
479ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (di->ddump_line)
480ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      VG_(printf)("  Length:                      %llu\n",
481ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  info.li_length);
482ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
483ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* Check the length of the block.  */
484ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (info.li_length > noLargerThan) {
485ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      ML_(symerr)(di, True,
486ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  "DWARF line info appears to be corrupt "
487ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  "- the section is too small");
488ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      goto out;
489ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
490ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
491ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* Check its version number.  */
492436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   info.li_version = ML_(cur_step_UShort)(&external);
493ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (di->ddump_line)
494ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      VG_(printf)("  DWARF Version:               %d\n",
495ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  (Int)info.li_version);
496ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
497ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (info.li_version != 2 && info.li_version != 3 && info.li_version != 4) {
498ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      ML_(symerr)(di, True,
499ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  "Only DWARF version 2, 3 and 4 line info "
500ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  "is currently supported.");
501ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      goto out;
502ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
503ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
504436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   info.li_header_length = is64 ? ML_(cur_step_ULong)(&external)
505436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov                                : (ULong)(ML_(cur_step_UInt)(&external));
506ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (di->ddump_line)
507ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      VG_(printf)("  Prologue Length:             %llu\n",
508ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  info.li_header_length);
509ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
510436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   info.li_min_insn_length = ML_(cur_step_UChar)(&external);
511ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (di->ddump_line)
512ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      VG_(printf)("  Minimum Instruction Length:  %d\n",
513ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  (Int)info.li_min_insn_length);
514ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
515ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* We only support machines with one opcode per instruction
516ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      for now. If we ever want to support VLIW machines there is
517ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      code to handle multiple opcodes per instruction in the
518ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      patch attached to BZ#233595.
519ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   */
520ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (info.li_version >= 4) {
521436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      info.li_max_ops_per_insn = ML_(cur_step_UChar)(&external);
522ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (info.li_max_ops_per_insn != 1) {
523ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         ML_(symerr)(di, True,
524ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     "Invalid Maximum Ops Per Insn in line info.");
525ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         goto out;
526ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
527ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (di->ddump_line)
528ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         VG_(printf)("  Maximum Ops Per Insn:        %d\n",
529ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  (Int)info.li_max_ops_per_insn);
530ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   } else {
531ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      info.li_max_ops_per_insn = 1;
532ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
533ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
534436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   info.li_default_is_stmt = ML_(cur_step_UChar)(&external);
535ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (di->ddump_line)
536ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      VG_(printf)("  Initial value of 'is_stmt':  %d\n",
537ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  (Int)info.li_default_is_stmt);
538ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
539ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* Josef Weidendorfer (20021021) writes:
540ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
541ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      It seems to me that the Intel Fortran compiler generates bad
542ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      DWARF2 line info code: It sets "is_stmt" of the state machine in
543ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      the the line info reader to be always false. Thus, there is
544ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      never a statement boundary generated and therefore never a
545ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      instruction range/line number mapping generated for valgrind.
546ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
547ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      Please have a look at the DWARF2 specification, Ch. 6.2
548ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      (x86.ddj.com/ftp/manuals/tools/dwarf.pdf).  Perhaps I understand
549ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      this wrong, but I don't think so.
550ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
551ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      I just had a look at the GDB DWARF2 reader...  They completely
552ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      ignore "is_stmt" when recording line info ;-) That's the reason
553ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      "objdump -S" works on files from the the intel fortran compiler.
554ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
555ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      Therefore: */
556ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   info.li_default_is_stmt = True;
557ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
558ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* JRS: changed (UInt*) to (UChar*) */
559436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   info.li_line_base = ML_(cur_step_UChar)(&external);
560436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   info.li_line_base = (Int)(Char)info.li_line_base;
561ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (di->ddump_line)
562ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      VG_(printf)("  Line Base:                   %d\n",
563ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  info.li_line_base);
564ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
565436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   info.li_line_range = ML_(cur_step_UChar)(&external);
566ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (di->ddump_line)
567ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      VG_(printf)("  Line Range:                  %d\n",
568ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  (Int)info.li_line_range);
569ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
570436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   info.li_opcode_base = ML_(cur_step_UChar)(&external);
571ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (di->ddump_line)
572ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      VG_(printf)("  Opcode Base:                 %d\n\n",
573ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  info.li_opcode_base);
574ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
575ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (0) VG_(printf)("dwarf2: line base: %d, range %d, opc base: %d\n",
576ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                      (Int)info.li_line_base,
577ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                      (Int)info.li_line_range,
578ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                      (Int)info.li_opcode_base);
579ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
580436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   DiCursor end_of_sequence
581436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov     = ML_(cur_plus)(data, info.li_length + (is64 ? 12 : 4));
582ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
583ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   reset_state_machine (info.li_default_is_stmt);
584ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
585ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* Read the contents of the Opcodes table.  */
586436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   DiCursor standard_opcodes = external;
587ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (di->ddump_line) {
588ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      VG_(printf)(" Opcodes:\n");
589ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      for (i = 1; i < (Int)info.li_opcode_base; i++) {
590ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         VG_(printf)("  Opcode %d has %d args\n",
591436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov                     i, (Int)ML_(cur_read_UChar)(
592436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov                                ML_(cur_plus)(standard_opcodes,
593436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov                                              (i-1) * sizeof(UChar)) ));
594ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
595ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      VG_(printf)("\n");
596ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
597ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
598ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* Read the contents of the Directory table.  */
599436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   data = ML_(cur_plus)(standard_opcodes, info.li_opcode_base - 1);
600ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
601ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (di->ddump_line)
602ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      VG_(printf)(" The Directory Table%s\n",
603436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov                  ML_(cur_read_UChar)(data) == 0 ? " is empty." : ":" );
604ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
605436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   while (ML_(cur_read_UChar)(data) != 0) {
606ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
607ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#     define NBUF 4096
608436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      static HChar buf[NBUF];
609ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
610436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      HChar* data_str = ML_(cur_read_strdup)(data, "di.rd2l.1");
611ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (di->ddump_line)
612436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         VG_(printf)("  %s\n", data_str);
613ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
614ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* If data[0] is '/', then 'data' is an absolute path and we
615ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         don't mess with it.  Otherwise, if we can, construct the
616436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         path 'ui->compdir' ++ "/" ++ 'data'. */
617ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
618436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      if (data_str[0] != '/'
619ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown          /* not an absolute path */
620436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov          && ML_(cur_is_valid)(ui->compdir)
621ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown          /* actually got something sensible for compdir */
622436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov          && ML_(cur_strlen)(ui->compdir)
623436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov             + VG_(strlen)(data_str) + 5/*paranoia*/ < NBUF
624ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown          /* it's short enough to concatenate */)
625ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      {
626ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         buf[0] = 0;
627436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         HChar* compdir_str = ML_(cur_read_strdup)(ui->compdir, "di.rd2l.1b");
628436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         VG_(strcat)(buf, compdir_str);
629ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         VG_(strcat)(buf, "/");
630436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         VG_(strcat)(buf, data_str);
631ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         vg_assert(VG_(strlen)(buf) < NBUF);
632ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addto_WordArray( &dirnames, (Word)ML_(addStr)(di,buf,-1) );
633ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (0) VG_(printf)("rel path  %s\n", buf);
634436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         ML_(dinfo_free)(compdir_str);
635ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      } else {
636ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* just use 'data'. */
637436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         addto_WordArray( &dirnames, (Word)ML_(addStr)(di,data_str,-1) );
638436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         if (0) VG_(printf)("abs path  %s\n", data_str);
639ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
640ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
641436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      data = ML_(cur_plus)(data, VG_(strlen)(data_str) + 1);
642436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      ML_(dinfo_free)(data_str);
643ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
644ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#     undef NBUF
645ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
646ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
647ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (di->ddump_line)
648ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      VG_(printf)("\n");
649ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
650436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   if (ML_(cur_read_UChar)(data) != 0) {
651ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      ML_(symerr)(di, True,
652ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  "can't find NUL at end of DWARF2 directory table");
653ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      goto out;
654ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
655436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   data = ML_(cur_plus)(data, 1);
656ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
657ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* Read the contents of the File Name table.  This produces a bunch
658ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      of file names, and for each, an index to the corresponding
659ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      directory name entry. */
660ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (di->ddump_line) {
661ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      VG_(printf)(" The File Name Table:\n");
662ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      VG_(printf)("  Entry	Dir	Time	Size	Name\n");
663ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
664ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
665ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   i = 1;
666436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   while (ML_(cur_read_UChar)(data) != 0) {
667436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      HChar* name    = ML_(cur_step_strdup)(&data, "di.rd2l.2");
668436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      Int    diridx  = step_leb128U(&data);
669436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      Int    uu_time = step_leb128U(&data); /* unused */
670436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      Int    uu_size = step_leb128U(&data); /* unused */
671ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      addto_WordArray( &filenames, (Word)ML_(addStr)(di,name,-1) );
672ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      addto_WordArray( &fnidx2dir, (Word)diridx );
673ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (0) VG_(printf)("file %s diridx %d\n", name, diridx );
674ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (di->ddump_line)
675ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         VG_(printf)("  %d\t%d\t%d\t%d\t%s\n",
676ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     i, diridx, uu_time, uu_size, name);
677ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      i++;
678436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      ML_(dinfo_free)(name);
679ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
680ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
681ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (di->ddump_line)
682ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      VG_(printf)("\n");
683ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
684436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   if (ML_(cur_read_UChar)(data) != 0) {
685ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      ML_(symerr)(di, True,
686ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  "can't find NUL at end of DWARF2 file name table");
687ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      goto out;
688ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
689436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   data = ML_(cur_plus)(data, 1);
690ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
691ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (di->ddump_line)
692ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      VG_(printf)(" Line Number Statements:\n");
693ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
694ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* Now display the statements.  */
695ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
696436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   while (ML_(cur_cmpLT)(data, end_of_sequence)) {
697436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      UChar op_code = ML_(cur_step_UChar)(&data);
698ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
699ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (0) VG_(printf)("dwarf2: OPC: %d\n", op_code);
700ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
701ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (op_code >= info.li_opcode_base) {
702ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         op_code -= info.li_opcode_base;
703436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         Word adv = (op_code / info.li_line_range)
704ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                       * info.li_min_insn_length;
705436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         Int advAddr = adv;
706ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         state_machine_regs.address += adv;
707ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
708436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         if (0) VG_(printf)("smr.a += %#lx\n", adv );
709ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         adv = (op_code % info.li_line_range) + info.li_line_base;
710ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (0) VG_(printf)("1002: di->o %#lx, smr.a %#lx\n",
711ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                            di->text_debug_bias, state_machine_regs.address );
712ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         state_machine_regs.line += adv;
713ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
714ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (di->ddump_line)
715ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            VG_(printf)("  Special opcode %d: advance Address by %d "
716ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        "to 0x%lx and Line by %d to %d\n",
717ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        (Int)op_code, advAddr, state_machine_regs.address,
718ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        (Int)adv, (Int)state_machine_regs.line );
719ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
720ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (state_machine_regs.is_stmt) {
721ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            /* only add a statement if there was a previous boundary */
722ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            if (state_machine_regs.last_address) {
723ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               Bool inRange = False;
724436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov               const HChar* filename
725436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov                  = (HChar*)index_WordArray( &inRange, &filenames,
726436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov                                             state_machine_regs.last_file);
727ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               if (!inRange || !filename)
728ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  filename = "???";
729ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               ML_(addLineInfo)(
730ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  di,
731ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  filename,
732ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  lookupDir( state_machine_regs.last_file,
733ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                             &fnidx2dir, &dirnames ),
734ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  di->text_debug_bias + state_machine_regs.last_address,
735ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  di->text_debug_bias + state_machine_regs.address,
736ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  state_machine_regs.last_line,
737ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  0
738ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               );
739ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            }
740ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            state_machine_regs.last_address = state_machine_regs.address;
741ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            state_machine_regs.last_file = state_machine_regs.file;
742ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            state_machine_regs.last_line = state_machine_regs.line;
743ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
744ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
745ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
746ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      else { /* ! (op_code >= info.li_opcode_base) */
747ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
748ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      switch (op_code) {
749ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case DW_LNS_extended_op:
750436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            process_extended_line_op (
751ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                       di, &filenames, &dirnames, &fnidx2dir,
752436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov                       &data, info.li_default_is_stmt);
753ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            break;
754ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
755ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case DW_LNS_copy:
756ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            if (0) VG_(printf)("1002: di->o %#lx, smr.a %#lx\n",
757ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                               di->text_debug_bias, state_machine_regs.address );
758ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            if (state_machine_regs.is_stmt) {
759ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               /* only add a statement if there was a previous boundary */
760ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               if (state_machine_regs.last_address) {
761ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  Bool inRange = False;
762436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov                  const HChar* filename
763436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov                     = (HChar*)index_WordArray( &inRange, &filenames,
764436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov                                                state_machine_regs.last_file );
765ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  if (!inRange || !filename)
766ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     filename = "???";
767ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  ML_(addLineInfo)(
768ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     di,
769ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     filename,
770ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     lookupDir( state_machine_regs.last_file,
771ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                &fnidx2dir, &dirnames ),
772ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     di->text_debug_bias + state_machine_regs.last_address,
773ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     di->text_debug_bias + state_machine_regs.address,
774ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     state_machine_regs.last_line,
775ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     0
776ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  );
777ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               }
778ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               state_machine_regs.last_address = state_machine_regs.address;
779ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               state_machine_regs.last_file = state_machine_regs.file;
780ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               state_machine_regs.last_line = state_machine_regs.line;
781ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            }
782ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            state_machine_regs.basic_block = 0; /* JRS added */
783ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            if (di->ddump_line)
784ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               VG_(printf)("  Copy\n");
785ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            break;
786ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
787436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         case DW_LNS_advance_pc: {
788436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            Word adv = info.li_min_insn_length * step_leb128U(&data);
789ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            state_machine_regs.address += adv;
790436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            if (0) VG_(printf)("smr.a += %#lx\n", adv );
791ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            if (di->ddump_line)
792436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov               VG_(printf)("  Advance PC by %ld to 0x%lx\n",
793436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov                           adv, state_machine_regs.address);
794ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            break;
795436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         }
796436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         case DW_LNS_advance_line: {
797436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            Word adv = step_leb128S(&data);
798ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            state_machine_regs.line += adv;
799ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            if (di->ddump_line)
800436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov               VG_(printf)("  Advance Line by %ld to %d\n",
801436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov                           adv, (Int)state_machine_regs.line);
802ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            break;
803436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         }
804436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         case DW_LNS_set_file: {
805436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            Word adv = step_leb128U(&data);
806ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            state_machine_regs.file = adv;
807ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            if (di->ddump_line)
808436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov               VG_(printf)("  Set File Name to entry %ld in the "
809436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov                           "File Name Table\n", adv);
810ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            break;
811436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         }
812436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         case DW_LNS_set_column: {
813436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            Word adv = step_leb128U(&data);
814ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            state_machine_regs.column = adv;
815ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            if (di->ddump_line)
816436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov               VG_(printf)("  Set column to %ld\n", adv);
817ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            break;
818436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         }
819436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         case DW_LNS_negate_stmt: {
820436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            Int adv = state_machine_regs.is_stmt;
821ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            adv = ! adv;
822ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            state_machine_regs.is_stmt = adv;
823ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            if (di->ddump_line)
824ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               VG_(printf)("  DWARF2-line: negate_stmt\n");
825ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            break;
826436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         }
827436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         case DW_LNS_set_basic_block: {
828ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            state_machine_regs.basic_block = 1;
829ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            if (di->ddump_line)
830ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               VG_(printf)("  DWARF2-line: set_basic_block\n");
831ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            break;
832436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         }
833436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         case DW_LNS_const_add_pc: {
834436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            Word adv = (((255 - info.li_opcode_base) / info.li_line_range)
835436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov                          * info.li_min_insn_length);
836ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            state_machine_regs.address += adv;
837436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            if (0) VG_(printf)("smr.a += %#lx\n", adv );
838ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            if (di->ddump_line)
839436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov               VG_(printf)("  Advance PC by constant %ld to 0x%lx\n",
840436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov                           adv, (Addr)state_machine_regs.address);
841ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            break;
842436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         }
843436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         case DW_LNS_fixed_advance_pc: {
844ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            /* XXX: Need something to get 2 bytes */
845436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            Word adv = ML_(cur_step_UShort)(&data);
846ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            state_machine_regs.address += adv;
847436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            if (0) VG_(printf)("smr.a += %#lx\n", adv );
848ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            if (di->ddump_line)
849ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               VG_(printf)("  DWARF2-line: fixed_advance_pc\n");
850ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            break;
851436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         }
852ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case DW_LNS_set_prologue_end:
853ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            if (di->ddump_line)
854ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               VG_(printf)("  DWARF2-line: set_prologue_end\n");
855ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            break;
856ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
857ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case DW_LNS_set_epilogue_begin:
858ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            if (di->ddump_line)
859ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               VG_(printf)("  DWARF2-line: set_epilogue_begin\n");
860ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            break;
861ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
862ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case DW_LNS_set_isa:
863436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            (void)step_leb128U(&data);
864ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            if (di->ddump_line)
865ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               VG_(printf)("  DWARF2-line: set_isa\n");
866ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            break;
867ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
868ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         default: {
869ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            Int j;
870436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            for (j = (Int)ML_(cur_read_UChar)(
871436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov                             ML_(cur_plus)(standard_opcodes,
872436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov                                           (op_code-1) * sizeof(UChar)));
873436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov                 j > 0 ; --j) {
874436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov               step_leb128U(&data);
875ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            }
876ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            if (di->ddump_line)
877ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               VG_(printf)("  Unknown opcode %d\n", (Int)op_code);
878ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            break;
879ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
880ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      } /* switch (op_code) */
881ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
882ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      } /* if (op_code >= info.li_opcode_base) */
883ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
884ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   } /* while (data < end_of_sequence) */
885ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
886ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (di->ddump_line)
887ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      VG_(printf)("\n");
888ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
889ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  out:
890ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   free_WordArray(&filenames);
891ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   free_WordArray(&dirnames);
892ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   free_WordArray(&fnidx2dir);
893ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
894ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
895ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown////////////////////////////////////////////////////////////////////
896ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown////////////////////////////////////////////////////////////////////
897ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
898ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Return abbrev for given code
899436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov * Returned cursor points to the tag
900ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown * */
901436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanovstatic DiCursor lookup_abbrev( DiCursor p, ULong acode )
902ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
903436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   while (1) {
904436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      ULong code = step_leb128U(&p);
905436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      if (code == acode)
906ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return p;
907436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      (void)step_leb128U(&p);  /* skip tag */
908436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      p = ML_(cur_plus)(p,1);  /* skip has_children flag */
909436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      ULong name;
910ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      do {
911436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         name = step_leb128U(&p); /* name */
912436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         (void)step_leb128U(&p);  /* form */
913ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
914436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      while (name != 0); /* until name == form == 0 */
915ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
916ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
917ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
918ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Read general information for a particular compile unit block in
919436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov * the .debug_info section. In particular read the name, compdir and
920436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov * stmt_list needed to parse the line number information.
921ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown *
922ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown * Input: - unitblock is the start of a compilation
923ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown *          unit block in .debuginfo section
924ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown *        - debugabbrev is start of .debug_abbrev section
925ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown *        - debugstr is start of .debug_str section
926436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov *        - debugstr_alt_img is start of .debug_str section in alt debug file
927ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown *
928ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown * Output: Fill members of ui pertaining to the compilation unit:
929ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown *         - ui->name is the name of the compilation unit
930ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown *         - ui->compdir is the compilation unit directory
931ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown *         - ui->stmt_list is the offset in .debug_line section
932ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown *                for the dbginfos of this compilation unit
933ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown *
934ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown * Note : the output strings are not allocated and point
935ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown * directly to the memory-mapped section.
936ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown */
937ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic
938ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid read_unitinfo_dwarf2( /*OUT*/UnitInfo* ui,
939436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov                                  DiCursor  unitblock_img,
940436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov                                  DiCursor  debugabbrev_img,
941436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov                                  DiCursor  debugstr_img,
942436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov                                  DiCursor  debugstr_alt_img )
943ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
944ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   UInt   acode, abcode;
945ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   ULong  atoffs, blklen;
946436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   UShort ver;
947ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
948436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   UChar    addr_size;
949436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   DiCursor p = unitblock_img;
950436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   DiCursor end_img;
951436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   DiCursor abbrev_img;
952ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
953ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   VG_(memset)( ui, 0, sizeof( UnitInfo ) );
954ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   ui->stmt_list = -1LL;
955ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
956ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* Read the compilation unit header in .debug_info section - See p 70 */
957ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
958ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* This block length */
959436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   blklen = step_initial_length_field( &p, &ui->dw64 );
960ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
961ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* version should be 2, 3 or 4 */
962436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   ver = ML_(cur_step_UShort)(&p);
963ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
964ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* get offset in abbrev */
965436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   atoffs = ui->dw64 ? ML_(cur_step_ULong)(&p)
966436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov                     : (ULong)(ML_(cur_step_UInt)(&p));
967ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
968ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* Address size */
969436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   addr_size = ML_(cur_step_UChar)(&p);
970436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov
971436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   /* End of this block */
972436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   end_img = ML_(cur_plus)(unitblock_img, blklen + (ui->dw64 ? 12 : 4));
973436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov
974436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   /* Abbreviation data for this block */
975436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   abbrev_img = ML_(cur_plus)(debugabbrev_img, atoffs);
976ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
977436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   /* Read the compilation unit entry - this is always the first DIE.
978436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov    * See DWARF4 para 7.5. */
979436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   if (ML_(cur_cmpLT)(p, end_img)) {
980ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      UInt tag;
981ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
982436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      acode = step_leb128U( &p ); /* abbreviation code */
983ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
984ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* Read abbreviation header */
985436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      abcode = step_leb128U( &abbrev_img ); /* abbreviation code */
986ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if ( acode != abcode ) {
987436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         /* This isn't illegal, but somewhat unlikely. Normally the
988436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov          * first abbrev describes the first DIE, the compile_unit.
989436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov          * But maybe this abbrevation data is shared with another
990436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov          * or it is a NULL entry used for padding. See para 7.5.3. */
991436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         abbrev_img = lookup_abbrev( ML_(cur_plus)(debugabbrev_img, atoffs),
992436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov                                     acode );
993ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
994ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
995436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      tag = step_leb128U( &abbrev_img );
996ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
997436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      if ( tag != 0x0011 /*TAG_compile_unit*/ )
998436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         return; /* Not a compile unit (might be partial) or broken DWARF. */
999436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov
1000436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      /* DW_CHILDREN_yes or DW_CHILDREN_no */
1001436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      abbrev_img = ML_(cur_plus)(abbrev_img, 1);
1002ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1003ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* And loop on entries */
1004ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      for ( ; ; ) {
1005ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* Read entry definition */
1006436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         ULong    cval = -1LL;  /* Constant value read */
1007436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         DiCursor sval = DiCursor_INVALID; /* String value read */
1008436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         UInt     name = step_leb128U( &abbrev_img );
1009436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         UInt     form = step_leb128U( &abbrev_img );
1010436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         if (name == 0)
1011ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            break;
1012ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1013ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* Read data */
1014ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* Attributes encoding explained p 71 */
1015ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if ( form == 0x16 /* FORM_indirect */ )
1016436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            form = step_leb128U( &p );
1017ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* Decode form. For most kinds, Just skip the amount of data since
1018ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            we don't use it for now */
1019ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* JRS 9 Feb 06: This now handles 64-bit DWARF too.  In
1020ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            64-bit DWARF, lineptr (and loclistptr,macptr,rangelistptr
1021ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            classes) use FORM_data8, not FORM_data4.  Also,
1022ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            FORM_ref_addr and FORM_strp are 64-bit values, not 32-bit
1023ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            values. */
1024ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* TJH 27 Apr 10: in DWARF 4 lineptr (and loclistptr,macptr,
1025ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            rangelistptr classes) use FORM_sec_offset which is 64 bits
1026ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            in 64 bit DWARF and 32 bits in 32 bit DWARF. */
1027b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         /* JRS 20 Apr 11: LLVM-2.9 encodes DW_AT_stmt_list using
1028b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov            FORM_addr rather than the FORM_data4 that GCC uses.  Hence
1029b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov            handle FORM_addr too. */
1030ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         switch( form ) {
1031ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            /* Those cases extract the data properly */
1032436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            case 0x05: /* FORM_data2 */
1033436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov               cval = ML_(cur_step_UShort)(&p);
1034436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov               break;
1035436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            case 0x06: /* FORM_data4 */
1036436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov               cval = ML_(cur_step_UInt)(&p);
1037436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov               break;
1038ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            case 0x0e: /* FORM_strp */      /* pointer in .debug_str */
1039436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov               /* 2006-01-01: only generate a value if a debug_str
1040436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov                  section was found) */
1041436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov               if (ML_(cur_is_valid)(debugstr_img) && !ui->dw64)
1042436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov                  sval = ML_(cur_plus)(debugstr_img, ML_(cur_read_UInt)(p));
1043436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov               if (ML_(cur_is_valid)(debugstr_img) && ui->dw64)
1044436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov                  sval = ML_(cur_plus)(debugstr_img, ML_(cur_read_ULong)(p));
1045436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov               p = ML_(cur_plus)(p, ui->dw64 ? 8 : 4);
1046436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov               break;
1047436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            case 0x08: /* FORM_string */
1048436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov               sval = p;
1049436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov               p = ML_(cur_plus)(p, ML_(cur_strlen)(p) + 1);
1050436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov               break;
1051436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            case 0x0b: /* FORM_data1 */
1052436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov               cval = ML_(cur_step_UChar)(&p);
1053436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov               break;
1054436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            case 0x17: /* FORM_sec_offset */
1055436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov               if (ui->dw64) {
1056436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov                 cval = ML_(cur_step_ULong)(&p);
1057436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov               } else {
1058436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov                 cval = ML_(cur_step_UInt)(&p);
1059436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov               };
1060436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov               break;
1061436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            case 0x07: /* FORM_data8 */
1062436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov               if (ui->dw64) cval = ML_(cur_read_ULong)(p);
1063436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov               p = ML_(cur_plus)(p, 8);
1064436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov               /* perhaps should assign unconditionally to cval? */
1065436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov               break;
1066ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            /* TODO : Following ones just skip data - implement if you need */
1067436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            case 0x01: /* FORM_addr */
1068436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov               p = ML_(cur_plus)(p, addr_size);
1069436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov               break;
1070436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            case 0x03: /* FORM_block2 */
1071436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov               p = ML_(cur_plus)(p, ML_(cur_read_UShort)(p) + 2);
1072436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov               break;
1073436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            case 0x04: /* FORM_block4 */
1074436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov               p = ML_(cur_plus)(p, ML_(cur_read_UInt)(p) + 4);
1075436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov               break;
1076436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            case 0x09:   /* FORM_block */     /* fallthrough */
1077436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            case 0x18: { /* FORM_exprloc */
1078436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov               ULong block_len = step_leb128U(&p);
1079436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov               p = ML_(cur_plus)(p, block_len);
1080436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov               break;
1081436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            }
1082436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            case 0x0a: /* FORM_block1 */
1083436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov               p = ML_(cur_plus)(p, ML_(cur_read_UChar)(p) + 1);
1084436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov               break;
1085436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            case 0x0c: /* FORM_flag */
1086436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov               p = ML_(cur_plus)(p, 1);
1087436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov               break;
1088436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            case 0x0d: /* FORM_sdata */
1089436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov               (void)step_leb128S(&p);
1090436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov               break;
1091436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            case 0x0f: /* FORM_udata */
1092436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov               (void)step_leb128U(&p);
1093436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov               break;
1094436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            case 0x10: /* FORM_ref_addr */
1095436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov               p = ML_(cur_plus)(p, (ver == 2) ? addr_size
1096436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov                                               : (ui->dw64 ? 8 : 4));
1097436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov               break;
1098436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            case 0x11: /* FORM_ref1 */
1099436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov               p = ML_(cur_plus)(p, 1);
1100436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov               break;
1101436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            case 0x12: /* FORM_ref2 */
1102436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov               p = ML_(cur_plus)(p, 2);
1103436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov               break;
1104436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            case 0x13: /* FORM_ref4 */
1105436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov               p = ML_(cur_plus)(p, 4);
1106436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov               break;
1107436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            case 0x14: /* FORM_ref8 */
1108436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov               p = ML_(cur_plus)(p, 8);
1109436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov               break;
1110436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            case 0x15: /* FORM_ref_udata */
1111436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov               (void)step_leb128U(&p);
1112436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov               break;
1113436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            case 0x19: /* FORM_flag_present */
1114436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov               break;
1115436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            case 0x20: /* FORM_ref_sig8 */
1116436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov               p = ML_(cur_plus)(p, 8);
1117436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov               break;
1118436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            case 0x1f20: /* FORM_GNU_ref_alt */
1119436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov               p = ML_(cur_plus)(p, ui->dw64 ? 8 : 4);
1120436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov               break;
1121663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            case 0x1f21: /* FORM_GNU_strp_alt */
1122436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov               if (ML_(cur_is_valid)(debugstr_alt_img) && !ui->dw64)
1123436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov                  sval = ML_(cur_plus)(debugstr_alt_img,
1124436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov                                       ML_(cur_read_UInt)(p));
1125436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov               if (ML_(cur_is_valid)(debugstr_alt_img) && ui->dw64)
1126436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov                  sval = ML_(cur_plus)(debugstr_alt_img,
1127436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov                                       ML_(cur_read_ULong)(p));
1128436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov               p = ML_(cur_plus)(p, ui->dw64 ? 8 : 4);
1129436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov               break;
1130ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1131ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            default:
1132436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov               VG_(printf)( "### unhandled dwarf2 abbrev form code 0x%x\n",
1133436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov                            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      }
1144436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   } /* Just read the first DIE, if that wasn't the compile_unit then
1145436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      * this might have been a partial unit or broken DWARF info.
1146436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      * That's enough info for us, and we are not gdb ! */
1147ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
1148ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1149ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1150ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown////////////////////////////////////////////////////////////////////
1151ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown////////////////////////////////////////////////////////////////////
1152ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1153ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Collect the debug info from DWARF3 debugging sections
1154ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown * of a given module.
1155ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown *
1156ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown * Inputs: given .debug_xxx sections
1157ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown * Output: update di to contain all the DWARF3 debug infos
1158ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown */
1159ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid ML_(read_debuginfo_dwarf3)
1160ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        ( struct _DebugInfo* di,
1161436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov          DiSlice escn_debug_info,      /* .debug_info */
1162436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov          DiSlice escn_debug_types,     /* .debug_types */
1163436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov          DiSlice escn_debug_abbv,      /* .debug_abbrev */
1164436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov          DiSlice escn_debug_line,      /* .debug_line */
1165436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov          DiSlice escn_debug_str,       /* .debug_str */
1166436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov          DiSlice escn_debug_str_alt )  /* .debug_str */
1167ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
1168ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   UnitInfo ui;
1169ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   UShort   ver;
1170ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   ULong    blklen;
1171ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Bool     blklen_is_64;
1172ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1173ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* Make sure we at least have a header for the first block */
1174436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   if (escn_debug_info.szB < 4) {
1175ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      ML_(symerr)( di, True,
1176ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                   "Last block truncated in .debug_info; ignoring" );
1177ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return;
1178ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
1179ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1180436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   DiCursor block_img = DiCursor_INVALID;
1181436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   DiCursor end1_img  = ML_(cur_plus)( ML_(cur_from_sli)(escn_debug_info),
1182436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov                                       escn_debug_info.szB );
1183436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   Int blklen_len = 0;
1184436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov
1185ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* Iterate on all the blocks we find in .debug_info */
1186436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   for ( block_img = ML_(cur_from_sli)(escn_debug_info);
1187436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         ML_(cur_cmpLT)(block_img, ML_(cur_plus)(end1_img, -(DiOffT)4));
1188436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         block_img = ML_(cur_plus)(block_img, blklen + blklen_len) ) {
1189ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1190ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* Read the compilation unit header in .debug_info section - See
1191ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         p 70 */
1192ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* This block length */
1193ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      blklen     = read_initial_length_field( block_img, &blklen_is_64 );
1194ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      blklen_len = blklen_is_64 ? 12 : 4;
1195436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov
1196436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      if (ML_(cur_cmpGT)( ML_(cur_plus)(block_img, blklen + blklen_len),
1197436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov                          end1_img )) {
1198ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         ML_(symerr)( di, True,
1199ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                      "Last block truncated in .debug_info; ignoring" );
1200ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return;
1201ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
1202ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1203ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* version should be 2 */
1204436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      ver = ML_(cur_read_UShort)( ML_(cur_plus)(block_img, blklen_len) );
1205ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if ( ver != 2 && ver != 3 && ver != 4 ) {
1206ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         ML_(symerr)( di, True,
1207ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                      "Ignoring non-Dwarf2/3/4 block in .debug_info" );
1208ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         continue;
1209ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
1210ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1211ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* Fill ui with offset in .debug_line and compdir */
1212ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (0)
1213436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         VG_(printf)(
1214436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            "Reading UnitInfo at 0x%llx.....\n",
1215436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            (ULong)ML_(cur_minus)( block_img,
1216436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov                                   ML_(cur_from_sli)(escn_debug_info)) );
1217ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      read_unitinfo_dwarf2( &ui, block_img,
1218436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov                                 ML_(cur_from_sli)(escn_debug_abbv),
1219436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov                                 ML_(cur_from_sli)(escn_debug_str),
1220436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov                                 ML_(cur_from_sli)(escn_debug_str_alt) );
1221436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      if (0) {
1222436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         HChar* str_name    = ML_(cur_read_strdup)(ui.name,    "di.rdd3.1");
1223436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         HChar* str_compdir = ML_(cur_read_strdup)(ui.compdir, "di.rdd3.2");
1224ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         VG_(printf)( "   => LINES=0x%llx    NAME=%s     DIR=%s\n",
1225436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov                      ui.stmt_list, str_name, str_compdir );
1226436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         ML_(dinfo_free)(str_name);
1227436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         ML_(dinfo_free)(str_compdir);
1228436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      }
1229436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov
1230ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* Ignore blocks with no .debug_line associated block */
1231ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if ( ui.stmt_list == -1LL )
1232ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         continue;
1233ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1234436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      if (0) {
1235436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         HChar* str_name = ML_(cur_read_strdup)(ui.name, "di.rdd3.3");
1236436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         VG_(printf)("debug_line_sz %lld, ui.stmt_list %lld  %s\n",
1237436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov                     escn_debug_line.szB, ui.stmt_list, str_name );
1238436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         ML_(dinfo_free)(str_name);
1239436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      }
1240436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov
1241ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* Read the .debug_line block for this compile unit */
1242436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      read_dwarf2_lineblock(
1243436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         di, &ui,
1244436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         ML_(cur_plus)(ML_(cur_from_sli)(escn_debug_line), ui.stmt_list),
1245436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         escn_debug_line.szB  - ui.stmt_list
1246436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      );
1247ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
1248ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
1249ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1250ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1251ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown////////////////////////////////////////////////////////////////////
1252ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown////////////////////////////////////////////////////////////////////
1253ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1254ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*------------------------------------------------------------*/
1255ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--- Read DWARF1 format line number info.                 ---*/
1256ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*------------------------------------------------------------*/
1257ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1258ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* DWARF1 appears to be redundant, but nevertheless the Lahey Fortran
1259ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   compiler generates it.
1260ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown*/
1261ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1262ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* The following three enums (dwarf_tag, dwarf_form, dwarf_attribute)
1263ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   are taken from the file include/elf/dwarf.h in the GNU gdb-6.0
1264ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   sources, which are Copyright 1992, 1993, 1995, 1999 Free Software
1265ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Foundation, Inc and naturally licensed under the GNU General Public
1266ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   License version 2 or later.
1267ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown*/
1268ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1269ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Tag names and codes.  */
1270ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1271ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownenum dwarf_tag {
1272ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    TAG_padding			= 0x0000,
1273ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    TAG_array_type		= 0x0001,
1274ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    TAG_class_type		= 0x0002,
1275ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    TAG_entry_point		= 0x0003,
1276ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    TAG_enumeration_type	= 0x0004,
1277ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    TAG_formal_parameter	= 0x0005,
1278ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    TAG_global_subroutine	= 0x0006,
1279ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    TAG_global_variable		= 0x0007,
1280ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    				/* 0x0008 -- reserved */
1281ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown				/* 0x0009 -- reserved */
1282ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    TAG_label			= 0x000a,
1283ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    TAG_lexical_block		= 0x000b,
1284ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    TAG_local_variable		= 0x000c,
1285ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    TAG_member			= 0x000d,
1286ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown				/* 0x000e -- reserved */
1287ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    TAG_pointer_type		= 0x000f,
1288ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    TAG_reference_type		= 0x0010,
1289ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    TAG_compile_unit		= 0x0011,
1290ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    TAG_string_type		= 0x0012,
1291ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    TAG_structure_type		= 0x0013,
1292ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    TAG_subroutine		= 0x0014,
1293ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    TAG_subroutine_type		= 0x0015,
1294ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    TAG_typedef			= 0x0016,
1295ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    TAG_union_type		= 0x0017,
1296ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    TAG_unspecified_parameters	= 0x0018,
1297ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    TAG_variant			= 0x0019,
1298ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    TAG_common_block		= 0x001a,
1299ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    TAG_common_inclusion	= 0x001b,
1300ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    TAG_inheritance		= 0x001c,
1301ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    TAG_inlined_subroutine	= 0x001d,
1302ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    TAG_module			= 0x001e,
1303ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    TAG_ptr_to_member_type	= 0x001f,
1304ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    TAG_set_type		= 0x0020,
1305ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    TAG_subrange_type		= 0x0021,
1306ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    TAG_with_stmt		= 0x0022,
1307ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1308ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    /* GNU extensions */
1309ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1310ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    TAG_format_label		= 0x8000,  /* for FORTRAN 77 and Fortran 90 */
1311ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    TAG_namelist		= 0x8001,  /* For Fortran 90 */
1312ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    TAG_function_template	= 0x8002,  /* for C++ */
1313ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    TAG_class_template		= 0x8003   /* for C++ */
1314ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown};
1315ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1316ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Form names and codes.  */
1317ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1318ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownenum dwarf_form {
1319ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    FORM_ADDR	= 0x1,
1320ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    FORM_REF	= 0x2,
1321ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    FORM_BLOCK2	= 0x3,
1322ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    FORM_BLOCK4	= 0x4,
1323ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    FORM_DATA2	= 0x5,
1324ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    FORM_DATA4	= 0x6,
1325ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    FORM_DATA8	= 0x7,
1326ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    FORM_STRING	= 0x8
1327ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown};
1328ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1329ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Attribute names and codes.  */
1330ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1331ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownenum dwarf_attribute {
1332ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    AT_sibling			= (0x0010|FORM_REF),
1333ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    AT_location			= (0x0020|FORM_BLOCK2),
1334ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    AT_name			= (0x0030|FORM_STRING),
1335ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    AT_fund_type		= (0x0050|FORM_DATA2),
1336ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    AT_mod_fund_type		= (0x0060|FORM_BLOCK2),
1337ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    AT_user_def_type		= (0x0070|FORM_REF),
1338ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    AT_mod_u_d_type		= (0x0080|FORM_BLOCK2),
1339ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    AT_ordering			= (0x0090|FORM_DATA2),
1340ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    AT_subscr_data		= (0x00a0|FORM_BLOCK2),
1341ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    AT_byte_size		= (0x00b0|FORM_DATA4),
1342ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    AT_bit_offset		= (0x00c0|FORM_DATA2),
1343ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    AT_bit_size			= (0x00d0|FORM_DATA4),
1344ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown				/* (0x00e0|FORM_xxxx) -- reserved */
1345ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    AT_element_list		= (0x00f0|FORM_BLOCK4),
1346ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    AT_stmt_list		= (0x0100|FORM_DATA4),
1347ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    AT_low_pc			= (0x0110|FORM_ADDR),
1348ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    AT_high_pc			= (0x0120|FORM_ADDR),
1349ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    AT_language			= (0x0130|FORM_DATA4),
1350ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    AT_member			= (0x0140|FORM_REF),
1351ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    AT_discr			= (0x0150|FORM_REF),
1352ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    AT_discr_value		= (0x0160|FORM_BLOCK2),
1353ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown				/* (0x0170|FORM_xxxx) -- reserved */
1354ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown				/* (0x0180|FORM_xxxx) -- reserved */
1355ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    AT_string_length		= (0x0190|FORM_BLOCK2),
1356ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    AT_common_reference		= (0x01a0|FORM_REF),
1357ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    AT_comp_dir			= (0x01b0|FORM_STRING),
1358ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        AT_const_value_string	= (0x01c0|FORM_STRING),
1359ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        AT_const_value_data2	= (0x01c0|FORM_DATA2),
1360ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        AT_const_value_data4	= (0x01c0|FORM_DATA4),
1361ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        AT_const_value_data8	= (0x01c0|FORM_DATA8),
1362ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        AT_const_value_block2	= (0x01c0|FORM_BLOCK2),
1363ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        AT_const_value_block4	= (0x01c0|FORM_BLOCK4),
1364ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    AT_containing_type		= (0x01d0|FORM_REF),
1365ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        AT_default_value_addr	= (0x01e0|FORM_ADDR),
1366ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        AT_default_value_data2	= (0x01e0|FORM_DATA2),
1367ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        AT_default_value_data4	= (0x01e0|FORM_DATA4),
1368ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        AT_default_value_data8	= (0x01e0|FORM_DATA8),
1369ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        AT_default_value_string	= (0x01e0|FORM_STRING),
1370ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    AT_friends			= (0x01f0|FORM_BLOCK2),
1371ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    AT_inline			= (0x0200|FORM_STRING),
1372ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    AT_is_optional		= (0x0210|FORM_STRING),
1373ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        AT_lower_bound_ref	= (0x0220|FORM_REF),
1374ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        AT_lower_bound_data2	= (0x0220|FORM_DATA2),
1375ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        AT_lower_bound_data4	= (0x0220|FORM_DATA4),
1376ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        AT_lower_bound_data8	= (0x0220|FORM_DATA8),
1377ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    AT_private			= (0x0240|FORM_STRING),
1378ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    AT_producer			= (0x0250|FORM_STRING),
1379ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    AT_program			= (0x0230|FORM_STRING),
1380ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    AT_protected		= (0x0260|FORM_STRING),
1381ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    AT_prototyped		= (0x0270|FORM_STRING),
1382ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    AT_public			= (0x0280|FORM_STRING),
1383ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    AT_pure_virtual		= (0x0290|FORM_STRING),
1384ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    AT_return_addr		= (0x02a0|FORM_BLOCK2),
1385ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    AT_abstract_origin		= (0x02b0|FORM_REF),
1386ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    AT_start_scope		= (0x02c0|FORM_DATA4),
1387ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    AT_stride_size		= (0x02e0|FORM_DATA4),
1388ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        AT_upper_bound_ref	= (0x02f0|FORM_REF),
1389ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        AT_upper_bound_data2	= (0x02f0|FORM_DATA2),
1390ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        AT_upper_bound_data4	= (0x02f0|FORM_DATA4),
1391ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        AT_upper_bound_data8	= (0x02f0|FORM_DATA8),
1392ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    AT_virtual			= (0x0300|FORM_STRING),
1393ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1394ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    /* GNU extensions.  */
1395ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1396ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    AT_sf_names			= (0x8000|FORM_DATA4),
1397ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    AT_src_info			= (0x8010|FORM_DATA4),
1398ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    AT_mac_info			= (0x8020|FORM_DATA4),
1399ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    AT_src_coords		= (0x8030|FORM_DATA4),
1400ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    AT_body_begin		= (0x8040|FORM_ADDR),
1401ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    AT_body_end			= (0x8050|FORM_ADDR)
1402ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown};
1403ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1404ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* end of enums taken from gdb-6.0 sources */
1405436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov#if 0
1406ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid ML_(read_debuginfo_dwarf1) (
1407ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        struct _DebugInfo* di,
1408ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        UChar* dwarf1d, Int dwarf1d_sz,
1409ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        UChar* dwarf1l, Int dwarf1l_sz )
1410ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
1411ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   UInt   stmt_list;
1412ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Bool   stmt_list_found;
1413ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Int    die_offset, die_szb, at_offset;
1414ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   UShort die_kind, at_kind;
1415ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   UChar* at_base;
1416436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   HChar* src_filename;
1417ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1418ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (0)
1419ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      VG_(printf)("read_debuginfo_dwarf1 ( %p, %d, %p, %d )\n",
1420ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	          dwarf1d, dwarf1d_sz, dwarf1l, dwarf1l_sz );
1421ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1422ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* This loop scans the DIEs. */
1423ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   die_offset = 0;
1424ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   while (True) {
1425ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (die_offset >= dwarf1d_sz) break;
1426ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1427b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      die_szb  = ML_(read_Int)(dwarf1d + die_offset);
1428b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      die_kind = ML_(read_UShort)(dwarf1d + die_offset + 4);
1429ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1430ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* We're only interested in compile_unit DIEs; ignore others. */
1431ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (die_kind != TAG_compile_unit) {
1432ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         die_offset += die_szb;
1433ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         continue;
1434ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
1435ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1436ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (0)
1437ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         VG_(printf)("compile-unit DIE: offset %d, tag 0x%x, size %d\n",
1438ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     die_offset, (Int)die_kind, die_szb );
1439ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1440ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* We've got a compile_unit DIE starting at (dwarf1d +
1441ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         die_offset+6).  Try and find the AT_name and AT_stmt_list
1442ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         attributes.  Then, finally, we can read the line number info
1443ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         for this source file. */
1444ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1445ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* The next 3 are set as we find the relevant attrs. */
1446ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      src_filename    = NULL;
1447ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      stmt_list_found = False;
1448ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      stmt_list       = 0;
1449ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1450ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* This loop scans the Attrs inside compile_unit DIEs. */
1451ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      at_base = dwarf1d + die_offset + 6;
1452ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      at_offset = 0;
1453ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      while (True) {
1454ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (at_offset >= die_szb-6) break;
1455ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1456b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         at_kind = ML_(read_UShort)(at_base + at_offset);
1457ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (0) VG_(printf)("atoffset %d, attag 0x%x\n",
1458ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                            at_offset, (Int)at_kind );
1459ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         at_offset += 2; /* step over the attribute itself */
1460ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	 /* We have to examine the attribute to figure out its
1461ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            length. */
1462ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         switch (at_kind) {
1463ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            case AT_stmt_list:
1464ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            case AT_language:
1465ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            case AT_sibling:
1466ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               if (at_kind == AT_stmt_list) {
1467ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  stmt_list_found = True;
1468b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                  stmt_list = ML_(read_Int)(at_base+at_offset);
1469ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               }
1470ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               at_offset += 4; break;
1471ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            case AT_high_pc:
1472ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            case AT_low_pc:
1473ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               at_offset += sizeof(void*); break;
1474ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            case AT_name:
1475ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            case AT_producer:
1476ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            case AT_comp_dir:
1477ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               /* Zero terminated string, step over it. */
1478ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               if (at_kind == AT_name)
1479436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov                 src_filename = (HChar *)(at_base + at_offset);
1480ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               while (at_offset < die_szb-6 && at_base[at_offset] != 0)
1481ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  at_offset++;
1482ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               at_offset++;
1483ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               break;
1484ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            default:
1485ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               VG_(printf)("Unhandled DWARF-1 attribute 0x%x\n",
1486ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                           (Int)at_kind );
1487ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               VG_(core_panic)("Unhandled DWARF-1 attribute");
1488ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         } /* switch (at_kind) */
1489ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      } /* looping over attributes */
1490ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1491ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* So, did we find the required stuff for a line number table in
1492ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         this DIE?  If yes, read it. */
1493ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (stmt_list_found /* there is a line number table */
1494ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown          && src_filename != NULL /* we know the source filename */
1495ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         ) {
1496ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* Table starts:
1497ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               Length:
1498ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  4 bytes, includes the entire table
1499ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               Base address:
1500ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  unclear (4? 8?), assuming native pointer size here.
1501ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            Then a sequence of triples
1502ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               (source line number -- 32 bits
1503ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                source line column -- 16 bits
1504ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                address delta -- 32 bits)
1505ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	 */
1506ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         Addr   base;
1507ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	 Int    len;
1508436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         HChar* curr_filenm;
1509ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         UChar* ptr;
1510ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         UInt   prev_line, prev_delta;
1511ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1512ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         curr_filenm = ML_(addStr) ( di, src_filename, -1 );
1513ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         prev_line = prev_delta = 0;
1514ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1515ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         ptr = dwarf1l + stmt_list;
1516b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         len  = ML_(read_Int)(ptr);  ptr += sizeof(Int);
1517b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         base = ML_(read_Addr)(ptr); ptr += sizeof(void*);
1518ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         len -= (sizeof(Int) + sizeof(void*));
1519ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         while (len > 0) {
1520ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            UInt   line;
1521ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            UShort col;
1522ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            UInt   delta;
1523b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov            line = ML_(read_UInt)(ptr);    ptr += sizeof(UInt);
1524b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov            col  = ML_(read_UShort)(ptr);  ptr += sizeof(UShort);
1525b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov            delta = ML_(read_UInt)(ptr);   ptr += sizeof(UInt);
1526ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	    if (0) VG_(printf)("line %d, col %d, delta %d\n",
1527ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                               line, (Int)col, delta );
1528ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            len -= (sizeof(UInt) + sizeof(UShort) + sizeof(UInt));
1529ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1530ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	    if (delta > 0 && prev_line > 0) {
1531ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	       if (0) VG_(printf) ("     %d  %d-%d\n",
1532ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                   prev_line, prev_delta, delta-1);
1533ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	       ML_(addLineInfo) ( di, curr_filenm, NULL,
1534ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown		 	          base + prev_delta, base + delta,
1535ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown			          prev_line, 0 );
1536ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	    }
1537ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	    prev_line = line;
1538ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	    prev_delta = delta;
1539ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	 }
1540ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
1541ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1542ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* Move on the the next DIE. */
1543ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      die_offset += die_szb;
1544ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1545ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   } /* Looping over DIEs */
1546ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1547ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
1548436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov#endif
1549ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1550ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*------------------------------------------------------------*/
1551ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--- Read call-frame info from an .eh_frame section       ---*/
1552ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*------------------------------------------------------------*/
1553ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1554ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Sources of info:
1555ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1556ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   The DWARF3 spec, available from http://www.dwarfstd.org/Download.php
1557ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1558ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   This describes how to read CFA data from .debug_frame sections.
1559ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   So as to maximise everybody's annoyance and confusion, .eh_frame
1560ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   sections are almost the same as .debug_frame sections, but differ
1561ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   in a few subtle and ill documented but important aspects.
1562ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1563ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Generic ELF Specification, sections 7.5 (DWARF Extensions) and 7.6
1564ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   (Exception Frames), available from
1565ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1566ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   http://www.linux-foundation.org/spec/book/ELF-generic/ELF-generic.html
1567ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1568ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   This really does describe .eh_frame, at least the aspects that
1569ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   differ from standard DWARF3.  It's better than guessing, and
1570ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   (marginally) more fun than reading the gdb source code.
1571ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown*/
1572ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1573ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Useful info ..
1574ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1575ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   In general:
1576ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   gdb-6.3/gdb/dwarf2-frame.c
1577ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1578ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   gdb-6.3/gdb/i386-tdep.c:
1579ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1580ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   DWARF2/GCC uses the stack address *before* the function call as a
1581ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   frame's CFA.  [jrs: I presume this means %esp before the call as
1582ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   the CFA].
1583ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1584ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   JRS: on amd64, the dwarf register numbering is, as per
1585ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   gdb-6.3/gdb/amd64-tdep.c and also amd64-abi-0.98.pdf:
1586ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1587ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      0    1    2    3    4    5    6    7
1588ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      RAX  RDX  RCX  RBX  RSI  RDI  RBP  RSP
1589ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1590ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      8  ...  15
1591ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      R8 ... R15
1592ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1593ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      16 is the return address (RIP)
1594ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      "The table defines Return Address to have a register number,
1595ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      even though the address is stored in 0(%rsp) and not in a
1596ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      physical register."
1597ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1598ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      17   ...   24
1599ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      XMM0 ... XMM7
1600ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1601ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      25   ...    32
1602ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      XMM8 ... XMM15
1603ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1604ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      33   ...   40
1605ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      ST0  ...  ST7
1606ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1607ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      41   ...   48
1608ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      MM0  ...  MM7
1609ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1610ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      49                  RFLAGS
1611ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      50,51,52,53,54,55   ES,CS,SS,DS,FS,GS
1612ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      58                  FS.BASE  (what's that?)
1613ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      59                  GS.BASE  (what's that?)
1614ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      62                  TR (task register)
1615ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      63                  LDTR (LDT register)
1616ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      64                  MXCSR
1617ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      65                  FCW (x87 control word)
1618ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      66                  FSW (x86 status word)
1619ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1620ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   On x86 I cannot find any documentation.  It _appears_ to be the
1621ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   actual instruction encoding, viz:
1622ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1623ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      0    1    2    3    4    5    6    7
1624ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      EAX  ECX  EDX  EBX  ESP  EBP  ESI  EDI
1625ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1626ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      8 is the return address (EIP) */
1627ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1628ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1629ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Comments re DW_CFA_set_loc, 16 Nov 06.
1630ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1631ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   JRS:
1632ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Someone recently sent me a libcrypto.so.0.9.8 as distributed with
1633ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Ubuntu of some flavour, compiled with gcc 4.1.2 on amd64.  It
1634ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   causes V's CF reader to complain a lot:
1635ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1636ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   >> --19976-- DWARF2 CFI reader: unhandled CFI instruction 0:24
1637ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   >> --19976-- DWARF2 CFI reader: unhandled CFI instruction 0:24
1638ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   >> --19976-- DWARF2 CFI reader: unhandled CFI instruction 0:24
1639ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   >> --19976-- DWARF2 CFI reader: unhandled CFI instruction 0:24
1640ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   >> --19976-- DWARF2 CFI reader: unhandled CFI instruction 0:48
1641ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   >> --19976-- DWARF2 CFI reader: unhandled CFI instruction 0:24
1642ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1643ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   After chasing this around a bit it seems that the CF bytecode
1644ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   parser lost sync at a DW_CFA_set_loc, which has a single argument
1645ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   denoting an address.
1646ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1647ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   As it stands that address is extracted by read_Addr().  On amd64
1648ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   that just fetches 8 bytes regardless of anything else.
1649ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1650ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   read_encoded_Addr() is more sophisticated.  This appears to take
1651ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   into account some kind of encoding flag.  When I replace the uses
1652ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   of read_Addr by read_encoded_Addr for DW_CFA_set_loc, the
1653ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   complaints go away, there is no loss of sync, and the parsed CF
1654ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   instructions are the same as shown by readelf --debug-dump=frames.
1655ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1656ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   So it seems a plausible fix.  The problem is I looked in the DWARF3
1657ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   spec and completely failed to figure out whether or not the arg to
1658ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   DW_CFA_set_loc is supposed to be encoded in a way suitable for
1659ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   read_encoded_Addr, nor for that matter any description of what it
1660ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   is that read_encoded_Addr is really decoding.
1661ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1662ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   TomH:
1663ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   The problem is that the encoding is not standard - the eh_frame
1664ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   section uses the same encoding as the dwarf_frame section except
1665ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   for a few small changes, and this is one of them. So this is not
1666ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   something the DWARF standard covers.
1667ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1668ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   There is an augmentation string to indicate what is going on though
1669ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   so that programs can recognise it.
1670ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1671ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   What we are doing seems to match what gdb 6.5 and libdwarf 20060614
1672ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   do though. I'm not sure about readelf though.
1673ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1674ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   (later): Well dwarfdump barfs on it:
1675ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1676ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      dwarfdump ERROR:  dwarf_get_fde_info_for_reg:
1677ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        DW_DLE_DF_FRAME_DECODING_ERROR(193) (193)
1678ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1679ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   I've looked at binutils as well now, and the code in readelf agrees
1680ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   with your patch - ie it treats set_loc as having an encoded address
1681ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if there is a zR augmentation indicating an encoding.
1682ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1683ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Quite why gdb and libdwarf don't understand this is an interesting
1684ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   question...
1685ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1686ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Final outcome: all uses of read_Addr were replaced by
1687ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   read_encoded_Addr.  A new type AddressDecodingInfo was added to
1688ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   make it relatively clean to plumb through the extra info needed by
1689ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   read_encoded_Addr.
1690ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown*/
1691ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1692ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* More badness re address encoding, 12 Jan 07.
1693ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1694ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Most gcc provided CIEs have a "zR" augmentation, which means they
1695ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   supply their own address encoding, and that works fine.  However,
1696ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   some icc9 supplied CIEs have no augmentation, which means they use
1697ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   the default_Addr_encoding().  That says to use a machine-word sized
1698ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   value, literally unmodified.
1699ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1700ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Since .so's are, in general, relocated when loaded, having absolute
1701ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   addresses in the CFI data makes no sense when read_encoded_Addr is
1702ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   used to find the initial location for a FDE.  The resulting saga:
1703ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1704ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   TomH:
1705ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   > I'm chasing a stack backtrace failure for an amd64 .so which was
1706ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   > created I believe by icc 9.1.  After a while I wound up looking at
1707ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   > this: (readdwarf.c)
1708ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   >
1709ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   >   5083        tom static UChar default_Addr_encoding ( void )
1710ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   >   3584        tom {
1711ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   >   3584        tom    switch (sizeof(Addr)) {
1712ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   >   3584        tom       case 4: return DW_EH_PE_udata4;
1713ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   >   3584        tom       case 8: return DW_EH_PE_udata8;
1714ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   >   3584        tom       default: vg_assert(0);
1715ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   >   3584        tom    }
1716ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   >   3584        tom }
1717ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   >
1718ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   > If a CIE does not have an "augmentation string" (typically "zR") then
1719ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   > addresses are decoded as described by default_Addr_encoding.  If there
1720ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   > is an 'R' in the augmentation string then the encoding to use
1721ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   > is specified by the CIE itself, which works fine with GCC compiled code
1722ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   > since that always appears to specify zR.
1723ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1724ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Correct.
1725ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1726ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   > Problem is this .so has no augmentation string and so uses the
1727ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   > default encoding, viz DW_EH_PE_udata8.  That appears to mean
1728ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   > "read a 64 bit number" and use that as-is (for the starting value
1729ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   > of the program counter when running the CFA program).
1730ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1731ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Strictly speaking the default is DW_EH_PE_absptr, but that amounts
1732ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   to either udata4 or udata8 depending on the platform's pointer size
1733ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   which is a shortcut I used.
1734ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1735ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   > For this .so that gives nonsense (very small) PCs which are later
1736ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   > rejected by the sanity check which ensures PC ranges fall inside
1737ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   > the mapped text segment.  It seems like the .so expects to have the
1738ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   > start VMA of the text segment added on.  This would correspond to
1739ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   >
1740ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   >   static UChar default_Addr_encoding ( void )
1741ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   >   {
1742ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   >      switch (sizeof(Addr)) {
1743ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   >         case 4: return DW_EH_PE_textrel + DW_EH_PE_udata4;
1744ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   >         case 8: return DW_EH_PE_textrel + DW_EH_PE_udata8;
1745ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   >         default: vg_assert(0);
1746ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   >      }
1747ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   >   }
1748ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1749ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   The problem you're seeing is that you have absolute pointers inside
1750ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   a shared library, which obviously makes little sense on the face of
1751ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   things as how would the linker know where the library will be
1752ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   loaded?
1753ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1754ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   The answer of course is that it doesn't, so if it points absolute
1755ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   pointers in the frame unwind data is has to include relocations for
1756ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   them, and I'm betting that if you look at the relocations in the
1757ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   library you will there are some for that data.
1758ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1759ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   That is fine of course when ld.so maps the library - it will
1760ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   relocate the eh_frame data as it maps it (or prelinking will
1761ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   already have done so) and when the g++ exception code kicks in and
1762ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   unwinds the stack it will see relocated data.
1763ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1764ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   We of course are mapping the section from the ELF file ourselves
1765ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   and are not applying the relocations, hence the problem you are
1766ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   seeing.
1767ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1768ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Strictly speaking we should apply the relocations but the cheap
1769ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   solution is essentially to do what you've done - strictly speaking
1770ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   you should adjust by the difference between the address the library
1771ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   was linked for and the address it has been loaded at, but a shared
1772ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   library will normally be linked for address zero I believe. It's
1773ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   possible that prelinking might change that though?
1774ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1775ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   JRS:
1776ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   That all syncs with what I am seeing.
1777ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1778ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   So what I am inclined to do is:
1779ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1780ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   - Leave default_Addr_encoding as it is
1781ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1782ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   - Change read_encoded_Addr's handling of "case DW_EH_PE_absptr" so
1783ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     it sets base to, as you say, the difference between the address
1784ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     the library was linked for and the address it has been loaded at
1785ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     (== the SegInfo's text_bias)
1786ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1787ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Does that sound sane?  I think it should even handle the prelinked
1788ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case.
1789ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1790ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   (JRS, later)
1791ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1792ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Hmm.  Plausible as it sounds, it doesn't work.  It now produces
1793ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   bogus backtraces for locations inside the (statically linked)
1794ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   memcheck executable.
1795ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1796ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Besides, there are a couple of other places where read_encoded_Addr
1797ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   is used -- one of which is used to establish the length of the
1798ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   address range covered by the current FDE:
1799ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1800ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         fde_arange = read_encoded_Addr(&nbytes, &adi, data);
1801ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1802ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   and it doesn't seem to make any sense for read_encoded_Addr to add
1803ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   on the text segment bias in that context.  The DWARF3 spec says
1804ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   that both the initial_location and address_range (length) fields
1805ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   are encoded the same way ("target address"), so it is unclear at
1806ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   what stage in the process it would be appropriate to relocate the
1807ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   former but not the latter.
1808ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1809ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   One unprincipled kludge that does work is the following: just
1810ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   before handing one of the address range fragments off to
1811ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   ML_(addDiCfSI) for permanent storage, check its start address.  If
1812ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   that is very low (less than 2 M), and is far below the mapped text
1813ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   segment, and adding the text bias would move the fragment entirely
1814ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   inside the mapped text segment, then do so.  A kind of kludged
1815ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   last-minute relocation, if you like.
1816ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1817ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   12 Jan 07: committing said kludge (see kludge_then_addDiCfSI).  If
1818ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   the situation clarifies, it can easily enough be backed out and
1819ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   replaced by a better fix.
1820ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown*/
1821ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1822ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* --------------- Decls --------------- */
1823ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1824ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#if defined(VGP_x86_linux)
1825ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#  define FP_REG         5
1826ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#  define SP_REG         4
1827ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#  define RA_REG_DEFAULT 8
1828ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#elif defined(VGP_amd64_linux)
1829ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#  define FP_REG         6
1830ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#  define SP_REG         7
1831ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#  define RA_REG_DEFAULT 16
1832ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#elif defined(VGP_ppc32_linux)
1833ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#  define FP_REG         1
1834ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#  define SP_REG         1
1835ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#  define RA_REG_DEFAULT 65
1836ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#elif defined(VGP_ppc64_linux)
1837ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#  define FP_REG         1
1838ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#  define SP_REG         1
1839ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#  define RA_REG_DEFAULT 65
1840ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#elif defined(VGP_arm_linux)
1841ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#  define FP_REG         12
1842ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#  define SP_REG         13
1843436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov#  define RA_REG_DEFAULT 14
1844436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov#elif defined(VGP_arm64_linux)
1845436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov#  define FP_REG         29
1846436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov#  define SP_REG         31
1847436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov#  define RA_REG_DEFAULT 30
1848ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#elif defined(VGP_x86_darwin)
1849ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#  define FP_REG         5
1850ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#  define SP_REG         4
1851ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#  define RA_REG_DEFAULT 8
1852ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#elif defined(VGP_amd64_darwin)
1853ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#  define FP_REG         6
1854ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#  define SP_REG         7
1855ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#  define RA_REG_DEFAULT 16
1856b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov#elif defined(VGP_s390x_linux)
1857b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov#  define FP_REG         11    // sometimes s390 has a frame pointer in r11
1858b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov#  define SP_REG         15    // stack is always r15
1859b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov#  define RA_REG_DEFAULT 14    // the return address is in r14
1860663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng#elif defined(VGP_mips32_linux)
1861663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng#  define FP_REG         30
1862663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng#  define SP_REG         29
1863663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng#  define RA_REG_DEFAULT 31
1864436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov#elif defined(VGP_mips64_linux)
1865436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov#  define FP_REG         30
1866436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov#  define SP_REG         29
1867436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov#  define RA_REG_DEFAULT 31
1868ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#else
1869ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#  error "Unknown platform"
1870ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#endif
1871ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1872663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng/* The number of regs we are prepared to unwind.  The number for
1873663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   arm-linux (320) seems ludicrously high, but the ARM IHI 0040A page
1874663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   7 (DWARF for the ARM Architecture) specifies that values up to 320
1875663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   might exist, for Neon/VFP-v3. */
1876663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng#if defined(VGP_ppc32_linux) || defined(VGP_ppc64_linux) \
1877436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov    || defined(VGP_mips32_linux) || defined(VGP_mips64_linux)
1878ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# define N_CFI_REGS 72
1879663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng#elif defined(VGP_arm_linux)
1880663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng# define N_CFI_REGS 320
1881436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov#elif defined(VGP_arm64_linux)
1882436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov# define N_CFI_REGS 128
1883ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#else
1884ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# define N_CFI_REGS 20
1885ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#endif
1886ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1887ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Instructions for the automaton */
1888ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownenum dwarf_cfa_primary_ops
1889ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  {
1890ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DW_CFA_use_secondary = 0,
1891ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DW_CFA_advance_loc   = 1,
1892ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DW_CFA_offset        = 2,
1893ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DW_CFA_restore       = 3
1894ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  };
1895ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1896ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownenum dwarf_cfa_secondary_ops
1897ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  {
1898ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DW_CFA_nop                = 0x00,
1899ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DW_CFA_set_loc            = 0x01,
1900ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DW_CFA_advance_loc1       = 0x02,
1901ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DW_CFA_advance_loc2       = 0x03,
1902ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DW_CFA_advance_loc4       = 0x04,
1903ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DW_CFA_offset_extended    = 0x05,
1904ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DW_CFA_restore_extended   = 0x06,
1905ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DW_CFA_undefined          = 0x07,
1906ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DW_CFA_same_value         = 0x08,
1907ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DW_CFA_register           = 0x09,
1908ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DW_CFA_remember_state     = 0x0a,
1909ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DW_CFA_restore_state      = 0x0b,
1910ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DW_CFA_def_cfa            = 0x0c,
1911ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DW_CFA_def_cfa_register   = 0x0d,
1912ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DW_CFA_def_cfa_offset     = 0x0e,
1913ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DW_CFA_def_cfa_expression = 0x0f, /* DWARF3 only */
1914ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DW_CFA_expression         = 0x10, /* DWARF3 only */
1915ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DW_CFA_offset_extended_sf = 0x11, /* DWARF3 only */
1916ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DW_CFA_def_cfa_sf         = 0x12, /* DWARF3 only */
1917ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DW_CFA_def_cfa_offset_sf  = 0x13, /* DWARF3 only */
1918ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DW_CFA_val_offset         = 0x14, /* DWARF3 only */
1919ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DW_CFA_val_offset_sf      = 0x15, /* DWARF3 only */
1920ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DW_CFA_val_expression     = 0x16, /* DWARF3 only */
1921ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DW_CFA_lo_user            = 0x1c,
1922ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DW_CFA_GNU_window_save    = 0x2d, /* GNU extension */
1923ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DW_CFA_GNU_args_size      = 0x2e, /* GNU extension */
1924ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DW_CFA_GNU_negative_offset_extended = 0x2f, /* GNU extension */
1925ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DW_CFA_hi_user            = 0x3f
1926ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  };
1927ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1928ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define DW_EH_PE_absptr		0x00
1929ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define DW_EH_PE_omit		0xff
1930ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1931ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define DW_EH_PE_uleb128	0x01
1932ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define DW_EH_PE_udata2		0x02
1933ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define DW_EH_PE_udata4		0x03
1934ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define DW_EH_PE_udata8		0x04
1935ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define DW_EH_PE_sleb128	0x09
1936ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define DW_EH_PE_sdata2		0x0A
1937ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define DW_EH_PE_sdata4		0x0B
1938ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define DW_EH_PE_sdata8		0x0C
1939ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define DW_EH_PE_signed		0x08
1940ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1941ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define DW_EH_PE_pcrel		0x10
1942ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define DW_EH_PE_textrel	0x20
1943ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define DW_EH_PE_datarel	0x30
1944ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define DW_EH_PE_funcrel	0x40
1945ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define DW_EH_PE_aligned	0x50
1946ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1947ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define DW_EH_PE_indirect	0x80
1948ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1949ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1950ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* RegRule and UnwindContext are used temporarily to do the unwinding.
1951ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   The result is then summarised into a sequence of CfiSIs, if
1952ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   possible.  UnwindContext effectively holds the state of the
1953ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   abstract machine whilst it is running.
1954ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1955ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   The CFA can either be a signed offset from a register,
1956ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   or an expression:
1957ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1958ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   CFA = cfa_reg + cfa_off   when UnwindContext.cfa_is_regoff==True
1959ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown       | [[ cfa_expr_id ]]
1960ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1961ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   When .cfa_is_regoff == True,  cfa_expr_id must be zero
1962ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   When .cfa_is_regoff == False, cfa_reg must be zero
1963ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                 and cfa_off must be zero
1964ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1965ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   RegRule describes, for each register, how to get its
1966ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   value in the previous frame, where 'cfa' denotes the cfa
1967ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   for the frame as a whole:
1968ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1969ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   RegRule = RR_Undef          -- undefined
1970ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           | RR_Same           -- same as in previous frame
1971ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           | RR_CFAOff    arg  -- is at * ( cfa + arg )
1972ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           | RR_CFAValOff arg  -- is ( cfa + arg )
1973ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           | RR_Reg       arg  -- is in register 'arg'
1974ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           | RR_Expr      arg  -- is at * [[ arg ]]
1975ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           | RR_ValExpr   arg  -- is [[ arg ]]
1976ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           | RR_Arch           -- dunno
1977ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1978ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Note that RR_Expr is redundant since the same can be represented
1979ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   using RR_ValExpr with an explicit dereference (CfiExpr_Deref) at
1980ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   the outermost level.
1981ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1982ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   All expressions are stored in exprs in the containing
1983ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   UnwindContext.  Since the UnwindContext gets reinitialised for each
1984ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   new FDE, summarise_context needs to copy out any expressions it
1985ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   wants to keep into the cfsi_exprs field of the containing SegInfo.
1986ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown*/
1987ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Browntypedef
1988ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   struct {
1989ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      enum { RR_Undef, RR_Same, RR_CFAOff, RR_CFAValOff,
1990ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown             RR_Reg, /*RR_Expr,*/ RR_ValExpr, RR_Arch } tag;
1991ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* meaning:  int offset for CFAoff/CFAValOff
1992ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                   reg # for Reg
1993ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                   expr index for Expr/ValExpr */
1994ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      Int arg;
1995ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
1996ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   RegRule;
1997ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1998ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic void ppRegRule ( XArray* exprs, RegRule* rrule )
1999ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
2000ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vg_assert(exprs);
2001ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   switch (rrule->tag) {
2002ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case RR_Undef:     VG_(printf)("u  "); break;
2003ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case RR_Same:      VG_(printf)("s  "); break;
2004ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case RR_CFAOff:    VG_(printf)("c%d ", rrule->arg); break;
2005ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case RR_CFAValOff: VG_(printf)("v%d ", rrule->arg); break;
2006ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case RR_Reg:       VG_(printf)("r%d ", rrule->arg); break;
2007ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case RR_ValExpr:   VG_(printf)("ve{");
2008ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                         ML_(ppCfiExpr)( exprs, rrule->arg );
2009ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                         VG_(printf)("} ");
2010ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                         break;
2011ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case RR_Arch:      VG_(printf)("a  "); break;
2012ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      default:           VG_(core_panic)("ppRegRule");
2013ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
2014ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
2015ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2016ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2017ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Size of the stack of register unwind rules.  This is only
2018ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   exceedingly rarely used, so a stack of size 1 should actually work
2019ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   with almost all compiler-generated CFA. */
2020ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define N_RR_STACK 4
2021ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2022ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Browntypedef
2023ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   struct {
2024ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* Read-only fields (set by the CIE) */
2025ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      Int     code_a_f;
2026ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      Int     data_a_f;
2027ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      Addr    initloc;
2028ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      Int     ra_reg;
2029ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* The rest of these fields can be modifed by
2030ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         run_CF_instruction. */
2031ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* The LOC entry */
2032ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      Addr    loc;
2033ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* We need a stack of these in order to handle
2034ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         DW_CFA_{remember,restore}_state. */
2035ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      struct UnwindContextState {
2036ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown          /* The CFA entry.  This can be either reg+/-offset or an expr. */
2037ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown          Bool    cfa_is_regoff; /* True=>is reg+offset; False=>is expr */
2038ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown          Int     cfa_reg;
2039ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown          Int     cfa_off;  /* in bytes */
2040ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown          Int     cfa_expr_ix; /* index into cfa_exprs */
2041ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown          /* Register unwind rules.  */
2042ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown          RegRule reg[N_CFI_REGS];
2043ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
2044ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      state[N_RR_STACK];
2045ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      Int     state_sp; /* 0 <= state_sp < N_RR_STACK; points at the
2046ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                           currently-in-use rule set. */
2047ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* array of CfiExpr, shared by reg[] and cfa_expr_ix */
2048ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      XArray* exprs;
2049ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
2050ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   UnwindContext;
2051ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2052ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic void ppUnwindContext ( UnwindContext* ctx )
2053ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
2054ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Int j, i;
2055ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   VG_(printf)("0x%llx: ", (ULong)ctx->loc);
2056ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   for (j = 0; j <= ctx->state_sp; j++) {
2057ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      struct UnwindContextState* ctxs = &ctx->state[j];
2058ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      VG_(printf)("%s[%d]={ ", j > 0 ? " " : "", j);
2059ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (ctxs->cfa_is_regoff) {
2060ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         VG_(printf)("%d(r%d) ", ctxs->cfa_off, ctxs->cfa_reg);
2061ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      } else {
2062ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         vg_assert(ctx->exprs);
2063ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         VG_(printf)("{");
2064ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         ML_(ppCfiExpr)( ctx->exprs, ctxs->cfa_expr_ix );
2065ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         VG_(printf)("} ");
2066ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
2067ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      VG_(printf)("{ ");
2068ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      for (i = 0; i < N_CFI_REGS; i++)
2069ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         ppRegRule(ctx->exprs, &ctxs->reg[i]);
2070ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      VG_(printf)("}");
2071ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
2072ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   VG_(printf)("\n");
2073ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
2074ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2075ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic void initUnwindContext ( /*OUT*/UnwindContext* ctx )
2076ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
2077ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Int j, i;
2078ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   VG_(memset)(ctx, 0, sizeof(*ctx));
2079ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* ctx->code_a_f   = 0;
2080ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   ctx->data_a_f      = 0;
2081ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   ctx->initloc       = 0; */
2082ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   ctx->ra_reg        = RA_REG_DEFAULT;
2083ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* ctx->loc        = 0;
2084ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   ctx->exprs         = NULL;
2085ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   ctx->state_sp        = 0; */
2086ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   for (j = 0; j < N_RR_STACK; j++) {
2087ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      ctx->state[j].cfa_is_regoff = True;
2088ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* ctx->state[j].cfa_reg    = 0;
2089ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      ctx->state[j].cfa_off       = 0;
2090ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      ctx->state[j].cfa_expr_ix   = 0; */
2091ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      for (i = 0; i < N_CFI_REGS; i++) {
2092ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (RR_Undef != 0)
2093ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           ctx->state[j].reg[i].tag = RR_Undef;
2094ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* ctx->state[j].reg[i].arg = 0; */
2095ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
2096ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#     if defined(VGA_arm)
2097ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* All callee-saved registers (or at least the ones we are
2098ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         summarising for) should start out as RR_Same, on ARM. */
2099ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      ctx->state[j].reg[11].tag = RR_Same;
2100ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* ctx->state[j].reg[13].tag = RR_Same; */
2101ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      ctx->state[j].reg[14].tag = RR_Same;
2102ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      ctx->state[j].reg[12].tag = RR_Same;
2103ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      ctx->state[j].reg[7].tag  = RR_Same;
2104ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* this can't be right though: R12 (IP) isn't callee saved. */
2105436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov#     elif defined(VGA_arm64)
2106436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      /* Callee-saved registers (that we are interested in) should
2107436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         start out as RR_Same. */
2108436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      ctx->state[j].reg[29/*FP*/].tag = RR_Same;
2109436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      ctx->state[j].reg[30/*LR*/].tag = RR_Same;
2110ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#     endif
2111ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
2112ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
2113ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2114ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2115ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* A structure which holds information needed by read_encoded_Addr().
2116ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown*/
2117ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Browntypedef
2118ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   struct {
2119436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      UChar    encoding;
2120436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      DiCursor ehframe_image;
2121436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      Addr     ehframe_avma;
2122436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      Addr     text_bias;
2123ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
2124ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   AddressDecodingInfo;
2125ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2126ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2127ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* ------------ Deal with summary-info records ------------ */
2128ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2129ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic void initCfiSI ( DiCfSI* si )
2130ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
2131436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   VG_(bzero_inline)(si, sizeof(*si));
2132ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
2133ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2134ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2135ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* --------------- Summarisation --------------- */
2136ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2137ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Forward */
2138ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic
2139ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownInt copy_convert_CfiExpr_tree ( XArray*        dst,
2140ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                UnwindContext* srcuc,
2141ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                Int            nd );
2142ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2143ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Summarise ctx into si, if possible.  Returns True if successful.
2144ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   This is taken to be just after ctx's loc advances; hence the
2145ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   summary is up to but not including the current loc.  This works
2146ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   on both x86 and amd64.
2147ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown*/
2148ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic Bool summarise_context( /*OUT*/DiCfSI* si,
2149ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                               Addr loc_start,
2150ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	                       UnwindContext* ctx,
2151ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                               struct _DebugInfo* debuginfo )
2152ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
2153ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Int why = 0;
2154ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   struct UnwindContextState* ctxs;
2155ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   initCfiSI(si);
2156ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2157ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* Guard against obviously stupid settings of the reg-rule stack
2158ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      pointer. */
2159ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (ctx->state_sp < 0)           { why = 8; goto failed; }
2160ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (ctx->state_sp >= N_RR_STACK) { why = 9; goto failed; }
2161ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   ctxs = &ctx->state[ctx->state_sp];
2162ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2163ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* First, summarise the method for generating the CFA */
2164ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (!ctxs->cfa_is_regoff) {
2165ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* it was set by DW_CFA_def_cfa_expression; try to convert */
2166ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      XArray *src, *dst;
2167ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      Int    conv;
2168ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      src = ctx->exprs;
2169ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      dst = debuginfo->cfsi_exprs;
2170ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (src && (VG_(sizeXA)(src) > 0) && (!dst)) {
2171ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         dst = VG_(newXA)( ML_(dinfo_zalloc), "di.ccCt.1", ML_(dinfo_free),
2172ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                           sizeof(CfiExpr) );
2173ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         vg_assert(dst);
2174ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         debuginfo->cfsi_exprs = dst;
2175ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
2176ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      conv = copy_convert_CfiExpr_tree
2177ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    ( dst, ctx, ctxs->cfa_expr_ix );
2178ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      vg_assert(conv >= -1);
2179ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (conv == -1) { why = 6; goto failed; }
2180ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      si->cfa_how = CFIC_EXPR;
2181ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      si->cfa_off = conv;
2182ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (0 && debuginfo->ddump_frames)
2183ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         ML_(ppCfiExpr)(dst, conv);
2184ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
2185ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   else
2186ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (ctxs->cfa_is_regoff && ctxs->cfa_reg == SP_REG) {
2187ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      si->cfa_off = ctxs->cfa_off;
2188663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng#     if defined(VGA_x86) || defined(VGA_amd64) || defined(VGA_s390x) \
2189436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         || defined(VGA_mips32) || defined(VGA_mips64)
2190ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      si->cfa_how = CFIC_IA_SPREL;
2191ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#     elif defined(VGA_arm)
2192ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      si->cfa_how = CFIC_ARM_R13REL;
2193436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov#     elif defined(VGA_arm64)
2194436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      si->cfa_how = CFIC_ARM64_SPREL;
2195ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#     else
2196ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      si->cfa_how = 0; /* invalid */
2197ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#     endif
2198ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
2199ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   else
2200ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (ctxs->cfa_is_regoff && ctxs->cfa_reg == FP_REG) {
2201ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      si->cfa_off = ctxs->cfa_off;
2202663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng#     if defined(VGA_x86) || defined(VGA_amd64) || defined(VGA_s390x) \
2203436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         || defined(VGA_mips32) || defined(VGA_mips64)
2204ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      si->cfa_how = CFIC_IA_BPREL;
2205ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#     elif defined(VGA_arm)
2206ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      si->cfa_how = CFIC_ARM_R12REL;
2207436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov#     elif defined(VGA_arm64)
2208436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      si->cfa_how = CFIC_ARM64_X29REL;
2209ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#     else
2210ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      si->cfa_how = 0; /* invalid */
2211ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#     endif
2212ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
2213ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#  if defined(VGA_arm)
2214ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   else
2215ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (ctxs->cfa_is_regoff && ctxs->cfa_reg == 11/*??_REG*/) {
2216ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      si->cfa_how = CFIC_ARM_R11REL;
2217ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      si->cfa_off = ctxs->cfa_off;
2218ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
2219ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   else
2220ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (ctxs->cfa_is_regoff && ctxs->cfa_reg == 7/*??_REG*/) {
2221ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      si->cfa_how = CFIC_ARM_R7REL;
2222ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      si->cfa_off = ctxs->cfa_off;
2223ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
2224436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov#  elif defined(VGA_arm64)
2225436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   // do we need any arm64 specifics here?
2226ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#  endif
2227ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   else {
2228ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      why = 1;
2229ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      goto failed;
2230ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
2231ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2232ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#  define SUMMARISE_HOW(_how, _off, _ctxreg)                  \
2233ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   switch (_ctxreg.tag) {                                     \
2234ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case RR_Undef:                                          \
2235ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         _how = CFIR_UNKNOWN;   _off = 0; break;              \
2236ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case RR_Same:                                           \
2237ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         _how = CFIR_SAME;      _off = 0; break;              \
2238ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case RR_CFAOff:                                         \
2239ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         _how = CFIR_MEMCFAREL; _off = _ctxreg.arg; break;    \
2240ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case RR_CFAValOff:                                      \
2241ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         _how = CFIR_CFAREL;    _off = _ctxreg.arg; break;    \
2242ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case RR_ValExpr: {                                      \
2243ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         XArray *src, *dst;                                   \
2244ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         Int    conv;                                         \
2245ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         src = ctx->exprs;                                    \
2246ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         dst = debuginfo->cfsi_exprs;                         \
2247ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (src && (VG_(sizeXA)(src) > 0) && (!dst)) {       \
2248ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            dst = VG_(newXA)( ML_(dinfo_zalloc),              \
2249ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                              "di.ccCt.2",                    \
2250ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                              ML_(dinfo_free),                \
2251ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                              sizeof(CfiExpr) );              \
2252ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            vg_assert(dst);                                   \
2253ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            debuginfo->cfsi_exprs = dst;                      \
2254ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }                                                    \
2255ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         conv = copy_convert_CfiExpr_tree                     \
2256ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                       ( dst, ctx, _ctxreg.arg );             \
2257ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         vg_assert(conv >= -1);                               \
2258ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (conv == -1) { why = 7; goto failed; }            \
2259ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         _how = CFIR_EXPR;                                    \
2260ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         _off = conv;                                         \
2261ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (0 && debuginfo->ddump_frames)                    \
2262ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            ML_(ppCfiExpr)(dst, conv);                        \
2263ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         break;                                               \
2264ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }                                                       \
2265ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      default:                                                \
2266ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         why = 2; goto failed; /* otherwise give up */        \
2267ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
2268ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2269436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov
2270ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#  if defined(VGA_x86) || defined(VGA_amd64)
2271ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2272ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* --- entire tail of this fn specialised for x86/amd64 --- */
2273ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2274ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   SUMMARISE_HOW(si->ra_how, si->ra_off,
2275ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                             ctxs->reg[ctx->ra_reg] );
2276ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   SUMMARISE_HOW(si->bp_how, si->bp_off,
2277ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                             ctxs->reg[FP_REG] );
2278ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2279ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* on x86/amd64, it seems the old %{e,r}sp value before the call is
2280ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      always the same as the CFA.  Therefore ... */
2281ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   si->sp_how = CFIR_CFAREL;
2282ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   si->sp_off = 0;
2283ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2284ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* also, gcc says "Undef" for %{e,r}bp when it is unchanged.  So
2285ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      .. */
2286ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (ctxs->reg[FP_REG].tag == RR_Undef)
2287ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      si->bp_how = CFIR_SAME;
2288ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2289ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* knock out some obviously stupid cases */
2290ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (si->ra_how == CFIR_SAME)
2291ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      { why = 3; goto failed; }
2292ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2293ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* bogus looking range?  Note, we require that the difference is
2294ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      representable in 32 bits. */
2295ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (loc_start >= ctx->loc)
2296ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      { why = 4; goto failed; }
2297ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (ctx->loc - loc_start > 10000000 /* let's say */)
2298ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      { why = 5; goto failed; }
2299ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2300ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   si->base = loc_start + ctx->initloc;
2301ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   si->len  = (UInt)(ctx->loc - loc_start);
2302ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2303ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return True;
2304ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2305ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#  elif defined(VGA_arm)
2306ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2307ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* ---- entire tail of this fn specialised for arm ---- */
2308ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2309ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   SUMMARISE_HOW(si->r14_how, si->r14_off,
2310ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                              ctxs->reg[14] );
2311ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2312ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   //SUMMARISE_HOW(si->r13_how, si->r13_off,
2313ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   //                           ctxs->reg[13] );
2314ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2315ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   SUMMARISE_HOW(si->r12_how, si->r12_off,
2316ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                              ctxs->reg[FP_REG] );
2317ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2318ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   SUMMARISE_HOW(si->r11_how, si->r11_off,
2319ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                              ctxs->reg[11/*FP_REG*/] );
2320ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2321ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   SUMMARISE_HOW(si->r7_how, si->r7_off,
2322ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                             ctxs->reg[7] );
2323ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2324ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (ctxs->reg[14/*LR*/].tag == RR_Same
2325ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown       && ctx->ra_reg == 14/*as we expect it always to be*/) {
2326ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* Generate a trivial CfiExpr, which merely says "r14".  First
2327ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         ensure this DebugInfo has a cfsi_expr array in which to park
2328ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         it. */
2329ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (!debuginfo->cfsi_exprs)
2330ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         debuginfo->cfsi_exprs = VG_(newXA)( ML_(dinfo_zalloc),
2331ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                             "di.ccCt.2a",
2332ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                             ML_(dinfo_free),
2333ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                             sizeof(CfiExpr) );
2334ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      si->ra_off = ML_(CfiExpr_CfiReg)( debuginfo->cfsi_exprs,
2335ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                        Creg_ARM_R14);
2336ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      si->ra_how = CFIR_EXPR;
2337ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   } else {
2338ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* Just summarise it in the normal way */
2339ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      SUMMARISE_HOW(si->ra_how, si->ra_off,
2340ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                ctxs->reg[ctx->ra_reg] );
2341ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
2342ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2343ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* on arm, it seems the old r13 (SP) value before the call is
2344ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      always the same as the CFA.  Therefore ... */
2345ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   si->r13_how = CFIR_CFAREL;
2346ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   si->r13_off = 0;
2347ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2348ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* bogus looking range?  Note, we require that the difference is
2349ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      representable in 32 bits. */
2350ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (loc_start >= ctx->loc)
2351ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      { why = 4; goto failed; }
2352ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (ctx->loc - loc_start > 10000000 /* let's say */)
2353ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      { why = 5; goto failed; }
2354ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2355ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   si->base = loc_start + ctx->initloc;
2356ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   si->len  = (UInt)(ctx->loc - loc_start);
2357ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2358ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return True;
2359ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2360436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov#  elif defined(VGA_arm64)
2361436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov
2362436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   /* --- entire tail of this fn specialised for arm64 --- */
2363436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov
2364436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   SUMMARISE_HOW(si->x30_how, si->x30_off, ctxs->reg[30/*LR*/]);
2365436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   SUMMARISE_HOW(si->x29_how, si->x29_off, ctxs->reg[29/*FP*/]);
2366436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov
2367436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   if (ctxs->reg[30/*LR*/].tag == RR_Same
2368436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov       && ctx->ra_reg == 30/*as we expect it always to be*/) {
2369436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      /* Generate a trivial CfiExpr, which merely says "x30".  First
2370436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         ensure this DebugInfo has a cfsi_expr array in which to park
2371436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         it. */
2372436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      if (!debuginfo->cfsi_exprs)
2373436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         debuginfo->cfsi_exprs = VG_(newXA)( ML_(dinfo_zalloc),
2374436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov                                             "di.ccCt.2a-arm64",
2375436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov                                             ML_(dinfo_free),
2376436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov                                             sizeof(CfiExpr) );
2377436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      si->ra_off = ML_(CfiExpr_CfiReg)( debuginfo->cfsi_exprs,
2378436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov                                        Creg_ARM64_X30);
2379436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      si->ra_how = CFIR_EXPR;
2380436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   } else {
2381436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      /* Just summarise it in the normal way */
2382436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      SUMMARISE_HOW(si->ra_how, si->ra_off, ctxs->reg[ctx->ra_reg]);
2383436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   }
2384436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov
2385436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   /* on arm64, it seems the old SP value before the call is always
2386436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      the same as the CFA.  Therefore ... */
2387436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   si->sp_how = CFIR_CFAREL;
2388436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   si->sp_off = 0;
2389436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov
2390436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   /* bogus looking range?  Note, we require that the difference is
2391436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      representable in 32 bits. */
2392436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   if (loc_start >= ctx->loc)
2393436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      { why = 4; goto failed; }
2394436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   if (ctx->loc - loc_start > 10000000 /* let's say */)
2395436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      { why = 5; goto failed; }
2396436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov
2397436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   si->base = loc_start + ctx->initloc;
2398436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   si->len  = (UInt)(ctx->loc - loc_start);
2399436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov
2400436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   return True;
2401ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2402b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov#  elif defined(VGA_s390x)
2403b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
2404436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   /* --- entire tail of this fn specialised for s390 --- */
2405436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov
2406b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   SUMMARISE_HOW(si->ra_how, si->ra_off,
2407b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                             ctxs->reg[ctx->ra_reg] );
2408b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   SUMMARISE_HOW(si->fp_how, si->fp_off,
2409b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                             ctxs->reg[FP_REG] );
2410b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   SUMMARISE_HOW(si->sp_how, si->sp_off,
2411b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                             ctxs->reg[SP_REG] );
2412b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
2413b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   /* change some defaults to consumable values */
2414b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   if (si->sp_how == CFIR_UNKNOWN)
2415b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      si->sp_how = CFIR_SAME;
2416b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
2417b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   if (si->fp_how == CFIR_UNKNOWN)
2418b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      si->fp_how = CFIR_SAME;
2419b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
2420b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   if (si->cfa_how == CFIR_UNKNOWN) {
2421b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      si->cfa_how = CFIC_IA_SPREL;
2422b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      si->cfa_off = 160;
2423b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   }
2424b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   if (si->ra_how == CFIR_UNKNOWN) {
2425b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      if (!debuginfo->cfsi_exprs)
2426b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         debuginfo->cfsi_exprs = VG_(newXA)( ML_(dinfo_zalloc),
2427b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                                             "di.ccCt.2a",
2428b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                                             ML_(dinfo_free),
2429b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                                             sizeof(CfiExpr) );
2430b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      si->ra_how = CFIR_EXPR;
2431b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      si->ra_off = ML_(CfiExpr_CfiReg)( debuginfo->cfsi_exprs,
2432b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                                        Creg_S390_R14);
2433b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   }
2434b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
2435b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   /* knock out some obviously stupid cases */
2436b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   if (si->ra_how == CFIR_SAME)
2437b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      { why = 3; goto failed; }
2438b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
2439b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   /* bogus looking range?  Note, we require that the difference is
2440b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      representable in 32 bits. */
2441b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   if (loc_start >= ctx->loc)
2442b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      { why = 4; goto failed; }
2443b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   if (ctx->loc - loc_start > 10000000 /* let's say */)
2444b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      { why = 5; goto failed; }
2445b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
2446b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   si->base = loc_start + ctx->initloc;
2447b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   si->len  = (UInt)(ctx->loc - loc_start);
2448b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
2449b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   return True;
2450b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
2451436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov#  elif defined(VGA_mips32) || defined(VGA_mips64)
2452663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
2453663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   /* --- entire tail of this fn specialised for mips --- */
2454663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
2455663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   SUMMARISE_HOW(si->ra_how, si->ra_off,
2456663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                             ctxs->reg[ctx->ra_reg] );
2457663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   SUMMARISE_HOW(si->fp_how, si->fp_off,
2458663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                             ctxs->reg[FP_REG] );
2459663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   SUMMARISE_HOW(si->sp_how, si->sp_off,
2460663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                             ctxs->reg[SP_REG] );
2461663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      si->sp_how = CFIR_CFAREL;
2462663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   si->sp_off = 0;
2463663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
2464663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   if (si->fp_how == CFIR_UNKNOWN)
2465663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng       si->fp_how = CFIR_SAME;
2466663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   if (si->cfa_how == CFIR_UNKNOWN) {
2467663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      si->cfa_how = CFIC_IA_SPREL;
2468663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      si->cfa_off = 160;
2469663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   }
2470663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   if (si->ra_how == CFIR_UNKNOWN) {
2471663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (!debuginfo->cfsi_exprs)
2472663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         debuginfo->cfsi_exprs = VG_(newXA)( ML_(dinfo_zalloc),
2473663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                                             "di.ccCt.2a",
2474663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                                             ML_(dinfo_free),
2475663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                                             sizeof(CfiExpr) );
2476663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      si->ra_how = CFIR_EXPR;
2477663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      si->ra_off = ML_(CfiExpr_CfiReg)( debuginfo->cfsi_exprs,
2478663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                                        Creg_MIPS_RA);
2479663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   }
2480663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
2481663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   if (si->ra_how == CFIR_SAME)
2482663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      { why = 3; goto failed; }
2483663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
2484663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   if (loc_start >= ctx->loc)
2485663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      { why = 4; goto failed; }
2486663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   if (ctx->loc - loc_start > 10000000 /* let's say */)
2487663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      { why = 5; goto failed; }
2488663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
2489663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   si->base = loc_start + ctx->initloc;
2490663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   si->len  = (UInt)(ctx->loc - loc_start);
2491663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
2492663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   return True;
2493663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
2494ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#  elif defined(VGA_ppc32) || defined(VGA_ppc64)
2495436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   /* These don't use CFI based unwinding (is that really true?) */
2496436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov
2497ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#  else
2498ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#    error "Unknown arch"
2499ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#  endif
2500ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2501436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   /* --- non-specialised code after this point --- */
2502436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov
2503ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#  undef SUMMARISE_HOW
2504ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2505ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  failed:
2506ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (VG_(clo_verbosity) > 2 || debuginfo->trace_cfi) {
2507ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      VG_(message)(Vg_DebugMsg,
2508ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  "summarise_context(loc_start = %#lx)"
2509ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  ": cannot summarise(why=%d):   \n", loc_start, why);
2510ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      ppUnwindContext(ctx);
2511ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
2512ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return False;
2513ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
2514ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2515ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Copy the tree rooted at srcuc->exprs node srcix to dstxa, on the
2516ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   way converting any DwReg regs (regs numbered using the Dwarf scheme
2517ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   defined by each architecture's ABI) into CfiRegs, which are
2518ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   platform independent.  If the conversion isn't possible because
2519ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   there is no equivalent register, return -1.  This has the
2520ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   undesirable side effect of de-dagifying the input; oh well. */
2521ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic Int copy_convert_CfiExpr_tree ( XArray*        dstxa,
2522ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                       UnwindContext* srcuc,
2523ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                       Int            srcix )
2524ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
2525ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   CfiExpr* src;
2526b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   Int      cpL, cpR, cpA;
2527ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   XArray*  srcxa = srcuc->exprs;
2528ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vg_assert(srcxa);
2529ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vg_assert(dstxa);
2530ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vg_assert(srcix >= 0 && srcix < VG_(sizeXA)(srcxa));
2531ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2532ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   src = VG_(indexXA)( srcxa, srcix );
2533ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   switch (src->tag) {
2534ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Cex_Undef:
2535ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return ML_(CfiExpr_Undef)( dstxa );
2536ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Cex_Deref:
2537ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         cpA = copy_convert_CfiExpr_tree( dstxa, srcuc, src->Cex.Deref.ixAddr );
2538ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (cpA == -1)
2539ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            return -1; /* propagate failure */
2540ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return ML_(CfiExpr_Deref)( dstxa, cpA );
2541ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Cex_Const:
2542ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return ML_(CfiExpr_Const)( dstxa, src->Cex.Const.con );
2543ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Cex_Binop:
2544ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         cpL = copy_convert_CfiExpr_tree( dstxa, srcuc, src->Cex.Binop.ixL );
2545ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         cpR = copy_convert_CfiExpr_tree( dstxa, srcuc, src->Cex.Binop.ixR );
2546ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         vg_assert(cpL >= -1 && cpR >= -1);
2547ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (cpL == -1 || cpR == -1)
2548ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            return -1; /* propagate failure */
2549ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return ML_(CfiExpr_Binop)( dstxa, src->Cex.Binop.op, cpL, cpR );
2550ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Cex_CfiReg:
2551ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* should not see these in input (are created only by this
2552ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            conversion step!) */
2553ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         VG_(core_panic)("copy_convert_CfiExpr_tree: CfiReg in input");
2554b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      case Cex_DwReg: {
2555ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* This is the only place where the conversion can fail. */
2556b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         Int dwreg __attribute__((unused));
2557ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         dwreg = src->Cex.DwReg.reg;
2558ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#        if defined(VGA_x86) || defined(VGA_amd64)
2559ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (dwreg == SP_REG)
2560ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            return ML_(CfiExpr_CfiReg)( dstxa, Creg_IA_SP );
2561ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (dwreg == FP_REG)
2562ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            return ML_(CfiExpr_CfiReg)( dstxa, Creg_IA_BP );
2563ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (dwreg == srcuc->ra_reg)
2564ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            return ML_(CfiExpr_CfiReg)( dstxa, Creg_IA_IP ); /* correct? */
2565ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#        elif defined(VGA_arm)
2566ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (dwreg == SP_REG)
2567ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            return ML_(CfiExpr_CfiReg)( dstxa, Creg_ARM_R13 );
2568ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (dwreg == FP_REG)
2569ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            return ML_(CfiExpr_CfiReg)( dstxa, Creg_ARM_R12 );
2570ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (dwreg == srcuc->ra_reg)
2571ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           return ML_(CfiExpr_CfiReg)( dstxa, Creg_ARM_R15 ); /* correct? */
2572b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov#        elif defined(VGA_s390x)
2573b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         if (dwreg == SP_REG)
2574b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov            return ML_(CfiExpr_CfiReg)( dstxa, Creg_IA_SP );
2575b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         if (dwreg == FP_REG)
2576b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov            return ML_(CfiExpr_CfiReg)( dstxa, Creg_IA_BP );
2577b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         if (dwreg == srcuc->ra_reg)
2578b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov            return ML_(CfiExpr_CfiReg)( dstxa, Creg_IA_IP ); /* correct? */
2579436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov#        elif defined(VGA_mips32) || defined(VGA_mips64)
2580663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         if (dwreg == SP_REG)
2581663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            return ML_(CfiExpr_CfiReg)( dstxa, Creg_IA_SP );
2582663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         if (dwreg == FP_REG)
2583663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            return ML_(CfiExpr_CfiReg)( dstxa, Creg_IA_BP );
2584663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         if (dwreg == srcuc->ra_reg)
2585663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            return ML_(CfiExpr_CfiReg)( dstxa, Creg_IA_IP );
2586436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov#        elif defined(VGA_arm64)
2587436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         I_die_here;
2588ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#        elif defined(VGA_ppc32) || defined(VGA_ppc64)
2589ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#        else
2590ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#           error "Unknown arch"
2591ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#        endif
2592ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* else we must fail - can't represent the reg */
2593ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return -1;
2594b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      }
2595ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      default:
2596ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         VG_(core_panic)("copy_convert_CfiExpr_tree: default");
2597ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
2598ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
2599ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2600ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2601ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic void ppUnwindContext_summary ( UnwindContext* ctx )
2602ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
2603ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   struct UnwindContextState* ctxs = &ctx->state[ctx->state_sp];
2604ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2605ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   VG_(printf)("0x%llx-1: ", (ULong)ctx->loc);
2606ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2607ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (ctxs->cfa_reg == SP_REG) {
2608ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      VG_(printf)("SP/CFA=%d+SP   ", ctxs->cfa_off);
2609ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   } else
2610ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (ctxs->cfa_reg == FP_REG) {
2611ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      VG_(printf)("SP/CFA=%d+FP   ", ctxs->cfa_off);
2612ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   } else {
2613ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      VG_(printf)("SP/CFA=unknown  ");
2614ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
2615ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2616ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   VG_(printf)("RA=");
2617ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   ppRegRule( ctx->exprs, &ctxs->reg[ctx->ra_reg] );
2618ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2619ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   VG_(printf)("FP=");
2620ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   ppRegRule( ctx->exprs, &ctxs->reg[FP_REG] );
2621ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   VG_(printf)("\n");
2622ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
2623ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2624ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2625ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* ------------ Pick apart DWARF2 byte streams ------------ */
2626ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2627436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanovstatic ULong step_le_u_encoded_literal ( DiCursor* data, UInt size )
2628ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
2629ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   switch (size) {
2630436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      case 8:  return (ULong)ML_(cur_step_ULong)( data );
2631436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      case 4:  return (ULong)ML_(cur_step_UInt)( data );
2632436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      case 2:  return (ULong)ML_(cur_step_UShort)( data );
2633436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      case 1:  return (ULong)ML_(cur_step_UChar)( data );
2634ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      default: vg_assert(0); /*NOTREACHED*/ return 0;
2635ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
2636ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
2637ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2638436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanovstatic Long step_le_s_encoded_literal ( DiCursor* data, UInt size )
2639ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
2640436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   Long s64 = step_le_u_encoded_literal( data, size );
2641ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   switch (size) {
2642ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 8:  break;
2643ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 4:  s64 <<= 32; s64 >>= 32; break;
2644ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 2:  s64 <<= 48; s64 >>= 48; break;
2645ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 1:  s64 <<= 56; s64 >>= 56; break;
2646ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      default: vg_assert(0); /*NOTREACHED*/ return 0;
2647ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
2648ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return s64;
2649ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
2650ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2651ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic UChar default_Addr_encoding ( void )
2652ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
2653ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   switch (sizeof(Addr)) {
2654ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 4: return DW_EH_PE_udata4;
2655ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 8: return DW_EH_PE_udata8;
2656ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      default: vg_assert(0);
2657ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
2658ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
2659ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2660ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic UInt size_of_encoded_Addr ( UChar encoding )
2661ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
2662ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (encoding == DW_EH_PE_omit)
2663ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return 0;
2664ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2665ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   switch (encoding & 0x07) {
2666ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case DW_EH_PE_absptr: return sizeof(Addr);
2667ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case DW_EH_PE_udata2: return sizeof(UShort);
2668ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case DW_EH_PE_udata4: return sizeof(UInt);
2669ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case DW_EH_PE_udata8: return sizeof(ULong);
2670ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      default: vg_assert(0);
2671ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
2672ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
2673ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2674436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanovstatic Addr step_encoded_Addr ( AddressDecodingInfo* adi,
2675436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov                                /*MOD*/DiCursor* data )
2676ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
2677ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* Regarding the handling of DW_EH_PE_absptr.  DWARF3 says this
2678ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      denotes an absolute address, hence you would think 'base' is
2679ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      zero.  However, that is nonsensical (unless relocations are to
2680ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      be applied to the unwind data before reading it, which sounds
2681ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      unlikely).  My interpretation is that DW_EH_PE_absptr indicates
2682ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      an address relative to where the object was loaded (technically,
2683ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      relative to its stated load VMA, hence the use of text_bias
2684ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      rather than text_avma).  Hmm, should we use text_bias or
2685ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      text_avma here?  Not sure.
2686ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2687ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      This view appears to be supported by DWARF3 spec sec 7.3
2688ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      "Executable Objects and Shared Objects":
2689ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2690ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         This requirement makes the debugging information for shared
2691ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         objects position independent.  Virtual addresses in a shared
2692ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         object may be calculated by adding the offset to the base
2693ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         address at which the object was attached.  This offset is
2694ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         available in the run-time linker's data structures.
2695ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   */
2696436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   Addr     base;
2697436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   Word     offset;
2698436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   UChar    encoding      = adi->encoding;
2699436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   DiCursor ehframe_image = adi->ehframe_image;
2700436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   Addr     ehframe_avma  = adi->ehframe_avma;
2701ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2702ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vg_assert((encoding & DW_EH_PE_indirect) == 0);
2703ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2704ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   switch (encoding & 0x70) {
2705ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case DW_EH_PE_absptr:
2706ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         base = adi->text_bias;
2707ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         break;
2708ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case DW_EH_PE_pcrel:
2709436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         base = ehframe_avma + ML_(cur_minus)(*data, ehframe_image);
2710ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         break;
2711ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case DW_EH_PE_datarel:
2712ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         vg_assert(0);
2713ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         base = /* data base address */ 0;
2714ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         break;
2715ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case DW_EH_PE_textrel:
2716ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         vg_assert(0);
2717ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         base = /* text base address */ 0;
2718ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         break;
2719ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case DW_EH_PE_funcrel:
2720ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         base = 0;
2721ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         break;
2722ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case DW_EH_PE_aligned:
2723ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         base = 0;
2724436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         offset = ML_(cur_minus)(*data, ehframe_image);
2725ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if ((offset % sizeof(Addr)) != 0) {
2726436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            Word nbytes = sizeof(Addr) - (offset % sizeof(Addr));
2727436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            *data = ML_(cur_plus)(*data, nbytes);
2728ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
2729ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         break;
2730ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      default:
2731ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         vg_assert(0);
2732ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
2733ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2734ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if ((encoding & 0x07) == 0x00)
2735ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      encoding |= default_Addr_encoding();
2736ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2737ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   switch (encoding & 0x0f) {
2738ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case DW_EH_PE_udata2:
2739436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         return base + ML_(cur_step_UShort)(data);
2740ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case DW_EH_PE_udata4:
2741436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         return base + ML_(cur_step_UInt)(data);
2742ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case DW_EH_PE_udata8:
2743436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         return base + ML_(cur_step_ULong)(data);
2744ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case DW_EH_PE_sdata2:
2745436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         return base + ML_(cur_step_Short)(data);
2746ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case DW_EH_PE_sdata4:
2747436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         return base + ML_(cur_step_Int)(data);
2748ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case DW_EH_PE_sdata8:
2749436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         return base + ML_(cur_step_Long)(data);
2750ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      default:
2751ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         vg_assert2(0, "read encoded address %d\n", encoding & 0x0f);
2752ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
2753ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
2754ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2755ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2756ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* ------------ Run/show DWARF3 expressions ---------- */
2757ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2758ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Convert the DWARF3 expression in expr[0 .. exprlen-1] into a dag
2759ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   (of CfiExprs) stored in ctx->exprs, and return the index in
2760ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   ctx->exprs of the root node.  Or fail in which case return -1. */
2761ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* IMPORTANT: when adding expression forms here, also remember to
2762ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   add suitable evaluation code in evalCfiExpr in debuginfo.c. */
2763ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic Int dwarfexpr_to_dag ( UnwindContext* ctx,
2764436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov                              DiCursor expr, Int exprlen,
2765ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                              Bool push_cfa_at_start,
2766ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                              Bool ddump_frames )
2767ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
2768ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#  define N_EXPR_STACK 20
2769ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2770ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#  define PUSH(_arg)                               \
2771ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      do {                                         \
2772ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         vg_assert(sp >= -1 && sp < N_EXPR_STACK); \
2773ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (sp == N_EXPR_STACK-1)                 \
2774ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            return -1;                             \
2775ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         sp++;                                     \
2776ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         stack[sp] = (_arg);                       \
2777ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      } while (0)
2778ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2779ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#  define POP(_lval)                               \
2780ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      do {                                         \
2781ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         vg_assert(sp >= -1 && sp < N_EXPR_STACK); \
2782ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (sp == -1)                             \
2783ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            return -1;                             \
2784ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         _lval = stack[sp];                        \
2785ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         sp--;                                     \
2786ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      } while (0)
2787ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2788436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   Int      ix, ix2, reg;
2789436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   UChar    opcode;
2790436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   Word     sw;
2791436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   UWord    uw;
2792436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   CfiUnop  uop;
2793436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   CfiBinop bop;
2794436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   const HChar* opname;
2795ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2796ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Int sp; /* # of top element: valid is -1 .. N_EXPR_STACK-1 */
2797ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Int stack[N_EXPR_STACK];  /* indices into ctx->exprs */
2798ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   struct UnwindContextState* ctxs = &ctx->state[ctx->state_sp];
2799ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2800436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   XArray*  dst   = ctx->exprs;
2801436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   DiCursor limit = ML_(cur_plus)(expr, exprlen);
2802ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2803ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vg_assert(dst);
2804ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vg_assert(exprlen >= 0);
2805ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2806ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   sp = -1; /* empty */
2807ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2808ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* Synthesise the CFA as a CfiExpr */
2809ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (push_cfa_at_start) {
2810ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (ctxs->cfa_is_regoff) {
2811ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* cfa is reg +/- offset */
2812ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         ix = ML_(CfiExpr_Binop)( dst,
2813436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov                 Cbinop_Add,
2814ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                 ML_(CfiExpr_DwReg)( dst, ctxs->cfa_reg ),
2815ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                 ML_(CfiExpr_Const)( dst, (UWord)(Word)ctxs->cfa_off )
2816ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown              );
2817ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         PUSH(ix);
2818ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      } else {
2819ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* CFA is already an expr; use its root node */
2820ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         PUSH(ctxs->cfa_expr_ix);
2821ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
2822ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
2823ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2824ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   while (True) {
2825ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2826ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      vg_assert(sp >= -1 && sp < N_EXPR_STACK);
2827ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2828436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      if (ML_(cur_cmpGT)(expr, limit)) /* "expr > limit" */
2829ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return -1;  /* overrun - something's wrong */
2830ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2831436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      if (ML_(cur_cmpEQ)(expr, limit)) { /* "expr == limit" */
2832ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        /* end of expr - return expr on the top of stack. */
2833ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        if (sp == -1)
2834ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           return -1; /* stack empty.  Bad. */
2835ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        else
2836ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           break;
2837ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
2838ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2839436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      uop = 0; bop = 0; opname = NULL; /* excessively conservative */
2840ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2841436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      opcode = ML_(cur_step_UChar)(&expr);
2842ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      switch (opcode) {
2843ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2844ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case DW_OP_lit0 ... DW_OP_lit31:
2845ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            /* push: literal 0 .. 31 */
2846ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            sw = (Word)opcode - (Word)DW_OP_lit0;
2847ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            vg_assert(sw >= 0 && sw <= 31);
2848ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            PUSH( ML_(CfiExpr_Const)( dst, (UWord)sw ) );
2849ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            if (ddump_frames)
2850ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               VG_(printf)("DW_OP_lit%ld", sw);
2851ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            break;
2852ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2853ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case DW_OP_breg0 ... DW_OP_breg31:
2854ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            /* push: reg + sleb128 */
2855ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            reg = (Int)opcode - (Int)DW_OP_breg0;
2856ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            vg_assert(reg >= 0 && reg <= 31);
2857436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            sw = step_leb128S( &expr );
2858ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            ix = ML_(CfiExpr_Binop)( dst,
2859436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov                    Cbinop_Add,
2860ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    ML_(CfiExpr_DwReg)( dst, reg ),
2861ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    ML_(CfiExpr_Const)( dst, (UWord)sw )
2862ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                 );
2863ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            PUSH(ix);
2864ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            if (ddump_frames)
2865ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               VG_(printf)("DW_OP_breg%d: %ld", reg, sw);
2866ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            break;
2867ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2868ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case DW_OP_reg0 ... DW_OP_reg31:
2869ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            /* push: reg */
2870ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            reg = (Int)opcode - (Int)DW_OP_reg0;
2871ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            vg_assert(reg >= 0 && reg <= 31);
2872ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            ix = ML_(CfiExpr_DwReg)( dst, reg );
2873ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            PUSH(ix);
2874ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            if (ddump_frames)
2875ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               VG_(printf)("DW_OP_reg%d", reg);
2876ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            break;
2877ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2878ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case DW_OP_plus_uconst:
2879436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            uw = step_leb128U( &expr );
2880ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            PUSH( ML_(CfiExpr_Const)( dst, uw ) );
2881ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            POP( ix );
2882ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            POP( ix2 );
2883436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            PUSH( ML_(CfiExpr_Binop)( dst, Cbinop_Add, ix2, ix ) );
2884ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            if (ddump_frames)
2885ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               VG_(printf)("DW_OP_plus_uconst: %lu", uw);
2886ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            break;
2887ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2888ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case DW_OP_const4s:
2889ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            /* push: 32-bit signed immediate */
2890436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            sw = step_le_s_encoded_literal( &expr, 4 );
2891ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            PUSH( ML_(CfiExpr_Const)( dst, (UWord)sw ) );
2892ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            if (ddump_frames)
2893ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               VG_(printf)("DW_OP_const4s: %ld", sw);
2894ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            break;
2895ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2896436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         case DW_OP_const2s:
2897436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            /* push: 16-bit signed immediate */
2898436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            sw = step_le_s_encoded_literal( &expr, 2 );
2899436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            PUSH( ML_(CfiExpr_Const)( dst, (UWord)sw ) );
2900436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            if (ddump_frames)
2901436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov               VG_(printf)("DW_OP_const2s: %ld", sw);
2902436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            break;
2903436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov
2904ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case DW_OP_const1s:
2905ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            /* push: 8-bit signed immediate */
2906436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            sw = step_le_s_encoded_literal( &expr, 1 );
2907ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            PUSH( ML_(CfiExpr_Const)( dst, (UWord)sw ) );
2908ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            if (ddump_frames)
2909ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               VG_(printf)("DW_OP_const1s: %ld", sw);
2910ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            break;
2911ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2912436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         case DW_OP_const1u:
2913436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            /* push: 8-bit unsigned immediate */
2914436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            uw = step_le_u_encoded_literal( &expr, 1 );
2915436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            PUSH( ML_(CfiExpr_Const)( dst, uw ) );
2916436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            if (ddump_frames)
2917436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov               VG_(printf)("DW_OP_const1: %lu", uw);
2918436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            break;
2919436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov
2920436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         case DW_OP_const2u:
2921436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            /* push: 16-bit unsigned immediate */
2922436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            uw = step_le_u_encoded_literal( &expr, 2 );
2923436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            PUSH( ML_(CfiExpr_Const)( dst, uw ) );
2924436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            if (ddump_frames)
2925436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov               VG_(printf)("DW_OP_const2: %lu", uw);
2926436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            break;
2927436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov
2928436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         case DW_OP_const4u:
2929436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            /* push: 32-bit unsigned immediate */
2930436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            uw = step_le_u_encoded_literal( &expr, 4 );
2931436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            PUSH( ML_(CfiExpr_Const)( dst, uw ) );
2932436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            if (ddump_frames)
2933436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov               VG_(printf)("DW_OP_const4: %lu", uw);
2934436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            break;
2935436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov
2936436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         case DW_OP_abs:
2937436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            uop = Cunop_Abs; opname = "abs"; goto unop;
2938436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         case DW_OP_neg:
2939436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            uop = Cunop_Neg; opname = "neg"; goto unop;
2940436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         case DW_OP_not:
2941436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            uop = Cunop_Not; opname = "not"; goto unop;
2942436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         unop:
2943436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            POP( ix );
2944436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            PUSH( ML_(CfiExpr_Unop)( dst, uop, ix ) );
2945436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            if (ddump_frames)
2946436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov               VG_(printf)("DW_OP_%s", opname);
2947436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            break;
2948436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov
2949ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case DW_OP_minus:
2950436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            bop = Cbinop_Sub; opname = "minus"; goto binop;
2951ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case DW_OP_plus:
2952436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            bop = Cbinop_Add; opname = "plus"; goto binop;
2953ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case DW_OP_and:
2954436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            bop = Cbinop_And; opname = "and"; goto binop;
2955ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case DW_OP_mul:
2956436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            bop = Cbinop_Mul; opname = "mul"; goto binop;
2957b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         case DW_OP_shl:
2958436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            bop = Cbinop_Shl; opname = "shl"; goto binop;
2959b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         case DW_OP_shr:
2960436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            bop = Cbinop_Shr; opname = "shr"; goto binop;
2961b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         case DW_OP_eq:
2962436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            bop = Cbinop_Eq; opname = "eq"; goto binop;
2963b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         case DW_OP_ge:
2964436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            bop = Cbinop_Ge; opname = "ge"; goto binop;
2965b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         case DW_OP_gt:
2966436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            bop = Cbinop_Gt; opname = "gt"; goto binop;
2967b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         case DW_OP_le:
2968436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            bop = Cbinop_Le; opname = "le"; goto binop;
2969b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         case DW_OP_lt:
2970436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            bop = Cbinop_Lt; opname = "lt"; goto binop;
2971b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         case DW_OP_ne:
2972436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            bop = Cbinop_Ne; opname = "ne"; goto binop;
2973ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         binop:
2974ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            POP( ix );
2975ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            POP( ix2 );
2976436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            PUSH( ML_(CfiExpr_Binop)( dst, bop, ix2, ix ) );
2977ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            if (ddump_frames)
2978ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               VG_(printf)("DW_OP_%s", opname);
2979ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            break;
2980ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2981ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case DW_OP_deref:
2982ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            POP( ix );
2983ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            PUSH( ML_(CfiExpr_Deref)( dst, ix ) );
2984ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            if (ddump_frames)
2985ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               VG_(printf)("DW_OP_deref");
2986ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            break;
2987ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2988ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         default:
2989ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            if (!VG_(clo_xml))
2990ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               VG_(message)(Vg_DebugMsg,
2991ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                            "Warning: DWARF2 CFI reader: unhandled DW_OP_ "
2992ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                            "opcode 0x%x\n", (Int)opcode);
2993ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            return -1;
2994ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
2995ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2996436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      if (ML_(cur_cmpLT)(expr, limit) && ddump_frames)
2997ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         VG_(printf)("; ");
2998ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2999ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
3000ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3001ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vg_assert(sp >= -1 && sp < N_EXPR_STACK);
3002ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (sp == -1)
3003ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return -1;
3004ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3005ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (0 && ddump_frames)
3006ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      ML_(ppCfiExpr)( dst, stack[sp] );
3007ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return stack[sp];
3008ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3009ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#  undef POP
3010ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#  undef PUSH
3011ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#  undef N_EXPR_STACK
3012ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
3013ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3014ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3015ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* ------------ Run/show CFI instructions ------------ */
3016ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3017ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Run a CFI instruction, and also return its length.
3018ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Returns 0 if the instruction could not be executed.
3019ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown*/
3020ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic Int run_CF_instruction ( /*MOD*/UnwindContext* ctx,
3021436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov                                DiCursor instrIN,
3022ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                UnwindContext* restore_ctx,
3023ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                AddressDecodingInfo* adi,
3024ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                struct _DebugInfo* di )
3025ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
3026436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   Int      off, reg, reg2, len, j;
3027436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   UInt     delta;
3028436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   Addr     printing_bias = ((Addr)ctx->initloc) - ((Addr)di->text_bias);
3029ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   struct UnwindContextState* ctxs;
3030436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov
3031436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   DiCursor instr   = instrIN;
3032436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   UChar    instr_0 = ML_(cur_step_UChar)(&instr);
3033436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   UChar    hi2     = (instr_0 >> 6) & 3;
3034436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   UChar    lo6     = instr_0 & 0x3F;
3035ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3036ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (ctx->state_sp < 0 || ctx->state_sp >= N_RR_STACK)
3037ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return 0; /* bogus reg-rule stack pointer */
3038ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3039ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   ctxs = &ctx->state[ctx->state_sp];
3040ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (hi2 == DW_CFA_advance_loc) {
3041ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      delta = (UInt)lo6;
3042ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      delta *= ctx->code_a_f;
3043ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      ctx->loc += delta;
3044ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (di->ddump_frames)
3045ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         VG_(printf)("  DW_CFA_advance_loc: %d to %08lx\n",
3046ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     (Int)delta, (Addr)ctx->loc + printing_bias);
3047436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      return ML_(cur_minus)(instr, instrIN);
3048ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
3049ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3050ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (hi2 == DW_CFA_offset) {
3051ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* Set rule for reg 'lo6' to CFAOff(off * data_af) */
3052436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      off = step_leb128( &instr, 0 );
3053ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      reg = (Int)lo6;
3054ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (reg < 0 || reg >= N_CFI_REGS)
3055ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return 0; /* fail */
3056ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      ctxs->reg[reg].tag = RR_CFAOff;
3057ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      ctxs->reg[reg].arg = off * ctx->data_a_f;
3058ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (di->ddump_frames)
3059ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         VG_(printf)("  DW_CFA_offset: r%d at cfa%s%d\n",
3060ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     (Int)reg,
3061ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     ctxs->reg[reg].arg < 0 ? "" : "+",
3062ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     (Int)ctxs->reg[reg].arg );
3063436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      return ML_(cur_minus)(instr, instrIN);
3064ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
3065ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3066ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (hi2 == DW_CFA_restore) {
3067ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      reg = (Int)lo6;
3068ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (reg < 0 || reg >= N_CFI_REGS)
3069ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return 0; /* fail */
3070ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (restore_ctx == NULL)
3071ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return 0; /* fail */
3072ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      ctxs->reg[reg] = restore_ctx->state[restore_ctx->state_sp].reg[reg];
3073ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (di->ddump_frames)
3074ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         VG_(printf)("  DW_CFA_restore: r%d\n", (Int)reg);
3075436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      return ML_(cur_minus)(instr, instrIN);
3076ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
3077ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3078ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vg_assert(hi2 == DW_CFA_use_secondary);
3079ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3080ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   switch (lo6) {
3081ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case DW_CFA_nop:
3082ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (di->ddump_frames)
3083ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            VG_(printf)("  DW_CFA_nop\n");
3084ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         break;
3085ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case DW_CFA_set_loc:
3086ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* WAS:
3087ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            ctx->loc = read_Addr(&instr[i]) - ctx->initloc; i+= sizeof(Addr);
3088ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            Was this ever right? */
3089ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* 2007 Feb 23: No.  binutils/dwarf.c treats it as an encoded
3090ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            address and that appears to be in accordance with the
3091ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            DWARF3 spec. */
3092436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         ctx->loc = step_encoded_Addr(adi, &instr);
3093ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (di->ddump_frames)
3094ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            VG_(printf)("  rci:DW_CFA_set_loc\n");
3095ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         break;
3096ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case DW_CFA_advance_loc1:
3097436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         delta = (UInt)ML_(cur_step_UChar)(&instr);
3098ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         delta *= ctx->code_a_f;
3099ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         ctx->loc += delta;
3100ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (di->ddump_frames)
3101ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            VG_(printf)("  DW_CFA_advance_loc1: %d to %08lx\n",
3102ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        (Int)delta, (Addr)ctx->loc + printing_bias);
3103ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         break;
3104ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case DW_CFA_advance_loc2:
3105436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         delta = (UInt)ML_(cur_step_UShort)(&instr);
3106ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         delta *= ctx->code_a_f;
3107ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         ctx->loc += delta;
3108ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (di->ddump_frames)
3109ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            VG_(printf)("  DW_CFA_advance_loc2: %d to %08lx\n",
3110ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        (Int)delta, (Addr)ctx->loc + printing_bias);
3111ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         break;
3112ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case DW_CFA_advance_loc4:
3113436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         delta = (UInt)ML_(cur_step_UInt)(&instr);
3114ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         delta *= ctx->code_a_f;
3115ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         ctx->loc += delta;
3116ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (di->ddump_frames)
3117ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            VG_(printf)("  DW_CFA_advance_loc4: %d to %08lx\n",
3118ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        (Int)delta, (Addr)ctx->loc + printing_bias);
3119ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         break;
3120ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3121ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case DW_CFA_def_cfa:
3122436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         reg = step_leb128( &instr, 0 );
3123436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         off = step_leb128( &instr, 0 );
3124ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (reg < 0 || reg >= N_CFI_REGS)
3125ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            return 0; /* fail */
3126ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         ctxs->cfa_is_regoff = True;
3127ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         ctxs->cfa_expr_ix   = 0;
3128ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         ctxs->cfa_reg       = reg;
3129ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         ctxs->cfa_off       = off;
3130ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (di->ddump_frames)
3131ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            VG_(printf)("  DW_CFA_def_cfa: r%d ofs %d\n", (Int)reg, (Int)off);
3132ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         break;
3133ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3134ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case DW_CFA_def_cfa_sf:
3135436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         reg = step_leb128( &instr, 0 );
3136436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         off = step_leb128( &instr, 1 );
3137ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (reg < 0 || reg >= N_CFI_REGS)
3138ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            return 0; /* fail */
3139ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         ctxs->cfa_is_regoff = True;
3140ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         ctxs->cfa_expr_ix   = 0;
3141ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         ctxs->cfa_reg       = reg;
3142ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         ctxs->cfa_off       = off * ctx->data_a_f;
3143ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (di->ddump_frames)
3144ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            VG_(printf)("  rci:DW_CFA_def_cfa_sf\n");
3145ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         break;
3146ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3147ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case DW_CFA_register:
3148436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         reg  = step_leb128( &instr, 0 );
3149436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         reg2 = step_leb128( &instr, 0 );
3150ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (reg < 0 || reg >= N_CFI_REGS)
3151ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            return 0; /* fail */
3152ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (reg2 < 0 || reg2 >= N_CFI_REGS)
3153ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            return 0; /* fail */
3154ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         ctxs->reg[reg].tag = RR_Reg;
3155ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         ctxs->reg[reg].arg = reg2;
3156ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (di->ddump_frames)
3157ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            VG_(printf)("  DW_CFA_register: r%d in r%d\n",
3158ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        (Int)reg, (Int)reg2);
3159ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         break;
3160ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3161ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case DW_CFA_offset_extended:
3162436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         reg = step_leb128( &instr, 0 );
3163436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         off = step_leb128( &instr, 0 );
3164ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (reg < 0 || reg >= N_CFI_REGS)
3165ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            return 0; /* fail */
3166ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         ctxs->reg[reg].tag = RR_CFAOff;
3167ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         ctxs->reg[reg].arg = off * ctx->data_a_f;
3168ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (di->ddump_frames)
3169ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            VG_(printf)("  rci:DW_CFA_offset_extended\n");
3170ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         break;
3171ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3172ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case DW_CFA_offset_extended_sf:
3173436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         reg = step_leb128( &instr, 0 );
3174436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         off = step_leb128( &instr, 1 );
3175ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (reg < 0 || reg >= N_CFI_REGS)
3176ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            return 0; /* fail */
3177ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         ctxs->reg[reg].tag = RR_CFAOff;
3178ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         ctxs->reg[reg].arg = off * ctx->data_a_f;
3179ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (di->ddump_frames)
3180ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            VG_(printf)("  DW_CFA_offset_extended_sf: r%d at cfa%s%d\n",
3181ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        reg,
3182ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        ctxs->reg[reg].arg < 0 ? "" : "+",
3183ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        (Int)ctxs->reg[reg].arg);
3184ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         break;
3185ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3186ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case DW_CFA_GNU_negative_offset_extended:
3187436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         reg = step_leb128( &instr, 0 );
3188436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         off = step_leb128( &instr, 0 );
3189ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (reg < 0 || reg >= N_CFI_REGS)
3190ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            return 0; /* fail */
3191ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         ctxs->reg[reg].tag = RR_CFAOff;
3192ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         ctxs->reg[reg].arg = (-off) * ctx->data_a_f;
3193ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (di->ddump_frames)
3194ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            VG_(printf)("  rci:DW_CFA_GNU_negative_offset_extended\n");
3195ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         break;
3196ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3197ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case DW_CFA_restore_extended:
3198436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         reg = step_leb128( &instr, 0 );
3199ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (reg < 0 || reg >= N_CFI_REGS)
3200ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            return 0; /* fail */
3201ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	 if (restore_ctx == NULL)
3202ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	    return 0; /* fail */
3203ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	 ctxs->reg[reg] = restore_ctx->state[restore_ctx->state_sp].reg[reg];
3204ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (di->ddump_frames)
3205ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            VG_(printf)("  rci:DW_CFA_restore_extended\n");
3206ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         break;
3207ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3208ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case DW_CFA_val_offset:
3209436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         reg = step_leb128( &instr, 0 );
3210436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         off = step_leb128( &instr, 0 );
3211ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (reg < 0 || reg >= N_CFI_REGS)
3212ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            return 0; /* fail */
3213ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         ctxs->reg[reg].tag = RR_CFAValOff;
3214ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         ctxs->reg[reg].arg = off * ctx->data_a_f;
3215ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (di->ddump_frames)
3216ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            VG_(printf)("  rci:DW_CFA_val_offset\n");
3217ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         break;
3218ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3219ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case DW_CFA_val_offset_sf:
3220436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         reg = step_leb128( &instr, 0 );
3221436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         off = step_leb128( &instr, 1 );
3222ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (reg < 0 || reg >= N_CFI_REGS)
3223ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            return 0; /* fail */
3224ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         ctxs->reg[reg].tag = RR_CFAValOff;
3225ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         ctxs->reg[reg].arg = off * ctx->data_a_f;
3226ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (di->ddump_frames)
3227ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            VG_(printf)("  rci:DW_CFA_val_offset_sf\n");
3228ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         break;
3229ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3230ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case DW_CFA_def_cfa_register:
3231436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         reg = step_leb128( &instr, 0);
3232ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (reg < 0 || reg >= N_CFI_REGS)
3233ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            return 0; /* fail */
3234ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         ctxs->cfa_is_regoff = True;
3235ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         ctxs->cfa_expr_ix   = 0;
3236ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         ctxs->cfa_reg       = reg;
3237ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* ->cfa_off unchanged */
3238ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (di->ddump_frames)
3239ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            VG_(printf)("  DW_CFA_def_cfa_register: r%d\n", (Int)reg );
3240ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         break;
3241ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3242ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case DW_CFA_def_cfa_offset:
3243436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         off = step_leb128( &instr, 0);
3244ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         ctxs->cfa_is_regoff = True;
3245ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         ctxs->cfa_expr_ix   = 0;
3246ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* ->reg is unchanged */
3247ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         ctxs->cfa_off       = off;
3248ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (di->ddump_frames)
3249ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            VG_(printf)("  DW_CFA_def_cfa_offset: %d\n", (Int)off);
3250ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         break;
3251ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3252ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case DW_CFA_def_cfa_offset_sf:
3253436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         off = step_leb128( &instr, 1);
3254ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         ctxs->cfa_is_regoff = True;
3255ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         ctxs->cfa_expr_ix   = 0;
3256ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* ->reg is unchanged */
3257ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         ctxs->cfa_off       = off * ctx->data_a_f;
3258ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (di->ddump_frames)
3259ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            VG_(printf)("  DW_CFA_def_cfa_offset_sf: %d\n", ctxs->cfa_off);
3260ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         break;
3261ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3262ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case DW_CFA_undefined:
3263436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         reg = step_leb128( &instr, 0);
3264ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (reg < 0 || reg >= N_CFI_REGS)
3265ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            return 0; /* fail */
3266ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         ctxs->reg[reg].tag = RR_Undef;
3267ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         ctxs->reg[reg].arg = 0;
3268ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (di->ddump_frames)
3269ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            VG_(printf)("  rci:DW_CFA_undefined\n");
3270ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         break;
3271ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3272ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case DW_CFA_same_value:
3273436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         reg = step_leb128( &instr, 0);
3274ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (reg < 0 || reg >= N_CFI_REGS)
3275ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            return 0; /* fail */
3276ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         ctxs->reg[reg].tag = RR_Same;
3277ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         ctxs->reg[reg].arg = 0;
3278ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (di->ddump_frames)
3279ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            VG_(printf)("  rci:DW_CFA_same_value\n");
3280ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         break;
3281ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3282ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case DW_CFA_GNU_args_size:
3283ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* No idea what is supposed to happen.  gdb-6.3 simply
3284ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            ignores these. */
3285436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         /*off = */ (void)step_leb128( &instr, 0 );
3286ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (di->ddump_frames)
3287ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            VG_(printf)("  rci:DW_CFA_GNU_args_size (ignored)\n");
3288ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         break;
3289ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3290436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      case DW_CFA_expression: {
3291ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* Identical to DW_CFA_val_expression except that the value
3292ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            computed is an address and so needs one final
3293ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            dereference. */
3294436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         DiCursor expr;
3295436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         reg = step_leb128( &instr, 0 );
3296436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         len = step_leb128( &instr, 0 );
3297436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         expr = instr;
3298436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         instr = ML_(cur_plus)(instr, len);
3299ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (reg < 0 || reg >= N_CFI_REGS)
3300ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            return 0; /* fail */
3301ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (di->ddump_frames)
3302ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            VG_(printf)("  DW_CFA_expression: r%d (",
3303ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        (Int)reg);
3304ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* Convert the expression into a dag rooted at ctx->exprs index j,
3305ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            or fail. */
3306ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         j = dwarfexpr_to_dag ( ctx, expr, len, True/*push CFA at start*/,
3307ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                di->ddump_frames);
3308ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (di->ddump_frames)
3309ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            VG_(printf)(")\n");
3310ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         vg_assert(j >= -1);
3311ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (j >= 0) {
3312ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            vg_assert(ctx->exprs);
3313ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            vg_assert( j < VG_(sizeXA)(ctx->exprs) );
3314ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
3315ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (j == -1)
3316ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            return 0; /* fail */
3317ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* Add an extra dereference */
3318ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         j = ML_(CfiExpr_Deref)( ctx->exprs, j );
3319ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         ctxs->reg[reg].tag = RR_ValExpr;
3320ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         ctxs->reg[reg].arg = j;
3321ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         break;
3322436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      }
3323ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3324436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      case DW_CFA_val_expression: {
3325436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         DiCursor expr;
3326436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         reg = step_leb128( &instr, 0 );
3327436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         len = step_leb128( &instr, 0 );
3328436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         expr = instr;
3329436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         instr = ML_(cur_plus)(instr, len);
3330ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (reg < 0 || reg >= N_CFI_REGS)
3331ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            return 0; /* fail */
3332ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (di->ddump_frames)
3333ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            VG_(printf)("  DW_CFA_val_expression: r%d (",
3334ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        (Int)reg);
3335ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* Convert the expression into a dag rooted at ctx->exprs index j,
3336ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            or fail. */
3337ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         j = dwarfexpr_to_dag ( ctx, expr, len, True/*push CFA at start*/,
3338ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                di->ddump_frames);
3339ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (di->ddump_frames)
3340ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            VG_(printf)(")\n");
3341ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         vg_assert(j >= -1);
3342ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (j >= 0) {
3343ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            vg_assert(ctx->exprs);
3344ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            vg_assert( j < VG_(sizeXA)(ctx->exprs) );
3345ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
3346ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (j == -1)
3347ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            return 0; /* fail */
3348ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         ctxs->reg[reg].tag = RR_ValExpr;
3349ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         ctxs->reg[reg].arg = j;
3350ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         break;
3351436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      }
3352ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3353436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      case DW_CFA_def_cfa_expression: {
3354436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         DiCursor expr;
3355436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         len = step_leb128( &instr, 0 );
3356436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         expr = instr;
3357436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         instr = ML_(cur_plus)(instr, len);
3358ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (di->ddump_frames)
3359ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            VG_(printf)("  DW_CFA_def_cfa_expression (");
3360ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* Convert the expression into a dag rooted at ctx->exprs index j,
3361ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            or fail. */
3362ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         j = dwarfexpr_to_dag ( ctx, expr, len, True/*push CFA at start*/,
3363ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                di->ddump_frames);
3364ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (di->ddump_frames)
3365ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            VG_(printf)(")\n");
3366ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         ctxs->cfa_is_regoff = False;
3367ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         ctxs->cfa_reg       = 0;
3368ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         ctxs->cfa_off       = 0;
3369ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         ctxs->cfa_expr_ix   = j;
3370ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         break;
3371436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      }
3372ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3373ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case DW_CFA_GNU_window_save:
3374ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* Ignored.  This appears to be sparc-specific; quite why it
3375ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            turns up in SuSE-supplied x86 .so's beats me. */
3376ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (di->ddump_frames)
3377ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            VG_(printf)("  DW_CFA_GNU_window_save\n");
3378ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         break;
3379ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3380ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case DW_CFA_remember_state:
3381ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (di->ddump_frames)
3382ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            VG_(printf)("  DW_CFA_remember_state\n");
3383ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* we just checked this at entry, so: */
3384ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         vg_assert(ctx->state_sp >= 0 && ctx->state_sp < N_RR_STACK);
3385ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         ctx->state_sp++;
3386ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (ctx->state_sp == N_RR_STACK) {
3387ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            /* stack overflow.  We're hosed. */
3388ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            VG_(message)(Vg_DebugMsg, "DWARF2 CFI reader: N_RR_STACK is "
3389ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                      "too low; increase and recompile.");
3390436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            return 0; /* indicate failure */
3391ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         } else {
3392ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            VG_(memcpy)(/*dst*/&ctx->state[ctx->state_sp],
3393ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        /*src*/&ctx->state[ctx->state_sp - 1],
3394ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        sizeof(ctx->state[ctx->state_sp]) );
3395ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
3396ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         break;
3397ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3398ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case DW_CFA_restore_state:
3399ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (di->ddump_frames)
3400ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            VG_(printf)("  DW_CFA_restore_state\n");
3401ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* we just checked this at entry, so: */
3402ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         vg_assert(ctx->state_sp >= 0 && ctx->state_sp < N_RR_STACK);
3403ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (ctx->state_sp == 0) {
3404436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            /* stack undefflow.  Give up. */
3405436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            return 0; /* indicate failure */
3406ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         } else {
3407ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            /* simply fall back to previous entry */
3408ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            ctx->state_sp--;
3409ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
3410ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         break;
3411ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3412ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      default:
3413ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         VG_(message)(Vg_DebugMsg, "DWARF2 CFI reader: unhandled CFI "
3414ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                   "instruction 0:%d\n", (Int)lo6);
3415ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (di->ddump_frames)
3416ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            VG_(printf)("  rci:run_CF_instruction:default\n");
3417436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         return 0; /* failure */
3418436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         /*NOTREACHED*/
3419ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
3420ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3421436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   return ML_(cur_minus)(instr, instrIN);
3422ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
3423ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3424ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3425ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Show a CFI instruction, and also return its length.  Show it as
3426ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   close as possible (preferably identical) to how GNU binutils
3427ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   readelf --debug-dump=frames would. */
3428ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3429436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanovstatic Int show_CF_instruction ( DiCursor instrIN,
3430ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                 AddressDecodingInfo* adi,
3431ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                 Int code_a_f, Int data_a_f )
3432ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
3433436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   Int      off, coff, reg, reg2, len;
3434436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   UInt     delta;
3435436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   Addr     loc;
3436436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   DiCursor instr   = instrIN;
3437436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   UChar    instr_0 = ML_(cur_step_UChar)(&instr);
3438436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   UChar    hi2     = (instr_0 >> 6) & 3;
3439436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   UChar    lo6     = instr_0 & 0x3F;
3440436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov
3441436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   if (0) {
3442436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      DiCursor tmpi = instrIN;
3443436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      UInt i_0 = ML_(cur_step_UChar)(&tmpi);
3444436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      UInt i_1 = ML_(cur_step_UChar)(&tmpi);
3445436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      UInt i_2 = ML_(cur_step_UChar)(&tmpi);
3446436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      UInt i_3 = ML_(cur_step_UChar)(&tmpi);
3447436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      UInt i_4 = ML_(cur_step_UChar)(&tmpi);
3448436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      UInt i_5 = ML_(cur_step_UChar)(&tmpi);
3449436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      UInt i_6 = ML_(cur_step_UChar)(&tmpi);
3450436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      UInt i_7 = ML_(cur_step_UChar)(&tmpi);
3451436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      VG_(printf)("raw:%x/%x:%x:%x:%x:%x:%x:%x:%x:%x\n",
3452436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov                  hi2, lo6, i_0, i_1, i_2, i_3, i_4, i_5, i_6, i_7);
3453436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   }
3454ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3455ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (hi2 == DW_CFA_advance_loc) {
3456ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      VG_(printf)("  sci:DW_CFA_advance_loc(%d)\n", (Int)lo6);
3457436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      return ML_(cur_minus)(instr, instrIN);
3458ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
3459ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3460ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (hi2 == DW_CFA_offset) {
3461436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      off = step_leb128( &instr, 0 );
3462ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      coff = off * data_a_f;
3463ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      VG_(printf)("  DW_CFA_offset: r%d at cfa%s%d\n",
3464ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  (Int)lo6, coff < 0 ? "" : "+", (Int)coff );
3465436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      return ML_(cur_minus)(instr, instrIN);
3466ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
3467ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3468ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (hi2 == DW_CFA_restore) {
3469ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      VG_(printf)("  sci:DW_CFA_restore(r%d)\n", (Int)lo6);
3470436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      return ML_(cur_minus)(instr, instrIN);
3471ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
3472ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3473ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vg_assert(hi2 == DW_CFA_use_secondary);
3474ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3475ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   switch (lo6) {
3476ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3477ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case DW_CFA_nop:
3478ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         VG_(printf)("  DW_CFA_nop\n");
3479ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         break;
3480ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3481ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case DW_CFA_set_loc:
3482ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* WAS: loc = read_Addr(&instr[i]); i+= sizeof(Addr);
3483ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            (now known to be incorrect -- the address is encoded) */
3484436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         loc = step_encoded_Addr(adi, &instr);
3485ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         VG_(printf)("  sci:DW_CFA_set_loc(%#lx)\n", loc);
3486ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         break;
3487ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3488ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case DW_CFA_advance_loc1:
3489436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         delta = (UInt)ML_(cur_step_UChar)(&instr);
3490ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         VG_(printf)("  sci:DW_CFA_advance_loc1(%d)\n", delta);
3491ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         break;
3492ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3493ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case DW_CFA_advance_loc2:
3494436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         delta = (UInt)ML_(cur_step_UShort)(&instr);
3495ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         VG_(printf)("  sci:DW_CFA_advance_loc2(%d)\n", delta);
3496ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         break;
3497ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3498ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case DW_CFA_advance_loc4:
3499436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         delta = (UInt)ML_(cur_step_UInt)(&instr);
3500ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         VG_(printf)("  DW_CFA_advance_loc4(%d)\n", delta);
3501ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         break;
3502ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3503ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case DW_CFA_def_cfa:
3504436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         reg = step_leb128( &instr, 0 );
3505436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         off = step_leb128( &instr, 0 );
3506ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         VG_(printf)("  DW_CFA_def_cfa: r%d ofs %d\n", (Int)reg, (Int)off);
3507ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         break;
3508ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3509ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case DW_CFA_def_cfa_sf:
3510436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         reg = step_leb128( &instr, 0 );
3511436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         off = step_leb128( &instr, 1 );
3512ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         VG_(printf)("  DW_CFA_def_cfa_sf: r%d ofs %d\n",
3513ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     (Int)reg, (Int)(off * data_a_f));
3514ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         break;
3515ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3516ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case DW_CFA_register:
3517436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         reg  = step_leb128( &instr, 0);
3518436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         reg2 = step_leb128( &instr, 0);
3519ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         VG_(printf)("  sci:DW_CFA_register(r%d, r%d)\n", reg, reg2);
3520ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         break;
3521ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3522ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case DW_CFA_def_cfa_register:
3523436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         reg = step_leb128( &instr, 0);
3524ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         VG_(printf)("  sci:DW_CFA_def_cfa_register(r%d)\n", reg);
3525ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         break;
3526ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3527ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case DW_CFA_def_cfa_offset:
3528436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         off = step_leb128( &instr, 0);
3529ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         VG_(printf)("  sci:DW_CFA_def_cfa_offset(%d)\n", off);
3530ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         break;
3531ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3532ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case DW_CFA_def_cfa_offset_sf:
3533436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         off = step_leb128( &instr, 1);
3534ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         VG_(printf)("  sci:DW_CFA_def_cfa_offset_sf(%d)\n", off);
3535ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         break;
3536ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3537ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case DW_CFA_restore_extended:
3538436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         reg = step_leb128( &instr, 0);
3539ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         VG_(printf)("  sci:DW_CFA_restore_extended(r%d)\n", reg);
3540ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         break;
3541ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3542ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case DW_CFA_undefined:
3543436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         reg = step_leb128( &instr, 0);
3544ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         VG_(printf)("  sci:DW_CFA_undefined(r%d)\n", reg);
3545ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         break;
3546ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3547ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case DW_CFA_same_value:
3548436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         reg = step_leb128( &instr, 0);
3549ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         VG_(printf)("  sci:DW_CFA_same_value(r%d)\n", reg);
3550ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         break;
3551ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3552ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case DW_CFA_remember_state:
3553ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         VG_(printf)("  sci:DW_CFA_remember_state\n");
3554ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         break;
3555ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3556ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case DW_CFA_restore_state:
3557ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         VG_(printf)("  sci:DW_CFA_restore_state\n");
3558ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         break;
3559ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3560ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case DW_CFA_GNU_args_size:
3561436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         off = step_leb128( &instr, 0 );
3562ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         VG_(printf)("  sci:DW_CFA_GNU_args_size(%d)\n", off );
3563ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         break;
3564ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3565ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case DW_CFA_def_cfa_expression:
3566436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         len = step_leb128( &instr, 0 );
3567436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         instr = ML_(cur_plus)(instr, len);
3568ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         VG_(printf)("  sci:DW_CFA_def_cfa_expression(length %d)\n", len);
3569ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         break;
3570ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3571ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case DW_CFA_expression:
3572436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         reg = step_leb128( &instr, 0 );
3573436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         len = step_leb128( &instr, 0 );
3574436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         instr = ML_(cur_plus)(instr, len);
3575ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         VG_(printf)("  sci:DW_CFA_expression(r%d, length %d)\n", reg, len);
3576ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         break;
3577ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3578ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case DW_CFA_val_expression:
3579436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         reg = step_leb128( &instr, 0 );
3580436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         len = step_leb128( &instr, 0 );
3581436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         instr = ML_(cur_plus)(instr, len);
3582ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         VG_(printf)("  sci:DW_CFA_val_expression(r%d, length %d)\n", reg, len);
3583ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         break;
3584ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3585ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case DW_CFA_offset_extended:
3586436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         reg = step_leb128( &instr, 0 );
3587436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         off = step_leb128( &instr, 0 );
3588ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         VG_(printf)("  sci:DW_CFA_offset_extended(r%d, "
3589ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     "off %d x data_af)\n", reg, off);
3590ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         break;
3591ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3592ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case DW_CFA_offset_extended_sf:
3593436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         reg = step_leb128( &instr, 0 );
3594436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         off = step_leb128( &instr, 1 );
3595ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	 coff = (Int)(off * data_a_f);
3596ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         VG_(printf)("  DW_CFA_offset_extended_sf: r%d at cfa%s%d\n",
3597ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        reg, coff < 0 ? "" : "+", coff);
3598ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         break;
3599ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3600ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case DW_CFA_GNU_negative_offset_extended:
3601436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         reg = step_leb128( &instr, 0 );
3602436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         off = step_leb128( &instr, 0 );
3603ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         VG_(printf)("  sci:DW_CFA_GNU_negative_offset_extended"
3604ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     "(r%d, off %d x data_af)\n", reg, -off);
3605ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         break;
3606ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3607ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case DW_CFA_val_offset:
3608436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         reg = step_leb128( &instr, 0 );
3609436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         off = step_leb128( &instr, 0 );
3610ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         VG_(printf)("  sci:DW_CFA_val_offset(r%d, off %d x data_af)\n",
3611ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     reg, off);
3612ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         break;
3613ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3614ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown       case DW_CFA_val_offset_sf:
3615436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         reg = step_leb128( &instr, 0 );
3616436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         off = step_leb128( &instr, 1 );
3617ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         VG_(printf)("  sci:DW_CFA_val_offset_sf(r%d, off %d x data_af)\n",
3618ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     reg, off);
3619ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         break;
3620ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3621ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case DW_CFA_GNU_window_save:
3622ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         VG_(printf)("  sci:DW_CFA_GNU_window_save\n");
3623ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         break;
3624ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3625ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      default:
3626ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         VG_(printf)("  sci:0:%d\n", (Int)lo6);
3627ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         break;
3628ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
3629ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3630436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   return ML_(cur_minus)(instr, instrIN);
3631ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
3632ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3633ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3634ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Show the instructions in instrs[0 .. ilen-1]. */
3635436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanovstatic void show_CF_instructions ( DiCursor instrs, Int ilen,
3636ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                   AddressDecodingInfo* adi,
3637ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                   Int code_a_f, Int data_a_f )
3638ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
3639ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Int i = 0;
3640ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   while (True) {
3641ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (i >= ilen) break;
3642436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      i += show_CF_instruction( ML_(cur_plus)(instrs, i),
3643436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov                                adi, code_a_f, data_a_f );
3644ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
3645ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
3646ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3647ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3648ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Run the CF instructions in instrs[0 .. ilen-1], until the end is
3649ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   reached, or until there is a failure.  Return True iff success.
3650ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown*/
3651ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic
3652ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownBool run_CF_instructions ( struct _DebugInfo* di,
3653ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                           Bool record,
3654436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov                           UnwindContext* ctx, DiCursor instrs, Int ilen,
3655ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                           UWord fde_arange,
3656ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                           UnwindContext* restore_ctx,
3657ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                           AddressDecodingInfo* adi )
3658ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
3659ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   DiCfSI cfsi;
3660ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Bool summ_ok;
3661ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Int j, i = 0;
3662ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Addr loc_prev;
3663ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (0) ppUnwindContext(ctx);
3664ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (0) ppUnwindContext_summary(ctx);
3665ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   while (True) {
3666ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      loc_prev = ctx->loc;
3667ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (i >= ilen) break;
3668436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      if (0) (void)show_CF_instruction( ML_(cur_plus)(instrs,i), adi,
3669ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                        ctx->code_a_f, ctx->data_a_f );
3670436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      j = run_CF_instruction( ctx, ML_(cur_plus)(instrs,i),
3671436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov                              restore_ctx, adi, di );
3672ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (j == 0)
3673ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return False; /* execution failed */
3674ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      i += j;
3675ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (0) ppUnwindContext(ctx);
3676ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (record && loc_prev != ctx->loc) {
3677ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         summ_ok = summarise_context ( &cfsi, loc_prev, ctx, di );
3678ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (summ_ok) {
3679ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            ML_(addDiCfSI)(di, &cfsi);
3680ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            if (di->trace_cfi)
3681ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               ML_(ppDiCfSI)(di->cfsi_exprs, &cfsi);
3682ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
3683ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
3684ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
3685ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (ctx->loc < fde_arange) {
3686ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      loc_prev = ctx->loc;
3687ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      ctx->loc = fde_arange;
3688ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (record) {
3689ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         summ_ok = summarise_context ( &cfsi, loc_prev, ctx, di );
3690ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (summ_ok) {
3691ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            ML_(addDiCfSI)(di, &cfsi);
3692ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            if (di->trace_cfi)
3693ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               ML_(ppDiCfSI)(di->cfsi_exprs, &cfsi);
3694ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
3695ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
3696ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
3697ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return True;
3698ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
3699ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3700ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3701ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* ------------ Main entry point for CFI reading ------------ */
3702ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3703ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Browntypedef
3704ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   struct {
3705ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* This gives the CIE an identity to which FDEs will refer. */
3706436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      ULong    offset;
3707ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* Code, data factors. */
3708436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      Int      code_a_f;
3709436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      Int      data_a_f;
3710ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* Return-address pseudo-register. */
3711436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      Int      ra_reg;
3712436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      UChar    address_encoding;
3713436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      /* Where are the instrs? */
3714436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      DiCursor instrs;
3715436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      Int      ilen;
3716ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* God knows .. don't ask */
3717436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      Bool     saw_z_augmentation;
3718ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
3719ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   CIE;
3720ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3721ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic void init_CIE ( CIE* cie )
3722ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
3723ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   cie->offset             = 0;
3724ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   cie->code_a_f           = 0;
3725ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   cie->data_a_f           = 0;
3726ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   cie->ra_reg             = 0;
3727ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   cie->address_encoding   = 0;
3728436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   cie->instrs             = DiCursor_INVALID;
3729ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   cie->ilen               = 0;
3730ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   cie->saw_z_augmentation = False;
3731ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
3732ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3733436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov#define N_CIEs 8000
3734ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic CIE the_CIEs[N_CIEs];
3735ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3736ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3737b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov/* Read, summarise and store CFA unwind info from .eh_frame and
3738b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   .debug_frame sections.  is_ehframe tells us which kind we are
3739b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   dealing with -- they are slightly different. */
3740ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid ML_(read_callframe_info_dwarf3)
3741b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov        ( /*OUT*/struct _DebugInfo* di,
3742436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov          DiSlice escn_frame, Addr frame_avma, Bool is_ehframe )
3743ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
3744436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   const HChar* how = NULL;
3745436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   Int      n_CIEs = 0;
3746436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   DiCursor frame_image = ML_(cur_from_sli)(escn_frame); /* fixed */
3747436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   DiOffT   frame_size  = escn_frame.szB;
3748436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   DiCursor data        = frame_image;
3749436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   UWord    cfsi_used_orig;
3750b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
3751b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   /* If we're dealing with a .debug_frame, assume zero frame_avma. */
3752b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   if (!is_ehframe)
3753b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      vg_assert(frame_avma == 0);
3754ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3755ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#  if defined(VGP_ppc32_linux) || defined(VGP_ppc64_linux)
3756ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* These targets don't use CFI-based stack unwinding.  */
3757ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return;
3758ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#  endif
3759ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3760b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   /* If we read more than one .debug_frame or .eh_frame for this
3761b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      DebugInfo*, the second and subsequent reads should only add FDEs
3762b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      for address ranges not already covered by the FDEs already
3763b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      present.  To be able to quickly check which address ranges are
3764b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      already present, any existing records (DiCFSIs) must be sorted,
3765b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      so we can binary-search them in the code below.  We also record
3766b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      di->cfsi_used so that we know where the boundary is between
3767b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      existing and new records. */
3768b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   if (di->cfsi_used > 0) {
3769ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      ML_(canonicaliseCFI) ( di );
3770ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
3771b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   cfsi_used_orig = di->cfsi_used;
3772ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3773ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (di->trace_cfi) {
3774ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      VG_(printf)("\n-----------------------------------------------\n");
3775436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      VG_(printf)("CFI info: szB %lld, _avma %#lx\n",
3776436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov                  escn_frame.szB, frame_avma );
3777436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      VG_(printf)("CFI info: name %s\n", di->fsm.filename );
3778ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
3779ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3780ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* Loop over CIEs/FDEs */
3781ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3782ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* Conceptually, the frame info is a sequence of FDEs, one for each
3783ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      function.  Inside an FDE is a miniature program for a special
3784ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      state machine, which, when run, produces the stack-unwinding
3785ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      info for that function.
3786ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3787ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      Because the FDEs typically have much in common, and because the
3788ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      DWARF designers appear to have been fanatical about space
3789ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      saving, the common parts are factored out into so-called CIEs.
3790ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      That means that what we traverse is a sequence of structs, each
3791ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      of which is either a FDE (usually) or a CIE (occasionally).
3792ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      Each FDE has a field indicating which CIE is the one pertaining
3793ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      to it.
3794ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3795ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      The following loop traverses the sequence.  FDEs are dealt with
3796ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      immediately; once we harvest the useful info in an FDE, it is
3797ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      then forgotten about.  By contrast, CIEs are validated and
3798ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      dumped into an array, because later FDEs may refer to any
3799ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      previously-seen CIE.
3800ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   */
3801ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   while (True) {
3802436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      DiCursor ciefde_start;
3803436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      ULong    ciefde_len;
3804436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      ULong    cie_pointer;
3805436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      Bool     dw64;
3806ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3807ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* Are we done? */
3808436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      if (ML_(cur_cmpEQ)(data, ML_(cur_plus)(frame_image, frame_size)))
3809ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return;
3810ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3811ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* Overshot the end?  Means something is wrong */
3812436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      if (ML_(cur_cmpGT)(data, ML_(cur_plus)(frame_image, frame_size))) {
3813ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         how = "overran the end of .eh_frame";
3814ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         goto bad;
3815ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
3816ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3817ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* Ok, we must be looking at the start of a new CIE or FDE.
3818ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         Figure out which it is. */
3819ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3820ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      ciefde_start = data;
3821ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (di->trace_cfi)
3822436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         VG_(printf)("\ncie/fde.start   = (frame_image + 0x%llx)\n",
3823436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov                     ML_(cur_minus)(ciefde_start, frame_image));
3824ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3825436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      ciefde_len = (ULong)ML_(cur_step_UInt)(&data);
3826ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (di->trace_cfi)
3827ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         VG_(printf)("cie/fde.length  = %lld\n", ciefde_len);
3828ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3829ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* Apparently, if the .length field is zero, we are at the end
3830ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         of the sequence.  This is stated in the Generic Elf
3831ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         Specification (see comments far above here) and is one of the
3832ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         places where .eh_frame and .debug_frame data differ. */
3833ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (ciefde_len == 0) {
3834ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (di->ddump_frames)
3835436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            VG_(printf)("%08llx ZERO terminator\n\n",
3836436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov                        ML_(cur_minus)(ciefde_start, frame_image));
3837ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return;
3838ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
3839ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3840ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* If the .length field is 0xFFFFFFFF then we're dealing with
3841ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         64-bit DWARF, and the real length is stored as a 64-bit
3842ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         number immediately following it. */
3843ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      dw64 = False;
3844ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (ciefde_len == 0xFFFFFFFFUL) {
3845ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         dw64 = True;
3846436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         ciefde_len = ML_(cur_step_ULong)(&data);
3847ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
3848ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3849ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* Now get the CIE ID, whose size depends on the DWARF 32 vs
3850ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	 64-ness. */
3851ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (dw64) {
3852436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         /* see XXX below */
3853436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         cie_pointer = ML_(cur_step_ULong)(&data);
3854ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      } else {
3855436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         /* see XXX below */
3856436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         cie_pointer = (ULong)ML_(cur_step_UInt)(&data);
3857ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
3858ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3859ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (di->trace_cfi)
3860ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         VG_(printf)("cie.pointer     = %lld\n", cie_pointer);
3861ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3862ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* If cie_pointer is zero for .eh_frame or all ones for .debug_frame,
3863ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         we've got a CIE; else it's an FDE. */
3864b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      if (cie_pointer == (is_ehframe ? 0ULL
3865ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                          : dw64 ? 0xFFFFFFFFFFFFFFFFULL : 0xFFFFFFFFULL)) {
3866ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3867436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         Int      this_CIE;
3868436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         UChar    cie_version;
3869436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         DiCursor cie_augmentation;
3870ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3871ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* --------- CIE --------- */
3872ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	 if (di->trace_cfi)
3873ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            VG_(printf)("------ new CIE (#%d of 0 .. %d) ------\n",
3874ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        n_CIEs, N_CIEs - 1);
3875ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3876ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	 /* Allocate a new CIE record. */
3877ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         vg_assert(n_CIEs >= 0 && n_CIEs <= N_CIEs);
3878ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (n_CIEs == N_CIEs) {
3879ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            how = "N_CIEs is too low.  Increase and recompile.";
3880ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            goto bad;
3881ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
3882ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3883ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         this_CIE = n_CIEs;
3884ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         n_CIEs++;
3885ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         init_CIE( &the_CIEs[this_CIE] );
3886ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3887ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	 /* Record its offset.  This is how we will find it again
3888ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            later when looking at an FDE. */
3889436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         the_CIEs[this_CIE].offset
3890436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            = (ULong)ML_(cur_minus)(ciefde_start, frame_image);
3891ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3892ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (di->ddump_frames)
3893ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            VG_(printf)("%08lx %08lx %08lx CIE\n",
3894436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov                        (Addr)ML_(cur_minus)(ciefde_start, frame_image),
3895ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        (Addr)ciefde_len,
3896ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        (Addr)(UWord)cie_pointer );
3897ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3898436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         cie_version = ML_(cur_step_UChar)(&data);
3899ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (di->trace_cfi)
3900ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            VG_(printf)("cie.version     = %d\n", (Int)cie_version);
3901ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (di->ddump_frames)
3902ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            VG_(printf)("  Version:               %d\n", (Int)cie_version);
3903ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (cie_version != 1 && cie_version != 3 && cie_version != 4) {
3904ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            how = "unexpected CIE version (not 1 nor 3 nor 4)";
3905ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            goto bad;
3906ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
3907ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3908ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         cie_augmentation = data;
3909436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         data = ML_(cur_plus)(data, 1 + ML_(cur_strlen)(cie_augmentation));
3910436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov
3911436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         if (di->trace_cfi || di->ddump_frames) {
3912436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            HChar* str = ML_(cur_read_strdup)(cie_augmentation, "di.rcid3.1");
3913436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            if (di->trace_cfi)
3914436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov               VG_(printf)("cie.augment     = \"%s\"\n", str);
3915436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            if (di->ddump_frames)
3916436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov               VG_(printf)("  Augmentation:          \"%s\"\n", str);
3917436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            ML_(dinfo_free)(str);
3918436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         }
3919ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3920436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         if (ML_(cur_read_UChar)(cie_augmentation) == 'e'
3921436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov             && ML_(cur_read_UChar)
3922436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov                   (ML_(cur_plus)(cie_augmentation, 1)) == 'h') {
3923436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            data = ML_(cur_plus)(data, sizeof(Addr));
3924436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            cie_augmentation = ML_(cur_plus)(cie_augmentation, 2);
3925ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
3926ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3927ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (cie_version >= 4) {
3928436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            if (ML_(cur_step_UChar)(&data) != sizeof(Addr)) {
3929ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               how = "unexpected address size";
3930ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               goto bad;
3931ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            }
3932436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            if (ML_(cur_step_UChar)(&data) != 0) {
3933ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               how = "unexpected non-zero segment size";
3934ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               goto bad;
3935ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            }
3936ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
3937ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3938436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         the_CIEs[this_CIE].code_a_f = step_leb128( &data, 0);
3939ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (di->trace_cfi)
3940ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            VG_(printf)("cie.code_af     = %d\n",
3941ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        the_CIEs[this_CIE].code_a_f);
3942ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (di->ddump_frames)
3943ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            VG_(printf)("  Code alignment factor: %d\n",
3944ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        (Int)the_CIEs[this_CIE].code_a_f);
3945ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3946436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         the_CIEs[this_CIE].data_a_f = step_leb128( &data, 1);
3947ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (di->trace_cfi)
3948ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            VG_(printf)("cie.data_af     = %d\n",
3949ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        the_CIEs[this_CIE].data_a_f);
3950ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (di->ddump_frames)
3951ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            VG_(printf)("  Data alignment factor: %d\n",
3952ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        (Int)the_CIEs[this_CIE].data_a_f);
3953ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3954ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (cie_version == 1) {
3955436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            the_CIEs[this_CIE].ra_reg = (Int)ML_(cur_step_UChar)(&data);
3956ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         } else {
3957436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            the_CIEs[this_CIE].ra_reg = step_leb128( &data, 0);
3958ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
3959ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (di->trace_cfi)
3960ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            VG_(printf)("cie.ra_reg      = %d\n",
3961ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        the_CIEs[this_CIE].ra_reg);
3962ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (di->ddump_frames)
3963ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            VG_(printf)("  Return address column: %d\n",
3964ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        (Int)the_CIEs[this_CIE].ra_reg);
3965ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3966ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (the_CIEs[this_CIE].ra_reg < 0
3967ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown             || the_CIEs[this_CIE].ra_reg >= N_CFI_REGS) {
3968ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            how = "cie.ra_reg has implausible value";
3969ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            goto bad;
3970ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
3971ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3972ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         the_CIEs[this_CIE].saw_z_augmentation
3973436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            = ML_(cur_read_UChar)(cie_augmentation) == 'z';
3974ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (the_CIEs[this_CIE].saw_z_augmentation) {
3975436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            UInt length = step_leb128( &data, 0);
3976436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            the_CIEs[this_CIE].instrs = ML_(cur_plus)(data, length);
3977436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            cie_augmentation = ML_(cur_plus)(cie_augmentation, 1);
3978ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            if (di->ddump_frames) {
3979ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               UInt i;
3980ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               VG_(printf)("  Augmentation data:    ");
3981ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               for (i = 0; i < length; i++)
3982436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov                  VG_(printf)(" %02x", (UInt)ML_(cur_read_UChar)
3983436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov                                                (ML_(cur_plus)(data, i)));
3984ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               VG_(printf)("\n");
3985ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            }
3986ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         } else {
3987436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            the_CIEs[this_CIE].instrs = DiCursor_INVALID;
3988ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
3989ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3990ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         the_CIEs[this_CIE].address_encoding = default_Addr_encoding();
3991ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3992436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         while (ML_(cur_read_UChar)(cie_augmentation)) {
3993436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            switch (ML_(cur_read_UChar)(cie_augmentation)) {
3994ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               case 'L':
3995436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov                  data = ML_(cur_plus)(data, 1);
3996436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov                  cie_augmentation = ML_(cur_plus)(cie_augmentation, 1);
3997ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  break;
3998ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               case 'R':
3999ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  the_CIEs[this_CIE].address_encoding
4000436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov                     = ML_(cur_step_UChar)(&data);
4001436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov                  cie_augmentation = ML_(cur_plus)(cie_augmentation, 1);
4002ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  break;
4003ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               case 'P':
4004436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov                  data = ML_(cur_plus)(data, size_of_encoded_Addr(
4005436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov                                                ML_(cur_read_UChar)(data) ));
4006436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov                  data = ML_(cur_plus)(data, 1);
4007436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov                  cie_augmentation = ML_(cur_plus)(cie_augmentation, 1);
4008ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  break;
4009ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               case 'S':
4010436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov                  cie_augmentation = ML_(cur_plus)(cie_augmentation, 1);
4011ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  break;
4012ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               default:
4013436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov                  if (!ML_(cur_is_valid)(the_CIEs[this_CIE].instrs)) {
4014ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     how = "unhandled cie.augmentation";
4015ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     goto bad;
4016ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  }
4017ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  data = the_CIEs[this_CIE].instrs;
4018ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  goto done_augmentation;
4019ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            }
4020ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
4021ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4022ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        done_augmentation:
4023ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4024ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (di->trace_cfi)
4025ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            VG_(printf)("cie.encoding    = 0x%x\n",
4026ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        the_CIEs[this_CIE].address_encoding);
4027ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4028ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         the_CIEs[this_CIE].instrs = data;
4029436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         the_CIEs[this_CIE].ilen   = ML_(cur_minus)(ciefde_start, data)
4030436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov                                     + (Long)ciefde_len + (Long)sizeof(UInt);
4031ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (di->trace_cfi) {
4032436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            //VG_(printf)("cie.instrs      = %p\n", the_CIEs[this_CIE].instrs);
4033ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            VG_(printf)("cie.ilen        = %d\n", the_CIEs[this_CIE].ilen);
4034ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	 }
4035ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4036ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (the_CIEs[this_CIE].ilen < 0
4037ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown             || the_CIEs[this_CIE].ilen > frame_size) {
4038ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            how = "implausible # cie initial insns";
4039ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            goto bad;
4040ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
4041ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4042436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         data = ML_(cur_plus)(data, the_CIEs[this_CIE].ilen);
4043ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4044ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* Show the CIE's instructions (the preamble for each FDE
4045ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            that uses this CIE). */
4046ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (di->ddump_frames)
4047ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            VG_(printf)("\n");
4048ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4049ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (di->trace_cfi || di->ddump_frames) {
4050ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            AddressDecodingInfo adi;
4051ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            adi.encoding      = the_CIEs[this_CIE].address_encoding;
4052ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            adi.ehframe_image = frame_image;
4053ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            adi.ehframe_avma  = frame_avma;
4054ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            adi.text_bias     = di->text_debug_bias;
4055ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            show_CF_instructions( the_CIEs[this_CIE].instrs,
4056ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                  the_CIEs[this_CIE].ilen, &adi,
4057ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                  the_CIEs[this_CIE].code_a_f,
4058ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                  the_CIEs[this_CIE].data_a_f );
4059ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
4060ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4061ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (di->ddump_frames)
4062ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            VG_(printf)("\n");
4063ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4064ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      } else {
4065ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4066ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         AddressDecodingInfo adi;
4067ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         UnwindContext ctx, restore_ctx;
4068436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         Int      cie;
4069436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         ULong    look_for;
4070436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         Bool     ok;
4071436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         Addr     fde_initloc;
4072436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         UWord    fde_arange;
4073436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         DiCursor fde_instrs;
4074436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         Int      fde_ilen;
4075ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4076ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* --------- FDE --------- */
4077ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4078ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* Find the relevant CIE.  The CIE we want is located
4079ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            cie_pointer bytes back from here. */
4080ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4081ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* re sizeof(UInt) / sizeof(ULong), matches XXX above. */
4082b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         if (is_ehframe)
4083436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            look_for = ML_(cur_minus)(data, frame_image)
4084436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov                       - (dw64 ? sizeof(ULong) : sizeof(UInt))
4085ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                       - cie_pointer;
4086ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         else
4087ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            look_for = cie_pointer;
4088ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4089ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         for (cie = 0; cie < n_CIEs; cie++) {
4090ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            if (0) VG_(printf)("look for %lld   %lld\n",
4091ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                               look_for, the_CIEs[cie].offset );
4092ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            if (the_CIEs[cie].offset == look_for)
4093ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               break;
4094ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	 }
4095ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         vg_assert(cie >= 0 && cie <= n_CIEs);
4096ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (cie == n_CIEs) {
4097ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            how = "FDE refers to not-findable CIE";
4098ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            goto bad;
4099ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	 }
4100ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4101ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         adi.encoding      = the_CIEs[cie].address_encoding;
4102ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         adi.ehframe_image = frame_image;
4103ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         adi.ehframe_avma  = frame_avma;
4104ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         adi.text_bias     = di->text_debug_bias;
4105436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         fde_initloc = step_encoded_Addr(&adi, &data);
4106ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (di->trace_cfi)
4107ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            VG_(printf)("fde.initloc     = %#lx\n", fde_initloc);
4108ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4109ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         adi.encoding      = the_CIEs[cie].address_encoding & 0xf;
4110ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         adi.ehframe_image = frame_image;
4111ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         adi.ehframe_avma  = frame_avma;
4112ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         adi.text_bias     = di->text_debug_bias;
4113ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4114ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* WAS (incorrectly):
4115ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            fde_arange = read_encoded_Addr(&nbytes, &adi, data);
4116ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            data += nbytes;
4117ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            The following corresponds to what binutils/dwarf.c does:
4118ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         */
4119ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         { UInt ptr_size = size_of_encoded_Addr( adi.encoding );
4120ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           switch (ptr_size) {
4121ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown              case 8: case 4: case 2: case 1:
4122ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                 fde_arange
4123436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov                    = (UWord)step_le_u_encoded_literal(&data, ptr_size);
4124ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                 break;
4125ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown              default:
4126ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                 how = "unknown arange field encoding in FDE";
4127ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                 goto bad;
4128ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           }
4129ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
4130ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4131ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (di->trace_cfi)
4132ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            VG_(printf)("fde.arangec     = %#lx\n", fde_arange);
4133ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4134ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (di->ddump_frames)
4135ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            VG_(printf)("%08lx %08lx %08lx FDE cie=%08lx pc=%08lx..%08lx\n",
4136436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov                        (Addr)ML_(cur_minus)(ciefde_start, frame_image),
4137ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        (Addr)ciefde_len,
4138ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        (Addr)(UWord)cie_pointer,
4139ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        (Addr)look_for,
4140ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        ((Addr)fde_initloc) - di->text_debug_bias,
4141ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        ((Addr)fde_initloc) - di->text_debug_bias + fde_arange);
4142ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4143ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (the_CIEs[cie].saw_z_augmentation) {
4144436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            UInt length = step_leb128( &data, 0);
4145ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            if (di->ddump_frames && (length > 0)) {
4146ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               UInt i;
4147ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               VG_(printf)("  Augmentation data:    ");
4148ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               for (i = 0; i < length; i++)
4149436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov                  VG_(printf)(" %02x", (UInt)ML_(cur_read_UChar)
4150436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov                                                (ML_(cur_plus)(data, i)));
4151ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               VG_(printf)("\n\n");
4152ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            }
4153436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            data = ML_(cur_plus)(data, length);
4154ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
4155ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4156ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         fde_instrs = data;
4157436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         fde_ilen   = ML_(cur_minus)(ciefde_start, data)
4158436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov                      + (Long)ciefde_len + (Long)sizeof(UInt);
4159ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (di->trace_cfi) {
4160436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            //VG_(printf)("fde.instrs      = %p\n", fde_instrs);
4161ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            VG_(printf)("fde.ilen        = %d\n", (Int)fde_ilen);
4162ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	 }
4163ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4164ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (fde_ilen < 0 || fde_ilen > frame_size) {
4165ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            how = "implausible # fde insns";
4166ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            goto bad;
4167ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
4168ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4169436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov	 data = ML_(cur_plus)(data, fde_ilen);
4170ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4171b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         /* If this object's DebugInfo* had some DiCFSIs from a
4172b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov            previous .eh_frame or .debug_frame read, we must check
4173b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov            that we're not adding a duplicate. */
4174b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         if (cfsi_used_orig > 0) {
4175ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            Addr a_mid_lo, a_mid_hi;
4176ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            Word mid, size,
4177ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                 lo = 0,
4178b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                 hi = cfsi_used_orig-1;
4179ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            while (True) {
4180ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               /* current unsearched space is from lo to hi, inclusive. */
4181ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               if (lo > hi) break; /* not found */
4182ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               mid      = (lo + hi) / 2;
4183ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               a_mid_lo = di->cfsi[mid].base;
4184ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               size     = di->cfsi[mid].len;
4185ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               a_mid_hi = a_mid_lo + size - 1;
4186ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               vg_assert(a_mid_hi >= a_mid_lo);
4187ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               if (fde_initloc + fde_arange <= a_mid_lo) {
4188ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  hi = mid-1; continue;
4189ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               }
4190ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               if (fde_initloc > a_mid_hi) { lo = mid+1; continue; }
4191ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               break;
4192ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            }
4193ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4194ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            /* The range this .debug_frame FDE covers has been already
4195ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               covered in .eh_frame section.  Don't add it from .debug_frame
4196ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               section again.  */
4197ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            if (lo <= hi)
4198ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               continue;
4199ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
4200ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4201ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         adi.encoding      = the_CIEs[cie].address_encoding;
4202ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         adi.ehframe_image = frame_image;
4203ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         adi.ehframe_avma  = frame_avma;
4204ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         adi.text_bias     = di->text_debug_bias;
4205ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4206ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (di->trace_cfi)
4207ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            show_CF_instructions( fde_instrs, fde_ilen, &adi,
4208ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                  the_CIEs[cie].code_a_f,
4209ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                  the_CIEs[cie].data_a_f );
4210ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4211ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	 initUnwindContext(&ctx);
4212ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         ctx.code_a_f = the_CIEs[cie].code_a_f;
4213ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         ctx.data_a_f = the_CIEs[cie].data_a_f;
4214ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         ctx.initloc  = fde_initloc;
4215ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         ctx.ra_reg   = the_CIEs[cie].ra_reg;
4216ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         ctx.exprs    = VG_(newXA)( ML_(dinfo_zalloc), "di.rcid.1",
4217ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                    ML_(dinfo_free),
4218ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                    sizeof(CfiExpr) );
4219ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         vg_assert(ctx.exprs);
4220ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4221ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	 /* Run the CIE's instructions.  Ugly hack: if
4222ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            --debug-dump=frames is in effect, suppress output for
4223ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            these instructions since they will already have been shown
4224ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            at the time the CIE was first encountered.  Note, not
4225ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            thread safe - if this reader is ever made threaded, should
4226ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            fix properly. */
4227ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	 { Bool hack = di->ddump_frames;
4228ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           di->ddump_frames = False;
4229ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           initUnwindContext(&restore_ctx);
4230ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           ok = run_CF_instructions(
4231ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                   di, False, &ctx, the_CIEs[cie].instrs,
4232ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                   the_CIEs[cie].ilen, 0, NULL, &adi
4233ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                );
4234ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           di->ddump_frames = hack;
4235ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
4236ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* And now run the instructions for the FDE, starting from
4237ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            the state created by running the CIE preamble
4238ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            instructions. */
4239ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (ok) {
4240ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            restore_ctx = ctx;
4241ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	    ok = run_CF_instructions(
4242ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    di, True, &ctx, fde_instrs, fde_ilen, fde_arange,
4243ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    &restore_ctx, &adi
4244ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                 );
4245ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            if (di->ddump_frames)
4246ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               VG_(printf)("\n");
4247ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	 }
4248ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4249ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         VG_(deleteXA)( ctx.exprs );
4250ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
4251ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
4252ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4253ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return;
4254ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4255ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   bad:
4256ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    if (!VG_(clo_xml) && VG_(clo_verbosity) > 1)
4257ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown       VG_(message)(Vg_UserMsg,
4258ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    "Warning: %s in DWARF2 CFI reading\n", how);
4259ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    return;
4260ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
4261ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4262ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#endif // defined(VGO_linux) || defined(VGO_darwin)
4263ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4264ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--------------------------------------------------------------------*/
4265ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--- end                                                          ---*/
4266ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--------------------------------------------------------------------*/
4267