Bug 439685 compiler warning in callgrind/main.c
[valgrind.git] / coregrind / m_debuginfo / image.c
blob28dfd0b4722a628b99684b7cf0d943c03f3ea90e
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(entNo < img->ces_used);
527 if (LIKELY(entNo == 1)) {
528 CEnt* tmp = img->ces[1];
529 img->ces[entNo] = img->ces[0];
530 img->ces[0] = tmp;
531 } else {
532 vg_assert(entNo > 1); // a.k.a. >= 2
533 CEnt* tmp = img->ces[entNo];
534 img->ces[entNo] = img->ces[entNo-1];
535 entNo--;
536 img->ces[entNo] = img->ces[entNo-1];
537 entNo--;
538 while (entNo > 0) {
539 img->ces[entNo] = img->ces[entNo-1];
540 entNo--;
542 img->ces[0] = tmp;
546 /* Set the given entry so that it has a chunk of the file containing
547 the given offset. It is this function that brings data into the
548 cache, either by reading the local file or pulling it from the
549 remote server. */
550 static void set_CEnt ( const DiImage* img, UInt entNo, DiOffT off )
552 SizeT len;
553 DiOffT off_orig = off;
554 vg_assert(img != NULL);
555 vg_assert(img->ces_used <= CACHE_N_ENTRIES);
556 vg_assert(entNo >= 0 && entNo < img->ces_used);
557 vg_assert(off < img->real_size);
558 CEnt* ce = img->ces[entNo];
559 vg_assert(ce != NULL);
560 /* Compute [off, +len) as the slice we are going to read. */
561 off = block_round_down(off);
562 len = img->real_size - off;
563 if (len > ce->size)
564 len = ce->size;
565 /* It is conceivable that the 'len > 0' bit could fail if we make
566 an image with a zero sized file. But then no 'get' request on
567 that image would be valid. */
568 vg_assert(len > 0 && len <= ce->size);
569 vg_assert(off + len <= img->real_size);
570 vg_assert(off <= off_orig && off_orig < off+len);
571 /* So, read off .. off+len-1 into the entry. */
573 if (0) {
574 static UInt t_last = 0;
575 static ULong nread = 0;
576 UInt now = VG_(read_millisecond_timer)();
577 UInt delay = now - t_last;
578 t_last = now;
579 nread += len;
580 VG_(printf)("XXXXXXXX (tot %'llu) read %'lu offset %'llu delay %'u\n",
581 nread, len, off, delay);
584 if (img->source.is_local) {
585 // Simple: just read it
586 SysRes sr = VG_(pread)(img->source.fd, &ce->data[0], (Int)len, off);
587 vg_assert(!sr_isError(sr));
588 } else {
589 // Not so simple: poke the server
590 vg_assert(img->source.session_id > 0);
591 Frame* req
592 = mk_Frame_le64_le64_le64("READ", img->source.session_id, off, len);
593 Frame* res = do_transaction(img->source.fd, req);
594 free_Frame(req); req = NULL;
595 if (!res) goto server_fail;
596 ULong rx_session_id = 0, rx_off = 0, rx_len = 0, rx_zdata_len = 0;
597 UChar* rx_data = NULL;
598 /* Pretty confusing. rx_sessionid, rx_off and rx_len are copies
599 of the values that we requested in the READ frame just above,
600 so we can be sure that the server is responding to the right
601 request. It just copies them from the request into the
602 response. rx_data is the actual data, and rx_zdata_len is
603 its compressed length. Hence rx_len must equal len, but
604 rx_zdata_len can be different -- smaller, hopefully.. */
605 if (!parse_Frame_le64_le64_le64_bytes
606 (res, "RDOK", &rx_session_id, &rx_off,
607 &rx_len, &rx_data, &rx_zdata_len))
608 goto server_fail;
609 if (rx_session_id != img->source.session_id
610 || rx_off != off || rx_len != len || rx_data == NULL)
611 goto server_fail;
613 //VG_(memcpy)(&ce->data[0], rx_data, len);
614 // Decompress into the destination buffer
615 // Tell the lib the max number of output bytes it can write.
616 // After the call, this holds the number of bytes actually written,
617 // and it's an error if it is different.
618 lzo_uint out_len = len;
619 Int lzo_rc = lzo1x_decompress_safe(rx_data, rx_zdata_len,
620 &ce->data[0], &out_len,
621 NULL);
622 Bool ok = lzo_rc == LZO_E_OK && out_len == len;
623 if (!ok) goto server_fail;
625 free_Frame(res); res = NULL;
626 goto end_of_else_clause;
627 server_fail:
628 /* The server screwed up somehow. Now what? */
629 if (res) {
630 UChar* reason = NULL;
631 if (parse_Frame_asciiz(res, "FAIL", &reason)) {
632 VG_(umsg)("set_CEnt (reading data from DI server): fail: "
633 "%s\n", reason);
634 } else {
635 VG_(umsg)("set_CEnt (reading data from DI server): fail: "
636 "unknown reason\n");
638 free_Frame(res); res = NULL;
639 } else {
640 VG_(umsg)("set_CEnt (reading data from DI server): fail: "
641 "server unexpectedly closed the connection\n");
643 give_up__comms_lost();
644 /* NOTREACHED */
645 vg_assert(0);
646 end_of_else_clause:
650 ce->off = off;
651 ce->used = len;
652 ce->fromC = False;
653 vg_assert(ce == img->ces[entNo]);
654 vg_assert(is_sane_CEnt("set_CEnt", img, entNo));
657 __attribute__((noinline))
658 static UChar get_slowcase ( DiImage* img, DiOffT off )
660 /* Stay sane .. */
661 vg_assert(off < img->size);
662 vg_assert(img->ces_used <= CACHE_N_ENTRIES);
663 UInt i;
664 /* Start the search at entry 1, since the fast-case function
665 checked slot zero already. */
666 for (i = 1; i < img->ces_used; i++) {
667 vg_assert(img->ces[i]);
668 if (is_in_CEnt(img->ces[i], off))
669 break;
671 vg_assert(i >= 1);
673 if (LIKELY(i < img->ces_used)) {
674 // Found it. Move to the top and stop.
675 move_CEnt_to_top(img, i);
676 vg_assert(is_in_CEnt(img->ces[0], off));
677 return img->ces[0]->data[ off - img->ces[0]->off ];
680 vg_assert(i <= img->ces_used);
682 // It's not in any entry. Either allocate a new one or recycle the LRU
683 // one. This is where the presence of compressed sections makes things
684 // tricky. There are 4 cases to consider:
686 // (1) not from a compressed slice, we can allocate a new entry
687 // (2) not from a compressed slice, we have to recycle the LRU entry
688 // (3) from a compressed slice, we can allocate a new entry
689 // (4) from a compressed slice, we have to recycle the LRU entry
691 // Cases (3) and (4) are complex because we will have to call
692 // ML_(img_get_some) to get the compressed data. But this function is
693 // reachable from ML_(img_get_some), so we may re-enter get_slowcase a
694 // second time as a result. Given that the compressed data will be cause
695 // only cases (1) and (2) to happen, this guarantees no infinite recursion.
696 // It does however mean that we can't carry (in this function invokation)
697 // any local copies of the overall cache state across the ML_(img_get_some)
698 // call, since it may become invalidated by the recursive call to
699 // get_slowcase.
701 // First of all, see if it is in a compressed slice, and if so, pull the
702 // compressed data into an intermediate buffer. Given the preceding
703 // comment, this is a safe place to do it, since we are not carrying any
704 // cache state here apart from the knowledge that the requested offset is
705 // not in the cache at all, and the recursive call won't change that fact.
707 CSlc* cslc = find_cslc(img, off);
708 UChar* cbuf = NULL;
709 if (cslc != NULL) {
710 SizeT len = 0;
711 cbuf = ML_(dinfo_zalloc)("di.image.get_slowcase.cbuf-1", cslc->szC);
712 // get compressed data
713 while (len < cslc->szC)
714 len += ML_(img_get_some)(cbuf + len, img, cslc->offC + len,
715 cslc->szC - len);
718 // Now we can do what we like.
719 vg_assert((cslc == NULL && cbuf == NULL) || (cslc != NULL && cbuf != NULL));
721 // Note, we can't capture this earlier, for exactly the reasons detailed
722 // above.
723 UInt ces_used_at_entry = img->ces_used;
725 // This is the size of the CEnt that we want to have after allocation or
726 // recycling.
727 SizeT size = (cslc == NULL) ? CACHE_ENTRY_SIZE : cslc->szD;
729 // Cases (1) and (3)
730 if (img->ces_used < CACHE_N_ENTRIES) {
731 /* Allocate a new cache entry, and fill it in. */
732 i = alloc_CEnt(img, size, /*fromC?*/cslc != NULL);
733 if (cslc == NULL) {
734 set_CEnt(img, i, off);
735 img->ces[i]->fromC = False;
736 vg_assert(is_sane_CEnt("get_slowcase-case-1", img, i));
737 vg_assert(img->ces_used == ces_used_at_entry + 1);
738 } else {
739 SizeT len = tinfl_decompress_mem_to_mem(
740 img->ces[i]->data, cslc->szD,
741 cbuf, cslc->szC,
742 TINFL_FLAG_USING_NON_WRAPPING_OUTPUT_BUF
743 | TINFL_FLAG_PARSE_ZLIB_HEADER);
744 vg_assert(len == cslc->szD); // sanity check on data, FIXME
745 vg_assert(cslc->szD == size);
746 img->ces[i]->used = cslc->szD;
747 img->ces[i]->off = cslc->offD;
748 img->ces[i]->fromC = True;
749 vg_assert(is_sane_CEnt("get_slowcase-case-3", img, i));
750 vg_assert(img->ces_used == ces_used_at_entry + 1);
752 vg_assert(img->ces_used == ces_used_at_entry + 1);
753 if (i > 0) {
754 move_CEnt_to_top(img, i);
755 i = 0;
757 vg_assert(is_in_CEnt(img->ces[i], off));
758 if (cbuf != NULL) {
759 ML_(dinfo_free)(cbuf);
761 return img->ces[i]->data[ off - img->ces[i]->off ];
764 // Cases (2) and (4)
765 /* All entries in use. Recycle the (ostensibly) LRU one. But try to find
766 a non-fromC entry to recycle, though, since discarding and reloading
767 fromC entries is very expensive. The result is that -- unless all
768 CACHE_N_ENTRIES wind up being used by decompressed slices, which is
769 highly unlikely -- we'll wind up keeping all the decompressed data in
770 the cache for its entire remaining life. We could probably do better
771 but it would make the cache management even more complex. */
772 vg_assert(img->ces_used == CACHE_N_ENTRIES);
774 // Select entry to recycle.
775 for (i = CACHE_N_ENTRIES-1; i > 0; i--) {
776 if (!img->ces[i]->fromC)
777 break;
779 vg_assert(i >= 0 && i < CACHE_N_ENTRIES);
781 realloc_CEnt(img, i, size, /*fromC?*/cslc != NULL);
782 img->ces[i]->size = size;
783 img->ces[i]->used = 0;
784 if (cslc == NULL) {
785 set_CEnt(img, i, off);
786 img->ces[i]->fromC = False;
787 vg_assert(is_sane_CEnt("get_slowcase-case-2", img, i));
788 } else {
789 SizeT len = tinfl_decompress_mem_to_mem(
790 img->ces[i]->data, cslc->szD,
791 cbuf, cslc->szC,
792 TINFL_FLAG_USING_NON_WRAPPING_OUTPUT_BUF
793 | TINFL_FLAG_PARSE_ZLIB_HEADER);
794 vg_assert(len == size);
795 img->ces[i]->used = size;
796 img->ces[i]->off = cslc->offD;
797 img->ces[i]->fromC = True;
798 vg_assert(is_sane_CEnt("get_slowcase-case-4", img, i));
800 vg_assert(img->ces_used == ces_used_at_entry);
801 if (i > 0) {
802 move_CEnt_to_top(img, i);
803 i = 0;
805 vg_assert(is_in_CEnt(img->ces[i], off));
806 if (cbuf != NULL) {
807 ML_(dinfo_free)(cbuf);
809 return img->ces[i]->data[ off - img->ces[i]->off ];
812 // This is called a lot, so do the usual fast/slow split stuff on it. */
813 static inline UChar get ( DiImage* img, DiOffT off )
815 /* Most likely case is, it's in the ces[0] position. */
816 /* ML_(img_from_local_file) requests a read for ces[0] when
817 creating the image. Hence slot zero is always non-NULL, so we
818 can skip this test. */
819 if (LIKELY(/* img->ces[0] != NULL && */
820 is_in_CEnt(img->ces[0], off))) {
821 return img->ces[0]->data[ off - img->ces[0]->off ];
823 /* Else we'll have to fish around for it. */
824 return get_slowcase(img, off);
827 /* Create an image from a file in the local filesystem. This is
828 relatively straightforward. */
829 DiImage* ML_(img_from_local_file)(const HChar* fullpath)
831 SysRes fd;
832 struct vg_stat stat_buf;
833 DiOffT size;
835 fd = VG_(open)(fullpath, VKI_O_RDONLY, 0);
836 if (sr_isError(fd))
837 return NULL;
839 if (VG_(fstat)(sr_Res(fd), &stat_buf) != 0) {
840 VG_(close)(sr_Res(fd));
841 return NULL;
844 size = stat_buf.size;
845 if (size == 0 || size == DiOffT_INVALID
846 || /* size is unrepresentable as a SizeT */
847 size != (DiOffT)(SizeT)(size)) {
848 VG_(close)(sr_Res(fd));
849 return NULL;
852 DiImage* img = ML_(dinfo_zalloc)("di.image.ML_iflf.1", sizeof(DiImage));
853 img->source.is_local = True;
854 img->source.fd = sr_Res(fd);
855 img->size = size;
856 img->real_size = size;
857 img->ces_used = 0;
858 img->source.name = ML_(dinfo_strdup)("di.image.ML_iflf.2", fullpath);
859 img->cslc = NULL;
860 img->cslc_size = 0;
861 img->cslc_used = 0;
862 /* img->ces is already zeroed out */
863 vg_assert(img->source.fd >= 0);
865 /* Force the zeroth entry to be the first chunk of the file.
866 That's likely to be the first part that's requested anyway, and
867 loading it at this point forcing img->cent[0] to always be
868 non-empty, thereby saving us an is-it-empty check on the fast
869 path in get(). */
870 UInt entNo = alloc_CEnt(img, CACHE_ENTRY_SIZE, False/*!fromC*/);
871 vg_assert(entNo == 0);
872 set_CEnt(img, 0, 0);
874 return img;
877 /* As above, but uses fd rather than filename */
878 DiImage* ML_(img_from_fd)(Int fd, const HChar* fullpath)
880 struct vg_stat stat_buf;
881 DiOffT size;
883 if (VG_(fstat)(fd, &stat_buf) != 0) {
884 return NULL;
887 size = stat_buf.size;
888 if (size == 0 || size == DiOffT_INVALID
889 || /* size is unrepresentable as a SizeT */
890 size != (DiOffT)(SizeT)(size)) {
891 return NULL;
894 DiImage* img = ML_(dinfo_zalloc)("di.image.ML_iflf.1", sizeof(DiImage));
895 img->source.is_local = True;
896 img->source.fd = fd;
897 img->size = size;
898 img->real_size = size;
899 img->ces_used = 0;
900 img->source.name = ML_(dinfo_strdup)("di.image.ML_iflf.2", fullpath);
901 img->cslc = NULL;
902 img->cslc_size = 0;
903 img->cslc_used = 0;
904 /* img->ces is already zeroed out */
905 vg_assert(img->source.fd >= 0);
907 /* Force the zeroth entry to be the first chunk of the file.
908 That's likely to be the first part that's requested anyway, and
909 loading it at this point forcing img->cent[0] to always be
910 non-empty, thereby saving us an is-it-empty check on the fast
911 path in get(). */
912 UInt entNo = alloc_CEnt(img, CACHE_ENTRY_SIZE, False/*!fromC*/);
913 vg_assert(entNo == 0);
914 set_CEnt(img, 0, 0);
916 return img;
921 /* Create an image from a file on a remote debuginfo server. This is
922 more complex. There are lots of ways in which it can fail. */
923 DiImage* ML_(img_from_di_server)(const HChar* filename,
924 const HChar* serverAddr)
926 if (filename == NULL || serverAddr == NULL)
927 return NULL;
929 /* The filename must be a plain filename -- no slashes at all. */
930 if (VG_(strchr)(filename, '/') != NULL)
931 return NULL;
933 /* Try to connect to the server. A side effect of this is to parse
934 and reject, if syntactically invalid, |serverAddr|. Reasons why
935 this could fail:
936 - serverAddr is not of the form d.d.d.d:d or d.d.d.d
937 - attempt to connect to that address:port failed
939 Int sd = VG_(connect_via_socket)(serverAddr);
940 if (sd < 0)
941 return NULL;
942 if (!set_blocking(sd))
943 return NULL;
944 Int one = 1;
945 Int sr = VG_(setsockopt)(sd, VKI_IPPROTO_TCP, VKI_TCP_NODELAY,
946 &one, sizeof(one));
947 vg_assert(sr == 0);
949 /* Ok, we got a connection. Ask it for version string, so as to be
950 reasonably sure we're talking to an instance of
951 auxprogs/valgrind-di-server and not to some other random program
952 that happens to be listening on that port. */
953 Frame* req = mk_Frame_noargs("VERS");
954 Frame* res = do_transaction(sd, req);
955 if (res == NULL)
956 goto fail; // do_transaction failed?!
957 UChar* vstr = NULL;
958 if (!parse_Frame_asciiz(res, "VEOK", &vstr))
959 goto fail; // unexpected response kind, or invalid ID string
960 vg_assert(vstr);
961 if (VG_(strcmp)("Valgrind Debuginfo Server, Version 1",
962 (const HChar*)vstr) != 0)
963 goto fail; // wrong version string
964 free_Frame(req);
965 free_Frame(res);
966 req = NULL;
967 res = NULL;
969 /* Server seems plausible. Present it with the name of the file we
970 want and see if it'll give us back a session ID for it. */
971 req = mk_Frame_asciiz("OPEN", filename);
972 res = do_transaction(sd, req);
973 if (res == NULL)
974 goto fail;
975 ULong session_id = 0, size = 0;
976 if (!parse_Frame_le64_le64(res, "OPOK", &session_id, &size))
977 goto fail;
978 free_Frame(req);
979 free_Frame(res);
980 req = NULL;
981 res = NULL;
983 /* We have a session ID. We're ready to roll. */
984 DiImage* img = ML_(dinfo_zalloc)("di.image.ML_ifds.1", sizeof(DiImage));
985 img->source.is_local = False;
986 img->source.fd = sd;
987 img->source.session_id = session_id;
988 img->size = size;
989 img->real_size = size;
990 img->ces_used = 0;
991 img->source.name = ML_(dinfo_zalloc)("di.image.ML_ifds.2",
992 20 + VG_(strlen)(filename)
993 + VG_(strlen)(serverAddr));
994 VG_(sprintf)(img->source.name, "%s at %s", filename, serverAddr);
995 img->cslc = NULL;
996 img->cslc_size = 0;
997 img->cslc_used = 0;
999 /* img->ces is already zeroed out */
1000 vg_assert(img->source.fd >= 0);
1002 /* See comment on equivalent bit in ML_(img_from_local_file) for
1003 rationale. */
1004 UInt entNo = alloc_CEnt(img, CACHE_ENTRY_SIZE, False/*!fromC*/);
1005 vg_assert(entNo == 0);
1006 set_CEnt(img, 0, 0);
1008 return img;
1010 fail:
1011 free_Frame(req);
1012 if (res) {
1013 UChar* reason = NULL;
1014 if (parse_Frame_asciiz(res, "FAIL", &reason)) {
1015 // HACK: if it's just telling us that the file can't
1016 // be opened, don't print it, else we'll get flooded with
1017 // such complaints, one for each main object for which there
1018 // isn't a debuginfo file on the server.
1019 if (0 != VG_(strcmp)((const HChar*)reason, "OPEN: cannot open file"))
1020 VG_(umsg)("ML_(img_from_di_server): fail: %s\n", reason);
1021 } else {
1022 VG_(umsg)("ML_(img_from_di_server): fail: unknown reason\n");
1024 free_Frame(res);
1026 VG_(close)(sd);
1027 return NULL;
1030 DiOffT ML_(img_mark_compressed_part)(DiImage* img, DiOffT offset, SizeT szC,
1031 SizeT szD)
1033 DiOffT ret;
1034 vg_assert(img != NULL);
1035 vg_assert(offset + szC <= img->size);
1037 if (img->cslc_used == img->cslc_size) {
1038 img->cslc_size += COMPRESSED_SLICE_ARRAY_GROW_SIZE;
1039 img->cslc = ML_(dinfo_realloc)("di.image.ML_img_mark_compressed_part.1",
1040 img->cslc, img->cslc_size * sizeof(CSlc));
1043 ret = img->size;
1044 img->cslc[img->cslc_used].offC = offset;
1045 img->cslc[img->cslc_used].szC = szC;
1046 img->cslc[img->cslc_used].offD = img->size;
1047 img->cslc[img->cslc_used].szD = szD;
1048 img->size += szD;
1049 img->cslc_used++;
1050 return ret;
1053 void ML_(img_free)(DiImage* img)
1055 vg_assert(img != NULL);
1057 /* Free up the cache entries, ultimately |img| itself. */
1058 UInt i;
1059 vg_assert(img->ces_used <= CACHE_N_ENTRIES);
1060 for (i = 0; i < img->ces_used; i++) {
1061 ML_(dinfo_free)(img->ces[i]);
1063 /* Take the opportunity to sanity check the rest. */
1064 for (i = i; i < img->ces_used; i++) {
1065 vg_assert(img->ces[i] == NULL);
1067 ML_(dinfo_free)(img->source.name);
1068 ML_(dinfo_free)(img->cslc);
1069 ML_(dinfo_free)(img);
1072 void ML_(img_done)(DiImage* img)
1074 vg_assert(img != NULL);
1075 if (img->source.is_local) {
1076 /* Close the file; nothing else to do. */
1077 vg_assert(img->source.session_id == 0);
1078 VG_(close)(img->source.fd);
1079 } else {
1080 /* Close the socket. The server can detect this and will scrub
1081 the connection when it happens, so there's no need to tell it
1082 explicitly by sending it a "CLOSE" message, or any such. */
1083 vg_assert(img->source.session_id != 0);
1084 VG_(close)(img->source.fd);
1087 ML_(img_free)(img);
1092 DiOffT ML_(img_size)(const DiImage* img)
1094 vg_assert(img != NULL);
1095 return img->size;
1098 DiOffT ML_(img_real_size)(const DiImage* img)
1100 vg_assert(img != NULL);
1101 return img->real_size;
1104 inline Bool ML_(img_valid)(const DiImage* img, DiOffT offset, SizeT size)
1106 vg_assert(img != NULL);
1107 vg_assert(offset != DiOffT_INVALID);
1108 return img->size > 0 && offset + size <= (DiOffT)img->size;
1111 __attribute__((noinline))
1112 static void ensure_valid_failed (const DiImage* img, DiOffT offset, SizeT size,
1113 const HChar* caller)
1115 VG_(umsg)("Valgrind: debuginfo reader: ensure_valid failed:\n");
1116 VG_(umsg)("Valgrind: during call to %s\n", caller);
1117 VG_(umsg)("Valgrind: request for range [%llu, +%lu) exceeds\n",
1118 offset, size);
1119 VG_(umsg)("Valgrind: valid image size of %lu for image:\n",
1120 img->size);
1121 VG_(umsg)("Valgrind: \"%s\"\n", img->source.name);
1122 give_up__image_overrun();
1125 /* Check the given range is valid, and if not, shut down the system.
1126 An invalid range would imply that we're trying to read outside the
1127 image, which normally means the image is corrupted somehow, or the
1128 caller is buggy. Recovering is too complex, and we have
1129 probably-corrupt debuginfo, so just give up. */
1130 static void ensure_valid(const DiImage* img, DiOffT offset, SizeT size,
1131 const HChar* caller)
1133 if (LIKELY(ML_(img_valid)(img, offset, size)))
1134 return;
1135 else
1136 ensure_valid_failed(img, offset, size, caller);
1140 void ML_(img_get)(/*OUT*/void* dst,
1141 DiImage* img, DiOffT offset, SizeT size)
1143 vg_assert(img != NULL);
1144 vg_assert(size > 0);
1145 ensure_valid(img, offset, size, "ML_(img_get)");
1146 SizeT i;
1147 for (i = 0; i < size; i++) {
1148 ((UChar*)dst)[i] = get(img, offset + i);
1152 SizeT ML_(img_get_some)(/*OUT*/void* dst,
1153 DiImage* img, DiOffT offset, SizeT size)
1155 vg_assert(img != NULL);
1156 vg_assert(size > 0);
1157 ensure_valid(img, offset, size, "ML_(img_get_some)");
1158 UChar* dstU = (UChar*)dst;
1159 /* Use |get| in the normal way to get the first byte of the range.
1160 This guarantees to put the cache entry containing |offset| in
1161 position zero. */
1162 dstU[0] = get(img, offset);
1163 /* Now just read as many bytes as we can (or need) directly out of
1164 entry zero, without bothering to call |get| each time. */
1165 const CEnt* ce = img->ces[0];
1166 vg_assert(ce && ce->used >= 1);
1167 vg_assert(is_in_CEnt(ce, offset));
1168 SizeT nToCopy = size - 1;
1169 SizeT nAvail = (SizeT)(ce->used - (offset + 1 - ce->off));
1170 vg_assert(nAvail >= 0 && nAvail <= ce->used-1);
1171 if (nAvail < nToCopy) nToCopy = nAvail;
1172 VG_(memcpy)(&dstU[1], &ce->data[offset + 1 - ce->off], nToCopy);
1173 return nToCopy + 1;
1177 SizeT ML_(img_strlen)(DiImage* img, DiOffT off)
1179 ensure_valid(img, off, 1, "ML_(img_strlen)");
1180 SizeT i = 0;
1181 while (get(img, off + i) != 0) i++;
1182 return i;
1185 HChar* ML_(img_strdup)(DiImage* img, const HChar* cc, DiOffT offset)
1187 ensure_valid(img, offset, 1, "ML_(img_strdup)");
1188 SizeT len = ML_(img_strlen)(img, offset);
1189 HChar* res = ML_(dinfo_zalloc)(cc, len+1);
1190 SizeT i;
1191 for (i = 0; i < len; i++) {
1192 res[i] = get(img, offset+i);
1194 vg_assert(res[len] == 0);
1195 return res;
1198 Int ML_(img_strcmp)(DiImage* img, DiOffT off1, DiOffT off2)
1200 ensure_valid(img, off1, 1, "ML_(img_strcmp)(first arg)");
1201 ensure_valid(img, off2, 1, "ML_(img_strcmp)(second arg)");
1202 while (True) {
1203 UChar c1 = get(img, off1);
1204 UChar c2 = get(img, off2);
1205 if (c1 < c2) return -1;
1206 if (c1 > c2) return 1;
1207 if (c1 == 0) return 0;
1208 off1++; off2++;
1212 Int ML_(img_strcmp_c)(DiImage* img, DiOffT off1, const HChar* str2)
1214 ensure_valid(img, off1, 1, "ML_(img_strcmp_c)");
1215 while (True) {
1216 UChar c1 = get(img, off1);
1217 UChar c2 = *(const UChar*)str2;
1218 if (c1 < c2) return -1;
1219 if (c1 > c2) return 1;
1220 if (c1 == 0) return 0;
1221 off1++; str2++;
1225 UChar ML_(img_get_UChar)(DiImage* img, DiOffT offset)
1227 ensure_valid(img, offset, 1, "ML_(img_get_UChar)");
1228 return get(img, offset);
1231 UShort ML_(img_get_UShort)(DiImage* img, DiOffT offset)
1233 UShort r;
1234 ML_(img_get)(&r, img, offset, sizeof(r));
1235 return r;
1238 UInt ML_(img_get_UInt)(DiImage* img, DiOffT offset)
1240 UInt r;
1241 ML_(img_get)(&r, img, offset, sizeof(r));
1242 return r;
1245 ULong ML_(img_get_ULong)(DiImage* img, DiOffT offset)
1247 ULong r;
1248 ML_(img_get)(&r, img, offset, sizeof(r));
1249 return r;
1254 * This routine for calculating the CRC for a separate debug file
1255 * is GPLed code borrowed from GNU binutils.
1257 UInt ML_(img_calc_gnu_debuglink_crc32)(DiImage* img)
1259 static const UInt crc32_table[256] =
1261 0x00000000, 0x77073096, 0xee0e612c, 0x990951ba, 0x076dc419,
1262 0x706af48f, 0xe963a535, 0x9e6495a3, 0x0edb8832, 0x79dcb8a4,
1263 0xe0d5e91e, 0x97d2d988, 0x09b64c2b, 0x7eb17cbd, 0xe7b82d07,
1264 0x90bf1d91, 0x1db71064, 0x6ab020f2, 0xf3b97148, 0x84be41de,
1265 0x1adad47d, 0x6ddde4eb, 0xf4d4b551, 0x83d385c7, 0x136c9856,
1266 0x646ba8c0, 0xfd62f97a, 0x8a65c9ec, 0x14015c4f, 0x63066cd9,
1267 0xfa0f3d63, 0x8d080df5, 0x3b6e20c8, 0x4c69105e, 0xd56041e4,
1268 0xa2677172, 0x3c03e4d1, 0x4b04d447, 0xd20d85fd, 0xa50ab56b,
1269 0x35b5a8fa, 0x42b2986c, 0xdbbbc9d6, 0xacbcf940, 0x32d86ce3,
1270 0x45df5c75, 0xdcd60dcf, 0xabd13d59, 0x26d930ac, 0x51de003a,
1271 0xc8d75180, 0xbfd06116, 0x21b4f4b5, 0x56b3c423, 0xcfba9599,
1272 0xb8bda50f, 0x2802b89e, 0x5f058808, 0xc60cd9b2, 0xb10be924,
1273 0x2f6f7c87, 0x58684c11, 0xc1611dab, 0xb6662d3d, 0x76dc4190,
1274 0x01db7106, 0x98d220bc, 0xefd5102a, 0x71b18589, 0x06b6b51f,
1275 0x9fbfe4a5, 0xe8b8d433, 0x7807c9a2, 0x0f00f934, 0x9609a88e,
1276 0xe10e9818, 0x7f6a0dbb, 0x086d3d2d, 0x91646c97, 0xe6635c01,
1277 0x6b6b51f4, 0x1c6c6162, 0x856530d8, 0xf262004e, 0x6c0695ed,
1278 0x1b01a57b, 0x8208f4c1, 0xf50fc457, 0x65b0d9c6, 0x12b7e950,
1279 0x8bbeb8ea, 0xfcb9887c, 0x62dd1ddf, 0x15da2d49, 0x8cd37cf3,
1280 0xfbd44c65, 0x4db26158, 0x3ab551ce, 0xa3bc0074, 0xd4bb30e2,
1281 0x4adfa541, 0x3dd895d7, 0xa4d1c46d, 0xd3d6f4fb, 0x4369e96a,
1282 0x346ed9fc, 0xad678846, 0xda60b8d0, 0x44042d73, 0x33031de5,
1283 0xaa0a4c5f, 0xdd0d7cc9, 0x5005713c, 0x270241aa, 0xbe0b1010,
1284 0xc90c2086, 0x5768b525, 0x206f85b3, 0xb966d409, 0xce61e49f,
1285 0x5edef90e, 0x29d9c998, 0xb0d09822, 0xc7d7a8b4, 0x59b33d17,
1286 0x2eb40d81, 0xb7bd5c3b, 0xc0ba6cad, 0xedb88320, 0x9abfb3b6,
1287 0x03b6e20c, 0x74b1d29a, 0xead54739, 0x9dd277af, 0x04db2615,
1288 0x73dc1683, 0xe3630b12, 0x94643b84, 0x0d6d6a3e, 0x7a6a5aa8,
1289 0xe40ecf0b, 0x9309ff9d, 0x0a00ae27, 0x7d079eb1, 0xf00f9344,
1290 0x8708a3d2, 0x1e01f268, 0x6906c2fe, 0xf762575d, 0x806567cb,
1291 0x196c3671, 0x6e6b06e7, 0xfed41b76, 0x89d32be0, 0x10da7a5a,
1292 0x67dd4acc, 0xf9b9df6f, 0x8ebeeff9, 0x17b7be43, 0x60b08ed5,
1293 0xd6d6a3e8, 0xa1d1937e, 0x38d8c2c4, 0x4fdff252, 0xd1bb67f1,
1294 0xa6bc5767, 0x3fb506dd, 0x48b2364b, 0xd80d2bda, 0xaf0a1b4c,
1295 0x36034af6, 0x41047a60, 0xdf60efc3, 0xa867df55, 0x316e8eef,
1296 0x4669be79, 0xcb61b38c, 0xbc66831a, 0x256fd2a0, 0x5268e236,
1297 0xcc0c7795, 0xbb0b4703, 0x220216b9, 0x5505262f, 0xc5ba3bbe,
1298 0xb2bd0b28, 0x2bb45a92, 0x5cb36a04, 0xc2d7ffa7, 0xb5d0cf31,
1299 0x2cd99e8b, 0x5bdeae1d, 0x9b64c2b0, 0xec63f226, 0x756aa39c,
1300 0x026d930a, 0x9c0906a9, 0xeb0e363f, 0x72076785, 0x05005713,
1301 0x95bf4a82, 0xe2b87a14, 0x7bb12bae, 0x0cb61b38, 0x92d28e9b,
1302 0xe5d5be0d, 0x7cdcefb7, 0x0bdbdf21, 0x86d3d2d4, 0xf1d4e242,
1303 0x68ddb3f8, 0x1fda836e, 0x81be16cd, 0xf6b9265b, 0x6fb077e1,
1304 0x18b74777, 0x88085ae6, 0xff0f6a70, 0x66063bca, 0x11010b5c,
1305 0x8f659eff, 0xf862ae69, 0x616bffd3, 0x166ccf45, 0xa00ae278,
1306 0xd70dd2ee, 0x4e048354, 0x3903b3c2, 0xa7672661, 0xd06016f7,
1307 0x4969474d, 0x3e6e77db, 0xaed16a4a, 0xd9d65adc, 0x40df0b66,
1308 0x37d83bf0, 0xa9bcae53, 0xdebb9ec5, 0x47b2cf7f, 0x30b5ffe9,
1309 0xbdbdf21c, 0xcabac28a, 0x53b39330, 0x24b4a3a6, 0xbad03605,
1310 0xcdd70693, 0x54de5729, 0x23d967bf, 0xb3667a2e, 0xc4614ab8,
1311 0x5d681b02, 0x2a6f2b94, 0xb40bbe37, 0xc30c8ea1, 0x5a05df1b,
1312 0x2d02ef8d
1315 vg_assert(img != NULL);
1317 /* If the image is local, calculate the CRC here directly. If it's
1318 remote, forward the request to the server. */
1319 if (img->source.is_local) {
1320 /* Work through the image in 1 KB chunks. */
1321 UInt crc = 0xFFFFFFFF;
1322 DiOffT img_szB = ML_(img_size)(img);
1323 DiOffT curr_off = 0;
1324 while (1) {
1325 vg_assert(curr_off >= 0 && curr_off <= img_szB);
1326 if (curr_off == img_szB) break;
1327 DiOffT avail = img_szB - curr_off;
1328 vg_assert(avail > 0 && avail <= img_szB);
1329 if (avail > 1024) avail = 1024;
1330 UChar buf[1024];
1331 SizeT nGot = ML_(img_get_some)(buf, img, curr_off, avail);
1332 vg_assert(nGot >= 1 && nGot <= avail);
1333 UInt i;
1334 for (i = 0; i < (UInt)nGot; i++)
1335 crc = crc32_table[(crc ^ buf[i]) & 0xff] ^ (crc >> 8);
1336 curr_off += nGot;
1338 return ~crc & 0xFFFFFFFF;
1339 } else {
1340 Frame* req = mk_Frame_noargs("CRC3");
1341 Frame* res = do_transaction(img->source.fd, req);
1342 if (!res) goto remote_crc_fail;
1343 ULong crc32 = 0;
1344 if (!parse_Frame_le64(res, "CROK", &crc32)) goto remote_crc_fail;
1345 if ((crc32 & ~0xFFFFFFFFULL) != 0) goto remote_crc_fail;
1346 free_Frame(req);
1347 free_Frame(res);
1348 return (UInt)crc32;
1349 remote_crc_fail:
1351 // XXXX common this up with the READ diagnostic cases
1352 if (res) {
1353 UChar* reason = NULL;
1354 if (parse_Frame_asciiz(res, "FAIL", &reason)) {
1355 VG_(umsg)("img_calc_gnu_debuglink_crc32: fail: "
1356 "%s\n", reason);
1357 } else {
1358 VG_(umsg)("img_calc_gnu_debuglink_crc32: fail: "
1359 "unknown reason\n");
1361 } else {
1362 VG_(umsg)("img_calc_gnu_debuglink_crc32: fail: "
1363 "server unexpectedly closed the connection\n");
1366 if (req) free_Frame(req);
1367 if (res) free_Frame(res);
1368 // FIXME: now what?
1369 give_up__comms_lost();
1370 /* NOTREACHED */
1371 vg_assert(0);
1373 /*NOTREACHED*/
1374 vg_assert(0);
1377 ////////////////////////////////////////////////////
1378 #include "minilzo-inl.c"
1380 /*--------------------------------------------------------------------*/
1381 /*--- end image.c ---*/
1382 /*--------------------------------------------------------------------*/