1 /* -*- mode: C; c-basic-offset: 3; -*- */
3 /*--------------------------------------------------------------------*/
4 /*--- An abstraction that provides a file-reading mechanism. ---*/
6 /*--------------------------------------------------------------------*/
9 This file is part of Valgrind, a dynamic binary instrumentation
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 */
46 #define TINFL_HEADER_FILE_ONLY
49 /* These values (1024 entries of 8192 bytes each) gives a cache
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. */
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
69 /* Compressed slice */
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
79 /* Source for files */
82 // True: img is of local file. False: img is from a server.
84 // The fd for the local file, or sd for a remote server.
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.
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.
97 // The source -- how to get hold of the file we are reading
99 // Virtual size of the image = real size + size of uncompressed data
101 // Real size of image
103 // The number of entries used. 0 .. CACHE_N_ENTRIES
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
113 // Number of compressed slices used
115 // Size of cslc array
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
)
131 vg_assert(i
<= CACHE_N_ENTRIES
);
133 CEnt
* ce
= img
->ces
[i
];
134 if (!(ce
->used
<= ce
->size
)) goto fail
;
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
;
144 if (!(ce
->size
== CACHE_ENTRY_SIZE
)) goto fail
;
145 if (!(ce
->off
+ ce
->used
<= img
->real_size
)) goto fail
;
150 VG_(printf
)("is_sane_CEnt[%u]: fail: %s\n", i
, who
);
151 pp_CEnt("failing CEnt", ce
);
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
)
163 for (i
= 0; i
<= 3; i
++) {
164 dst
[i
] = (UChar
)(n
& 0xFF);
169 static UInt
read_UInt_le ( const UChar
* src
)
173 for (i
= 3; i
>= 0; i
--) {
180 static void write_ULong_le ( /*OUT*/UChar
* dst
, ULong n
)
183 for (i
= 0; i
<= 7; i
++) {
184 dst
[i
] = (UChar
)(n
& 0xFF);
189 static ULong
read_ULong_le ( const UChar
* src
)
193 for (i
= 7; i
>= 0; i
--) {
201 /* Set |sd| to be blocking. Returns True on success. */
202 static Bool
set_blocking ( int sd
)
205 res
= VG_(fcntl
)(sd
, VKI_F_GETFL
, 0/*ignored*/);
207 res
= VG_(fcntl
)(sd
, VKI_F_SETFL
, res
& ~VKI_O_NONBLOCK
);
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
215 static Int
my_read ( Int fd
, UChar
* buf
, Int len
)
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 */
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
233 static Int
my_write ( Int fd
, const UChar
* buf
, Int len
)
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 */
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)
253 "Valgrind: debuginfo reader: Lost communication with the remote\n");
255 "Valgrind: debuginfo server. I can't recover. Giving up. Sorry.\n");
261 static void give_up__image_overrun(void)
265 "Valgrind: debuginfo reader: Possibly corrupted debuginfo file.\n");
267 "Valgrind: I can't recover. Giving up. Sorry.\n");
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
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. */
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);
326 adler
= VG_(adler32
)(adler
, res
->data
, res
->n_data
);
328 if (adler
/*computed*/ != rd_adler
/*expected*/) return NULL
;
332 static void free_Frame ( Frame
* fr
)
334 vg_assert(fr
&& fr
->data
);
335 ML_(dinfo_free
)(fr
->data
);
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
));
344 f
->data
= ML_(dinfo_zalloc
)("di.mFn.2", f
->n_data
);
345 VG_(memcpy
)(&f
->data
[0], tag
, 4);
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
));
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
);
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);
376 static Bool
parse_Frame_le64 ( const Frame
* fr
, const HChar
* tag
,
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]);
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]);
401 static Bool
parse_Frame_asciiz ( const Frame
* fr
, const HChar
* tag
,
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. */
414 if (i
>= fr
->n_data
) break;
415 if (fr
->data
[i
] == 0) break;
418 vg_assert(i
<= fr
->n_data
);
419 if (i
== fr
->n_data
-1 && fr
->data
[i
] == 0) {
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);
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
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:
465 --> x-LO >= 0 && x-LO < LO+N-LO
466 --> x-LO >= 0 && 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
];
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
);
496 // szB can be arbitrary
498 vg_assert(szB
== CACHE_ENTRY_SIZE
);
500 UInt entNo
= 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
));
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",
518 offsetof(CEnt
, data
) + szB
);
521 /* Move the given entry to the top and slide those above it down by 1,
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];
531 vg_assert(entNo
> 1); // a.k.a. >= 2
532 CEnt
* tmp
= img
->ces
[entNo
];
533 img
->ces
[entNo
] = img
->ces
[entNo
-1];
535 img
->ces
[entNo
] = img
->ces
[entNo
-1];
538 img
->ces
[entNo
] = img
->ces
[entNo
-1];
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
549 static void set_CEnt ( const DiImage
* img
, UInt entNo
, DiOffT off
)
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
;
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. */
573 static UInt t_last
= 0;
574 static ULong nread
= 0;
575 UInt now
= VG_(read_millisecond_timer
)();
576 UInt delay
= now
- t_last
;
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
));
588 // Not so simple: poke the server
589 vg_assert(img
->source
.session_id
> 0);
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
))
608 if (rx_session_id
!= img
->source
.session_id
609 || rx_off
!= off
|| rx_len
!= len
|| rx_data
== NULL
)
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
,
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
;
627 /* The server screwed up somehow. Now what? */
629 UChar
* reason
= NULL
;
630 if (parse_Frame_asciiz(res
, "FAIL", &reason
)) {
631 VG_(umsg
)("set_CEnt (reading data from DI server): fail: "
634 VG_(umsg
)("set_CEnt (reading data from DI server): fail: "
637 free_Frame(res
); res
= NULL
;
639 VG_(umsg
)("set_CEnt (reading data from DI server): fail: "
640 "server unexpectedly closed the connection\n");
642 give_up__comms_lost();
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
)
660 vg_assert(off
< img
->size
);
661 vg_assert(img
->ces_used
<= CACHE_N_ENTRIES
);
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
))
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
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
);
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
,
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
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
726 SizeT size
= (cslc
== NULL
) ? CACHE_ENTRY_SIZE
: cslc
->szD
;
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
);
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);
738 SizeT len
= tinfl_decompress_mem_to_mem(
739 img
->ces
[i
]->data
, cslc
->szD
,
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);
753 move_CEnt_to_top(img
, i
);
756 vg_assert(is_in_CEnt(img
->ces
[i
], off
));
758 ML_(dinfo_free
)(cbuf
);
760 return img
->ces
[i
]->data
[ off
- img
->ces
[i
]->off
];
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
)
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;
784 set_CEnt(img
, i
, off
);
785 img
->ces
[i
]->fromC
= False
;
786 vg_assert(is_sane_CEnt("get_slowcase-case-2", img
, i
));
788 SizeT len
= tinfl_decompress_mem_to_mem(
789 img
->ces
[i
]->data
, cslc
->szD
,
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
);
801 move_CEnt_to_top(img
, i
);
804 vg_assert(is_in_CEnt(img
->ces
[i
], off
));
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
)
831 struct vg_stat stat_buf
;
834 fd
= VG_(open
)(fullpath
, VKI_O_RDONLY
, 0);
838 if (VG_(fstat
)(sr_Res(fd
), &stat_buf
) != 0) {
839 VG_(close
)(sr_Res(fd
));
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
));
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
);
855 img
->real_size
= size
;
857 img
->source
.name
= ML_(dinfo_strdup
)("di.image.ML_iflf.2", fullpath
);
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
869 UInt entNo
= alloc_CEnt(img
, CACHE_ENTRY_SIZE
, False
/*!fromC*/);
870 vg_assert(entNo
== 0);
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
;
882 if (VG_(fstat
)(fd
, &stat_buf
) != 0) {
886 size
= stat_buf
.size
;
887 if (size
== 0 || size
== DiOffT_INVALID
888 || /* size is unrepresentable as a SizeT */
889 size
!= (DiOffT
)(SizeT
)(size
)) {
893 DiImage
* img
= ML_(dinfo_zalloc
)("di.image.ML_iflf.1", sizeof(DiImage
));
894 img
->source
.is_local
= True
;
897 img
->real_size
= size
;
899 img
->source
.name
= ML_(dinfo_strdup
)("di.image.ML_iflf.2", fullpath
);
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
911 UInt entNo
= alloc_CEnt(img
, CACHE_ENTRY_SIZE
, False
/*!fromC*/);
912 vg_assert(entNo
== 0);
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
)
928 /* The filename must be a plain filename -- no slashes at all. */
929 if (VG_(strchr
)(filename
, '/') != 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
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
);
941 if (!set_blocking(sd
))
944 Int sr
= VG_(setsockopt
)(sd
, VKI_IPPROTO_TCP
, VKI_TCP_NODELAY
,
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
);
955 goto fail
; // do_transaction failed?!
957 if (!parse_Frame_asciiz(res
, "VEOK", &vstr
))
958 goto fail
; // unexpected response kind, or invalid ID string
960 if (VG_(strcmp
)("Valgrind Debuginfo Server, Version 1",
961 (const HChar
*)vstr
) != 0)
962 goto fail
; // wrong version string
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
);
974 ULong session_id
= 0, size
= 0;
975 if (!parse_Frame_le64_le64(res
, "OPOK", &session_id
, &size
))
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
;
986 img
->source
.session_id
= session_id
;
988 img
->real_size
= size
;
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
);
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
1003 UInt entNo
= alloc_CEnt(img
, CACHE_ENTRY_SIZE
, False
/*!fromC*/);
1004 vg_assert(entNo
== 0);
1005 set_CEnt(img
, 0, 0);
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
);
1021 VG_(umsg
)("ML_(img_from_di_server): fail: unknown reason\n");
1029 DiOffT
ML_(img_mark_compressed_part
)(DiImage
* img
, DiOffT offset
, SizeT szC
,
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
));
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
;
1052 void ML_(img_free
)(DiImage
* img
)
1054 vg_assert(img
!= NULL
);
1056 /* Free up the cache entries, ultimately |img| itself. */
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
);
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
);
1091 DiOffT
ML_(img_size
)(const DiImage
* img
)
1093 vg_assert(img
!= NULL
);
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",
1118 VG_(umsg
)("Valgrind: valid image size of %lu for image:\n",
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
)))
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)");
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
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
);
1176 SizeT
ML_(img_strlen
)(DiImage
* img
, DiOffT off
)
1178 ensure_valid(img
, off
, 1, "ML_(img_strlen)");
1180 while (get(img
, off
+ i
) != 0) 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);
1190 for (i
= 0; i
< len
; i
++) {
1191 res
[i
] = get(img
, offset
+i
);
1193 vg_assert(res
[len
] == 0);
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)");
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;
1211 Int
ML_(img_strcmp_c
)(DiImage
* img
, DiOffT off1
, const HChar
* str2
)
1213 ensure_valid(img
, off1
, 1, "ML_(img_strcmp_c)");
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;
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
)
1233 ML_(img_get
)(&r
, img
, offset
, sizeof(r
));
1237 UInt
ML_(img_get_UInt
)(DiImage
* img
, DiOffT offset
)
1240 ML_(img_get
)(&r
, img
, offset
, sizeof(r
));
1244 ULong
ML_(img_get_ULong
)(DiImage
* img
, DiOffT offset
)
1247 ML_(img_get
)(&r
, img
, offset
, sizeof(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,
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;
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;
1330 SizeT nGot
= ML_(img_get_some
)(buf
, img
, curr_off
, avail
);
1331 vg_assert(nGot
>= 1 && nGot
<= avail
);
1333 for (i
= 0; i
< (UInt
)nGot
; i
++)
1334 crc
= crc32_table
[(crc
^ buf
[i
]) & 0xff] ^ (crc
>> 8);
1337 return ~crc
& 0xFFFFFFFF;
1339 Frame
* req
= mk_Frame_noargs("CRC3");
1340 Frame
* res
= do_transaction(img
->source
.fd
, req
);
1341 if (!res
) goto remote_crc_fail
;
1343 if (!parse_Frame_le64(res
, "CROK", &crc32
)) goto remote_crc_fail
;
1344 if ((crc32
& ~0xFFFFFFFFULL
) != 0) goto remote_crc_fail
;
1350 // XXXX common this up with the READ diagnostic cases
1352 UChar
* reason
= NULL
;
1353 if (parse_Frame_asciiz(res
, "FAIL", &reason
)) {
1354 VG_(umsg
)("img_calc_gnu_debuglink_crc32: fail: "
1357 VG_(umsg
)("img_calc_gnu_debuglink_crc32: fail: "
1358 "unknown reason\n");
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
);
1368 give_up__comms_lost();
1376 ////////////////////////////////////////////////////
1377 #include "minilzo-inl.c"
1379 /*--------------------------------------------------------------------*/
1380 /*--- end image.c ---*/
1381 /*--------------------------------------------------------------------*/