s390x: Re-implement STFLE as an extension
[valgrind.git] / coregrind / m_debuginfo / priv_image.h
blobc91e49f015f4843ec75fa2b9a0de7257867f6491
2 /*--------------------------------------------------------------------*/
3 /*--- An abstraction that provides a file-reading mechanism. ---*/
4 /*--- priv_image.h ---*/
5 /*--------------------------------------------------------------------*/
7 /*
8 This file is part of Valgrind, a dynamic binary instrumentation
9 framework.
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. */
45 /* abstract */
46 typedef struct _DiImage DiImage;
48 /* an offset in the image */
49 typedef ULong DiOffT;
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 DiImage* ML_(img_from_fd)(Int fd, const HChar* fullpath);
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);
74 /* Free memory allocated for image. */
75 void ML_(img_free)(DiImage*);
77 /* Destroy an existing image. */
78 void ML_(img_done)(DiImage*);
80 /* Virtual size of the image. */
81 DiOffT ML_(img_size)(const DiImage* img);
83 /* Real size of the image. */
84 DiOffT ML_(img_real_size)(const DiImage* img);
86 /* Does the section [offset, +size) exist in the image? */
87 Bool ML_(img_valid)(const DiImage* img, DiOffT offset, SizeT size);
89 /* Get info out of an image. If any part of the section denoted by
90 [offset, +size) is invalid, does not return. */
91 void ML_(img_get)(/*OUT*/void* dst,
92 DiImage* img, DiOffT offset, SizeT size);
94 /* A version of ML_(img_get) that is significantly cheaper when
95 fetching a lot of data, at the cost of being more difficult to use.
96 Fetches between 1 and |size| bytes from |img| at |offset| and
97 places them in |dst|. |size| must be at least 1. The number of
98 bytes read is returned, and the caller must be able to deal with
99 any number between 1 and |size|. |offset| must be a valid offset
100 in the image; if not the function will not return. This function
101 will not read off the end of the image. */
102 SizeT ML_(img_get_some)(/*OUT*/void* dst,
103 DiImage* img, DiOffT offset, SizeT size);
105 /* Copy a C string out of the image, into ML_(dinfo_zalloc)'d space.
106 The caller owns the string and must free it with ML_(dinfo_free).
107 |offset| may be DiOffT_INVALID, in which case this returns NULL. */
108 HChar* ML_(img_strdup)(DiImage* img, const HChar* cc, DiOffT offset);
110 /* Do strcmp on two C strings in the image. Chars are cast to HChar
111 before comparison. */
112 Int ML_(img_strcmp)(DiImage* img, DiOffT off1, DiOffT off2);
114 /* Do strcmp of a C string in the image vs a normal one. Chars are
115 cast to HChar before comparison. */
116 Int ML_(img_strcmp_c)(DiImage* img, DiOffT off1, const HChar* str2);
118 /* Do strncmp of a C string in the image vs a normal one. Chars are
119 cast to HChar before comparison. */
120 Int ML_(img_strcmp_n)(DiImage* img, DiOffT off1, const HChar* str2, Word n);
122 /* Do strlen of a C string in the image. */
123 SizeT ML_(img_strlen)(DiImage* img, DiOffT off);
125 /* Fetch various sized primitive types from the image. These operate
126 at the endianness and word size of the host. */
127 UChar ML_(img_get_UChar) (DiImage* img, DiOffT offset);
128 UShort ML_(img_get_UShort)(DiImage* img, DiOffT offset);
129 UInt ML_(img_get_UInt) (DiImage* img, DiOffT offset);
130 ULong ML_(img_get_ULong) (DiImage* img, DiOffT offset);
132 /* Calculate the "GNU Debuglink CRC" for the image. This
133 unfortunately has to be done as part of the DiImage implementation
134 because it involves reading the entire image, and is therefore
135 something that needs to be handed off to the remote server -- since
136 to do it otherwise would imply pulling the entire image across the
137 connection, making the client/server split pointless. */
138 UInt ML_(img_calc_gnu_debuglink_crc32)(DiImage* img);
140 /* Mark compressed part of image defined with (offset, szC).
141 szD is length of uncompressed data (should be known before decompression).
142 Returns (virtual) position in image from which decompressed data can be
143 read. */
144 DiOffT ML_(img_mark_compressed_part)(DiImage* img, DiOffT offset, SizeT szC,
145 SizeT szD);
148 /*------------------------------------------------------------*/
149 /*--- DiCursor -- cursors for reading images ---*/
150 /*------------------------------------------------------------*/
152 /* A type built on DiImage. It contains a DiImage and a 'current
153 offset' in the image, and is useful for building low level readers
154 of images. In the functions section below, "read" means "read data
155 at the cursor without moving it along", and "step" means "read data
156 at the cursor and move it along by the size of the item read". */
157 typedef
158 struct { DiImage* img; DiOffT ioff; }
159 DiCursor;
161 /* An invalid cursor. You can't use it for anything. */
162 #define DiCursor_INVALID ((DiCursor){NULL,DiOffT_INVALID})
164 static inline DiCursor mk_DiCursor ( DiImage* img, DiOffT ioff ) {
165 return (DiCursor){img, ioff};
168 static inline Bool ML_(cur_is_valid)(DiCursor c) {
169 return c.img != NULL;
173 /*------------------------------------------------------------*/
174 /*--- DiSlice -- subranges within DiImages ---*/
175 /*------------------------------------------------------------*/
177 /* Another type built on top of DiImage. It denotes a subrange of an
178 image and is useful for representing (eg) exactly the part of an
179 image that is a specific ELF section. */
180 typedef
181 struct { DiImage* img; DiOffT ioff; DiOffT szB; }
182 DiSlice;
184 /* A DiSlice can also be INVALID, meaning it does not refer to any
185 part of any image. */
186 #define DiSlice_INVALID ((DiSlice){NULL,DiOffT_INVALID,0})
188 static inline DiSlice mk_DiSlice ( DiImage* img, DiOffT ioff, DiOffT szB ) {
189 return (DiSlice){img, ioff, szB};
192 static inline Bool ML_(sli_is_valid)( DiSlice sli ) {
193 return sli.img != NULL;
196 /* Create a slice from a combination of a cursor and a length. The
197 maximum implied offset must not exceed the size of the underlying
198 image; this is asserted for. */
199 static inline DiSlice ML_(sli_from_cur)( DiCursor cur, DiOffT size ) {
200 if (ML_(cur_is_valid)(cur)) {
201 vg_assert(size != DiOffT_INVALID);
202 vg_assert(cur.ioff + size <= ML_(img_size)(cur.img));
203 return mk_DiSlice(cur.img, cur.ioff, size);
204 } else {
205 return DiSlice_INVALID;
209 /* Create a slice which exactly covers the given image. */
210 static inline DiSlice ML_(sli_from_img)( DiImage* img ) {
211 if (img) {
212 return mk_DiSlice(img, 0, ML_(img_size)(img));
213 } else {
214 return DiSlice_INVALID;
219 /*------------------------------------------------------------*/
220 /*--- Functions that operate on DiCursors ---*/
221 /*------------------------------------------------------------*/
223 /* Create a cursor from a slice, referring to the first byte of the
224 slice. */
225 static inline DiCursor ML_(cur_from_sli)( DiSlice sl ) {
226 if (ML_(sli_is_valid)(sl)) {
227 DiCursor c;
228 c.img = sl.img;
229 c.ioff = sl.ioff;
230 return c;
231 } else {
232 return DiCursor_INVALID;
236 static inline Bool ML_(cur_cmpLT)( DiCursor c1, DiCursor c2 ) {
237 vg_assert(c1.img == c2.img);
238 return c1.ioff < c2.ioff;
240 static inline Bool ML_(cur_cmpEQ)( DiCursor c1, DiCursor c2 ) {
241 vg_assert(c1.img == c2.img);
242 return c1.ioff == c2.ioff;
244 static inline Bool ML_(cur_cmpGT)( DiCursor c1, DiCursor c2 ) {
245 vg_assert(c1.img == c2.img);
246 return c1.ioff > c2.ioff;
249 static inline DiCursor ML_(cur_plus)( DiCursor c, Long n ) {
250 c.ioff += (DiOffT)n;
251 return c;
254 /* Asserts that c1 and c2 refer to the same image. Returns the difference
255 in offsets (c1.ioff - c2.ioff). */
256 static inline Long ML_(cur_minus)( DiCursor c1, DiCursor c2 ) {
257 vg_assert(c1.img == c2.img);
258 return (Long)(c1.ioff) - (Long)(c2.ioff);
261 static inline SizeT ML_(cur_strlen)( DiCursor c ) {
262 return ML_(img_strlen)( c.img, c.ioff );
265 // strdup from the given cursor. Caller must ML_(dinfo_free) the
266 // resulting string.
267 static inline HChar* ML_(cur_read_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 return res;
272 // strdup from the given cursor and advance it. Caller must
273 // ML_(dinfo_free) the resulting string.
274 static inline HChar* ML_(cur_step_strdup)( DiCursor* c, const HChar* cc ) {
275 vg_assert(c->ioff != DiOffT_INVALID);
276 HChar* res = ML_(img_strdup)(c->img, cc, c->ioff);
277 c->ioff += VG_(strlen)(res) + 1;
278 return res;
281 // Fetch an arbitrary number of bytes from the cursor.
282 static inline void ML_(cur_read_get) ( /*OUT*/void* dst,
283 DiCursor c, SizeT size) {
284 ML_(img_get)(dst, c.img, c.ioff, size);
287 // Fetch an arbitrary number of bytes from the cursor, and advance it.
288 static inline void ML_(cur_step_get) ( /*OUT*/void* dst,
289 DiCursor* c, SizeT size) {
290 ML_(img_get)(dst, c->img, c->ioff, size);
291 c->ioff += size;
294 // memdup from the given cursor. Caller must ML_(dinfo_free) the
295 // resulting block.
296 static inline UChar* ML_(cur_read_memdup)( DiCursor c, SizeT size,
297 const HChar* cc )
299 UChar* dst = ML_(dinfo_zalloc)(cc, size);
300 if (size > 0)
301 ML_(cur_read_get)(dst, c, size);
302 return dst;
305 static inline UChar ML_(cur_read_UChar) ( DiCursor c ) {
306 UChar r = ML_(img_get_UChar)( c.img, c.ioff );
307 return r;
309 static inline UChar ML_(cur_step_UChar)( DiCursor* c ) {
310 UChar r = ML_(img_get_UChar)( c->img, c->ioff );
311 c->ioff += sizeof(UChar);
312 return r;
315 static inline UShort ML_(cur_read_UShort) ( DiCursor c ) {
316 UShort r = ML_(img_get_UShort)( c.img, c.ioff );
317 return r;
319 static inline UShort ML_(cur_step_UShort) ( DiCursor* c ) {
320 UShort r = ML_(img_get_UShort)( c->img, c->ioff );
321 c->ioff += sizeof(UShort);
322 return r;
324 static inline Short ML_(cur_step_Short) ( DiCursor* c ) {
325 return (Short)ML_(cur_step_UShort)( c );
328 static inline UInt ML_(cur_read_UInt) ( DiCursor c ) {
329 UInt r = ML_(img_get_UInt)( c.img, c.ioff );
330 return r;
332 static inline UInt ML_(cur_step_UInt) ( DiCursor* c ) {
333 UInt r = ML_(img_get_UInt)( c->img, c->ioff );
334 c->ioff += sizeof(UInt);
335 return r;
337 static inline Int ML_(cur_step_Int) ( DiCursor* c ) {
338 return (Int)ML_(cur_step_UInt)( c );
341 static inline ULong ML_(cur_read_ULong) ( DiCursor c ) {
342 ULong r = ML_(img_get_ULong)( c.img, c.ioff );
343 return r;
345 static inline ULong ML_(cur_step_ULong) ( DiCursor* c ) {
346 ULong r = ML_(img_get_ULong)( c->img, c->ioff );
347 c->ioff += sizeof(ULong);
348 return r;
350 static inline Long ML_(cur_step_Long) ( DiCursor* c ) {
351 return (Long)ML_(cur_step_ULong)( c );
354 static inline Addr ML_(cur_step_Addr) ( DiCursor* c ) {
355 if (sizeof(Addr) == sizeof(UInt)) {
356 return ML_(cur_step_UInt)(c);
357 } else if (sizeof(Addr) == sizeof(ULong)) {
358 return ML_(cur_step_ULong)(c);
359 } else {
360 vg_assert(0);
364 #endif /* ndef __PRIV_IMAGE_H */
366 /*--------------------------------------------------------------------*/
367 /*--- end priv_image.h ---*/
368 /*--------------------------------------------------------------------*/