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-2017 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 /* Virtual size of the image. */
     78 DiOffT ML_(img_size)(const DiImage* img);
     79 
     80 /* Real size of the image. */
     81 DiOffT ML_(img_real_size)(const DiImage* img);
     82 
     83 /* Does the section [offset, +size) exist in the image? */
     84 Bool ML_(img_valid)(const DiImage* img, DiOffT offset, SizeT size);
     85 
     86 /* Get info out of an image.  If any part of the section denoted by
     87    [offset, +size) is invalid, does not return. */
     88 void ML_(img_get)(/*OUT*/void* dst,
     89                   DiImage* img, DiOffT offset, SizeT size);
     90 
     91 /* A version of ML_(img_get) that is significantly cheaper when
     92    fetching a lot of data, at the cost of being more difficult to use.
     93    Fetches between 1 and |size| bytes from |img| at |offset| and
     94    places them in |dst|.  |size| must be at least 1.  The number of
     95    bytes read is returned, and the caller must be able to deal with
     96    any number between 1 and |size|.  |offset| must be a valid offset
     97    in the image; if not the function will not return.  This function
     98    will not read off the end of the image. */
     99 SizeT ML_(img_get_some)(/*OUT*/void* dst,
    100                         DiImage* img, DiOffT offset, SizeT size);
    101 
    102 /* Copy a C string out of the image, into ML_(dinfo_zalloc)'d space.
    103    The caller owns the string and must free it with ML_(dinfo_free).
    104    |offset| may be DiOffT_INVALID, in which case this returns NULL. */
    105 HChar* ML_(img_strdup)(DiImage* img, const HChar* cc, DiOffT offset);
    106 
    107 /* Do strcmp on two C strings in the image.  Chars are cast to HChar
    108    before comparison. */
    109 Int ML_(img_strcmp)(DiImage* img, DiOffT off1, DiOffT off2);
    110 
    111 /* Do strcmp of a C string in the image vs a normal one.  Chars are
    112    cast to HChar before comparison. */
    113 Int ML_(img_strcmp_c)(DiImage* img, DiOffT off1, const HChar* str2);
    114 
    115 /* Do strlen of a C string in the image. */
    116 SizeT ML_(img_strlen)(DiImage* img, DiOffT off);
    117 
    118 /* Fetch various sized primitive types from the image.  These operate
    119    at the endianness and word size of the host. */
    120 UChar  ML_(img_get_UChar) (DiImage* img, DiOffT offset);
    121 UShort ML_(img_get_UShort)(DiImage* img, DiOffT offset);
    122 UInt   ML_(img_get_UInt)  (DiImage* img, DiOffT offset);
    123 ULong  ML_(img_get_ULong) (DiImage* img, DiOffT offset);
    124 
    125 /* Calculate the "GNU Debuglink CRC" for the image.  This
    126    unfortunately has to be done as part of the DiImage implementation
    127    because it involves reading the entire image, and is therefore
    128    something that needs to be handed off to the remote server -- since
    129    to do it otherwise would imply pulling the entire image across the
    130    connection, making the client/server split pointless. */
    131 UInt ML_(img_calc_gnu_debuglink_crc32)(DiImage* img);
    132 
    133 /* Mark compressed part of image defined with (offset, szC).
    134    szD is length of uncompressed data (should be known before decompression).
    135    Returns (virtual) position in image from which decompressed data can be
    136    read. */
    137 DiOffT ML_(img_mark_compressed_part)(DiImage* img, DiOffT offset, SizeT szC,
    138                                      SizeT szD);
    139 
    140 
    141 /*------------------------------------------------------------*/
    142 /*--- DiCursor -- cursors for reading images               ---*/
    143 /*------------------------------------------------------------*/
    144 
    145 /* A type built on DiImage.  It contains a DiImage and a 'current
    146    offset' in the image, and is useful for building low level readers
    147    of images.  In the functions section below, "read" means "read data
    148    at the cursor without moving it along", and "step" means "read data
    149    at the cursor and move it along by the size of the item read". */
    150 typedef
    151    struct { DiImage* img; DiOffT ioff; }
    152    DiCursor;
    153 
    154 /* An invalid cursor.  You can't use it for anything. */
    155 #define DiCursor_INVALID ((DiCursor){NULL,DiOffT_INVALID})
    156 
    157 static inline DiCursor mk_DiCursor ( DiImage* img, DiOffT ioff ) {
    158    return (DiCursor){img, ioff};
    159 }
    160 
    161 static inline Bool ML_(cur_is_valid)(DiCursor c) {
    162    return c.img != NULL;
    163 }
    164 
    165 
    166 /*------------------------------------------------------------*/
    167 /*--- DiSlice -- subranges within DiImages                 ---*/
    168 /*------------------------------------------------------------*/
    169 
    170 /* Another type built on top of DiImage.  It denotes a subrange of an
    171    image and is useful for representing (eg) exactly the part of an
    172    image that is a specific ELF section. */
    173 typedef
    174    struct { DiImage* img; DiOffT ioff; DiOffT szB; }
    175    DiSlice;
    176 
    177 /* A DiSlice can also be INVALID, meaning it does not refer to any
    178    part of any image. */
    179 #define DiSlice_INVALID ((DiSlice){NULL,DiOffT_INVALID,0})
    180 
    181 static inline DiSlice mk_DiSlice ( DiImage* img, DiOffT ioff, DiOffT szB ) {
    182    return (DiSlice){img, ioff, szB};
    183 }
    184 
    185 static inline Bool ML_(sli_is_valid)( DiSlice sli ) {
    186    return sli.img != NULL;
    187 }
    188 
    189 /* Create a slice from a combination of a cursor and a length.  The
    190    maximum implied offset must not exceed the size of the underlying
    191    image; this is asserted for. */
    192 static inline DiSlice ML_(sli_from_cur)( DiCursor cur, DiOffT size ) {
    193    if (ML_(cur_is_valid)(cur)) {
    194       vg_assert(size != DiOffT_INVALID);
    195       vg_assert(cur.ioff + size <= ML_(img_size)(cur.img));
    196       return mk_DiSlice(cur.img, cur.ioff, size);
    197    } else {
    198       return DiSlice_INVALID;
    199    }
    200 }
    201 
    202 /* Create a slice which exactly covers the given image. */
    203 static inline DiSlice ML_(sli_from_img)( DiImage* img ) {
    204    if (img) {
    205       return mk_DiSlice(img, 0, ML_(img_size)(img));
    206    } else {
    207       return DiSlice_INVALID;
    208    }
    209 }
    210 
    211 
    212 /*------------------------------------------------------------*/
    213 /*--- Functions that operate on DiCursors                  ---*/
    214 /*------------------------------------------------------------*/
    215 
    216 /* Create a cursor from a slice, referring to the first byte of the
    217    slice. */
    218 static inline DiCursor ML_(cur_from_sli)( DiSlice sl ) {
    219    if (ML_(sli_is_valid)(sl)) {
    220       DiCursor c;
    221       c.img  = sl.img;
    222       c.ioff = sl.ioff;
    223       return c;
    224    } else {
    225       return DiCursor_INVALID;
    226    }
    227 }
    228 
    229 static inline Bool ML_(cur_cmpLT)( DiCursor c1, DiCursor c2 ) {
    230    vg_assert(c1.img == c2.img);
    231    return c1.ioff < c2.ioff;
    232 }
    233 static inline Bool ML_(cur_cmpEQ)( DiCursor c1, DiCursor c2 ) {
    234    vg_assert(c1.img == c2.img);
    235    return c1.ioff == c2.ioff;
    236 }
    237 static inline Bool ML_(cur_cmpGT)( DiCursor c1, DiCursor c2 ) {
    238    vg_assert(c1.img == c2.img);
    239    return c1.ioff > c2.ioff;
    240 }
    241 
    242 static inline DiCursor ML_(cur_plus)( DiCursor c, Long n ) {
    243    c.ioff += (DiOffT)n;
    244    return c;
    245 }
    246 
    247 /* Asserts that c1 and c2 refer to the same image.  Returns the difference
    248    in offsets (c1.ioff - c2.ioff). */
    249 static inline Long ML_(cur_minus)( DiCursor c1, DiCursor c2 ) {
    250    vg_assert(c1.img == c2.img);
    251    return (Long)(c1.ioff) - (Long)(c2.ioff);
    252 }
    253 
    254 static inline SizeT ML_(cur_strlen)( DiCursor c ) {
    255    return ML_(img_strlen)( c.img, c.ioff );
    256 }
    257 
    258 // strdup from the given cursor.  Caller must ML_(dinfo_free) the
    259 // resulting string.
    260 static inline HChar* ML_(cur_read_strdup)( DiCursor c, const HChar* cc ) {
    261    vg_assert(c.ioff != DiOffT_INVALID);
    262    HChar* res = ML_(img_strdup)(c.img, cc, c.ioff);
    263    return res;
    264 }
    265 // strdup from the given cursor and advance it.  Caller must
    266 // ML_(dinfo_free) the resulting string.
    267 static inline HChar* ML_(cur_step_strdup)( DiCursor* c, const HChar* cc ) {
    268    vg_assert(c->ioff != DiOffT_INVALID);
    269    HChar* res = ML_(img_strdup)(c->img, cc, c->ioff);
    270    c->ioff += VG_(strlen)(res) + 1;
    271    return res;
    272 }
    273 
    274 // Fetch an arbitrary number of bytes from the cursor.
    275 static inline void ML_(cur_read_get) ( /*OUT*/void* dst,
    276                                        DiCursor c, SizeT size) {
    277    ML_(img_get)(dst, c.img, c.ioff, size);
    278 }
    279 
    280 // Fetch an arbitrary number of bytes from the cursor, and advance it.
    281 static inline void ML_(cur_step_get) ( /*OUT*/void* dst,
    282                                        DiCursor* c, SizeT size) {
    283    ML_(img_get)(dst, c->img, c->ioff, size);
    284    c->ioff += size;
    285 }
    286 
    287 // memdup from the given cursor.  Caller must ML_(dinfo_free) the
    288 // resulting block.
    289 static inline UChar* ML_(cur_read_memdup)( DiCursor c, SizeT size,
    290                                            const HChar* cc )
    291 {
    292    UChar* dst = ML_(dinfo_zalloc)(cc, size);
    293    if (size > 0)
    294       ML_(cur_read_get)(dst, c, size);
    295    return dst;
    296 }
    297 
    298 static inline UChar ML_(cur_read_UChar) ( DiCursor c ) {
    299    UChar r = ML_(img_get_UChar)( c.img, c.ioff );
    300    return r;
    301 }
    302 static inline UChar ML_(cur_step_UChar)( DiCursor* c ) {
    303    UChar r = ML_(img_get_UChar)( c->img, c->ioff );
    304    c->ioff += sizeof(UChar);
    305    return r;
    306 }
    307 
    308 static inline UShort ML_(cur_read_UShort) ( DiCursor c ) {
    309    UShort r = ML_(img_get_UShort)( c.img, c.ioff );
    310    return r;
    311 }
    312 static inline UShort ML_(cur_step_UShort) ( DiCursor* c ) {
    313    UShort r = ML_(img_get_UShort)( c->img, c->ioff );
    314    c->ioff += sizeof(UShort);
    315    return r;
    316 }
    317 static inline Short ML_(cur_step_Short) ( DiCursor* c ) {
    318    return (Short)ML_(cur_step_UShort)( c );
    319 }
    320 
    321 static inline UInt ML_(cur_read_UInt) ( DiCursor c ) {
    322    UInt r = ML_(img_get_UInt)( c.img, c.ioff );
    323    return r;
    324 }
    325 static inline UInt ML_(cur_step_UInt) ( DiCursor* c ) {
    326    UInt r = ML_(img_get_UInt)( c->img, c->ioff );
    327    c->ioff += sizeof(UInt);
    328    return r;
    329 }
    330 static inline Int ML_(cur_step_Int) ( DiCursor* c ) {
    331    return (Int)ML_(cur_step_UInt)( c );
    332 }
    333 
    334 static inline ULong ML_(cur_read_ULong) ( DiCursor c ) {
    335    ULong r = ML_(img_get_ULong)( c.img, c.ioff );
    336    return r;
    337 }
    338 static inline ULong ML_(cur_step_ULong) ( DiCursor* c ) {
    339    ULong r = ML_(img_get_ULong)( c->img, c->ioff );
    340    c->ioff += sizeof(ULong);
    341    return r;
    342 }
    343 static inline Long ML_(cur_step_Long) ( DiCursor* c ) {
    344    return (Long)ML_(cur_step_ULong)( c );
    345 }
    346 
    347 static inline Addr ML_(cur_step_Addr) ( DiCursor* c ) {
    348    if (sizeof(Addr) == sizeof(UInt)) {
    349       return ML_(cur_step_UInt)(c);
    350    } else if  (sizeof(Addr) == sizeof(ULong)) {
    351       return ML_(cur_step_ULong)(c);
    352    } else {
    353       vg_assert(0);
    354    }
    355 }
    356 
    357 #endif /* ndef __PRIV_IMAGE_H */
    358 
    359 /*--------------------------------------------------------------------*/
    360 /*--- end                                             priv_image.h ---*/
    361 /*--------------------------------------------------------------------*/
    362