Home | History | Annotate | Download | only in m_debuginfo
      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-2013 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 (at) 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 
     49 #define CACHE_ENTRY_SIZE_BITS (12+1)
     50 #define CACHE_N_ENTRIES       32
     51 
     52 #define CACHE_ENTRY_SIZE      (1 << CACHE_ENTRY_SIZE_BITS)
     53 
     54 /* An entry in the cache. */
     55 typedef
     56    struct {
     57       DiOffT off; // file offset for data[0]
     58       SizeT  used; // 1 .. sizeof(data), or 0 to denote not-in-use
     59       UChar  data[CACHE_ENTRY_SIZE];
     60    }
     61    CEnt;
     62 
     63 /* Source for files */
     64 typedef
     65    struct {
     66       // True: img is of local file.  False: img is from a server.
     67       Bool  is_local;
     68       // The fd for the local file, or sd for a remote server.
     69       Int   fd;
     70       // The name.  In ML_(dinfo_zalloc)'d space.  Used only for printing
     71       // error messages; hence it doesn't really matter what this contains.
     72       HChar* name;
     73       // The rest of these fields are only valid when using remote files
     74       // (that is, using a debuginfo server; hence when is_local==False)
     75       // Session ID allocated to us by the server.  Cannot be zero.
     76       ULong session_id;
     77    }
     78    Source;
     79 
     80 struct _DiImage {
     81    // The source -- how to get hold of the file we are reading
     82    Source source;
     83    // Total size of the image.
     84    SizeT size;
     85    // The number of entries used.  0 .. CACHE_N_ENTRIES
     86    UInt  ces_used;
     87    // Pointers to the entries.  ces[0 .. ces_used-1] are non-NULL.
     88    // ces[ces_used .. CACHE_N_ENTRIES-1] are NULL.
     89    // The non-NULL entries may be arranged arbitrarily.  We expect to use
     90    // a pseudo-LRU scheme though.
     91    CEnt* ces[CACHE_N_ENTRIES];
     92 };
     93 
     94 /* A frame.  The first 4 bytes of |data| give the kind of the frame,
     95    and the rest of it is kind-specific data. */
     96 typedef  struct { UChar* data; SizeT n_data; }  Frame;
     97 
     98 static void write_UInt_le ( /*OUT*/UChar* dst, UInt n )
     99 {
    100    Int i;
    101    for (i = 0; i <= 3; i++) {
    102       dst[i] = (UChar)(n & 0xFF);
    103       n >>= 8;
    104    }
    105 }
    106 
    107 static UInt read_UInt_le ( UChar* src )
    108 {
    109    UInt r = 0;
    110    Int i;
    111    for (i = 3; i >= 0; i--) {
    112       r <<= 8;
    113       r += (UInt)src[i];
    114    }
    115    return r;
    116 }
    117 
    118 static void write_ULong_le ( /*OUT*/UChar* dst, ULong n )
    119 {
    120    Int i;
    121    for (i = 0; i <= 7; i++) {
    122       dst[i] = (UChar)(n & 0xFF);
    123       n >>= 8;
    124    }
    125 }
    126 
    127 static ULong read_ULong_le ( UChar* src )
    128 {
    129    ULong r = 0;
    130    Int i;
    131    for (i = 7; i >= 0; i--) {
    132       r <<= 8;
    133       r += (ULong)src[i];
    134    }
    135    return r;
    136 }
    137 
    138 
    139 /* Set |sd| to be blocking.  Returns True on success. */
    140 static Bool set_blocking ( int sd )
    141 {
    142    Int res;
    143    res = VG_(fcntl)(sd, VKI_F_GETFL, 0/*ignored*/);
    144    if (res != -1)
    145       res = VG_(fcntl)(sd, VKI_F_SETFL, res & ~VKI_O_NONBLOCK);
    146    return (res != -1);
    147 }
    148 
    149 /* Tries to read 'len' bytes from fd, blocking if necessary.  Assumes
    150    fd has been set in blocking mode.  If it returns with the number of
    151    bytes read < len, it means that either fd was closed, or there was
    152    an error on it. */
    153 static Int my_read ( Int fd, UChar* buf, Int len )
    154 {
    155    Int nRead = 0;
    156    while (1) {
    157       if (nRead == len) return nRead;
    158       vg_assert(nRead < len);
    159       Int nNeeded = len - nRead;
    160       vg_assert(nNeeded > 0);
    161       Int n = VG_(read)(fd, &buf[nRead], nNeeded);
    162       if (n <= 0) return nRead; /* error or EOF */
    163       nRead += n;
    164    }
    165 }
    166 
    167 /* Tries to write 'len' bytes to fd, blocking if necessary.  Assumes
    168    fd has been set in blocking mode.  If it returns with the number of
    169    bytes written < len, it means that either fd was closed, or there was
    170    an error on it. */
    171 static Int my_write ( Int fd, UChar* buf, Int len )
    172 {
    173    Int nWritten = 0;
    174    while (1) {
    175       if (nWritten == len) return nWritten;
    176       vg_assert(nWritten < len);
    177       Int nStillToDo = len - nWritten;
    178       vg_assert(nStillToDo > 0);
    179       Int n = VG_(write_socket)(fd, &buf[nWritten], nStillToDo);
    180       if (n < 0) return nWritten; /* error or EOF */
    181       nWritten += n;
    182    }
    183 }
    184 
    185 /* If we lost communication with the remote server, just give up.
    186    Recovering is too difficult. */
    187 static void give_up__comms_lost(void)
    188 {
    189    VG_(umsg)("\n");
    190    VG_(umsg)(
    191       "Valgrind: debuginfo reader: Lost communication with the remote\n");
    192    VG_(umsg)(
    193       "Valgrind: debuginfo server.  I can't recover.  Giving up.  Sorry.\n");
    194    VG_(umsg)("\n");
    195    VG_(exit)(1);
    196    /*NOTREACHED*/
    197 }
    198 
    199 static void give_up__image_overrun(void)
    200 {
    201    VG_(umsg)("\n");
    202    VG_(umsg)(
    203       "Valgrind: debuginfo reader: Possibly corrupted debuginfo file.\n");
    204    VG_(umsg)(
    205       "Valgrind: I can't recover.  Giving up.  Sorry.\n");
    206    VG_(umsg)("\n");
    207    VG_(exit)(1);
    208    /*NOTREACHED*/
    209 }
    210 
    211 /* "Do" a transaction: that is, send the given frame to the server and
    212    return the frame it sends back.  Caller owns the resulting frame
    213    and must free it.  A NULL return means the transaction failed for
    214    some reason. */
    215 static Frame* do_transaction ( Int sd, Frame* req )
    216 {
    217    if (0) VG_(printf)("CLIENT: send %c%c%c%c\n",
    218                       req->data[0], req->data[1], req->data[2], req->data[3]);
    219 
    220    /* What goes on the wire is:
    221          adler(le32) n_data(le32) data[0 .. n_data-1]
    222       where the checksum covers n_data as well as data[].
    223    */
    224    /* The initial Adler-32 value */
    225    UInt adler = VG_(adler32)(0, NULL, 0);
    226 
    227    /* Fold in the length field, encoded as le32. */
    228    UChar wr_first8[8];
    229    write_UInt_le(&wr_first8[4], req->n_data);
    230    adler = VG_(adler32)(adler, &wr_first8[4], 4);
    231    /* Fold in the data values */
    232    adler = VG_(adler32)(adler, req->data, req->n_data);
    233    write_UInt_le(&wr_first8[0], adler);
    234 
    235    Int r = my_write(sd, &wr_first8[0], 8);
    236    if (r != 8) return NULL;
    237    vg_assert(req->n_data >= 4); // else ill formed -- no KIND field
    238    r = my_write(sd, req->data, req->n_data);
    239    if (r != req->n_data) return NULL;
    240 
    241    /* So, the request is sent.  Now get a request of the same format
    242       out of the channel. */
    243    UChar rd_first8[8];  // adler32; length32
    244    r = my_read(sd, &rd_first8[0], 8);
    245    if (r != 8) return NULL;
    246    UInt rd_adler = read_UInt_le(&rd_first8[0]);
    247    UInt rd_len   = read_UInt_le(&rd_first8[4]);
    248    /* Allocate a Frame to hold the result data, and read into it. */
    249    // Reject obviously-insane length fields.
    250    if (rd_len < 4 || rd_len > 4*1024*1024) return NULL;
    251    Frame* res = ML_(dinfo_zalloc)("di.do_transaction.1", sizeof(Frame));
    252    res->n_data = rd_len;
    253    res->data = ML_(dinfo_zalloc)("di.do_transaction.2", rd_len);
    254    r = my_read(sd, res->data, res->n_data);
    255    if (r != rd_len) return NULL;
    256 
    257    if (0) VG_(printf)("CLIENT: recv %c%c%c%c\n",
    258                       res->data[0], res->data[1], res->data[2], res->data[3]);
    259 
    260    /* Compute the checksum for the received data, and check it. */
    261    adler = VG_(adler32)(0, NULL, 0); // initial value
    262    adler = VG_(adler32)(adler, &rd_first8[4], 4);
    263    if (res->n_data > 0)
    264       adler = VG_(adler32)(adler, res->data, res->n_data);
    265 
    266    if (adler/*computed*/ != rd_adler/*expected*/) return NULL;
    267    return res;
    268 }
    269 
    270 static void free_Frame ( Frame* fr )
    271 {
    272    vg_assert(fr && fr->data);
    273    ML_(dinfo_free)(fr->data);
    274    ML_(dinfo_free)(fr);
    275 }
    276 
    277 static Frame* mk_Frame_noargs ( const HChar* tag )
    278 {
    279    vg_assert(VG_(strlen)(tag) == 4);
    280    Frame* f = ML_(dinfo_zalloc)("di.mFn.1", sizeof(Frame));
    281    f->n_data = 4;
    282    f->data = ML_(dinfo_zalloc)("di.mFn.2", f->n_data);
    283    VG_(memcpy)(&f->data[0], tag, 4);
    284    return f;
    285 }
    286 
    287 static Frame* mk_Frame_le64_le64_le64 ( const HChar* tag,
    288                                         ULong n1, ULong n2, ULong n3 )
    289 {
    290    vg_assert(VG_(strlen)(tag) == 4);
    291    Frame* f = ML_(dinfo_zalloc)("di.mFlll.1", sizeof(Frame));
    292    f->n_data = 4 + 3*8;
    293    f->data = ML_(dinfo_zalloc)("di.mFlll.2", f->n_data);
    294    VG_(memcpy)(&f->data[0], tag, 4);
    295    write_ULong_le(&f->data[4 + 0*8], n1);
    296    write_ULong_le(&f->data[4 + 1*8], n2);
    297    write_ULong_le(&f->data[4 + 2*8], n3);
    298    return f;
    299 }
    300 
    301 static Frame* mk_Frame_asciiz ( const HChar* tag, const HChar* str )
    302 {
    303    vg_assert(VG_(strlen)(tag) == 4);
    304    Frame* f = ML_(dinfo_zalloc)("di.mFa.1", sizeof(Frame));
    305    SizeT n_str = VG_(strlen)(str);
    306    f->n_data = 4 + n_str + 1;
    307    f->data = ML_(dinfo_zalloc)("di.mFa.2", f->n_data);
    308    VG_(memcpy)(&f->data[0], tag, 4);
    309    VG_(memcpy)(&f->data[4], str, n_str);
    310    vg_assert(f->data[4 + n_str] == 0);
    311    return f;
    312 }
    313 
    314 static Bool parse_Frame_le64 ( Frame* fr, const HChar* tag, /*OUT*/ULong* n1 )
    315 {
    316    vg_assert(VG_(strlen)(tag) == 4);
    317    if (!fr || !fr->data) return False;
    318    if (fr->n_data < 4) return False;
    319    if (VG_(memcmp)(&fr->data[0], tag, 4) != 0) return False;
    320    if (fr->n_data != 4 + 1*8) return False;
    321    *n1 = read_ULong_le(&fr->data[4 + 0*8]);
    322    return True;
    323 }
    324 
    325 static Bool parse_Frame_le64_le64 ( Frame* fr, const HChar* tag,
    326                                     /*OUT*/ULong* n1, /*OUT*/ULong* n2 )
    327 {
    328    vg_assert(VG_(strlen)(tag) == 4);
    329    if (!fr || !fr->data) return False;
    330    if (fr->n_data < 4) return False;
    331    if (VG_(memcmp)(&fr->data[0], tag, 4) != 0) return False;
    332    if (fr->n_data != 4 + 2*8) return False;
    333    *n1 = read_ULong_le(&fr->data[4 + 0*8]);
    334    *n2 = read_ULong_le(&fr->data[4 + 1*8]);
    335    return True;
    336 }
    337 
    338 static Bool parse_Frame_asciiz ( Frame* fr, const HChar* tag,
    339                                  /*OUT*/UChar** str )
    340 {
    341    vg_assert(VG_(strlen)(tag) == 4);
    342    if (!fr || !fr->data) return False;
    343    if (fr->n_data < 4) return False;
    344    if (VG_(memcmp)(&fr->data[0], tag, 4) != 0) return False;
    345    if (fr->n_data < 5) return False; // else there isn't even enough
    346                                      // space for the terminating zero
    347    /* Find the terminating zero and ensure it's right at the end
    348       of the data.  If not, the frame is malformed. */
    349    SizeT i = 4;
    350    while (True) {
    351       if (i >= fr->n_data) break;
    352       if (fr->data[i] == 0) break;
    353       i++;
    354    }
    355    vg_assert(i <= fr->n_data);
    356    if (i == fr->n_data-1 && fr->data[i] == 0) {
    357       *str = &fr->data[4];
    358       return True;
    359    } else {
    360       return False;
    361    }
    362 }
    363 
    364 static Bool parse_Frame_le64_le64_le64_bytes (
    365                Frame* fr, const HChar* tag,
    366                /*OUT*/ULong* n1, /*OUT*/ULong* n2, /*OUT*/ULong* n3,
    367                /*OUT*/UChar** data, /*OUT*/ULong* n_data
    368             )
    369 {
    370    vg_assert(VG_(strlen)(tag) == 4);
    371    if (!fr || !fr->data) return False;
    372    if (fr->n_data < 4) return False;
    373    if (VG_(memcmp)(&fr->data[0], tag, 4) != 0) return False;
    374    if (fr->n_data < 4 + 3*8) return False;
    375    *n1 = read_ULong_le(&fr->data[4 + 0*8]);
    376    *n2 = read_ULong_le(&fr->data[4 + 1*8]);
    377    *n3 = read_ULong_le(&fr->data[4 + 2*8]);
    378    *data   = &fr->data[4 + 3*8];
    379    *n_data = fr->n_data - (4 + 3*8);
    380    vg_assert(fr->n_data >= 4 + 3*8);
    381    return True;
    382 }
    383 
    384 static DiOffT block_round_down ( DiOffT i )
    385 {
    386    return i & ((DiOffT)~(CACHE_ENTRY_SIZE-1));
    387 }
    388 
    389 /* Is this offset inside this CEnt? */
    390 static inline Bool is_in_CEnt ( CEnt* cent, DiOffT off )
    391 {
    392    /* This assertion is checked by set_CEnt, so checking it here has
    393       no benefit, whereas skipping it does remove it from the hottest
    394       path. */
    395    /* vg_assert(cent->used > 0 && cent->used <= CACHE_ENTRY_SIZE); */
    396    return cent->off <= off && off < cent->off + cent->used;
    397 }
    398 
    399 /* Allocate a new CEnt, connect it to |img|, and return its index. */
    400 static UInt alloc_CEnt ( DiImage* img )
    401 {
    402    vg_assert(img);
    403    vg_assert(img->ces_used < CACHE_N_ENTRIES);
    404    UInt entNo = img->ces_used;
    405    img->ces_used++;
    406    vg_assert(img->ces[entNo] == NULL);
    407    img->ces[entNo] = ML_(dinfo_zalloc)("di.alloc_CEnt.1", sizeof(CEnt));
    408    return entNo;
    409 }
    410 
    411 /* Move the given entry to the top and slide those above it down by 1,
    412    to make space. */
    413 static void move_CEnt_to_top ( DiImage* img, UInt entNo )
    414 {
    415    vg_assert(img->ces_used <= CACHE_N_ENTRIES);
    416    vg_assert(entNo > 0 && entNo < img->ces_used);
    417    CEnt* tmp = img->ces[entNo];
    418    while (entNo > 0) {
    419       img->ces[entNo] = img->ces[entNo-1];
    420       entNo--;
    421    }
    422    img->ces[0] = tmp;
    423 }
    424 
    425 /* Set the given entry so that it has a chunk of the file containing
    426    the given offset.  It is this function that brings data into the
    427    cache, either by reading the local file or pulling it from the
    428    remote server. */
    429 static void set_CEnt ( DiImage* img, UInt entNo, DiOffT off )
    430 {
    431    SizeT len;
    432    DiOffT off_orig = off;
    433    vg_assert(img);
    434    vg_assert(img->ces_used <= CACHE_N_ENTRIES);
    435    vg_assert(entNo >= 0 && entNo < img->ces_used);
    436    vg_assert(off < img->size);
    437    vg_assert(img->ces[entNo] != NULL);
    438    /* Compute [off, +len) as the slice we are going to read. */
    439    off = block_round_down(off);
    440    len = img->size - off;
    441    if (len > CACHE_ENTRY_SIZE) len = CACHE_ENTRY_SIZE;
    442    /* It is conceivable that the 'len > 0' bit could fail if we make
    443       an image with a zero sized file.  But then no 'get' request on
    444       that image would be valid. */
    445    vg_assert(len > 0 && len <= CACHE_ENTRY_SIZE);
    446    vg_assert(off + len <= img->size);
    447    vg_assert(off <= off_orig && off_orig < off+len);
    448    /* So, read  off .. off+len-1  into the entry. */
    449    CEnt* ce = img->ces[entNo];
    450 
    451    if (0) {
    452       static UInt t_last = 0;
    453       static ULong nread = 0;
    454       UInt now = VG_(read_millisecond_timer)();
    455       UInt delay = now - t_last;
    456       t_last = now;
    457       nread += len;
    458       VG_(printf)("XXXXXXXX (tot %lld) read %ld offset %lld  %u\n",
    459                   nread, len, off, delay);
    460    }
    461 
    462    if (img->source.is_local) {
    463       // Simple: just read it
    464       SysRes sr = VG_(pread)(img->source.fd, &ce->data[0], (Int)len, off);
    465       vg_assert(!sr_isError(sr));
    466    } else {
    467       // Not so simple: poke the server
    468       vg_assert(img->source.session_id > 0);
    469       Frame* req
    470          = mk_Frame_le64_le64_le64("READ", img->source.session_id, off, len);
    471       Frame* res = do_transaction(img->source.fd, req);
    472       free_Frame(req); req = NULL;
    473       if (!res) goto server_fail;
    474       ULong  rx_session_id = 0, rx_off = 0, rx_len = 0, rx_zdata_len = 0;
    475       UChar* rx_data = NULL;
    476       /* Pretty confusing.  rx_sessionid, rx_off and rx_len are copies
    477          of the values that we requested in the READ frame just above,
    478          so we can be sure that the server is responding to the right
    479          request.  It just copies them from the request into the
    480          response.  rx_data is the actual data, and rx_zdata_len is
    481          its compressed length.  Hence rx_len must equal len, but
    482          rx_zdata_len can be different -- smaller, hopefully.. */
    483       if (!parse_Frame_le64_le64_le64_bytes
    484           (res, "RDOK", &rx_session_id, &rx_off,
    485                         &rx_len, &rx_data, &rx_zdata_len))
    486          goto server_fail;
    487       if (rx_session_id != img->source.session_id
    488           || rx_off != off || rx_len != len || rx_data == NULL)
    489          goto server_fail;
    490 
    491       //VG_(memcpy)(&ce->data[0], rx_data, len);
    492       // Decompress into the destination buffer
    493       // Tell the lib the max number of output bytes it can write.
    494       // After the call, this holds the number of bytes actually written,
    495       // and it's an error if it is different.
    496       UInt out_len = len;
    497       Int lzo_rc = lzo1x_decompress_safe(rx_data, rx_zdata_len,
    498                                          &ce->data[0], (lzo_uint*)&out_len,
    499                                          NULL);
    500       Bool ok = lzo_rc == LZO_E_OK && out_len == len;
    501       if (!ok) goto server_fail;
    502 
    503       free_Frame(res); res = NULL;
    504       goto end_of_else_clause;
    505      server_fail:
    506       /* The server screwed up somehow.  Now what? */
    507       if (res) {
    508          UChar* reason = NULL;
    509          if (parse_Frame_asciiz(res, "FAIL", &reason)) {
    510             VG_(umsg)("set_CEnt (reading data from DI server): fail: "
    511                       "%s\n", reason);
    512          } else {
    513             VG_(umsg)("set_CEnt (reading data from DI server): fail: "
    514                       "unknown reason\n");
    515          }
    516          free_Frame(res); res = NULL;
    517       } else {
    518          VG_(umsg)("set_CEnt (reading data from DI server): fail: "
    519                    "server unexpectedly closed the connection\n");
    520       }
    521       give_up__comms_lost();
    522       /* NOTREACHED */
    523       vg_assert(0);
    524      end_of_else_clause:
    525       {}
    526    }
    527 
    528    ce->off  = off;
    529    ce->used = len;
    530    vg_assert(ce->used > 0 && ce->used <= CACHE_ENTRY_SIZE);
    531 }
    532 
    533 __attribute__((noinline))
    534 static UChar get_slowcase ( DiImage* img, DiOffT off )
    535 {
    536    /* Stay sane .. */
    537    vg_assert(off < img->size);
    538    vg_assert(img->ces_used <= CACHE_N_ENTRIES);
    539    UInt i;
    540    /* Start the search at entry 1, since the fast-case function
    541       checked slot zero already. */
    542    for (i = 1; i < img->ces_used; i++) {
    543       vg_assert(img->ces[i]);
    544       if (is_in_CEnt(img->ces[i], off))
    545          break;
    546    }
    547    vg_assert(i <= img->ces_used);
    548    if (i == img->ces_used) {
    549       /* It's not in any entry.  Either allocate a new entry or
    550          recycle the LRU one. */
    551       if (img->ces_used == CACHE_N_ENTRIES) {
    552          /* All entries in use.  Recycle the (ostensibly) LRU one. */
    553          set_CEnt(img, CACHE_N_ENTRIES-1, off);
    554          i = CACHE_N_ENTRIES-1;
    555       } else {
    556          /* Allocate a new one, and fill it in. */
    557          UInt entNo = alloc_CEnt(img);
    558          set_CEnt(img, entNo, off);
    559          i = entNo;
    560       }
    561    } else {
    562       /* We found it at position 'i'. */
    563       vg_assert(i > 0);
    564    }
    565    if (i > 0) {
    566       move_CEnt_to_top(img, i);
    567       i = 0;
    568    }
    569    vg_assert(is_in_CEnt(img->ces[i], off));
    570    return img->ces[i]->data[ off - img->ces[i]->off ];
    571 }
    572 
    573 // This is called a lot, so do the usual fast/slow split stuff on it. */
    574 static UChar get ( DiImage* img, DiOffT off )
    575 {
    576    /* Most likely case is, it's in the ces[0] position. */
    577    /* ML_(img_from_local_file) requests a read for ces[0] when
    578       creating the image.  Hence slot zero is always non-NULL, so we
    579       can skip this test. */
    580    if (LIKELY(/* img->ces[0] != NULL && */
    581               is_in_CEnt(img->ces[0], off))) {
    582       return img->ces[0]->data[ off - img->ces[0]->off ];
    583    }
    584    /* Else we'll have to fish around for it. */
    585    return get_slowcase(img, off);
    586 }
    587 
    588 /* Create an image from a file in the local filesystem.  This is
    589    relatively straightforward. */
    590 DiImage* ML_(img_from_local_file)(const HChar* fullpath)
    591 {
    592    SysRes         fd;
    593    struct vg_stat stat_buf;
    594    DiOffT         size;
    595 
    596    fd = VG_(open)(fullpath, VKI_O_RDONLY, 0);
    597    if (sr_isError(fd))
    598       return NULL;
    599 
    600    if (VG_(fstat)(sr_Res(fd), &stat_buf) != 0) {
    601       VG_(close)(sr_Res(fd));
    602       return NULL;
    603    }
    604 
    605    size = stat_buf.size;
    606    if (size == 0 || size == DiOffT_INVALID
    607        || /* size is unrepresentable as a SizeT */
    608           size != (DiOffT)(SizeT)(size)) {
    609       VG_(close)(sr_Res(fd));
    610       return NULL;
    611    }
    612 
    613    DiImage* img = ML_(dinfo_zalloc)("di.image.ML_iflf.1", sizeof(DiImage));
    614    img->source.is_local = True;
    615    img->source.fd       = sr_Res(fd);
    616    img->size            = size;
    617    img->ces_used        = 0;
    618    img->source.name     = ML_(dinfo_strdup)("di.image.ML_iflf.2", fullpath);
    619    /* img->ces is already zeroed out */
    620    vg_assert(img->source.fd >= 0);
    621 
    622    /* Force the zeroth entry to be the first chunk of the file.
    623       That's likely to be the first part that's requested anyway, and
    624       loading it at this point forcing img->cent[0] to always be
    625       non-empty, thereby saving us an is-it-empty check on the fast
    626       path in get(). */
    627    UInt entNo = alloc_CEnt(img);
    628    vg_assert(entNo == 0);
    629    set_CEnt(img, 0, 0);
    630 
    631    return img;
    632 }
    633 
    634 
    635 /* Create an image from a file on a remote debuginfo server.  This is
    636    more complex.  There are lots of ways in which it can fail. */
    637 DiImage* ML_(img_from_di_server)(const HChar* filename,
    638                                  const HChar* serverAddr)
    639 {
    640    if (filename == NULL || serverAddr == NULL)
    641       return NULL;
    642 
    643    /* The filename must be a plain filename -- no slashes at all. */
    644    if (VG_(strchr)(filename, '/') != NULL)
    645       return NULL;
    646 
    647    /* Try to connect to the server.  A side effect of this is to parse
    648       and reject, if syntactically invalid, |serverAddr|.  Reasons why
    649       this could fail:
    650       - serverAddr is not of the form d.d.d.d:d or d.d.d.d
    651       - attempt to connect to that address:port failed
    652    */
    653    Int sd = VG_(connect_via_socket)(serverAddr);
    654    if (sd < 0)
    655       return NULL;
    656    if (!set_blocking(sd))
    657       return NULL;
    658    Int one = 1;
    659    Int sr = VG_(setsockopt)(sd, VKI_IPPROTO_TCP, VKI_TCP_NODELAY,
    660                             &one, sizeof(one));
    661    vg_assert(sr == 0);
    662 
    663    /* Ok, we got a connection.  Ask it for version string, so as to be
    664       reasonably sure we're talking to an instance of
    665       auxprogs/valgrind-di-server and not to some other random program
    666       that happens to be listening on that port. */
    667    Frame* req = mk_Frame_noargs("VERS");
    668    Frame* res = do_transaction(sd, req);
    669    if (res == NULL)
    670       goto fail; // do_transaction failed?!
    671    UChar* vstr = NULL;
    672    if (!parse_Frame_asciiz(res, "VEOK", &vstr))
    673       goto fail; // unexpected response kind, or invalid ID string
    674    vg_assert(vstr);
    675    if (VG_(strcmp)("Valgrind Debuginfo Server, Version 1",
    676                    (const HChar*)vstr) != 0)
    677       goto fail; // wrong version string
    678    free_Frame(req);
    679    free_Frame(res);
    680    req = NULL;
    681    res = NULL;
    682 
    683    /* Server seems plausible.  Present it with the name of the file we
    684       want and see if it'll give us back a session ID for it. */
    685    req = mk_Frame_asciiz("OPEN", filename);
    686    res = do_transaction(sd, req);
    687    if (res == NULL)
    688       goto fail;
    689    ULong session_id = 0, size = 0;
    690    if (!parse_Frame_le64_le64(res, "OPOK", &session_id, &size))
    691       goto fail;
    692    free_Frame(req);
    693    free_Frame(res);
    694    req = NULL;
    695    res = NULL;
    696 
    697    /* We have a session ID.  We're ready to roll. */
    698    DiImage* img = ML_(dinfo_zalloc)("di.image.ML_ifds.1", sizeof(DiImage));
    699    img->source.is_local   = False;
    700    img->source.fd         = sd;
    701    img->source.session_id = session_id;
    702    img->size              = size;
    703    img->ces_used          = 0;
    704    img->source.name       = ML_(dinfo_zalloc)("di.image.ML_ifds.2",
    705                                               20 + VG_(strlen)(filename)
    706                                                  + VG_(strlen)(serverAddr));
    707    VG_(sprintf)(img->source.name, "%s at %s", filename, serverAddr);
    708 
    709    /* img->ces is already zeroed out */
    710    vg_assert(img->source.fd >= 0);
    711 
    712    /* See comment on equivalent bit in ML_(img_from_local_file) for
    713       rationale. */
    714    UInt entNo = alloc_CEnt(img);
    715    vg_assert(entNo == 0);
    716    set_CEnt(img, 0, 0);
    717 
    718    return img;
    719 
    720   fail:
    721    if (req) free_Frame(req);
    722    if (res) {
    723       UChar* reason = NULL;
    724       if (parse_Frame_asciiz(res, "FAIL", &reason)) {
    725          // HACK: if it's just telling us that the file can't
    726          // be opened, don't print it, else we'll get flooded with
    727          // such complaints, one for each main object for which there
    728          // isn't a debuginfo file on the server.
    729          if (0 != VG_(strcmp)((const HChar*)reason, "OPEN: cannot open file"))
    730             VG_(umsg)("ML_(img_from_di_server): fail: %s\n", reason);
    731       } else {
    732          VG_(umsg)("ML_(img_from_di_server): fail: unknown reason\n");
    733       }
    734       free_Frame(res);
    735    }
    736    VG_(close)(sd);
    737    return NULL;
    738 }
    739 
    740 void ML_(img_done)(DiImage* img)
    741 {
    742    vg_assert(img);
    743    if (img->source.is_local) {
    744       /* Close the file; nothing else to do. */
    745       vg_assert(img->source.session_id == 0);
    746       VG_(close)(img->source.fd);
    747    } else {
    748       /* Close the socket.  The server can detect this and will scrub
    749          the connection when it happens, so there's no need to tell it
    750          explicitly by sending it a "CLOSE" message, or any such. */
    751       vg_assert(img->source.session_id != 0);
    752       VG_(close)(img->source.fd);
    753    }
    754 
    755    /* Free up the cache entries, ultimately |img| itself. */
    756    UInt i;
    757    vg_assert(img->ces_used <= CACHE_N_ENTRIES);
    758    for (i = 0; i < img->ces_used; i++) {
    759       ML_(dinfo_free)(img->ces[i]);
    760    }
    761    /* Take the opportunity to sanity check the rest. */
    762    for (i = i; i < img->ces_used; i++) {
    763       vg_assert(img->ces[i] == NULL);
    764    }
    765    ML_(dinfo_free)(img->source.name);
    766    ML_(dinfo_free)(img);
    767 }
    768 
    769 DiOffT ML_(img_size)(DiImage* img)
    770 {
    771    vg_assert(img);
    772    return img->size;
    773 }
    774 
    775 inline Bool ML_(img_valid)(DiImage* img, DiOffT offset, SizeT size)
    776 {
    777    vg_assert(img);
    778    vg_assert(offset != DiOffT_INVALID);
    779    return img->size > 0 && offset + size <= (DiOffT)img->size;
    780 }
    781 
    782 /* Check the given range is valid, and if not, shut down the system.
    783    An invalid range would imply that we're trying to read outside the
    784    image, which normally means the image is corrupted somehow, or the
    785    caller is buggy.  Recovering is too complex, and we have
    786    probably-corrupt debuginfo, so just give up. */
    787 static void ensure_valid(DiImage* img, DiOffT offset, SizeT size,
    788                          const HChar* caller)
    789 {
    790    if (LIKELY(ML_(img_valid)(img, offset, size)))
    791       return;
    792    VG_(umsg)("Valgrind: debuginfo reader: ensure_valid failed:\n");
    793    VG_(umsg)("Valgrind:   during call to %s\n", caller);
    794    VG_(umsg)("Valgrind:   request for range [%llu, +%llu) exceeds\n",
    795              (ULong)offset, (ULong)size);
    796    VG_(umsg)("Valgrind:   valid image size of %llu for image:\n",
    797              (ULong)img->size);
    798    VG_(umsg)("Valgrind:   \"%s\"\n", img->source.name);
    799    give_up__image_overrun();
    800 }
    801 
    802 
    803 void ML_(img_get)(/*OUT*/void* dst,
    804                   DiImage* img, DiOffT offset, SizeT size)
    805 {
    806    vg_assert(img);
    807    vg_assert(size > 0);
    808    ensure_valid(img, offset, size, "ML_(img_get)");
    809    SizeT i;
    810    for (i = 0; i < size; i++) {
    811       ((UChar*)dst)[i] = get(img, offset + i);
    812    }
    813 }
    814 
    815 SizeT ML_(img_get_some)(/*OUT*/void* dst,
    816                         DiImage* img, DiOffT offset, SizeT size)
    817 {
    818    vg_assert(img);
    819    vg_assert(size > 0);
    820    ensure_valid(img, offset, size, "ML_(img_get_some)");
    821    UChar* dstU = (UChar*)dst;
    822    /* Use |get| in the normal way to get the first byte of the range.
    823       This guarantees to put the cache entry containing |offset| in
    824       position zero. */
    825    dstU[0] = get(img, offset);
    826    /* Now just read as many bytes as we can (or need) directly out of
    827       entry zero, without bothering to call |get| each time. */
    828    CEnt* ce = img->ces[0];
    829    vg_assert(ce && ce->used >= 1);
    830    vg_assert(is_in_CEnt(ce, offset));
    831    SizeT nToCopy = size - 1;
    832    SizeT nAvail  = (SizeT)(ce->used - (offset + 1 - ce->off));
    833    vg_assert(nAvail >= 0 && nAvail <= ce->used-1);
    834    if (nAvail < nToCopy) nToCopy = nAvail;
    835    VG_(memcpy)(&dstU[1], &ce->data[offset + 1 - ce->off], nToCopy);
    836    return nToCopy + 1;
    837 }
    838 
    839 
    840 SizeT ML_(img_strlen)(DiImage* img, DiOffT off)
    841 {
    842    ensure_valid(img, off, 1, "ML_(img_strlen)");
    843    SizeT i = 0;
    844    while (get(img, off + i) != 0) i++;
    845    return i;
    846 }
    847 
    848 HChar* ML_(img_strdup)(DiImage* img, const HChar* cc, DiOffT offset)
    849 {
    850    ensure_valid(img, offset, 1, "ML_(img_strdup)");
    851    SizeT  len = ML_(img_strlen)(img, offset);
    852    HChar* res = ML_(dinfo_zalloc)(cc, len+1);
    853    SizeT  i;
    854    for (i = 0; i < len; i++) {
    855       res[i] = get(img, offset+i);
    856    }
    857    vg_assert(res[len] == 0);
    858    return res;
    859 }
    860 
    861 Int ML_(img_strcmp)(DiImage* img, DiOffT off1, DiOffT off2)
    862 {
    863    ensure_valid(img, off1, 1, "ML_(img_strcmp)(first arg)");
    864    ensure_valid(img, off2, 1, "ML_(img_strcmp)(second arg)");
    865    while (True) {
    866       UChar c1 = get(img, off1);
    867       UChar c2 = get(img, off2);
    868       if (c1 < c2) return -1;
    869       if (c1 > c2) return 1;
    870       if (c1 == 0) return 0;
    871       off1++; off2++;
    872    }
    873 }
    874 
    875 Int ML_(img_strcmp_c)(DiImage* img, DiOffT off1, const HChar* str2)
    876 {
    877    ensure_valid(img, off1, 1, "ML_(img_strcmp_c)");
    878    while (True) {
    879       UChar c1 = get(img, off1);
    880       UChar c2 = *(UChar*)str2;
    881       if (c1 < c2) return -1;
    882       if (c1 > c2) return 1;
    883       if (c1 == 0) return 0;
    884       off1++; str2++;
    885    }
    886 }
    887 
    888 UChar ML_(img_get_UChar)(DiImage* img, DiOffT offset)
    889 {
    890    ensure_valid(img, offset, 1, "ML_(img_get_UChar)");
    891    return get(img, offset);
    892 }
    893 
    894 UShort ML_(img_get_UShort)(DiImage* img, DiOffT offset)
    895 {
    896    UShort r;
    897    ML_(img_get)(&r, img, offset, sizeof(r));
    898    return r;
    899 }
    900 
    901 UInt ML_(img_get_UInt)(DiImage* img, DiOffT offset)
    902 {
    903    UInt r;
    904    ML_(img_get)(&r, img, offset, sizeof(r));
    905    return r;
    906 }
    907 
    908 ULong ML_(img_get_ULong)(DiImage* img, DiOffT offset)
    909 {
    910    ULong r;
    911    ML_(img_get)(&r, img, offset, sizeof(r));
    912    return r;
    913 }
    914 
    915 
    916 /*
    917  * This routine for calculating the CRC for a separate debug file
    918  * is GPLed code borrowed from GNU binutils.
    919  */
    920 UInt ML_(img_calc_gnu_debuglink_crc32)(DiImage* img)
    921 {
    922   static const UInt crc32_table[256] =
    923     {
    924       0x00000000, 0x77073096, 0xee0e612c, 0x990951ba, 0x076dc419,
    925       0x706af48f, 0xe963a535, 0x9e6495a3, 0x0edb8832, 0x79dcb8a4,
    926       0xe0d5e91e, 0x97d2d988, 0x09b64c2b, 0x7eb17cbd, 0xe7b82d07,
    927       0x90bf1d91, 0x1db71064, 0x6ab020f2, 0xf3b97148, 0x84be41de,
    928       0x1adad47d, 0x6ddde4eb, 0xf4d4b551, 0x83d385c7, 0x136c9856,
    929       0x646ba8c0, 0xfd62f97a, 0x8a65c9ec, 0x14015c4f, 0x63066cd9,
    930       0xfa0f3d63, 0x8d080df5, 0x3b6e20c8, 0x4c69105e, 0xd56041e4,
    931       0xa2677172, 0x3c03e4d1, 0x4b04d447, 0xd20d85fd, 0xa50ab56b,
    932       0x35b5a8fa, 0x42b2986c, 0xdbbbc9d6, 0xacbcf940, 0x32d86ce3,
    933       0x45df5c75, 0xdcd60dcf, 0xabd13d59, 0x26d930ac, 0x51de003a,
    934       0xc8d75180, 0xbfd06116, 0x21b4f4b5, 0x56b3c423, 0xcfba9599,
    935       0xb8bda50f, 0x2802b89e, 0x5f058808, 0xc60cd9b2, 0xb10be924,
    936       0x2f6f7c87, 0x58684c11, 0xc1611dab, 0xb6662d3d, 0x76dc4190,
    937       0x01db7106, 0x98d220bc, 0xefd5102a, 0x71b18589, 0x06b6b51f,
    938       0x9fbfe4a5, 0xe8b8d433, 0x7807c9a2, 0x0f00f934, 0x9609a88e,
    939       0xe10e9818, 0x7f6a0dbb, 0x086d3d2d, 0x91646c97, 0xe6635c01,
    940       0x6b6b51f4, 0x1c6c6162, 0x856530d8, 0xf262004e, 0x6c0695ed,
    941       0x1b01a57b, 0x8208f4c1, 0xf50fc457, 0x65b0d9c6, 0x12b7e950,
    942       0x8bbeb8ea, 0xfcb9887c, 0x62dd1ddf, 0x15da2d49, 0x8cd37cf3,
    943       0xfbd44c65, 0x4db26158, 0x3ab551ce, 0xa3bc0074, 0xd4bb30e2,
    944       0x4adfa541, 0x3dd895d7, 0xa4d1c46d, 0xd3d6f4fb, 0x4369e96a,
    945       0x346ed9fc, 0xad678846, 0xda60b8d0, 0x44042d73, 0x33031de5,
    946       0xaa0a4c5f, 0xdd0d7cc9, 0x5005713c, 0x270241aa, 0xbe0b1010,
    947       0xc90c2086, 0x5768b525, 0x206f85b3, 0xb966d409, 0xce61e49f,
    948       0x5edef90e, 0x29d9c998, 0xb0d09822, 0xc7d7a8b4, 0x59b33d17,
    949       0x2eb40d81, 0xb7bd5c3b, 0xc0ba6cad, 0xedb88320, 0x9abfb3b6,
    950       0x03b6e20c, 0x74b1d29a, 0xead54739, 0x9dd277af, 0x04db2615,
    951       0x73dc1683, 0xe3630b12, 0x94643b84, 0x0d6d6a3e, 0x7a6a5aa8,
    952       0xe40ecf0b, 0x9309ff9d, 0x0a00ae27, 0x7d079eb1, 0xf00f9344,
    953       0x8708a3d2, 0x1e01f268, 0x6906c2fe, 0xf762575d, 0x806567cb,
    954       0x196c3671, 0x6e6b06e7, 0xfed41b76, 0x89d32be0, 0x10da7a5a,
    955       0x67dd4acc, 0xf9b9df6f, 0x8ebeeff9, 0x17b7be43, 0x60b08ed5,
    956       0xd6d6a3e8, 0xa1d1937e, 0x38d8c2c4, 0x4fdff252, 0xd1bb67f1,
    957       0xa6bc5767, 0x3fb506dd, 0x48b2364b, 0xd80d2bda, 0xaf0a1b4c,
    958       0x36034af6, 0x41047a60, 0xdf60efc3, 0xa867df55, 0x316e8eef,
    959       0x4669be79, 0xcb61b38c, 0xbc66831a, 0x256fd2a0, 0x5268e236,
    960       0xcc0c7795, 0xbb0b4703, 0x220216b9, 0x5505262f, 0xc5ba3bbe,
    961       0xb2bd0b28, 0x2bb45a92, 0x5cb36a04, 0xc2d7ffa7, 0xb5d0cf31,
    962       0x2cd99e8b, 0x5bdeae1d, 0x9b64c2b0, 0xec63f226, 0x756aa39c,
    963       0x026d930a, 0x9c0906a9, 0xeb0e363f, 0x72076785, 0x05005713,
    964       0x95bf4a82, 0xe2b87a14, 0x7bb12bae, 0x0cb61b38, 0x92d28e9b,
    965       0xe5d5be0d, 0x7cdcefb7, 0x0bdbdf21, 0x86d3d2d4, 0xf1d4e242,
    966       0x68ddb3f8, 0x1fda836e, 0x81be16cd, 0xf6b9265b, 0x6fb077e1,
    967       0x18b74777, 0x88085ae6, 0xff0f6a70, 0x66063bca, 0x11010b5c,
    968       0x8f659eff, 0xf862ae69, 0x616bffd3, 0x166ccf45, 0xa00ae278,
    969       0xd70dd2ee, 0x4e048354, 0x3903b3c2, 0xa7672661, 0xd06016f7,
    970       0x4969474d, 0x3e6e77db, 0xaed16a4a, 0xd9d65adc, 0x40df0b66,
    971       0x37d83bf0, 0xa9bcae53, 0xdebb9ec5, 0x47b2cf7f, 0x30b5ffe9,
    972       0xbdbdf21c, 0xcabac28a, 0x53b39330, 0x24b4a3a6, 0xbad03605,
    973       0xcdd70693, 0x54de5729, 0x23d967bf, 0xb3667a2e, 0xc4614ab8,
    974       0x5d681b02, 0x2a6f2b94, 0xb40bbe37, 0xc30c8ea1, 0x5a05df1b,
    975       0x2d02ef8d
    976     };
    977 
    978    vg_assert(img);
    979 
    980    /* If the image is local, calculate the CRC here directly.  If it's
    981       remote, forward the request to the server. */
    982    if (img->source.is_local) {
    983       /* Work through the image in 1 KB chunks. */
    984       UInt   crc      = 0xFFFFFFFF;
    985       DiOffT img_szB  = ML_(img_size)(img);
    986       DiOffT curr_off = 0;
    987       while (1) {
    988          vg_assert(curr_off >= 0 && curr_off <= img_szB);
    989          if (curr_off == img_szB) break;
    990          DiOffT avail = img_szB - curr_off;
    991          vg_assert(avail > 0 && avail <= img_szB);
    992          if (avail > 1024) avail = 1024;
    993          UChar buf[1024];
    994          SizeT nGot = ML_(img_get_some)(buf, img, curr_off, avail);
    995          vg_assert(nGot >= 1 && nGot <= avail);
    996          UInt i;
    997          for (i = 0; i < (UInt)nGot; i++)
    998             crc = crc32_table[(crc ^ buf[i]) & 0xff] ^ (crc >> 8);
    999          curr_off += nGot;
   1000       }
   1001       return ~crc & 0xFFFFFFFF;
   1002    } else {
   1003       Frame* req = mk_Frame_noargs("CRC3");
   1004       Frame* res = do_transaction(img->source.fd, req);
   1005       if (!res) goto remote_crc_fail;
   1006       ULong crc32 = 0;
   1007       if (!parse_Frame_le64(res, "CROK", &crc32)) goto remote_crc_fail;
   1008       if ((crc32 & ~0xFFFFFFFFULL) != 0) goto remote_crc_fail;
   1009       if (req) free_Frame(req);
   1010       if (res) free_Frame(res);
   1011       return (UInt)crc32;
   1012      remote_crc_fail:
   1013 
   1014       // XXXX common this up with the READ diagnostic cases
   1015       if (res) {
   1016          UChar* reason = NULL;
   1017          if (parse_Frame_asciiz(res, "FAIL", &reason)) {
   1018             VG_(umsg)("img_calc_gnu_debuglink_crc32: fail: "
   1019                       "%s\n", reason);
   1020          } else {
   1021             VG_(umsg)("img_calc_gnu_debuglink_crc32: fail: "
   1022                       "unknown reason\n");
   1023          }
   1024       } else {
   1025          VG_(umsg)("img_calc_gnu_debuglink_crc32: fail: "
   1026                    "server unexpectedly closed the connection\n");
   1027       }
   1028 
   1029       if (req) free_Frame(req);
   1030       if (res) free_Frame(res);
   1031       // FIXME: now what?
   1032       give_up__comms_lost();
   1033       /* NOTREACHED */
   1034       vg_assert(0);
   1035    }
   1036    /*NOTREACHED*/
   1037    vg_assert(0);
   1038 }
   1039 
   1040 ////////////////////////////////////////////////////
   1041 #include "minilzo-inl.c"
   1042 
   1043 /*--------------------------------------------------------------------*/
   1044 /*--- end                                                  image.c ---*/
   1045 /*--------------------------------------------------------------------*/
   1046