Home | History | Annotate | Download | only in m_debuginfo
      1 
      2 /*--------------------------------------------------------------------*/
      3 /*--- An abstraction that provides a file-reading mechanism.       ---*/
      4 /*---                                                 priv_image.h ---*/
      5 /*--------------------------------------------------------------------*/
      6 
      7 /*
      8    This file is part of Valgrind, a dynamic binary instrumentation
      9    framework.
     10 
     11    Copyright (C) 2013-2013 Mozilla Foundation
     12 
     13    This program is free software; you can redistribute it and/or
     14    modify it under the terms of the GNU General Public License as
     15    published by the Free Software Foundation; either version 2 of the
     16    License, or (at your option) any later version.
     17 
     18    This program is distributed in the hope that it will be useful, but
     19    WITHOUT ANY WARRANTY; without even the implied warranty of
     20    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
     21    General Public License for more details.
     22 
     23    You should have received a copy of the GNU General Public License
     24    along with this program; if not, write to the Free Software
     25    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
     26    02111-1307, USA.
     27 
     28    The GNU General Public License is contained in the file COPYING.
     29 */
     30 
     31 /* Contributed by Julian Seward <jseward (at) acm.org> */
     32 
     33 #ifndef __PRIV_IMAGE_H
     34 #define __PRIV_IMAGE_H
     35 
     36 #include "pub_core_basics.h"    // ULong
     37 #include "priv_misc.h"          // ML_(dinfo_zalloc)
     38 
     39 /*------------------------------------------------------------*/
     40 /*--- DiImage -- abstract images                           ---*/
     41 /*------------------------------------------------------------*/
     42 
     43 /* The basic type, containing an abstractified memory area that can be
     44    read from.  This is an abstract type since there can be more than
     45    one implementation of it. */
     46 
     47 /* abstract */
     48 typedef  struct _DiImage  DiImage;
     49 
     50 /* an offset in the image */
     51 typedef  ULong  DiOffT;
     52 
     53 /* This denotes an invalid DiOffT value.  Except where otherwise
     54    noted, you must never pass this to any of the ML_(image_*)
     55    functions -- they will assert.  That does mean though that they can
     56    be used for signalling other conditions, for example that some
     57    expected part of the image is missing. */
     58 #define DiOffT_INVALID ((DiOffT)(0xFFFFFFFFFFFFFFFFULL))
     59 
     60 /* Create an image from a file in the local filesysem.  Returns NULL
     61    if it fails, for whatever reason. */
     62 DiImage* ML_(img_from_local_file)(const HChar* fullpath);
     63 
     64 /* Create an image by connecting to a Valgrind debuginfo server
     65    (auxprogs/valgrind-di-server.c).  |filename| contains the object
     66    name to ask for; it must be a plain filename, not absolute, not a
     67    path.  |serverAddr| must be of the form either "d.d.d.d" or
     68    "d.d.d.d:d" where d is one or more digits.  These specify the IPv4
     69    address and (in the second case) port number for the server.  In
     70    the first case, port 1500 is assumed. */
     71 DiImage* ML_(img_from_di_server)(const HChar* filename,
     72                                  const HChar* serverAddr);
     73 
     74 /* Destroy an existing image. */
     75 void ML_(img_done)(DiImage*);
     76 
     77 /* How big is the image? */
     78 DiOffT ML_(img_size)(DiImage* img);
     79 
     80 /* Does the section [offset, +size) exist in the image? */
     81 Bool ML_(img_valid)(DiImage* img, DiOffT offset, SizeT size);
     82 
     83 /* Get info out of an image.  If any part of the section denoted by
     84    [offset, +size) is invalid, does not return. */
     85 void ML_(img_get)(/*OUT*/void* dst,
     86                   DiImage* img, DiOffT offset, SizeT size);
     87 
     88 /* A version of ML_(img_get) that is significantly cheaper when
     89    fetching a lot of data, at the cost of being more difficult to use.
     90    Fetches between 1 and |size| bytes from |img| at |offset| and
     91    places them in |dst|.  |size| must be at least 1.  The number of
     92    bytes read is returned, and the caller must be able to deal with
     93    any number between 1 and |size|.  |offset| must be a valid offset
     94    in the image; if not the function will not return.  This function
     95    will not read off the end of the image. */
     96 SizeT ML_(img_get_some)(/*OUT*/void* dst,
     97                         DiImage* img, DiOffT offset, SizeT size);
     98 
     99 /* Copy a C string out of the image, into ML_(dinfo_zalloc)'d space.
    100    The caller owns the string and must free it with ML_(dinfo_free).
    101    |offset| may be DiOffT_INVALID, in which case this returns NULL. */
    102 HChar* ML_(img_strdup)(DiImage* img, const HChar* cc, DiOffT offset);
    103 
    104 /* Do strcmp on two C strings in the image.  Chars are cast to HChar
    105    before comparison. */
    106 Int ML_(img_strcmp)(DiImage* img, DiOffT off1, DiOffT off2);
    107 
    108 /* Do strcmp of a C string in the image vs a normal one.  Chars are
    109    cast to HChar before comparison. */
    110 Int ML_(img_strcmp_c)(DiImage* img, DiOffT off1, const HChar* str2);
    111 
    112 /* Do strlen of a C string in the image. */
    113 SizeT ML_(img_strlen)(DiImage* img, DiOffT off);
    114 
    115 /* Fetch various sized primitive types from the image.  These operate
    116    at the endianness and word size of the host. */
    117 UChar  ML_(img_get_UChar) (DiImage* img, DiOffT offset);
    118 UShort ML_(img_get_UShort)(DiImage* img, DiOffT offset);
    119 UInt   ML_(img_get_UInt)  (DiImage* img, DiOffT offset);
    120 ULong  ML_(img_get_ULong) (DiImage* img, DiOffT offset);
    121 
    122 /* Calculate the "GNU Debuglink CRC" for the image.  This
    123    unfortunately has to be done as part of the DiImage implementation
    124    because it involves reading the entire image, and is therefore
    125    something that needs to be handed off to the remote server -- since
    126    to do it otherwise would imply pulling the entire image across the
    127    connection, making the client/server split pointless. */
    128 UInt ML_(img_calc_gnu_debuglink_crc32)(DiImage* img);
    129 
    130 
    131 /*------------------------------------------------------------*/
    132 /*--- DiCursor -- cursors for reading images               ---*/
    133 /*------------------------------------------------------------*/
    134 
    135 /* A type built on DiImage.  It contains a DiImage and a 'current
    136    offset' in the image, and is useful for building low level readers
    137    of images.  In the functions section below, "read" means "read data
    138    at the cursor without moving it along", and "step" means "read data
    139    at the cursor and move it along by the size of the item read". */
    140 typedef
    141    struct { DiImage* img; DiOffT ioff; }
    142    DiCursor;
    143 
    144 /* An invalid cursor.  You can't use it for anything. */
    145 #define DiCursor_INVALID ((DiCursor){NULL,DiOffT_INVALID})
    146 
    147 static inline DiCursor mk_DiCursor ( DiImage* img, DiOffT ioff ) {
    148    return (DiCursor){img, ioff};
    149 }
    150 
    151 static inline Bool ML_(cur_is_valid)(DiCursor c) {
    152    return c.img != NULL;
    153 }
    154 
    155 
    156 /*------------------------------------------------------------*/
    157 /*--- DiSlice -- subranges within DiImages                 ---*/
    158 /*------------------------------------------------------------*/
    159 
    160 /* Another type built on top of DiImage.  It denotes a subrange of an
    161    image and is useful for representing (eg) exactly the part of an
    162    image that is a specific ELF section. */
    163 typedef
    164    struct { DiImage* img; DiOffT ioff; DiOffT szB; }
    165    DiSlice;
    166 
    167 /* A DiSlice can also be INVALID, meaning it does not refer to any
    168    part of any image. */
    169 #define DiSlice_INVALID ((DiSlice){NULL,DiOffT_INVALID,0})
    170 
    171 static inline DiSlice mk_DiSlice ( DiImage* img, DiOffT ioff, DiOffT szB ) {
    172    return (DiSlice){img, ioff, szB};
    173 }
    174 
    175 static inline Bool ML_(sli_is_valid)( DiSlice sli ) {
    176    return sli.img != NULL;
    177 }
    178 
    179 /* Create a slice from a combination of a cursor and a length.  The
    180    maximum implied offset must not exceed the size of the underlying
    181    image; this is asserted for. */
    182 static inline DiSlice ML_(sli_from_cur)( DiCursor cur, DiOffT size ) {
    183    if (ML_(cur_is_valid)(cur)) {
    184       vg_assert(size != DiOffT_INVALID);
    185       vg_assert(cur.ioff + size <= ML_(img_size)(cur.img));
    186       return mk_DiSlice(cur.img, cur.ioff, size);
    187    } else {
    188       return DiSlice_INVALID;
    189    }
    190 }
    191 
    192 /* Create a slice which exactly covers the given image. */
    193 static inline DiSlice ML_(sli_from_img)( DiImage* img ) {
    194    if (img) {
    195       return mk_DiSlice(img, 0, ML_(img_size)(img));
    196    } else {
    197       return DiSlice_INVALID;
    198    }
    199 }
    200 
    201 
    202 /*------------------------------------------------------------*/
    203 /*--- Functions that operate on DiCursors                  ---*/
    204 /*------------------------------------------------------------*/
    205 
    206 /* Create a cursor from a slice, referring to the first byte of the
    207    slice. */
    208 static inline DiCursor ML_(cur_from_sli)( DiSlice sl ) {
    209    if (ML_(sli_is_valid)(sl)) {
    210       DiCursor c;
    211       c.img  = sl.img;
    212       c.ioff = sl.ioff;
    213       return c;
    214    } else {
    215       return DiCursor_INVALID;
    216    }
    217 }
    218 
    219 static inline Bool ML_(cur_cmpLT)( DiCursor c1, DiCursor c2 ) {
    220    vg_assert(c1.img == c2.img);
    221    return c1.ioff < c2.ioff;
    222 }
    223 static inline Bool ML_(cur_cmpEQ)( DiCursor c1, DiCursor c2 ) {
    224    vg_assert(c1.img == c2.img);
    225    return c1.ioff == c2.ioff;
    226 }
    227 static inline Bool ML_(cur_cmpGT)( DiCursor c1, DiCursor c2 ) {
    228    vg_assert(c1.img == c2.img);
    229    return c1.ioff > c2.ioff;
    230 }
    231 
    232 static inline DiCursor ML_(cur_plus)( DiCursor c, Long n ) {
    233    c.ioff += (DiOffT)n;
    234    return c;
    235 }
    236 
    237 /* Asserts that c1 and c2 refer to the same image.  Returns the difference
    238    in offsets (c1.ioff - c2.ioff). */
    239 static inline Long ML_(cur_minus)( DiCursor c1, DiCursor c2 ) {
    240    vg_assert(c1.img == c2.img);
    241    return (Long)(c1.ioff) - (Long)(c2.ioff);
    242 }
    243 
    244 static inline SizeT ML_(cur_strlen)( DiCursor c ) {
    245    return ML_(img_strlen)( c.img, c.ioff );
    246 }
    247 
    248 // strdup from the given cursor.  Caller must ML_(dinfo_free) the
    249 // resulting string.
    250 static inline HChar* ML_(cur_read_strdup)( DiCursor c, const HChar* cc ) {
    251    vg_assert(c.ioff != DiOffT_INVALID);
    252    HChar* res = ML_(img_strdup)(c.img, cc, c.ioff);
    253    return res;
    254 }
    255 // strdup from the given cursor and advance it.  Caller must
    256 // ML_(dinfo_free) the resulting string.
    257 static inline HChar* ML_(cur_step_strdup)( DiCursor* c, const HChar* cc ) {
    258    vg_assert(c->ioff != DiOffT_INVALID);
    259    HChar* res = ML_(img_strdup)(c->img, cc, c->ioff);
    260    c->ioff += VG_(strlen)(res) + 1;
    261    return res;
    262 }
    263 
    264 // Fetch an arbitrary number of bytes from the cursor.
    265 static inline void ML_(cur_read_get) ( /*OUT*/void* dst,
    266                                        DiCursor c, SizeT size) {
    267    ML_(img_get)(dst, c.img, c.ioff, size);
    268 }
    269 
    270 // Fetch an arbitrary number of bytes from the cursor, and advance it.
    271 static inline void ML_(cur_step_get) ( /*OUT*/void* dst,
    272                                        DiCursor* c, SizeT size) {
    273    ML_(img_get)(dst, c->img, c->ioff, size);
    274    c->ioff += size;
    275 }
    276 
    277 // memdup from the given cursor.  Caller must ML_(dinfo_free) the
    278 // resulting block.
    279 static inline UChar* ML_(cur_read_memdup)( DiCursor c, SizeT size,
    280                                            const HChar* cc )
    281 {
    282    UChar* dst = ML_(dinfo_zalloc)(cc, size);
    283    if (size > 0)
    284       ML_(cur_read_get)(dst, c, size);
    285    return dst;
    286 }
    287 
    288 static inline UChar ML_(cur_read_UChar) ( DiCursor c ) {
    289    UChar r = ML_(img_get_UChar)( c.img, c.ioff );
    290    return r;
    291 }
    292 static inline UChar ML_(cur_step_UChar)( DiCursor* c ) {
    293    UChar r = ML_(img_get_UChar)( c->img, c->ioff );
    294    c->ioff += sizeof(UChar);
    295    return r;
    296 }
    297 
    298 static inline UShort ML_(cur_read_UShort) ( DiCursor c ) {
    299    UShort r = ML_(img_get_UShort)( c.img, c.ioff );
    300    return r;
    301 }
    302 static inline UShort ML_(cur_step_UShort) ( DiCursor* c ) {
    303    UShort r = ML_(img_get_UShort)( c->img, c->ioff );
    304    c->ioff += sizeof(UShort);
    305    return r;
    306 }
    307 static inline Short ML_(cur_step_Short) ( DiCursor* c ) {
    308    return (Short)ML_(cur_step_UShort)( c );
    309 }
    310 
    311 static inline UInt ML_(cur_read_UInt) ( DiCursor c ) {
    312    UInt r = ML_(img_get_UInt)( c.img, c.ioff );
    313    return r;
    314 }
    315 static inline UInt ML_(cur_step_UInt) ( DiCursor* c ) {
    316    UInt r = ML_(img_get_UInt)( c->img, c->ioff );
    317    c->ioff += sizeof(UInt);
    318    return r;
    319 }
    320 static inline Int ML_(cur_step_Int) ( DiCursor* c ) {
    321    return (Int)ML_(cur_step_UInt)( c );
    322 }
    323 
    324 static inline ULong ML_(cur_read_ULong) ( DiCursor c ) {
    325    ULong r = ML_(img_get_ULong)( c.img, c.ioff );
    326    return r;
    327 }
    328 static inline ULong ML_(cur_step_ULong) ( DiCursor* c ) {
    329    ULong r = ML_(img_get_ULong)( c->img, c->ioff );
    330    c->ioff += sizeof(ULong);
    331    return r;
    332 }
    333 static inline Long ML_(cur_step_Long) ( DiCursor* c ) {
    334    return (Long)ML_(cur_step_ULong)( c );
    335 }
    336 
    337 static inline Addr ML_(cur_step_Addr) ( DiCursor* c ) {
    338    if (sizeof(Addr) == sizeof(UInt)) {
    339       return ML_(cur_step_UInt)(c);
    340    } else if  (sizeof(Addr) == sizeof(ULong)) {
    341       return ML_(cur_step_ULong)(c);
    342    } else {
    343       vg_assert(0);
    344    }
    345 }
    346 
    347 #endif /* ndef __PRIV_IMAGE_H */
    348 
    349 /*--------------------------------------------------------------------*/
    350 /*--- end                                             priv_image.h ---*/
    351 /*--------------------------------------------------------------------*/
    352