1/* -*- mode: C; c-basic-offset: 3; -*- */ 2 3/*--------------------------------------------------------------------*/ 4/*--- An abstraction that provides a file-reading mechanism. ---*/ 5/*--- image.c ---*/ 6/*--------------------------------------------------------------------*/ 7 8/* 9 This file is part of Valgrind, a dynamic binary instrumentation 10 framework. 11 12 Copyright (C) 2013-2017 Mozilla Foundation 13 14 This program is free software; you can redistribute it and/or 15 modify it under the terms of the GNU General Public License as 16 published by the Free Software Foundation; either version 2 of the 17 License, or (at your option) any later version. 18 19 This program is distributed in the hope that it will be useful, but 20 WITHOUT ANY WARRANTY; without even the implied warranty of 21 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 22 General Public License for more details. 23 24 You should have received a copy of the GNU General Public License 25 along with this program; if not, write to the Free Software 26 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 27 02111-1307, USA. 28 29 The GNU General Public License is contained in the file COPYING. 30*/ 31 32/* Contributed by Julian Seward <jseward@acm.org> */ 33 34/* See the corresponding auxprogs/valgrind-di-server.c for a list of 35 cleanups for this file and itself. */ 36 37#include "pub_core_basics.h" 38#include "pub_core_vki.h" 39#include "pub_core_libcbase.h" 40#include "pub_core_libcassert.h" 41#include "pub_core_libcprint.h" 42#include "pub_core_libcproc.h" /* VG_(read_millisecond_timer) */ 43#include "pub_core_libcfile.h" 44#include "priv_misc.h" /* dinfo_zalloc/free/strdup */ 45#include "priv_image.h" /* self */ 46 47#include "minilzo.h" 48#define TINFL_HEADER_FILE_ONLY 49#include "tinfl.c" 50 51/* These values (1024 entries of 8192 bytes each) gives a cache 52 size of 8MB. */ 53#define CACHE_ENTRY_SIZE_BITS (12+1) 54#define CACHE_N_ENTRIES 1024 55 56#define CACHE_ENTRY_SIZE (1 << CACHE_ENTRY_SIZE_BITS) 57 58#define COMPRESSED_SLICE_ARRAY_GROW_SIZE 64 59 60/* An entry in the cache. */ 61typedef 62 struct { 63 Bool fromC; // True === contains decompressed data 64 DiOffT off; // file offset for data[0] 65 SizeT size; // sizeof(data) 66 SizeT used; // 1 .. sizeof(data), or 0 to denote not-in-use 67 UChar data[]; 68 } 69 CEnt; 70 71/* Compressed slice */ 72typedef 73 struct { 74 DiOffT offD; // offset of decompressed data 75 SizeT szD; // size of decompressed data 76 DiOffT offC; // offset of compressed data 77 SizeT szC; // size of compressed data 78 } 79 CSlc; 80 81/* Source for files */ 82typedef 83 struct { 84 // True: img is of local file. False: img is from a server. 85 Bool is_local; 86 // The fd for the local file, or sd for a remote server. 87 Int fd; 88 // The name. In ML_(dinfo_zalloc)'d space. Used only for printing 89 // error messages; hence it doesn't really matter what this contains. 90 HChar* name; 91 // The rest of these fields are only valid when using remote files 92 // (that is, using a debuginfo server; hence when is_local==False) 93 // Session ID allocated to us by the server. Cannot be zero. 94 ULong session_id; 95 } 96 Source; 97 98struct _DiImage { 99 // The source -- how to get hold of the file we are reading 100 Source source; 101 // Virtual size of the image = real size + size of uncompressed data 102 SizeT size; 103 // Real size of image 104 SizeT real_size; 105 // The number of entries used. 0 .. CACHE_N_ENTRIES 106 UInt ces_used; 107 // Pointers to the entries. ces[0 .. ces_used-1] are non-NULL. 108 // ces[ces_used .. CACHE_N_ENTRIES-1] are NULL. 109 // The non-NULL entries may be arranged arbitrarily. We expect to use 110 // a pseudo-LRU scheme though. 111 CEnt* ces[CACHE_N_ENTRIES]; 112 113 // Array of compressed slices 114 CSlc* cslc; 115 // Number of compressed slices used 116 UInt cslc_used; 117 // Size of cslc array 118 UInt cslc_size; 119}; 120 121 122/* Sanity check code for CEnts. */ 123static void pp_CEnt(const HChar* msg, CEnt* ce) 124{ 125 VG_(printf)("%s: fromC %s, used %llu, size %llu, offset %llu\n", 126 msg, ce->fromC ? "True" : "False", 127 (ULong)ce->used, (ULong)ce->size, (ULong)ce->off); 128} 129 130static Bool is_sane_CEnt ( const HChar* who, const DiImage* img, UInt i ) 131{ 132 vg_assert(img); 133 vg_assert(i <= CACHE_N_ENTRIES); 134 135 CEnt* ce = img->ces[i]; 136 if (!(ce->used <= ce->size)) goto fail; 137 if (ce->fromC) { 138 // ce->size can be anything, but ce->used must be either the 139 // same or zero, in the case that it hasn't been set yet. 140 // Similarly, ce->off must either be above the real_size 141 // threshold, or zero if it hasn't been set yet. 142 if (!(ce->off >= img->real_size || ce->off == 0)) goto fail; 143 if (!(ce->off + ce->used <= img->size)) goto fail; 144 if (!(ce->used == ce->size || ce->used == 0)) goto fail; 145 } else { 146 if (!(ce->size == CACHE_ENTRY_SIZE)) goto fail; 147 if (!(ce->off >= 0)) goto fail; 148 if (!(ce->off + ce->used <= img->real_size)) goto fail; 149 } 150 return True; 151 152 fail: 153 VG_(printf)("is_sane_CEnt[%u]: fail: %s\n", i, who); 154 pp_CEnt("failing CEnt", ce); 155 return False; 156} 157 158 159/* A frame. The first 4 bytes of |data| give the kind of the frame, 160 and the rest of it is kind-specific data. */ 161typedef struct { UChar* data; SizeT n_data; } Frame; 162 163static void write_UInt_le ( /*OUT*/UChar* dst, UInt n ) 164{ 165 Int i; 166 for (i = 0; i <= 3; i++) { 167 dst[i] = (UChar)(n & 0xFF); 168 n >>= 8; 169 } 170} 171 172static UInt read_UInt_le ( const UChar* src ) 173{ 174 UInt r = 0; 175 Int i; 176 for (i = 3; i >= 0; i--) { 177 r <<= 8; 178 r += (UInt)src[i]; 179 } 180 return r; 181} 182 183static void write_ULong_le ( /*OUT*/UChar* dst, ULong n ) 184{ 185 Int i; 186 for (i = 0; i <= 7; i++) { 187 dst[i] = (UChar)(n & 0xFF); 188 n >>= 8; 189 } 190} 191 192static ULong read_ULong_le ( const UChar* src ) 193{ 194 ULong r = 0; 195 Int i; 196 for (i = 7; i >= 0; i--) { 197 r <<= 8; 198 r += (ULong)src[i]; 199 } 200 return r; 201} 202 203 204/* Set |sd| to be blocking. Returns True on success. */ 205static Bool set_blocking ( int sd ) 206{ 207 Int res; 208 res = VG_(fcntl)(sd, VKI_F_GETFL, 0/*ignored*/); 209 if (res != -1) 210 res = VG_(fcntl)(sd, VKI_F_SETFL, res & ~VKI_O_NONBLOCK); 211 return (res != -1); 212} 213 214/* Tries to read 'len' bytes from fd, blocking if necessary. Assumes 215 fd has been set in blocking mode. If it returns with the number of 216 bytes read < len, it means that either fd was closed, or there was 217 an error on it. */ 218static Int my_read ( Int fd, UChar* buf, Int len ) 219{ 220 Int nRead = 0; 221 while (1) { 222 if (nRead == len) return nRead; 223 vg_assert(nRead < len); 224 Int nNeeded = len - nRead; 225 vg_assert(nNeeded > 0); 226 Int n = VG_(read)(fd, &buf[nRead], nNeeded); 227 if (n <= 0) return nRead; /* error or EOF */ 228 nRead += n; 229 } 230} 231 232/* Tries to write 'len' bytes to fd, blocking if necessary. Assumes 233 fd has been set in blocking mode. If it returns with the number of 234 bytes written < len, it means that either fd was closed, or there was 235 an error on it. */ 236static Int my_write ( Int fd, const UChar* buf, Int len ) 237{ 238 Int nWritten = 0; 239 while (1) { 240 if (nWritten == len) return nWritten; 241 vg_assert(nWritten < len); 242 Int nStillToDo = len - nWritten; 243 vg_assert(nStillToDo > 0); 244 Int n = VG_(write_socket)(fd, &buf[nWritten], nStillToDo); 245 if (n < 0) return nWritten; /* error or EOF */ 246 nWritten += n; 247 } 248} 249 250/* If we lost communication with the remote server, just give up. 251 Recovering is too difficult. */ 252static void give_up__comms_lost(void) 253{ 254 VG_(umsg)("\n"); 255 VG_(umsg)( 256 "Valgrind: debuginfo reader: Lost communication with the remote\n"); 257 VG_(umsg)( 258 "Valgrind: debuginfo server. I can't recover. Giving up. Sorry.\n"); 259 VG_(umsg)("\n"); 260 VG_(exit)(1); 261 /*NOTREACHED*/ 262} 263 264static void give_up__image_overrun(void) 265{ 266 VG_(umsg)("\n"); 267 VG_(umsg)( 268 "Valgrind: debuginfo reader: Possibly corrupted debuginfo file.\n"); 269 VG_(umsg)( 270 "Valgrind: I can't recover. Giving up. Sorry.\n"); 271 VG_(umsg)("\n"); 272 VG_(exit)(1); 273 /*NOTREACHED*/ 274} 275 276/* "Do" a transaction: that is, send the given frame to the server and 277 return the frame it sends back. Caller owns the resulting frame 278 and must free it. A NULL return means the transaction failed for 279 some reason. */ 280static Frame* do_transaction ( Int sd, const Frame* req ) 281{ 282 if (0) VG_(printf)("CLIENT: send %c%c%c%c\n", 283 req->data[0], req->data[1], req->data[2], req->data[3]); 284 285 /* What goes on the wire is: 286 adler(le32) n_data(le32) data[0 .. n_data-1] 287 where the checksum covers n_data as well as data[]. 288 */ 289 /* The initial Adler-32 value */ 290 UInt adler = VG_(adler32)(0, NULL, 0); 291 292 /* Fold in the length field, encoded as le32. */ 293 UChar wr_first8[8]; 294 write_UInt_le(&wr_first8[4], req->n_data); 295 adler = VG_(adler32)(adler, &wr_first8[4], 4); 296 /* Fold in the data values */ 297 adler = VG_(adler32)(adler, req->data, req->n_data); 298 write_UInt_le(&wr_first8[0], adler); 299 300 Int r = my_write(sd, &wr_first8[0], 8); 301 if (r != 8) return NULL; 302 vg_assert(req->n_data >= 4); // else ill formed -- no KIND field 303 r = my_write(sd, req->data, req->n_data); 304 if (r != req->n_data) return NULL; 305 306 /* So, the request is sent. Now get a request of the same format 307 out of the channel. */ 308 UChar rd_first8[8]; // adler32; length32 309 r = my_read(sd, &rd_first8[0], 8); 310 if (r != 8) return NULL; 311 UInt rd_adler = read_UInt_le(&rd_first8[0]); 312 UInt rd_len = read_UInt_le(&rd_first8[4]); 313 /* Allocate a Frame to hold the result data, and read into it. */ 314 // Reject obviously-insane length fields. 315 if (rd_len < 4 || rd_len > 4*1024*1024) return NULL; 316 Frame* res = ML_(dinfo_zalloc)("di.do_transaction.1", sizeof(Frame)); 317 res->n_data = rd_len; 318 res->data = ML_(dinfo_zalloc)("di.do_transaction.2", rd_len); 319 r = my_read(sd, res->data, res->n_data); 320 if (r != rd_len) return NULL; 321 322 if (0) VG_(printf)("CLIENT: recv %c%c%c%c\n", 323 res->data[0], res->data[1], res->data[2], res->data[3]); 324 325 /* Compute the checksum for the received data, and check it. */ 326 adler = VG_(adler32)(0, NULL, 0); // initial value 327 adler = VG_(adler32)(adler, &rd_first8[4], 4); 328 if (res->n_data > 0) 329 adler = VG_(adler32)(adler, res->data, res->n_data); 330 331 if (adler/*computed*/ != rd_adler/*expected*/) return NULL; 332 return res; 333} 334 335static void free_Frame ( Frame* fr ) 336{ 337 vg_assert(fr && fr->data); 338 ML_(dinfo_free)(fr->data); 339 ML_(dinfo_free)(fr); 340} 341 342static Frame* mk_Frame_noargs ( const HChar* tag ) 343{ 344 vg_assert(VG_(strlen)(tag) == 4); 345 Frame* f = ML_(dinfo_zalloc)("di.mFn.1", sizeof(Frame)); 346 f->n_data = 4; 347 f->data = ML_(dinfo_zalloc)("di.mFn.2", f->n_data); 348 VG_(memcpy)(&f->data[0], tag, 4); 349 return f; 350} 351 352static Frame* mk_Frame_le64_le64_le64 ( const HChar* tag, 353 ULong n1, ULong n2, ULong n3 ) 354{ 355 vg_assert(VG_(strlen)(tag) == 4); 356 Frame* f = ML_(dinfo_zalloc)("di.mFlll.1", sizeof(Frame)); 357 f->n_data = 4 + 3*8; 358 f->data = ML_(dinfo_zalloc)("di.mFlll.2", f->n_data); 359 VG_(memcpy)(&f->data[0], tag, 4); 360 write_ULong_le(&f->data[4 + 0*8], n1); 361 write_ULong_le(&f->data[4 + 1*8], n2); 362 write_ULong_le(&f->data[4 + 2*8], n3); 363 return f; 364} 365 366static Frame* mk_Frame_asciiz ( const HChar* tag, const HChar* str ) 367{ 368 vg_assert(VG_(strlen)(tag) == 4); 369 Frame* f = ML_(dinfo_zalloc)("di.mFa.1", sizeof(Frame)); 370 SizeT n_str = VG_(strlen)(str); 371 f->n_data = 4 + n_str + 1; 372 f->data = ML_(dinfo_zalloc)("di.mFa.2", f->n_data); 373 VG_(memcpy)(&f->data[0], tag, 4); 374 VG_(memcpy)(&f->data[4], str, n_str); 375 vg_assert(f->data[4 + n_str] == 0); 376 return f; 377} 378 379static Bool parse_Frame_le64 ( const Frame* fr, const HChar* tag, 380 /*OUT*/ULong* n1 ) 381{ 382 vg_assert(VG_(strlen)(tag) == 4); 383 if (!fr || !fr->data) return False; 384 if (fr->n_data < 4) return False; 385 if (VG_(memcmp)(&fr->data[0], tag, 4) != 0) return False; 386 if (fr->n_data != 4 + 1*8) return False; 387 *n1 = read_ULong_le(&fr->data[4 + 0*8]); 388 return True; 389} 390 391static Bool parse_Frame_le64_le64 ( const Frame* fr, const HChar* tag, 392 /*OUT*/ULong* n1, /*OUT*/ULong* n2 ) 393{ 394 vg_assert(VG_(strlen)(tag) == 4); 395 if (!fr || !fr->data) return False; 396 if (fr->n_data < 4) return False; 397 if (VG_(memcmp)(&fr->data[0], tag, 4) != 0) return False; 398 if (fr->n_data != 4 + 2*8) return False; 399 *n1 = read_ULong_le(&fr->data[4 + 0*8]); 400 *n2 = read_ULong_le(&fr->data[4 + 1*8]); 401 return True; 402} 403 404static Bool parse_Frame_asciiz ( const Frame* fr, const HChar* tag, 405 /*OUT*/UChar** str ) 406{ 407 vg_assert(VG_(strlen)(tag) == 4); 408 if (!fr || !fr->data) return False; 409 if (fr->n_data < 4) return False; 410 if (VG_(memcmp)(&fr->data[0], tag, 4) != 0) return False; 411 if (fr->n_data < 5) return False; // else there isn't even enough 412 // space for the terminating zero 413 /* Find the terminating zero and ensure it's right at the end 414 of the data. If not, the frame is malformed. */ 415 SizeT i = 4; 416 while (True) { 417 if (i >= fr->n_data) break; 418 if (fr->data[i] == 0) break; 419 i++; 420 } 421 vg_assert(i <= fr->n_data); 422 if (i == fr->n_data-1 && fr->data[i] == 0) { 423 *str = &fr->data[4]; 424 return True; 425 } else { 426 return False; 427 } 428} 429 430static Bool parse_Frame_le64_le64_le64_bytes ( 431 const Frame* fr, const HChar* tag, 432 /*OUT*/ULong* n1, /*OUT*/ULong* n2, /*OUT*/ULong* n3, 433 /*OUT*/UChar** data, /*OUT*/ULong* n_data 434 ) 435{ 436 vg_assert(VG_(strlen)(tag) == 4); 437 if (!fr || !fr->data) return False; 438 if (fr->n_data < 4) return False; 439 if (VG_(memcmp)(&fr->data[0], tag, 4) != 0) return False; 440 if (fr->n_data < 4 + 3*8) return False; 441 *n1 = read_ULong_le(&fr->data[4 + 0*8]); 442 *n2 = read_ULong_le(&fr->data[4 + 1*8]); 443 *n3 = read_ULong_le(&fr->data[4 + 2*8]); 444 *data = &fr->data[4 + 3*8]; 445 *n_data = fr->n_data - (4 + 3*8); 446 vg_assert(fr->n_data >= 4 + 3*8); 447 return True; 448} 449 450static DiOffT block_round_down ( DiOffT i ) 451{ 452 return i & ((DiOffT)~(CACHE_ENTRY_SIZE-1)); 453} 454 455/* Is this offset inside this CEnt? */ 456static inline Bool is_in_CEnt ( const CEnt* cent, DiOffT off ) 457{ 458 /* This assertion is checked by set_CEnt, so checking it here has 459 no benefit, whereas skipping it does remove it from the hottest 460 path. */ 461 /* vg_assert(cent->used > 0 && cent->used <= cent->size); */ 462 /* What we want to return is: 463 cent->off <= off && off < cent->off + cent->used; 464 This is however a very hot path, so here's alternative that uses 465 only one conditional branch, using the following transformation, 466 where all quantities are unsigned: 467 x >= LO && x < LO+N 468 --> x-LO >= 0 && x-LO < LO+N-LO 469 --> x-LO >= 0 && x-LO < N 470 --> x-LO < N 471 This is however only valid when the original bounds, that is, LO 472 .. LO+N-1, do not wrap around the end of the address space. That 473 is, we require that LO <= LO+N-1. But that's OK .. we don't 474 expect wraparounds in CEnts or for that matter any object 475 allocated from C-land. See Hacker's Delight, Chapter 4.1, 476 "Checking Bounds of Integers", for more details. 477 */ 478 return off - cent->off < cent->used; 479} 480 481/* Returns pointer to CSlc or NULL */ 482static inline CSlc* find_cslc ( DiImage* img, DiOffT off ) 483{ 484 for (UInt i = 0; i < img->cslc_used; i++) { 485 if ( (img->cslc[i].offD <= off) 486 && (img->cslc[i].offD + img->cslc[i].szD > off) 487 ) 488 return &img->cslc[i]; 489 } 490 return NULL; 491} 492 493/* Allocate a new CEnt, connect it to |img|, and return its index. */ 494static UInt alloc_CEnt ( DiImage* img, SizeT szB, Bool fromC ) 495{ 496 vg_assert(img != NULL); 497 vg_assert(img->ces_used < CACHE_N_ENTRIES); 498 if (fromC) { 499 // szB can be arbitrary 500 } else { 501 vg_assert(szB == CACHE_ENTRY_SIZE); 502 } 503 UInt entNo = img->ces_used; 504 img->ces_used++; 505 vg_assert(img->ces[entNo] == NULL); 506 img->ces[entNo] = ML_(dinfo_zalloc)("di.alloc_CEnt.1", 507 offsetof(CEnt, data) + szB); 508 img->ces[entNo]->size = szB; 509 img->ces[entNo]->fromC = fromC; 510 vg_assert(is_sane_CEnt("alloc_CEnt", img, entNo)); 511 return entNo; 512} 513 514static void realloc_CEnt ( DiImage* img, UInt entNo, SizeT szB ) 515{ 516 vg_assert(img != NULL); 517 vg_assert(szB >= CACHE_ENTRY_SIZE); 518 vg_assert(is_sane_CEnt("realloc_CEnt-pre", img, entNo)); 519 img->ces[entNo] = ML_(dinfo_realloc)("di.realloc_CEnt.1", 520 img->ces[entNo], 521 offsetof(CEnt, data) + szB); 522} 523 524/* Move the given entry to the top and slide those above it down by 1, 525 to make space. */ 526static void move_CEnt_to_top ( DiImage* img, UInt entNo ) 527{ 528 vg_assert(img->ces_used <= CACHE_N_ENTRIES); 529 vg_assert(entNo > 0 && entNo < img->ces_used); 530 CEnt* tmp = img->ces[entNo]; 531 while (entNo > 0) { 532 img->ces[entNo] = img->ces[entNo-1]; 533 entNo--; 534 } 535 img->ces[0] = tmp; 536} 537 538/* Set the given entry so that it has a chunk of the file containing 539 the given offset. It is this function that brings data into the 540 cache, either by reading the local file or pulling it from the 541 remote server. */ 542static void set_CEnt ( const DiImage* img, UInt entNo, DiOffT off ) 543{ 544 SizeT len; 545 DiOffT off_orig = off; 546 vg_assert(img != NULL); 547 vg_assert(img->ces_used <= CACHE_N_ENTRIES); 548 vg_assert(entNo >= 0 && entNo < img->ces_used); 549 vg_assert(off < img->real_size); 550 CEnt* ce = img->ces[entNo]; 551 vg_assert(ce != NULL); 552 /* Compute [off, +len) as the slice we are going to read. */ 553 off = block_round_down(off); 554 len = img->real_size - off; 555 if (len > ce->size) 556 len = ce->size; 557 /* It is conceivable that the 'len > 0' bit could fail if we make 558 an image with a zero sized file. But then no 'get' request on 559 that image would be valid. */ 560 vg_assert(len > 0 && len <= ce->size); 561 vg_assert(off + len <= img->real_size); 562 vg_assert(off <= off_orig && off_orig < off+len); 563 /* So, read off .. off+len-1 into the entry. */ 564 565 if (0) { 566 static UInt t_last = 0; 567 static ULong nread = 0; 568 UInt now = VG_(read_millisecond_timer)(); 569 UInt delay = now - t_last; 570 t_last = now; 571 nread += len; 572 VG_(printf)("XXXXXXXX (tot %'llu) read %'lu offset %'llu delay %'u\n", 573 nread, len, off, delay); 574 } 575 576 if (img->source.is_local) { 577 // Simple: just read it 578 SysRes sr = VG_(pread)(img->source.fd, &ce->data[0], (Int)len, off); 579 vg_assert(!sr_isError(sr)); 580 } else { 581 // Not so simple: poke the server 582 vg_assert(img->source.session_id > 0); 583 Frame* req 584 = mk_Frame_le64_le64_le64("READ", img->source.session_id, off, len); 585 Frame* res = do_transaction(img->source.fd, req); 586 free_Frame(req); req = NULL; 587 if (!res) goto server_fail; 588 ULong rx_session_id = 0, rx_off = 0, rx_len = 0, rx_zdata_len = 0; 589 UChar* rx_data = NULL; 590 /* Pretty confusing. rx_sessionid, rx_off and rx_len are copies 591 of the values that we requested in the READ frame just above, 592 so we can be sure that the server is responding to the right 593 request. It just copies them from the request into the 594 response. rx_data is the actual data, and rx_zdata_len is 595 its compressed length. Hence rx_len must equal len, but 596 rx_zdata_len can be different -- smaller, hopefully.. */ 597 if (!parse_Frame_le64_le64_le64_bytes 598 (res, "RDOK", &rx_session_id, &rx_off, 599 &rx_len, &rx_data, &rx_zdata_len)) 600 goto server_fail; 601 if (rx_session_id != img->source.session_id 602 || rx_off != off || rx_len != len || rx_data == NULL) 603 goto server_fail; 604 605 //VG_(memcpy)(&ce->data[0], rx_data, len); 606 // Decompress into the destination buffer 607 // Tell the lib the max number of output bytes it can write. 608 // After the call, this holds the number of bytes actually written, 609 // and it's an error if it is different. 610 lzo_uint out_len = len; 611 Int lzo_rc = lzo1x_decompress_safe(rx_data, rx_zdata_len, 612 &ce->data[0], &out_len, 613 NULL); 614 Bool ok = lzo_rc == LZO_E_OK && out_len == len; 615 if (!ok) goto server_fail; 616 617 free_Frame(res); res = NULL; 618 goto end_of_else_clause; 619 server_fail: 620 /* The server screwed up somehow. Now what? */ 621 if (res) { 622 UChar* reason = NULL; 623 if (parse_Frame_asciiz(res, "FAIL", &reason)) { 624 VG_(umsg)("set_CEnt (reading data from DI server): fail: " 625 "%s\n", reason); 626 } else { 627 VG_(umsg)("set_CEnt (reading data from DI server): fail: " 628 "unknown reason\n"); 629 } 630 free_Frame(res); res = NULL; 631 } else { 632 VG_(umsg)("set_CEnt (reading data from DI server): fail: " 633 "server unexpectedly closed the connection\n"); 634 } 635 give_up__comms_lost(); 636 /* NOTREACHED */ 637 vg_assert(0); 638 end_of_else_clause: 639 {} 640 } 641 642 ce->off = off; 643 ce->used = len; 644 ce->fromC = False; 645 vg_assert(ce == img->ces[entNo]); 646 vg_assert(is_sane_CEnt("set_CEnt", img, entNo)); 647} 648 649__attribute__((noinline)) 650static UChar get_slowcase ( DiImage* img, DiOffT off ) 651{ 652 /* Stay sane .. */ 653 vg_assert(off < img->size); 654 vg_assert(img->ces_used <= CACHE_N_ENTRIES); 655 UInt i; 656 /* Start the search at entry 1, since the fast-case function 657 checked slot zero already. */ 658 for (i = 1; i < img->ces_used; i++) { 659 vg_assert(img->ces[i]); 660 if (is_in_CEnt(img->ces[i], off)) 661 break; 662 } 663 vg_assert(i >= 1); 664 665 if (LIKELY(i < img->ces_used)) { 666 // Found it. Move to the top and stop. 667 move_CEnt_to_top(img, i); 668 vg_assert(is_in_CEnt(img->ces[0], off)); 669 return img->ces[0]->data[ off - img->ces[0]->off ]; 670 } 671 672 vg_assert(i <= img->ces_used); 673 674 // It's not in any entry. Either allocate a new one or recycle the LRU 675 // one. This is where the presence of compressed sections makes things 676 // tricky. There are 4 cases to consider: 677 // 678 // (1) not from a compressed slice, we can allocate a new entry 679 // (2) not from a compressed slice, we have to recycle the LRU entry 680 // (3) from a compressed slice, we can allocate a new entry 681 // (4) from a compressed slice, we have to recycle the LRU entry 682 // 683 // Cases (3) and (4) are complex because we will have to call 684 // ML_(img_get_some) to get the compressed data. But this function is 685 // reachable from ML_(img_get_some), so we may re-enter get_slowcase a 686 // second time as a result. Given that the compressed data will be cause 687 // only cases (1) and (2) to happen, this guarantees no infinite recursion. 688 // It does however mean that we can't carry (in this function invokation) 689 // any local copies of the overall cache state across the ML_(img_get_some) 690 // call, since it may become invalidated by the recursive call to 691 // get_slowcase. 692 693 // First of all, see if it is in a compressed slice, and if so, pull the 694 // compressed data into an intermediate buffer. Given the preceding 695 // comment, this is a safe place to do it, since we are not carrying any 696 // cache state here apart from the knowledge that the requested offset is 697 // not in the cache at all, and the recursive call won't change that fact. 698 699 CSlc* cslc = find_cslc(img, off); 700 UChar* cbuf = NULL; 701 if (cslc != NULL) { 702 SizeT len = 0; 703 cbuf = ML_(dinfo_zalloc)("di.image.get_slowcase.cbuf-1", cslc->szC); 704 // get compressed data 705 while (len < cslc->szC) 706 len += ML_(img_get_some)(cbuf + len, img, cslc->offC + len, 707 cslc->szC - len); 708 } 709 710 // Now we can do what we like. 711 vg_assert((cslc == NULL && cbuf == NULL) || (cslc != NULL && cbuf != NULL)); 712 713 // Note, we can't capture this earlier, for exactly the reasons detailed 714 // above. 715 UInt ces_used_at_entry = img->ces_used; 716 717 // This is the size of the CEnt that we want to have after allocation or 718 // recycling. 719 SizeT size = (cslc == NULL) ? CACHE_ENTRY_SIZE : cslc->szD; 720 721 // Cases (1) and (3) 722 if (img->ces_used < CACHE_N_ENTRIES) { 723 /* Allocate a new cache entry, and fill it in. */ 724 i = alloc_CEnt(img, size, /*fromC?*/cslc != NULL); 725 if (cslc == NULL) { 726 set_CEnt(img, i, off); 727 img->ces[i]->fromC = False; 728 vg_assert(is_sane_CEnt("get_slowcase-case-1", img, i)); 729 vg_assert(img->ces_used == ces_used_at_entry + 1); 730 } else { 731 SizeT len = tinfl_decompress_mem_to_mem( 732 img->ces[i]->data, cslc->szD, 733 cbuf, cslc->szC, 734 TINFL_FLAG_USING_NON_WRAPPING_OUTPUT_BUF 735 | TINFL_FLAG_PARSE_ZLIB_HEADER); 736 vg_assert(len == cslc->szD); // sanity check on data, FIXME 737 vg_assert(cslc->szD == size); 738 img->ces[i]->used = cslc->szD; 739 img->ces[i]->off = cslc->offD; 740 img->ces[i]->fromC = True; 741 vg_assert(is_sane_CEnt("get_slowcase-case-3", img, i)); 742 vg_assert(img->ces_used == ces_used_at_entry + 1); 743 } 744 vg_assert(img->ces_used == ces_used_at_entry + 1); 745 if (i > 0) { 746 move_CEnt_to_top(img, i); 747 i = 0; 748 } 749 vg_assert(is_in_CEnt(img->ces[i], off)); 750 if (cbuf != NULL) { 751 ML_(dinfo_free)(cbuf); 752 } 753 return img->ces[i]->data[ off - img->ces[i]->off ]; 754 } 755 756 // Cases (2) and (4) 757 /* All entries in use. Recycle the (ostensibly) LRU one. But try to find 758 a non-fromC entry to recycle, though, since discarding and reloading 759 fromC entries is very expensive. The result is that -- unless all 760 CACHE_N_ENTRIES wind up being used by decompressed slices, which is 761 highly unlikely -- we'll wind up keeping all the decompressed data in 762 the cache for its entire remaining life. We could probably do better 763 but it would make the cache management even more complex. */ 764 vg_assert(img->ces_used == CACHE_N_ENTRIES); 765 766 // Select entry to recycle. 767 for (i = CACHE_N_ENTRIES-1; i > 0; i--) { 768 if (!img->ces[i]->fromC) 769 break; 770 } 771 vg_assert(i >= 0 && i < CACHE_N_ENTRIES); 772 773 realloc_CEnt(img, i, size); 774 img->ces[i]->size = size; 775 img->ces[i]->used = 0; 776 if (cslc == NULL) { 777 set_CEnt(img, i, off); 778 img->ces[i]->fromC = False; 779 vg_assert(is_sane_CEnt("get_slowcase-case-2", img, i)); 780 } else { 781 SizeT len = tinfl_decompress_mem_to_mem( 782 img->ces[i]->data, cslc->szD, 783 cbuf, cslc->szC, 784 TINFL_FLAG_USING_NON_WRAPPING_OUTPUT_BUF 785 | TINFL_FLAG_PARSE_ZLIB_HEADER); 786 vg_assert(len == size); 787 img->ces[i]->used = size; 788 img->ces[i]->off = cslc->offD; 789 img->ces[i]->fromC = True; 790 vg_assert(is_sane_CEnt("get_slowcase-case-4", img, i)); 791 } 792 vg_assert(img->ces_used == ces_used_at_entry); 793 if (i > 0) { 794 move_CEnt_to_top(img, i); 795 i = 0; 796 } 797 vg_assert(is_in_CEnt(img->ces[i], off)); 798 if (cbuf != NULL) { 799 ML_(dinfo_free)(cbuf); 800 } 801 return img->ces[i]->data[ off - img->ces[i]->off ]; 802} 803 804// This is called a lot, so do the usual fast/slow split stuff on it. */ 805static inline UChar get ( DiImage* img, DiOffT off ) 806{ 807 /* Most likely case is, it's in the ces[0] position. */ 808 /* ML_(img_from_local_file) requests a read for ces[0] when 809 creating the image. Hence slot zero is always non-NULL, so we 810 can skip this test. */ 811 if (LIKELY(/* img->ces[0] != NULL && */ 812 is_in_CEnt(img->ces[0], off))) { 813 return img->ces[0]->data[ off - img->ces[0]->off ]; 814 } 815 /* Else we'll have to fish around for it. */ 816 return get_slowcase(img, off); 817} 818 819/* Create an image from a file in the local filesystem. This is 820 relatively straightforward. */ 821DiImage* ML_(img_from_local_file)(const HChar* fullpath) 822{ 823 SysRes fd; 824 struct vg_stat stat_buf; 825 DiOffT size; 826 827 fd = VG_(open)(fullpath, VKI_O_RDONLY, 0); 828 if (sr_isError(fd)) 829 return NULL; 830 831 if (VG_(fstat)(sr_Res(fd), &stat_buf) != 0) { 832 VG_(close)(sr_Res(fd)); 833 return NULL; 834 } 835 836 size = stat_buf.size; 837 if (size == 0 || size == DiOffT_INVALID 838 || /* size is unrepresentable as a SizeT */ 839 size != (DiOffT)(SizeT)(size)) { 840 VG_(close)(sr_Res(fd)); 841 return NULL; 842 } 843 844 DiImage* img = ML_(dinfo_zalloc)("di.image.ML_iflf.1", sizeof(DiImage)); 845 img->source.is_local = True; 846 img->source.fd = sr_Res(fd); 847 img->size = size; 848 img->real_size = size; 849 img->ces_used = 0; 850 img->source.name = ML_(dinfo_strdup)("di.image.ML_iflf.2", fullpath); 851 img->cslc = NULL; 852 img->cslc_size = 0; 853 img->cslc_used = 0; 854 /* img->ces is already zeroed out */ 855 vg_assert(img->source.fd >= 0); 856 857 /* Force the zeroth entry to be the first chunk of the file. 858 That's likely to be the first part that's requested anyway, and 859 loading it at this point forcing img->cent[0] to always be 860 non-empty, thereby saving us an is-it-empty check on the fast 861 path in get(). */ 862 UInt entNo = alloc_CEnt(img, CACHE_ENTRY_SIZE, False/*!fromC*/); 863 vg_assert(entNo == 0); 864 set_CEnt(img, 0, 0); 865 866 return img; 867} 868 869 870/* Create an image from a file on a remote debuginfo server. This is 871 more complex. There are lots of ways in which it can fail. */ 872DiImage* ML_(img_from_di_server)(const HChar* filename, 873 const HChar* serverAddr) 874{ 875 if (filename == NULL || serverAddr == NULL) 876 return NULL; 877 878 /* The filename must be a plain filename -- no slashes at all. */ 879 if (VG_(strchr)(filename, '/') != NULL) 880 return NULL; 881 882 /* Try to connect to the server. A side effect of this is to parse 883 and reject, if syntactically invalid, |serverAddr|. Reasons why 884 this could fail: 885 - serverAddr is not of the form d.d.d.d:d or d.d.d.d 886 - attempt to connect to that address:port failed 887 */ 888 Int sd = VG_(connect_via_socket)(serverAddr); 889 if (sd < 0) 890 return NULL; 891 if (!set_blocking(sd)) 892 return NULL; 893 Int one = 1; 894 Int sr = VG_(setsockopt)(sd, VKI_IPPROTO_TCP, VKI_TCP_NODELAY, 895 &one, sizeof(one)); 896 vg_assert(sr == 0); 897 898 /* Ok, we got a connection. Ask it for version string, so as to be 899 reasonably sure we're talking to an instance of 900 auxprogs/valgrind-di-server and not to some other random program 901 that happens to be listening on that port. */ 902 Frame* req = mk_Frame_noargs("VERS"); 903 Frame* res = do_transaction(sd, req); 904 if (res == NULL) 905 goto fail; // do_transaction failed?! 906 UChar* vstr = NULL; 907 if (!parse_Frame_asciiz(res, "VEOK", &vstr)) 908 goto fail; // unexpected response kind, or invalid ID string 909 vg_assert(vstr); 910 if (VG_(strcmp)("Valgrind Debuginfo Server, Version 1", 911 (const HChar*)vstr) != 0) 912 goto fail; // wrong version string 913 free_Frame(req); 914 free_Frame(res); 915 req = NULL; 916 res = NULL; 917 918 /* Server seems plausible. Present it with the name of the file we 919 want and see if it'll give us back a session ID for it. */ 920 req = mk_Frame_asciiz("OPEN", filename); 921 res = do_transaction(sd, req); 922 if (res == NULL) 923 goto fail; 924 ULong session_id = 0, size = 0; 925 if (!parse_Frame_le64_le64(res, "OPOK", &session_id, &size)) 926 goto fail; 927 free_Frame(req); 928 free_Frame(res); 929 req = NULL; 930 res = NULL; 931 932 /* We have a session ID. We're ready to roll. */ 933 DiImage* img = ML_(dinfo_zalloc)("di.image.ML_ifds.1", sizeof(DiImage)); 934 img->source.is_local = False; 935 img->source.fd = sd; 936 img->source.session_id = session_id; 937 img->size = size; 938 img->real_size = size; 939 img->ces_used = 0; 940 img->source.name = ML_(dinfo_zalloc)("di.image.ML_ifds.2", 941 20 + VG_(strlen)(filename) 942 + VG_(strlen)(serverAddr)); 943 VG_(sprintf)(img->source.name, "%s at %s", filename, serverAddr); 944 img->cslc = NULL; 945 img->cslc_size = 0; 946 img->cslc_used = 0; 947 948 /* img->ces is already zeroed out */ 949 vg_assert(img->source.fd >= 0); 950 951 /* See comment on equivalent bit in ML_(img_from_local_file) for 952 rationale. */ 953 UInt entNo = alloc_CEnt(img, CACHE_ENTRY_SIZE, False/*!fromC*/); 954 vg_assert(entNo == 0); 955 set_CEnt(img, 0, 0); 956 957 return img; 958 959 fail: 960 free_Frame(req); 961 if (res) { 962 UChar* reason = NULL; 963 if (parse_Frame_asciiz(res, "FAIL", &reason)) { 964 // HACK: if it's just telling us that the file can't 965 // be opened, don't print it, else we'll get flooded with 966 // such complaints, one for each main object for which there 967 // isn't a debuginfo file on the server. 968 if (0 != VG_(strcmp)((const HChar*)reason, "OPEN: cannot open file")) 969 VG_(umsg)("ML_(img_from_di_server): fail: %s\n", reason); 970 } else { 971 VG_(umsg)("ML_(img_from_di_server): fail: unknown reason\n"); 972 } 973 free_Frame(res); 974 } 975 VG_(close)(sd); 976 return NULL; 977} 978 979DiOffT ML_(img_mark_compressed_part)(DiImage* img, DiOffT offset, SizeT szC, 980 SizeT szD) 981{ 982 DiOffT ret; 983 vg_assert(img != NULL); 984 vg_assert(offset + szC <= img->size); 985 986 if (img->cslc_used == img->cslc_size) { 987 img->cslc_size += COMPRESSED_SLICE_ARRAY_GROW_SIZE; 988 img->cslc = ML_(dinfo_realloc)("di.image.ML_img_mark_compressed_part.1", 989 img->cslc, img->cslc_size * sizeof(CSlc)); 990 } 991 992 ret = img->size; 993 img->cslc[img->cslc_used].offC = offset; 994 img->cslc[img->cslc_used].szC = szC; 995 img->cslc[img->cslc_used].offD = img->size; 996 img->cslc[img->cslc_used].szD = szD; 997 img->size += szD; 998 img->cslc_used++; 999 return ret; 1000} 1001 1002void ML_(img_done)(DiImage* img) 1003{ 1004 vg_assert(img != NULL); 1005 if (img->source.is_local) { 1006 /* Close the file; nothing else to do. */ 1007 vg_assert(img->source.session_id == 0); 1008 VG_(close)(img->source.fd); 1009 } else { 1010 /* Close the socket. The server can detect this and will scrub 1011 the connection when it happens, so there's no need to tell it 1012 explicitly by sending it a "CLOSE" message, or any such. */ 1013 vg_assert(img->source.session_id != 0); 1014 VG_(close)(img->source.fd); 1015 } 1016 1017 /* Free up the cache entries, ultimately |img| itself. */ 1018 UInt i; 1019 vg_assert(img->ces_used <= CACHE_N_ENTRIES); 1020 for (i = 0; i < img->ces_used; i++) { 1021 ML_(dinfo_free)(img->ces[i]); 1022 } 1023 /* Take the opportunity to sanity check the rest. */ 1024 for (i = i; i < img->ces_used; i++) { 1025 vg_assert(img->ces[i] == NULL); 1026 } 1027 ML_(dinfo_free)(img->source.name); 1028 ML_(dinfo_free)(img->cslc); 1029 ML_(dinfo_free)(img); 1030} 1031 1032DiOffT ML_(img_size)(const DiImage* img) 1033{ 1034 vg_assert(img != NULL); 1035 return img->size; 1036} 1037 1038DiOffT ML_(img_real_size)(const DiImage* img) 1039{ 1040 vg_assert(img != NULL); 1041 return img->real_size; 1042} 1043 1044inline Bool ML_(img_valid)(const DiImage* img, DiOffT offset, SizeT size) 1045{ 1046 vg_assert(img != NULL); 1047 vg_assert(offset != DiOffT_INVALID); 1048 return img->size > 0 && offset + size <= (DiOffT)img->size; 1049} 1050 1051__attribute__((noinline)) 1052static void ensure_valid_failed (const DiImage* img, DiOffT offset, SizeT size, 1053 const HChar* caller) 1054{ 1055 VG_(umsg)("Valgrind: debuginfo reader: ensure_valid failed:\n"); 1056 VG_(umsg)("Valgrind: during call to %s\n", caller); 1057 VG_(umsg)("Valgrind: request for range [%llu, +%lu) exceeds\n", 1058 offset, size); 1059 VG_(umsg)("Valgrind: valid image size of %lu for image:\n", 1060 img->size); 1061 VG_(umsg)("Valgrind: \"%s\"\n", img->source.name); 1062 give_up__image_overrun(); 1063} 1064 1065/* Check the given range is valid, and if not, shut down the system. 1066 An invalid range would imply that we're trying to read outside the 1067 image, which normally means the image is corrupted somehow, or the 1068 caller is buggy. Recovering is too complex, and we have 1069 probably-corrupt debuginfo, so just give up. */ 1070static void ensure_valid(const DiImage* img, DiOffT offset, SizeT size, 1071 const HChar* caller) 1072{ 1073 if (LIKELY(ML_(img_valid)(img, offset, size))) 1074 return; 1075 else 1076 ensure_valid_failed(img, offset, size, caller); 1077} 1078 1079 1080void ML_(img_get)(/*OUT*/void* dst, 1081 DiImage* img, DiOffT offset, SizeT size) 1082{ 1083 vg_assert(img != NULL); 1084 vg_assert(size > 0); 1085 ensure_valid(img, offset, size, "ML_(img_get)"); 1086 SizeT i; 1087 for (i = 0; i < size; i++) { 1088 ((UChar*)dst)[i] = get(img, offset + i); 1089 } 1090} 1091 1092SizeT ML_(img_get_some)(/*OUT*/void* dst, 1093 DiImage* img, DiOffT offset, SizeT size) 1094{ 1095 vg_assert(img != NULL); 1096 vg_assert(size > 0); 1097 ensure_valid(img, offset, size, "ML_(img_get_some)"); 1098 UChar* dstU = (UChar*)dst; 1099 /* Use |get| in the normal way to get the first byte of the range. 1100 This guarantees to put the cache entry containing |offset| in 1101 position zero. */ 1102 dstU[0] = get(img, offset); 1103 /* Now just read as many bytes as we can (or need) directly out of 1104 entry zero, without bothering to call |get| each time. */ 1105 const CEnt* ce = img->ces[0]; 1106 vg_assert(ce && ce->used >= 1); 1107 vg_assert(is_in_CEnt(ce, offset)); 1108 SizeT nToCopy = size - 1; 1109 SizeT nAvail = (SizeT)(ce->used - (offset + 1 - ce->off)); 1110 vg_assert(nAvail >= 0 && nAvail <= ce->used-1); 1111 if (nAvail < nToCopy) nToCopy = nAvail; 1112 VG_(memcpy)(&dstU[1], &ce->data[offset + 1 - ce->off], nToCopy); 1113 return nToCopy + 1; 1114} 1115 1116 1117SizeT ML_(img_strlen)(DiImage* img, DiOffT off) 1118{ 1119 ensure_valid(img, off, 1, "ML_(img_strlen)"); 1120 SizeT i = 0; 1121 while (get(img, off + i) != 0) i++; 1122 return i; 1123} 1124 1125HChar* ML_(img_strdup)(DiImage* img, const HChar* cc, DiOffT offset) 1126{ 1127 ensure_valid(img, offset, 1, "ML_(img_strdup)"); 1128 SizeT len = ML_(img_strlen)(img, offset); 1129 HChar* res = ML_(dinfo_zalloc)(cc, len+1); 1130 SizeT i; 1131 for (i = 0; i < len; i++) { 1132 res[i] = get(img, offset+i); 1133 } 1134 vg_assert(res[len] == 0); 1135 return res; 1136} 1137 1138Int ML_(img_strcmp)(DiImage* img, DiOffT off1, DiOffT off2) 1139{ 1140 ensure_valid(img, off1, 1, "ML_(img_strcmp)(first arg)"); 1141 ensure_valid(img, off2, 1, "ML_(img_strcmp)(second arg)"); 1142 while (True) { 1143 UChar c1 = get(img, off1); 1144 UChar c2 = get(img, off2); 1145 if (c1 < c2) return -1; 1146 if (c1 > c2) return 1; 1147 if (c1 == 0) return 0; 1148 off1++; off2++; 1149 } 1150} 1151 1152Int ML_(img_strcmp_c)(DiImage* img, DiOffT off1, const HChar* str2) 1153{ 1154 ensure_valid(img, off1, 1, "ML_(img_strcmp_c)"); 1155 while (True) { 1156 UChar c1 = get(img, off1); 1157 UChar c2 = *(const UChar*)str2; 1158 if (c1 < c2) return -1; 1159 if (c1 > c2) return 1; 1160 if (c1 == 0) return 0; 1161 off1++; str2++; 1162 } 1163} 1164 1165UChar ML_(img_get_UChar)(DiImage* img, DiOffT offset) 1166{ 1167 ensure_valid(img, offset, 1, "ML_(img_get_UChar)"); 1168 return get(img, offset); 1169} 1170 1171UShort ML_(img_get_UShort)(DiImage* img, DiOffT offset) 1172{ 1173 UShort r; 1174 ML_(img_get)(&r, img, offset, sizeof(r)); 1175 return r; 1176} 1177 1178UInt ML_(img_get_UInt)(DiImage* img, DiOffT offset) 1179{ 1180 UInt r; 1181 ML_(img_get)(&r, img, offset, sizeof(r)); 1182 return r; 1183} 1184 1185ULong ML_(img_get_ULong)(DiImage* img, DiOffT offset) 1186{ 1187 ULong r; 1188 ML_(img_get)(&r, img, offset, sizeof(r)); 1189 return r; 1190} 1191 1192 1193/* 1194 * This routine for calculating the CRC for a separate debug file 1195 * is GPLed code borrowed from GNU binutils. 1196 */ 1197UInt ML_(img_calc_gnu_debuglink_crc32)(DiImage* img) 1198{ 1199 static const UInt crc32_table[256] = 1200 { 1201 0x00000000, 0x77073096, 0xee0e612c, 0x990951ba, 0x076dc419, 1202 0x706af48f, 0xe963a535, 0x9e6495a3, 0x0edb8832, 0x79dcb8a4, 1203 0xe0d5e91e, 0x97d2d988, 0x09b64c2b, 0x7eb17cbd, 0xe7b82d07, 1204 0x90bf1d91, 0x1db71064, 0x6ab020f2, 0xf3b97148, 0x84be41de, 1205 0x1adad47d, 0x6ddde4eb, 0xf4d4b551, 0x83d385c7, 0x136c9856, 1206 0x646ba8c0, 0xfd62f97a, 0x8a65c9ec, 0x14015c4f, 0x63066cd9, 1207 0xfa0f3d63, 0x8d080df5, 0x3b6e20c8, 0x4c69105e, 0xd56041e4, 1208 0xa2677172, 0x3c03e4d1, 0x4b04d447, 0xd20d85fd, 0xa50ab56b, 1209 0x35b5a8fa, 0x42b2986c, 0xdbbbc9d6, 0xacbcf940, 0x32d86ce3, 1210 0x45df5c75, 0xdcd60dcf, 0xabd13d59, 0x26d930ac, 0x51de003a, 1211 0xc8d75180, 0xbfd06116, 0x21b4f4b5, 0x56b3c423, 0xcfba9599, 1212 0xb8bda50f, 0x2802b89e, 0x5f058808, 0xc60cd9b2, 0xb10be924, 1213 0x2f6f7c87, 0x58684c11, 0xc1611dab, 0xb6662d3d, 0x76dc4190, 1214 0x01db7106, 0x98d220bc, 0xefd5102a, 0x71b18589, 0x06b6b51f, 1215 0x9fbfe4a5, 0xe8b8d433, 0x7807c9a2, 0x0f00f934, 0x9609a88e, 1216 0xe10e9818, 0x7f6a0dbb, 0x086d3d2d, 0x91646c97, 0xe6635c01, 1217 0x6b6b51f4, 0x1c6c6162, 0x856530d8, 0xf262004e, 0x6c0695ed, 1218 0x1b01a57b, 0x8208f4c1, 0xf50fc457, 0x65b0d9c6, 0x12b7e950, 1219 0x8bbeb8ea, 0xfcb9887c, 0x62dd1ddf, 0x15da2d49, 0x8cd37cf3, 1220 0xfbd44c65, 0x4db26158, 0x3ab551ce, 0xa3bc0074, 0xd4bb30e2, 1221 0x4adfa541, 0x3dd895d7, 0xa4d1c46d, 0xd3d6f4fb, 0x4369e96a, 1222 0x346ed9fc, 0xad678846, 0xda60b8d0, 0x44042d73, 0x33031de5, 1223 0xaa0a4c5f, 0xdd0d7cc9, 0x5005713c, 0x270241aa, 0xbe0b1010, 1224 0xc90c2086, 0x5768b525, 0x206f85b3, 0xb966d409, 0xce61e49f, 1225 0x5edef90e, 0x29d9c998, 0xb0d09822, 0xc7d7a8b4, 0x59b33d17, 1226 0x2eb40d81, 0xb7bd5c3b, 0xc0ba6cad, 0xedb88320, 0x9abfb3b6, 1227 0x03b6e20c, 0x74b1d29a, 0xead54739, 0x9dd277af, 0x04db2615, 1228 0x73dc1683, 0xe3630b12, 0x94643b84, 0x0d6d6a3e, 0x7a6a5aa8, 1229 0xe40ecf0b, 0x9309ff9d, 0x0a00ae27, 0x7d079eb1, 0xf00f9344, 1230 0x8708a3d2, 0x1e01f268, 0x6906c2fe, 0xf762575d, 0x806567cb, 1231 0x196c3671, 0x6e6b06e7, 0xfed41b76, 0x89d32be0, 0x10da7a5a, 1232 0x67dd4acc, 0xf9b9df6f, 0x8ebeeff9, 0x17b7be43, 0x60b08ed5, 1233 0xd6d6a3e8, 0xa1d1937e, 0x38d8c2c4, 0x4fdff252, 0xd1bb67f1, 1234 0xa6bc5767, 0x3fb506dd, 0x48b2364b, 0xd80d2bda, 0xaf0a1b4c, 1235 0x36034af6, 0x41047a60, 0xdf60efc3, 0xa867df55, 0x316e8eef, 1236 0x4669be79, 0xcb61b38c, 0xbc66831a, 0x256fd2a0, 0x5268e236, 1237 0xcc0c7795, 0xbb0b4703, 0x220216b9, 0x5505262f, 0xc5ba3bbe, 1238 0xb2bd0b28, 0x2bb45a92, 0x5cb36a04, 0xc2d7ffa7, 0xb5d0cf31, 1239 0x2cd99e8b, 0x5bdeae1d, 0x9b64c2b0, 0xec63f226, 0x756aa39c, 1240 0x026d930a, 0x9c0906a9, 0xeb0e363f, 0x72076785, 0x05005713, 1241 0x95bf4a82, 0xe2b87a14, 0x7bb12bae, 0x0cb61b38, 0x92d28e9b, 1242 0xe5d5be0d, 0x7cdcefb7, 0x0bdbdf21, 0x86d3d2d4, 0xf1d4e242, 1243 0x68ddb3f8, 0x1fda836e, 0x81be16cd, 0xf6b9265b, 0x6fb077e1, 1244 0x18b74777, 0x88085ae6, 0xff0f6a70, 0x66063bca, 0x11010b5c, 1245 0x8f659eff, 0xf862ae69, 0x616bffd3, 0x166ccf45, 0xa00ae278, 1246 0xd70dd2ee, 0x4e048354, 0x3903b3c2, 0xa7672661, 0xd06016f7, 1247 0x4969474d, 0x3e6e77db, 0xaed16a4a, 0xd9d65adc, 0x40df0b66, 1248 0x37d83bf0, 0xa9bcae53, 0xdebb9ec5, 0x47b2cf7f, 0x30b5ffe9, 1249 0xbdbdf21c, 0xcabac28a, 0x53b39330, 0x24b4a3a6, 0xbad03605, 1250 0xcdd70693, 0x54de5729, 0x23d967bf, 0xb3667a2e, 0xc4614ab8, 1251 0x5d681b02, 0x2a6f2b94, 0xb40bbe37, 0xc30c8ea1, 0x5a05df1b, 1252 0x2d02ef8d 1253 }; 1254 1255 vg_assert(img != NULL); 1256 1257 /* If the image is local, calculate the CRC here directly. If it's 1258 remote, forward the request to the server. */ 1259 if (img->source.is_local) { 1260 /* Work through the image in 1 KB chunks. */ 1261 UInt crc = 0xFFFFFFFF; 1262 DiOffT img_szB = ML_(img_size)(img); 1263 DiOffT curr_off = 0; 1264 while (1) { 1265 vg_assert(curr_off >= 0 && curr_off <= img_szB); 1266 if (curr_off == img_szB) break; 1267 DiOffT avail = img_szB - curr_off; 1268 vg_assert(avail > 0 && avail <= img_szB); 1269 if (avail > 1024) avail = 1024; 1270 UChar buf[1024]; 1271 SizeT nGot = ML_(img_get_some)(buf, img, curr_off, avail); 1272 vg_assert(nGot >= 1 && nGot <= avail); 1273 UInt i; 1274 for (i = 0; i < (UInt)nGot; i++) 1275 crc = crc32_table[(crc ^ buf[i]) & 0xff] ^ (crc >> 8); 1276 curr_off += nGot; 1277 } 1278 return ~crc & 0xFFFFFFFF; 1279 } else { 1280 Frame* req = mk_Frame_noargs("CRC3"); 1281 Frame* res = do_transaction(img->source.fd, req); 1282 if (!res) goto remote_crc_fail; 1283 ULong crc32 = 0; 1284 if (!parse_Frame_le64(res, "CROK", &crc32)) goto remote_crc_fail; 1285 if ((crc32 & ~0xFFFFFFFFULL) != 0) goto remote_crc_fail; 1286 free_Frame(req); 1287 free_Frame(res); 1288 return (UInt)crc32; 1289 remote_crc_fail: 1290 1291 // XXXX common this up with the READ diagnostic cases 1292 if (res) { 1293 UChar* reason = NULL; 1294 if (parse_Frame_asciiz(res, "FAIL", &reason)) { 1295 VG_(umsg)("img_calc_gnu_debuglink_crc32: fail: " 1296 "%s\n", reason); 1297 } else { 1298 VG_(umsg)("img_calc_gnu_debuglink_crc32: fail: " 1299 "unknown reason\n"); 1300 } 1301 } else { 1302 VG_(umsg)("img_calc_gnu_debuglink_crc32: fail: " 1303 "server unexpectedly closed the connection\n"); 1304 } 1305 1306 if (req) free_Frame(req); 1307 if (res) free_Frame(res); 1308 // FIXME: now what? 1309 give_up__comms_lost(); 1310 /* NOTREACHED */ 1311 vg_assert(0); 1312 } 1313 /*NOTREACHED*/ 1314 vg_assert(0); 1315} 1316 1317//////////////////////////////////////////////////// 1318#include "minilzo-inl.c" 1319 1320/*--------------------------------------------------------------------*/ 1321/*--- end image.c ---*/ 1322/*--------------------------------------------------------------------*/ 1323