• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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