1ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--------------------------------------------------------------------*/ 2ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--- Callgrind ---*/ 3ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--- ct_fn.c ---*/ 4ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--------------------------------------------------------------------*/ 5ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 6ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* 7ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown This file is part of Callgrind, a Valgrind tool for call tracing. 8ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 9436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov Copyright (C) 2002-2013, Josef Weidendorfer (Josef.Weidendorfer@gmx.de) 10ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 11ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown This program is free software; you can redistribute it and/or 12ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown modify it under the terms of the GNU General Public License as 13ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown published by the Free Software Foundation; either version 2 of the 14ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown License, or (at your option) any later version. 15ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 16ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown This program is distributed in the hope that it will be useful, but 17ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown WITHOUT ANY WARRANTY; without even the implied warranty of 18ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 19ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown General Public License for more details. 20ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 21ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown You should have received a copy of the GNU General Public License 22ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown along with this program; if not, write to the Free Software 23ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 24ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 02111-1307, USA. 25ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 26ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown The GNU General Public License is contained in the file COPYING. 27ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown*/ 28ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 29ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "global.h" 30ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 31ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define N_INITIAL_FN_ARRAY_SIZE 10071 32ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 33ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic fn_array current_fn_active; 34ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 35ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic Addr runtime_resolve_addr = 0; 36ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic int runtime_resolve_length = 0; 37ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 38ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// a code pattern is a list of tuples (start offset, length) 39ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstruct chunk_t { int start, len; }; 40ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstruct pattern 41ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 42436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov const HChar* name; 43ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown int len; 44ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown struct chunk_t chunk[]; 45ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}; 46ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 47ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Scan for a pattern in the code of an ELF object. 48ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown * If found, return true and set runtime_resolve_{addr,length} 49ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown */ 50ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown__attribute__((unused)) // Possibly; depends on the platform. 51ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic Bool check_code(obj_node* obj, 52436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov UChar code[], struct pattern* pat) 53ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 54ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Bool found; 55ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Addr addr, end; 56ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown int chunk, start, len; 57ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 58ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* first chunk of pattern should always start at offset 0 and 59ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown * have at least 3 bytes */ 60ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown CLG_ASSERT((pat->chunk[0].start == 0) && (pat->chunk[0].len >2)); 61ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 62ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown CLG_DEBUG(1, "check_code: %s, pattern %s, check %d bytes of [%x %x %x...]\n", 63ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown obj->name, pat->name, pat->chunk[0].len, code[0], code[1], code[2]); 64ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 65ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown end = obj->start + obj->size - pat->len; 66ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addr = obj->start; 67ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown while(addr < end) { 68ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown found = (VG_(memcmp)( (void*)addr, code, pat->chunk[0].len) == 0); 69ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 70ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (found) { 71ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown chunk = 1; 72ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown while(1) { 73ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown start = pat->chunk[chunk].start; 74ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown len = pat->chunk[chunk].len; 75ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (len == 0) break; 76ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 77ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown CLG_ASSERT(len >2); 78ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown CLG_DEBUG(1, " found chunk %d at %#lx, checking %d bytes " 79ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown "of [%x %x %x...]\n", 80ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown chunk-1, addr - obj->start, len, 81ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown code[start], code[start+1], code[start+2]); 82ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 83ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (VG_(memcmp)( (void*)(addr+start), code+start, len) != 0) { 84ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown found = False; 85ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown break; 86ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 87ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown chunk++; 88ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 89ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 90ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (found) { 91ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown CLG_DEBUG(1, "found at offset %#lx.\n", addr - obj->start); 92ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (VG_(clo_verbosity) > 1) 93ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(message)(Vg_DebugMsg, "Found runtime_resolve (%s): " 94ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown "%s +%#lx=%#lx, length %d\n", 95ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown pat->name, obj->name + obj->last_slash_pos, 96ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addr - obj->start, addr, pat->len); 97ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 98ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown runtime_resolve_addr = addr; 99ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown runtime_resolve_length = pat->len; 100ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return True; 101ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 102ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 103ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addr++; 104ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 105ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown CLG_DEBUG(1, " found nothing.\n"); 106ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return False; 107ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 108ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 109ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 110ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* _ld_runtime_resolve, located in ld.so, needs special handling: 111ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown * The jump at end into the resolved function should not be 112ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown * represented as a call (as usually done in callgrind with jumps), 113ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown * but as a return + call. Otherwise, the repeated existance of 114ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown * _ld_runtime_resolve in call chains will lead to huge cycles, 115ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown * making the profile almost worthless. 116ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown * 117ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown * If ld.so is stripped, the symbol will not appear. But as this 118ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown * function is handcrafted assembler, we search for it. 119ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown * 120ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown * We stop if the ELF object name does not seem to be the runtime linker 121ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown */ 122ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic Bool search_runtime_resolve(obj_node* obj) 123ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 124ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#if defined(VGP_x86_linux) 125436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov static UChar code[] = { 126ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* 0*/ 0x50, 0x51, 0x52, 0x8b, 0x54, 0x24, 0x10, 0x8b, 127ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* 8*/ 0x44, 0x24, 0x0c, 0xe8, 0x70, 0x01, 0x00, 0x00, 128ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /*16*/ 0x5a, 0x59, 0x87, 0x04, 0x24, 0xc2, 0x08, 0x00 }; 129ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* Check ranges [0-11] and [16-23] ([12-15] is an absolute address) */ 130ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown static struct pattern pat = { 131ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown "x86-def", 24, {{ 0,12 }, { 16,8 }, { 24,0}} }; 132ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 133ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* Pattern for glibc-2.8 on OpenSuse11.0 */ 134436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov static UChar code_28[] = { 135ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* 0*/ 0x50, 0x51, 0x52, 0x8b, 0x54, 0x24, 0x10, 0x8b, 136ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* 8*/ 0x44, 0x24, 0x0c, 0xe8, 0x70, 0x01, 0x00, 0x00, 137ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /*16*/ 0x5a, 0x8b, 0x0c, 0x24, 0x89, 0x04, 0x24, 0x8b, 138ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /*24*/ 0x44, 0x24, 0x04, 0xc2, 0x0c, 0x00 }; 139ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown static struct pattern pat_28 = { 140ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown "x86-glibc2.8", 30, {{ 0,12 }, { 16,14 }, { 30,0}} }; 141ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 142ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (VG_(strncmp)(obj->name, "/lib/ld", 7) != 0) return False; 143ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (check_code(obj, code, &pat)) return True; 144ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (check_code(obj, code_28, &pat_28)) return True; 145ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return False; 146ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#endif 147ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 148ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#if defined(VGP_ppc32_linux) 149436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov static UChar code[] = { 150ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* 0*/ 0x94, 0x21, 0xff, 0xc0, 0x90, 0x01, 0x00, 0x0c, 151ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* 8*/ 0x90, 0x61, 0x00, 0x10, 0x90, 0x81, 0x00, 0x14, 152ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /*16*/ 0x7d, 0x83, 0x63, 0x78, 0x90, 0xa1, 0x00, 0x18, 153ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /*24*/ 0x7d, 0x64, 0x5b, 0x78, 0x90, 0xc1, 0x00, 0x1c, 154ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /*32*/ 0x7c, 0x08, 0x02, 0xa6, 0x90, 0xe1, 0x00, 0x20, 155ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /*40*/ 0x90, 0x01, 0x00, 0x30, 0x91, 0x01, 0x00, 0x24, 156ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /*48*/ 0x7c, 0x00, 0x00, 0x26, 0x91, 0x21, 0x00, 0x28, 157ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /*56*/ 0x91, 0x41, 0x00, 0x2c, 0x90, 0x01, 0x00, 0x08, 158ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /*64*/ 0x48, 0x00, 0x02, 0x91, 0x7c, 0x69, 0x03, 0xa6, /* at 64: bl aff0 <fixup> */ 159ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /*72*/ 0x80, 0x01, 0x00, 0x30, 0x81, 0x41, 0x00, 0x2c, 160ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /*80*/ 0x81, 0x21, 0x00, 0x28, 0x7c, 0x08, 0x03, 0xa6, 161ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /*88*/ 0x81, 0x01, 0x00, 0x24, 0x80, 0x01, 0x00, 0x08, 162ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /*96*/ 0x80, 0xe1, 0x00, 0x20, 0x80, 0xc1, 0x00, 0x1c, 163ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /*104*/0x7c, 0x0f, 0xf1, 0x20, 0x80, 0xa1, 0x00, 0x18, 164ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /*112*/0x80, 0x81, 0x00, 0x14, 0x80, 0x61, 0x00, 0x10, 165ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /*120*/0x80, 0x01, 0x00, 0x0c, 0x38, 0x21, 0x00, 0x40, 166ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /*128*/0x4e, 0x80, 0x04, 0x20 }; 167ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown static struct pattern pat = { 168ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown "ppc32-def", 132, {{ 0,65 }, { 68,64 }, { 132,0 }} }; 169ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 170ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (VG_(strncmp)(obj->name, "/lib/ld", 7) != 0) return False; 171ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return check_code(obj, code, &pat); 172ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#endif 173ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 174ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#if defined(VGP_amd64_linux) 175436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov static UChar code[] = { 176ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* 0*/ 0x48, 0x83, 0xec, 0x38, 0x48, 0x89, 0x04, 0x24, 177ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* 8*/ 0x48, 0x89, 0x4c, 0x24, 0x08, 0x48, 0x89, 0x54, 0x24, 0x10, 178ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /*18*/ 0x48, 0x89, 0x74, 0x24, 0x18, 0x48, 0x89, 0x7c, 0x24, 0x20, 179ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /*28*/ 0x4c, 0x89, 0x44, 0x24, 0x28, 0x4c, 0x89, 0x4c, 0x24, 0x30, 180ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /*38*/ 0x48, 0x8b, 0x74, 0x24, 0x40, 0x49, 0x89, 0xf3, 181ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /*46*/ 0x4c, 0x01, 0xde, 0x4c, 0x01, 0xde, 0x48, 0xc1, 0xe6, 0x03, 182ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /*56*/ 0x48, 0x8b, 0x7c, 0x24, 0x38, 0xe8, 0xee, 0x01, 0x00, 0x00, 183ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /*66*/ 0x49, 0x89, 0xc3, 0x4c, 0x8b, 0x4c, 0x24, 0x30, 184ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /*74*/ 0x4c, 0x8b, 0x44, 0x24, 0x28, 0x48, 0x8b, 0x7c, 0x24, 0x20, 185ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /*84*/ 0x48, 0x8b, 0x74, 0x24, 0x18, 0x48, 0x8b, 0x54, 0x24, 0x10, 186ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /*94*/ 0x48, 0x8b, 0x4c, 0x24, 0x08, 0x48, 0x8b, 0x04, 0x24, 187ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /*103*/0x48, 0x83, 0xc4, 0x48, 0x41, 0xff, 0xe3 }; 188ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown static struct pattern pat = { 189ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown "amd64-def", 110, {{ 0,62 }, { 66,44 }, { 110,0 }} }; 190ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 191ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if ((VG_(strncmp)(obj->name, "/lib/ld", 7) != 0) && 192ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown (VG_(strncmp)(obj->name, "/lib64/ld", 9) != 0)) return False; 193ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return check_code(obj, code, &pat); 194ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#endif 195ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 196ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* For other platforms, no patterns known */ 197ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return False; 198ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 199ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 200ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 201ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*------------------------------------------------------------*/ 202ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--- Object/File/Function hash entry operations ---*/ 203ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*------------------------------------------------------------*/ 204ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 205ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Object hash table, fixed */ 206ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic obj_node* obj_table[N_OBJ_ENTRIES]; 207ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 208ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid CLG_(init_obj_table)() 209ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 210ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Int i; 211ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown for (i = 0; i < N_OBJ_ENTRIES; i++) 212ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown obj_table[i] = 0; 213ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 214ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 215ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define HASH_CONSTANT 256 216ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 217436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanovstatic UInt str_hash(const HChar *s, UInt table_size) 218ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 219ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown int hash_value = 0; 220ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown for ( ; *s; s++) 221ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown hash_value = (HASH_CONSTANT * hash_value + *s) % table_size; 222ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return hash_value; 223ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 224ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 225ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 226436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanovstatic const HChar* anonymous_obj = "???"; 227ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 228ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic __inline__ 229ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownobj_node* new_obj_node(DebugInfo* di, obj_node* next) 230ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 231ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Int i; 232ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown obj_node* obj; 233ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 234ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown obj = (obj_node*) CLG_MALLOC("cl.fn.non.1", sizeof(obj_node)); 235ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown obj->name = di ? VG_(strdup)( "cl.fn.non.2", 236ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(DebugInfo_get_filename)(di) ) 237ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown : anonymous_obj; 238ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown for (i = 0; i < N_FILE_ENTRIES; i++) { 239ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown obj->files[i] = NULL; 240ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 241ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown CLG_(stat).distinct_objs ++; 242ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown obj->number = CLG_(stat).distinct_objs; 243ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* JRS 2008 Feb 19: maybe rename .start/.size/.offset to 244ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown .text_avma/.text_size/.test_bias to make it clearer what these 245ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown fields really mean */ 246ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown obj->start = di ? VG_(DebugInfo_get_text_avma)(di) : 0; 247ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown obj->size = di ? VG_(DebugInfo_get_text_size)(di) : 0; 248ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown obj->offset = di ? VG_(DebugInfo_get_text_bias)(di) : 0; 249ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown obj->next = next; 250ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 251ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown // not only used for debug output (see static.c) 252ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown obj->last_slash_pos = 0; 253ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown i = 0; 254ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown while(obj->name[i]) { 255ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (obj->name[i]=='/') obj->last_slash_pos = i+1; 256ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown i++; 257ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 258ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 259ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (runtime_resolve_addr == 0) search_runtime_resolve(obj); 260ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 261ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return obj; 262ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 263ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 264ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownobj_node* CLG_(get_obj_node)(DebugInfo* di) 265ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 266ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown obj_node* curr_obj_node; 267ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown UInt objname_hash; 268436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov const HChar* obj_name; 269ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 270436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov obj_name = di ? VG_(DebugInfo_get_filename)(di) : anonymous_obj; 271ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 272ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* lookup in obj hash */ 273ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown objname_hash = str_hash(obj_name, N_OBJ_ENTRIES); 274ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown curr_obj_node = obj_table[objname_hash]; 275ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown while (NULL != curr_obj_node && 276ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(strcmp)(obj_name, curr_obj_node->name) != 0) { 277ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown curr_obj_node = curr_obj_node->next; 278ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 279ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (NULL == curr_obj_node) { 280ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown obj_table[objname_hash] = curr_obj_node = 281ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown new_obj_node(di, obj_table[objname_hash]); 282ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 283ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 284ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return curr_obj_node; 285ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 286ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 287ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 288ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic __inline__ 289436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanovfile_node* new_file_node(HChar filename[FILENAME_LEN], 290ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown obj_node* obj, file_node* next) 291ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 292ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Int i; 293ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown file_node* file = (file_node*) CLG_MALLOC("cl.fn.nfn.1", 294ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown sizeof(file_node)); 295ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown file->name = VG_(strdup)("cl.fn.nfn.2", filename); 296ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown for (i = 0; i < N_FN_ENTRIES; i++) { 297ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown file->fns[i] = NULL; 298ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 299ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown CLG_(stat).distinct_files++; 300ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown file->number = CLG_(stat).distinct_files; 301ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown file->obj = obj; 302ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown file->next = next; 303ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return file; 304ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 305ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 306ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 307ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownfile_node* CLG_(get_file_node)(obj_node* curr_obj_node, 308436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov HChar filename[FILENAME_LEN]) 309ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 310ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown file_node* curr_file_node; 311ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown UInt filename_hash; 312ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 313ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* lookup in file hash */ 314ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown filename_hash = str_hash(filename, N_FILE_ENTRIES); 315ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown curr_file_node = curr_obj_node->files[filename_hash]; 316ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown while (NULL != curr_file_node && 317ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(strcmp)(filename, curr_file_node->name) != 0) { 318ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown curr_file_node = curr_file_node->next; 319ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 320ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (NULL == curr_file_node) { 321ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown curr_obj_node->files[filename_hash] = curr_file_node = 322ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown new_file_node(filename, curr_obj_node, 323ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown curr_obj_node->files[filename_hash]); 324ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 325ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 326ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return curr_file_node; 327ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 328ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 329ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* forward decl. */ 330ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic void resize_fn_array(void); 331ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 332ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic __inline__ 333436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanovfn_node* new_fn_node(HChar fnname[FILENAME_LEN], 334ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown file_node* file, fn_node* next) 335ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 336ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown fn_node* fn = (fn_node*) CLG_MALLOC("cl.fn.nfnnd.1", 337ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown sizeof(fn_node)); 338ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown fn->name = VG_(strdup)("cl.fn.nfnnd.2", fnname); 339ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 340ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown CLG_(stat).distinct_fns++; 341ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown fn->number = CLG_(stat).distinct_fns; 342ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown fn->last_cxt = 0; 343ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown fn->pure_cxt = 0; 344ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown fn->file = file; 345ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown fn->next = next; 346ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 347ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown fn->dump_before = False; 348ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown fn->dump_after = False; 349ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown fn->zero_before = False; 350ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown fn->toggle_collect = False; 351ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown fn->skip = False; 352ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown fn->pop_on_jump = CLG_(clo).pop_on_jump; 353ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown fn->is_malloc = False; 354ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown fn->is_realloc = False; 355ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown fn->is_free = False; 356ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 357ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown fn->group = 0; 358ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown fn->separate_callers = CLG_(clo).separate_callers; 359ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown fn->separate_recursions = CLG_(clo).separate_recursions; 360ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 361ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#if CLG_ENABLE_DEBUG 362ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown fn->verbosity = -1; 363ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#endif 364ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 365ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (CLG_(stat).distinct_fns >= current_fn_active.size) 366ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown resize_fn_array(); 367ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 368ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return fn; 369ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 370ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 371ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 372ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Get a function node in hash2 with known file node. 373ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown * hash nodes are created if needed 374ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown */ 375ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic 376ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownfn_node* get_fn_node_infile(file_node* curr_file_node, 377436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov HChar fnname[FN_NAME_LEN]) 378ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 379ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown fn_node* curr_fn_node; 380ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown UInt fnname_hash; 381ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 382ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown CLG_ASSERT(curr_file_node != 0); 383ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 384ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* lookup in function hash */ 385ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown fnname_hash = str_hash(fnname, N_FN_ENTRIES); 386ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown curr_fn_node = curr_file_node->fns[fnname_hash]; 387ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown while (NULL != curr_fn_node && 388ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(strcmp)(fnname, curr_fn_node->name) != 0) { 389ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown curr_fn_node = curr_fn_node->next; 390ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 391ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (NULL == curr_fn_node) { 392ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown curr_file_node->fns[fnname_hash] = curr_fn_node = 393ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown new_fn_node(fnname, curr_file_node, 394ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown curr_file_node->fns[fnname_hash]); 395ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 396ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 397ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return curr_fn_node; 398ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 399ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 400ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 401ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Get a function node in a Segment. 402ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown * Hash nodes are created if needed. 403ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown */ 404ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic __inline__ 405ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownfn_node* get_fn_node_inseg(DebugInfo* di, 406436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov HChar filename[FILENAME_LEN], 407436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov HChar fnname[FN_NAME_LEN]) 408ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 409ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown obj_node *obj = CLG_(get_obj_node)(di); 410ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown file_node *file = CLG_(get_file_node)(obj, filename); 411ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown fn_node *fn = get_fn_node_infile(file, fnname); 412ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 413ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return fn; 414ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 415ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 416ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 417ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownBool CLG_(get_debug_info)(Addr instr_addr, 418436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov HChar file[FILENAME_LEN], 419436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov HChar fn_name[FN_NAME_LEN], UInt* line_num, 420ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown DebugInfo** pDebugInfo) 421ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 422ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Bool found_file_line, found_fn, found_dirname, result = True; 423436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov HChar dir[FILENAME_LEN]; 424ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown UInt line; 425ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 426ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown CLG_DEBUG(6, " + get_debug_info(%#lx)\n", instr_addr); 427ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 428ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (pDebugInfo) { 429ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown *pDebugInfo = VG_(find_DebugInfo)(instr_addr); 430ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 431ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown // for generated code in anonymous space, pSegInfo is 0 432ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 433ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 434ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown found_file_line = VG_(get_filename_linenum)(instr_addr, 435ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown file, FILENAME_LEN, 436ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown dir, FILENAME_LEN, 437ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown &found_dirname, 438ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown &line); 439ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown found_fn = VG_(get_fnname)(instr_addr, 440ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown fn_name, FN_NAME_LEN); 441ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 442ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (found_dirname) { 443ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown // +1 for the '/'. 444ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown CLG_ASSERT(VG_(strlen)(dir) + VG_(strlen)(file) + 1 < FILENAME_LEN); 445ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(strcat)(dir, "/"); // Append '/' 446ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(strcat)(dir, file); // Append file to dir 447ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(strcpy)(file, dir); // Move dir+file to file 448ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 449ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 450ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (!found_file_line && !found_fn) { 451ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown CLG_(stat).no_debug_BBs++; 452ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(strcpy)(file, "???"); 453ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(strcpy)(fn_name, "???"); 454ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (line_num) *line_num=0; 455ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown result = False; 456ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 457ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } else if ( found_file_line && found_fn) { 458ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown CLG_(stat).full_debug_BBs++; 459ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (line_num) *line_num=line; 460ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 461ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } else if ( found_file_line && !found_fn) { 462ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown CLG_(stat).file_line_debug_BBs++; 463ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(strcpy)(fn_name, "???"); 464ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (line_num) *line_num=line; 465ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 466ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } else /*(!found_file_line && found_fn)*/ { 467ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown CLG_(stat).fn_name_debug_BBs++; 468ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(strcpy)(file, "???"); 469ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (line_num) *line_num=0; 470ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 471ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 472ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown CLG_DEBUG(6, " - get_debug_info(%#lx): seg '%s', fn %s\n", 473ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown instr_addr, 474436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov !pDebugInfo ? "-" : 475ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown (*pDebugInfo) ? VG_(DebugInfo_get_filename)(*pDebugInfo) : 476436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov "(None)", 477ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown fn_name); 478ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 479ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return result; 480ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 481ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 482ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* for _libc_freeres_wrapper => _exit renaming */ 483ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic BB* exit_bb = 0; 484ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 485ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 486ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* 487ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown * Attach function struct to a BB from debug info. 488ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown */ 489ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownfn_node* CLG_(get_fn_node)(BB* bb) 490ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 491436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov HChar filename[FILENAME_LEN], fnname[FN_NAME_LEN]; 492ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown DebugInfo* di; 493ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown UInt line_num; 494ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown fn_node* fn; 495ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 496ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* fn from debug info is idempotent for a BB */ 497ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (bb->fn) return bb->fn; 498ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 499ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown CLG_DEBUG(3,"+ get_fn_node(BB %#lx)\n", bb_addr(bb)); 500ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 501ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* get function/file name, line number and object of 502ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown * the BB according to debug information 503ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown */ 504ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown CLG_(get_debug_info)(bb_addr(bb), 505ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown filename, fnname, &line_num, &di); 506ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 507ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (0 == VG_(strcmp)(fnname, "???")) { 508ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown int p; 509ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 510ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* Use address as found in library */ 511ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (sizeof(Addr) == 4) 512ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown p = VG_(sprintf)(fnname, "%#08lx", bb->offset); 513ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown else 514ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown // 64bit address 515ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown p = VG_(sprintf)(fnname, "%#016lx", bb->offset); 516ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 517ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(sprintf)(fnname+p, "%s", 518ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown (bb->sect_kind == Vg_SectData) ? " [Data]" : 519ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown (bb->sect_kind == Vg_SectBSS) ? " [BSS]" : 520ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown (bb->sect_kind == Vg_SectGOT) ? " [GOT]" : 521ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown (bb->sect_kind == Vg_SectPLT) ? " [PLT]" : ""); 522ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 523ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown else { 524ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (VG_(get_fnname_if_entry)(bb_addr(bb), fnname, FN_NAME_LEN)) 525ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown bb->is_entry = 1; 526ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 527ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 528ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* HACK for correct _exit: 529ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown * _exit is redirected to VG_(__libc_freeres_wrapper) by valgrind, 530ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown * so we rename it back again :-) 531ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown */ 532ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (0 == VG_(strcmp)(fnname, "vgPlain___libc_freeres_wrapper") 533ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown && exit_bb) { 534ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown CLG_(get_debug_info)(bb_addr(exit_bb), 535ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown filename, fnname, &line_num, &di); 536ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 537ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown CLG_DEBUG(1, "__libc_freeres_wrapper renamed to _exit\n"); 538ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 539ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (0 == VG_(strcmp)(fnname, "_exit") && !exit_bb) 540ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown exit_bb = bb; 541ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 542ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (runtime_resolve_addr && 543ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown (bb_addr(bb) >= runtime_resolve_addr) && 544ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown (bb_addr(bb) < runtime_resolve_addr + runtime_resolve_length)) { 545ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* BB in runtime_resolve found by code check; use this name */ 546ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(sprintf)(fnname, "_dl_runtime_resolve"); 547ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 548ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 549ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* get fn_node struct for this function */ 550ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown fn = get_fn_node_inseg( di, filename, fnname); 551ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 552ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* if this is the 1st time the function is seen, 553ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown * some attributes are set */ 554ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (fn->pure_cxt == 0) { 555ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 556ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* Every function gets a "pure" context, i.e. a context with stack 557ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown * depth 1 only with this function. This is for compression of mangled 558ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown * names 559ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown */ 560ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown fn_node* pure[2]; 561ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown pure[0] = 0; 562ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown pure[1] = fn; 563ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown fn->pure_cxt = CLG_(get_cxt)(pure+1); 564ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 565ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (bb->sect_kind == Vg_SectPLT) 566ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown fn->skip = CLG_(clo).skip_plt; 567ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 568ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (VG_(strcmp)(fn->name, "_dl_runtime_resolve")==0) { 569ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown fn->pop_on_jump = True; 570ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 571ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (VG_(clo_verbosity) > 1) 572ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(message)(Vg_DebugMsg, "Symbol match: found runtime_resolve:" 573ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown " %s +%#lx=%#lx\n", 574ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown bb->obj->name + bb->obj->last_slash_pos, 575ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown bb->offset, bb_addr(bb)); 576ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 577ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 578ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown fn->is_malloc = (VG_(strcmp)(fn->name, "malloc")==0); 579ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown fn->is_realloc = (VG_(strcmp)(fn->name, "realloc")==0); 580ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown fn->is_free = (VG_(strcmp)(fn->name, "free")==0); 581ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 582ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* apply config options from function name patterns 583ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown * given on command line */ 584ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown CLG_(update_fn_config)(fn); 585ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 586ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 587ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 588ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown bb->fn = fn; 589ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown bb->line = line_num; 590ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 591ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown CLG_DEBUG(3,"- get_fn_node(BB %#lx): %s (in %s:%u)\n", 592ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown bb_addr(bb), fnname, filename, line_num); 593ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 594ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return fn; 595ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 596ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 597ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 598ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*------------------------------------------------------------*/ 599ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--- Active function array operations ---*/ 600ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*------------------------------------------------------------*/ 601ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 602ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* The active function array is a thread-specific array 603ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown * of UInts, mapping function numbers to the active count of 604ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown * functions. 605ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown * The active count is the number of times a function appears 606ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown * in the current call stack, and is used when costs for recursion 607ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown * levels should be separated. 608ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown */ 609ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 610ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownUInt* CLG_(get_fn_entry)(Int n) 611ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 612ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown CLG_ASSERT(n < current_fn_active.size); 613ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return current_fn_active.array + n; 614ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 615ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 616ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid CLG_(init_fn_array)(fn_array* a) 617ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 618ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Int i; 619ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 620ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown CLG_ASSERT(a != 0); 621ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 622ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown a->size = N_INITIAL_FN_ARRAY_SIZE; 623ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (a->size <= CLG_(stat).distinct_fns) 624ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown a->size = CLG_(stat).distinct_fns+1; 625ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 626ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown a->array = (UInt*) CLG_MALLOC("cl.fn.gfe.1", 627ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown a->size * sizeof(UInt)); 628ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown for(i=0;i<a->size;i++) 629ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown a->array[i] = 0; 630ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 631ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 632ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid CLG_(copy_current_fn_array)(fn_array* dst) 633ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 634ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown CLG_ASSERT(dst != 0); 635ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 636ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown dst->size = current_fn_active.size; 637ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown dst->array = current_fn_active.array; 638ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 639ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 640ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownfn_array* CLG_(get_current_fn_array)() 641ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 642ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return ¤t_fn_active; 643ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 644ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 645ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid CLG_(set_current_fn_array)(fn_array* a) 646ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 647ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown CLG_ASSERT(a != 0); 648ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 649ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown current_fn_active.size = a->size; 650ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown current_fn_active.array = a->array; 651ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (current_fn_active.size <= CLG_(stat).distinct_fns) 652ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown resize_fn_array(); 653ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 654ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 655ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* ensure that active_array is big enough: 656ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown * <distinct_fns> is the highest index, so <fn_active_array_size> 657ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown * has to be bigger than that. 658ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown */ 659ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic void resize_fn_array(void) 660ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 661ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown UInt* new_array; 662ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Int i, newsize; 663ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 664ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown newsize = current_fn_active.size; 665ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown while (newsize <= CLG_(stat).distinct_fns) newsize *=2; 666ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 667ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown CLG_DEBUG(0, "Resize fn_active_array: %d => %d\n", 668ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown current_fn_active.size, newsize); 669ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 670ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown new_array = (UInt*) CLG_MALLOC("cl.fn.rfa.1", newsize * sizeof(UInt)); 671ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown for(i=0;i<current_fn_active.size;i++) 672ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown new_array[i] = current_fn_active.array[i]; 673ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown while(i<newsize) 674ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown new_array[i++] = 0; 675ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 676ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(free)(current_fn_active.array); 677ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown current_fn_active.size = newsize; 678ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown current_fn_active.array = new_array; 679ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown CLG_(stat).fn_array_resizes++; 680ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 681ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 682ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 683