s390x: Re-implement STFLE as an extension
[valgrind.git] / coregrind / m_debuginfo / image.c
blob4ef01c5251582f585138caf699cf05e6ab94c0e2
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
586 // PJF not quite so simple - see
587 // https://bugs.kde.org/show_bug.cgi?id=480405
588 // if img->source.fd was opened with O_DIRECT the memory needs
589 // to be aligned and also the length
590 // that's a lot of hassle just to take a quick peek to see if
591 // is an ELF binary so just twiddle the flag before and after
592 // peeking.
593 // This doesn't seem to be a problem on FreeBSD. I haven't tested
594 // on macOS or Solaris, hence the conditional compilation
595 #if defined(VKI_O_DIRECT)
596 Int flags = VG_(fcntl)(img->source.fd, VKI_F_GETFL, 0);
597 if (flags & VKI_O_DIRECT) {
598 VG_(fcntl)(img->source.fd, VKI_F_SETFL, flags & ~VKI_O_DIRECT);
600 #endif
601 SysRes sr = VG_(pread)(img->source.fd, &ce->data[0], (Int)len, off);
602 #if defined(VKI_O_DIRECT)
603 if (flags & VKI_O_DIRECT) {
604 VG_(fcntl)(img->source.fd, VKI_F_SETFL, flags);
606 #endif
607 vg_assert(!sr_isError(sr));
608 } else {
609 // Not so simple: poke the server
610 vg_assert(img->source.session_id > 0);
611 Frame* req
612 = mk_Frame_le64_le64_le64("READ", img->source.session_id, off, len);
613 Frame* res = do_transaction(img->source.fd, req);
614 free_Frame(req); req = NULL;
615 if (!res) goto server_fail;
616 ULong rx_session_id = 0, rx_off = 0, rx_len = 0, rx_zdata_len = 0;
617 UChar* rx_data = NULL;
618 /* Pretty confusing. rx_sessionid, rx_off and rx_len are copies
619 of the values that we requested in the READ frame just above,
620 so we can be sure that the server is responding to the right
621 request. It just copies them from the request into the
622 response. rx_data is the actual data, and rx_zdata_len is
623 its compressed length. Hence rx_len must equal len, but
624 rx_zdata_len can be different -- smaller, hopefully.. */
625 if (!parse_Frame_le64_le64_le64_bytes
626 (res, "RDOK", &rx_session_id, &rx_off,
627 &rx_len, &rx_data, &rx_zdata_len))
628 goto server_fail;
629 if (rx_session_id != img->source.session_id
630 || rx_off != off || rx_len != len || rx_data == NULL)
631 goto server_fail;
633 //VG_(memcpy)(&ce->data[0], rx_data, len);
634 // Decompress into the destination buffer
635 // Tell the lib the max number of output bytes it can write.
636 // After the call, this holds the number of bytes actually written,
637 // and it's an error if it is different.
638 lzo_uint out_len = len;
639 Int lzo_rc = lzo1x_decompress_safe(rx_data, rx_zdata_len,
640 &ce->data[0], &out_len,
641 NULL);
642 Bool ok = lzo_rc == LZO_E_OK && out_len == len;
643 if (!ok) goto server_fail;
645 free_Frame(res); res = NULL;
646 goto end_of_else_clause;
647 server_fail:
648 /* The server screwed up somehow. Now what? */
649 if (res) {
650 UChar* reason = NULL;
651 if (parse_Frame_asciiz(res, "FAIL", &reason)) {
652 VG_(umsg)("set_CEnt (reading data from DI server): fail: "
653 "%s\n", reason);
654 } else {
655 VG_(umsg)("set_CEnt (reading data from DI server): fail: "
656 "unknown reason\n");
658 free_Frame(res); res = NULL;
659 } else {
660 VG_(umsg)("set_CEnt (reading data from DI server): fail: "
661 "server unexpectedly closed the connection\n");
663 give_up__comms_lost();
664 /* NOTREACHED */
665 vg_assert(0);
666 end_of_else_clause:
670 ce->off = off;
671 ce->used = len;
672 ce->fromC = False;
673 vg_assert(ce == img->ces[entNo]);
674 vg_assert(is_sane_CEnt("set_CEnt", img, entNo));
677 __attribute__((noinline))
678 static UChar get_slowcase ( DiImage* img, DiOffT off )
680 /* Stay sane .. */
681 vg_assert(off < img->size);
682 vg_assert(img->ces_used <= CACHE_N_ENTRIES);
683 UInt i;
684 /* Start the search at entry 1, since the fast-case function
685 checked slot zero already. */
686 for (i = 1; i < img->ces_used; i++) {
687 vg_assert(img->ces[i]);
688 if (is_in_CEnt(img->ces[i], off))
689 break;
691 vg_assert(i >= 1);
693 if (LIKELY(i < img->ces_used)) {
694 // Found it. Move to the top and stop.
695 move_CEnt_to_top(img, i);
696 vg_assert(is_in_CEnt(img->ces[0], off));
697 return img->ces[0]->data[ off - img->ces[0]->off ];
700 vg_assert(i <= img->ces_used);
702 // It's not in any entry. Either allocate a new one or recycle the LRU
703 // one. This is where the presence of compressed sections makes things
704 // tricky. There are 4 cases to consider:
706 // (1) not from a compressed slice, we can allocate a new entry
707 // (2) not from a compressed slice, we have to recycle the LRU entry
708 // (3) from a compressed slice, we can allocate a new entry
709 // (4) from a compressed slice, we have to recycle the LRU entry
711 // Cases (3) and (4) are complex because we will have to call
712 // ML_(img_get_some) to get the compressed data. But this function is
713 // reachable from ML_(img_get_some), so we may re-enter get_slowcase a
714 // second time as a result. Given that the compressed data will be cause
715 // only cases (1) and (2) to happen, this guarantees no infinite recursion.
716 // It does however mean that we can't carry (in this function invokation)
717 // any local copies of the overall cache state across the ML_(img_get_some)
718 // call, since it may become invalidated by the recursive call to
719 // get_slowcase.
721 // First of all, see if it is in a compressed slice, and if so, pull the
722 // compressed data into an intermediate buffer. Given the preceding
723 // comment, this is a safe place to do it, since we are not carrying any
724 // cache state here apart from the knowledge that the requested offset is
725 // not in the cache at all, and the recursive call won't change that fact.
727 CSlc* cslc = find_cslc(img, off);
728 UChar* cbuf = NULL;
729 if (cslc != NULL) {
730 SizeT len = 0;
731 cbuf = ML_(dinfo_zalloc)("di.image.get_slowcase.cbuf-1", cslc->szC);
732 // get compressed data
733 while (len < cslc->szC)
734 len += ML_(img_get_some)(cbuf + len, img, cslc->offC + len,
735 cslc->szC - len);
738 // Now we can do what we like.
739 vg_assert((cslc == NULL && cbuf == NULL) || (cslc != NULL && cbuf != NULL));
741 // Note, we can't capture this earlier, for exactly the reasons detailed
742 // above.
743 UInt ces_used_at_entry = img->ces_used;
745 // This is the size of the CEnt that we want to have after allocation or
746 // recycling.
747 SizeT size = (cslc == NULL) ? CACHE_ENTRY_SIZE : cslc->szD;
749 // Cases (1) and (3)
750 if (img->ces_used < CACHE_N_ENTRIES) {
751 /* Allocate a new cache entry, and fill it in. */
752 i = alloc_CEnt(img, size, /*fromC?*/cslc != NULL);
753 if (cslc == NULL) {
754 set_CEnt(img, i, off);
755 img->ces[i]->fromC = False;
756 vg_assert(is_sane_CEnt("get_slowcase-case-1", img, i));
757 vg_assert(img->ces_used == ces_used_at_entry + 1);
758 } else {
759 SizeT len = tinfl_decompress_mem_to_mem(
760 img->ces[i]->data, cslc->szD,
761 cbuf, cslc->szC,
762 TINFL_FLAG_USING_NON_WRAPPING_OUTPUT_BUF
763 | TINFL_FLAG_PARSE_ZLIB_HEADER);
764 vg_assert(len == cslc->szD); // sanity check on data, FIXME
765 vg_assert(cslc->szD == size);
766 img->ces[i]->used = cslc->szD;
767 img->ces[i]->off = cslc->offD;
768 img->ces[i]->fromC = True;
769 vg_assert(is_sane_CEnt("get_slowcase-case-3", img, i));
770 vg_assert(img->ces_used == ces_used_at_entry + 1);
772 vg_assert(img->ces_used == ces_used_at_entry + 1);
773 if (i > 0) {
774 move_CEnt_to_top(img, i);
775 i = 0;
777 vg_assert(is_in_CEnt(img->ces[i], off));
778 if (cbuf != NULL) {
779 ML_(dinfo_free)(cbuf);
781 return img->ces[i]->data[ off - img->ces[i]->off ];
784 // Cases (2) and (4)
785 /* All entries in use. Recycle the (ostensibly) LRU one. But try to find
786 a non-fromC entry to recycle, though, since discarding and reloading
787 fromC entries is very expensive. The result is that -- unless all
788 CACHE_N_ENTRIES wind up being used by decompressed slices, which is
789 highly unlikely -- we'll wind up keeping all the decompressed data in
790 the cache for its entire remaining life. We could probably do better
791 but it would make the cache management even more complex. */
792 vg_assert(img->ces_used == CACHE_N_ENTRIES);
794 // Select entry to recycle.
795 for (i = CACHE_N_ENTRIES-1; i > 0; i--) {
796 if (!img->ces[i]->fromC)
797 break;
799 vg_assert(i < CACHE_N_ENTRIES);
801 realloc_CEnt(img, i, size, /*fromC?*/cslc != NULL);
802 img->ces[i]->size = size;
803 img->ces[i]->used = 0;
804 if (cslc == NULL) {
805 set_CEnt(img, i, off);
806 img->ces[i]->fromC = False;
807 vg_assert(is_sane_CEnt("get_slowcase-case-2", img, i));
808 } else {
809 SizeT len = tinfl_decompress_mem_to_mem(
810 img->ces[i]->data, cslc->szD,
811 cbuf, cslc->szC,
812 TINFL_FLAG_USING_NON_WRAPPING_OUTPUT_BUF
813 | TINFL_FLAG_PARSE_ZLIB_HEADER);
814 vg_assert(len == size);
815 img->ces[i]->used = size;
816 img->ces[i]->off = cslc->offD;
817 img->ces[i]->fromC = True;
818 vg_assert(is_sane_CEnt("get_slowcase-case-4", img, i));
820 vg_assert(img->ces_used == ces_used_at_entry);
821 if (i > 0) {
822 move_CEnt_to_top(img, i);
823 i = 0;
825 vg_assert(is_in_CEnt(img->ces[i], off));
826 if (cbuf != NULL) {
827 ML_(dinfo_free)(cbuf);
829 return img->ces[i]->data[ off - img->ces[i]->off ];
832 // This is called a lot, so do the usual fast/slow split stuff on it. */
833 static inline UChar get ( DiImage* img, DiOffT off )
835 /* Most likely case is, it's in the ces[0] position. */
836 /* ML_(img_from_local_file) requests a read for ces[0] when
837 creating the image. Hence slot zero is always non-NULL, so we
838 can skip this test. */
839 if (LIKELY(/* img->ces[0] != NULL && */
840 is_in_CEnt(img->ces[0], off))) {
841 return img->ces[0]->data[ off - img->ces[0]->off ];
843 /* Else we'll have to fish around for it. */
844 return get_slowcase(img, off);
847 /* Create an image from a file in the local filesystem. This is
848 relatively straightforward. */
849 DiImage* ML_(img_from_local_file)(const HChar* fullpath)
851 SysRes fd;
852 struct vg_stat stat_buf;
853 DiOffT size;
855 fd = VG_(open)(fullpath, VKI_O_RDONLY, 0);
856 if (sr_isError(fd))
857 return NULL;
859 if (VG_(fstat)(sr_Res(fd), &stat_buf) != 0) {
860 VG_(close)(sr_Res(fd));
861 return NULL;
864 size = stat_buf.size;
865 if (size == 0 || size == DiOffT_INVALID
866 || /* size is unrepresentable as a SizeT */
867 size != (DiOffT)(SizeT)(size)) {
868 VG_(close)(sr_Res(fd));
869 return NULL;
872 DiImage* img = ML_(dinfo_zalloc)("di.image.ML_iflf.1", sizeof(DiImage));
873 img->source.is_local = True;
874 img->source.fd = sr_Res(fd);
875 img->size = size;
876 img->real_size = size;
877 img->ces_used = 0;
878 img->source.name = ML_(dinfo_strdup)("di.image.ML_iflf.2", fullpath);
879 img->cslc = NULL;
880 img->cslc_size = 0;
881 img->cslc_used = 0;
882 /* img->ces is already zeroed out */
883 vg_assert(img->source.fd >= 0);
885 /* Force the zeroth entry to be the first chunk of the file.
886 That's likely to be the first part that's requested anyway, and
887 loading it at this point forcing img->cent[0] to always be
888 non-empty, thereby saving us an is-it-empty check on the fast
889 path in get(). */
890 UInt entNo = alloc_CEnt(img, CACHE_ENTRY_SIZE, False/*!fromC*/);
891 vg_assert(entNo == 0);
892 set_CEnt(img, 0, 0);
894 return img;
897 /* As above, but uses fd rather than filename */
898 DiImage* ML_(img_from_fd)(Int fd, const HChar* fullpath)
900 struct vg_stat stat_buf;
901 DiOffT size;
903 if (VG_(fstat)(fd, &stat_buf) != 0) {
904 return NULL;
907 size = stat_buf.size;
908 if (size == 0 || size == DiOffT_INVALID
909 || /* size is unrepresentable as a SizeT */
910 size != (DiOffT)(SizeT)(size)) {
911 return NULL;
914 DiImage* img = ML_(dinfo_zalloc)("di.image.ML_iflf.1", sizeof(DiImage));
915 img->source.is_local = True;
916 img->source.fd = fd;
917 img->size = size;
918 img->real_size = size;
919 img->ces_used = 0;
920 img->source.name = ML_(dinfo_strdup)("di.image.ML_iflf.2", fullpath);
921 img->cslc = NULL;
922 img->cslc_size = 0;
923 img->cslc_used = 0;
924 /* img->ces is already zeroed out */
925 vg_assert(img->source.fd >= 0);
927 /* Force the zeroth entry to be the first chunk of the file.
928 That's likely to be the first part that's requested anyway, and
929 loading it at this point forcing img->cent[0] to always be
930 non-empty, thereby saving us an is-it-empty check on the fast
931 path in get(). */
932 UInt entNo = alloc_CEnt(img, CACHE_ENTRY_SIZE, False/*!fromC*/);
933 vg_assert(entNo == 0);
934 set_CEnt(img, 0, 0);
936 return img;
941 /* Create an image from a file on a remote debuginfo server. This is
942 more complex. There are lots of ways in which it can fail. */
943 DiImage* ML_(img_from_di_server)(const HChar* filename,
944 const HChar* serverAddr)
946 if (filename == NULL || serverAddr == NULL)
947 return NULL;
949 /* The filename must be a plain filename -- no slashes at all. */
950 if (VG_(strchr)(filename, '/') != NULL)
951 return NULL;
953 /* Try to connect to the server. A side effect of this is to parse
954 and reject, if syntactically invalid, |serverAddr|. Reasons why
955 this could fail:
956 - serverAddr is not of the form d.d.d.d:d or d.d.d.d
957 - attempt to connect to that address:port failed
959 Int sd = VG_(connect_via_socket)(serverAddr);
960 if (sd < 0)
961 return NULL;
962 if (!set_blocking(sd))
963 return NULL;
964 Int one = 1;
965 Int sr = VG_(setsockopt)(sd, VKI_IPPROTO_TCP, VKI_TCP_NODELAY,
966 &one, sizeof(one));
967 vg_assert(sr == 0);
969 /* Ok, we got a connection. Ask it for version string, so as to be
970 reasonably sure we're talking to an instance of
971 auxprogs/valgrind-di-server and not to some other random program
972 that happens to be listening on that port. */
973 Frame* req = mk_Frame_noargs("VERS");
974 Frame* res = do_transaction(sd, req);
975 if (res == NULL)
976 goto fail; // do_transaction failed?!
977 UChar* vstr = NULL;
978 if (!parse_Frame_asciiz(res, "VEOK", &vstr))
979 goto fail; // unexpected response kind, or invalid ID string
980 vg_assert(vstr);
981 if (VG_(strcmp)("Valgrind Debuginfo Server, Version 1",
982 (const HChar*)vstr) != 0)
983 goto fail; // wrong version string
984 free_Frame(req);
985 free_Frame(res);
986 req = NULL;
987 res = NULL;
989 /* Server seems plausible. Present it with the name of the file we
990 want and see if it'll give us back a session ID for it. */
991 req = mk_Frame_asciiz("OPEN", filename);
992 res = do_transaction(sd, req);
993 if (res == NULL)
994 goto fail;
995 ULong session_id = 0, size = 0;
996 if (!parse_Frame_le64_le64(res, "OPOK", &session_id, &size))
997 goto fail;
998 free_Frame(req);
999 free_Frame(res);
1000 req = NULL;
1001 res = NULL;
1003 /* We have a session ID. We're ready to roll. */
1004 DiImage* img = ML_(dinfo_zalloc)("di.image.ML_ifds.1", sizeof(DiImage));
1005 img->source.is_local = False;
1006 img->source.fd = sd;
1007 img->source.session_id = session_id;
1008 img->size = size;
1009 img->real_size = size;
1010 img->ces_used = 0;
1011 img->source.name = ML_(dinfo_zalloc)("di.image.ML_ifds.2",
1012 20 + VG_(strlen)(filename)
1013 + VG_(strlen)(serverAddr));
1014 VG_(sprintf)(img->source.name, "%s at %s", filename, serverAddr);
1015 img->cslc = NULL;
1016 img->cslc_size = 0;
1017 img->cslc_used = 0;
1019 /* img->ces is already zeroed out */
1020 vg_assert(img->source.fd >= 0);
1022 /* See comment on equivalent bit in ML_(img_from_local_file) for
1023 rationale. */
1024 UInt entNo = alloc_CEnt(img, CACHE_ENTRY_SIZE, False/*!fromC*/);
1025 vg_assert(entNo == 0);
1026 set_CEnt(img, 0, 0);
1028 return img;
1030 fail:
1031 free_Frame(req);
1032 if (res) {
1033 UChar* reason = NULL;
1034 if (parse_Frame_asciiz(res, "FAIL", &reason)) {
1035 // HACK: if it's just telling us that the file can't
1036 // be opened, don't print it, else we'll get flooded with
1037 // such complaints, one for each main object for which there
1038 // isn't a debuginfo file on the server.
1039 if (0 != VG_(strcmp)((const HChar*)reason, "OPEN: cannot open file"))
1040 VG_(umsg)("ML_(img_from_di_server): fail: %s\n", reason);
1041 } else {
1042 VG_(umsg)("ML_(img_from_di_server): fail: unknown reason\n");
1044 free_Frame(res);
1046 VG_(close)(sd);
1047 return NULL;
1050 DiOffT ML_(img_mark_compressed_part)(DiImage* img, DiOffT offset, SizeT szC,
1051 SizeT szD)
1053 DiOffT ret;
1054 vg_assert(img != NULL);
1055 vg_assert(offset + szC <= img->size);
1057 if (img->cslc_used == img->cslc_size) {
1058 img->cslc_size += COMPRESSED_SLICE_ARRAY_GROW_SIZE;
1059 img->cslc = ML_(dinfo_realloc)("di.image.ML_img_mark_compressed_part.1",
1060 img->cslc, img->cslc_size * sizeof(CSlc));
1063 ret = img->size;
1064 img->cslc[img->cslc_used].offC = offset;
1065 img->cslc[img->cslc_used].szC = szC;
1066 img->cslc[img->cslc_used].offD = img->size;
1067 img->cslc[img->cslc_used].szD = szD;
1068 img->size += szD;
1069 img->cslc_used++;
1070 return ret;
1073 void ML_(img_free)(DiImage* img)
1075 vg_assert(img != NULL);
1077 /* Free up the cache entries, ultimately |img| itself. */
1078 UInt i;
1079 vg_assert(img->ces_used <= CACHE_N_ENTRIES);
1080 for (i = 0; i < img->ces_used; i++) {
1081 ML_(dinfo_free)(img->ces[i]);
1083 /* Take the opportunity to sanity check the rest. */
1084 for (i = i; i < img->ces_used; i++) {
1085 vg_assert(img->ces[i] == NULL);
1087 ML_(dinfo_free)(img->source.name);
1088 ML_(dinfo_free)(img->cslc);
1089 ML_(dinfo_free)(img);
1092 void ML_(img_done)(DiImage* img)
1094 vg_assert(img != NULL);
1095 if (img->source.is_local) {
1096 /* Close the file; nothing else to do. */
1097 vg_assert(img->source.session_id == 0);
1098 VG_(close)(img->source.fd);
1099 } else {
1100 /* Close the socket. The server can detect this and will scrub
1101 the connection when it happens, so there's no need to tell it
1102 explicitly by sending it a "CLOSE" message, or any such. */
1103 vg_assert(img->source.session_id != 0);
1104 VG_(close)(img->source.fd);
1107 ML_(img_free)(img);
1112 DiOffT ML_(img_size)(const DiImage* img)
1114 vg_assert(img != NULL);
1115 return img->size;
1118 DiOffT ML_(img_real_size)(const DiImage* img)
1120 vg_assert(img != NULL);
1121 return img->real_size;
1124 inline Bool ML_(img_valid)(const DiImage* img, DiOffT offset, SizeT size)
1126 vg_assert(img != NULL);
1127 vg_assert(offset != DiOffT_INVALID);
1128 return img->size > 0 && offset + size <= (DiOffT)img->size;
1131 __attribute__((noinline))
1132 static void ensure_valid_failed (const DiImage* img, DiOffT offset, SizeT size,
1133 const HChar* caller)
1135 VG_(umsg)("Valgrind: debuginfo reader: ensure_valid failed:\n");
1136 VG_(umsg)("Valgrind: during call to %s\n", caller);
1137 VG_(umsg)("Valgrind: request for range [%llu, +%lu) exceeds\n",
1138 offset, size);
1139 VG_(umsg)("Valgrind: valid image size of %lu for image:\n",
1140 img->size);
1141 VG_(umsg)("Valgrind: \"%s\"\n", img->source.name);
1142 give_up__image_overrun();
1145 /* Check the given range is valid, and if not, shut down the system.
1146 An invalid range would imply that we're trying to read outside the
1147 image, which normally means the image is corrupted somehow, or the
1148 caller is buggy. Recovering is too complex, and we have
1149 probably-corrupt debuginfo, so just give up. */
1150 static void ensure_valid(const DiImage* img, DiOffT offset, SizeT size,
1151 const HChar* caller)
1153 if (LIKELY(ML_(img_valid)(img, offset, size)))
1154 return;
1155 else
1156 ensure_valid_failed(img, offset, size, caller);
1160 void ML_(img_get)(/*OUT*/void* dst,
1161 DiImage* img, DiOffT offset, SizeT size)
1163 vg_assert(img != NULL);
1164 vg_assert(size > 0);
1165 ensure_valid(img, offset, size, "ML_(img_get)");
1166 SizeT i;
1167 for (i = 0; i < size; i++) {
1168 ((UChar*)dst)[i] = get(img, offset + i);
1172 SizeT ML_(img_get_some)(/*OUT*/void* dst,
1173 DiImage* img, DiOffT offset, SizeT size)
1175 vg_assert(img != NULL);
1176 vg_assert(size > 0);
1177 ensure_valid(img, offset, size, "ML_(img_get_some)");
1178 UChar* dstU = (UChar*)dst;
1179 /* Use |get| in the normal way to get the first byte of the range.
1180 This guarantees to put the cache entry containing |offset| in
1181 position zero. */
1182 dstU[0] = get(img, offset);
1183 /* Now just read as many bytes as we can (or need) directly out of
1184 entry zero, without bothering to call |get| each time. */
1185 const CEnt* ce = img->ces[0];
1186 vg_assert(ce && ce->used >= 1);
1187 vg_assert(is_in_CEnt(ce, offset));
1188 SizeT nToCopy = size - 1;
1189 SizeT nAvail = (SizeT)(ce->used - (offset + 1 - ce->off));
1190 vg_assert(nAvail <= ce->used-1);
1191 if (nAvail < nToCopy) nToCopy = nAvail;
1192 VG_(memcpy)(&dstU[1], &ce->data[offset + 1 - ce->off], nToCopy);
1193 return nToCopy + 1;
1197 SizeT ML_(img_strlen)(DiImage* img, DiOffT off)
1199 ensure_valid(img, off, 1, "ML_(img_strlen)");
1200 SizeT i = 0;
1201 while (get(img, off + i) != 0) i++;
1202 return i;
1205 HChar* ML_(img_strdup)(DiImage* img, const HChar* cc, DiOffT offset)
1207 ensure_valid(img, offset, 1, "ML_(img_strdup)");
1208 SizeT len = ML_(img_strlen)(img, offset);
1209 HChar* res = ML_(dinfo_zalloc)(cc, len+1);
1210 SizeT i;
1211 for (i = 0; i < len; i++) {
1212 res[i] = get(img, offset+i);
1214 vg_assert(res[len] == 0);
1215 return res;
1218 Int ML_(img_strcmp)(DiImage* img, DiOffT off1, DiOffT off2)
1220 ensure_valid(img, off1, 1, "ML_(img_strcmp)(first arg)");
1221 ensure_valid(img, off2, 1, "ML_(img_strcmp)(second arg)");
1222 while (True) {
1223 UChar c1 = get(img, off1);
1224 UChar c2 = get(img, off2);
1225 if (c1 < c2) return -1;
1226 if (c1 > c2) return 1;
1227 if (c1 == 0) return 0;
1228 off1++; off2++;
1232 Int ML_(img_strcmp_c)(DiImage* img, DiOffT off1, const HChar* str2)
1234 ensure_valid(img, off1, 1, "ML_(img_strcmp_c)");
1235 while (True) {
1236 UChar c1 = get(img, off1);
1237 UChar c2 = *(const UChar*)str2;
1238 if (c1 < c2) return -1;
1239 if (c1 > c2) return 1;
1240 if (c1 == 0) return 0;
1241 off1++; str2++;
1245 Int ML_(img_strcmp_n)(DiImage* img, DiOffT off1, const HChar* str2, Word n)
1247 ensure_valid(img, off1, 1, "ML_(img_strcmp_c)");
1248 while (n) {
1249 UChar c1 = get(img, off1);
1250 UChar c2 = *(const UChar*)str2;
1251 if (c1 < c2) return -1;
1252 if (c1 > c2) return 1;
1253 if (c1 == 0) return 0;
1254 off1++; str2++; --n;
1256 return 0;
1259 UChar ML_(img_get_UChar)(DiImage* img, DiOffT offset)
1261 ensure_valid(img, offset, 1, "ML_(img_get_UChar)");
1262 return get(img, offset);
1265 UShort ML_(img_get_UShort)(DiImage* img, DiOffT offset)
1267 UShort r;
1268 ML_(img_get)(&r, img, offset, sizeof(r));
1269 return r;
1272 UInt ML_(img_get_UInt)(DiImage* img, DiOffT offset)
1274 UInt r;
1275 ML_(img_get)(&r, img, offset, sizeof(r));
1276 return r;
1279 ULong ML_(img_get_ULong)(DiImage* img, DiOffT offset)
1281 ULong r;
1282 ML_(img_get)(&r, img, offset, sizeof(r));
1283 return r;
1288 * This routine for calculating the CRC for a separate debug file
1289 * is GPLed code borrowed from GNU binutils.
1291 UInt ML_(img_calc_gnu_debuglink_crc32)(DiImage* img)
1293 static const UInt crc32_table[256] =
1295 0x00000000, 0x77073096, 0xee0e612c, 0x990951ba, 0x076dc419,
1296 0x706af48f, 0xe963a535, 0x9e6495a3, 0x0edb8832, 0x79dcb8a4,
1297 0xe0d5e91e, 0x97d2d988, 0x09b64c2b, 0x7eb17cbd, 0xe7b82d07,
1298 0x90bf1d91, 0x1db71064, 0x6ab020f2, 0xf3b97148, 0x84be41de,
1299 0x1adad47d, 0x6ddde4eb, 0xf4d4b551, 0x83d385c7, 0x136c9856,
1300 0x646ba8c0, 0xfd62f97a, 0x8a65c9ec, 0x14015c4f, 0x63066cd9,
1301 0xfa0f3d63, 0x8d080df5, 0x3b6e20c8, 0x4c69105e, 0xd56041e4,
1302 0xa2677172, 0x3c03e4d1, 0x4b04d447, 0xd20d85fd, 0xa50ab56b,
1303 0x35b5a8fa, 0x42b2986c, 0xdbbbc9d6, 0xacbcf940, 0x32d86ce3,
1304 0x45df5c75, 0xdcd60dcf, 0xabd13d59, 0x26d930ac, 0x51de003a,
1305 0xc8d75180, 0xbfd06116, 0x21b4f4b5, 0x56b3c423, 0xcfba9599,
1306 0xb8bda50f, 0x2802b89e, 0x5f058808, 0xc60cd9b2, 0xb10be924,
1307 0x2f6f7c87, 0x58684c11, 0xc1611dab, 0xb6662d3d, 0x76dc4190,
1308 0x01db7106, 0x98d220bc, 0xefd5102a, 0x71b18589, 0x06b6b51f,
1309 0x9fbfe4a5, 0xe8b8d433, 0x7807c9a2, 0x0f00f934, 0x9609a88e,
1310 0xe10e9818, 0x7f6a0dbb, 0x086d3d2d, 0x91646c97, 0xe6635c01,
1311 0x6b6b51f4, 0x1c6c6162, 0x856530d8, 0xf262004e, 0x6c0695ed,
1312 0x1b01a57b, 0x8208f4c1, 0xf50fc457, 0x65b0d9c6, 0x12b7e950,
1313 0x8bbeb8ea, 0xfcb9887c, 0x62dd1ddf, 0x15da2d49, 0x8cd37cf3,
1314 0xfbd44c65, 0x4db26158, 0x3ab551ce, 0xa3bc0074, 0xd4bb30e2,
1315 0x4adfa541, 0x3dd895d7, 0xa4d1c46d, 0xd3d6f4fb, 0x4369e96a,
1316 0x346ed9fc, 0xad678846, 0xda60b8d0, 0x44042d73, 0x33031de5,
1317 0xaa0a4c5f, 0xdd0d7cc9, 0x5005713c, 0x270241aa, 0xbe0b1010,
1318 0xc90c2086, 0x5768b525, 0x206f85b3, 0xb966d409, 0xce61e49f,
1319 0x5edef90e, 0x29d9c998, 0xb0d09822, 0xc7d7a8b4, 0x59b33d17,
1320 0x2eb40d81, 0xb7bd5c3b, 0xc0ba6cad, 0xedb88320, 0x9abfb3b6,
1321 0x03b6e20c, 0x74b1d29a, 0xead54739, 0x9dd277af, 0x04db2615,
1322 0x73dc1683, 0xe3630b12, 0x94643b84, 0x0d6d6a3e, 0x7a6a5aa8,
1323 0xe40ecf0b, 0x9309ff9d, 0x0a00ae27, 0x7d079eb1, 0xf00f9344,
1324 0x8708a3d2, 0x1e01f268, 0x6906c2fe, 0xf762575d, 0x806567cb,
1325 0x196c3671, 0x6e6b06e7, 0xfed41b76, 0x89d32be0, 0x10da7a5a,
1326 0x67dd4acc, 0xf9b9df6f, 0x8ebeeff9, 0x17b7be43, 0x60b08ed5,
1327 0xd6d6a3e8, 0xa1d1937e, 0x38d8c2c4, 0x4fdff252, 0xd1bb67f1,
1328 0xa6bc5767, 0x3fb506dd, 0x48b2364b, 0xd80d2bda, 0xaf0a1b4c,
1329 0x36034af6, 0x41047a60, 0xdf60efc3, 0xa867df55, 0x316e8eef,
1330 0x4669be79, 0xcb61b38c, 0xbc66831a, 0x256fd2a0, 0x5268e236,
1331 0xcc0c7795, 0xbb0b4703, 0x220216b9, 0x5505262f, 0xc5ba3bbe,
1332 0xb2bd0b28, 0x2bb45a92, 0x5cb36a04, 0xc2d7ffa7, 0xb5d0cf31,
1333 0x2cd99e8b, 0x5bdeae1d, 0x9b64c2b0, 0xec63f226, 0x756aa39c,
1334 0x026d930a, 0x9c0906a9, 0xeb0e363f, 0x72076785, 0x05005713,
1335 0x95bf4a82, 0xe2b87a14, 0x7bb12bae, 0x0cb61b38, 0x92d28e9b,
1336 0xe5d5be0d, 0x7cdcefb7, 0x0bdbdf21, 0x86d3d2d4, 0xf1d4e242,
1337 0x68ddb3f8, 0x1fda836e, 0x81be16cd, 0xf6b9265b, 0x6fb077e1,
1338 0x18b74777, 0x88085ae6, 0xff0f6a70, 0x66063bca, 0x11010b5c,
1339 0x8f659eff, 0xf862ae69, 0x616bffd3, 0x166ccf45, 0xa00ae278,
1340 0xd70dd2ee, 0x4e048354, 0x3903b3c2, 0xa7672661, 0xd06016f7,
1341 0x4969474d, 0x3e6e77db, 0xaed16a4a, 0xd9d65adc, 0x40df0b66,
1342 0x37d83bf0, 0xa9bcae53, 0xdebb9ec5, 0x47b2cf7f, 0x30b5ffe9,
1343 0xbdbdf21c, 0xcabac28a, 0x53b39330, 0x24b4a3a6, 0xbad03605,
1344 0xcdd70693, 0x54de5729, 0x23d967bf, 0xb3667a2e, 0xc4614ab8,
1345 0x5d681b02, 0x2a6f2b94, 0xb40bbe37, 0xc30c8ea1, 0x5a05df1b,
1346 0x2d02ef8d
1349 vg_assert(img != NULL);
1351 /* If the image is local, calculate the CRC here directly. If it's
1352 remote, forward the request to the server. */
1353 if (img->source.is_local) {
1354 /* Work through the image in 1 KB chunks. */
1355 UInt crc = 0xFFFFFFFF;
1356 DiOffT img_szB = ML_(img_size)(img);
1357 DiOffT curr_off = 0;
1358 while (1) {
1359 vg_assert(curr_off <= img_szB);
1360 if (curr_off == img_szB) break;
1361 DiOffT avail = img_szB - curr_off;
1362 vg_assert(avail > 0 && avail <= img_szB);
1363 if (avail > 1024) avail = 1024;
1364 UChar buf[1024];
1365 SizeT nGot = ML_(img_get_some)(buf, img, curr_off, avail);
1366 vg_assert(nGot >= 1 && nGot <= avail);
1367 UInt i;
1368 for (i = 0; i < (UInt)nGot; i++)
1369 crc = crc32_table[(crc ^ buf[i]) & 0xff] ^ (crc >> 8);
1370 curr_off += nGot;
1372 return ~crc & 0xFFFFFFFF;
1373 } else {
1374 Frame* req = mk_Frame_noargs("CRC3");
1375 Frame* res = do_transaction(img->source.fd, req);
1376 if (!res) goto remote_crc_fail;
1377 ULong crc32 = 0;
1378 if (!parse_Frame_le64(res, "CROK", &crc32)) goto remote_crc_fail;
1379 if ((crc32 & ~0xFFFFFFFFULL) != 0) goto remote_crc_fail;
1380 free_Frame(req);
1381 free_Frame(res);
1382 return (UInt)crc32;
1383 remote_crc_fail:
1385 // XXXX common this up with the READ diagnostic cases
1386 if (res) {
1387 UChar* reason = NULL;
1388 if (parse_Frame_asciiz(res, "FAIL", &reason)) {
1389 VG_(umsg)("img_calc_gnu_debuglink_crc32: fail: "
1390 "%s\n", reason);
1391 } else {
1392 VG_(umsg)("img_calc_gnu_debuglink_crc32: fail: "
1393 "unknown reason\n");
1395 } else {
1396 VG_(umsg)("img_calc_gnu_debuglink_crc32: fail: "
1397 "server unexpectedly closed the connection\n");
1400 if (req) free_Frame(req);
1401 if (res) free_Frame(res);
1402 // FIXME: now what?
1403 give_up__comms_lost();
1404 /* NOTREACHED */
1405 vg_assert(0);
1407 /*NOTREACHED*/
1408 vg_assert(0);
1411 ////////////////////////////////////////////////////
1412 #include "minilzo-inl.c"
1414 /*--------------------------------------------------------------------*/
1415 /*--- end image.c ---*/
1416 /*--------------------------------------------------------------------*/