2 /*--------------------------------------------------------------------*/
3 /*--- An abstraction that provides a file-reading mechanism. ---*/
4 /*--- priv_image.h ---*/
5 /*--------------------------------------------------------------------*/
8 This file is part of Valgrind, a dynamic binary instrumentation
11 Copyright (C) 2013-2017 Mozilla Foundation
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.
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.
23 You should have received a copy of the GNU General Public License
24 along with this program; if not, see <http://www.gnu.org/licenses/>.
26 The GNU General Public License is contained in the file COPYING.
29 /* Contributed by Julian Seward <jseward@acm.org> */
31 #ifndef __PRIV_IMAGE_H
32 #define __PRIV_IMAGE_H
34 #include "pub_core_basics.h" // ULong
35 #include "priv_misc.h" // ML_(dinfo_zalloc)
37 /*------------------------------------------------------------*/
38 /*--- DiImage -- abstract images ---*/
39 /*------------------------------------------------------------*/
41 /* The basic type, containing an abstractified memory area that can be
42 read from. This is an abstract type since there can be more than
43 one implementation of it. */
46 typedef struct _DiImage DiImage
;
48 /* an offset in the image */
51 /* This denotes an invalid DiOffT value. Except where otherwise
52 noted, you must never pass this to any of the ML_(image_*)
53 functions -- they will assert. That does mean though that they can
54 be used for signalling other conditions, for example that some
55 expected part of the image is missing. */
56 #define DiOffT_INVALID ((DiOffT)(0xFFFFFFFFFFFFFFFFULL))
58 /* Create an image from a file in the local filesysem. Returns NULL
59 if it fails, for whatever reason. */
60 DiImage
* ML_(img_from_local_file
)(const HChar
* fullpath
);
62 /* Create an image by connecting to a Valgrind debuginfo server
63 (auxprogs/valgrind-di-server.c). |filename| contains the object
64 name to ask for; it must be a plain filename, not absolute, not a
65 path. |serverAddr| must be of the form either "d.d.d.d" or
66 "d.d.d.d:d" where d is one or more digits. These specify the IPv4
67 address and (in the second case) port number for the server. In
68 the first case, port 1500 is assumed. */
69 DiImage
* ML_(img_from_di_server
)(const HChar
* filename
,
70 const HChar
* serverAddr
);
72 /* Destroy an existing image. */
73 void ML_(img_done
)(DiImage
*);
75 /* Virtual size of the image. */
76 DiOffT
ML_(img_size
)(const DiImage
* img
);
78 /* Real size of the image. */
79 DiOffT
ML_(img_real_size
)(const DiImage
* img
);
81 /* Does the section [offset, +size) exist in the image? */
82 Bool
ML_(img_valid
)(const DiImage
* img
, DiOffT offset
, SizeT size
);
84 /* Get info out of an image. If any part of the section denoted by
85 [offset, +size) is invalid, does not return. */
86 void ML_(img_get
)(/*OUT*/void* dst
,
87 DiImage
* img
, DiOffT offset
, SizeT size
);
89 /* A version of ML_(img_get) that is significantly cheaper when
90 fetching a lot of data, at the cost of being more difficult to use.
91 Fetches between 1 and |size| bytes from |img| at |offset| and
92 places them in |dst|. |size| must be at least 1. The number of
93 bytes read is returned, and the caller must be able to deal with
94 any number between 1 and |size|. |offset| must be a valid offset
95 in the image; if not the function will not return. This function
96 will not read off the end of the image. */
97 SizeT
ML_(img_get_some
)(/*OUT*/void* dst
,
98 DiImage
* img
, DiOffT offset
, SizeT size
);
100 /* Copy a C string out of the image, into ML_(dinfo_zalloc)'d space.
101 The caller owns the string and must free it with ML_(dinfo_free).
102 |offset| may be DiOffT_INVALID, in which case this returns NULL. */
103 HChar
* ML_(img_strdup
)(DiImage
* img
, const HChar
* cc
, DiOffT offset
);
105 /* Do strcmp on two C strings in the image. Chars are cast to HChar
106 before comparison. */
107 Int
ML_(img_strcmp
)(DiImage
* img
, DiOffT off1
, DiOffT off2
);
109 /* Do strcmp of a C string in the image vs a normal one. Chars are
110 cast to HChar before comparison. */
111 Int
ML_(img_strcmp_c
)(DiImage
* img
, DiOffT off1
, const HChar
* str2
);
113 /* Do strlen of a C string in the image. */
114 SizeT
ML_(img_strlen
)(DiImage
* img
, DiOffT off
);
116 /* Fetch various sized primitive types from the image. These operate
117 at the endianness and word size of the host. */
118 UChar
ML_(img_get_UChar
) (DiImage
* img
, DiOffT offset
);
119 UShort
ML_(img_get_UShort
)(DiImage
* img
, DiOffT offset
);
120 UInt
ML_(img_get_UInt
) (DiImage
* img
, DiOffT offset
);
121 ULong
ML_(img_get_ULong
) (DiImage
* img
, DiOffT offset
);
123 /* Calculate the "GNU Debuglink CRC" for the image. This
124 unfortunately has to be done as part of the DiImage implementation
125 because it involves reading the entire image, and is therefore
126 something that needs to be handed off to the remote server -- since
127 to do it otherwise would imply pulling the entire image across the
128 connection, making the client/server split pointless. */
129 UInt
ML_(img_calc_gnu_debuglink_crc32
)(DiImage
* img
);
131 /* Mark compressed part of image defined with (offset, szC).
132 szD is length of uncompressed data (should be known before decompression).
133 Returns (virtual) position in image from which decompressed data can be
135 DiOffT
ML_(img_mark_compressed_part
)(DiImage
* img
, DiOffT offset
, SizeT szC
,
139 /*------------------------------------------------------------*/
140 /*--- DiCursor -- cursors for reading images ---*/
141 /*------------------------------------------------------------*/
143 /* A type built on DiImage. It contains a DiImage and a 'current
144 offset' in the image, and is useful for building low level readers
145 of images. In the functions section below, "read" means "read data
146 at the cursor without moving it along", and "step" means "read data
147 at the cursor and move it along by the size of the item read". */
149 struct { DiImage
* img
; DiOffT ioff
; }
152 /* An invalid cursor. You can't use it for anything. */
153 #define DiCursor_INVALID ((DiCursor){NULL,DiOffT_INVALID})
155 static inline DiCursor
mk_DiCursor ( DiImage
* img
, DiOffT ioff
) {
156 return (DiCursor
){img
, ioff
};
159 static inline Bool
ML_(cur_is_valid
)(DiCursor c
) {
160 return c
.img
!= NULL
;
164 /*------------------------------------------------------------*/
165 /*--- DiSlice -- subranges within DiImages ---*/
166 /*------------------------------------------------------------*/
168 /* Another type built on top of DiImage. It denotes a subrange of an
169 image and is useful for representing (eg) exactly the part of an
170 image that is a specific ELF section. */
172 struct { DiImage
* img
; DiOffT ioff
; DiOffT szB
; }
175 /* A DiSlice can also be INVALID, meaning it does not refer to any
176 part of any image. */
177 #define DiSlice_INVALID ((DiSlice){NULL,DiOffT_INVALID,0})
179 static inline DiSlice
mk_DiSlice ( DiImage
* img
, DiOffT ioff
, DiOffT szB
) {
180 return (DiSlice
){img
, ioff
, szB
};
183 static inline Bool
ML_(sli_is_valid
)( DiSlice sli
) {
184 return sli
.img
!= NULL
;
187 /* Create a slice from a combination of a cursor and a length. The
188 maximum implied offset must not exceed the size of the underlying
189 image; this is asserted for. */
190 static inline DiSlice
ML_(sli_from_cur
)( DiCursor cur
, DiOffT size
) {
191 if (ML_(cur_is_valid
)(cur
)) {
192 vg_assert(size
!= DiOffT_INVALID
);
193 vg_assert(cur
.ioff
+ size
<= ML_(img_size
)(cur
.img
));
194 return mk_DiSlice(cur
.img
, cur
.ioff
, size
);
196 return DiSlice_INVALID
;
200 /* Create a slice which exactly covers the given image. */
201 static inline DiSlice
ML_(sli_from_img
)( DiImage
* img
) {
203 return mk_DiSlice(img
, 0, ML_(img_size
)(img
));
205 return DiSlice_INVALID
;
210 /*------------------------------------------------------------*/
211 /*--- Functions that operate on DiCursors ---*/
212 /*------------------------------------------------------------*/
214 /* Create a cursor from a slice, referring to the first byte of the
216 static inline DiCursor
ML_(cur_from_sli
)( DiSlice sl
) {
217 if (ML_(sli_is_valid
)(sl
)) {
223 return DiCursor_INVALID
;
227 static inline Bool
ML_(cur_cmpLT
)( DiCursor c1
, DiCursor c2
) {
228 vg_assert(c1
.img
== c2
.img
);
229 return c1
.ioff
< c2
.ioff
;
231 static inline Bool
ML_(cur_cmpEQ
)( DiCursor c1
, DiCursor c2
) {
232 vg_assert(c1
.img
== c2
.img
);
233 return c1
.ioff
== c2
.ioff
;
235 static inline Bool
ML_(cur_cmpGT
)( DiCursor c1
, DiCursor c2
) {
236 vg_assert(c1
.img
== c2
.img
);
237 return c1
.ioff
> c2
.ioff
;
240 static inline DiCursor
ML_(cur_plus
)( DiCursor c
, Long n
) {
245 /* Asserts that c1 and c2 refer to the same image. Returns the difference
246 in offsets (c1.ioff - c2.ioff). */
247 static inline Long
ML_(cur_minus
)( DiCursor c1
, DiCursor c2
) {
248 vg_assert(c1
.img
== c2
.img
);
249 return (Long
)(c1
.ioff
) - (Long
)(c2
.ioff
);
252 static inline SizeT
ML_(cur_strlen
)( DiCursor c
) {
253 return ML_(img_strlen
)( c
.img
, c
.ioff
);
256 // strdup from the given cursor. Caller must ML_(dinfo_free) the
258 static inline HChar
* ML_(cur_read_strdup
)( DiCursor c
, const HChar
* cc
) {
259 vg_assert(c
.ioff
!= DiOffT_INVALID
);
260 HChar
* res
= ML_(img_strdup
)(c
.img
, cc
, c
.ioff
);
263 // strdup from the given cursor and advance it. Caller must
264 // ML_(dinfo_free) the resulting string.
265 static inline HChar
* ML_(cur_step_strdup
)( DiCursor
* c
, const HChar
* cc
) {
266 vg_assert(c
->ioff
!= DiOffT_INVALID
);
267 HChar
* res
= ML_(img_strdup
)(c
->img
, cc
, c
->ioff
);
268 c
->ioff
+= VG_(strlen
)(res
) + 1;
272 // Fetch an arbitrary number of bytes from the cursor.
273 static inline void ML_(cur_read_get
) ( /*OUT*/void* dst
,
274 DiCursor c
, SizeT size
) {
275 ML_(img_get
)(dst
, c
.img
, c
.ioff
, size
);
278 // Fetch an arbitrary number of bytes from the cursor, and advance it.
279 static inline void ML_(cur_step_get
) ( /*OUT*/void* dst
,
280 DiCursor
* c
, SizeT size
) {
281 ML_(img_get
)(dst
, c
->img
, c
->ioff
, size
);
285 // memdup from the given cursor. Caller must ML_(dinfo_free) the
287 static inline UChar
* ML_(cur_read_memdup
)( DiCursor c
, SizeT size
,
290 UChar
* dst
= ML_(dinfo_zalloc
)(cc
, size
);
292 ML_(cur_read_get
)(dst
, c
, size
);
296 static inline UChar
ML_(cur_read_UChar
) ( DiCursor c
) {
297 UChar r
= ML_(img_get_UChar
)( c
.img
, c
.ioff
);
300 static inline UChar
ML_(cur_step_UChar
)( DiCursor
* c
) {
301 UChar r
= ML_(img_get_UChar
)( c
->img
, c
->ioff
);
302 c
->ioff
+= sizeof(UChar
);
306 static inline UShort
ML_(cur_read_UShort
) ( DiCursor c
) {
307 UShort r
= ML_(img_get_UShort
)( c
.img
, c
.ioff
);
310 static inline UShort
ML_(cur_step_UShort
) ( DiCursor
* c
) {
311 UShort r
= ML_(img_get_UShort
)( c
->img
, c
->ioff
);
312 c
->ioff
+= sizeof(UShort
);
315 static inline Short
ML_(cur_step_Short
) ( DiCursor
* c
) {
316 return (Short
)ML_(cur_step_UShort
)( c
);
319 static inline UInt
ML_(cur_read_UInt
) ( DiCursor c
) {
320 UInt r
= ML_(img_get_UInt
)( c
.img
, c
.ioff
);
323 static inline UInt
ML_(cur_step_UInt
) ( DiCursor
* c
) {
324 UInt r
= ML_(img_get_UInt
)( c
->img
, c
->ioff
);
325 c
->ioff
+= sizeof(UInt
);
328 static inline Int
ML_(cur_step_Int
) ( DiCursor
* c
) {
329 return (Int
)ML_(cur_step_UInt
)( c
);
332 static inline ULong
ML_(cur_read_ULong
) ( DiCursor c
) {
333 ULong r
= ML_(img_get_ULong
)( c
.img
, c
.ioff
);
336 static inline ULong
ML_(cur_step_ULong
) ( DiCursor
* c
) {
337 ULong r
= ML_(img_get_ULong
)( c
->img
, c
->ioff
);
338 c
->ioff
+= sizeof(ULong
);
341 static inline Long
ML_(cur_step_Long
) ( DiCursor
* c
) {
342 return (Long
)ML_(cur_step_ULong
)( c
);
345 static inline Addr
ML_(cur_step_Addr
) ( DiCursor
* c
) {
346 if (sizeof(Addr
) == sizeof(UInt
)) {
347 return ML_(cur_step_UInt
)(c
);
348 } else if (sizeof(Addr
) == sizeof(ULong
)) {
349 return ML_(cur_step_ULong
)(c
);
355 #endif /* ndef __PRIV_IMAGE_H */
357 /*--------------------------------------------------------------------*/
358 /*--- end priv_image.h ---*/
359 /*--------------------------------------------------------------------*/