blob: 965a4a9bc9434758d3c4d0fbc9c048311a652e47 [file] [log] [blame]
sewardj5d616df2013-07-02 08:07:15 +00001
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 Hughesed398002017-06-21 14:41:24 -070011 Copyright (C) 2013-2017 Mozilla Foundation
sewardj5d616df2013-07-02 08:07:15 +000012
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
florian535fb1b2013-09-15 13:54:34 +000033#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)
sewardj5d616df2013-07-02 08:07:15 +000038
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 */
48typedef struct _DiImage DiImage;
49
50/* an offset in the image */
51typedef 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. */
62DiImage* 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. */
71DiImage* ML_(img_from_di_server)(const HChar* filename,
72 const HChar* serverAddr);
73
74/* Destroy an existing image. */
75void ML_(img_done)(DiImage*);
76
Elliott Hughesa0664b92017-04-18 17:46:52 -070077/* Virtual size of the image. */
florian518850b2014-10-22 22:25:30 +000078DiOffT ML_(img_size)(const DiImage* img);
sewardj5d616df2013-07-02 08:07:15 +000079
Elliott Hughesa0664b92017-04-18 17:46:52 -070080/* Real size of the image. */
81DiOffT ML_(img_real_size)(const DiImage* img);
82
sewardj5d616df2013-07-02 08:07:15 +000083/* Does the section [offset, +size) exist in the image? */
florian518850b2014-10-22 22:25:30 +000084Bool ML_(img_valid)(const DiImage* img, DiOffT offset, SizeT size);
sewardj5d616df2013-07-02 08:07:15 +000085
86/* Get info out of an image. If any part of the section denoted by
87 [offset, +size) is invalid, does not return. */
88void 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. */
99SizeT 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. */
105HChar* 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. */
109Int 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. */
113Int ML_(img_strcmp_c)(DiImage* img, DiOffT off1, const HChar* str2);
114
115/* Do strlen of a C string in the image. */
116SizeT 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. */
120UChar ML_(img_get_UChar) (DiImage* img, DiOffT offset);
121UShort ML_(img_get_UShort)(DiImage* img, DiOffT offset);
122UInt ML_(img_get_UInt) (DiImage* img, DiOffT offset);
123ULong 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. */
131UInt ML_(img_calc_gnu_debuglink_crc32)(DiImage* img);
132
Elliott Hughesa0664b92017-04-18 17:46:52 -0700133/* 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. */
137DiOffT ML_(img_mark_compressed_part)(DiImage* img, DiOffT offset, SizeT szC,
138 SizeT szD);
139
sewardj5d616df2013-07-02 08:07:15 +0000140
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". */
150typedef
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
157static inline DiCursor mk_DiCursor ( DiImage* img, DiOffT ioff ) {
158 return (DiCursor){img, ioff};
159}
160
161static 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. */
173typedef
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
181static inline DiSlice mk_DiSlice ( DiImage* img, DiOffT ioff, DiOffT szB ) {
182 return (DiSlice){img, ioff, szB};
183}
184
185static 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. */
192static 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. */
203static 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. */
218static 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
229static inline Bool ML_(cur_cmpLT)( DiCursor c1, DiCursor c2 ) {
230 vg_assert(c1.img == c2.img);
231 return c1.ioff < c2.ioff;
232}
233static inline Bool ML_(cur_cmpEQ)( DiCursor c1, DiCursor c2 ) {
234 vg_assert(c1.img == c2.img);
235 return c1.ioff == c2.ioff;
236}
237static inline Bool ML_(cur_cmpGT)( DiCursor c1, DiCursor c2 ) {
238 vg_assert(c1.img == c2.img);
239 return c1.ioff > c2.ioff;
240}
241
242static 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). */
249static 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
254static 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.
260static 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.
267static 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.
275static 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.
281static 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.
289static 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
298static inline UChar ML_(cur_read_UChar) ( DiCursor c ) {
299 UChar r = ML_(img_get_UChar)( c.img, c.ioff );
300 return r;
301}
302static 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
308static inline UShort ML_(cur_read_UShort) ( DiCursor c ) {
309 UShort r = ML_(img_get_UShort)( c.img, c.ioff );
310 return r;
311}
312static 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}
317static inline Short ML_(cur_step_Short) ( DiCursor* c ) {
318 return (Short)ML_(cur_step_UShort)( c );
319}
320
321static inline UInt ML_(cur_read_UInt) ( DiCursor c ) {
322 UInt r = ML_(img_get_UInt)( c.img, c.ioff );
323 return r;
324}
325static 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}
330static inline Int ML_(cur_step_Int) ( DiCursor* c ) {
331 return (Int)ML_(cur_step_UInt)( c );
332}
333
334static inline ULong ML_(cur_read_ULong) ( DiCursor c ) {
335 ULong r = ML_(img_get_ULong)( c.img, c.ioff );
336 return r;
337}
338static 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}
343static inline Long ML_(cur_step_Long) ( DiCursor* c ) {
344 return (Long)ML_(cur_step_ULong)( c );
345}
346
347static 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
florian535fb1b2013-09-15 13:54:34 +0000357#endif /* ndef __PRIV_IMAGE_H */
sewardj5d616df2013-07-02 08:07:15 +0000358
359/*--------------------------------------------------------------------*/
360/*--- end priv_image.h ---*/
361/*--------------------------------------------------------------------*/