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)(const DiImage* img); 79 80 /* Does the section [offset, +size) exist in the image? */ 81 Bool ML_(img_valid)(const 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