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