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