mirror of
https://github.com/Zenithsiz/ftmemsim-valgrind.git
synced 2026-02-03 18:13:01 +00:00
352 lines
12 KiB
C
352 lines
12 KiB
C
|
|
/*--------------------------------------------------------------------*/
|
|
/*--- An abstraction that provides a file-reading mechanism. ---*/
|
|
/*--- priv_image.h ---*/
|
|
/*--------------------------------------------------------------------*/
|
|
|
|
/*
|
|
This file is part of Valgrind, a dynamic binary instrumentation
|
|
framework.
|
|
|
|
Copyright (C) 2013-2015 Mozilla Foundation
|
|
|
|
This program is free software; you can redistribute it and/or
|
|
modify it under the terms of the GNU General Public License as
|
|
published by the Free Software Foundation; either version 2 of the
|
|
License, or (at your option) any later version.
|
|
|
|
This program is distributed in the hope that it will be useful, but
|
|
WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
General Public License for more details.
|
|
|
|
You should have received a copy of the GNU General Public License
|
|
along with this program; if not, write to the Free Software
|
|
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
|
|
02111-1307, USA.
|
|
|
|
The GNU General Public License is contained in the file COPYING.
|
|
*/
|
|
|
|
/* Contributed by Julian Seward <jseward@acm.org> */
|
|
|
|
#ifndef __PRIV_IMAGE_H
|
|
#define __PRIV_IMAGE_H
|
|
|
|
#include "pub_core_basics.h" // ULong
|
|
#include "priv_misc.h" // ML_(dinfo_zalloc)
|
|
|
|
/*------------------------------------------------------------*/
|
|
/*--- DiImage -- abstract images ---*/
|
|
/*------------------------------------------------------------*/
|
|
|
|
/* The basic type, containing an abstractified memory area that can be
|
|
read from. This is an abstract type since there can be more than
|
|
one implementation of it. */
|
|
|
|
/* abstract */
|
|
typedef struct _DiImage DiImage;
|
|
|
|
/* an offset in the image */
|
|
typedef ULong DiOffT;
|
|
|
|
/* This denotes an invalid DiOffT value. Except where otherwise
|
|
noted, you must never pass this to any of the ML_(image_*)
|
|
functions -- they will assert. That does mean though that they can
|
|
be used for signalling other conditions, for example that some
|
|
expected part of the image is missing. */
|
|
#define DiOffT_INVALID ((DiOffT)(0xFFFFFFFFFFFFFFFFULL))
|
|
|
|
/* Create an image from a file in the local filesysem. Returns NULL
|
|
if it fails, for whatever reason. */
|
|
DiImage* ML_(img_from_local_file)(const HChar* fullpath);
|
|
|
|
/* Create an image by connecting to a Valgrind debuginfo server
|
|
(auxprogs/valgrind-di-server.c). |filename| contains the object
|
|
name to ask for; it must be a plain filename, not absolute, not a
|
|
path. |serverAddr| must be of the form either "d.d.d.d" or
|
|
"d.d.d.d:d" where d is one or more digits. These specify the IPv4
|
|
address and (in the second case) port number for the server. In
|
|
the first case, port 1500 is assumed. */
|
|
DiImage* ML_(img_from_di_server)(const HChar* filename,
|
|
const HChar* serverAddr);
|
|
|
|
/* Destroy an existing image. */
|
|
void ML_(img_done)(DiImage*);
|
|
|
|
/* How big is the image? */
|
|
DiOffT ML_(img_size)(const DiImage* img);
|
|
|
|
/* Does the section [offset, +size) exist in the image? */
|
|
Bool ML_(img_valid)(const DiImage* img, DiOffT offset, SizeT size);
|
|
|
|
/* Get info out of an image. If any part of the section denoted by
|
|
[offset, +size) is invalid, does not return. */
|
|
void ML_(img_get)(/*OUT*/void* dst,
|
|
DiImage* img, DiOffT offset, SizeT size);
|
|
|
|
/* A version of ML_(img_get) that is significantly cheaper when
|
|
fetching a lot of data, at the cost of being more difficult to use.
|
|
Fetches between 1 and |size| bytes from |img| at |offset| and
|
|
places them in |dst|. |size| must be at least 1. The number of
|
|
bytes read is returned, and the caller must be able to deal with
|
|
any number between 1 and |size|. |offset| must be a valid offset
|
|
in the image; if not the function will not return. This function
|
|
will not read off the end of the image. */
|
|
SizeT ML_(img_get_some)(/*OUT*/void* dst,
|
|
DiImage* img, DiOffT offset, SizeT size);
|
|
|
|
/* Copy a C string out of the image, into ML_(dinfo_zalloc)'d space.
|
|
The caller owns the string and must free it with ML_(dinfo_free).
|
|
|offset| may be DiOffT_INVALID, in which case this returns NULL. */
|
|
HChar* ML_(img_strdup)(DiImage* img, const HChar* cc, DiOffT offset);
|
|
|
|
/* Do strcmp on two C strings in the image. Chars are cast to HChar
|
|
before comparison. */
|
|
Int ML_(img_strcmp)(DiImage* img, DiOffT off1, DiOffT off2);
|
|
|
|
/* Do strcmp of a C string in the image vs a normal one. Chars are
|
|
cast to HChar before comparison. */
|
|
Int ML_(img_strcmp_c)(DiImage* img, DiOffT off1, const HChar* str2);
|
|
|
|
/* Do strlen of a C string in the image. */
|
|
SizeT ML_(img_strlen)(DiImage* img, DiOffT off);
|
|
|
|
/* Fetch various sized primitive types from the image. These operate
|
|
at the endianness and word size of the host. */
|
|
UChar ML_(img_get_UChar) (DiImage* img, DiOffT offset);
|
|
UShort ML_(img_get_UShort)(DiImage* img, DiOffT offset);
|
|
UInt ML_(img_get_UInt) (DiImage* img, DiOffT offset);
|
|
ULong ML_(img_get_ULong) (DiImage* img, DiOffT offset);
|
|
|
|
/* Calculate the "GNU Debuglink CRC" for the image. This
|
|
unfortunately has to be done as part of the DiImage implementation
|
|
because it involves reading the entire image, and is therefore
|
|
something that needs to be handed off to the remote server -- since
|
|
to do it otherwise would imply pulling the entire image across the
|
|
connection, making the client/server split pointless. */
|
|
UInt ML_(img_calc_gnu_debuglink_crc32)(DiImage* img);
|
|
|
|
|
|
/*------------------------------------------------------------*/
|
|
/*--- DiCursor -- cursors for reading images ---*/
|
|
/*------------------------------------------------------------*/
|
|
|
|
/* A type built on DiImage. It contains a DiImage and a 'current
|
|
offset' in the image, and is useful for building low level readers
|
|
of images. In the functions section below, "read" means "read data
|
|
at the cursor without moving it along", and "step" means "read data
|
|
at the cursor and move it along by the size of the item read". */
|
|
typedef
|
|
struct { DiImage* img; DiOffT ioff; }
|
|
DiCursor;
|
|
|
|
/* An invalid cursor. You can't use it for anything. */
|
|
#define DiCursor_INVALID ((DiCursor){NULL,DiOffT_INVALID})
|
|
|
|
static inline DiCursor mk_DiCursor ( DiImage* img, DiOffT ioff ) {
|
|
return (DiCursor){img, ioff};
|
|
}
|
|
|
|
static inline Bool ML_(cur_is_valid)(DiCursor c) {
|
|
return c.img != NULL;
|
|
}
|
|
|
|
|
|
/*------------------------------------------------------------*/
|
|
/*--- DiSlice -- subranges within DiImages ---*/
|
|
/*------------------------------------------------------------*/
|
|
|
|
/* Another type built on top of DiImage. It denotes a subrange of an
|
|
image and is useful for representing (eg) exactly the part of an
|
|
image that is a specific ELF section. */
|
|
typedef
|
|
struct { DiImage* img; DiOffT ioff; DiOffT szB; }
|
|
DiSlice;
|
|
|
|
/* A DiSlice can also be INVALID, meaning it does not refer to any
|
|
part of any image. */
|
|
#define DiSlice_INVALID ((DiSlice){NULL,DiOffT_INVALID,0})
|
|
|
|
static inline DiSlice mk_DiSlice ( DiImage* img, DiOffT ioff, DiOffT szB ) {
|
|
return (DiSlice){img, ioff, szB};
|
|
}
|
|
|
|
static inline Bool ML_(sli_is_valid)( DiSlice sli ) {
|
|
return sli.img != NULL;
|
|
}
|
|
|
|
/* Create a slice from a combination of a cursor and a length. The
|
|
maximum implied offset must not exceed the size of the underlying
|
|
image; this is asserted for. */
|
|
static inline DiSlice ML_(sli_from_cur)( DiCursor cur, DiOffT size ) {
|
|
if (ML_(cur_is_valid)(cur)) {
|
|
vg_assert(size != DiOffT_INVALID);
|
|
vg_assert(cur.ioff + size <= ML_(img_size)(cur.img));
|
|
return mk_DiSlice(cur.img, cur.ioff, size);
|
|
} else {
|
|
return DiSlice_INVALID;
|
|
}
|
|
}
|
|
|
|
/* Create a slice which exactly covers the given image. */
|
|
static inline DiSlice ML_(sli_from_img)( DiImage* img ) {
|
|
if (img) {
|
|
return mk_DiSlice(img, 0, ML_(img_size)(img));
|
|
} else {
|
|
return DiSlice_INVALID;
|
|
}
|
|
}
|
|
|
|
|
|
/*------------------------------------------------------------*/
|
|
/*--- Functions that operate on DiCursors ---*/
|
|
/*------------------------------------------------------------*/
|
|
|
|
/* Create a cursor from a slice, referring to the first byte of the
|
|
slice. */
|
|
static inline DiCursor ML_(cur_from_sli)( DiSlice sl ) {
|
|
if (ML_(sli_is_valid)(sl)) {
|
|
DiCursor c;
|
|
c.img = sl.img;
|
|
c.ioff = sl.ioff;
|
|
return c;
|
|
} else {
|
|
return DiCursor_INVALID;
|
|
}
|
|
}
|
|
|
|
static inline Bool ML_(cur_cmpLT)( DiCursor c1, DiCursor c2 ) {
|
|
vg_assert(c1.img == c2.img);
|
|
return c1.ioff < c2.ioff;
|
|
}
|
|
static inline Bool ML_(cur_cmpEQ)( DiCursor c1, DiCursor c2 ) {
|
|
vg_assert(c1.img == c2.img);
|
|
return c1.ioff == c2.ioff;
|
|
}
|
|
static inline Bool ML_(cur_cmpGT)( DiCursor c1, DiCursor c2 ) {
|
|
vg_assert(c1.img == c2.img);
|
|
return c1.ioff > c2.ioff;
|
|
}
|
|
|
|
static inline DiCursor ML_(cur_plus)( DiCursor c, Long n ) {
|
|
c.ioff += (DiOffT)n;
|
|
return c;
|
|
}
|
|
|
|
/* Asserts that c1 and c2 refer to the same image. Returns the difference
|
|
in offsets (c1.ioff - c2.ioff). */
|
|
static inline Long ML_(cur_minus)( DiCursor c1, DiCursor c2 ) {
|
|
vg_assert(c1.img == c2.img);
|
|
return (Long)(c1.ioff) - (Long)(c2.ioff);
|
|
}
|
|
|
|
static inline SizeT ML_(cur_strlen)( DiCursor c ) {
|
|
return ML_(img_strlen)( c.img, c.ioff );
|
|
}
|
|
|
|
// strdup from the given cursor. Caller must ML_(dinfo_free) the
|
|
// resulting string.
|
|
static inline HChar* ML_(cur_read_strdup)( DiCursor c, const HChar* cc ) {
|
|
vg_assert(c.ioff != DiOffT_INVALID);
|
|
HChar* res = ML_(img_strdup)(c.img, cc, c.ioff);
|
|
return res;
|
|
}
|
|
// strdup from the given cursor and advance it. Caller must
|
|
// ML_(dinfo_free) the resulting string.
|
|
static inline HChar* ML_(cur_step_strdup)( DiCursor* c, const HChar* cc ) {
|
|
vg_assert(c->ioff != DiOffT_INVALID);
|
|
HChar* res = ML_(img_strdup)(c->img, cc, c->ioff);
|
|
c->ioff += VG_(strlen)(res) + 1;
|
|
return res;
|
|
}
|
|
|
|
// Fetch an arbitrary number of bytes from the cursor.
|
|
static inline void ML_(cur_read_get) ( /*OUT*/void* dst,
|
|
DiCursor c, SizeT size) {
|
|
ML_(img_get)(dst, c.img, c.ioff, size);
|
|
}
|
|
|
|
// Fetch an arbitrary number of bytes from the cursor, and advance it.
|
|
static inline void ML_(cur_step_get) ( /*OUT*/void* dst,
|
|
DiCursor* c, SizeT size) {
|
|
ML_(img_get)(dst, c->img, c->ioff, size);
|
|
c->ioff += size;
|
|
}
|
|
|
|
// memdup from the given cursor. Caller must ML_(dinfo_free) the
|
|
// resulting block.
|
|
static inline UChar* ML_(cur_read_memdup)( DiCursor c, SizeT size,
|
|
const HChar* cc )
|
|
{
|
|
UChar* dst = ML_(dinfo_zalloc)(cc, size);
|
|
if (size > 0)
|
|
ML_(cur_read_get)(dst, c, size);
|
|
return dst;
|
|
}
|
|
|
|
static inline UChar ML_(cur_read_UChar) ( DiCursor c ) {
|
|
UChar r = ML_(img_get_UChar)( c.img, c.ioff );
|
|
return r;
|
|
}
|
|
static inline UChar ML_(cur_step_UChar)( DiCursor* c ) {
|
|
UChar r = ML_(img_get_UChar)( c->img, c->ioff );
|
|
c->ioff += sizeof(UChar);
|
|
return r;
|
|
}
|
|
|
|
static inline UShort ML_(cur_read_UShort) ( DiCursor c ) {
|
|
UShort r = ML_(img_get_UShort)( c.img, c.ioff );
|
|
return r;
|
|
}
|
|
static inline UShort ML_(cur_step_UShort) ( DiCursor* c ) {
|
|
UShort r = ML_(img_get_UShort)( c->img, c->ioff );
|
|
c->ioff += sizeof(UShort);
|
|
return r;
|
|
}
|
|
static inline Short ML_(cur_step_Short) ( DiCursor* c ) {
|
|
return (Short)ML_(cur_step_UShort)( c );
|
|
}
|
|
|
|
static inline UInt ML_(cur_read_UInt) ( DiCursor c ) {
|
|
UInt r = ML_(img_get_UInt)( c.img, c.ioff );
|
|
return r;
|
|
}
|
|
static inline UInt ML_(cur_step_UInt) ( DiCursor* c ) {
|
|
UInt r = ML_(img_get_UInt)( c->img, c->ioff );
|
|
c->ioff += sizeof(UInt);
|
|
return r;
|
|
}
|
|
static inline Int ML_(cur_step_Int) ( DiCursor* c ) {
|
|
return (Int)ML_(cur_step_UInt)( c );
|
|
}
|
|
|
|
static inline ULong ML_(cur_read_ULong) ( DiCursor c ) {
|
|
ULong r = ML_(img_get_ULong)( c.img, c.ioff );
|
|
return r;
|
|
}
|
|
static inline ULong ML_(cur_step_ULong) ( DiCursor* c ) {
|
|
ULong r = ML_(img_get_ULong)( c->img, c->ioff );
|
|
c->ioff += sizeof(ULong);
|
|
return r;
|
|
}
|
|
static inline Long ML_(cur_step_Long) ( DiCursor* c ) {
|
|
return (Long)ML_(cur_step_ULong)( c );
|
|
}
|
|
|
|
static inline Addr ML_(cur_step_Addr) ( DiCursor* c ) {
|
|
if (sizeof(Addr) == sizeof(UInt)) {
|
|
return ML_(cur_step_UInt)(c);
|
|
} else if (sizeof(Addr) == sizeof(ULong)) {
|
|
return ML_(cur_step_ULong)(c);
|
|
} else {
|
|
vg_assert(0);
|
|
}
|
|
}
|
|
|
|
#endif /* ndef __PRIV_IMAGE_H */
|
|
|
|
/*--------------------------------------------------------------------*/
|
|
/*--- end priv_image.h ---*/
|
|
/*--------------------------------------------------------------------*/
|