coverity: most of the remaining unsigned >= 0 comparison warnings
[valgrind.git] / coregrind / m_debuginfo / image.c
blobede83573093d3da3bdd1d1a218f848682900b26b
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 + ce->used <= img->real_size)) goto fail;
147 return True;
149 fail:
150 VG_(printf)("is_sane_CEnt[%u]: fail: %s\n", i, who);
151 pp_CEnt("failing CEnt", ce);
152 return False;
156 /* A frame. The first 4 bytes of |data| give the kind of the frame,
157 and the rest of it is kind-specific data. */
158 typedef struct { UChar* data; SizeT n_data; } Frame;
160 static void write_UInt_le ( /*OUT*/UChar* dst, UInt n )
162 Int i;
163 for (i = 0; i <= 3; i++) {
164 dst[i] = (UChar)(n & 0xFF);
165 n >>= 8;
169 static UInt read_UInt_le ( const UChar* src )
171 UInt r = 0;
172 Int i;
173 for (i = 3; i >= 0; i--) {
174 r <<= 8;
175 r += (UInt)src[i];
177 return r;
180 static void write_ULong_le ( /*OUT*/UChar* dst, ULong n )
182 Int i;
183 for (i = 0; i <= 7; i++) {
184 dst[i] = (UChar)(n & 0xFF);
185 n >>= 8;
189 static ULong read_ULong_le ( const UChar* src )
191 ULong r = 0;
192 Int i;
193 for (i = 7; i >= 0; i--) {
194 r <<= 8;
195 r += (ULong)src[i];
197 return r;
201 /* Set |sd| to be blocking. Returns True on success. */
202 static Bool set_blocking ( int sd )
204 Int res;
205 res = VG_(fcntl)(sd, VKI_F_GETFL, 0/*ignored*/);
206 if (res != -1)
207 res = VG_(fcntl)(sd, VKI_F_SETFL, res & ~VKI_O_NONBLOCK);
208 return (res != -1);
211 /* Tries to read 'len' bytes from fd, blocking if necessary. Assumes
212 fd has been set in blocking mode. If it returns with the number of
213 bytes read < len, it means that either fd was closed, or there was
214 an error on it. */
215 static Int my_read ( Int fd, UChar* buf, Int len )
217 Int nRead = 0;
218 while (1) {
219 if (nRead == len) return nRead;
220 vg_assert(nRead < len);
221 Int nNeeded = len - nRead;
222 vg_assert(nNeeded > 0);
223 Int n = VG_(read)(fd, &buf[nRead], nNeeded);
224 if (n <= 0) return nRead; /* error or EOF */
225 nRead += n;
229 /* Tries to write 'len' bytes to fd, blocking if necessary. Assumes
230 fd has been set in blocking mode. If it returns with the number of
231 bytes written < len, it means that either fd was closed, or there was
232 an error on it. */
233 static Int my_write ( Int fd, const UChar* buf, Int len )
235 Int nWritten = 0;
236 while (1) {
237 if (nWritten == len) return nWritten;
238 vg_assert(nWritten < len);
239 Int nStillToDo = len - nWritten;
240 vg_assert(nStillToDo > 0);
241 Int n = VG_(write_socket)(fd, &buf[nWritten], nStillToDo);
242 if (n < 0) return nWritten; /* error or EOF */
243 nWritten += n;
247 /* If we lost communication with the remote server, just give up.
248 Recovering is too difficult. */
249 static void give_up__comms_lost(void)
251 VG_(umsg)("\n");
252 VG_(umsg)(
253 "Valgrind: debuginfo reader: Lost communication with the remote\n");
254 VG_(umsg)(
255 "Valgrind: debuginfo server. I can't recover. Giving up. Sorry.\n");
256 VG_(umsg)("\n");
257 VG_(exit)(1);
258 /*NOTREACHED*/
261 static void give_up__image_overrun(void)
263 VG_(umsg)("\n");
264 VG_(umsg)(
265 "Valgrind: debuginfo reader: Possibly corrupted debuginfo file.\n");
266 VG_(umsg)(
267 "Valgrind: I can't recover. Giving up. Sorry.\n");
268 VG_(umsg)("\n");
269 VG_(exit)(1);
270 /*NOTREACHED*/
273 /* "Do" a transaction: that is, send the given frame to the server and
274 return the frame it sends back. Caller owns the resulting frame
275 and must free it. A NULL return means the transaction failed for
276 some reason. */
277 static Frame* do_transaction ( Int sd, const Frame* req )
279 if (0) VG_(printf)("CLIENT: send %c%c%c%c\n",
280 req->data[0], req->data[1], req->data[2], req->data[3]);
282 /* What goes on the wire is:
283 adler(le32) n_data(le32) data[0 .. n_data-1]
284 where the checksum covers n_data as well as data[].
286 /* The initial Adler-32 value */
287 UInt adler = VG_(adler32)(0, NULL, 0);
289 /* Fold in the length field, encoded as le32. */
290 UChar wr_first8[8];
291 write_UInt_le(&wr_first8[4], req->n_data);
292 adler = VG_(adler32)(adler, &wr_first8[4], 4);
293 /* Fold in the data values */
294 adler = VG_(adler32)(adler, req->data, req->n_data);
295 write_UInt_le(&wr_first8[0], adler);
297 Int r = my_write(sd, &wr_first8[0], 8);
298 if (r != 8) return NULL;
299 vg_assert(req->n_data >= 4); // else ill formed -- no KIND field
300 r = my_write(sd, req->data, req->n_data);
301 if (r != req->n_data) return NULL;
303 /* So, the request is sent. Now get a request of the same format
304 out of the channel. */
305 UChar rd_first8[8]; // adler32; length32
306 r = my_read(sd, &rd_first8[0], 8);
307 if (r != 8) return NULL;
308 UInt rd_adler = read_UInt_le(&rd_first8[0]);
309 UInt rd_len = read_UInt_le(&rd_first8[4]);
310 /* Allocate a Frame to hold the result data, and read into it. */
311 // Reject obviously-insane length fields.
312 if (rd_len < 4 || rd_len > 4*1024*1024) return NULL;
313 Frame* res = ML_(dinfo_zalloc)("di.do_transaction.1", sizeof(Frame));
314 res->n_data = rd_len;
315 res->data = ML_(dinfo_zalloc)("di.do_transaction.2", rd_len);
316 r = my_read(sd, res->data, res->n_data);
317 if (r != rd_len) return NULL;
319 if (0) VG_(printf)("CLIENT: recv %c%c%c%c\n",
320 res->data[0], res->data[1], res->data[2], res->data[3]);
322 /* Compute the checksum for the received data, and check it. */
323 adler = VG_(adler32)(0, NULL, 0); // initial value
324 adler = VG_(adler32)(adler, &rd_first8[4], 4);
325 if (res->n_data > 0)
326 adler = VG_(adler32)(adler, res->data, res->n_data);
328 if (adler/*computed*/ != rd_adler/*expected*/) return NULL;
329 return res;
332 static void free_Frame ( Frame* fr )
334 vg_assert(fr && fr->data);
335 ML_(dinfo_free)(fr->data);
336 ML_(dinfo_free)(fr);
339 static Frame* mk_Frame_noargs ( const HChar* tag )
341 vg_assert(VG_(strlen)(tag) == 4);
342 Frame* f = ML_(dinfo_zalloc)("di.mFn.1", sizeof(Frame));
343 f->n_data = 4;
344 f->data = ML_(dinfo_zalloc)("di.mFn.2", f->n_data);
345 VG_(memcpy)(&f->data[0], tag, 4);
346 return f;
349 static Frame* mk_Frame_le64_le64_le64 ( const HChar* tag,
350 ULong n1, ULong n2, ULong n3 )
352 vg_assert(VG_(strlen)(tag) == 4);
353 Frame* f = ML_(dinfo_zalloc)("di.mFlll.1", sizeof(Frame));
354 f->n_data = 4 + 3*8;
355 f->data = ML_(dinfo_zalloc)("di.mFlll.2", f->n_data);
356 VG_(memcpy)(&f->data[0], tag, 4);
357 write_ULong_le(&f->data[4 + 0*8], n1);
358 write_ULong_le(&f->data[4 + 1*8], n2);
359 write_ULong_le(&f->data[4 + 2*8], n3);
360 return f;
363 static Frame* mk_Frame_asciiz ( const HChar* tag, const HChar* str )
365 vg_assert(VG_(strlen)(tag) == 4);
366 Frame* f = ML_(dinfo_zalloc)("di.mFa.1", sizeof(Frame));
367 SizeT n_str = VG_(strlen)(str);
368 f->n_data = 4 + n_str + 1;
369 f->data = ML_(dinfo_zalloc)("di.mFa.2", f->n_data);
370 VG_(memcpy)(&f->data[0], tag, 4);
371 VG_(memcpy)(&f->data[4], str, n_str);
372 vg_assert(f->data[4 + n_str] == 0);
373 return f;
376 static Bool parse_Frame_le64 ( const Frame* fr, const HChar* tag,
377 /*OUT*/ULong* n1 )
379 vg_assert(VG_(strlen)(tag) == 4);
380 if (!fr || !fr->data) return False;
381 if (fr->n_data < 4) return False;
382 if (VG_(memcmp)(&fr->data[0], tag, 4) != 0) return False;
383 if (fr->n_data != 4 + 1*8) return False;
384 *n1 = read_ULong_le(&fr->data[4 + 0*8]);
385 return True;
388 static Bool parse_Frame_le64_le64 ( const Frame* fr, const HChar* tag,
389 /*OUT*/ULong* n1, /*OUT*/ULong* n2 )
391 vg_assert(VG_(strlen)(tag) == 4);
392 if (!fr || !fr->data) return False;
393 if (fr->n_data < 4) return False;
394 if (VG_(memcmp)(&fr->data[0], tag, 4) != 0) return False;
395 if (fr->n_data != 4 + 2*8) return False;
396 *n1 = read_ULong_le(&fr->data[4 + 0*8]);
397 *n2 = read_ULong_le(&fr->data[4 + 1*8]);
398 return True;
401 static Bool parse_Frame_asciiz ( const Frame* fr, const HChar* tag,
402 /*OUT*/UChar** str )
404 vg_assert(VG_(strlen)(tag) == 4);
405 if (!fr || !fr->data) return False;
406 if (fr->n_data < 4) return False;
407 if (VG_(memcmp)(&fr->data[0], tag, 4) != 0) return False;
408 if (fr->n_data < 5) return False; // else there isn't even enough
409 // space for the terminating zero
410 /* Find the terminating zero and ensure it's right at the end
411 of the data. If not, the frame is malformed. */
412 SizeT i = 4;
413 while (True) {
414 if (i >= fr->n_data) break;
415 if (fr->data[i] == 0) break;
416 i++;
418 vg_assert(i <= fr->n_data);
419 if (i == fr->n_data-1 && fr->data[i] == 0) {
420 *str = &fr->data[4];
421 return True;
422 } else {
423 return False;
427 static Bool parse_Frame_le64_le64_le64_bytes (
428 const Frame* fr, const HChar* tag,
429 /*OUT*/ULong* n1, /*OUT*/ULong* n2, /*OUT*/ULong* n3,
430 /*OUT*/UChar** data, /*OUT*/ULong* n_data
433 vg_assert(VG_(strlen)(tag) == 4);
434 if (!fr || !fr->data) return False;
435 if (fr->n_data < 4) return False;
436 if (VG_(memcmp)(&fr->data[0], tag, 4) != 0) return False;
437 if (fr->n_data < 4 + 3*8) return False;
438 *n1 = read_ULong_le(&fr->data[4 + 0*8]);
439 *n2 = read_ULong_le(&fr->data[4 + 1*8]);
440 *n3 = read_ULong_le(&fr->data[4 + 2*8]);
441 *data = &fr->data[4 + 3*8];
442 *n_data = fr->n_data - (4 + 3*8);
443 vg_assert(fr->n_data >= 4 + 3*8);
444 return True;
447 static DiOffT block_round_down ( DiOffT i )
449 return i & ((DiOffT)~(CACHE_ENTRY_SIZE-1));
452 /* Is this offset inside this CEnt? */
453 static inline Bool is_in_CEnt ( const CEnt* cent, DiOffT off )
455 /* This assertion is checked by set_CEnt, so checking it here has
456 no benefit, whereas skipping it does remove it from the hottest
457 path. */
458 /* vg_assert(cent->used > 0 && cent->used <= cent->size); */
459 /* What we want to return is:
460 cent->off <= off && off < cent->off + cent->used;
461 This is however a very hot path, so here's alternative that uses
462 only one conditional branch, using the following transformation,
463 where all quantities are unsigned:
464 x >= LO && x < LO+N
465 --> x-LO >= 0 && x-LO < LO+N-LO
466 --> x-LO >= 0 && x-LO < N
467 --> x-LO < N
468 This is however only valid when the original bounds, that is, LO
469 .. LO+N-1, do not wrap around the end of the address space. That
470 is, we require that LO <= LO+N-1. But that's OK .. we don't
471 expect wraparounds in CEnts or for that matter any object
472 allocated from C-land. See Hacker's Delight, Chapter 4.1,
473 "Checking Bounds of Integers", for more details.
475 return off - cent->off < cent->used;
478 /* Returns pointer to CSlc or NULL */
479 static inline CSlc* find_cslc ( DiImage* img, DiOffT off )
481 for (UInt i = 0; i < img->cslc_used; i++) {
482 if ( (img->cslc[i].offD <= off)
483 && (img->cslc[i].offD + img->cslc[i].szD > off)
485 return &img->cslc[i];
487 return NULL;
490 /* Allocate a new CEnt, connect it to |img|, and return its index. */
491 static UInt alloc_CEnt ( DiImage* img, SizeT szB, Bool fromC )
493 vg_assert(img != NULL);
494 vg_assert(img->ces_used < CACHE_N_ENTRIES);
495 if (fromC) {
496 // szB can be arbitrary
497 } else {
498 vg_assert(szB == CACHE_ENTRY_SIZE);
500 UInt entNo = img->ces_used;
501 img->ces_used++;
502 vg_assert(img->ces[entNo] == NULL);
503 img->ces[entNo] = ML_(dinfo_zalloc)("di.alloc_CEnt.1",
504 offsetof(CEnt, data) + szB);
505 img->ces[entNo]->size = szB;
506 img->ces[entNo]->fromC = fromC;
507 vg_assert(is_sane_CEnt("alloc_CEnt", img, entNo));
508 return entNo;
511 static void realloc_CEnt ( DiImage* img, UInt entNo, SizeT szB, Bool fromC )
513 vg_assert(img != NULL);
514 vg_assert(fromC || szB >= CACHE_ENTRY_SIZE);
515 vg_assert(is_sane_CEnt("realloc_CEnt-pre", img, entNo));
516 img->ces[entNo] = ML_(dinfo_realloc)("di.realloc_CEnt.1",
517 img->ces[entNo],
518 offsetof(CEnt, data) + szB);
521 /* Move the given entry to the top and slide those above it down by 1,
522 to make space. */
523 static void move_CEnt_to_top ( DiImage* img, UInt entNo )
525 vg_assert(entNo < img->ces_used);
526 if (LIKELY(entNo == 1)) {
527 CEnt* tmp = img->ces[1];
528 img->ces[entNo] = img->ces[0];
529 img->ces[0] = tmp;
530 } else {
531 vg_assert(entNo > 1); // a.k.a. >= 2
532 CEnt* tmp = img->ces[entNo];
533 img->ces[entNo] = img->ces[entNo-1];
534 entNo--;
535 img->ces[entNo] = img->ces[entNo-1];
536 entNo--;
537 while (entNo > 0) {
538 img->ces[entNo] = img->ces[entNo-1];
539 entNo--;
541 img->ces[0] = tmp;
545 /* Set the given entry so that it has a chunk of the file containing
546 the given offset. It is this function that brings data into the
547 cache, either by reading the local file or pulling it from the
548 remote server. */
549 static void set_CEnt ( const DiImage* img, UInt entNo, DiOffT off )
551 SizeT len;
552 DiOffT off_orig = off;
553 vg_assert(img != NULL);
554 vg_assert(img->ces_used <= CACHE_N_ENTRIES);
555 vg_assert(entNo < img->ces_used);
556 vg_assert(off < img->real_size);
557 CEnt* ce = img->ces[entNo];
558 vg_assert(ce != NULL);
559 /* Compute [off, +len) as the slice we are going to read. */
560 off = block_round_down(off);
561 len = img->real_size - off;
562 if (len > ce->size)
563 len = ce->size;
564 /* It is conceivable that the 'len > 0' bit could fail if we make
565 an image with a zero sized file. But then no 'get' request on
566 that image would be valid. */
567 vg_assert(len > 0 && len <= ce->size);
568 vg_assert(off + len <= img->real_size);
569 vg_assert(off <= off_orig && off_orig < off+len);
570 /* So, read off .. off+len-1 into the entry. */
572 if (0) {
573 static UInt t_last = 0;
574 static ULong nread = 0;
575 UInt now = VG_(read_millisecond_timer)();
576 UInt delay = now - t_last;
577 t_last = now;
578 nread += len;
579 VG_(printf)("XXXXXXXX (tot %'llu) read %'lu offset %'llu delay %'u\n",
580 nread, len, off, delay);
583 if (img->source.is_local) {
584 // Simple: just read it
585 SysRes sr = VG_(pread)(img->source.fd, &ce->data[0], (Int)len, off);
586 vg_assert(!sr_isError(sr));
587 } else {
588 // Not so simple: poke the server
589 vg_assert(img->source.session_id > 0);
590 Frame* req
591 = mk_Frame_le64_le64_le64("READ", img->source.session_id, off, len);
592 Frame* res = do_transaction(img->source.fd, req);
593 free_Frame(req); req = NULL;
594 if (!res) goto server_fail;
595 ULong rx_session_id = 0, rx_off = 0, rx_len = 0, rx_zdata_len = 0;
596 UChar* rx_data = NULL;
597 /* Pretty confusing. rx_sessionid, rx_off and rx_len are copies
598 of the values that we requested in the READ frame just above,
599 so we can be sure that the server is responding to the right
600 request. It just copies them from the request into the
601 response. rx_data is the actual data, and rx_zdata_len is
602 its compressed length. Hence rx_len must equal len, but
603 rx_zdata_len can be different -- smaller, hopefully.. */
604 if (!parse_Frame_le64_le64_le64_bytes
605 (res, "RDOK", &rx_session_id, &rx_off,
606 &rx_len, &rx_data, &rx_zdata_len))
607 goto server_fail;
608 if (rx_session_id != img->source.session_id
609 || rx_off != off || rx_len != len || rx_data == NULL)
610 goto server_fail;
612 //VG_(memcpy)(&ce->data[0], rx_data, len);
613 // Decompress into the destination buffer
614 // Tell the lib the max number of output bytes it can write.
615 // After the call, this holds the number of bytes actually written,
616 // and it's an error if it is different.
617 lzo_uint out_len = len;
618 Int lzo_rc = lzo1x_decompress_safe(rx_data, rx_zdata_len,
619 &ce->data[0], &out_len,
620 NULL);
621 Bool ok = lzo_rc == LZO_E_OK && out_len == len;
622 if (!ok) goto server_fail;
624 free_Frame(res); res = NULL;
625 goto end_of_else_clause;
626 server_fail:
627 /* The server screwed up somehow. Now what? */
628 if (res) {
629 UChar* reason = NULL;
630 if (parse_Frame_asciiz(res, "FAIL", &reason)) {
631 VG_(umsg)("set_CEnt (reading data from DI server): fail: "
632 "%s\n", reason);
633 } else {
634 VG_(umsg)("set_CEnt (reading data from DI server): fail: "
635 "unknown reason\n");
637 free_Frame(res); res = NULL;
638 } else {
639 VG_(umsg)("set_CEnt (reading data from DI server): fail: "
640 "server unexpectedly closed the connection\n");
642 give_up__comms_lost();
643 /* NOTREACHED */
644 vg_assert(0);
645 end_of_else_clause:
649 ce->off = off;
650 ce->used = len;
651 ce->fromC = False;
652 vg_assert(ce == img->ces[entNo]);
653 vg_assert(is_sane_CEnt("set_CEnt", img, entNo));
656 __attribute__((noinline))
657 static UChar get_slowcase ( DiImage* img, DiOffT off )
659 /* Stay sane .. */
660 vg_assert(off < img->size);
661 vg_assert(img->ces_used <= CACHE_N_ENTRIES);
662 UInt i;
663 /* Start the search at entry 1, since the fast-case function
664 checked slot zero already. */
665 for (i = 1; i < img->ces_used; i++) {
666 vg_assert(img->ces[i]);
667 if (is_in_CEnt(img->ces[i], off))
668 break;
670 vg_assert(i >= 1);
672 if (LIKELY(i < img->ces_used)) {
673 // Found it. Move to the top and stop.
674 move_CEnt_to_top(img, i);
675 vg_assert(is_in_CEnt(img->ces[0], off));
676 return img->ces[0]->data[ off - img->ces[0]->off ];
679 vg_assert(i <= img->ces_used);
681 // It's not in any entry. Either allocate a new one or recycle the LRU
682 // one. This is where the presence of compressed sections makes things
683 // tricky. There are 4 cases to consider:
685 // (1) not from a compressed slice, we can allocate a new entry
686 // (2) not from a compressed slice, we have to recycle the LRU entry
687 // (3) from a compressed slice, we can allocate a new entry
688 // (4) from a compressed slice, we have to recycle the LRU entry
690 // Cases (3) and (4) are complex because we will have to call
691 // ML_(img_get_some) to get the compressed data. But this function is
692 // reachable from ML_(img_get_some), so we may re-enter get_slowcase a
693 // second time as a result. Given that the compressed data will be cause
694 // only cases (1) and (2) to happen, this guarantees no infinite recursion.
695 // It does however mean that we can't carry (in this function invokation)
696 // any local copies of the overall cache state across the ML_(img_get_some)
697 // call, since it may become invalidated by the recursive call to
698 // get_slowcase.
700 // First of all, see if it is in a compressed slice, and if so, pull the
701 // compressed data into an intermediate buffer. Given the preceding
702 // comment, this is a safe place to do it, since we are not carrying any
703 // cache state here apart from the knowledge that the requested offset is
704 // not in the cache at all, and the recursive call won't change that fact.
706 CSlc* cslc = find_cslc(img, off);
707 UChar* cbuf = NULL;
708 if (cslc != NULL) {
709 SizeT len = 0;
710 cbuf = ML_(dinfo_zalloc)("di.image.get_slowcase.cbuf-1", cslc->szC);
711 // get compressed data
712 while (len < cslc->szC)
713 len += ML_(img_get_some)(cbuf + len, img, cslc->offC + len,
714 cslc->szC - len);
717 // Now we can do what we like.
718 vg_assert((cslc == NULL && cbuf == NULL) || (cslc != NULL && cbuf != NULL));
720 // Note, we can't capture this earlier, for exactly the reasons detailed
721 // above.
722 UInt ces_used_at_entry = img->ces_used;
724 // This is the size of the CEnt that we want to have after allocation or
725 // recycling.
726 SizeT size = (cslc == NULL) ? CACHE_ENTRY_SIZE : cslc->szD;
728 // Cases (1) and (3)
729 if (img->ces_used < CACHE_N_ENTRIES) {
730 /* Allocate a new cache entry, and fill it in. */
731 i = alloc_CEnt(img, size, /*fromC?*/cslc != NULL);
732 if (cslc == NULL) {
733 set_CEnt(img, i, off);
734 img->ces[i]->fromC = False;
735 vg_assert(is_sane_CEnt("get_slowcase-case-1", img, i));
736 vg_assert(img->ces_used == ces_used_at_entry + 1);
737 } else {
738 SizeT len = tinfl_decompress_mem_to_mem(
739 img->ces[i]->data, cslc->szD,
740 cbuf, cslc->szC,
741 TINFL_FLAG_USING_NON_WRAPPING_OUTPUT_BUF
742 | TINFL_FLAG_PARSE_ZLIB_HEADER);
743 vg_assert(len == cslc->szD); // sanity check on data, FIXME
744 vg_assert(cslc->szD == size);
745 img->ces[i]->used = cslc->szD;
746 img->ces[i]->off = cslc->offD;
747 img->ces[i]->fromC = True;
748 vg_assert(is_sane_CEnt("get_slowcase-case-3", img, i));
749 vg_assert(img->ces_used == ces_used_at_entry + 1);
751 vg_assert(img->ces_used == ces_used_at_entry + 1);
752 if (i > 0) {
753 move_CEnt_to_top(img, i);
754 i = 0;
756 vg_assert(is_in_CEnt(img->ces[i], off));
757 if (cbuf != NULL) {
758 ML_(dinfo_free)(cbuf);
760 return img->ces[i]->data[ off - img->ces[i]->off ];
763 // Cases (2) and (4)
764 /* All entries in use. Recycle the (ostensibly) LRU one. But try to find
765 a non-fromC entry to recycle, though, since discarding and reloading
766 fromC entries is very expensive. The result is that -- unless all
767 CACHE_N_ENTRIES wind up being used by decompressed slices, which is
768 highly unlikely -- we'll wind up keeping all the decompressed data in
769 the cache for its entire remaining life. We could probably do better
770 but it would make the cache management even more complex. */
771 vg_assert(img->ces_used == CACHE_N_ENTRIES);
773 // Select entry to recycle.
774 for (i = CACHE_N_ENTRIES-1; i > 0; i--) {
775 if (!img->ces[i]->fromC)
776 break;
778 vg_assert(i >= 0 && i < CACHE_N_ENTRIES);
780 realloc_CEnt(img, i, size, /*fromC?*/cslc != NULL);
781 img->ces[i]->size = size;
782 img->ces[i]->used = 0;
783 if (cslc == NULL) {
784 set_CEnt(img, i, off);
785 img->ces[i]->fromC = False;
786 vg_assert(is_sane_CEnt("get_slowcase-case-2", img, i));
787 } else {
788 SizeT len = tinfl_decompress_mem_to_mem(
789 img->ces[i]->data, cslc->szD,
790 cbuf, cslc->szC,
791 TINFL_FLAG_USING_NON_WRAPPING_OUTPUT_BUF
792 | TINFL_FLAG_PARSE_ZLIB_HEADER);
793 vg_assert(len == size);
794 img->ces[i]->used = size;
795 img->ces[i]->off = cslc->offD;
796 img->ces[i]->fromC = True;
797 vg_assert(is_sane_CEnt("get_slowcase-case-4", img, i));
799 vg_assert(img->ces_used == ces_used_at_entry);
800 if (i > 0) {
801 move_CEnt_to_top(img, i);
802 i = 0;
804 vg_assert(is_in_CEnt(img->ces[i], off));
805 if (cbuf != NULL) {
806 ML_(dinfo_free)(cbuf);
808 return img->ces[i]->data[ off - img->ces[i]->off ];
811 // This is called a lot, so do the usual fast/slow split stuff on it. */
812 static inline UChar get ( DiImage* img, DiOffT off )
814 /* Most likely case is, it's in the ces[0] position. */
815 /* ML_(img_from_local_file) requests a read for ces[0] when
816 creating the image. Hence slot zero is always non-NULL, so we
817 can skip this test. */
818 if (LIKELY(/* img->ces[0] != NULL && */
819 is_in_CEnt(img->ces[0], off))) {
820 return img->ces[0]->data[ off - img->ces[0]->off ];
822 /* Else we'll have to fish around for it. */
823 return get_slowcase(img, off);
826 /* Create an image from a file in the local filesystem. This is
827 relatively straightforward. */
828 DiImage* ML_(img_from_local_file)(const HChar* fullpath)
830 SysRes fd;
831 struct vg_stat stat_buf;
832 DiOffT size;
834 fd = VG_(open)(fullpath, VKI_O_RDONLY, 0);
835 if (sr_isError(fd))
836 return NULL;
838 if (VG_(fstat)(sr_Res(fd), &stat_buf) != 0) {
839 VG_(close)(sr_Res(fd));
840 return NULL;
843 size = stat_buf.size;
844 if (size == 0 || size == DiOffT_INVALID
845 || /* size is unrepresentable as a SizeT */
846 size != (DiOffT)(SizeT)(size)) {
847 VG_(close)(sr_Res(fd));
848 return NULL;
851 DiImage* img = ML_(dinfo_zalloc)("di.image.ML_iflf.1", sizeof(DiImage));
852 img->source.is_local = True;
853 img->source.fd = sr_Res(fd);
854 img->size = size;
855 img->real_size = size;
856 img->ces_used = 0;
857 img->source.name = ML_(dinfo_strdup)("di.image.ML_iflf.2", fullpath);
858 img->cslc = NULL;
859 img->cslc_size = 0;
860 img->cslc_used = 0;
861 /* img->ces is already zeroed out */
862 vg_assert(img->source.fd >= 0);
864 /* Force the zeroth entry to be the first chunk of the file.
865 That's likely to be the first part that's requested anyway, and
866 loading it at this point forcing img->cent[0] to always be
867 non-empty, thereby saving us an is-it-empty check on the fast
868 path in get(). */
869 UInt entNo = alloc_CEnt(img, CACHE_ENTRY_SIZE, False/*!fromC*/);
870 vg_assert(entNo == 0);
871 set_CEnt(img, 0, 0);
873 return img;
876 /* As above, but uses fd rather than filename */
877 DiImage* ML_(img_from_fd)(Int fd, const HChar* fullpath)
879 struct vg_stat stat_buf;
880 DiOffT size;
882 if (VG_(fstat)(fd, &stat_buf) != 0) {
883 return NULL;
886 size = stat_buf.size;
887 if (size == 0 || size == DiOffT_INVALID
888 || /* size is unrepresentable as a SizeT */
889 size != (DiOffT)(SizeT)(size)) {
890 return NULL;
893 DiImage* img = ML_(dinfo_zalloc)("di.image.ML_iflf.1", sizeof(DiImage));
894 img->source.is_local = True;
895 img->source.fd = fd;
896 img->size = size;
897 img->real_size = size;
898 img->ces_used = 0;
899 img->source.name = ML_(dinfo_strdup)("di.image.ML_iflf.2", fullpath);
900 img->cslc = NULL;
901 img->cslc_size = 0;
902 img->cslc_used = 0;
903 /* img->ces is already zeroed out */
904 vg_assert(img->source.fd >= 0);
906 /* Force the zeroth entry to be the first chunk of the file.
907 That's likely to be the first part that's requested anyway, and
908 loading it at this point forcing img->cent[0] to always be
909 non-empty, thereby saving us an is-it-empty check on the fast
910 path in get(). */
911 UInt entNo = alloc_CEnt(img, CACHE_ENTRY_SIZE, False/*!fromC*/);
912 vg_assert(entNo == 0);
913 set_CEnt(img, 0, 0);
915 return img;
920 /* Create an image from a file on a remote debuginfo server. This is
921 more complex. There are lots of ways in which it can fail. */
922 DiImage* ML_(img_from_di_server)(const HChar* filename,
923 const HChar* serverAddr)
925 if (filename == NULL || serverAddr == NULL)
926 return NULL;
928 /* The filename must be a plain filename -- no slashes at all. */
929 if (VG_(strchr)(filename, '/') != NULL)
930 return NULL;
932 /* Try to connect to the server. A side effect of this is to parse
933 and reject, if syntactically invalid, |serverAddr|. Reasons why
934 this could fail:
935 - serverAddr is not of the form d.d.d.d:d or d.d.d.d
936 - attempt to connect to that address:port failed
938 Int sd = VG_(connect_via_socket)(serverAddr);
939 if (sd < 0)
940 return NULL;
941 if (!set_blocking(sd))
942 return NULL;
943 Int one = 1;
944 Int sr = VG_(setsockopt)(sd, VKI_IPPROTO_TCP, VKI_TCP_NODELAY,
945 &one, sizeof(one));
946 vg_assert(sr == 0);
948 /* Ok, we got a connection. Ask it for version string, so as to be
949 reasonably sure we're talking to an instance of
950 auxprogs/valgrind-di-server and not to some other random program
951 that happens to be listening on that port. */
952 Frame* req = mk_Frame_noargs("VERS");
953 Frame* res = do_transaction(sd, req);
954 if (res == NULL)
955 goto fail; // do_transaction failed?!
956 UChar* vstr = NULL;
957 if (!parse_Frame_asciiz(res, "VEOK", &vstr))
958 goto fail; // unexpected response kind, or invalid ID string
959 vg_assert(vstr);
960 if (VG_(strcmp)("Valgrind Debuginfo Server, Version 1",
961 (const HChar*)vstr) != 0)
962 goto fail; // wrong version string
963 free_Frame(req);
964 free_Frame(res);
965 req = NULL;
966 res = NULL;
968 /* Server seems plausible. Present it with the name of the file we
969 want and see if it'll give us back a session ID for it. */
970 req = mk_Frame_asciiz("OPEN", filename);
971 res = do_transaction(sd, req);
972 if (res == NULL)
973 goto fail;
974 ULong session_id = 0, size = 0;
975 if (!parse_Frame_le64_le64(res, "OPOK", &session_id, &size))
976 goto fail;
977 free_Frame(req);
978 free_Frame(res);
979 req = NULL;
980 res = NULL;
982 /* We have a session ID. We're ready to roll. */
983 DiImage* img = ML_(dinfo_zalloc)("di.image.ML_ifds.1", sizeof(DiImage));
984 img->source.is_local = False;
985 img->source.fd = sd;
986 img->source.session_id = session_id;
987 img->size = size;
988 img->real_size = size;
989 img->ces_used = 0;
990 img->source.name = ML_(dinfo_zalloc)("di.image.ML_ifds.2",
991 20 + VG_(strlen)(filename)
992 + VG_(strlen)(serverAddr));
993 VG_(sprintf)(img->source.name, "%s at %s", filename, serverAddr);
994 img->cslc = NULL;
995 img->cslc_size = 0;
996 img->cslc_used = 0;
998 /* img->ces is already zeroed out */
999 vg_assert(img->source.fd >= 0);
1001 /* See comment on equivalent bit in ML_(img_from_local_file) for
1002 rationale. */
1003 UInt entNo = alloc_CEnt(img, CACHE_ENTRY_SIZE, False/*!fromC*/);
1004 vg_assert(entNo == 0);
1005 set_CEnt(img, 0, 0);
1007 return img;
1009 fail:
1010 free_Frame(req);
1011 if (res) {
1012 UChar* reason = NULL;
1013 if (parse_Frame_asciiz(res, "FAIL", &reason)) {
1014 // HACK: if it's just telling us that the file can't
1015 // be opened, don't print it, else we'll get flooded with
1016 // such complaints, one for each main object for which there
1017 // isn't a debuginfo file on the server.
1018 if (0 != VG_(strcmp)((const HChar*)reason, "OPEN: cannot open file"))
1019 VG_(umsg)("ML_(img_from_di_server): fail: %s\n", reason);
1020 } else {
1021 VG_(umsg)("ML_(img_from_di_server): fail: unknown reason\n");
1023 free_Frame(res);
1025 VG_(close)(sd);
1026 return NULL;
1029 DiOffT ML_(img_mark_compressed_part)(DiImage* img, DiOffT offset, SizeT szC,
1030 SizeT szD)
1032 DiOffT ret;
1033 vg_assert(img != NULL);
1034 vg_assert(offset + szC <= img->size);
1036 if (img->cslc_used == img->cslc_size) {
1037 img->cslc_size += COMPRESSED_SLICE_ARRAY_GROW_SIZE;
1038 img->cslc = ML_(dinfo_realloc)("di.image.ML_img_mark_compressed_part.1",
1039 img->cslc, img->cslc_size * sizeof(CSlc));
1042 ret = img->size;
1043 img->cslc[img->cslc_used].offC = offset;
1044 img->cslc[img->cslc_used].szC = szC;
1045 img->cslc[img->cslc_used].offD = img->size;
1046 img->cslc[img->cslc_used].szD = szD;
1047 img->size += szD;
1048 img->cslc_used++;
1049 return ret;
1052 void ML_(img_free)(DiImage* img)
1054 vg_assert(img != NULL);
1056 /* Free up the cache entries, ultimately |img| itself. */
1057 UInt i;
1058 vg_assert(img->ces_used <= CACHE_N_ENTRIES);
1059 for (i = 0; i < img->ces_used; i++) {
1060 ML_(dinfo_free)(img->ces[i]);
1062 /* Take the opportunity to sanity check the rest. */
1063 for (i = i; i < img->ces_used; i++) {
1064 vg_assert(img->ces[i] == NULL);
1066 ML_(dinfo_free)(img->source.name);
1067 ML_(dinfo_free)(img->cslc);
1068 ML_(dinfo_free)(img);
1071 void ML_(img_done)(DiImage* img)
1073 vg_assert(img != NULL);
1074 if (img->source.is_local) {
1075 /* Close the file; nothing else to do. */
1076 vg_assert(img->source.session_id == 0);
1077 VG_(close)(img->source.fd);
1078 } else {
1079 /* Close the socket. The server can detect this and will scrub
1080 the connection when it happens, so there's no need to tell it
1081 explicitly by sending it a "CLOSE" message, or any such. */
1082 vg_assert(img->source.session_id != 0);
1083 VG_(close)(img->source.fd);
1086 ML_(img_free)(img);
1091 DiOffT ML_(img_size)(const DiImage* img)
1093 vg_assert(img != NULL);
1094 return img->size;
1097 DiOffT ML_(img_real_size)(const DiImage* img)
1099 vg_assert(img != NULL);
1100 return img->real_size;
1103 inline Bool ML_(img_valid)(const DiImage* img, DiOffT offset, SizeT size)
1105 vg_assert(img != NULL);
1106 vg_assert(offset != DiOffT_INVALID);
1107 return img->size > 0 && offset + size <= (DiOffT)img->size;
1110 __attribute__((noinline))
1111 static void ensure_valid_failed (const DiImage* img, DiOffT offset, SizeT size,
1112 const HChar* caller)
1114 VG_(umsg)("Valgrind: debuginfo reader: ensure_valid failed:\n");
1115 VG_(umsg)("Valgrind: during call to %s\n", caller);
1116 VG_(umsg)("Valgrind: request for range [%llu, +%lu) exceeds\n",
1117 offset, size);
1118 VG_(umsg)("Valgrind: valid image size of %lu for image:\n",
1119 img->size);
1120 VG_(umsg)("Valgrind: \"%s\"\n", img->source.name);
1121 give_up__image_overrun();
1124 /* Check the given range is valid, and if not, shut down the system.
1125 An invalid range would imply that we're trying to read outside the
1126 image, which normally means the image is corrupted somehow, or the
1127 caller is buggy. Recovering is too complex, and we have
1128 probably-corrupt debuginfo, so just give up. */
1129 static void ensure_valid(const DiImage* img, DiOffT offset, SizeT size,
1130 const HChar* caller)
1132 if (LIKELY(ML_(img_valid)(img, offset, size)))
1133 return;
1134 else
1135 ensure_valid_failed(img, offset, size, caller);
1139 void ML_(img_get)(/*OUT*/void* dst,
1140 DiImage* img, DiOffT offset, SizeT size)
1142 vg_assert(img != NULL);
1143 vg_assert(size > 0);
1144 ensure_valid(img, offset, size, "ML_(img_get)");
1145 SizeT i;
1146 for (i = 0; i < size; i++) {
1147 ((UChar*)dst)[i] = get(img, offset + i);
1151 SizeT ML_(img_get_some)(/*OUT*/void* dst,
1152 DiImage* img, DiOffT offset, SizeT size)
1154 vg_assert(img != NULL);
1155 vg_assert(size > 0);
1156 ensure_valid(img, offset, size, "ML_(img_get_some)");
1157 UChar* dstU = (UChar*)dst;
1158 /* Use |get| in the normal way to get the first byte of the range.
1159 This guarantees to put the cache entry containing |offset| in
1160 position zero. */
1161 dstU[0] = get(img, offset);
1162 /* Now just read as many bytes as we can (or need) directly out of
1163 entry zero, without bothering to call |get| each time. */
1164 const CEnt* ce = img->ces[0];
1165 vg_assert(ce && ce->used >= 1);
1166 vg_assert(is_in_CEnt(ce, offset));
1167 SizeT nToCopy = size - 1;
1168 SizeT nAvail = (SizeT)(ce->used - (offset + 1 - ce->off));
1169 vg_assert(nAvail >= 0 && nAvail <= ce->used-1);
1170 if (nAvail < nToCopy) nToCopy = nAvail;
1171 VG_(memcpy)(&dstU[1], &ce->data[offset + 1 - ce->off], nToCopy);
1172 return nToCopy + 1;
1176 SizeT ML_(img_strlen)(DiImage* img, DiOffT off)
1178 ensure_valid(img, off, 1, "ML_(img_strlen)");
1179 SizeT i = 0;
1180 while (get(img, off + i) != 0) i++;
1181 return i;
1184 HChar* ML_(img_strdup)(DiImage* img, const HChar* cc, DiOffT offset)
1186 ensure_valid(img, offset, 1, "ML_(img_strdup)");
1187 SizeT len = ML_(img_strlen)(img, offset);
1188 HChar* res = ML_(dinfo_zalloc)(cc, len+1);
1189 SizeT i;
1190 for (i = 0; i < len; i++) {
1191 res[i] = get(img, offset+i);
1193 vg_assert(res[len] == 0);
1194 return res;
1197 Int ML_(img_strcmp)(DiImage* img, DiOffT off1, DiOffT off2)
1199 ensure_valid(img, off1, 1, "ML_(img_strcmp)(first arg)");
1200 ensure_valid(img, off2, 1, "ML_(img_strcmp)(second arg)");
1201 while (True) {
1202 UChar c1 = get(img, off1);
1203 UChar c2 = get(img, off2);
1204 if (c1 < c2) return -1;
1205 if (c1 > c2) return 1;
1206 if (c1 == 0) return 0;
1207 off1++; off2++;
1211 Int ML_(img_strcmp_c)(DiImage* img, DiOffT off1, const HChar* str2)
1213 ensure_valid(img, off1, 1, "ML_(img_strcmp_c)");
1214 while (True) {
1215 UChar c1 = get(img, off1);
1216 UChar c2 = *(const UChar*)str2;
1217 if (c1 < c2) return -1;
1218 if (c1 > c2) return 1;
1219 if (c1 == 0) return 0;
1220 off1++; str2++;
1224 UChar ML_(img_get_UChar)(DiImage* img, DiOffT offset)
1226 ensure_valid(img, offset, 1, "ML_(img_get_UChar)");
1227 return get(img, offset);
1230 UShort ML_(img_get_UShort)(DiImage* img, DiOffT offset)
1232 UShort r;
1233 ML_(img_get)(&r, img, offset, sizeof(r));
1234 return r;
1237 UInt ML_(img_get_UInt)(DiImage* img, DiOffT offset)
1239 UInt r;
1240 ML_(img_get)(&r, img, offset, sizeof(r));
1241 return r;
1244 ULong ML_(img_get_ULong)(DiImage* img, DiOffT offset)
1246 ULong r;
1247 ML_(img_get)(&r, img, offset, sizeof(r));
1248 return r;
1253 * This routine for calculating the CRC for a separate debug file
1254 * is GPLed code borrowed from GNU binutils.
1256 UInt ML_(img_calc_gnu_debuglink_crc32)(DiImage* img)
1258 static const UInt crc32_table[256] =
1260 0x00000000, 0x77073096, 0xee0e612c, 0x990951ba, 0x076dc419,
1261 0x706af48f, 0xe963a535, 0x9e6495a3, 0x0edb8832, 0x79dcb8a4,
1262 0xe0d5e91e, 0x97d2d988, 0x09b64c2b, 0x7eb17cbd, 0xe7b82d07,
1263 0x90bf1d91, 0x1db71064, 0x6ab020f2, 0xf3b97148, 0x84be41de,
1264 0x1adad47d, 0x6ddde4eb, 0xf4d4b551, 0x83d385c7, 0x136c9856,
1265 0x646ba8c0, 0xfd62f97a, 0x8a65c9ec, 0x14015c4f, 0x63066cd9,
1266 0xfa0f3d63, 0x8d080df5, 0x3b6e20c8, 0x4c69105e, 0xd56041e4,
1267 0xa2677172, 0x3c03e4d1, 0x4b04d447, 0xd20d85fd, 0xa50ab56b,
1268 0x35b5a8fa, 0x42b2986c, 0xdbbbc9d6, 0xacbcf940, 0x32d86ce3,
1269 0x45df5c75, 0xdcd60dcf, 0xabd13d59, 0x26d930ac, 0x51de003a,
1270 0xc8d75180, 0xbfd06116, 0x21b4f4b5, 0x56b3c423, 0xcfba9599,
1271 0xb8bda50f, 0x2802b89e, 0x5f058808, 0xc60cd9b2, 0xb10be924,
1272 0x2f6f7c87, 0x58684c11, 0xc1611dab, 0xb6662d3d, 0x76dc4190,
1273 0x01db7106, 0x98d220bc, 0xefd5102a, 0x71b18589, 0x06b6b51f,
1274 0x9fbfe4a5, 0xe8b8d433, 0x7807c9a2, 0x0f00f934, 0x9609a88e,
1275 0xe10e9818, 0x7f6a0dbb, 0x086d3d2d, 0x91646c97, 0xe6635c01,
1276 0x6b6b51f4, 0x1c6c6162, 0x856530d8, 0xf262004e, 0x6c0695ed,
1277 0x1b01a57b, 0x8208f4c1, 0xf50fc457, 0x65b0d9c6, 0x12b7e950,
1278 0x8bbeb8ea, 0xfcb9887c, 0x62dd1ddf, 0x15da2d49, 0x8cd37cf3,
1279 0xfbd44c65, 0x4db26158, 0x3ab551ce, 0xa3bc0074, 0xd4bb30e2,
1280 0x4adfa541, 0x3dd895d7, 0xa4d1c46d, 0xd3d6f4fb, 0x4369e96a,
1281 0x346ed9fc, 0xad678846, 0xda60b8d0, 0x44042d73, 0x33031de5,
1282 0xaa0a4c5f, 0xdd0d7cc9, 0x5005713c, 0x270241aa, 0xbe0b1010,
1283 0xc90c2086, 0x5768b525, 0x206f85b3, 0xb966d409, 0xce61e49f,
1284 0x5edef90e, 0x29d9c998, 0xb0d09822, 0xc7d7a8b4, 0x59b33d17,
1285 0x2eb40d81, 0xb7bd5c3b, 0xc0ba6cad, 0xedb88320, 0x9abfb3b6,
1286 0x03b6e20c, 0x74b1d29a, 0xead54739, 0x9dd277af, 0x04db2615,
1287 0x73dc1683, 0xe3630b12, 0x94643b84, 0x0d6d6a3e, 0x7a6a5aa8,
1288 0xe40ecf0b, 0x9309ff9d, 0x0a00ae27, 0x7d079eb1, 0xf00f9344,
1289 0x8708a3d2, 0x1e01f268, 0x6906c2fe, 0xf762575d, 0x806567cb,
1290 0x196c3671, 0x6e6b06e7, 0xfed41b76, 0x89d32be0, 0x10da7a5a,
1291 0x67dd4acc, 0xf9b9df6f, 0x8ebeeff9, 0x17b7be43, 0x60b08ed5,
1292 0xd6d6a3e8, 0xa1d1937e, 0x38d8c2c4, 0x4fdff252, 0xd1bb67f1,
1293 0xa6bc5767, 0x3fb506dd, 0x48b2364b, 0xd80d2bda, 0xaf0a1b4c,
1294 0x36034af6, 0x41047a60, 0xdf60efc3, 0xa867df55, 0x316e8eef,
1295 0x4669be79, 0xcb61b38c, 0xbc66831a, 0x256fd2a0, 0x5268e236,
1296 0xcc0c7795, 0xbb0b4703, 0x220216b9, 0x5505262f, 0xc5ba3bbe,
1297 0xb2bd0b28, 0x2bb45a92, 0x5cb36a04, 0xc2d7ffa7, 0xb5d0cf31,
1298 0x2cd99e8b, 0x5bdeae1d, 0x9b64c2b0, 0xec63f226, 0x756aa39c,
1299 0x026d930a, 0x9c0906a9, 0xeb0e363f, 0x72076785, 0x05005713,
1300 0x95bf4a82, 0xe2b87a14, 0x7bb12bae, 0x0cb61b38, 0x92d28e9b,
1301 0xe5d5be0d, 0x7cdcefb7, 0x0bdbdf21, 0x86d3d2d4, 0xf1d4e242,
1302 0x68ddb3f8, 0x1fda836e, 0x81be16cd, 0xf6b9265b, 0x6fb077e1,
1303 0x18b74777, 0x88085ae6, 0xff0f6a70, 0x66063bca, 0x11010b5c,
1304 0x8f659eff, 0xf862ae69, 0x616bffd3, 0x166ccf45, 0xa00ae278,
1305 0xd70dd2ee, 0x4e048354, 0x3903b3c2, 0xa7672661, 0xd06016f7,
1306 0x4969474d, 0x3e6e77db, 0xaed16a4a, 0xd9d65adc, 0x40df0b66,
1307 0x37d83bf0, 0xa9bcae53, 0xdebb9ec5, 0x47b2cf7f, 0x30b5ffe9,
1308 0xbdbdf21c, 0xcabac28a, 0x53b39330, 0x24b4a3a6, 0xbad03605,
1309 0xcdd70693, 0x54de5729, 0x23d967bf, 0xb3667a2e, 0xc4614ab8,
1310 0x5d681b02, 0x2a6f2b94, 0xb40bbe37, 0xc30c8ea1, 0x5a05df1b,
1311 0x2d02ef8d
1314 vg_assert(img != NULL);
1316 /* If the image is local, calculate the CRC here directly. If it's
1317 remote, forward the request to the server. */
1318 if (img->source.is_local) {
1319 /* Work through the image in 1 KB chunks. */
1320 UInt crc = 0xFFFFFFFF;
1321 DiOffT img_szB = ML_(img_size)(img);
1322 DiOffT curr_off = 0;
1323 while (1) {
1324 vg_assert(curr_off <= img_szB);
1325 if (curr_off == img_szB) break;
1326 DiOffT avail = img_szB - curr_off;
1327 vg_assert(avail > 0 && avail <= img_szB);
1328 if (avail > 1024) avail = 1024;
1329 UChar buf[1024];
1330 SizeT nGot = ML_(img_get_some)(buf, img, curr_off, avail);
1331 vg_assert(nGot >= 1 && nGot <= avail);
1332 UInt i;
1333 for (i = 0; i < (UInt)nGot; i++)
1334 crc = crc32_table[(crc ^ buf[i]) & 0xff] ^ (crc >> 8);
1335 curr_off += nGot;
1337 return ~crc & 0xFFFFFFFF;
1338 } else {
1339 Frame* req = mk_Frame_noargs("CRC3");
1340 Frame* res = do_transaction(img->source.fd, req);
1341 if (!res) goto remote_crc_fail;
1342 ULong crc32 = 0;
1343 if (!parse_Frame_le64(res, "CROK", &crc32)) goto remote_crc_fail;
1344 if ((crc32 & ~0xFFFFFFFFULL) != 0) goto remote_crc_fail;
1345 free_Frame(req);
1346 free_Frame(res);
1347 return (UInt)crc32;
1348 remote_crc_fail:
1350 // XXXX common this up with the READ diagnostic cases
1351 if (res) {
1352 UChar* reason = NULL;
1353 if (parse_Frame_asciiz(res, "FAIL", &reason)) {
1354 VG_(umsg)("img_calc_gnu_debuglink_crc32: fail: "
1355 "%s\n", reason);
1356 } else {
1357 VG_(umsg)("img_calc_gnu_debuglink_crc32: fail: "
1358 "unknown reason\n");
1360 } else {
1361 VG_(umsg)("img_calc_gnu_debuglink_crc32: fail: "
1362 "server unexpectedly closed the connection\n");
1365 if (req) free_Frame(req);
1366 if (res) free_Frame(res);
1367 // FIXME: now what?
1368 give_up__comms_lost();
1369 /* NOTREACHED */
1370 vg_assert(0);
1372 /*NOTREACHED*/
1373 vg_assert(0);
1376 ////////////////////////////////////////////////////
1377 #include "minilzo-inl.c"
1379 /*--------------------------------------------------------------------*/
1380 /*--- end image.c ---*/
1381 /*--------------------------------------------------------------------*/