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