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
>= 0)) goto fail
;
146 if (!(ce
->off
+ ce
->used
<= img
->real_size
)) goto fail
;
151 VG_(printf
)("is_sane_CEnt[%u]: fail: %s\n", i
, who
);
152 pp_CEnt("failing CEnt", ce
);
157 /* A frame. The first 4 bytes of |data| give the kind of the frame,
158 and the rest of it is kind-specific data. */
159 typedef struct { UChar
* data
; SizeT n_data
; } Frame
;
161 static void write_UInt_le ( /*OUT*/UChar
* dst
, UInt n
)
164 for (i
= 0; i
<= 3; i
++) {
165 dst
[i
] = (UChar
)(n
& 0xFF);
170 static UInt
read_UInt_le ( const UChar
* src
)
174 for (i
= 3; i
>= 0; i
--) {
181 static void write_ULong_le ( /*OUT*/UChar
* dst
, ULong n
)
184 for (i
= 0; i
<= 7; i
++) {
185 dst
[i
] = (UChar
)(n
& 0xFF);
190 static ULong
read_ULong_le ( const UChar
* src
)
194 for (i
= 7; i
>= 0; i
--) {
202 /* Set |sd| to be blocking. Returns True on success. */
203 static Bool
set_blocking ( int sd
)
206 res
= VG_(fcntl
)(sd
, VKI_F_GETFL
, 0/*ignored*/);
208 res
= VG_(fcntl
)(sd
, VKI_F_SETFL
, res
& ~VKI_O_NONBLOCK
);
212 /* Tries to read 'len' bytes from fd, blocking if necessary. Assumes
213 fd has been set in blocking mode. If it returns with the number of
214 bytes read < len, it means that either fd was closed, or there was
216 static Int
my_read ( Int fd
, UChar
* buf
, Int len
)
220 if (nRead
== len
) return nRead
;
221 vg_assert(nRead
< len
);
222 Int nNeeded
= len
- nRead
;
223 vg_assert(nNeeded
> 0);
224 Int n
= VG_(read
)(fd
, &buf
[nRead
], nNeeded
);
225 if (n
<= 0) return nRead
; /* error or EOF */
230 /* Tries to write 'len' bytes to fd, blocking if necessary. Assumes
231 fd has been set in blocking mode. If it returns with the number of
232 bytes written < len, it means that either fd was closed, or there was
234 static Int
my_write ( Int fd
, const UChar
* buf
, Int len
)
238 if (nWritten
== len
) return nWritten
;
239 vg_assert(nWritten
< len
);
240 Int nStillToDo
= len
- nWritten
;
241 vg_assert(nStillToDo
> 0);
242 Int n
= VG_(write_socket
)(fd
, &buf
[nWritten
], nStillToDo
);
243 if (n
< 0) return nWritten
; /* error or EOF */
248 /* If we lost communication with the remote server, just give up.
249 Recovering is too difficult. */
250 static void give_up__comms_lost(void)
254 "Valgrind: debuginfo reader: Lost communication with the remote\n");
256 "Valgrind: debuginfo server. I can't recover. Giving up. Sorry.\n");
262 static void give_up__image_overrun(void)
266 "Valgrind: debuginfo reader: Possibly corrupted debuginfo file.\n");
268 "Valgrind: I can't recover. Giving up. Sorry.\n");
274 /* "Do" a transaction: that is, send the given frame to the server and
275 return the frame it sends back. Caller owns the resulting frame
276 and must free it. A NULL return means the transaction failed for
278 static Frame
* do_transaction ( Int sd
, const Frame
* req
)
280 if (0) VG_(printf
)("CLIENT: send %c%c%c%c\n",
281 req
->data
[0], req
->data
[1], req
->data
[2], req
->data
[3]);
283 /* What goes on the wire is:
284 adler(le32) n_data(le32) data[0 .. n_data-1]
285 where the checksum covers n_data as well as data[].
287 /* The initial Adler-32 value */
288 UInt adler
= VG_(adler32
)(0, NULL
, 0);
290 /* Fold in the length field, encoded as le32. */
292 write_UInt_le(&wr_first8
[4], req
->n_data
);
293 adler
= VG_(adler32
)(adler
, &wr_first8
[4], 4);
294 /* Fold in the data values */
295 adler
= VG_(adler32
)(adler
, req
->data
, req
->n_data
);
296 write_UInt_le(&wr_first8
[0], adler
);
298 Int r
= my_write(sd
, &wr_first8
[0], 8);
299 if (r
!= 8) return NULL
;
300 vg_assert(req
->n_data
>= 4); // else ill formed -- no KIND field
301 r
= my_write(sd
, req
->data
, req
->n_data
);
302 if (r
!= req
->n_data
) return NULL
;
304 /* So, the request is sent. Now get a request of the same format
305 out of the channel. */
306 UChar rd_first8
[8]; // adler32; length32
307 r
= my_read(sd
, &rd_first8
[0], 8);
308 if (r
!= 8) return NULL
;
309 UInt rd_adler
= read_UInt_le(&rd_first8
[0]);
310 UInt rd_len
= read_UInt_le(&rd_first8
[4]);
311 /* Allocate a Frame to hold the result data, and read into it. */
312 // Reject obviously-insane length fields.
313 if (rd_len
< 4 || rd_len
> 4*1024*1024) return NULL
;
314 Frame
* res
= ML_(dinfo_zalloc
)("di.do_transaction.1", sizeof(Frame
));
315 res
->n_data
= rd_len
;
316 res
->data
= ML_(dinfo_zalloc
)("di.do_transaction.2", rd_len
);
317 r
= my_read(sd
, res
->data
, res
->n_data
);
318 if (r
!= rd_len
) return NULL
;
320 if (0) VG_(printf
)("CLIENT: recv %c%c%c%c\n",
321 res
->data
[0], res
->data
[1], res
->data
[2], res
->data
[3]);
323 /* Compute the checksum for the received data, and check it. */
324 adler
= VG_(adler32
)(0, NULL
, 0); // initial value
325 adler
= VG_(adler32
)(adler
, &rd_first8
[4], 4);
327 adler
= VG_(adler32
)(adler
, res
->data
, res
->n_data
);
329 if (adler
/*computed*/ != rd_adler
/*expected*/) return NULL
;
333 static void free_Frame ( Frame
* fr
)
335 vg_assert(fr
&& fr
->data
);
336 ML_(dinfo_free
)(fr
->data
);
340 static Frame
* mk_Frame_noargs ( const HChar
* tag
)
342 vg_assert(VG_(strlen
)(tag
) == 4);
343 Frame
* f
= ML_(dinfo_zalloc
)("di.mFn.1", sizeof(Frame
));
345 f
->data
= ML_(dinfo_zalloc
)("di.mFn.2", f
->n_data
);
346 VG_(memcpy
)(&f
->data
[0], tag
, 4);
350 static Frame
* mk_Frame_le64_le64_le64 ( const HChar
* tag
,
351 ULong n1
, ULong n2
, ULong n3
)
353 vg_assert(VG_(strlen
)(tag
) == 4);
354 Frame
* f
= ML_(dinfo_zalloc
)("di.mFlll.1", sizeof(Frame
));
356 f
->data
= ML_(dinfo_zalloc
)("di.mFlll.2", f
->n_data
);
357 VG_(memcpy
)(&f
->data
[0], tag
, 4);
358 write_ULong_le(&f
->data
[4 + 0*8], n1
);
359 write_ULong_le(&f
->data
[4 + 1*8], n2
);
360 write_ULong_le(&f
->data
[4 + 2*8], n3
);
364 static Frame
* mk_Frame_asciiz ( const HChar
* tag
, const HChar
* str
)
366 vg_assert(VG_(strlen
)(tag
) == 4);
367 Frame
* f
= ML_(dinfo_zalloc
)("di.mFa.1", sizeof(Frame
));
368 SizeT n_str
= VG_(strlen
)(str
);
369 f
->n_data
= 4 + n_str
+ 1;
370 f
->data
= ML_(dinfo_zalloc
)("di.mFa.2", f
->n_data
);
371 VG_(memcpy
)(&f
->data
[0], tag
, 4);
372 VG_(memcpy
)(&f
->data
[4], str
, n_str
);
373 vg_assert(f
->data
[4 + n_str
] == 0);
377 static Bool
parse_Frame_le64 ( const Frame
* fr
, const HChar
* tag
,
380 vg_assert(VG_(strlen
)(tag
) == 4);
381 if (!fr
|| !fr
->data
) return False
;
382 if (fr
->n_data
< 4) return False
;
383 if (VG_(memcmp
)(&fr
->data
[0], tag
, 4) != 0) return False
;
384 if (fr
->n_data
!= 4 + 1*8) return False
;
385 *n1
= read_ULong_le(&fr
->data
[4 + 0*8]);
389 static Bool
parse_Frame_le64_le64 ( const Frame
* fr
, const HChar
* tag
,
390 /*OUT*/ULong
* n1
, /*OUT*/ULong
* n2
)
392 vg_assert(VG_(strlen
)(tag
) == 4);
393 if (!fr
|| !fr
->data
) return False
;
394 if (fr
->n_data
< 4) return False
;
395 if (VG_(memcmp
)(&fr
->data
[0], tag
, 4) != 0) return False
;
396 if (fr
->n_data
!= 4 + 2*8) return False
;
397 *n1
= read_ULong_le(&fr
->data
[4 + 0*8]);
398 *n2
= read_ULong_le(&fr
->data
[4 + 1*8]);
402 static Bool
parse_Frame_asciiz ( const Frame
* fr
, const HChar
* tag
,
405 vg_assert(VG_(strlen
)(tag
) == 4);
406 if (!fr
|| !fr
->data
) return False
;
407 if (fr
->n_data
< 4) return False
;
408 if (VG_(memcmp
)(&fr
->data
[0], tag
, 4) != 0) return False
;
409 if (fr
->n_data
< 5) return False
; // else there isn't even enough
410 // space for the terminating zero
411 /* Find the terminating zero and ensure it's right at the end
412 of the data. If not, the frame is malformed. */
415 if (i
>= fr
->n_data
) break;
416 if (fr
->data
[i
] == 0) break;
419 vg_assert(i
<= fr
->n_data
);
420 if (i
== fr
->n_data
-1 && fr
->data
[i
] == 0) {
428 static Bool
parse_Frame_le64_le64_le64_bytes (
429 const Frame
* fr
, const HChar
* tag
,
430 /*OUT*/ULong
* n1
, /*OUT*/ULong
* n2
, /*OUT*/ULong
* n3
,
431 /*OUT*/UChar
** data
, /*OUT*/ULong
* n_data
434 vg_assert(VG_(strlen
)(tag
) == 4);
435 if (!fr
|| !fr
->data
) return False
;
436 if (fr
->n_data
< 4) return False
;
437 if (VG_(memcmp
)(&fr
->data
[0], tag
, 4) != 0) return False
;
438 if (fr
->n_data
< 4 + 3*8) return False
;
439 *n1
= read_ULong_le(&fr
->data
[4 + 0*8]);
440 *n2
= read_ULong_le(&fr
->data
[4 + 1*8]);
441 *n3
= read_ULong_le(&fr
->data
[4 + 2*8]);
442 *data
= &fr
->data
[4 + 3*8];
443 *n_data
= fr
->n_data
- (4 + 3*8);
444 vg_assert(fr
->n_data
>= 4 + 3*8);
448 static DiOffT
block_round_down ( DiOffT i
)
450 return i
& ((DiOffT
)~(CACHE_ENTRY_SIZE
-1));
453 /* Is this offset inside this CEnt? */
454 static inline Bool
is_in_CEnt ( const CEnt
* cent
, DiOffT off
)
456 /* This assertion is checked by set_CEnt, so checking it here has
457 no benefit, whereas skipping it does remove it from the hottest
459 /* vg_assert(cent->used > 0 && cent->used <= cent->size); */
460 /* What we want to return is:
461 cent->off <= off && off < cent->off + cent->used;
462 This is however a very hot path, so here's alternative that uses
463 only one conditional branch, using the following transformation,
464 where all quantities are unsigned:
466 --> x-LO >= 0 && x-LO < LO+N-LO
467 --> x-LO >= 0 && x-LO < N
469 This is however only valid when the original bounds, that is, LO
470 .. LO+N-1, do not wrap around the end of the address space. That
471 is, we require that LO <= LO+N-1. But that's OK .. we don't
472 expect wraparounds in CEnts or for that matter any object
473 allocated from C-land. See Hacker's Delight, Chapter 4.1,
474 "Checking Bounds of Integers", for more details.
476 return off
- cent
->off
< cent
->used
;
479 /* Returns pointer to CSlc or NULL */
480 static inline CSlc
* find_cslc ( DiImage
* img
, DiOffT off
)
482 for (UInt i
= 0; i
< img
->cslc_used
; i
++) {
483 if ( (img
->cslc
[i
].offD
<= off
)
484 && (img
->cslc
[i
].offD
+ img
->cslc
[i
].szD
> off
)
486 return &img
->cslc
[i
];
491 /* Allocate a new CEnt, connect it to |img|, and return its index. */
492 static UInt
alloc_CEnt ( DiImage
* img
, SizeT szB
, Bool fromC
)
494 vg_assert(img
!= NULL
);
495 vg_assert(img
->ces_used
< CACHE_N_ENTRIES
);
497 // szB can be arbitrary
499 vg_assert(szB
== CACHE_ENTRY_SIZE
);
501 UInt entNo
= img
->ces_used
;
503 vg_assert(img
->ces
[entNo
] == NULL
);
504 img
->ces
[entNo
] = ML_(dinfo_zalloc
)("di.alloc_CEnt.1",
505 offsetof(CEnt
, data
) + szB
);
506 img
->ces
[entNo
]->size
= szB
;
507 img
->ces
[entNo
]->fromC
= fromC
;
508 vg_assert(is_sane_CEnt("alloc_CEnt", img
, entNo
));
512 static void realloc_CEnt ( DiImage
* img
, UInt entNo
, SizeT szB
, Bool fromC
)
514 vg_assert(img
!= NULL
);
515 vg_assert(fromC
|| szB
>= CACHE_ENTRY_SIZE
);
516 vg_assert(is_sane_CEnt("realloc_CEnt-pre", img
, entNo
));
517 img
->ces
[entNo
] = ML_(dinfo_realloc
)("di.realloc_CEnt.1",
519 offsetof(CEnt
, data
) + szB
);
522 /* Move the given entry to the top and slide those above it down by 1,
524 static void move_CEnt_to_top ( DiImage
* img
, UInt entNo
)
526 vg_assert(entNo
< img
->ces_used
);
527 if (LIKELY(entNo
== 1)) {
528 CEnt
* tmp
= img
->ces
[1];
529 img
->ces
[entNo
] = img
->ces
[0];
532 vg_assert(entNo
> 1); // a.k.a. >= 2
533 CEnt
* tmp
= img
->ces
[entNo
];
534 img
->ces
[entNo
] = img
->ces
[entNo
-1];
536 img
->ces
[entNo
] = img
->ces
[entNo
-1];
539 img
->ces
[entNo
] = img
->ces
[entNo
-1];
546 /* Set the given entry so that it has a chunk of the file containing
547 the given offset. It is this function that brings data into the
548 cache, either by reading the local file or pulling it from the
550 static void set_CEnt ( const DiImage
* img
, UInt entNo
, DiOffT off
)
553 DiOffT off_orig
= off
;
554 vg_assert(img
!= NULL
);
555 vg_assert(img
->ces_used
<= CACHE_N_ENTRIES
);
556 vg_assert(entNo
>= 0 && entNo
< img
->ces_used
);
557 vg_assert(off
< img
->real_size
);
558 CEnt
* ce
= img
->ces
[entNo
];
559 vg_assert(ce
!= NULL
);
560 /* Compute [off, +len) as the slice we are going to read. */
561 off
= block_round_down(off
);
562 len
= img
->real_size
- off
;
565 /* It is conceivable that the 'len > 0' bit could fail if we make
566 an image with a zero sized file. But then no 'get' request on
567 that image would be valid. */
568 vg_assert(len
> 0 && len
<= ce
->size
);
569 vg_assert(off
+ len
<= img
->real_size
);
570 vg_assert(off
<= off_orig
&& off_orig
< off
+len
);
571 /* So, read off .. off+len-1 into the entry. */
574 static UInt t_last
= 0;
575 static ULong nread
= 0;
576 UInt now
= VG_(read_millisecond_timer
)();
577 UInt delay
= now
- t_last
;
580 VG_(printf
)("XXXXXXXX (tot %'llu) read %'lu offset %'llu delay %'u\n",
581 nread
, len
, off
, delay
);
584 if (img
->source
.is_local
) {
585 // Simple: just read it
586 SysRes sr
= VG_(pread
)(img
->source
.fd
, &ce
->data
[0], (Int
)len
, off
);
587 vg_assert(!sr_isError(sr
));
589 // Not so simple: poke the server
590 vg_assert(img
->source
.session_id
> 0);
592 = mk_Frame_le64_le64_le64("READ", img
->source
.session_id
, off
, len
);
593 Frame
* res
= do_transaction(img
->source
.fd
, req
);
594 free_Frame(req
); req
= NULL
;
595 if (!res
) goto server_fail
;
596 ULong rx_session_id
= 0, rx_off
= 0, rx_len
= 0, rx_zdata_len
= 0;
597 UChar
* rx_data
= NULL
;
598 /* Pretty confusing. rx_sessionid, rx_off and rx_len are copies
599 of the values that we requested in the READ frame just above,
600 so we can be sure that the server is responding to the right
601 request. It just copies them from the request into the
602 response. rx_data is the actual data, and rx_zdata_len is
603 its compressed length. Hence rx_len must equal len, but
604 rx_zdata_len can be different -- smaller, hopefully.. */
605 if (!parse_Frame_le64_le64_le64_bytes
606 (res
, "RDOK", &rx_session_id
, &rx_off
,
607 &rx_len
, &rx_data
, &rx_zdata_len
))
609 if (rx_session_id
!= img
->source
.session_id
610 || rx_off
!= off
|| rx_len
!= len
|| rx_data
== NULL
)
613 //VG_(memcpy)(&ce->data[0], rx_data, len);
614 // Decompress into the destination buffer
615 // Tell the lib the max number of output bytes it can write.
616 // After the call, this holds the number of bytes actually written,
617 // and it's an error if it is different.
618 lzo_uint out_len
= len
;
619 Int lzo_rc
= lzo1x_decompress_safe(rx_data
, rx_zdata_len
,
620 &ce
->data
[0], &out_len
,
622 Bool ok
= lzo_rc
== LZO_E_OK
&& out_len
== len
;
623 if (!ok
) goto server_fail
;
625 free_Frame(res
); res
= NULL
;
626 goto end_of_else_clause
;
628 /* The server screwed up somehow. Now what? */
630 UChar
* reason
= NULL
;
631 if (parse_Frame_asciiz(res
, "FAIL", &reason
)) {
632 VG_(umsg
)("set_CEnt (reading data from DI server): fail: "
635 VG_(umsg
)("set_CEnt (reading data from DI server): fail: "
638 free_Frame(res
); res
= NULL
;
640 VG_(umsg
)("set_CEnt (reading data from DI server): fail: "
641 "server unexpectedly closed the connection\n");
643 give_up__comms_lost();
653 vg_assert(ce
== img
->ces
[entNo
]);
654 vg_assert(is_sane_CEnt("set_CEnt", img
, entNo
));
657 __attribute__((noinline
))
658 static UChar
get_slowcase ( DiImage
* img
, DiOffT off
)
661 vg_assert(off
< img
->size
);
662 vg_assert(img
->ces_used
<= CACHE_N_ENTRIES
);
664 /* Start the search at entry 1, since the fast-case function
665 checked slot zero already. */
666 for (i
= 1; i
< img
->ces_used
; i
++) {
667 vg_assert(img
->ces
[i
]);
668 if (is_in_CEnt(img
->ces
[i
], off
))
673 if (LIKELY(i
< img
->ces_used
)) {
674 // Found it. Move to the top and stop.
675 move_CEnt_to_top(img
, i
);
676 vg_assert(is_in_CEnt(img
->ces
[0], off
));
677 return img
->ces
[0]->data
[ off
- img
->ces
[0]->off
];
680 vg_assert(i
<= img
->ces_used
);
682 // It's not in any entry. Either allocate a new one or recycle the LRU
683 // one. This is where the presence of compressed sections makes things
684 // tricky. There are 4 cases to consider:
686 // (1) not from a compressed slice, we can allocate a new entry
687 // (2) not from a compressed slice, we have to recycle the LRU entry
688 // (3) from a compressed slice, we can allocate a new entry
689 // (4) from a compressed slice, we have to recycle the LRU entry
691 // Cases (3) and (4) are complex because we will have to call
692 // ML_(img_get_some) to get the compressed data. But this function is
693 // reachable from ML_(img_get_some), so we may re-enter get_slowcase a
694 // second time as a result. Given that the compressed data will be cause
695 // only cases (1) and (2) to happen, this guarantees no infinite recursion.
696 // It does however mean that we can't carry (in this function invokation)
697 // any local copies of the overall cache state across the ML_(img_get_some)
698 // call, since it may become invalidated by the recursive call to
701 // First of all, see if it is in a compressed slice, and if so, pull the
702 // compressed data into an intermediate buffer. Given the preceding
703 // comment, this is a safe place to do it, since we are not carrying any
704 // cache state here apart from the knowledge that the requested offset is
705 // not in the cache at all, and the recursive call won't change that fact.
707 CSlc
* cslc
= find_cslc(img
, off
);
711 cbuf
= ML_(dinfo_zalloc
)("di.image.get_slowcase.cbuf-1", cslc
->szC
);
712 // get compressed data
713 while (len
< cslc
->szC
)
714 len
+= ML_(img_get_some
)(cbuf
+ len
, img
, cslc
->offC
+ len
,
718 // Now we can do what we like.
719 vg_assert((cslc
== NULL
&& cbuf
== NULL
) || (cslc
!= NULL
&& cbuf
!= NULL
));
721 // Note, we can't capture this earlier, for exactly the reasons detailed
723 UInt ces_used_at_entry
= img
->ces_used
;
725 // This is the size of the CEnt that we want to have after allocation or
727 SizeT size
= (cslc
== NULL
) ? CACHE_ENTRY_SIZE
: cslc
->szD
;
730 if (img
->ces_used
< CACHE_N_ENTRIES
) {
731 /* Allocate a new cache entry, and fill it in. */
732 i
= alloc_CEnt(img
, size
, /*fromC?*/cslc
!= NULL
);
734 set_CEnt(img
, i
, off
);
735 img
->ces
[i
]->fromC
= False
;
736 vg_assert(is_sane_CEnt("get_slowcase-case-1", img
, i
));
737 vg_assert(img
->ces_used
== ces_used_at_entry
+ 1);
739 SizeT len
= tinfl_decompress_mem_to_mem(
740 img
->ces
[i
]->data
, cslc
->szD
,
742 TINFL_FLAG_USING_NON_WRAPPING_OUTPUT_BUF
743 | TINFL_FLAG_PARSE_ZLIB_HEADER
);
744 vg_assert(len
== cslc
->szD
); // sanity check on data, FIXME
745 vg_assert(cslc
->szD
== size
);
746 img
->ces
[i
]->used
= cslc
->szD
;
747 img
->ces
[i
]->off
= cslc
->offD
;
748 img
->ces
[i
]->fromC
= True
;
749 vg_assert(is_sane_CEnt("get_slowcase-case-3", img
, i
));
750 vg_assert(img
->ces_used
== ces_used_at_entry
+ 1);
752 vg_assert(img
->ces_used
== ces_used_at_entry
+ 1);
754 move_CEnt_to_top(img
, i
);
757 vg_assert(is_in_CEnt(img
->ces
[i
], off
));
759 ML_(dinfo_free
)(cbuf
);
761 return img
->ces
[i
]->data
[ off
- img
->ces
[i
]->off
];
765 /* All entries in use. Recycle the (ostensibly) LRU one. But try to find
766 a non-fromC entry to recycle, though, since discarding and reloading
767 fromC entries is very expensive. The result is that -- unless all
768 CACHE_N_ENTRIES wind up being used by decompressed slices, which is
769 highly unlikely -- we'll wind up keeping all the decompressed data in
770 the cache for its entire remaining life. We could probably do better
771 but it would make the cache management even more complex. */
772 vg_assert(img
->ces_used
== CACHE_N_ENTRIES
);
774 // Select entry to recycle.
775 for (i
= CACHE_N_ENTRIES
-1; i
> 0; i
--) {
776 if (!img
->ces
[i
]->fromC
)
779 vg_assert(i
>= 0 && i
< CACHE_N_ENTRIES
);
781 realloc_CEnt(img
, i
, size
, /*fromC?*/cslc
!= NULL
);
782 img
->ces
[i
]->size
= size
;
783 img
->ces
[i
]->used
= 0;
785 set_CEnt(img
, i
, off
);
786 img
->ces
[i
]->fromC
= False
;
787 vg_assert(is_sane_CEnt("get_slowcase-case-2", img
, i
));
789 SizeT len
= tinfl_decompress_mem_to_mem(
790 img
->ces
[i
]->data
, cslc
->szD
,
792 TINFL_FLAG_USING_NON_WRAPPING_OUTPUT_BUF
793 | TINFL_FLAG_PARSE_ZLIB_HEADER
);
794 vg_assert(len
== size
);
795 img
->ces
[i
]->used
= size
;
796 img
->ces
[i
]->off
= cslc
->offD
;
797 img
->ces
[i
]->fromC
= True
;
798 vg_assert(is_sane_CEnt("get_slowcase-case-4", img
, i
));
800 vg_assert(img
->ces_used
== ces_used_at_entry
);
802 move_CEnt_to_top(img
, i
);
805 vg_assert(is_in_CEnt(img
->ces
[i
], off
));
807 ML_(dinfo_free
)(cbuf
);
809 return img
->ces
[i
]->data
[ off
- img
->ces
[i
]->off
];
812 // This is called a lot, so do the usual fast/slow split stuff on it. */
813 static inline UChar
get ( DiImage
* img
, DiOffT off
)
815 /* Most likely case is, it's in the ces[0] position. */
816 /* ML_(img_from_local_file) requests a read for ces[0] when
817 creating the image. Hence slot zero is always non-NULL, so we
818 can skip this test. */
819 if (LIKELY(/* img->ces[0] != NULL && */
820 is_in_CEnt(img
->ces
[0], off
))) {
821 return img
->ces
[0]->data
[ off
- img
->ces
[0]->off
];
823 /* Else we'll have to fish around for it. */
824 return get_slowcase(img
, off
);
827 /* Create an image from a file in the local filesystem. This is
828 relatively straightforward. */
829 DiImage
* ML_(img_from_local_file
)(const HChar
* fullpath
)
832 struct vg_stat stat_buf
;
835 fd
= VG_(open
)(fullpath
, VKI_O_RDONLY
, 0);
839 if (VG_(fstat
)(sr_Res(fd
), &stat_buf
) != 0) {
840 VG_(close
)(sr_Res(fd
));
844 size
= stat_buf
.size
;
845 if (size
== 0 || size
== DiOffT_INVALID
846 || /* size is unrepresentable as a SizeT */
847 size
!= (DiOffT
)(SizeT
)(size
)) {
848 VG_(close
)(sr_Res(fd
));
852 DiImage
* img
= ML_(dinfo_zalloc
)("di.image.ML_iflf.1", sizeof(DiImage
));
853 img
->source
.is_local
= True
;
854 img
->source
.fd
= sr_Res(fd
);
856 img
->real_size
= size
;
858 img
->source
.name
= ML_(dinfo_strdup
)("di.image.ML_iflf.2", fullpath
);
862 /* img->ces is already zeroed out */
863 vg_assert(img
->source
.fd
>= 0);
865 /* Force the zeroth entry to be the first chunk of the file.
866 That's likely to be the first part that's requested anyway, and
867 loading it at this point forcing img->cent[0] to always be
868 non-empty, thereby saving us an is-it-empty check on the fast
870 UInt entNo
= alloc_CEnt(img
, CACHE_ENTRY_SIZE
, False
/*!fromC*/);
871 vg_assert(entNo
== 0);
877 /* As above, but uses fd rather than filename */
878 DiImage
* ML_(img_from_fd
)(Int fd
, const HChar
* fullpath
)
880 struct vg_stat stat_buf
;
883 if (VG_(fstat
)(fd
, &stat_buf
) != 0) {
887 size
= stat_buf
.size
;
888 if (size
== 0 || size
== DiOffT_INVALID
889 || /* size is unrepresentable as a SizeT */
890 size
!= (DiOffT
)(SizeT
)(size
)) {
894 DiImage
* img
= ML_(dinfo_zalloc
)("di.image.ML_iflf.1", sizeof(DiImage
));
895 img
->source
.is_local
= True
;
898 img
->real_size
= size
;
900 img
->source
.name
= ML_(dinfo_strdup
)("di.image.ML_iflf.2", fullpath
);
904 /* img->ces is already zeroed out */
905 vg_assert(img
->source
.fd
>= 0);
907 /* Force the zeroth entry to be the first chunk of the file.
908 That's likely to be the first part that's requested anyway, and
909 loading it at this point forcing img->cent[0] to always be
910 non-empty, thereby saving us an is-it-empty check on the fast
912 UInt entNo
= alloc_CEnt(img
, CACHE_ENTRY_SIZE
, False
/*!fromC*/);
913 vg_assert(entNo
== 0);
921 /* Create an image from a file on a remote debuginfo server. This is
922 more complex. There are lots of ways in which it can fail. */
923 DiImage
* ML_(img_from_di_server
)(const HChar
* filename
,
924 const HChar
* serverAddr
)
926 if (filename
== NULL
|| serverAddr
== NULL
)
929 /* The filename must be a plain filename -- no slashes at all. */
930 if (VG_(strchr
)(filename
, '/') != NULL
)
933 /* Try to connect to the server. A side effect of this is to parse
934 and reject, if syntactically invalid, |serverAddr|. Reasons why
936 - serverAddr is not of the form d.d.d.d:d or d.d.d.d
937 - attempt to connect to that address:port failed
939 Int sd
= VG_(connect_via_socket
)(serverAddr
);
942 if (!set_blocking(sd
))
945 Int sr
= VG_(setsockopt
)(sd
, VKI_IPPROTO_TCP
, VKI_TCP_NODELAY
,
949 /* Ok, we got a connection. Ask it for version string, so as to be
950 reasonably sure we're talking to an instance of
951 auxprogs/valgrind-di-server and not to some other random program
952 that happens to be listening on that port. */
953 Frame
* req
= mk_Frame_noargs("VERS");
954 Frame
* res
= do_transaction(sd
, req
);
956 goto fail
; // do_transaction failed?!
958 if (!parse_Frame_asciiz(res
, "VEOK", &vstr
))
959 goto fail
; // unexpected response kind, or invalid ID string
961 if (VG_(strcmp
)("Valgrind Debuginfo Server, Version 1",
962 (const HChar
*)vstr
) != 0)
963 goto fail
; // wrong version string
969 /* Server seems plausible. Present it with the name of the file we
970 want and see if it'll give us back a session ID for it. */
971 req
= mk_Frame_asciiz("OPEN", filename
);
972 res
= do_transaction(sd
, req
);
975 ULong session_id
= 0, size
= 0;
976 if (!parse_Frame_le64_le64(res
, "OPOK", &session_id
, &size
))
983 /* We have a session ID. We're ready to roll. */
984 DiImage
* img
= ML_(dinfo_zalloc
)("di.image.ML_ifds.1", sizeof(DiImage
));
985 img
->source
.is_local
= False
;
987 img
->source
.session_id
= session_id
;
989 img
->real_size
= size
;
991 img
->source
.name
= ML_(dinfo_zalloc
)("di.image.ML_ifds.2",
992 20 + VG_(strlen
)(filename
)
993 + VG_(strlen
)(serverAddr
));
994 VG_(sprintf
)(img
->source
.name
, "%s at %s", filename
, serverAddr
);
999 /* img->ces is already zeroed out */
1000 vg_assert(img
->source
.fd
>= 0);
1002 /* See comment on equivalent bit in ML_(img_from_local_file) for
1004 UInt entNo
= alloc_CEnt(img
, CACHE_ENTRY_SIZE
, False
/*!fromC*/);
1005 vg_assert(entNo
== 0);
1006 set_CEnt(img
, 0, 0);
1013 UChar
* reason
= NULL
;
1014 if (parse_Frame_asciiz(res
, "FAIL", &reason
)) {
1015 // HACK: if it's just telling us that the file can't
1016 // be opened, don't print it, else we'll get flooded with
1017 // such complaints, one for each main object for which there
1018 // isn't a debuginfo file on the server.
1019 if (0 != VG_(strcmp
)((const HChar
*)reason
, "OPEN: cannot open file"))
1020 VG_(umsg
)("ML_(img_from_di_server): fail: %s\n", reason
);
1022 VG_(umsg
)("ML_(img_from_di_server): fail: unknown reason\n");
1030 DiOffT
ML_(img_mark_compressed_part
)(DiImage
* img
, DiOffT offset
, SizeT szC
,
1034 vg_assert(img
!= NULL
);
1035 vg_assert(offset
+ szC
<= img
->size
);
1037 if (img
->cslc_used
== img
->cslc_size
) {
1038 img
->cslc_size
+= COMPRESSED_SLICE_ARRAY_GROW_SIZE
;
1039 img
->cslc
= ML_(dinfo_realloc
)("di.image.ML_img_mark_compressed_part.1",
1040 img
->cslc
, img
->cslc_size
* sizeof(CSlc
));
1044 img
->cslc
[img
->cslc_used
].offC
= offset
;
1045 img
->cslc
[img
->cslc_used
].szC
= szC
;
1046 img
->cslc
[img
->cslc_used
].offD
= img
->size
;
1047 img
->cslc
[img
->cslc_used
].szD
= szD
;
1053 void ML_(img_free
)(DiImage
* img
)
1055 vg_assert(img
!= NULL
);
1057 /* Free up the cache entries, ultimately |img| itself. */
1059 vg_assert(img
->ces_used
<= CACHE_N_ENTRIES
);
1060 for (i
= 0; i
< img
->ces_used
; i
++) {
1061 ML_(dinfo_free
)(img
->ces
[i
]);
1063 /* Take the opportunity to sanity check the rest. */
1064 for (i
= i
; i
< img
->ces_used
; i
++) {
1065 vg_assert(img
->ces
[i
] == NULL
);
1067 ML_(dinfo_free
)(img
->source
.name
);
1068 ML_(dinfo_free
)(img
->cslc
);
1069 ML_(dinfo_free
)(img
);
1072 void ML_(img_done
)(DiImage
* img
)
1074 vg_assert(img
!= NULL
);
1075 if (img
->source
.is_local
) {
1076 /* Close the file; nothing else to do. */
1077 vg_assert(img
->source
.session_id
== 0);
1078 VG_(close
)(img
->source
.fd
);
1080 /* Close the socket. The server can detect this and will scrub
1081 the connection when it happens, so there's no need to tell it
1082 explicitly by sending it a "CLOSE" message, or any such. */
1083 vg_assert(img
->source
.session_id
!= 0);
1084 VG_(close
)(img
->source
.fd
);
1092 DiOffT
ML_(img_size
)(const DiImage
* img
)
1094 vg_assert(img
!= NULL
);
1098 DiOffT
ML_(img_real_size
)(const DiImage
* img
)
1100 vg_assert(img
!= NULL
);
1101 return img
->real_size
;
1104 inline Bool
ML_(img_valid
)(const DiImage
* img
, DiOffT offset
, SizeT size
)
1106 vg_assert(img
!= NULL
);
1107 vg_assert(offset
!= DiOffT_INVALID
);
1108 return img
->size
> 0 && offset
+ size
<= (DiOffT
)img
->size
;
1111 __attribute__((noinline
))
1112 static void ensure_valid_failed (const DiImage
* img
, DiOffT offset
, SizeT size
,
1113 const HChar
* caller
)
1115 VG_(umsg
)("Valgrind: debuginfo reader: ensure_valid failed:\n");
1116 VG_(umsg
)("Valgrind: during call to %s\n", caller
);
1117 VG_(umsg
)("Valgrind: request for range [%llu, +%lu) exceeds\n",
1119 VG_(umsg
)("Valgrind: valid image size of %lu for image:\n",
1121 VG_(umsg
)("Valgrind: \"%s\"\n", img
->source
.name
);
1122 give_up__image_overrun();
1125 /* Check the given range is valid, and if not, shut down the system.
1126 An invalid range would imply that we're trying to read outside the
1127 image, which normally means the image is corrupted somehow, or the
1128 caller is buggy. Recovering is too complex, and we have
1129 probably-corrupt debuginfo, so just give up. */
1130 static void ensure_valid(const DiImage
* img
, DiOffT offset
, SizeT size
,
1131 const HChar
* caller
)
1133 if (LIKELY(ML_(img_valid
)(img
, offset
, size
)))
1136 ensure_valid_failed(img
, offset
, size
, caller
);
1140 void ML_(img_get
)(/*OUT*/void* dst
,
1141 DiImage
* img
, DiOffT offset
, SizeT size
)
1143 vg_assert(img
!= NULL
);
1144 vg_assert(size
> 0);
1145 ensure_valid(img
, offset
, size
, "ML_(img_get)");
1147 for (i
= 0; i
< size
; i
++) {
1148 ((UChar
*)dst
)[i
] = get(img
, offset
+ i
);
1152 SizeT
ML_(img_get_some
)(/*OUT*/void* dst
,
1153 DiImage
* img
, DiOffT offset
, SizeT size
)
1155 vg_assert(img
!= NULL
);
1156 vg_assert(size
> 0);
1157 ensure_valid(img
, offset
, size
, "ML_(img_get_some)");
1158 UChar
* dstU
= (UChar
*)dst
;
1159 /* Use |get| in the normal way to get the first byte of the range.
1160 This guarantees to put the cache entry containing |offset| in
1162 dstU
[0] = get(img
, offset
);
1163 /* Now just read as many bytes as we can (or need) directly out of
1164 entry zero, without bothering to call |get| each time. */
1165 const CEnt
* ce
= img
->ces
[0];
1166 vg_assert(ce
&& ce
->used
>= 1);
1167 vg_assert(is_in_CEnt(ce
, offset
));
1168 SizeT nToCopy
= size
- 1;
1169 SizeT nAvail
= (SizeT
)(ce
->used
- (offset
+ 1 - ce
->off
));
1170 vg_assert(nAvail
>= 0 && nAvail
<= ce
->used
-1);
1171 if (nAvail
< nToCopy
) nToCopy
= nAvail
;
1172 VG_(memcpy
)(&dstU
[1], &ce
->data
[offset
+ 1 - ce
->off
], nToCopy
);
1177 SizeT
ML_(img_strlen
)(DiImage
* img
, DiOffT off
)
1179 ensure_valid(img
, off
, 1, "ML_(img_strlen)");
1181 while (get(img
, off
+ i
) != 0) i
++;
1185 HChar
* ML_(img_strdup
)(DiImage
* img
, const HChar
* cc
, DiOffT offset
)
1187 ensure_valid(img
, offset
, 1, "ML_(img_strdup)");
1188 SizeT len
= ML_(img_strlen
)(img
, offset
);
1189 HChar
* res
= ML_(dinfo_zalloc
)(cc
, len
+1);
1191 for (i
= 0; i
< len
; i
++) {
1192 res
[i
] = get(img
, offset
+i
);
1194 vg_assert(res
[len
] == 0);
1198 Int
ML_(img_strcmp
)(DiImage
* img
, DiOffT off1
, DiOffT off2
)
1200 ensure_valid(img
, off1
, 1, "ML_(img_strcmp)(first arg)");
1201 ensure_valid(img
, off2
, 1, "ML_(img_strcmp)(second arg)");
1203 UChar c1
= get(img
, off1
);
1204 UChar c2
= get(img
, off2
);
1205 if (c1
< c2
) return -1;
1206 if (c1
> c2
) return 1;
1207 if (c1
== 0) return 0;
1212 Int
ML_(img_strcmp_c
)(DiImage
* img
, DiOffT off1
, const HChar
* str2
)
1214 ensure_valid(img
, off1
, 1, "ML_(img_strcmp_c)");
1216 UChar c1
= get(img
, off1
);
1217 UChar c2
= *(const UChar
*)str2
;
1218 if (c1
< c2
) return -1;
1219 if (c1
> c2
) return 1;
1220 if (c1
== 0) return 0;
1225 UChar
ML_(img_get_UChar
)(DiImage
* img
, DiOffT offset
)
1227 ensure_valid(img
, offset
, 1, "ML_(img_get_UChar)");
1228 return get(img
, offset
);
1231 UShort
ML_(img_get_UShort
)(DiImage
* img
, DiOffT offset
)
1234 ML_(img_get
)(&r
, img
, offset
, sizeof(r
));
1238 UInt
ML_(img_get_UInt
)(DiImage
* img
, DiOffT offset
)
1241 ML_(img_get
)(&r
, img
, offset
, sizeof(r
));
1245 ULong
ML_(img_get_ULong
)(DiImage
* img
, DiOffT offset
)
1248 ML_(img_get
)(&r
, img
, offset
, sizeof(r
));
1254 * This routine for calculating the CRC for a separate debug file
1255 * is GPLed code borrowed from GNU binutils.
1257 UInt
ML_(img_calc_gnu_debuglink_crc32
)(DiImage
* img
)
1259 static const UInt crc32_table
[256] =
1261 0x00000000, 0x77073096, 0xee0e612c, 0x990951ba, 0x076dc419,
1262 0x706af48f, 0xe963a535, 0x9e6495a3, 0x0edb8832, 0x79dcb8a4,
1263 0xe0d5e91e, 0x97d2d988, 0x09b64c2b, 0x7eb17cbd, 0xe7b82d07,
1264 0x90bf1d91, 0x1db71064, 0x6ab020f2, 0xf3b97148, 0x84be41de,
1265 0x1adad47d, 0x6ddde4eb, 0xf4d4b551, 0x83d385c7, 0x136c9856,
1266 0x646ba8c0, 0xfd62f97a, 0x8a65c9ec, 0x14015c4f, 0x63066cd9,
1267 0xfa0f3d63, 0x8d080df5, 0x3b6e20c8, 0x4c69105e, 0xd56041e4,
1268 0xa2677172, 0x3c03e4d1, 0x4b04d447, 0xd20d85fd, 0xa50ab56b,
1269 0x35b5a8fa, 0x42b2986c, 0xdbbbc9d6, 0xacbcf940, 0x32d86ce3,
1270 0x45df5c75, 0xdcd60dcf, 0xabd13d59, 0x26d930ac, 0x51de003a,
1271 0xc8d75180, 0xbfd06116, 0x21b4f4b5, 0x56b3c423, 0xcfba9599,
1272 0xb8bda50f, 0x2802b89e, 0x5f058808, 0xc60cd9b2, 0xb10be924,
1273 0x2f6f7c87, 0x58684c11, 0xc1611dab, 0xb6662d3d, 0x76dc4190,
1274 0x01db7106, 0x98d220bc, 0xefd5102a, 0x71b18589, 0x06b6b51f,
1275 0x9fbfe4a5, 0xe8b8d433, 0x7807c9a2, 0x0f00f934, 0x9609a88e,
1276 0xe10e9818, 0x7f6a0dbb, 0x086d3d2d, 0x91646c97, 0xe6635c01,
1277 0x6b6b51f4, 0x1c6c6162, 0x856530d8, 0xf262004e, 0x6c0695ed,
1278 0x1b01a57b, 0x8208f4c1, 0xf50fc457, 0x65b0d9c6, 0x12b7e950,
1279 0x8bbeb8ea, 0xfcb9887c, 0x62dd1ddf, 0x15da2d49, 0x8cd37cf3,
1280 0xfbd44c65, 0x4db26158, 0x3ab551ce, 0xa3bc0074, 0xd4bb30e2,
1281 0x4adfa541, 0x3dd895d7, 0xa4d1c46d, 0xd3d6f4fb, 0x4369e96a,
1282 0x346ed9fc, 0xad678846, 0xda60b8d0, 0x44042d73, 0x33031de5,
1283 0xaa0a4c5f, 0xdd0d7cc9, 0x5005713c, 0x270241aa, 0xbe0b1010,
1284 0xc90c2086, 0x5768b525, 0x206f85b3, 0xb966d409, 0xce61e49f,
1285 0x5edef90e, 0x29d9c998, 0xb0d09822, 0xc7d7a8b4, 0x59b33d17,
1286 0x2eb40d81, 0xb7bd5c3b, 0xc0ba6cad, 0xedb88320, 0x9abfb3b6,
1287 0x03b6e20c, 0x74b1d29a, 0xead54739, 0x9dd277af, 0x04db2615,
1288 0x73dc1683, 0xe3630b12, 0x94643b84, 0x0d6d6a3e, 0x7a6a5aa8,
1289 0xe40ecf0b, 0x9309ff9d, 0x0a00ae27, 0x7d079eb1, 0xf00f9344,
1290 0x8708a3d2, 0x1e01f268, 0x6906c2fe, 0xf762575d, 0x806567cb,
1291 0x196c3671, 0x6e6b06e7, 0xfed41b76, 0x89d32be0, 0x10da7a5a,
1292 0x67dd4acc, 0xf9b9df6f, 0x8ebeeff9, 0x17b7be43, 0x60b08ed5,
1293 0xd6d6a3e8, 0xa1d1937e, 0x38d8c2c4, 0x4fdff252, 0xd1bb67f1,
1294 0xa6bc5767, 0x3fb506dd, 0x48b2364b, 0xd80d2bda, 0xaf0a1b4c,
1295 0x36034af6, 0x41047a60, 0xdf60efc3, 0xa867df55, 0x316e8eef,
1296 0x4669be79, 0xcb61b38c, 0xbc66831a, 0x256fd2a0, 0x5268e236,
1297 0xcc0c7795, 0xbb0b4703, 0x220216b9, 0x5505262f, 0xc5ba3bbe,
1298 0xb2bd0b28, 0x2bb45a92, 0x5cb36a04, 0xc2d7ffa7, 0xb5d0cf31,
1299 0x2cd99e8b, 0x5bdeae1d, 0x9b64c2b0, 0xec63f226, 0x756aa39c,
1300 0x026d930a, 0x9c0906a9, 0xeb0e363f, 0x72076785, 0x05005713,
1301 0x95bf4a82, 0xe2b87a14, 0x7bb12bae, 0x0cb61b38, 0x92d28e9b,
1302 0xe5d5be0d, 0x7cdcefb7, 0x0bdbdf21, 0x86d3d2d4, 0xf1d4e242,
1303 0x68ddb3f8, 0x1fda836e, 0x81be16cd, 0xf6b9265b, 0x6fb077e1,
1304 0x18b74777, 0x88085ae6, 0xff0f6a70, 0x66063bca, 0x11010b5c,
1305 0x8f659eff, 0xf862ae69, 0x616bffd3, 0x166ccf45, 0xa00ae278,
1306 0xd70dd2ee, 0x4e048354, 0x3903b3c2, 0xa7672661, 0xd06016f7,
1307 0x4969474d, 0x3e6e77db, 0xaed16a4a, 0xd9d65adc, 0x40df0b66,
1308 0x37d83bf0, 0xa9bcae53, 0xdebb9ec5, 0x47b2cf7f, 0x30b5ffe9,
1309 0xbdbdf21c, 0xcabac28a, 0x53b39330, 0x24b4a3a6, 0xbad03605,
1310 0xcdd70693, 0x54de5729, 0x23d967bf, 0xb3667a2e, 0xc4614ab8,
1311 0x5d681b02, 0x2a6f2b94, 0xb40bbe37, 0xc30c8ea1, 0x5a05df1b,
1315 vg_assert(img
!= NULL
);
1317 /* If the image is local, calculate the CRC here directly. If it's
1318 remote, forward the request to the server. */
1319 if (img
->source
.is_local
) {
1320 /* Work through the image in 1 KB chunks. */
1321 UInt crc
= 0xFFFFFFFF;
1322 DiOffT img_szB
= ML_(img_size
)(img
);
1323 DiOffT curr_off
= 0;
1325 vg_assert(curr_off
>= 0 && curr_off
<= img_szB
);
1326 if (curr_off
== img_szB
) break;
1327 DiOffT avail
= img_szB
- curr_off
;
1328 vg_assert(avail
> 0 && avail
<= img_szB
);
1329 if (avail
> 1024) avail
= 1024;
1331 SizeT nGot
= ML_(img_get_some
)(buf
, img
, curr_off
, avail
);
1332 vg_assert(nGot
>= 1 && nGot
<= avail
);
1334 for (i
= 0; i
< (UInt
)nGot
; i
++)
1335 crc
= crc32_table
[(crc
^ buf
[i
]) & 0xff] ^ (crc
>> 8);
1338 return ~crc
& 0xFFFFFFFF;
1340 Frame
* req
= mk_Frame_noargs("CRC3");
1341 Frame
* res
= do_transaction(img
->source
.fd
, req
);
1342 if (!res
) goto remote_crc_fail
;
1344 if (!parse_Frame_le64(res
, "CROK", &crc32
)) goto remote_crc_fail
;
1345 if ((crc32
& ~0xFFFFFFFFULL
) != 0) goto remote_crc_fail
;
1351 // XXXX common this up with the READ diagnostic cases
1353 UChar
* reason
= NULL
;
1354 if (parse_Frame_asciiz(res
, "FAIL", &reason
)) {
1355 VG_(umsg
)("img_calc_gnu_debuglink_crc32: fail: "
1358 VG_(umsg
)("img_calc_gnu_debuglink_crc32: fail: "
1359 "unknown reason\n");
1362 VG_(umsg
)("img_calc_gnu_debuglink_crc32: fail: "
1363 "server unexpectedly closed the connection\n");
1366 if (req
) free_Frame(req
);
1367 if (res
) free_Frame(res
);
1369 give_up__comms_lost();
1377 ////////////////////////////////////////////////////
1378 #include "minilzo-inl.c"
1380 /*--------------------------------------------------------------------*/
1381 /*--- end image.c ---*/
1382 /*--------------------------------------------------------------------*/