1436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov/* -*- mode: C; c-basic-offset: 3; -*- */ 2436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov 3436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov/*--------------------------------------------------------------------*/ 4436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov/*--- An abstraction that provides a file-reading mechanism. ---*/ 5436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov/*--- image.c ---*/ 6436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov/*--------------------------------------------------------------------*/ 7436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov 8436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov/* 9436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov This file is part of Valgrind, a dynamic binary instrumentation 10436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov framework. 11436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov 12436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov Copyright (C) 2013-2013 Mozilla Foundation 13436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov 14436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov This program is free software; you can redistribute it and/or 15436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov modify it under the terms of the GNU General Public License as 16436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov published by the Free Software Foundation; either version 2 of the 17436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov License, or (at your option) any later version. 18436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov 19436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov This program is distributed in the hope that it will be useful, but 20436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov WITHOUT ANY WARRANTY; without even the implied warranty of 21436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 22436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov General Public License for more details. 23436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov 24436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov You should have received a copy of the GNU General Public License 25436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov along with this program; if not, write to the Free Software 26436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 27436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov 02111-1307, USA. 28436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov 29436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov The GNU General Public License is contained in the file COPYING. 30436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov*/ 31436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov 32436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov/* Contributed by Julian Seward <jseward@acm.org> */ 33436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov 34436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov/* See the corresponding auxprogs/valgrind-di-server.c for a list of 35436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov cleanups for this file and itself. */ 36436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov 37436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov#include "pub_core_basics.h" 38436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov#include "pub_core_vki.h" 39436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov#include "pub_core_libcbase.h" 40436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov#include "pub_core_libcassert.h" 41436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov#include "pub_core_libcprint.h" 42436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov#include "pub_core_libcproc.h" /* VG_(read_millisecond_timer) */ 43436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov#include "pub_core_libcfile.h" 44436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov#include "priv_misc.h" /* dinfo_zalloc/free/strdup */ 45436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov#include "priv_image.h" /* self */ 46436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov 47436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov#include "minilzo.h" 48436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov 49436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov#define CACHE_ENTRY_SIZE_BITS (12+1) 50436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov#define CACHE_N_ENTRIES 32 51436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov 52436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov#define CACHE_ENTRY_SIZE (1 << CACHE_ENTRY_SIZE_BITS) 53436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov 54436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov/* An entry in the cache. */ 55436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanovtypedef 56436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov struct { 57436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov DiOffT off; // file offset for data[0] 58436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov SizeT used; // 1 .. sizeof(data), or 0 to denote not-in-use 59436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov UChar data[CACHE_ENTRY_SIZE]; 60436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov } 61436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov CEnt; 62436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov 63436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov/* Source for files */ 64436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanovtypedef 65436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov struct { 66436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov // True: img is of local file. False: img is from a server. 67436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov Bool is_local; 68436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov // The fd for the local file, or sd for a remote server. 69436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov Int fd; 70436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov // The name. In ML_(dinfo_zalloc)'d space. Used only for printing 71436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov // error messages; hence it doesn't really matter what this contains. 72436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov HChar* name; 73436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov // The rest of these fields are only valid when using remote files 74436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov // (that is, using a debuginfo server; hence when is_local==False) 75436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov // Session ID allocated to us by the server. Cannot be zero. 76436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov ULong session_id; 77436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov } 78436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov Source; 79436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov 80436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanovstruct _DiImage { 81436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov // The source -- how to get hold of the file we are reading 82436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov Source source; 83436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov // Total size of the image. 84436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov SizeT size; 85436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov // The number of entries used. 0 .. CACHE_N_ENTRIES 86436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov UInt ces_used; 87436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov // Pointers to the entries. ces[0 .. ces_used-1] are non-NULL. 88436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov // ces[ces_used .. CACHE_N_ENTRIES-1] are NULL. 89436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov // The non-NULL entries may be arranged arbitrarily. We expect to use 90436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov // a pseudo-LRU scheme though. 91436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov CEnt* ces[CACHE_N_ENTRIES]; 92436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov}; 93436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov 94436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov/* A frame. The first 4 bytes of |data| give the kind of the frame, 95436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov and the rest of it is kind-specific data. */ 96436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanovtypedef struct { UChar* data; SizeT n_data; } Frame; 97436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov 98436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanovstatic void write_UInt_le ( /*OUT*/UChar* dst, UInt n ) 99436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov{ 100436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov Int i; 101436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov for (i = 0; i <= 3; i++) { 102436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov dst[i] = (UChar)(n & 0xFF); 103436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov n >>= 8; 104436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov } 105436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov} 106436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov 107436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanovstatic UInt read_UInt_le ( UChar* src ) 108436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov{ 109436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov UInt r = 0; 110436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov Int i; 111436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov for (i = 3; i >= 0; i--) { 112436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov r <<= 8; 113436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov r += (UInt)src[i]; 114436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov } 115436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov return r; 116436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov} 117436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov 118436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanovstatic void write_ULong_le ( /*OUT*/UChar* dst, ULong n ) 119436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov{ 120436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov Int i; 121436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov for (i = 0; i <= 7; i++) { 122436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov dst[i] = (UChar)(n & 0xFF); 123436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov n >>= 8; 124436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov } 125436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov} 126436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov 127436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanovstatic ULong read_ULong_le ( UChar* src ) 128436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov{ 129436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov ULong r = 0; 130436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov Int i; 131436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov for (i = 7; i >= 0; i--) { 132436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov r <<= 8; 133436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov r += (ULong)src[i]; 134436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov } 135436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov return r; 136436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov} 137436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov 138436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov 139436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov/* Set |sd| to be blocking. Returns True on success. */ 140436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanovstatic Bool set_blocking ( int sd ) 141436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov{ 142436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov Int res; 143436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov res = VG_(fcntl)(sd, VKI_F_GETFL, 0/*ignored*/); 144436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov if (res != -1) 145436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov res = VG_(fcntl)(sd, VKI_F_SETFL, res & ~VKI_O_NONBLOCK); 146436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov return (res != -1); 147436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov} 148436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov 149436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov/* Tries to read 'len' bytes from fd, blocking if necessary. Assumes 150436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov fd has been set in blocking mode. If it returns with the number of 151436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov bytes read < len, it means that either fd was closed, or there was 152436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov an error on it. */ 153436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanovstatic Int my_read ( Int fd, UChar* buf, Int len ) 154436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov{ 155436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov Int nRead = 0; 156436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov while (1) { 157436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov if (nRead == len) return nRead; 158436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov vg_assert(nRead < len); 159436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov Int nNeeded = len - nRead; 160436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov vg_assert(nNeeded > 0); 161436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov Int n = VG_(read)(fd, &buf[nRead], nNeeded); 162436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov if (n <= 0) return nRead; /* error or EOF */ 163436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov nRead += n; 164436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov } 165436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov} 166436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov 167436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov/* Tries to write 'len' bytes to fd, blocking if necessary. Assumes 168436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov fd has been set in blocking mode. If it returns with the number of 169436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov bytes written < len, it means that either fd was closed, or there was 170436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov an error on it. */ 171436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanovstatic Int my_write ( Int fd, UChar* buf, Int len ) 172436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov{ 173436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov Int nWritten = 0; 174436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov while (1) { 175436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov if (nWritten == len) return nWritten; 176436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov vg_assert(nWritten < len); 177436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov Int nStillToDo = len - nWritten; 178436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov vg_assert(nStillToDo > 0); 179436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov Int n = VG_(write_socket)(fd, &buf[nWritten], nStillToDo); 180436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov if (n < 0) return nWritten; /* error or EOF */ 181436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov nWritten += n; 182436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov } 183436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov} 184436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov 185436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov/* If we lost communication with the remote server, just give up. 186436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov Recovering is too difficult. */ 187436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanovstatic void give_up__comms_lost(void) 188436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov{ 189436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov VG_(umsg)("\n"); 190436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov VG_(umsg)( 191436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov "Valgrind: debuginfo reader: Lost communication with the remote\n"); 192436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov VG_(umsg)( 193436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov "Valgrind: debuginfo server. I can't recover. Giving up. Sorry.\n"); 194436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov VG_(umsg)("\n"); 195436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov VG_(exit)(1); 196436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov /*NOTREACHED*/ 197436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov} 198436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov 199436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanovstatic void give_up__image_overrun(void) 200436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov{ 201436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov VG_(umsg)("\n"); 202436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov VG_(umsg)( 203436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov "Valgrind: debuginfo reader: Possibly corrupted debuginfo file.\n"); 204436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov VG_(umsg)( 205436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov "Valgrind: I can't recover. Giving up. Sorry.\n"); 206436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov VG_(umsg)("\n"); 207436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov VG_(exit)(1); 208436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov /*NOTREACHED*/ 209436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov} 210436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov 211436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov/* "Do" a transaction: that is, send the given frame to the server and 212436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov return the frame it sends back. Caller owns the resulting frame 213436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov and must free it. A NULL return means the transaction failed for 214436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov some reason. */ 215436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanovstatic Frame* do_transaction ( Int sd, Frame* req ) 216436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov{ 217436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov if (0) VG_(printf)("CLIENT: send %c%c%c%c\n", 218436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov req->data[0], req->data[1], req->data[2], req->data[3]); 219436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov 220436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov /* What goes on the wire is: 221436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov adler(le32) n_data(le32) data[0 .. n_data-1] 222436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov where the checksum covers n_data as well as data[]. 223436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov */ 224436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov /* The initial Adler-32 value */ 225436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov UInt adler = VG_(adler32)(0, NULL, 0); 226436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov 227436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov /* Fold in the length field, encoded as le32. */ 228436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov UChar wr_first8[8]; 229436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov write_UInt_le(&wr_first8[4], req->n_data); 230436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov adler = VG_(adler32)(adler, &wr_first8[4], 4); 231436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov /* Fold in the data values */ 232436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov adler = VG_(adler32)(adler, req->data, req->n_data); 233436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov write_UInt_le(&wr_first8[0], adler); 234436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov 235436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov Int r = my_write(sd, &wr_first8[0], 8); 236436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov if (r != 8) return NULL; 237436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov vg_assert(req->n_data >= 4); // else ill formed -- no KIND field 238436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov r = my_write(sd, req->data, req->n_data); 239436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov if (r != req->n_data) return NULL; 240436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov 241436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov /* So, the request is sent. Now get a request of the same format 242436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov out of the channel. */ 243436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov UChar rd_first8[8]; // adler32; length32 244436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov r = my_read(sd, &rd_first8[0], 8); 245436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov if (r != 8) return NULL; 246436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov UInt rd_adler = read_UInt_le(&rd_first8[0]); 247436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov UInt rd_len = read_UInt_le(&rd_first8[4]); 248436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov /* Allocate a Frame to hold the result data, and read into it. */ 249436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov // Reject obviously-insane length fields. 250436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov if (rd_len < 4 || rd_len > 4*1024*1024) return NULL; 251436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov Frame* res = ML_(dinfo_zalloc)("di.do_transaction.1", sizeof(Frame)); 252436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov res->n_data = rd_len; 253436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov res->data = ML_(dinfo_zalloc)("di.do_transaction.2", rd_len); 254436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov r = my_read(sd, res->data, res->n_data); 255436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov if (r != rd_len) return NULL; 256436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov 257436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov if (0) VG_(printf)("CLIENT: recv %c%c%c%c\n", 258436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov res->data[0], res->data[1], res->data[2], res->data[3]); 259436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov 260436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov /* Compute the checksum for the received data, and check it. */ 261436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov adler = VG_(adler32)(0, NULL, 0); // initial value 262436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov adler = VG_(adler32)(adler, &rd_first8[4], 4); 263436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov if (res->n_data > 0) 264436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov adler = VG_(adler32)(adler, res->data, res->n_data); 265436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov 266436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov if (adler/*computed*/ != rd_adler/*expected*/) return NULL; 267436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov return res; 268436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov} 269436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov 270436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanovstatic void free_Frame ( Frame* fr ) 271436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov{ 272436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov vg_assert(fr && fr->data); 273436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov ML_(dinfo_free)(fr->data); 274436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov ML_(dinfo_free)(fr); 275436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov} 276436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov 277436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanovstatic Frame* mk_Frame_noargs ( const HChar* tag ) 278436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov{ 279436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov vg_assert(VG_(strlen)(tag) == 4); 280436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov Frame* f = ML_(dinfo_zalloc)("di.mFn.1", sizeof(Frame)); 281436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov f->n_data = 4; 282436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov f->data = ML_(dinfo_zalloc)("di.mFn.2", f->n_data); 283436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov VG_(memcpy)(&f->data[0], tag, 4); 284436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov return f; 285436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov} 286436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov 287436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanovstatic Frame* mk_Frame_le64_le64_le64 ( const HChar* tag, 288436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov ULong n1, ULong n2, ULong n3 ) 289436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov{ 290436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov vg_assert(VG_(strlen)(tag) == 4); 291436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov Frame* f = ML_(dinfo_zalloc)("di.mFlll.1", sizeof(Frame)); 292436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov f->n_data = 4 + 3*8; 293436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov f->data = ML_(dinfo_zalloc)("di.mFlll.2", f->n_data); 294436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov VG_(memcpy)(&f->data[0], tag, 4); 295436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov write_ULong_le(&f->data[4 + 0*8], n1); 296436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov write_ULong_le(&f->data[4 + 1*8], n2); 297436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov write_ULong_le(&f->data[4 + 2*8], n3); 298436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov return f; 299436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov} 300436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov 301436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanovstatic Frame* mk_Frame_asciiz ( const HChar* tag, const HChar* str ) 302436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov{ 303436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov vg_assert(VG_(strlen)(tag) == 4); 304436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov Frame* f = ML_(dinfo_zalloc)("di.mFa.1", sizeof(Frame)); 305436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov SizeT n_str = VG_(strlen)(str); 306436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov f->n_data = 4 + n_str + 1; 307436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov f->data = ML_(dinfo_zalloc)("di.mFa.2", f->n_data); 308436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov VG_(memcpy)(&f->data[0], tag, 4); 309436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov VG_(memcpy)(&f->data[4], str, n_str); 310436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov vg_assert(f->data[4 + n_str] == 0); 311436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov return f; 312436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov} 313436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov 314436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanovstatic Bool parse_Frame_le64 ( Frame* fr, const HChar* tag, /*OUT*/ULong* n1 ) 315436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov{ 316436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov vg_assert(VG_(strlen)(tag) == 4); 317436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov if (!fr || !fr->data) return False; 318436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov if (fr->n_data < 4) return False; 319436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov if (VG_(memcmp)(&fr->data[0], tag, 4) != 0) return False; 320436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov if (fr->n_data != 4 + 1*8) return False; 321436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov *n1 = read_ULong_le(&fr->data[4 + 0*8]); 322436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov return True; 323436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov} 324436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov 325436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanovstatic Bool parse_Frame_le64_le64 ( Frame* fr, const HChar* tag, 326436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov /*OUT*/ULong* n1, /*OUT*/ULong* n2 ) 327436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov{ 328436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov vg_assert(VG_(strlen)(tag) == 4); 329436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov if (!fr || !fr->data) return False; 330436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov if (fr->n_data < 4) return False; 331436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov if (VG_(memcmp)(&fr->data[0], tag, 4) != 0) return False; 332436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov if (fr->n_data != 4 + 2*8) return False; 333436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov *n1 = read_ULong_le(&fr->data[4 + 0*8]); 334436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov *n2 = read_ULong_le(&fr->data[4 + 1*8]); 335436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov return True; 336436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov} 337436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov 338436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanovstatic Bool parse_Frame_asciiz ( Frame* fr, const HChar* tag, 339436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov /*OUT*/UChar** str ) 340436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov{ 341436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov vg_assert(VG_(strlen)(tag) == 4); 342436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov if (!fr || !fr->data) return False; 343436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov if (fr->n_data < 4) return False; 344436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov if (VG_(memcmp)(&fr->data[0], tag, 4) != 0) return False; 345436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov if (fr->n_data < 5) return False; // else there isn't even enough 346436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov // space for the terminating zero 347436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov /* Find the terminating zero and ensure it's right at the end 348436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov of the data. If not, the frame is malformed. */ 349436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov SizeT i = 4; 350436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov while (True) { 351436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov if (i >= fr->n_data) break; 352436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov if (fr->data[i] == 0) break; 353436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov i++; 354436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov } 355436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov vg_assert(i <= fr->n_data); 356436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov if (i == fr->n_data-1 && fr->data[i] == 0) { 357436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov *str = &fr->data[4]; 358436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov return True; 359436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov } else { 360436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov return False; 361436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov } 362436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov} 363436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov 364436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanovstatic Bool parse_Frame_le64_le64_le64_bytes ( 365436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov Frame* fr, const HChar* tag, 366436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov /*OUT*/ULong* n1, /*OUT*/ULong* n2, /*OUT*/ULong* n3, 367436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov /*OUT*/UChar** data, /*OUT*/ULong* n_data 368436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov ) 369436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov{ 370436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov vg_assert(VG_(strlen)(tag) == 4); 371436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov if (!fr || !fr->data) return False; 372436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov if (fr->n_data < 4) return False; 373436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov if (VG_(memcmp)(&fr->data[0], tag, 4) != 0) return False; 374436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov if (fr->n_data < 4 + 3*8) return False; 375436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov *n1 = read_ULong_le(&fr->data[4 + 0*8]); 376436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov *n2 = read_ULong_le(&fr->data[4 + 1*8]); 377436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov *n3 = read_ULong_le(&fr->data[4 + 2*8]); 378436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov *data = &fr->data[4 + 3*8]; 379436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov *n_data = fr->n_data - (4 + 3*8); 380436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov vg_assert(fr->n_data >= 4 + 3*8); 381436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov return True; 382436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov} 383436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov 384436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanovstatic DiOffT block_round_down ( DiOffT i ) 385436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov{ 386436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov return i & ((DiOffT)~(CACHE_ENTRY_SIZE-1)); 387436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov} 388436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov 389436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov/* Is this offset inside this CEnt? */ 390436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanovstatic inline Bool is_in_CEnt ( CEnt* cent, DiOffT off ) 391436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov{ 392436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov /* This assertion is checked by set_CEnt, so checking it here has 393436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov no benefit, whereas skipping it does remove it from the hottest 394436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov path. */ 395436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov /* vg_assert(cent->used > 0 && cent->used <= CACHE_ENTRY_SIZE); */ 396436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov return cent->off <= off && off < cent->off + cent->used; 397436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov} 398436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov 399436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov/* Allocate a new CEnt, connect it to |img|, and return its index. */ 400436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanovstatic UInt alloc_CEnt ( DiImage* img ) 401436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov{ 402436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov vg_assert(img); 403436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov vg_assert(img->ces_used < CACHE_N_ENTRIES); 404436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov UInt entNo = img->ces_used; 405436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov img->ces_used++; 406436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov vg_assert(img->ces[entNo] == NULL); 407436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov img->ces[entNo] = ML_(dinfo_zalloc)("di.alloc_CEnt.1", sizeof(CEnt)); 408436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov return entNo; 409436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov} 410436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov 411436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov/* Move the given entry to the top and slide those above it down by 1, 412436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov to make space. */ 413436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanovstatic void move_CEnt_to_top ( DiImage* img, UInt entNo ) 414436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov{ 415436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov vg_assert(img->ces_used <= CACHE_N_ENTRIES); 416436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov vg_assert(entNo > 0 && entNo < img->ces_used); 417436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov CEnt* tmp = img->ces[entNo]; 418436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov while (entNo > 0) { 419436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov img->ces[entNo] = img->ces[entNo-1]; 420436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov entNo--; 421436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov } 422436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov img->ces[0] = tmp; 423436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov} 424436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov 425436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov/* Set the given entry so that it has a chunk of the file containing 426436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov the given offset. It is this function that brings data into the 427436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov cache, either by reading the local file or pulling it from the 428436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov remote server. */ 429436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanovstatic void set_CEnt ( DiImage* img, UInt entNo, DiOffT off ) 430436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov{ 431436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov SizeT len; 432436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov DiOffT off_orig = off; 433436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov vg_assert(img); 434436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov vg_assert(img->ces_used <= CACHE_N_ENTRIES); 435436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov vg_assert(entNo >= 0 && entNo < img->ces_used); 436436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov vg_assert(off < img->size); 437436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov vg_assert(img->ces[entNo] != NULL); 438436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov /* Compute [off, +len) as the slice we are going to read. */ 439436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov off = block_round_down(off); 440436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov len = img->size - off; 441436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov if (len > CACHE_ENTRY_SIZE) len = CACHE_ENTRY_SIZE; 442436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov /* It is conceivable that the 'len > 0' bit could fail if we make 443436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov an image with a zero sized file. But then no 'get' request on 444436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov that image would be valid. */ 445436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov vg_assert(len > 0 && len <= CACHE_ENTRY_SIZE); 446436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov vg_assert(off + len <= img->size); 447436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov vg_assert(off <= off_orig && off_orig < off+len); 448436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov /* So, read off .. off+len-1 into the entry. */ 449436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov CEnt* ce = img->ces[entNo]; 450436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov 451436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov if (0) { 452436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov static UInt t_last = 0; 453436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov static ULong nread = 0; 454436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov UInt now = VG_(read_millisecond_timer)(); 455436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov UInt delay = now - t_last; 456436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov t_last = now; 457436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov nread += len; 458436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov VG_(printf)("XXXXXXXX (tot %lld) read %ld offset %lld %u\n", 459436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov nread, len, off, delay); 460436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov } 461436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov 462436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov if (img->source.is_local) { 463436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov // Simple: just read it 464436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov SysRes sr = VG_(pread)(img->source.fd, &ce->data[0], (Int)len, off); 465436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov vg_assert(!sr_isError(sr)); 466436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov } else { 467436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov // Not so simple: poke the server 468436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov vg_assert(img->source.session_id > 0); 469436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov Frame* req 470436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov = mk_Frame_le64_le64_le64("READ", img->source.session_id, off, len); 471436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov Frame* res = do_transaction(img->source.fd, req); 472436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov free_Frame(req); req = NULL; 473436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov if (!res) goto server_fail; 474436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov ULong rx_session_id = 0, rx_off = 0, rx_len = 0, rx_zdata_len = 0; 475436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov UChar* rx_data = NULL; 476436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov /* Pretty confusing. rx_sessionid, rx_off and rx_len are copies 477436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov of the values that we requested in the READ frame just above, 478436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov so we can be sure that the server is responding to the right 479436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov request. It just copies them from the request into the 480436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov response. rx_data is the actual data, and rx_zdata_len is 481436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov its compressed length. Hence rx_len must equal len, but 482436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov rx_zdata_len can be different -- smaller, hopefully.. */ 483436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov if (!parse_Frame_le64_le64_le64_bytes 484436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov (res, "RDOK", &rx_session_id, &rx_off, 485436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov &rx_len, &rx_data, &rx_zdata_len)) 486436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov goto server_fail; 487436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov if (rx_session_id != img->source.session_id 488436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov || rx_off != off || rx_len != len || rx_data == NULL) 489436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov goto server_fail; 490436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov 491436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov //VG_(memcpy)(&ce->data[0], rx_data, len); 492436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov // Decompress into the destination buffer 493436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov // Tell the lib the max number of output bytes it can write. 494436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov // After the call, this holds the number of bytes actually written, 495436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov // and it's an error if it is different. 496436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov UInt out_len = len; 497436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov Int lzo_rc = lzo1x_decompress_safe(rx_data, rx_zdata_len, 498436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov &ce->data[0], (lzo_uint*)&out_len, 499436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov NULL); 500436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov Bool ok = lzo_rc == LZO_E_OK && out_len == len; 501436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov if (!ok) goto server_fail; 502436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov 503436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov free_Frame(res); res = NULL; 504436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov goto end_of_else_clause; 505436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov server_fail: 506436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov /* The server screwed up somehow. Now what? */ 507436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov if (res) { 508436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov UChar* reason = NULL; 509436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov if (parse_Frame_asciiz(res, "FAIL", &reason)) { 510436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov VG_(umsg)("set_CEnt (reading data from DI server): fail: " 511436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov "%s\n", reason); 512436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov } else { 513436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov VG_(umsg)("set_CEnt (reading data from DI server): fail: " 514436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov "unknown reason\n"); 515436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov } 516436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov free_Frame(res); res = NULL; 517436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov } else { 518436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov VG_(umsg)("set_CEnt (reading data from DI server): fail: " 519436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov "server unexpectedly closed the connection\n"); 520436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov } 521436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov give_up__comms_lost(); 522436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov /* NOTREACHED */ 523436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov vg_assert(0); 524436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov end_of_else_clause: 525436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov {} 526436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov } 527436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov 528436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov ce->off = off; 529436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov ce->used = len; 530436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov vg_assert(ce->used > 0 && ce->used <= CACHE_ENTRY_SIZE); 531436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov} 532436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov 533436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov__attribute__((noinline)) 534436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanovstatic UChar get_slowcase ( DiImage* img, DiOffT off ) 535436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov{ 536436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov /* Stay sane .. */ 537436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov vg_assert(off < img->size); 538436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov vg_assert(img->ces_used <= CACHE_N_ENTRIES); 539436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov UInt i; 540436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov /* Start the search at entry 1, since the fast-case function 541436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov checked slot zero already. */ 542436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov for (i = 1; i < img->ces_used; i++) { 543436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov vg_assert(img->ces[i]); 544436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov if (is_in_CEnt(img->ces[i], off)) 545436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov break; 546436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov } 547436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov vg_assert(i <= img->ces_used); 548436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov if (i == img->ces_used) { 549436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov /* It's not in any entry. Either allocate a new entry or 550436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov recycle the LRU one. */ 551436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov if (img->ces_used == CACHE_N_ENTRIES) { 552436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov /* All entries in use. Recycle the (ostensibly) LRU one. */ 553436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov set_CEnt(img, CACHE_N_ENTRIES-1, off); 554436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov i = CACHE_N_ENTRIES-1; 555436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov } else { 556436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov /* Allocate a new one, and fill it in. */ 557436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov UInt entNo = alloc_CEnt(img); 558436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov set_CEnt(img, entNo, off); 559436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov i = entNo; 560436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov } 561436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov } else { 562436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov /* We found it at position 'i'. */ 563436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov vg_assert(i > 0); 564436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov } 565436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov if (i > 0) { 566436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov move_CEnt_to_top(img, i); 567436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov i = 0; 568436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov } 569436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov vg_assert(is_in_CEnt(img->ces[i], off)); 570436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov return img->ces[i]->data[ off - img->ces[i]->off ]; 571436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov} 572436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov 573436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov// This is called a lot, so do the usual fast/slow split stuff on it. */ 574436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanovstatic UChar get ( DiImage* img, DiOffT off ) 575436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov{ 576436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov /* Most likely case is, it's in the ces[0] position. */ 577436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov /* ML_(img_from_local_file) requests a read for ces[0] when 578436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov creating the image. Hence slot zero is always non-NULL, so we 579436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov can skip this test. */ 580436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov if (LIKELY(/* img->ces[0] != NULL && */ 581436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov is_in_CEnt(img->ces[0], off))) { 582436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov return img->ces[0]->data[ off - img->ces[0]->off ]; 583436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov } 584436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov /* Else we'll have to fish around for it. */ 585436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov return get_slowcase(img, off); 586436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov} 587436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov 588436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov/* Create an image from a file in the local filesystem. This is 589436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov relatively straightforward. */ 590436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy IvanovDiImage* ML_(img_from_local_file)(const HChar* fullpath) 591436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov{ 592436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov SysRes fd; 593436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov struct vg_stat stat_buf; 594436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov DiOffT size; 595436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov 596436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov fd = VG_(open)(fullpath, VKI_O_RDONLY, 0); 597436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov if (sr_isError(fd)) 598436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov return NULL; 599436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov 600436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov if (VG_(fstat)(sr_Res(fd), &stat_buf) != 0) { 601436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov VG_(close)(sr_Res(fd)); 602436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov return NULL; 603436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov } 604436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov 605436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov size = stat_buf.size; 606436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov if (size == 0 || size == DiOffT_INVALID 607436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov || /* size is unrepresentable as a SizeT */ 608436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov size != (DiOffT)(SizeT)(size)) { 609436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov VG_(close)(sr_Res(fd)); 610436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov return NULL; 611436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov } 612436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov 613436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov DiImage* img = ML_(dinfo_zalloc)("di.image.ML_iflf.1", sizeof(DiImage)); 614436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov img->source.is_local = True; 615436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov img->source.fd = sr_Res(fd); 616436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov img->size = size; 617436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov img->ces_used = 0; 618436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov img->source.name = ML_(dinfo_strdup)("di.image.ML_iflf.2", fullpath); 619436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov /* img->ces is already zeroed out */ 620436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov vg_assert(img->source.fd >= 0); 621436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov 622436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov /* Force the zeroth entry to be the first chunk of the file. 623436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov That's likely to be the first part that's requested anyway, and 624436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov loading it at this point forcing img->cent[0] to always be 625436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov non-empty, thereby saving us an is-it-empty check on the fast 626436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov path in get(). */ 627436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov UInt entNo = alloc_CEnt(img); 628436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov vg_assert(entNo == 0); 629436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov set_CEnt(img, 0, 0); 630436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov 631436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov return img; 632436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov} 633436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov 634436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov 635436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov/* Create an image from a file on a remote debuginfo server. This is 636436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov more complex. There are lots of ways in which it can fail. */ 637436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy IvanovDiImage* ML_(img_from_di_server)(const HChar* filename, 638436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov const HChar* serverAddr) 639436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov{ 640436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov if (filename == NULL || serverAddr == NULL) 641436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov return NULL; 642436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov 643436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov /* The filename must be a plain filename -- no slashes at all. */ 644436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov if (VG_(strchr)(filename, '/') != NULL) 645436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov return NULL; 646436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov 647436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov /* Try to connect to the server. A side effect of this is to parse 648436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov and reject, if syntactically invalid, |serverAddr|. Reasons why 649436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov this could fail: 650436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov - serverAddr is not of the form d.d.d.d:d or d.d.d.d 651436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov - attempt to connect to that address:port failed 652436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov */ 653436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov Int sd = VG_(connect_via_socket)(serverAddr); 654436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov if (sd < 0) 655436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov return NULL; 656436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov if (!set_blocking(sd)) 657436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov return NULL; 658436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov Int one = 1; 659436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov Int sr = VG_(setsockopt)(sd, VKI_IPPROTO_TCP, VKI_TCP_NODELAY, 660436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov &one, sizeof(one)); 661436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov vg_assert(sr == 0); 662436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov 663436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov /* Ok, we got a connection. Ask it for version string, so as to be 664436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov reasonably sure we're talking to an instance of 665436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov auxprogs/valgrind-di-server and not to some other random program 666436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov that happens to be listening on that port. */ 667436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov Frame* req = mk_Frame_noargs("VERS"); 668436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov Frame* res = do_transaction(sd, req); 669436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov if (res == NULL) 670436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov goto fail; // do_transaction failed?! 671436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov UChar* vstr = NULL; 672436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov if (!parse_Frame_asciiz(res, "VEOK", &vstr)) 673436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov goto fail; // unexpected response kind, or invalid ID string 674436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov vg_assert(vstr); 675436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov if (VG_(strcmp)("Valgrind Debuginfo Server, Version 1", 676436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov (const HChar*)vstr) != 0) 677436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov goto fail; // wrong version string 678436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov free_Frame(req); 679436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov free_Frame(res); 680436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov req = NULL; 681436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov res = NULL; 682436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov 683436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov /* Server seems plausible. Present it with the name of the file we 684436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov want and see if it'll give us back a session ID for it. */ 685436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov req = mk_Frame_asciiz("OPEN", filename); 686436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov res = do_transaction(sd, req); 687436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov if (res == NULL) 688436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov goto fail; 689436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov ULong session_id = 0, size = 0; 690436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov if (!parse_Frame_le64_le64(res, "OPOK", &session_id, &size)) 691436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov goto fail; 692436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov free_Frame(req); 693436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov free_Frame(res); 694436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov req = NULL; 695436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov res = NULL; 696436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov 697436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov /* We have a session ID. We're ready to roll. */ 698436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov DiImage* img = ML_(dinfo_zalloc)("di.image.ML_ifds.1", sizeof(DiImage)); 699436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov img->source.is_local = False; 700436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov img->source.fd = sd; 701436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov img->source.session_id = session_id; 702436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov img->size = size; 703436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov img->ces_used = 0; 704436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov img->source.name = ML_(dinfo_zalloc)("di.image.ML_ifds.2", 705436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov 20 + VG_(strlen)(filename) 706436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov + VG_(strlen)(serverAddr)); 707436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov VG_(sprintf)(img->source.name, "%s at %s", filename, serverAddr); 708436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov 709436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov /* img->ces is already zeroed out */ 710436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov vg_assert(img->source.fd >= 0); 711436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov 712436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov /* See comment on equivalent bit in ML_(img_from_local_file) for 713436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov rationale. */ 714436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov UInt entNo = alloc_CEnt(img); 715436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov vg_assert(entNo == 0); 716436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov set_CEnt(img, 0, 0); 717436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov 718436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov return img; 719436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov 720436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov fail: 721436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov if (req) free_Frame(req); 722436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov if (res) { 723436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov UChar* reason = NULL; 724436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov if (parse_Frame_asciiz(res, "FAIL", &reason)) { 725436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov // HACK: if it's just telling us that the file can't 726436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov // be opened, don't print it, else we'll get flooded with 727436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov // such complaints, one for each main object for which there 728436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov // isn't a debuginfo file on the server. 729436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov if (0 != VG_(strcmp)((const HChar*)reason, "OPEN: cannot open file")) 730436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov VG_(umsg)("ML_(img_from_di_server): fail: %s\n", reason); 731436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov } else { 732436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov VG_(umsg)("ML_(img_from_di_server): fail: unknown reason\n"); 733436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov } 734436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov free_Frame(res); 735436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov } 736436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov VG_(close)(sd); 737436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov return NULL; 738436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov} 739436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov 740436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanovvoid ML_(img_done)(DiImage* img) 741436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov{ 742436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov vg_assert(img); 743436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov if (img->source.is_local) { 744436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov /* Close the file; nothing else to do. */ 745436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov vg_assert(img->source.session_id == 0); 746436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov VG_(close)(img->source.fd); 747436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov } else { 748436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov /* Close the socket. The server can detect this and will scrub 749436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov the connection when it happens, so there's no need to tell it 750436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov explicitly by sending it a "CLOSE" message, or any such. */ 751436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov vg_assert(img->source.session_id != 0); 752436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov VG_(close)(img->source.fd); 753436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov } 754436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov 755436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov /* Free up the cache entries, ultimately |img| itself. */ 756436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov UInt i; 757436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov vg_assert(img->ces_used <= CACHE_N_ENTRIES); 758436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov for (i = 0; i < img->ces_used; i++) { 759436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov ML_(dinfo_free)(img->ces[i]); 760436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov } 761436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov /* Take the opportunity to sanity check the rest. */ 762436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov for (i = i; i < img->ces_used; i++) { 763436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov vg_assert(img->ces[i] == NULL); 764436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov } 765436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov ML_(dinfo_free)(img->source.name); 766436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov ML_(dinfo_free)(img); 767436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov} 768436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov 769436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy IvanovDiOffT ML_(img_size)(DiImage* img) 770436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov{ 771436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov vg_assert(img); 772436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov return img->size; 773436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov} 774436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov 775436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanovinline Bool ML_(img_valid)(DiImage* img, DiOffT offset, SizeT size) 776436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov{ 777436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov vg_assert(img); 778436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov vg_assert(offset != DiOffT_INVALID); 779436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov return img->size > 0 && offset + size <= (DiOffT)img->size; 780436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov} 781436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov 782436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov/* Check the given range is valid, and if not, shut down the system. 783436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov An invalid range would imply that we're trying to read outside the 784436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov image, which normally means the image is corrupted somehow, or the 785436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov caller is buggy. Recovering is too complex, and we have 786436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov probably-corrupt debuginfo, so just give up. */ 787436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanovstatic void ensure_valid(DiImage* img, DiOffT offset, SizeT size, 788436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov const HChar* caller) 789436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov{ 790436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov if (LIKELY(ML_(img_valid)(img, offset, size))) 791436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov return; 792436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov VG_(umsg)("Valgrind: debuginfo reader: ensure_valid failed:\n"); 793436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov VG_(umsg)("Valgrind: during call to %s\n", caller); 794436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov VG_(umsg)("Valgrind: request for range [%llu, +%llu) exceeds\n", 795436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov (ULong)offset, (ULong)size); 796436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov VG_(umsg)("Valgrind: valid image size of %llu for image:\n", 797436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov (ULong)img->size); 798436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov VG_(umsg)("Valgrind: \"%s\"\n", img->source.name); 799436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov give_up__image_overrun(); 800436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov} 801436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov 802436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov 803436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanovvoid ML_(img_get)(/*OUT*/void* dst, 804436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov DiImage* img, DiOffT offset, SizeT size) 805436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov{ 806436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov vg_assert(img); 807436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov vg_assert(size > 0); 808436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov ensure_valid(img, offset, size, "ML_(img_get)"); 809436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov SizeT i; 810436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov for (i = 0; i < size; i++) { 811436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov ((UChar*)dst)[i] = get(img, offset + i); 812436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov } 813436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov} 814436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov 815436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy IvanovSizeT ML_(img_get_some)(/*OUT*/void* dst, 816436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov DiImage* img, DiOffT offset, SizeT size) 817436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov{ 818436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov vg_assert(img); 819436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov vg_assert(size > 0); 820436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov ensure_valid(img, offset, size, "ML_(img_get_some)"); 821436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov UChar* dstU = (UChar*)dst; 822436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov /* Use |get| in the normal way to get the first byte of the range. 823436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov This guarantees to put the cache entry containing |offset| in 824436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov position zero. */ 825436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov dstU[0] = get(img, offset); 826436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov /* Now just read as many bytes as we can (or need) directly out of 827436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov entry zero, without bothering to call |get| each time. */ 828436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov CEnt* ce = img->ces[0]; 829436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov vg_assert(ce && ce->used >= 1); 830436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov vg_assert(is_in_CEnt(ce, offset)); 831436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov SizeT nToCopy = size - 1; 832436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov SizeT nAvail = (SizeT)(ce->used - (offset + 1 - ce->off)); 833436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov vg_assert(nAvail >= 0 && nAvail <= ce->used-1); 834436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov if (nAvail < nToCopy) nToCopy = nAvail; 835436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov VG_(memcpy)(&dstU[1], &ce->data[offset + 1 - ce->off], nToCopy); 836436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov return nToCopy + 1; 837436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov} 838436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov 839436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov 840436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy IvanovSizeT ML_(img_strlen)(DiImage* img, DiOffT off) 841436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov{ 842436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov ensure_valid(img, off, 1, "ML_(img_strlen)"); 843436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov SizeT i = 0; 844436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov while (get(img, off + i) != 0) i++; 845436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov return i; 846436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov} 847436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov 848436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy IvanovHChar* ML_(img_strdup)(DiImage* img, const HChar* cc, DiOffT offset) 849436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov{ 850436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov ensure_valid(img, offset, 1, "ML_(img_strdup)"); 851436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov SizeT len = ML_(img_strlen)(img, offset); 852436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov HChar* res = ML_(dinfo_zalloc)(cc, len+1); 853436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov SizeT i; 854436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov for (i = 0; i < len; i++) { 855436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov res[i] = get(img, offset+i); 856436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov } 857436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov vg_assert(res[len] == 0); 858436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov return res; 859436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov} 860436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov 861436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy IvanovInt ML_(img_strcmp)(DiImage* img, DiOffT off1, DiOffT off2) 862436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov{ 863436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov ensure_valid(img, off1, 1, "ML_(img_strcmp)(first arg)"); 864436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov ensure_valid(img, off2, 1, "ML_(img_strcmp)(second arg)"); 865436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov while (True) { 866436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov UChar c1 = get(img, off1); 867436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov UChar c2 = get(img, off2); 868436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov if (c1 < c2) return -1; 869436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov if (c1 > c2) return 1; 870436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov if (c1 == 0) return 0; 871436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov off1++; off2++; 872436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov } 873436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov} 874436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov 875436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy IvanovInt ML_(img_strcmp_c)(DiImage* img, DiOffT off1, const HChar* str2) 876436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov{ 877436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov ensure_valid(img, off1, 1, "ML_(img_strcmp_c)"); 878436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov while (True) { 879436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov UChar c1 = get(img, off1); 880436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov UChar c2 = *(UChar*)str2; 881436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov if (c1 < c2) return -1; 882436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov if (c1 > c2) return 1; 883436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov if (c1 == 0) return 0; 884436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov off1++; str2++; 885436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov } 886436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov} 887436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov 888436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy IvanovUChar ML_(img_get_UChar)(DiImage* img, DiOffT offset) 889436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov{ 890436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov ensure_valid(img, offset, 1, "ML_(img_get_UChar)"); 891436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov return get(img, offset); 892436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov} 893436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov 894436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy IvanovUShort ML_(img_get_UShort)(DiImage* img, DiOffT offset) 895436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov{ 896436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov UShort r; 897436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov ML_(img_get)(&r, img, offset, sizeof(r)); 898436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov return r; 899436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov} 900436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov 901436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy IvanovUInt ML_(img_get_UInt)(DiImage* img, DiOffT offset) 902436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov{ 903436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov UInt r; 904436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov ML_(img_get)(&r, img, offset, sizeof(r)); 905436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov return r; 906436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov} 907436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov 908436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy IvanovULong ML_(img_get_ULong)(DiImage* img, DiOffT offset) 909436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov{ 910436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov ULong r; 911436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov ML_(img_get)(&r, img, offset, sizeof(r)); 912436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov return r; 913436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov} 914436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov 915436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov 916436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov/* 917436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov * This routine for calculating the CRC for a separate debug file 918436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov * is GPLed code borrowed from GNU binutils. 919436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov */ 920436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy IvanovUInt ML_(img_calc_gnu_debuglink_crc32)(DiImage* img) 921436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov{ 922436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov static const UInt crc32_table[256] = 923436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov { 924436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov 0x00000000, 0x77073096, 0xee0e612c, 0x990951ba, 0x076dc419, 925436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov 0x706af48f, 0xe963a535, 0x9e6495a3, 0x0edb8832, 0x79dcb8a4, 926436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov 0xe0d5e91e, 0x97d2d988, 0x09b64c2b, 0x7eb17cbd, 0xe7b82d07, 927436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov 0x90bf1d91, 0x1db71064, 0x6ab020f2, 0xf3b97148, 0x84be41de, 928436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov 0x1adad47d, 0x6ddde4eb, 0xf4d4b551, 0x83d385c7, 0x136c9856, 929436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov 0x646ba8c0, 0xfd62f97a, 0x8a65c9ec, 0x14015c4f, 0x63066cd9, 930436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov 0xfa0f3d63, 0x8d080df5, 0x3b6e20c8, 0x4c69105e, 0xd56041e4, 931436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov 0xa2677172, 0x3c03e4d1, 0x4b04d447, 0xd20d85fd, 0xa50ab56b, 932436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov 0x35b5a8fa, 0x42b2986c, 0xdbbbc9d6, 0xacbcf940, 0x32d86ce3, 933436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov 0x45df5c75, 0xdcd60dcf, 0xabd13d59, 0x26d930ac, 0x51de003a, 934436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov 0xc8d75180, 0xbfd06116, 0x21b4f4b5, 0x56b3c423, 0xcfba9599, 935436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov 0xb8bda50f, 0x2802b89e, 0x5f058808, 0xc60cd9b2, 0xb10be924, 936436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov 0x2f6f7c87, 0x58684c11, 0xc1611dab, 0xb6662d3d, 0x76dc4190, 937436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov 0x01db7106, 0x98d220bc, 0xefd5102a, 0x71b18589, 0x06b6b51f, 938436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov 0x9fbfe4a5, 0xe8b8d433, 0x7807c9a2, 0x0f00f934, 0x9609a88e, 939436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov 0xe10e9818, 0x7f6a0dbb, 0x086d3d2d, 0x91646c97, 0xe6635c01, 940436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov 0x6b6b51f4, 0x1c6c6162, 0x856530d8, 0xf262004e, 0x6c0695ed, 941436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov 0x1b01a57b, 0x8208f4c1, 0xf50fc457, 0x65b0d9c6, 0x12b7e950, 942436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov 0x8bbeb8ea, 0xfcb9887c, 0x62dd1ddf, 0x15da2d49, 0x8cd37cf3, 943436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov 0xfbd44c65, 0x4db26158, 0x3ab551ce, 0xa3bc0074, 0xd4bb30e2, 944436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov 0x4adfa541, 0x3dd895d7, 0xa4d1c46d, 0xd3d6f4fb, 0x4369e96a, 945436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov 0x346ed9fc, 0xad678846, 0xda60b8d0, 0x44042d73, 0x33031de5, 946436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov 0xaa0a4c5f, 0xdd0d7cc9, 0x5005713c, 0x270241aa, 0xbe0b1010, 947436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov 0xc90c2086, 0x5768b525, 0x206f85b3, 0xb966d409, 0xce61e49f, 948436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov 0x5edef90e, 0x29d9c998, 0xb0d09822, 0xc7d7a8b4, 0x59b33d17, 949436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov 0x2eb40d81, 0xb7bd5c3b, 0xc0ba6cad, 0xedb88320, 0x9abfb3b6, 950436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov 0x03b6e20c, 0x74b1d29a, 0xead54739, 0x9dd277af, 0x04db2615, 951436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov 0x73dc1683, 0xe3630b12, 0x94643b84, 0x0d6d6a3e, 0x7a6a5aa8, 952436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov 0xe40ecf0b, 0x9309ff9d, 0x0a00ae27, 0x7d079eb1, 0xf00f9344, 953436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov 0x8708a3d2, 0x1e01f268, 0x6906c2fe, 0xf762575d, 0x806567cb, 954436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov 0x196c3671, 0x6e6b06e7, 0xfed41b76, 0x89d32be0, 0x10da7a5a, 955436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov 0x67dd4acc, 0xf9b9df6f, 0x8ebeeff9, 0x17b7be43, 0x60b08ed5, 956436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov 0xd6d6a3e8, 0xa1d1937e, 0x38d8c2c4, 0x4fdff252, 0xd1bb67f1, 957436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov 0xa6bc5767, 0x3fb506dd, 0x48b2364b, 0xd80d2bda, 0xaf0a1b4c, 958436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov 0x36034af6, 0x41047a60, 0xdf60efc3, 0xa867df55, 0x316e8eef, 959436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov 0x4669be79, 0xcb61b38c, 0xbc66831a, 0x256fd2a0, 0x5268e236, 960436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov 0xcc0c7795, 0xbb0b4703, 0x220216b9, 0x5505262f, 0xc5ba3bbe, 961436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov 0xb2bd0b28, 0x2bb45a92, 0x5cb36a04, 0xc2d7ffa7, 0xb5d0cf31, 962436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov 0x2cd99e8b, 0x5bdeae1d, 0x9b64c2b0, 0xec63f226, 0x756aa39c, 963436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov 0x026d930a, 0x9c0906a9, 0xeb0e363f, 0x72076785, 0x05005713, 964436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov 0x95bf4a82, 0xe2b87a14, 0x7bb12bae, 0x0cb61b38, 0x92d28e9b, 965436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov 0xe5d5be0d, 0x7cdcefb7, 0x0bdbdf21, 0x86d3d2d4, 0xf1d4e242, 966436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov 0x68ddb3f8, 0x1fda836e, 0x81be16cd, 0xf6b9265b, 0x6fb077e1, 967436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov 0x18b74777, 0x88085ae6, 0xff0f6a70, 0x66063bca, 0x11010b5c, 968436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov 0x8f659eff, 0xf862ae69, 0x616bffd3, 0x166ccf45, 0xa00ae278, 969436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov 0xd70dd2ee, 0x4e048354, 0x3903b3c2, 0xa7672661, 0xd06016f7, 970436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov 0x4969474d, 0x3e6e77db, 0xaed16a4a, 0xd9d65adc, 0x40df0b66, 971436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov 0x37d83bf0, 0xa9bcae53, 0xdebb9ec5, 0x47b2cf7f, 0x30b5ffe9, 972436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov 0xbdbdf21c, 0xcabac28a, 0x53b39330, 0x24b4a3a6, 0xbad03605, 973436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov 0xcdd70693, 0x54de5729, 0x23d967bf, 0xb3667a2e, 0xc4614ab8, 974436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov 0x5d681b02, 0x2a6f2b94, 0xb40bbe37, 0xc30c8ea1, 0x5a05df1b, 975436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov 0x2d02ef8d 976436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov }; 977436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov 978436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov vg_assert(img); 979436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov 980436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov /* If the image is local, calculate the CRC here directly. If it's 981436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov remote, forward the request to the server. */ 982436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov if (img->source.is_local) { 983436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov /* Work through the image in 1 KB chunks. */ 984436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov UInt crc = 0xFFFFFFFF; 985436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov DiOffT img_szB = ML_(img_size)(img); 986436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov DiOffT curr_off = 0; 987436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov while (1) { 988436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov vg_assert(curr_off >= 0 && curr_off <= img_szB); 989436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov if (curr_off == img_szB) break; 990436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov DiOffT avail = img_szB - curr_off; 991436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov vg_assert(avail > 0 && avail <= img_szB); 992436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov if (avail > 1024) avail = 1024; 993436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov UChar buf[1024]; 994436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov SizeT nGot = ML_(img_get_some)(buf, img, curr_off, avail); 995436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov vg_assert(nGot >= 1 && nGot <= avail); 996436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov UInt i; 997436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov for (i = 0; i < (UInt)nGot; i++) 998436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov crc = crc32_table[(crc ^ buf[i]) & 0xff] ^ (crc >> 8); 999436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov curr_off += nGot; 1000436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov } 1001436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov return ~crc & 0xFFFFFFFF; 1002436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov } else { 1003436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov Frame* req = mk_Frame_noargs("CRC3"); 1004436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov Frame* res = do_transaction(img->source.fd, req); 1005436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov if (!res) goto remote_crc_fail; 1006436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov ULong crc32 = 0; 1007436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov if (!parse_Frame_le64(res, "CROK", &crc32)) goto remote_crc_fail; 1008436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov if ((crc32 & ~0xFFFFFFFFULL) != 0) goto remote_crc_fail; 1009436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov if (req) free_Frame(req); 1010436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov if (res) free_Frame(res); 1011436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov return (UInt)crc32; 1012436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov remote_crc_fail: 1013436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov 1014436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov // XXXX common this up with the READ diagnostic cases 1015436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov if (res) { 1016436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov UChar* reason = NULL; 1017436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov if (parse_Frame_asciiz(res, "FAIL", &reason)) { 1018436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov VG_(umsg)("img_calc_gnu_debuglink_crc32: fail: " 1019436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov "%s\n", reason); 1020436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov } else { 1021436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov VG_(umsg)("img_calc_gnu_debuglink_crc32: fail: " 1022436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov "unknown reason\n"); 1023436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov } 1024436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov } else { 1025436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov VG_(umsg)("img_calc_gnu_debuglink_crc32: fail: " 1026436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov "server unexpectedly closed the connection\n"); 1027436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov } 1028436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov 1029436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov if (req) free_Frame(req); 1030436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov if (res) free_Frame(res); 1031436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov // FIXME: now what? 1032436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov give_up__comms_lost(); 1033436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov /* NOTREACHED */ 1034436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov vg_assert(0); 1035436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov } 1036436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov /*NOTREACHED*/ 1037436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov vg_assert(0); 1038436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov} 1039436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov 1040436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov//////////////////////////////////////////////////// 1041436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov#include "minilzo-inl.c" 1042436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov 1043436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov/*--------------------------------------------------------------------*/ 1044436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov/*--- end image.c ---*/ 1045436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov/*--------------------------------------------------------------------*/ 1046