sewardj | 5d616df | 2013-07-02 08:07:15 +0000 | [diff] [blame] | 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 | |
Elliott Hughes | ed39800 | 2017-06-21 14:41:24 -0700 | [diff] [blame^] | 11 | Copyright (C) 2013-2017 Mozilla Foundation |
sewardj | 5d616df | 2013-07-02 08:07:15 +0000 | [diff] [blame] | 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@acm.org> */ |
| 32 | |
florian | 535fb1b | 2013-09-15 13:54:34 +0000 | [diff] [blame] | 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) |
sewardj | 5d616df | 2013-07-02 08:07:15 +0000 | [diff] [blame] | 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 | |
Elliott Hughes | a0664b9 | 2017-04-18 17:46:52 -0700 | [diff] [blame] | 77 | /* Virtual size of the image. */ |
florian | 518850b | 2014-10-22 22:25:30 +0000 | [diff] [blame] | 78 | DiOffT ML_(img_size)(const DiImage* img); |
sewardj | 5d616df | 2013-07-02 08:07:15 +0000 | [diff] [blame] | 79 | |
Elliott Hughes | a0664b9 | 2017-04-18 17:46:52 -0700 | [diff] [blame] | 80 | /* Real size of the image. */ |
| 81 | DiOffT ML_(img_real_size)(const DiImage* img); |
| 82 | |
sewardj | 5d616df | 2013-07-02 08:07:15 +0000 | [diff] [blame] | 83 | /* Does the section [offset, +size) exist in the image? */ |
florian | 518850b | 2014-10-22 22:25:30 +0000 | [diff] [blame] | 84 | Bool ML_(img_valid)(const DiImage* img, DiOffT offset, SizeT size); |
sewardj | 5d616df | 2013-07-02 08:07:15 +0000 | [diff] [blame] | 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 | |
Elliott Hughes | a0664b9 | 2017-04-18 17:46:52 -0700 | [diff] [blame] | 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 | |
sewardj | 5d616df | 2013-07-02 08:07:15 +0000 | [diff] [blame] | 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 | |
florian | 535fb1b | 2013-09-15 13:54:34 +0000 | [diff] [blame] | 357 | #endif /* ndef __PRIV_IMAGE_H */ |
sewardj | 5d616df | 2013-07-02 08:07:15 +0000 | [diff] [blame] | 358 | |
| 359 | /*--------------------------------------------------------------------*/ |
| 360 | /*--- end priv_image.h ---*/ |
| 361 | /*--------------------------------------------------------------------*/ |