1 /* -*- mode: C; c-basic-offset: 3; -*- */
2
3 /*--------------------------------------------------------------------*/
4 /*--- An abstraction that provides a file-reading mechanism. ---*/
5 /*--- image.c ---*/
6 /*--------------------------------------------------------------------*/
7
8 /*
9 This file is part of Valgrind, a dynamic binary instrumentation
10 framework.
11
12 Copyright (C) 2013-2017 Mozilla Foundation
13
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.
18
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.
23
24 You should have received a copy of the GNU General Public License
25 along with this program; if not, write to the Free Software
26 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
27 02111-1307, USA.
28
29 The GNU General Public License is contained in the file COPYING.
30 */
31
32 /* Contributed by Julian Seward <jseward@acm.org> */
33
34 /* See the corresponding auxprogs/valgrind-di-server.c for a list of
35 cleanups for this file and itself. */
36
37 #include "pub_core_basics.h"
38 #include "pub_core_vki.h"
39 #include "pub_core_libcbase.h"
40 #include "pub_core_libcassert.h"
41 #include "pub_core_libcprint.h"
42 #include "pub_core_libcproc.h" /* VG_(read_millisecond_timer) */
43 #include "pub_core_libcfile.h"
44 #include "priv_misc.h" /* dinfo_zalloc/free/strdup */
45 #include "priv_image.h" /* self */
46
47 #include "minilzo.h"
48 #define TINFL_HEADER_FILE_ONLY
49 #include "tinfl.c"
50
51 /* These values (1024 entries of 8192 bytes each) gives a cache
52 size of 8MB. */
53 #define CACHE_ENTRY_SIZE_BITS (12+1)
54 #define CACHE_N_ENTRIES 1024
55
56 #define CACHE_ENTRY_SIZE (1 << CACHE_ENTRY_SIZE_BITS)
57
58 #define COMPRESSED_SLICE_ARRAY_GROW_SIZE 64
59
60 /* An entry in the cache. */
61 typedef
62 struct {
63 Bool fromC; // True === contains decompressed data
64 DiOffT off; // file offset for data[0]
65 SizeT size; // sizeof(data)
66 SizeT used; // 1 .. sizeof(data), or 0 to denote not-in-use
67 UChar data[];
68 }
69 CEnt;
70
71 /* Compressed slice */
72 typedef
73 struct {
74 DiOffT offD; // offset of decompressed data
75 SizeT szD; // size of decompressed data
76 DiOffT offC; // offset of compressed data
77 SizeT szC; // size of compressed data
78 }
79 CSlc;
80
81 /* Source for files */
82 typedef
83 struct {
84 // True: img is of local file. False: img is from a server.
85 Bool is_local;
86 // The fd for the local file, or sd for a remote server.
87 Int fd;
88 // The name. In ML_(dinfo_zalloc)'d space. Used only for printing
89 // error messages; hence it doesn't really matter what this contains.
90 HChar* name;
91 // The rest of these fields are only valid when using remote files
92 // (that is, using a debuginfo server; hence when is_local==False)
93 // Session ID allocated to us by the server. Cannot be zero.
94 ULong session_id;
95 }
96 Source;
97
98 struct _DiImage {
99 // The source -- how to get hold of the file we are reading
100 Source source;
101 // Virtual size of the image = real size + size of uncompressed data
102 SizeT size;
103 // Real size of image
104 SizeT real_size;
105 // The number of entries used. 0 .. CACHE_N_ENTRIES
106 UInt ces_used;
107 // Pointers to the entries. ces[0 .. ces_used-1] are non-NULL.
108 // ces[ces_used .. CACHE_N_ENTRIES-1] are NULL.
109 // The non-NULL entries may be arranged arbitrarily. We expect to use
110 // a pseudo-LRU scheme though.
111 CEnt* ces[CACHE_N_ENTRIES];
112
113 // Array of compressed slices
114 CSlc* cslc;
115 // Number of compressed slices used
116 UInt cslc_used;
117 // Size of cslc array
118 UInt cslc_size;
119 };
120
121
122 /* Sanity check code for CEnts. */
pp_CEnt(const HChar * msg,CEnt * ce)123 static void pp_CEnt(const HChar* msg, CEnt* ce)
124 {
125 VG_(printf)("%s: fromC %s, used %llu, size %llu, offset %llu\n",
126 msg, ce->fromC ? "True" : "False",
127 (ULong)ce->used, (ULong)ce->size, (ULong)ce->off);
128 }
129
is_sane_CEnt(const HChar * who,const DiImage * img,UInt i)130 static Bool is_sane_CEnt ( const HChar* who, const DiImage* img, UInt i )
131 {
132 vg_assert(img);
133 vg_assert(i <= CACHE_N_ENTRIES);
134
135 CEnt* ce = img->ces[i];
136 if (!(ce->used <= ce->size)) goto fail;
137 if (ce->fromC) {
138 // ce->size can be anything, but ce->used must be either the
139 // same or zero, in the case that it hasn't been set yet.
140 // Similarly, ce->off must either be above the real_size
141 // threshold, or zero if it hasn't been set yet.
142 if (!(ce->off >= img->real_size || ce->off == 0)) goto fail;
143 if (!(ce->off + ce->used <= img->size)) goto fail;
144 if (!(ce->used == ce->size || ce->used == 0)) goto fail;
145 } else {
146 if (!(ce->size == CACHE_ENTRY_SIZE)) goto fail;
147 if (!(ce->off >= 0)) goto fail;
148 if (!(ce->off + ce->used <= img->real_size)) goto fail;
149 }
150 return True;
151
152 fail:
153 VG_(printf)("is_sane_CEnt[%u]: fail: %s\n", i, who);
154 pp_CEnt("failing CEnt", ce);
155 return False;
156 }
157
158
159 /* A frame. The first 4 bytes of |data| give the kind of the frame,
160 and the rest of it is kind-specific data. */
161 typedef struct { UChar* data; SizeT n_data; } Frame;
162
write_UInt_le(UChar * dst,UInt n)163 static void write_UInt_le ( /*OUT*/UChar* dst, UInt n )
164 {
165 Int i;
166 for (i = 0; i <= 3; i++) {
167 dst[i] = (UChar)(n & 0xFF);
168 n >>= 8;
169 }
170 }
171
read_UInt_le(const UChar * src)172 static UInt read_UInt_le ( const UChar* src )
173 {
174 UInt r = 0;
175 Int i;
176 for (i = 3; i >= 0; i--) {
177 r <<= 8;
178 r += (UInt)src[i];
179 }
180 return r;
181 }
182
write_ULong_le(UChar * dst,ULong n)183 static void write_ULong_le ( /*OUT*/UChar* dst, ULong n )
184 {
185 Int i;
186 for (i = 0; i <= 7; i++) {
187 dst[i] = (UChar)(n & 0xFF);
188 n >>= 8;
189 }
190 }
191
read_ULong_le(const UChar * src)192 static ULong read_ULong_le ( const UChar* src )
193 {
194 ULong r = 0;
195 Int i;
196 for (i = 7; i >= 0; i--) {
197 r <<= 8;
198 r += (ULong)src[i];
199 }
200 return r;
201 }
202
203
204 /* Set |sd| to be blocking. Returns True on success. */
set_blocking(int sd)205 static Bool set_blocking ( int sd )
206 {
207 Int res;
208 res = VG_(fcntl)(sd, VKI_F_GETFL, 0/*ignored*/);
209 if (res != -1)
210 res = VG_(fcntl)(sd, VKI_F_SETFL, res & ~VKI_O_NONBLOCK);
211 return (res != -1);
212 }
213
214 /* Tries to read 'len' bytes from fd, blocking if necessary. Assumes
215 fd has been set in blocking mode. If it returns with the number of
216 bytes read < len, it means that either fd was closed, or there was
217 an error on it. */
my_read(Int fd,UChar * buf,Int len)218 static Int my_read ( Int fd, UChar* buf, Int len )
219 {
220 Int nRead = 0;
221 while (1) {
222 if (nRead == len) return nRead;
223 vg_assert(nRead < len);
224 Int nNeeded = len - nRead;
225 vg_assert(nNeeded > 0);
226 Int n = VG_(read)(fd, &buf[nRead], nNeeded);
227 if (n <= 0) return nRead; /* error or EOF */
228 nRead += n;
229 }
230 }
231
232 /* Tries to write 'len' bytes to fd, blocking if necessary. Assumes
233 fd has been set in blocking mode. If it returns with the number of
234 bytes written < len, it means that either fd was closed, or there was
235 an error on it. */
my_write(Int fd,const UChar * buf,Int len)236 static Int my_write ( Int fd, const UChar* buf, Int len )
237 {
238 Int nWritten = 0;
239 while (1) {
240 if (nWritten == len) return nWritten;
241 vg_assert(nWritten < len);
242 Int nStillToDo = len - nWritten;
243 vg_assert(nStillToDo > 0);
244 Int n = VG_(write_socket)(fd, &buf[nWritten], nStillToDo);
245 if (n < 0) return nWritten; /* error or EOF */
246 nWritten += n;
247 }
248 }
249
250 /* If we lost communication with the remote server, just give up.
251 Recovering is too difficult. */
give_up__comms_lost(void)252 static void give_up__comms_lost(void)
253 {
254 VG_(umsg)("\n");
255 VG_(umsg)(
256 "Valgrind: debuginfo reader: Lost communication with the remote\n");
257 VG_(umsg)(
258 "Valgrind: debuginfo server. I can't recover. Giving up. Sorry.\n");
259 VG_(umsg)("\n");
260 VG_(exit)(1);
261 /*NOTREACHED*/
262 }
263
give_up__image_overrun(void)264 static void give_up__image_overrun(void)
265 {
266 VG_(umsg)("\n");
267 VG_(umsg)(
268 "Valgrind: debuginfo reader: Possibly corrupted debuginfo file.\n");
269 VG_(umsg)(
270 "Valgrind: I can't recover. Giving up. Sorry.\n");
271 VG_(umsg)("\n");
272 VG_(exit)(1);
273 /*NOTREACHED*/
274 }
275
276 /* "Do" a transaction: that is, send the given frame to the server and
277 return the frame it sends back. Caller owns the resulting frame
278 and must free it. A NULL return means the transaction failed for
279 some reason. */
do_transaction(Int sd,const Frame * req)280 static Frame* do_transaction ( Int sd, const Frame* req )
281 {
282 if (0) VG_(printf)("CLIENT: send %c%c%c%c\n",
283 req->data[0], req->data[1], req->data[2], req->data[3]);
284
285 /* What goes on the wire is:
286 adler(le32) n_data(le32) data[0 .. n_data-1]
287 where the checksum covers n_data as well as data[].
288 */
289 /* The initial Adler-32 value */
290 UInt adler = VG_(adler32)(0, NULL, 0);
291
292 /* Fold in the length field, encoded as le32. */
293 UChar wr_first8[8];
294 write_UInt_le(&wr_first8[4], req->n_data);
295 adler = VG_(adler32)(adler, &wr_first8[4], 4);
296 /* Fold in the data values */
297 adler = VG_(adler32)(adler, req->data, req->n_data);
298 write_UInt_le(&wr_first8[0], adler);
299
300 Int r = my_write(sd, &wr_first8[0], 8);
301 if (r != 8) return NULL;
302 vg_assert(req->n_data >= 4); // else ill formed -- no KIND field
303 r = my_write(sd, req->data, req->n_data);
304 if (r != req->n_data) return NULL;
305
306 /* So, the request is sent. Now get a request of the same format
307 out of the channel. */
308 UChar rd_first8[8]; // adler32; length32
309 r = my_read(sd, &rd_first8[0], 8);
310 if (r != 8) return NULL;
311 UInt rd_adler = read_UInt_le(&rd_first8[0]);
312 UInt rd_len = read_UInt_le(&rd_first8[4]);
313 /* Allocate a Frame to hold the result data, and read into it. */
314 // Reject obviously-insane length fields.
315 if (rd_len < 4 || rd_len > 4*1024*1024) return NULL;
316 Frame* res = ML_(dinfo_zalloc)("di.do_transaction.1", sizeof(Frame));
317 res->n_data = rd_len;
318 res->data = ML_(dinfo_zalloc)("di.do_transaction.2", rd_len);
319 r = my_read(sd, res->data, res->n_data);
320 if (r != rd_len) return NULL;
321
322 if (0) VG_(printf)("CLIENT: recv %c%c%c%c\n",
323 res->data[0], res->data[1], res->data[2], res->data[3]);
324
325 /* Compute the checksum for the received data, and check it. */
326 adler = VG_(adler32)(0, NULL, 0); // initial value
327 adler = VG_(adler32)(adler, &rd_first8[4], 4);
328 if (res->n_data > 0)
329 adler = VG_(adler32)(adler, res->data, res->n_data);
330
331 if (adler/*computed*/ != rd_adler/*expected*/) return NULL;
332 return res;
333 }
334
free_Frame(Frame * fr)335 static void free_Frame ( Frame* fr )
336 {
337 vg_assert(fr && fr->data);
338 ML_(dinfo_free)(fr->data);
339 ML_(dinfo_free)(fr);
340 }
341
mk_Frame_noargs(const HChar * tag)342 static Frame* mk_Frame_noargs ( const HChar* tag )
343 {
344 vg_assert(VG_(strlen)(tag) == 4);
345 Frame* f = ML_(dinfo_zalloc)("di.mFn.1", sizeof(Frame));
346 f->n_data = 4;
347 f->data = ML_(dinfo_zalloc)("di.mFn.2", f->n_data);
348 VG_(memcpy)(&f->data[0], tag, 4);
349 return f;
350 }
351
mk_Frame_le64_le64_le64(const HChar * tag,ULong n1,ULong n2,ULong n3)352 static Frame* mk_Frame_le64_le64_le64 ( const HChar* tag,
353 ULong n1, ULong n2, ULong n3 )
354 {
355 vg_assert(VG_(strlen)(tag) == 4);
356 Frame* f = ML_(dinfo_zalloc)("di.mFlll.1", sizeof(Frame));
357 f->n_data = 4 + 3*8;
358 f->data = ML_(dinfo_zalloc)("di.mFlll.2", f->n_data);
359 VG_(memcpy)(&f->data[0], tag, 4);
360 write_ULong_le(&f->data[4 + 0*8], n1);
361 write_ULong_le(&f->data[4 + 1*8], n2);
362 write_ULong_le(&f->data[4 + 2*8], n3);
363 return f;
364 }
365
mk_Frame_asciiz(const HChar * tag,const HChar * str)366 static Frame* mk_Frame_asciiz ( const HChar* tag, const HChar* str )
367 {
368 vg_assert(VG_(strlen)(tag) == 4);
369 Frame* f = ML_(dinfo_zalloc)("di.mFa.1", sizeof(Frame));
370 SizeT n_str = VG_(strlen)(str);
371 f->n_data = 4 + n_str + 1;
372 f->data = ML_(dinfo_zalloc)("di.mFa.2", f->n_data);
373 VG_(memcpy)(&f->data[0], tag, 4);
374 VG_(memcpy)(&f->data[4], str, n_str);
375 vg_assert(f->data[4 + n_str] == 0);
376 return f;
377 }
378
parse_Frame_le64(const Frame * fr,const HChar * tag,ULong * n1)379 static Bool parse_Frame_le64 ( const Frame* fr, const HChar* tag,
380 /*OUT*/ULong* n1 )
381 {
382 vg_assert(VG_(strlen)(tag) == 4);
383 if (!fr || !fr->data) return False;
384 if (fr->n_data < 4) return False;
385 if (VG_(memcmp)(&fr->data[0], tag, 4) != 0) return False;
386 if (fr->n_data != 4 + 1*8) return False;
387 *n1 = read_ULong_le(&fr->data[4 + 0*8]);
388 return True;
389 }
390
parse_Frame_le64_le64(const Frame * fr,const HChar * tag,ULong * n1,ULong * n2)391 static Bool parse_Frame_le64_le64 ( const Frame* fr, const HChar* tag,
392 /*OUT*/ULong* n1, /*OUT*/ULong* n2 )
393 {
394 vg_assert(VG_(strlen)(tag) == 4);
395 if (!fr || !fr->data) return False;
396 if (fr->n_data < 4) return False;
397 if (VG_(memcmp)(&fr->data[0], tag, 4) != 0) return False;
398 if (fr->n_data != 4 + 2*8) return False;
399 *n1 = read_ULong_le(&fr->data[4 + 0*8]);
400 *n2 = read_ULong_le(&fr->data[4 + 1*8]);
401 return True;
402 }
403
parse_Frame_asciiz(const Frame * fr,const HChar * tag,UChar ** str)404 static Bool parse_Frame_asciiz ( const Frame* fr, const HChar* tag,
405 /*OUT*/UChar** str )
406 {
407 vg_assert(VG_(strlen)(tag) == 4);
408 if (!fr || !fr->data) return False;
409 if (fr->n_data < 4) return False;
410 if (VG_(memcmp)(&fr->data[0], tag, 4) != 0) return False;
411 if (fr->n_data < 5) return False; // else there isn't even enough
412 // space for the terminating zero
413 /* Find the terminating zero and ensure it's right at the end
414 of the data. If not, the frame is malformed. */
415 SizeT i = 4;
416 while (True) {
417 if (i >= fr->n_data) break;
418 if (fr->data[i] == 0) break;
419 i++;
420 }
421 vg_assert(i <= fr->n_data);
422 if (i == fr->n_data-1 && fr->data[i] == 0) {
423 *str = &fr->data[4];
424 return True;
425 } else {
426 return False;
427 }
428 }
429
parse_Frame_le64_le64_le64_bytes(const Frame * fr,const HChar * tag,ULong * n1,ULong * n2,ULong * n3,UChar ** data,ULong * n_data)430 static Bool parse_Frame_le64_le64_le64_bytes (
431 const Frame* fr, const HChar* tag,
432 /*OUT*/ULong* n1, /*OUT*/ULong* n2, /*OUT*/ULong* n3,
433 /*OUT*/UChar** data, /*OUT*/ULong* n_data
434 )
435 {
436 vg_assert(VG_(strlen)(tag) == 4);
437 if (!fr || !fr->data) return False;
438 if (fr->n_data < 4) return False;
439 if (VG_(memcmp)(&fr->data[0], tag, 4) != 0) return False;
440 if (fr->n_data < 4 + 3*8) return False;
441 *n1 = read_ULong_le(&fr->data[4 + 0*8]);
442 *n2 = read_ULong_le(&fr->data[4 + 1*8]);
443 *n3 = read_ULong_le(&fr->data[4 + 2*8]);
444 *data = &fr->data[4 + 3*8];
445 *n_data = fr->n_data - (4 + 3*8);
446 vg_assert(fr->n_data >= 4 + 3*8);
447 return True;
448 }
449
block_round_down(DiOffT i)450 static DiOffT block_round_down ( DiOffT i )
451 {
452 return i & ((DiOffT)~(CACHE_ENTRY_SIZE-1));
453 }
454
455 /* Is this offset inside this CEnt? */
is_in_CEnt(const CEnt * cent,DiOffT off)456 static inline Bool is_in_CEnt ( const CEnt* cent, DiOffT off )
457 {
458 /* This assertion is checked by set_CEnt, so checking it here has
459 no benefit, whereas skipping it does remove it from the hottest
460 path. */
461 /* vg_assert(cent->used > 0 && cent->used <= cent->size); */
462 /* What we want to return is:
463 cent->off <= off && off < cent->off + cent->used;
464 This is however a very hot path, so here's alternative that uses
465 only one conditional branch, using the following transformation,
466 where all quantities are unsigned:
467 x >= LO && x < LO+N
468 --> x-LO >= 0 && x-LO < LO+N-LO
469 --> x-LO >= 0 && x-LO < N
470 --> x-LO < N
471 This is however only valid when the original bounds, that is, LO
472 .. LO+N-1, do not wrap around the end of the address space. That
473 is, we require that LO <= LO+N-1. But that's OK .. we don't
474 expect wraparounds in CEnts or for that matter any object
475 allocated from C-land. See Hacker's Delight, Chapter 4.1,
476 "Checking Bounds of Integers", for more details.
477 */
478 return off - cent->off < cent->used;
479 }
480
481 /* Returns pointer to CSlc or NULL */
find_cslc(DiImage * img,DiOffT off)482 static inline CSlc* find_cslc ( DiImage* img, DiOffT off )
483 {
484 for (UInt i = 0; i < img->cslc_used; i++) {
485 if ( (img->cslc[i].offD <= off)
486 && (img->cslc[i].offD + img->cslc[i].szD > off)
487 )
488 return &img->cslc[i];
489 }
490 return NULL;
491 }
492
493 /* Allocate a new CEnt, connect it to |img|, and return its index. */
alloc_CEnt(DiImage * img,SizeT szB,Bool fromC)494 static UInt alloc_CEnt ( DiImage* img, SizeT szB, Bool fromC )
495 {
496 vg_assert(img != NULL);
497 vg_assert(img->ces_used < CACHE_N_ENTRIES);
498 if (fromC) {
499 // szB can be arbitrary
500 } else {
501 vg_assert(szB == CACHE_ENTRY_SIZE);
502 }
503 UInt entNo = img->ces_used;
504 img->ces_used++;
505 vg_assert(img->ces[entNo] == NULL);
506 img->ces[entNo] = ML_(dinfo_zalloc)("di.alloc_CEnt.1",
507 offsetof(CEnt, data) + szB);
508 img->ces[entNo]->size = szB;
509 img->ces[entNo]->fromC = fromC;
510 vg_assert(is_sane_CEnt("alloc_CEnt", img, entNo));
511 return entNo;
512 }
513
realloc_CEnt(DiImage * img,UInt entNo,SizeT szB)514 static void realloc_CEnt ( DiImage* img, UInt entNo, SizeT szB )
515 {
516 vg_assert(img != NULL);
517 vg_assert(szB >= CACHE_ENTRY_SIZE);
518 vg_assert(is_sane_CEnt("realloc_CEnt-pre", img, entNo));
519 img->ces[entNo] = ML_(dinfo_realloc)("di.realloc_CEnt.1",
520 img->ces[entNo],
521 offsetof(CEnt, data) + szB);
522 }
523
524 /* Move the given entry to the top and slide those above it down by 1,
525 to make space. */
move_CEnt_to_top(DiImage * img,UInt entNo)526 static void move_CEnt_to_top ( DiImage* img, UInt entNo )
527 {
528 vg_assert(img->ces_used <= CACHE_N_ENTRIES);
529 vg_assert(entNo > 0 && entNo < img->ces_used);
530 CEnt* tmp = img->ces[entNo];
531 while (entNo > 0) {
532 img->ces[entNo] = img->ces[entNo-1];
533 entNo--;
534 }
535 img->ces[0] = tmp;
536 }
537
538 /* Set the given entry so that it has a chunk of the file containing
539 the given offset. It is this function that brings data into the
540 cache, either by reading the local file or pulling it from the
541 remote server. */
set_CEnt(const DiImage * img,UInt entNo,DiOffT off)542 static void set_CEnt ( const DiImage* img, UInt entNo, DiOffT off )
543 {
544 SizeT len;
545 DiOffT off_orig = off;
546 vg_assert(img != NULL);
547 vg_assert(img->ces_used <= CACHE_N_ENTRIES);
548 vg_assert(entNo >= 0 && entNo < img->ces_used);
549 vg_assert(off < img->real_size);
550 CEnt* ce = img->ces[entNo];
551 vg_assert(ce != NULL);
552 /* Compute [off, +len) as the slice we are going to read. */
553 off = block_round_down(off);
554 len = img->real_size - off;
555 if (len > ce->size)
556 len = ce->size;
557 /* It is conceivable that the 'len > 0' bit could fail if we make
558 an image with a zero sized file. But then no 'get' request on
559 that image would be valid. */
560 vg_assert(len > 0 && len <= ce->size);
561 vg_assert(off + len <= img->real_size);
562 vg_assert(off <= off_orig && off_orig < off+len);
563 /* So, read off .. off+len-1 into the entry. */
564
565 if (0) {
566 static UInt t_last = 0;
567 static ULong nread = 0;
568 UInt now = VG_(read_millisecond_timer)();
569 UInt delay = now - t_last;
570 t_last = now;
571 nread += len;
572 VG_(printf)("XXXXXXXX (tot %'llu) read %'lu offset %'llu delay %'u\n",
573 nread, len, off, delay);
574 }
575
576 if (img->source.is_local) {
577 // Simple: just read it
578 SysRes sr = VG_(pread)(img->source.fd, &ce->data[0], (Int)len, off);
579 vg_assert(!sr_isError(sr));
580 } else {
581 // Not so simple: poke the server
582 vg_assert(img->source.session_id > 0);
583 Frame* req
584 = mk_Frame_le64_le64_le64("READ", img->source.session_id, off, len);
585 Frame* res = do_transaction(img->source.fd, req);
586 free_Frame(req); req = NULL;
587 if (!res) goto server_fail;
588 ULong rx_session_id = 0, rx_off = 0, rx_len = 0, rx_zdata_len = 0;
589 UChar* rx_data = NULL;
590 /* Pretty confusing. rx_sessionid, rx_off and rx_len are copies
591 of the values that we requested in the READ frame just above,
592 so we can be sure that the server is responding to the right
593 request. It just copies them from the request into the
594 response. rx_data is the actual data, and rx_zdata_len is
595 its compressed length. Hence rx_len must equal len, but
596 rx_zdata_len can be different -- smaller, hopefully.. */
597 if (!parse_Frame_le64_le64_le64_bytes
598 (res, "RDOK", &rx_session_id, &rx_off,
599 &rx_len, &rx_data, &rx_zdata_len))
600 goto server_fail;
601 if (rx_session_id != img->source.session_id
602 || rx_off != off || rx_len != len || rx_data == NULL)
603 goto server_fail;
604
605 //VG_(memcpy)(&ce->data[0], rx_data, len);
606 // Decompress into the destination buffer
607 // Tell the lib the max number of output bytes it can write.
608 // After the call, this holds the number of bytes actually written,
609 // and it's an error if it is different.
610 lzo_uint out_len = len;
611 Int lzo_rc = lzo1x_decompress_safe(rx_data, rx_zdata_len,
612 &ce->data[0], &out_len,
613 NULL);
614 Bool ok = lzo_rc == LZO_E_OK && out_len == len;
615 if (!ok) goto server_fail;
616
617 free_Frame(res); res = NULL;
618 goto end_of_else_clause;
619 server_fail:
620 /* The server screwed up somehow. Now what? */
621 if (res) {
622 UChar* reason = NULL;
623 if (parse_Frame_asciiz(res, "FAIL", &reason)) {
624 VG_(umsg)("set_CEnt (reading data from DI server): fail: "
625 "%s\n", reason);
626 } else {
627 VG_(umsg)("set_CEnt (reading data from DI server): fail: "
628 "unknown reason\n");
629 }
630 free_Frame(res); res = NULL;
631 } else {
632 VG_(umsg)("set_CEnt (reading data from DI server): fail: "
633 "server unexpectedly closed the connection\n");
634 }
635 give_up__comms_lost();
636 /* NOTREACHED */
637 vg_assert(0);
638 end_of_else_clause:
639 {}
640 }
641
642 ce->off = off;
643 ce->used = len;
644 ce->fromC = False;
645 vg_assert(ce == img->ces[entNo]);
646 vg_assert(is_sane_CEnt("set_CEnt", img, entNo));
647 }
648
649 __attribute__((noinline))
get_slowcase(DiImage * img,DiOffT off)650 static UChar get_slowcase ( DiImage* img, DiOffT off )
651 {
652 /* Stay sane .. */
653 vg_assert(off < img->size);
654 vg_assert(img->ces_used <= CACHE_N_ENTRIES);
655 UInt i;
656 /* Start the search at entry 1, since the fast-case function
657 checked slot zero already. */
658 for (i = 1; i < img->ces_used; i++) {
659 vg_assert(img->ces[i]);
660 if (is_in_CEnt(img->ces[i], off))
661 break;
662 }
663 vg_assert(i >= 1);
664
665 if (LIKELY(i < img->ces_used)) {
666 // Found it. Move to the top and stop.
667 move_CEnt_to_top(img, i);
668 vg_assert(is_in_CEnt(img->ces[0], off));
669 return img->ces[0]->data[ off - img->ces[0]->off ];
670 }
671
672 vg_assert(i <= img->ces_used);
673
674 // It's not in any entry. Either allocate a new one or recycle the LRU
675 // one. This is where the presence of compressed sections makes things
676 // tricky. There are 4 cases to consider:
677 //
678 // (1) not from a compressed slice, we can allocate a new entry
679 // (2) not from a compressed slice, we have to recycle the LRU entry
680 // (3) from a compressed slice, we can allocate a new entry
681 // (4) from a compressed slice, we have to recycle the LRU entry
682 //
683 // Cases (3) and (4) are complex because we will have to call
684 // ML_(img_get_some) to get the compressed data. But this function is
685 // reachable from ML_(img_get_some), so we may re-enter get_slowcase a
686 // second time as a result. Given that the compressed data will be cause
687 // only cases (1) and (2) to happen, this guarantees no infinite recursion.
688 // It does however mean that we can't carry (in this function invokation)
689 // any local copies of the overall cache state across the ML_(img_get_some)
690 // call, since it may become invalidated by the recursive call to
691 // get_slowcase.
692
693 // First of all, see if it is in a compressed slice, and if so, pull the
694 // compressed data into an intermediate buffer. Given the preceding
695 // comment, this is a safe place to do it, since we are not carrying any
696 // cache state here apart from the knowledge that the requested offset is
697 // not in the cache at all, and the recursive call won't change that fact.
698
699 CSlc* cslc = find_cslc(img, off);
700 UChar* cbuf = NULL;
701 if (cslc != NULL) {
702 SizeT len = 0;
703 cbuf = ML_(dinfo_zalloc)("di.image.get_slowcase.cbuf-1", cslc->szC);
704 // get compressed data
705 while (len < cslc->szC)
706 len += ML_(img_get_some)(cbuf + len, img, cslc->offC + len,
707 cslc->szC - len);
708 }
709
710 // Now we can do what we like.
711 vg_assert((cslc == NULL && cbuf == NULL) || (cslc != NULL && cbuf != NULL));
712
713 // Note, we can't capture this earlier, for exactly the reasons detailed
714 // above.
715 UInt ces_used_at_entry = img->ces_used;
716
717 // This is the size of the CEnt that we want to have after allocation or
718 // recycling.
719 SizeT size = (cslc == NULL) ? CACHE_ENTRY_SIZE : cslc->szD;
720
721 // Cases (1) and (3)
722 if (img->ces_used < CACHE_N_ENTRIES) {
723 /* Allocate a new cache entry, and fill it in. */
724 i = alloc_CEnt(img, size, /*fromC?*/cslc != NULL);
725 if (cslc == NULL) {
726 set_CEnt(img, i, off);
727 img->ces[i]->fromC = False;
728 vg_assert(is_sane_CEnt("get_slowcase-case-1", img, i));
729 vg_assert(img->ces_used == ces_used_at_entry + 1);
730 } else {
731 SizeT len = tinfl_decompress_mem_to_mem(
732 img->ces[i]->data, cslc->szD,
733 cbuf, cslc->szC,
734 TINFL_FLAG_USING_NON_WRAPPING_OUTPUT_BUF
735 | TINFL_FLAG_PARSE_ZLIB_HEADER);
736 vg_assert(len == cslc->szD); // sanity check on data, FIXME
737 vg_assert(cslc->szD == size);
738 img->ces[i]->used = cslc->szD;
739 img->ces[i]->off = cslc->offD;
740 img->ces[i]->fromC = True;
741 vg_assert(is_sane_CEnt("get_slowcase-case-3", img, i));
742 vg_assert(img->ces_used == ces_used_at_entry + 1);
743 }
744 vg_assert(img->ces_used == ces_used_at_entry + 1);
745 if (i > 0) {
746 move_CEnt_to_top(img, i);
747 i = 0;
748 }
749 vg_assert(is_in_CEnt(img->ces[i], off));
750 if (cbuf != NULL) {
751 ML_(dinfo_free)(cbuf);
752 }
753 return img->ces[i]->data[ off - img->ces[i]->off ];
754 }
755
756 // Cases (2) and (4)
757 /* All entries in use. Recycle the (ostensibly) LRU one. But try to find
758 a non-fromC entry to recycle, though, since discarding and reloading
759 fromC entries is very expensive. The result is that -- unless all
760 CACHE_N_ENTRIES wind up being used by decompressed slices, which is
761 highly unlikely -- we'll wind up keeping all the decompressed data in
762 the cache for its entire remaining life. We could probably do better
763 but it would make the cache management even more complex. */
764 vg_assert(img->ces_used == CACHE_N_ENTRIES);
765
766 // Select entry to recycle.
767 for (i = CACHE_N_ENTRIES-1; i > 0; i--) {
768 if (!img->ces[i]->fromC)
769 break;
770 }
771 vg_assert(i >= 0 && i < CACHE_N_ENTRIES);
772
773 realloc_CEnt(img, i, size);
774 img->ces[i]->size = size;
775 img->ces[i]->used = 0;
776 if (cslc == NULL) {
777 set_CEnt(img, i, off);
778 img->ces[i]->fromC = False;
779 vg_assert(is_sane_CEnt("get_slowcase-case-2", img, i));
780 } else {
781 SizeT len = tinfl_decompress_mem_to_mem(
782 img->ces[i]->data, cslc->szD,
783 cbuf, cslc->szC,
784 TINFL_FLAG_USING_NON_WRAPPING_OUTPUT_BUF
785 | TINFL_FLAG_PARSE_ZLIB_HEADER);
786 vg_assert(len == size);
787 img->ces[i]->used = size;
788 img->ces[i]->off = cslc->offD;
789 img->ces[i]->fromC = True;
790 vg_assert(is_sane_CEnt("get_slowcase-case-4", img, i));
791 }
792 vg_assert(img->ces_used == ces_used_at_entry);
793 if (i > 0) {
794 move_CEnt_to_top(img, i);
795 i = 0;
796 }
797 vg_assert(is_in_CEnt(img->ces[i], off));
798 if (cbuf != NULL) {
799 ML_(dinfo_free)(cbuf);
800 }
801 return img->ces[i]->data[ off - img->ces[i]->off ];
802 }
803
804 // This is called a lot, so do the usual fast/slow split stuff on it. */
get(DiImage * img,DiOffT off)805 static inline UChar get ( DiImage* img, DiOffT off )
806 {
807 /* Most likely case is, it's in the ces[0] position. */
808 /* ML_(img_from_local_file) requests a read for ces[0] when
809 creating the image. Hence slot zero is always non-NULL, so we
810 can skip this test. */
811 if (LIKELY(/* img->ces[0] != NULL && */
812 is_in_CEnt(img->ces[0], off))) {
813 return img->ces[0]->data[ off - img->ces[0]->off ];
814 }
815 /* Else we'll have to fish around for it. */
816 return get_slowcase(img, off);
817 }
818
819 /* Create an image from a file in the local filesystem. This is
820 relatively straightforward. */
ML_(img_from_local_file)821 DiImage* ML_(img_from_local_file)(const HChar* fullpath)
822 {
823 SysRes fd;
824 struct vg_stat stat_buf;
825 DiOffT size;
826
827 fd = VG_(open)(fullpath, VKI_O_RDONLY, 0);
828 if (sr_isError(fd))
829 return NULL;
830
831 if (VG_(fstat)(sr_Res(fd), &stat_buf) != 0) {
832 VG_(close)(sr_Res(fd));
833 return NULL;
834 }
835
836 size = stat_buf.size;
837 if (size == 0 || size == DiOffT_INVALID
838 || /* size is unrepresentable as a SizeT */
839 size != (DiOffT)(SizeT)(size)) {
840 VG_(close)(sr_Res(fd));
841 return NULL;
842 }
843
844 DiImage* img = ML_(dinfo_zalloc)("di.image.ML_iflf.1", sizeof(DiImage));
845 img->source.is_local = True;
846 img->source.fd = sr_Res(fd);
847 img->size = size;
848 img->real_size = size;
849 img->ces_used = 0;
850 img->source.name = ML_(dinfo_strdup)("di.image.ML_iflf.2", fullpath);
851 img->cslc = NULL;
852 img->cslc_size = 0;
853 img->cslc_used = 0;
854 /* img->ces is already zeroed out */
855 vg_assert(img->source.fd >= 0);
856
857 /* Force the zeroth entry to be the first chunk of the file.
858 That's likely to be the first part that's requested anyway, and
859 loading it at this point forcing img->cent[0] to always be
860 non-empty, thereby saving us an is-it-empty check on the fast
861 path in get(). */
862 UInt entNo = alloc_CEnt(img, CACHE_ENTRY_SIZE, False/*!fromC*/);
863 vg_assert(entNo == 0);
864 set_CEnt(img, 0, 0);
865
866 return img;
867 }
868
869
870 /* Create an image from a file on a remote debuginfo server. This is
871 more complex. There are lots of ways in which it can fail. */
ML_(img_from_di_server)872 DiImage* ML_(img_from_di_server)(const HChar* filename,
873 const HChar* serverAddr)
874 {
875 if (filename == NULL || serverAddr == NULL)
876 return NULL;
877
878 /* The filename must be a plain filename -- no slashes at all. */
879 if (VG_(strchr)(filename, '/') != NULL)
880 return NULL;
881
882 /* Try to connect to the server. A side effect of this is to parse
883 and reject, if syntactically invalid, |serverAddr|. Reasons why
884 this could fail:
885 - serverAddr is not of the form d.d.d.d:d or d.d.d.d
886 - attempt to connect to that address:port failed
887 */
888 Int sd = VG_(connect_via_socket)(serverAddr);
889 if (sd < 0)
890 return NULL;
891 if (!set_blocking(sd))
892 return NULL;
893 Int one = 1;
894 Int sr = VG_(setsockopt)(sd, VKI_IPPROTO_TCP, VKI_TCP_NODELAY,
895 &one, sizeof(one));
896 vg_assert(sr == 0);
897
898 /* Ok, we got a connection. Ask it for version string, so as to be
899 reasonably sure we're talking to an instance of
900 auxprogs/valgrind-di-server and not to some other random program
901 that happens to be listening on that port. */
902 Frame* req = mk_Frame_noargs("VERS");
903 Frame* res = do_transaction(sd, req);
904 if (res == NULL)
905 goto fail; // do_transaction failed?!
906 UChar* vstr = NULL;
907 if (!parse_Frame_asciiz(res, "VEOK", &vstr))
908 goto fail; // unexpected response kind, or invalid ID string
909 vg_assert(vstr);
910 if (VG_(strcmp)("Valgrind Debuginfo Server, Version 1",
911 (const HChar*)vstr) != 0)
912 goto fail; // wrong version string
913 free_Frame(req);
914 free_Frame(res);
915 req = NULL;
916 res = NULL;
917
918 /* Server seems plausible. Present it with the name of the file we
919 want and see if it'll give us back a session ID for it. */
920 req = mk_Frame_asciiz("OPEN", filename);
921 res = do_transaction(sd, req);
922 if (res == NULL)
923 goto fail;
924 ULong session_id = 0, size = 0;
925 if (!parse_Frame_le64_le64(res, "OPOK", &session_id, &size))
926 goto fail;
927 free_Frame(req);
928 free_Frame(res);
929 req = NULL;
930 res = NULL;
931
932 /* We have a session ID. We're ready to roll. */
933 DiImage* img = ML_(dinfo_zalloc)("di.image.ML_ifds.1", sizeof(DiImage));
934 img->source.is_local = False;
935 img->source.fd = sd;
936 img->source.session_id = session_id;
937 img->size = size;
938 img->real_size = size;
939 img->ces_used = 0;
940 img->source.name = ML_(dinfo_zalloc)("di.image.ML_ifds.2",
941 20 + VG_(strlen)(filename)
942 + VG_(strlen)(serverAddr));
943 VG_(sprintf)(img->source.name, "%s at %s", filename, serverAddr);
944 img->cslc = NULL;
945 img->cslc_size = 0;
946 img->cslc_used = 0;
947
948 /* img->ces is already zeroed out */
949 vg_assert(img->source.fd >= 0);
950
951 /* See comment on equivalent bit in ML_(img_from_local_file) for
952 rationale. */
953 UInt entNo = alloc_CEnt(img, CACHE_ENTRY_SIZE, False/*!fromC*/);
954 vg_assert(entNo == 0);
955 set_CEnt(img, 0, 0);
956
957 return img;
958
959 fail:
960 free_Frame(req);
961 if (res) {
962 UChar* reason = NULL;
963 if (parse_Frame_asciiz(res, "FAIL", &reason)) {
964 // HACK: if it's just telling us that the file can't
965 // be opened, don't print it, else we'll get flooded with
966 // such complaints, one for each main object for which there
967 // isn't a debuginfo file on the server.
968 if (0 != VG_(strcmp)((const HChar*)reason, "OPEN: cannot open file"))
969 VG_(umsg)("ML_(img_from_di_server): fail: %s\n", reason);
970 } else {
971 VG_(umsg)("ML_(img_from_di_server): fail: unknown reason\n");
972 }
973 free_Frame(res);
974 }
975 VG_(close)(sd);
976 return NULL;
977 }
978
ML_(img_mark_compressed_part)979 DiOffT ML_(img_mark_compressed_part)(DiImage* img, DiOffT offset, SizeT szC,
980 SizeT szD)
981 {
982 DiOffT ret;
983 vg_assert(img != NULL);
984 vg_assert(offset + szC <= img->size);
985
986 if (img->cslc_used == img->cslc_size) {
987 img->cslc_size += COMPRESSED_SLICE_ARRAY_GROW_SIZE;
988 img->cslc = ML_(dinfo_realloc)("di.image.ML_img_mark_compressed_part.1",
989 img->cslc, img->cslc_size * sizeof(CSlc));
990 }
991
992 ret = img->size;
993 img->cslc[img->cslc_used].offC = offset;
994 img->cslc[img->cslc_used].szC = szC;
995 img->cslc[img->cslc_used].offD = img->size;
996 img->cslc[img->cslc_used].szD = szD;
997 img->size += szD;
998 img->cslc_used++;
999 return ret;
1000 }
1001
ML_(img_done)1002 void ML_(img_done)(DiImage* img)
1003 {
1004 vg_assert(img != NULL);
1005 if (img->source.is_local) {
1006 /* Close the file; nothing else to do. */
1007 vg_assert(img->source.session_id == 0);
1008 VG_(close)(img->source.fd);
1009 } else {
1010 /* Close the socket. The server can detect this and will scrub
1011 the connection when it happens, so there's no need to tell it
1012 explicitly by sending it a "CLOSE" message, or any such. */
1013 vg_assert(img->source.session_id != 0);
1014 VG_(close)(img->source.fd);
1015 }
1016
1017 /* Free up the cache entries, ultimately |img| itself. */
1018 UInt i;
1019 vg_assert(img->ces_used <= CACHE_N_ENTRIES);
1020 for (i = 0; i < img->ces_used; i++) {
1021 ML_(dinfo_free)(img->ces[i]);
1022 }
1023 /* Take the opportunity to sanity check the rest. */
1024 for (i = i; i < img->ces_used; i++) {
1025 vg_assert(img->ces[i] == NULL);
1026 }
1027 ML_(dinfo_free)(img->source.name);
1028 ML_(dinfo_free)(img->cslc);
1029 ML_(dinfo_free)(img);
1030 }
1031
ML_(img_size)1032 DiOffT ML_(img_size)(const DiImage* img)
1033 {
1034 vg_assert(img != NULL);
1035 return img->size;
1036 }
1037
ML_(img_real_size)1038 DiOffT ML_(img_real_size)(const DiImage* img)
1039 {
1040 vg_assert(img != NULL);
1041 return img->real_size;
1042 }
1043
ML_(img_valid)1044 inline Bool ML_(img_valid)(const DiImage* img, DiOffT offset, SizeT size)
1045 {
1046 vg_assert(img != NULL);
1047 vg_assert(offset != DiOffT_INVALID);
1048 return img->size > 0 && offset + size <= (DiOffT)img->size;
1049 }
1050
1051 __attribute__((noinline))
ensure_valid_failed(const DiImage * img,DiOffT offset,SizeT size,const HChar * caller)1052 static void ensure_valid_failed (const DiImage* img, DiOffT offset, SizeT size,
1053 const HChar* caller)
1054 {
1055 VG_(umsg)("Valgrind: debuginfo reader: ensure_valid failed:\n");
1056 VG_(umsg)("Valgrind: during call to %s\n", caller);
1057 VG_(umsg)("Valgrind: request for range [%llu, +%lu) exceeds\n",
1058 offset, size);
1059 VG_(umsg)("Valgrind: valid image size of %lu for image:\n",
1060 img->size);
1061 VG_(umsg)("Valgrind: \"%s\"\n", img->source.name);
1062 give_up__image_overrun();
1063 }
1064
1065 /* Check the given range is valid, and if not, shut down the system.
1066 An invalid range would imply that we're trying to read outside the
1067 image, which normally means the image is corrupted somehow, or the
1068 caller is buggy. Recovering is too complex, and we have
1069 probably-corrupt debuginfo, so just give up. */
ensure_valid(const DiImage * img,DiOffT offset,SizeT size,const HChar * caller)1070 static void ensure_valid(const DiImage* img, DiOffT offset, SizeT size,
1071 const HChar* caller)
1072 {
1073 if (LIKELY(ML_(img_valid)(img, offset, size)))
1074 return;
1075 else
1076 ensure_valid_failed(img, offset, size, caller);
1077 }
1078
1079
ML_(img_get)1080 void ML_(img_get)(/*OUT*/void* dst,
1081 DiImage* img, DiOffT offset, SizeT size)
1082 {
1083 vg_assert(img != NULL);
1084 vg_assert(size > 0);
1085 ensure_valid(img, offset, size, "ML_(img_get)");
1086 SizeT i;
1087 for (i = 0; i < size; i++) {
1088 ((UChar*)dst)[i] = get(img, offset + i);
1089 }
1090 }
1091
ML_(img_get_some)1092 SizeT ML_(img_get_some)(/*OUT*/void* dst,
1093 DiImage* img, DiOffT offset, SizeT size)
1094 {
1095 vg_assert(img != NULL);
1096 vg_assert(size > 0);
1097 ensure_valid(img, offset, size, "ML_(img_get_some)");
1098 UChar* dstU = (UChar*)dst;
1099 /* Use |get| in the normal way to get the first byte of the range.
1100 This guarantees to put the cache entry containing |offset| in
1101 position zero. */
1102 dstU[0] = get(img, offset);
1103 /* Now just read as many bytes as we can (or need) directly out of
1104 entry zero, without bothering to call |get| each time. */
1105 const CEnt* ce = img->ces[0];
1106 vg_assert(ce && ce->used >= 1);
1107 vg_assert(is_in_CEnt(ce, offset));
1108 SizeT nToCopy = size - 1;
1109 SizeT nAvail = (SizeT)(ce->used - (offset + 1 - ce->off));
1110 vg_assert(nAvail >= 0 && nAvail <= ce->used-1);
1111 if (nAvail < nToCopy) nToCopy = nAvail;
1112 VG_(memcpy)(&dstU[1], &ce->data[offset + 1 - ce->off], nToCopy);
1113 return nToCopy + 1;
1114 }
1115
1116
ML_(img_strlen)1117 SizeT ML_(img_strlen)(DiImage* img, DiOffT off)
1118 {
1119 ensure_valid(img, off, 1, "ML_(img_strlen)");
1120 SizeT i = 0;
1121 while (get(img, off + i) != 0) i++;
1122 return i;
1123 }
1124
ML_(img_strdup)1125 HChar* ML_(img_strdup)(DiImage* img, const HChar* cc, DiOffT offset)
1126 {
1127 ensure_valid(img, offset, 1, "ML_(img_strdup)");
1128 SizeT len = ML_(img_strlen)(img, offset);
1129 HChar* res = ML_(dinfo_zalloc)(cc, len+1);
1130 SizeT i;
1131 for (i = 0; i < len; i++) {
1132 res[i] = get(img, offset+i);
1133 }
1134 vg_assert(res[len] == 0);
1135 return res;
1136 }
1137
ML_(img_strcmp)1138 Int ML_(img_strcmp)(DiImage* img, DiOffT off1, DiOffT off2)
1139 {
1140 ensure_valid(img, off1, 1, "ML_(img_strcmp)(first arg)");
1141 ensure_valid(img, off2, 1, "ML_(img_strcmp)(second arg)");
1142 while (True) {
1143 UChar c1 = get(img, off1);
1144 UChar c2 = get(img, off2);
1145 if (c1 < c2) return -1;
1146 if (c1 > c2) return 1;
1147 if (c1 == 0) return 0;
1148 off1++; off2++;
1149 }
1150 }
1151
ML_(img_strcmp_c)1152 Int ML_(img_strcmp_c)(DiImage* img, DiOffT off1, const HChar* str2)
1153 {
1154 ensure_valid(img, off1, 1, "ML_(img_strcmp_c)");
1155 while (True) {
1156 UChar c1 = get(img, off1);
1157 UChar c2 = *(const UChar*)str2;
1158 if (c1 < c2) return -1;
1159 if (c1 > c2) return 1;
1160 if (c1 == 0) return 0;
1161 off1++; str2++;
1162 }
1163 }
1164
ML_(img_get_UChar)1165 UChar ML_(img_get_UChar)(DiImage* img, DiOffT offset)
1166 {
1167 ensure_valid(img, offset, 1, "ML_(img_get_UChar)");
1168 return get(img, offset);
1169 }
1170
ML_(img_get_UShort)1171 UShort ML_(img_get_UShort)(DiImage* img, DiOffT offset)
1172 {
1173 UShort r;
1174 ML_(img_get)(&r, img, offset, sizeof(r));
1175 return r;
1176 }
1177
ML_(img_get_UInt)1178 UInt ML_(img_get_UInt)(DiImage* img, DiOffT offset)
1179 {
1180 UInt r;
1181 ML_(img_get)(&r, img, offset, sizeof(r));
1182 return r;
1183 }
1184
ML_(img_get_ULong)1185 ULong ML_(img_get_ULong)(DiImage* img, DiOffT offset)
1186 {
1187 ULong r;
1188 ML_(img_get)(&r, img, offset, sizeof(r));
1189 return r;
1190 }
1191
1192
1193 /*
1194 * This routine for calculating the CRC for a separate debug file
1195 * is GPLed code borrowed from GNU binutils.
1196 */
ML_(img_calc_gnu_debuglink_crc32)1197 UInt ML_(img_calc_gnu_debuglink_crc32)(DiImage* img)
1198 {
1199 static const UInt crc32_table[256] =
1200 {
1201 0x00000000, 0x77073096, 0xee0e612c, 0x990951ba, 0x076dc419,
1202 0x706af48f, 0xe963a535, 0x9e6495a3, 0x0edb8832, 0x79dcb8a4,
1203 0xe0d5e91e, 0x97d2d988, 0x09b64c2b, 0x7eb17cbd, 0xe7b82d07,
1204 0x90bf1d91, 0x1db71064, 0x6ab020f2, 0xf3b97148, 0x84be41de,
1205 0x1adad47d, 0x6ddde4eb, 0xf4d4b551, 0x83d385c7, 0x136c9856,
1206 0x646ba8c0, 0xfd62f97a, 0x8a65c9ec, 0x14015c4f, 0x63066cd9,
1207 0xfa0f3d63, 0x8d080df5, 0x3b6e20c8, 0x4c69105e, 0xd56041e4,
1208 0xa2677172, 0x3c03e4d1, 0x4b04d447, 0xd20d85fd, 0xa50ab56b,
1209 0x35b5a8fa, 0x42b2986c, 0xdbbbc9d6, 0xacbcf940, 0x32d86ce3,
1210 0x45df5c75, 0xdcd60dcf, 0xabd13d59, 0x26d930ac, 0x51de003a,
1211 0xc8d75180, 0xbfd06116, 0x21b4f4b5, 0x56b3c423, 0xcfba9599,
1212 0xb8bda50f, 0x2802b89e, 0x5f058808, 0xc60cd9b2, 0xb10be924,
1213 0x2f6f7c87, 0x58684c11, 0xc1611dab, 0xb6662d3d, 0x76dc4190,
1214 0x01db7106, 0x98d220bc, 0xefd5102a, 0x71b18589, 0x06b6b51f,
1215 0x9fbfe4a5, 0xe8b8d433, 0x7807c9a2, 0x0f00f934, 0x9609a88e,
1216 0xe10e9818, 0x7f6a0dbb, 0x086d3d2d, 0x91646c97, 0xe6635c01,
1217 0x6b6b51f4, 0x1c6c6162, 0x856530d8, 0xf262004e, 0x6c0695ed,
1218 0x1b01a57b, 0x8208f4c1, 0xf50fc457, 0x65b0d9c6, 0x12b7e950,
1219 0x8bbeb8ea, 0xfcb9887c, 0x62dd1ddf, 0x15da2d49, 0x8cd37cf3,
1220 0xfbd44c65, 0x4db26158, 0x3ab551ce, 0xa3bc0074, 0xd4bb30e2,
1221 0x4adfa541, 0x3dd895d7, 0xa4d1c46d, 0xd3d6f4fb, 0x4369e96a,
1222 0x346ed9fc, 0xad678846, 0xda60b8d0, 0x44042d73, 0x33031de5,
1223 0xaa0a4c5f, 0xdd0d7cc9, 0x5005713c, 0x270241aa, 0xbe0b1010,
1224 0xc90c2086, 0x5768b525, 0x206f85b3, 0xb966d409, 0xce61e49f,
1225 0x5edef90e, 0x29d9c998, 0xb0d09822, 0xc7d7a8b4, 0x59b33d17,
1226 0x2eb40d81, 0xb7bd5c3b, 0xc0ba6cad, 0xedb88320, 0x9abfb3b6,
1227 0x03b6e20c, 0x74b1d29a, 0xead54739, 0x9dd277af, 0x04db2615,
1228 0x73dc1683, 0xe3630b12, 0x94643b84, 0x0d6d6a3e, 0x7a6a5aa8,
1229 0xe40ecf0b, 0x9309ff9d, 0x0a00ae27, 0x7d079eb1, 0xf00f9344,
1230 0x8708a3d2, 0x1e01f268, 0x6906c2fe, 0xf762575d, 0x806567cb,
1231 0x196c3671, 0x6e6b06e7, 0xfed41b76, 0x89d32be0, 0x10da7a5a,
1232 0x67dd4acc, 0xf9b9df6f, 0x8ebeeff9, 0x17b7be43, 0x60b08ed5,
1233 0xd6d6a3e8, 0xa1d1937e, 0x38d8c2c4, 0x4fdff252, 0xd1bb67f1,
1234 0xa6bc5767, 0x3fb506dd, 0x48b2364b, 0xd80d2bda, 0xaf0a1b4c,
1235 0x36034af6, 0x41047a60, 0xdf60efc3, 0xa867df55, 0x316e8eef,
1236 0x4669be79, 0xcb61b38c, 0xbc66831a, 0x256fd2a0, 0x5268e236,
1237 0xcc0c7795, 0xbb0b4703, 0x220216b9, 0x5505262f, 0xc5ba3bbe,
1238 0xb2bd0b28, 0x2bb45a92, 0x5cb36a04, 0xc2d7ffa7, 0xb5d0cf31,
1239 0x2cd99e8b, 0x5bdeae1d, 0x9b64c2b0, 0xec63f226, 0x756aa39c,
1240 0x026d930a, 0x9c0906a9, 0xeb0e363f, 0x72076785, 0x05005713,
1241 0x95bf4a82, 0xe2b87a14, 0x7bb12bae, 0x0cb61b38, 0x92d28e9b,
1242 0xe5d5be0d, 0x7cdcefb7, 0x0bdbdf21, 0x86d3d2d4, 0xf1d4e242,
1243 0x68ddb3f8, 0x1fda836e, 0x81be16cd, 0xf6b9265b, 0x6fb077e1,
1244 0x18b74777, 0x88085ae6, 0xff0f6a70, 0x66063bca, 0x11010b5c,
1245 0x8f659eff, 0xf862ae69, 0x616bffd3, 0x166ccf45, 0xa00ae278,
1246 0xd70dd2ee, 0x4e048354, 0x3903b3c2, 0xa7672661, 0xd06016f7,
1247 0x4969474d, 0x3e6e77db, 0xaed16a4a, 0xd9d65adc, 0x40df0b66,
1248 0x37d83bf0, 0xa9bcae53, 0xdebb9ec5, 0x47b2cf7f, 0x30b5ffe9,
1249 0xbdbdf21c, 0xcabac28a, 0x53b39330, 0x24b4a3a6, 0xbad03605,
1250 0xcdd70693, 0x54de5729, 0x23d967bf, 0xb3667a2e, 0xc4614ab8,
1251 0x5d681b02, 0x2a6f2b94, 0xb40bbe37, 0xc30c8ea1, 0x5a05df1b,
1252 0x2d02ef8d
1253 };
1254
1255 vg_assert(img != NULL);
1256
1257 /* If the image is local, calculate the CRC here directly. If it's
1258 remote, forward the request to the server. */
1259 if (img->source.is_local) {
1260 /* Work through the image in 1 KB chunks. */
1261 UInt crc = 0xFFFFFFFF;
1262 DiOffT img_szB = ML_(img_size)(img);
1263 DiOffT curr_off = 0;
1264 while (1) {
1265 vg_assert(curr_off >= 0 && curr_off <= img_szB);
1266 if (curr_off == img_szB) break;
1267 DiOffT avail = img_szB - curr_off;
1268 vg_assert(avail > 0 && avail <= img_szB);
1269 if (avail > 1024) avail = 1024;
1270 UChar buf[1024];
1271 SizeT nGot = ML_(img_get_some)(buf, img, curr_off, avail);
1272 vg_assert(nGot >= 1 && nGot <= avail);
1273 UInt i;
1274 for (i = 0; i < (UInt)nGot; i++)
1275 crc = crc32_table[(crc ^ buf[i]) & 0xff] ^ (crc >> 8);
1276 curr_off += nGot;
1277 }
1278 return ~crc & 0xFFFFFFFF;
1279 } else {
1280 Frame* req = mk_Frame_noargs("CRC3");
1281 Frame* res = do_transaction(img->source.fd, req);
1282 if (!res) goto remote_crc_fail;
1283 ULong crc32 = 0;
1284 if (!parse_Frame_le64(res, "CROK", &crc32)) goto remote_crc_fail;
1285 if ((crc32 & ~0xFFFFFFFFULL) != 0) goto remote_crc_fail;
1286 free_Frame(req);
1287 free_Frame(res);
1288 return (UInt)crc32;
1289 remote_crc_fail:
1290
1291 // XXXX common this up with the READ diagnostic cases
1292 if (res) {
1293 UChar* reason = NULL;
1294 if (parse_Frame_asciiz(res, "FAIL", &reason)) {
1295 VG_(umsg)("img_calc_gnu_debuglink_crc32: fail: "
1296 "%s\n", reason);
1297 } else {
1298 VG_(umsg)("img_calc_gnu_debuglink_crc32: fail: "
1299 "unknown reason\n");
1300 }
1301 } else {
1302 VG_(umsg)("img_calc_gnu_debuglink_crc32: fail: "
1303 "server unexpectedly closed the connection\n");
1304 }
1305
1306 if (req) free_Frame(req);
1307 if (res) free_Frame(res);
1308 // FIXME: now what?
1309 give_up__comms_lost();
1310 /* NOTREACHED */
1311 vg_assert(0);
1312 }
1313 /*NOTREACHED*/
1314 vg_assert(0);
1315 }
1316
1317 ////////////////////////////////////////////////////
1318 #include "minilzo-inl.c"
1319
1320 /*--------------------------------------------------------------------*/
1321 /*--- end image.c ---*/
1322 /*--------------------------------------------------------------------*/
1323