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@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 */
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
77/* How big is the image? */
78DiOffT ML_(img_size)(const DiImage* img);
79
80/* Does the section [offset, +size) exist in the image? */
81Bool 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. */
85void 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. */
96SizeT 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. */
102HChar* 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. */
106Int 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. */
110Int ML_(img_strcmp_c)(DiImage* img, DiOffT off1, const HChar* str2);
111
112/* Do strlen of a C string in the image. */
113SizeT 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. */
117UChar  ML_(img_get_UChar) (DiImage* img, DiOffT offset);
118UShort ML_(img_get_UShort)(DiImage* img, DiOffT offset);
119UInt   ML_(img_get_UInt)  (DiImage* img, DiOffT offset);
120ULong  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. */
128UInt 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". */
140typedef
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
147static inline DiCursor mk_DiCursor ( DiImage* img, DiOffT ioff ) {
148   return (DiCursor){img, ioff};
149}
150
151static 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. */
163typedef
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
171static inline DiSlice mk_DiSlice ( DiImage* img, DiOffT ioff, DiOffT szB ) {
172   return (DiSlice){img, ioff, szB};
173}
174
175static 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. */
182static 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. */
193static 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. */
208static 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
219static inline Bool ML_(cur_cmpLT)( DiCursor c1, DiCursor c2 ) {
220   vg_assert(c1.img == c2.img);
221   return c1.ioff < c2.ioff;
222}
223static inline Bool ML_(cur_cmpEQ)( DiCursor c1, DiCursor c2 ) {
224   vg_assert(c1.img == c2.img);
225   return c1.ioff == c2.ioff;
226}
227static inline Bool ML_(cur_cmpGT)( DiCursor c1, DiCursor c2 ) {
228   vg_assert(c1.img == c2.img);
229   return c1.ioff > c2.ioff;
230}
231
232static 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). */
239static 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
244static 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.
250static 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.
257static 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.
265static 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.
271static 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.
279static 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
288static inline UChar ML_(cur_read_UChar) ( DiCursor c ) {
289   UChar r = ML_(img_get_UChar)( c.img, c.ioff );
290   return r;
291}
292static 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
298static inline UShort ML_(cur_read_UShort) ( DiCursor c ) {
299   UShort r = ML_(img_get_UShort)( c.img, c.ioff );
300   return r;
301}
302static 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}
307static inline Short ML_(cur_step_Short) ( DiCursor* c ) {
308   return (Short)ML_(cur_step_UShort)( c );
309}
310
311static inline UInt ML_(cur_read_UInt) ( DiCursor c ) {
312   UInt r = ML_(img_get_UInt)( c.img, c.ioff );
313   return r;
314}
315static 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}
320static inline Int ML_(cur_step_Int) ( DiCursor* c ) {
321   return (Int)ML_(cur_step_UInt)( c );
322}
323
324static inline ULong ML_(cur_read_ULong) ( DiCursor c ) {
325   ULong r = ML_(img_get_ULong)( c.img, c.ioff );
326   return r;
327}
328static 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}
333static inline Long ML_(cur_step_Long) ( DiCursor* c ) {
334   return (Long)ML_(cur_step_ULong)( c );
335}
336
337static 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