Import magic library from llvm-apps

Change-Id: Icfbcfae6afc731a23e71448a7a5d0045b2c219e5
This commit is contained in:
David van Moolenbroek 2015-06-30 18:19:11 +02:00
parent 3e457fe321
commit 0acd3f1ae0
41 changed files with 20304 additions and 0 deletions

View file

@ -0,0 +1,940 @@
/*
Copyright (c) 2003-2013, Troy D. Hanson http://troydhanson.github.com/uthash/
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef UTHASH_H
#define UTHASH_H
#include <string.h> /* memcmp,strlen */
#include <stddef.h> /* ptrdiff_t */
#include <stdlib.h> /* exit() */
/* These macros use decltype or the earlier __typeof GNU extension.
As decltype is only available in newer compilers (VS2010 or gcc 4.3+
when compiling c++ source) this code uses whatever method is needed
or, for VS2008 where neither is available, uses casting workarounds. */
#ifdef _MSC_VER /* MS compiler */
#if _MSC_VER >= 1600 && defined(__cplusplus) /* VS2010 or newer in C++ mode */
#define DECLTYPE(x) (decltype(x))
#else /* VS2008 or older (or VS2010 in C mode) */
#define NO_DECLTYPE
#define DECLTYPE(x)
#endif
#else /* GNU, Sun and other compilers */
#define DECLTYPE(x) (__typeof(x))
#endif
#ifdef NO_DECLTYPE
#define DECLTYPE_ASSIGN(dst,src) \
do { \
char **_da_dst = (char**)(&(dst)); \
*_da_dst = (char*)(src); \
} while(0)
#else
#define DECLTYPE_ASSIGN(dst,src) \
do { \
(dst) = DECLTYPE(dst)(src); \
} while(0)
#endif
/* a number of the hash function use uint32_t which isn't defined on win32 */
#ifdef _MSC_VER
typedef unsigned int uint32_t;
typedef unsigned char uint8_t;
#else
#include <inttypes.h> /* uint32_t */
#endif
#define UTHASH_VERSION 1.9.8
#ifndef uthash_fatal
#define uthash_fatal(msg) exit(-1) /* fatal error (out of memory,etc) */
#endif
#ifndef uthash_malloc
#define uthash_malloc(sz) malloc(sz) /* malloc fcn */
#endif
#ifndef uthash_free
#define uthash_free(ptr,sz) free(ptr) /* free fcn */
#endif
#ifndef uthash_noexpand_fyi
#define uthash_noexpand_fyi(tbl) /* can be defined to log noexpand */
#endif
#ifndef uthash_expand_fyi
#define uthash_expand_fyi(tbl) /* can be defined to log expands */
#endif
/* initial number of buckets */
#define HASH_INITIAL_NUM_BUCKETS 32 /* initial number of buckets */
#define HASH_INITIAL_NUM_BUCKETS_LOG2 5 /* lg2 of initial number of buckets */
#define HASH_BKT_CAPACITY_THRESH 10 /* expand when bucket count reaches */
/* calculate the element whose hash handle address is hhe */
#define ELMT_FROM_HH(tbl,hhp) ((void*)(((char*)(hhp)) - ((tbl)->hho)))
#define HASH_FIND(hh,head,keyptr,keylen,out) \
do { \
unsigned _hf_bkt,_hf_hashv; \
out=NULL; \
if (head) { \
HASH_FCN(keyptr,keylen, (head)->hh.tbl->num_buckets, _hf_hashv, _hf_bkt); \
if (HASH_BLOOM_TEST((head)->hh.tbl, _hf_hashv)) { \
HASH_FIND_IN_BKT((head)->hh.tbl, hh, (head)->hh.tbl->buckets[ _hf_bkt ], \
keyptr,keylen,out); \
} \
} \
} while (0)
#ifdef HASH_BLOOM
#define HASH_BLOOM_BITLEN (1ULL << HASH_BLOOM)
#define HASH_BLOOM_BYTELEN (HASH_BLOOM_BITLEN/8) + ((HASH_BLOOM_BITLEN%8) ? 1:0)
#define HASH_BLOOM_MAKE(tbl) \
do { \
(tbl)->bloom_nbits = HASH_BLOOM; \
(tbl)->bloom_bv = (uint8_t*)uthash_malloc(HASH_BLOOM_BYTELEN); \
if (!((tbl)->bloom_bv)) { uthash_fatal( "out of memory"); } \
memset((tbl)->bloom_bv, 0, HASH_BLOOM_BYTELEN); \
(tbl)->bloom_sig = HASH_BLOOM_SIGNATURE; \
} while (0)
#define HASH_BLOOM_FREE(tbl) \
do { \
uthash_free((tbl)->bloom_bv, HASH_BLOOM_BYTELEN); \
} while (0)
#define HASH_BLOOM_BITSET(bv,idx) (bv[(idx)/8] |= (1U << ((idx)%8)))
#define HASH_BLOOM_BITTEST(bv,idx) (bv[(idx)/8] & (1U << ((idx)%8)))
#define HASH_BLOOM_ADD(tbl,hashv) \
HASH_BLOOM_BITSET((tbl)->bloom_bv, (hashv & (uint32_t)((1ULL << (tbl)->bloom_nbits) - 1)))
#define HASH_BLOOM_TEST(tbl,hashv) \
HASH_BLOOM_BITTEST((tbl)->bloom_bv, (hashv & (uint32_t)((1ULL << (tbl)->bloom_nbits) - 1)))
#else
#define HASH_BLOOM_MAKE(tbl)
#define HASH_BLOOM_FREE(tbl)
#define HASH_BLOOM_ADD(tbl,hashv)
#define HASH_BLOOM_TEST(tbl,hashv) (1)
#define HASH_BLOOM_BYTELEN 0
#endif
#define HASH_MAKE_TABLE(hh,head) \
do { \
(head)->hh.tbl = (UT_hash_table*)uthash_malloc( \
sizeof(UT_hash_table)); \
if (!((head)->hh.tbl)) { uthash_fatal( "out of memory"); } \
memset((head)->hh.tbl, 0, sizeof(UT_hash_table)); \
(head)->hh.tbl->tail = &((head)->hh); \
(head)->hh.tbl->num_buckets = HASH_INITIAL_NUM_BUCKETS; \
(head)->hh.tbl->log2_num_buckets = HASH_INITIAL_NUM_BUCKETS_LOG2; \
(head)->hh.tbl->hho = (char*)(&(head)->hh) - (char*)(head); \
(head)->hh.tbl->buckets = (UT_hash_bucket*)uthash_malloc( \
HASH_INITIAL_NUM_BUCKETS*sizeof(struct UT_hash_bucket)); \
if (! (head)->hh.tbl->buckets) { uthash_fatal( "out of memory"); } \
memset((head)->hh.tbl->buckets, 0, \
HASH_INITIAL_NUM_BUCKETS*sizeof(struct UT_hash_bucket)); \
HASH_BLOOM_MAKE((head)->hh.tbl); \
(head)->hh.tbl->signature = HASH_SIGNATURE; \
} while(0)
#define HASH_ADD(hh,head,fieldname,keylen_in,add) \
HASH_ADD_KEYPTR(hh,head,&((add)->fieldname),keylen_in,add)
#define HASH_REPLACE(hh,head,fieldname,keylen_in,add,replaced) \
do { \
replaced=NULL; \
HASH_FIND(hh,head,&((add)->fieldname),keylen_in,replaced); \
if (replaced!=NULL) { \
HASH_DELETE(hh,head,replaced); \
}; \
HASH_ADD(hh,head,fieldname,keylen_in,add); \
} while(0)
#define HASH_ADD_KEYPTR(hh,head,keyptr,keylen_in,add) \
do { \
unsigned _ha_bkt; \
(add)->hh.next = NULL; \
(add)->hh.key = (char*)keyptr; \
(add)->hh.keylen = (unsigned)keylen_in; \
if (!(head)) { \
head = (add); \
(head)->hh.prev = NULL; \
HASH_MAKE_TABLE(hh,head); \
} else { \
(head)->hh.tbl->tail->next = (add); \
(add)->hh.prev = ELMT_FROM_HH((head)->hh.tbl, (head)->hh.tbl->tail); \
(head)->hh.tbl->tail = &((add)->hh); \
} \
(head)->hh.tbl->num_items++; \
(add)->hh.tbl = (head)->hh.tbl; \
HASH_FCN(keyptr,keylen_in, (head)->hh.tbl->num_buckets, \
(add)->hh.hashv, _ha_bkt); \
HASH_ADD_TO_BKT((head)->hh.tbl->buckets[_ha_bkt],&(add)->hh); \
HASH_BLOOM_ADD((head)->hh.tbl,(add)->hh.hashv); \
HASH_EMIT_KEY(hh,head,keyptr,keylen_in); \
HASH_FSCK(hh,head); \
} while(0)
#define HASH_TO_BKT( hashv, num_bkts, bkt ) \
do { \
bkt = ((hashv) & ((num_bkts) - 1)); \
} while(0)
/* delete "delptr" from the hash table.
* "the usual" patch-up process for the app-order doubly-linked-list.
* The use of _hd_hh_del below deserves special explanation.
* These used to be expressed using (delptr) but that led to a bug
* if someone used the same symbol for the head and deletee, like
* HASH_DELETE(hh,users,users);
* We want that to work, but by changing the head (users) below
* we were forfeiting our ability to further refer to the deletee (users)
* in the patch-up process. Solution: use scratch space to
* copy the deletee pointer, then the latter references are via that
* scratch pointer rather than through the repointed (users) symbol.
*/
#define HASH_DELETE(hh,head,delptr) \
do { \
unsigned _hd_bkt; \
struct UT_hash_handle *_hd_hh_del; \
if ( ((delptr)->hh.prev == NULL) && ((delptr)->hh.next == NULL) ) { \
uthash_free((head)->hh.tbl->buckets, \
(head)->hh.tbl->num_buckets*sizeof(struct UT_hash_bucket) ); \
HASH_BLOOM_FREE((head)->hh.tbl); \
uthash_free((head)->hh.tbl, sizeof(UT_hash_table)); \
head = NULL; \
} else { \
_hd_hh_del = &((delptr)->hh); \
if ((delptr) == ELMT_FROM_HH((head)->hh.tbl,(head)->hh.tbl->tail)) { \
(head)->hh.tbl->tail = \
(UT_hash_handle*)((ptrdiff_t)((delptr)->hh.prev) + \
(head)->hh.tbl->hho); \
} \
if ((delptr)->hh.prev) { \
((UT_hash_handle*)((ptrdiff_t)((delptr)->hh.prev) + \
(head)->hh.tbl->hho))->next = (delptr)->hh.next; \
} else { \
DECLTYPE_ASSIGN(head,(delptr)->hh.next); \
} \
if (_hd_hh_del->next) { \
((UT_hash_handle*)((ptrdiff_t)_hd_hh_del->next + \
(head)->hh.tbl->hho))->prev = \
_hd_hh_del->prev; \
} \
HASH_TO_BKT( _hd_hh_del->hashv, (head)->hh.tbl->num_buckets, _hd_bkt); \
HASH_DEL_IN_BKT(hh,(head)->hh.tbl->buckets[_hd_bkt], _hd_hh_del); \
(head)->hh.tbl->num_items--; \
} \
HASH_FSCK(hh,head); \
} while (0)
/* convenience forms of HASH_FIND/HASH_ADD/HASH_DEL */
#define HASH_FIND_STR(head,findstr,out) \
HASH_FIND(hh,head,findstr,strlen(findstr),out)
#define HASH_ADD_STR(head,strfield,add) \
HASH_ADD(hh,head,strfield,strlen(add->strfield),add)
#define HASH_REPLACE_STR(head,strfield,add,replaced) \
HASH_REPLACE(hh,head,strfield,strlen(add->strfield),add,replaced)
#define HASH_FIND_INT(head,findint,out) \
HASH_FIND(hh,head,findint,sizeof(int),out)
#define HASH_ADD_INT(head,intfield,add) \
HASH_ADD(hh,head,intfield,sizeof(int),add)
#define HASH_REPLACE_INT(head,intfield,add,replaced) \
HASH_REPLACE(hh,head,intfield,sizeof(int),add,replaced)
#define HASH_FIND_PTR(head,findptr,out) \
HASH_FIND(hh,head,findptr,sizeof(void *),out)
#define HASH_ADD_PTR(head,ptrfield,add) \
HASH_ADD(hh,head,ptrfield,sizeof(void *),add)
#define HASH_REPLACE_PTR(head,ptrfield,add) \
HASH_REPLACE(hh,head,ptrfield,sizeof(void *),add,replaced)
#define HASH_DEL(head,delptr) \
HASH_DELETE(hh,head,delptr)
/* HASH_FSCK checks hash integrity on every add/delete when HASH_DEBUG is defined.
* This is for uthash developer only; it compiles away if HASH_DEBUG isn't defined.
*/
#ifdef HASH_DEBUG
#define HASH_OOPS(...) do { fprintf(stderr,__VA_ARGS__); exit(-1); } while (0)
#define HASH_FSCK(hh,head) \
do { \
unsigned _bkt_i; \
unsigned _count, _bkt_count; \
char *_prev; \
struct UT_hash_handle *_thh; \
if (head) { \
_count = 0; \
for( _bkt_i = 0; _bkt_i < (head)->hh.tbl->num_buckets; _bkt_i++) { \
_bkt_count = 0; \
_thh = (head)->hh.tbl->buckets[_bkt_i].hh_head; \
_prev = NULL; \
while (_thh) { \
if (_prev != (char*)(_thh->hh_prev)) { \
HASH_OOPS("invalid hh_prev %p, actual %p\n", \
_thh->hh_prev, _prev ); \
} \
_bkt_count++; \
_prev = (char*)(_thh); \
_thh = _thh->hh_next; \
} \
_count += _bkt_count; \
if ((head)->hh.tbl->buckets[_bkt_i].count != _bkt_count) { \
HASH_OOPS("invalid bucket count %d, actual %d\n", \
(head)->hh.tbl->buckets[_bkt_i].count, _bkt_count); \
} \
} \
if (_count != (head)->hh.tbl->num_items) { \
HASH_OOPS("invalid hh item count %d, actual %d\n", \
(head)->hh.tbl->num_items, _count ); \
} \
/* traverse hh in app order; check next/prev integrity, count */ \
_count = 0; \
_prev = NULL; \
_thh = &(head)->hh; \
while (_thh) { \
_count++; \
if (_prev !=(char*)(_thh->prev)) { \
HASH_OOPS("invalid prev %p, actual %p\n", \
_thh->prev, _prev ); \
} \
_prev = (char*)ELMT_FROM_HH((head)->hh.tbl, _thh); \
_thh = ( _thh->next ? (UT_hash_handle*)((char*)(_thh->next) + \
(head)->hh.tbl->hho) : NULL ); \
} \
if (_count != (head)->hh.tbl->num_items) { \
HASH_OOPS("invalid app item count %d, actual %d\n", \
(head)->hh.tbl->num_items, _count ); \
} \
} \
} while (0)
#else
#define HASH_FSCK(hh,head)
#endif
/* When compiled with -DHASH_EMIT_KEYS, length-prefixed keys are emitted to
* the descriptor to which this macro is defined for tuning the hash function.
* The app can #include <unistd.h> to get the prototype for write(2). */
#ifdef HASH_EMIT_KEYS
#define HASH_EMIT_KEY(hh,head,keyptr,fieldlen) \
do { \
unsigned _klen = fieldlen; \
write(HASH_EMIT_KEYS, &_klen, sizeof(_klen)); \
write(HASH_EMIT_KEYS, keyptr, fieldlen); \
} while (0)
#else
#define HASH_EMIT_KEY(hh,head,keyptr,fieldlen)
#endif
/* default to Jenkin's hash unless overridden e.g. DHASH_FUNCTION=HASH_SAX */
#ifdef HASH_FUNCTION
#define HASH_FCN HASH_FUNCTION
#else
#define HASH_FCN HASH_JEN
#endif
/* The Bernstein hash function, used in Perl prior to v5.6 */
#define HASH_BER(key,keylen,num_bkts,hashv,bkt) \
do { \
unsigned _hb_keylen=keylen; \
char *_hb_key=(char*)(key); \
(hashv) = 0; \
while (_hb_keylen--) { (hashv) = ((hashv) * 33) + *_hb_key++; } \
bkt = (hashv) & (num_bkts-1); \
} while (0)
/* SAX/FNV/OAT/JEN hash functions are macro variants of those listed at
* http://eternallyconfuzzled.com/tuts/algorithms/jsw_tut_hashing.aspx */
#define HASH_SAX(key,keylen,num_bkts,hashv,bkt) \
do { \
unsigned _sx_i; \
char *_hs_key=(char*)(key); \
hashv = 0; \
for(_sx_i=0; _sx_i < keylen; _sx_i++) \
hashv ^= (hashv << 5) + (hashv >> 2) + _hs_key[_sx_i]; \
bkt = hashv & (num_bkts-1); \
} while (0)
#define HASH_FNV(key,keylen,num_bkts,hashv,bkt) \
do { \
unsigned _fn_i; \
char *_hf_key=(char*)(key); \
hashv = 2166136261UL; \
for(_fn_i=0; _fn_i < keylen; _fn_i++) \
hashv = (hashv * 16777619) ^ _hf_key[_fn_i]; \
bkt = hashv & (num_bkts-1); \
} while(0)
#define HASH_OAT(key,keylen,num_bkts,hashv,bkt) \
do { \
unsigned _ho_i; \
char *_ho_key=(char*)(key); \
hashv = 0; \
for(_ho_i=0; _ho_i < keylen; _ho_i++) { \
hashv += _ho_key[_ho_i]; \
hashv += (hashv << 10); \
hashv ^= (hashv >> 6); \
} \
hashv += (hashv << 3); \
hashv ^= (hashv >> 11); \
hashv += (hashv << 15); \
bkt = hashv & (num_bkts-1); \
} while(0)
#define HASH_JEN_MIX(a,b,c) \
do { \
a -= b; a -= c; a ^= ( c >> 13 ); \
b -= c; b -= a; b ^= ( a << 8 ); \
c -= a; c -= b; c ^= ( b >> 13 ); \
a -= b; a -= c; a ^= ( c >> 12 ); \
b -= c; b -= a; b ^= ( a << 16 ); \
c -= a; c -= b; c ^= ( b >> 5 ); \
a -= b; a -= c; a ^= ( c >> 3 ); \
b -= c; b -= a; b ^= ( a << 10 ); \
c -= a; c -= b; c ^= ( b >> 15 ); \
} while (0)
#define HASH_JEN(key,keylen,num_bkts,hashv,bkt) \
do { \
unsigned _hj_i,_hj_j,_hj_k; \
unsigned char *_hj_key=(unsigned char*)(key); \
hashv = 0xfeedbeef; \
_hj_i = _hj_j = 0x9e3779b9; \
_hj_k = (unsigned)keylen; \
while (_hj_k >= 12) { \
_hj_i += (_hj_key[0] + ( (unsigned)_hj_key[1] << 8 ) \
+ ( (unsigned)_hj_key[2] << 16 ) \
+ ( (unsigned)_hj_key[3] << 24 ) ); \
_hj_j += (_hj_key[4] + ( (unsigned)_hj_key[5] << 8 ) \
+ ( (unsigned)_hj_key[6] << 16 ) \
+ ( (unsigned)_hj_key[7] << 24 ) ); \
hashv += (_hj_key[8] + ( (unsigned)_hj_key[9] << 8 ) \
+ ( (unsigned)_hj_key[10] << 16 ) \
+ ( (unsigned)_hj_key[11] << 24 ) ); \
\
HASH_JEN_MIX(_hj_i, _hj_j, hashv); \
\
_hj_key += 12; \
_hj_k -= 12; \
} \
hashv += keylen; \
switch ( _hj_k ) { \
case 11: hashv += ( (unsigned)_hj_key[10] << 24 ); \
case 10: hashv += ( (unsigned)_hj_key[9] << 16 ); \
case 9: hashv += ( (unsigned)_hj_key[8] << 8 ); \
case 8: _hj_j += ( (unsigned)_hj_key[7] << 24 ); \
case 7: _hj_j += ( (unsigned)_hj_key[6] << 16 ); \
case 6: _hj_j += ( (unsigned)_hj_key[5] << 8 ); \
case 5: _hj_j += _hj_key[4]; \
case 4: _hj_i += ( (unsigned)_hj_key[3] << 24 ); \
case 3: _hj_i += ( (unsigned)_hj_key[2] << 16 ); \
case 2: _hj_i += ( (unsigned)_hj_key[1] << 8 ); \
case 1: _hj_i += _hj_key[0]; \
} \
HASH_JEN_MIX(_hj_i, _hj_j, hashv); \
bkt = hashv & (num_bkts-1); \
} while(0)
/* The Paul Hsieh hash function */
#undef get16bits
#if (defined(__GNUC__) && defined(__i386__)) || defined(__WATCOMC__) \
|| defined(_MSC_VER) || defined (__BORLANDC__) || defined (__TURBOC__)
#define get16bits(d) (*((const uint16_t *) (d)))
#endif
#if !defined (get16bits)
#define get16bits(d) ((((uint32_t)(((const uint8_t *)(d))[1])) << 8) \
+(uint32_t)(((const uint8_t *)(d))[0]) )
#endif
#define HASH_SFH(key,keylen,num_bkts,hashv,bkt) \
do { \
unsigned char *_sfh_key=(unsigned char*)(key); \
uint32_t _sfh_tmp, _sfh_len = keylen; \
\
int _sfh_rem = _sfh_len & 3; \
_sfh_len >>= 2; \
hashv = 0xcafebabe; \
\
/* Main loop */ \
for (;_sfh_len > 0; _sfh_len--) { \
hashv += get16bits (_sfh_key); \
_sfh_tmp = (uint32_t)(get16bits (_sfh_key+2)) << 11 ^ hashv; \
hashv = (hashv << 16) ^ _sfh_tmp; \
_sfh_key += 2*sizeof (uint16_t); \
hashv += hashv >> 11; \
} \
\
/* Handle end cases */ \
switch (_sfh_rem) { \
case 3: hashv += get16bits (_sfh_key); \
hashv ^= hashv << 16; \
hashv ^= (uint32_t)(_sfh_key[sizeof (uint16_t)] << 18); \
hashv += hashv >> 11; \
break; \
case 2: hashv += get16bits (_sfh_key); \
hashv ^= hashv << 11; \
hashv += hashv >> 17; \
break; \
case 1: hashv += *_sfh_key; \
hashv ^= hashv << 10; \
hashv += hashv >> 1; \
} \
\
/* Force "avalanching" of final 127 bits */ \
hashv ^= hashv << 3; \
hashv += hashv >> 5; \
hashv ^= hashv << 4; \
hashv += hashv >> 17; \
hashv ^= hashv << 25; \
hashv += hashv >> 6; \
bkt = hashv & (num_bkts-1); \
} while(0)
#ifdef HASH_USING_NO_STRICT_ALIASING
/* The MurmurHash exploits some CPU's (x86,x86_64) tolerance for unaligned reads.
* For other types of CPU's (e.g. Sparc) an unaligned read causes a bus error.
* MurmurHash uses the faster approach only on CPU's where we know it's safe.
*
* Note the preprocessor built-in defines can be emitted using:
*
* gcc -m64 -dM -E - < /dev/null (on gcc)
* cc -## a.c (where a.c is a simple test file) (Sun Studio)
*/
#if (defined(__i386__) || defined(__x86_64__) || defined(_M_IX86))
#define MUR_GETBLOCK(p,i) p[i]
#else /* non intel */
#define MUR_PLUS0_ALIGNED(p) (((unsigned long)p & 0x3) == 0)
#define MUR_PLUS1_ALIGNED(p) (((unsigned long)p & 0x3) == 1)
#define MUR_PLUS2_ALIGNED(p) (((unsigned long)p & 0x3) == 2)
#define MUR_PLUS3_ALIGNED(p) (((unsigned long)p & 0x3) == 3)
#define WP(p) ((uint32_t*)((unsigned long)(p) & ~3UL))
#if (defined(__BIG_ENDIAN__) || defined(SPARC) || defined(__ppc__) || defined(__ppc64__))
#define MUR_THREE_ONE(p) ((((*WP(p))&0x00ffffff) << 8) | (((*(WP(p)+1))&0xff000000) >> 24))
#define MUR_TWO_TWO(p) ((((*WP(p))&0x0000ffff) <<16) | (((*(WP(p)+1))&0xffff0000) >> 16))
#define MUR_ONE_THREE(p) ((((*WP(p))&0x000000ff) <<24) | (((*(WP(p)+1))&0xffffff00) >> 8))
#else /* assume little endian non-intel */
#define MUR_THREE_ONE(p) ((((*WP(p))&0xffffff00) >> 8) | (((*(WP(p)+1))&0x000000ff) << 24))
#define MUR_TWO_TWO(p) ((((*WP(p))&0xffff0000) >>16) | (((*(WP(p)+1))&0x0000ffff) << 16))
#define MUR_ONE_THREE(p) ((((*WP(p))&0xff000000) >>24) | (((*(WP(p)+1))&0x00ffffff) << 8))
#endif
#define MUR_GETBLOCK(p,i) (MUR_PLUS0_ALIGNED(p) ? ((p)[i]) : \
(MUR_PLUS1_ALIGNED(p) ? MUR_THREE_ONE(p) : \
(MUR_PLUS2_ALIGNED(p) ? MUR_TWO_TWO(p) : \
MUR_ONE_THREE(p))))
#endif
#define MUR_ROTL32(x,r) (((x) << (r)) | ((x) >> (32 - (r))))
#define MUR_FMIX(_h) \
do { \
_h ^= _h >> 16; \
_h *= 0x85ebca6b; \
_h ^= _h >> 13; \
_h *= 0xc2b2ae35l; \
_h ^= _h >> 16; \
} while(0)
#define HASH_MUR(key,keylen,num_bkts,hashv,bkt) \
do { \
const uint8_t *_mur_data = (const uint8_t*)(key); \
const int _mur_nblocks = (keylen) / 4; \
uint32_t _mur_h1 = 0xf88D5353; \
uint32_t _mur_c1 = 0xcc9e2d51; \
uint32_t _mur_c2 = 0x1b873593; \
uint32_t _mur_k1 = 0; \
const uint8_t *_mur_tail; \
const uint32_t *_mur_blocks = (const uint32_t*)(_mur_data+_mur_nblocks*4); \
int _mur_i; \
for(_mur_i = -_mur_nblocks; _mur_i; _mur_i++) { \
_mur_k1 = MUR_GETBLOCK(_mur_blocks,_mur_i); \
_mur_k1 *= _mur_c1; \
_mur_k1 = MUR_ROTL32(_mur_k1,15); \
_mur_k1 *= _mur_c2; \
\
_mur_h1 ^= _mur_k1; \
_mur_h1 = MUR_ROTL32(_mur_h1,13); \
_mur_h1 = _mur_h1*5+0xe6546b64; \
} \
_mur_tail = (const uint8_t*)(_mur_data + _mur_nblocks*4); \
_mur_k1=0; \
switch((keylen) & 3) { \
case 3: _mur_k1 ^= _mur_tail[2] << 16; \
case 2: _mur_k1 ^= _mur_tail[1] << 8; \
case 1: _mur_k1 ^= _mur_tail[0]; \
_mur_k1 *= _mur_c1; \
_mur_k1 = MUR_ROTL32(_mur_k1,15); \
_mur_k1 *= _mur_c2; \
_mur_h1 ^= _mur_k1; \
} \
_mur_h1 ^= (keylen); \
MUR_FMIX(_mur_h1); \
hashv = _mur_h1; \
bkt = hashv & (num_bkts-1); \
} while(0)
#endif /* HASH_USING_NO_STRICT_ALIASING */
/* key comparison function; return 0 if keys equal */
#define HASH_KEYCMP(a,b,len) memcmp(a,b,len)
/* iterate over items in a known bucket to find desired item */
#define HASH_FIND_IN_BKT(tbl,hh,head,keyptr,keylen_in,out) \
do { \
if (head.hh_head) DECLTYPE_ASSIGN(out,ELMT_FROM_HH(tbl,head.hh_head)); \
else out=NULL; \
while (out) { \
if ((out)->hh.keylen == keylen_in) { \
if ((HASH_KEYCMP((out)->hh.key,keyptr,keylen_in)) == 0) break; \
} \
if ((out)->hh.hh_next) DECLTYPE_ASSIGN(out,ELMT_FROM_HH(tbl,(out)->hh.hh_next)); \
else out = NULL; \
} \
} while(0)
/* add an item to a bucket */
#define HASH_ADD_TO_BKT(head,addhh) \
do { \
head.count++; \
(addhh)->hh_next = head.hh_head; \
(addhh)->hh_prev = NULL; \
if (head.hh_head) { (head).hh_head->hh_prev = (addhh); } \
(head).hh_head=addhh; \
if (head.count >= ((head.expand_mult+1) * HASH_BKT_CAPACITY_THRESH) \
&& (addhh)->tbl->noexpand != 1) { \
HASH_EXPAND_BUCKETS((addhh)->tbl); \
} \
} while(0)
/* remove an item from a given bucket */
#define HASH_DEL_IN_BKT(hh,head,hh_del) \
(head).count--; \
if ((head).hh_head == hh_del) { \
(head).hh_head = hh_del->hh_next; \
} \
if (hh_del->hh_prev) { \
hh_del->hh_prev->hh_next = hh_del->hh_next; \
} \
if (hh_del->hh_next) { \
hh_del->hh_next->hh_prev = hh_del->hh_prev; \
}
/* Bucket expansion has the effect of doubling the number of buckets
* and redistributing the items into the new buckets. Ideally the
* items will distribute more or less evenly into the new buckets
* (the extent to which this is true is a measure of the quality of
* the hash function as it applies to the key domain).
*
* With the items distributed into more buckets, the chain length
* (item count) in each bucket is reduced. Thus by expanding buckets
* the hash keeps a bound on the chain length. This bounded chain
* length is the essence of how a hash provides constant time lookup.
*
* The calculation of tbl->ideal_chain_maxlen below deserves some
* explanation. First, keep in mind that we're calculating the ideal
* maximum chain length based on the *new* (doubled) bucket count.
* In fractions this is just n/b (n=number of items,b=new num buckets).
* Since the ideal chain length is an integer, we want to calculate
* ceil(n/b). We don't depend on floating point arithmetic in this
* hash, so to calculate ceil(n/b) with integers we could write
*
* ceil(n/b) = (n/b) + ((n%b)?1:0)
*
* and in fact a previous version of this hash did just that.
* But now we have improved things a bit by recognizing that b is
* always a power of two. We keep its base 2 log handy (call it lb),
* so now we can write this with a bit shift and logical AND:
*
* ceil(n/b) = (n>>lb) + ( (n & (b-1)) ? 1:0)
*
*/
#define HASH_EXPAND_BUCKETS(tbl) \
do { \
unsigned _he_bkt; \
unsigned _he_bkt_i; \
struct UT_hash_handle *_he_thh, *_he_hh_nxt; \
UT_hash_bucket *_he_new_buckets, *_he_newbkt; \
_he_new_buckets = (UT_hash_bucket*)uthash_malloc( \
2 * tbl->num_buckets * sizeof(struct UT_hash_bucket)); \
if (!_he_new_buckets) { uthash_fatal( "out of memory"); } \
memset(_he_new_buckets, 0, \
2 * tbl->num_buckets * sizeof(struct UT_hash_bucket)); \
tbl->ideal_chain_maxlen = \
(tbl->num_items >> (tbl->log2_num_buckets+1)) + \
((tbl->num_items & ((tbl->num_buckets*2)-1)) ? 1 : 0); \
tbl->nonideal_items = 0; \
for(_he_bkt_i = 0; _he_bkt_i < tbl->num_buckets; _he_bkt_i++) \
{ \
_he_thh = tbl->buckets[ _he_bkt_i ].hh_head; \
while (_he_thh) { \
_he_hh_nxt = _he_thh->hh_next; \
HASH_TO_BKT( _he_thh->hashv, tbl->num_buckets*2, _he_bkt); \
_he_newbkt = &(_he_new_buckets[ _he_bkt ]); \
if (++(_he_newbkt->count) > tbl->ideal_chain_maxlen) { \
tbl->nonideal_items++; \
_he_newbkt->expand_mult = _he_newbkt->count / \
tbl->ideal_chain_maxlen; \
} \
_he_thh->hh_prev = NULL; \
_he_thh->hh_next = _he_newbkt->hh_head; \
if (_he_newbkt->hh_head) _he_newbkt->hh_head->hh_prev = \
_he_thh; \
_he_newbkt->hh_head = _he_thh; \
_he_thh = _he_hh_nxt; \
} \
} \
uthash_free( tbl->buckets, tbl->num_buckets*sizeof(struct UT_hash_bucket) ); \
tbl->num_buckets *= 2; \
tbl->log2_num_buckets++; \
tbl->buckets = _he_new_buckets; \
tbl->ineff_expands = (tbl->nonideal_items > (tbl->num_items >> 1)) ? \
(tbl->ineff_expands+1) : 0; \
if (tbl->ineff_expands > 1) { \
tbl->noexpand=1; \
uthash_noexpand_fyi(tbl); \
} \
uthash_expand_fyi(tbl); \
} while(0)
/* This is an adaptation of Simon Tatham's O(n log(n)) mergesort */
/* Note that HASH_SORT assumes the hash handle name to be hh.
* HASH_SRT was added to allow the hash handle name to be passed in. */
#define HASH_SORT(head,cmpfcn) HASH_SRT(hh,head,cmpfcn)
#define HASH_SRT(hh,head,cmpfcn) \
do { \
unsigned _hs_i; \
unsigned _hs_looping,_hs_nmerges,_hs_insize,_hs_psize,_hs_qsize; \
struct UT_hash_handle *_hs_p, *_hs_q, *_hs_e, *_hs_list, *_hs_tail; \
if (head) { \
_hs_insize = 1; \
_hs_looping = 1; \
_hs_list = &((head)->hh); \
while (_hs_looping) { \
_hs_p = _hs_list; \
_hs_list = NULL; \
_hs_tail = NULL; \
_hs_nmerges = 0; \
while (_hs_p) { \
_hs_nmerges++; \
_hs_q = _hs_p; \
_hs_psize = 0; \
for ( _hs_i = 0; _hs_i < _hs_insize; _hs_i++ ) { \
_hs_psize++; \
_hs_q = (UT_hash_handle*)((_hs_q->next) ? \
((void*)((char*)(_hs_q->next) + \
(head)->hh.tbl->hho)) : NULL); \
if (! (_hs_q) ) break; \
} \
_hs_qsize = _hs_insize; \
while ((_hs_psize > 0) || ((_hs_qsize > 0) && _hs_q )) { \
if (_hs_psize == 0) { \
_hs_e = _hs_q; \
_hs_q = (UT_hash_handle*)((_hs_q->next) ? \
((void*)((char*)(_hs_q->next) + \
(head)->hh.tbl->hho)) : NULL); \
_hs_qsize--; \
} else if ( (_hs_qsize == 0) || !(_hs_q) ) { \
_hs_e = _hs_p; \
_hs_p = (UT_hash_handle*)((_hs_p->next) ? \
((void*)((char*)(_hs_p->next) + \
(head)->hh.tbl->hho)) : NULL); \
_hs_psize--; \
} else if (( \
cmpfcn(DECLTYPE(head)(ELMT_FROM_HH((head)->hh.tbl,_hs_p)), \
DECLTYPE(head)(ELMT_FROM_HH((head)->hh.tbl,_hs_q))) \
) <= 0) { \
_hs_e = _hs_p; \
_hs_p = (UT_hash_handle*)((_hs_p->next) ? \
((void*)((char*)(_hs_p->next) + \
(head)->hh.tbl->hho)) : NULL); \
_hs_psize--; \
} else { \
_hs_e = _hs_q; \
_hs_q = (UT_hash_handle*)((_hs_q->next) ? \
((void*)((char*)(_hs_q->next) + \
(head)->hh.tbl->hho)) : NULL); \
_hs_qsize--; \
} \
if ( _hs_tail ) { \
_hs_tail->next = ((_hs_e) ? \
ELMT_FROM_HH((head)->hh.tbl,_hs_e) : NULL); \
} else { \
_hs_list = _hs_e; \
} \
_hs_e->prev = ((_hs_tail) ? \
ELMT_FROM_HH((head)->hh.tbl,_hs_tail) : NULL); \
_hs_tail = _hs_e; \
} \
_hs_p = _hs_q; \
} \
_hs_tail->next = NULL; \
if ( _hs_nmerges <= 1 ) { \
_hs_looping=0; \
(head)->hh.tbl->tail = _hs_tail; \
DECLTYPE_ASSIGN(head,ELMT_FROM_HH((head)->hh.tbl, _hs_list)); \
} \
_hs_insize *= 2; \
} \
HASH_FSCK(hh,head); \
} \
} while (0)
/* This function selects items from one hash into another hash.
* The end result is that the selected items have dual presence
* in both hashes. There is no copy of the items made; rather
* they are added into the new hash through a secondary hash
* hash handle that must be present in the structure. */
#define HASH_SELECT(hh_dst, dst, hh_src, src, cond) \
do { \
unsigned _src_bkt, _dst_bkt; \
void *_last_elt=NULL, *_elt; \
UT_hash_handle *_src_hh, *_dst_hh, *_last_elt_hh=NULL; \
ptrdiff_t _dst_hho = ((char*)(&(dst)->hh_dst) - (char*)(dst)); \
if (src) { \
for(_src_bkt=0; _src_bkt < (src)->hh_src.tbl->num_buckets; _src_bkt++) { \
for(_src_hh = (src)->hh_src.tbl->buckets[_src_bkt].hh_head; \
_src_hh; \
_src_hh = _src_hh->hh_next) { \
_elt = ELMT_FROM_HH((src)->hh_src.tbl, _src_hh); \
if (cond(_elt)) { \
_dst_hh = (UT_hash_handle*)(((char*)_elt) + _dst_hho); \
_dst_hh->key = _src_hh->key; \
_dst_hh->keylen = _src_hh->keylen; \
_dst_hh->hashv = _src_hh->hashv; \
_dst_hh->prev = _last_elt; \
_dst_hh->next = NULL; \
if (_last_elt_hh) { _last_elt_hh->next = _elt; } \
if (!dst) { \
DECLTYPE_ASSIGN(dst,_elt); \
HASH_MAKE_TABLE(hh_dst,dst); \
} else { \
_dst_hh->tbl = (dst)->hh_dst.tbl; \
} \
HASH_TO_BKT(_dst_hh->hashv, _dst_hh->tbl->num_buckets, _dst_bkt); \
HASH_ADD_TO_BKT(_dst_hh->tbl->buckets[_dst_bkt],_dst_hh); \
(dst)->hh_dst.tbl->num_items++; \
_last_elt = _elt; \
_last_elt_hh = _dst_hh; \
} \
} \
} \
} \
HASH_FSCK(hh_dst,dst); \
} while (0)
#define HASH_CLEAR(hh,head) \
do { \
if (head) { \
uthash_free((head)->hh.tbl->buckets, \
(head)->hh.tbl->num_buckets*sizeof(struct UT_hash_bucket)); \
HASH_BLOOM_FREE((head)->hh.tbl); \
uthash_free((head)->hh.tbl, sizeof(UT_hash_table)); \
(head)=NULL; \
} \
} while(0)
#define HASH_OVERHEAD(hh,head) \
(size_t)((((head)->hh.tbl->num_items * sizeof(UT_hash_handle)) + \
((head)->hh.tbl->num_buckets * sizeof(UT_hash_bucket)) + \
(sizeof(UT_hash_table)) + \
(HASH_BLOOM_BYTELEN)))
#ifdef NO_DECLTYPE
#define HASH_ITER(hh,head,el,tmp) \
for((el)=(head), (*(char**)(&(tmp)))=(char*)((head)?(head)->hh.next:NULL); \
el; (el)=(tmp),(*(char**)(&(tmp)))=(char*)((tmp)?(tmp)->hh.next:NULL))
#else
#define HASH_ITER(hh,head,el,tmp) \
for((el)=(head),(tmp)=DECLTYPE(el)((head)?(head)->hh.next:NULL); \
el; (el)=(tmp),(tmp)=DECLTYPE(el)((tmp)?(tmp)->hh.next:NULL))
#endif
/* obtain a count of items in the hash */
#define HASH_COUNT(head) HASH_CNT(hh,head)
#define HASH_CNT(hh,head) ((head)?((head)->hh.tbl->num_items):0)
typedef struct UT_hash_bucket {
struct UT_hash_handle *hh_head;
unsigned count;
/* expand_mult is normally set to 0. In this situation, the max chain length
* threshold is enforced at its default value, HASH_BKT_CAPACITY_THRESH. (If
* the bucket's chain exceeds this length, bucket expansion is triggered).
* However, setting expand_mult to a non-zero value delays bucket expansion
* (that would be triggered by additions to this particular bucket)
* until its chain length reaches a *multiple* of HASH_BKT_CAPACITY_THRESH.
* (The multiplier is simply expand_mult+1). The whole idea of this
* multiplier is to reduce bucket expansions, since they are expensive, in
* situations where we know that a particular bucket tends to be overused.
* It is better to let its chain length grow to a longer yet-still-bounded
* value, than to do an O(n) bucket expansion too often.
*/
unsigned expand_mult;
} UT_hash_bucket;
/* random signature used only to find hash tables in external analysis */
#define HASH_SIGNATURE 0xa0111fe1
#define HASH_BLOOM_SIGNATURE 0xb12220f2
typedef struct UT_hash_table {
UT_hash_bucket *buckets;
unsigned num_buckets, log2_num_buckets;
unsigned num_items;
struct UT_hash_handle *tail; /* tail hh in app order, for fast append */
ptrdiff_t hho; /* hash handle offset (byte pos of hash handle in element */
/* in an ideal situation (all buckets used equally), no bucket would have
* more than ceil(#items/#buckets) items. that's the ideal chain length. */
unsigned ideal_chain_maxlen;
/* nonideal_items is the number of items in the hash whose chain position
* exceeds the ideal chain maxlen. these items pay the penalty for an uneven
* hash distribution; reaching them in a chain traversal takes >ideal steps */
unsigned nonideal_items;
/* ineffective expands occur when a bucket doubling was performed, but
* afterward, more than half the items in the hash had nonideal chain
* positions. If this happens on two consecutive expansions we inhibit any
* further expansion, as it's not helping; this happens when the hash
* function isn't a good fit for the key domain. When expansion is inhibited
* the hash will still work, albeit no longer in constant time. */
unsigned ineff_expands, noexpand;
uint32_t signature; /* used only to find hash tables in external analysis */
#ifdef HASH_BLOOM
uint32_t bloom_sig; /* used only to test bloom exists in external analysis */
uint8_t *bloom_bv;
char bloom_nbits;
#endif
} UT_hash_table;
typedef struct UT_hash_handle {
struct UT_hash_table *tbl;
void *prev; /* prev element in app order */
void *next; /* next element in app order */
struct UT_hash_handle *hh_prev; /* previous hh in bucket order */
struct UT_hash_handle *hh_next; /* next hh in bucket order */
void *key; /* ptr to enclosing struct's key */
unsigned keylen; /* enclosing struct's key len */
unsigned hashv; /* result of hash-fcn(key) */
} UT_hash_handle;
#endif /* UTHASH_H */

View file

@ -0,0 +1,728 @@
/*
Copyright (c) 2007-2013, Troy D. Hanson http://troydhanson.github.com/uthash/
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef UTLIST_H
#define UTLIST_H
#define UTLIST_VERSION 1.9.8
#include <assert.h>
/*
* This file contains macros to manipulate singly and doubly-linked lists.
*
* 1. LL_ macros: singly-linked lists.
* 2. DL_ macros: doubly-linked lists.
* 3. CDL_ macros: circular doubly-linked lists.
*
* To use singly-linked lists, your structure must have a "next" pointer.
* To use doubly-linked lists, your structure must "prev" and "next" pointers.
* Either way, the pointer to the head of the list must be initialized to NULL.
*
* ----------------.EXAMPLE -------------------------
* struct item {
* int id;
* struct item *prev, *next;
* }
*
* struct item *list = NULL:
*
* int main() {
* struct item *item;
* ... allocate and populate item ...
* DL_APPEND(list, item);
* }
* --------------------------------------------------
*
* For doubly-linked lists, the append and delete macros are O(1)
* For singly-linked lists, append and delete are O(n) but prepend is O(1)
* The sort macro is O(n log(n)) for all types of single/double/circular lists.
*/
/* These macros use decltype or the earlier __typeof GNU extension.
As decltype is only available in newer compilers (VS2010 or gcc 4.3+
when compiling c++ code), this code uses whatever method is needed
or, for VS2008 where neither is available, uses casting workarounds. */
#ifdef _MSC_VER /* MS compiler */
#if _MSC_VER >= 1600 && defined(__cplusplus) /* VS2010 or newer in C++ mode */
#define LDECLTYPE(x) decltype(x)
#else /* VS2008 or older (or VS2010 in C mode) */
#define NO_DECLTYPE
#define LDECLTYPE(x) char*
#endif
#else /* GNU, Sun and other compilers */
#define LDECLTYPE(x) __typeof(x)
#endif
/* for VS2008 we use some workarounds to get around the lack of decltype,
* namely, we always reassign our tmp variable to the list head if we need
* to dereference its prev/next pointers, and save/restore the real head.*/
#ifdef NO_DECLTYPE
#define _SV(elt,list) _tmp = (char*)(list); {char **_alias = (char**)&(list); *_alias = (elt); }
#define _NEXT(elt,list,next) ((char*)((list)->next))
#define _NEXTASGN(elt,list,to,next) { char **_alias = (char**)&((list)->next); *_alias=(char*)(to); }
/* #define _PREV(elt,list,prev) ((char*)((list)->prev)) */
#define _PREVASGN(elt,list,to,prev) { char **_alias = (char**)&((list)->prev); *_alias=(char*)(to); }
#define _RS(list) { char **_alias = (char**)&(list); *_alias=_tmp; }
#define _CASTASGN(a,b) { char **_alias = (char**)&(a); *_alias=(char*)(b); }
#else
#define _SV(elt,list)
#define _NEXT(elt,list,next) ((elt)->next)
#define _NEXTASGN(elt,list,to,next) ((elt)->next)=(to)
/* #define _PREV(elt,list,prev) ((elt)->prev) */
#define _PREVASGN(elt,list,to,prev) ((elt)->prev)=(to)
#define _RS(list)
#define _CASTASGN(a,b) (a)=(b)
#endif
/******************************************************************************
* The sort macro is an adaptation of Simon Tatham's O(n log(n)) mergesort *
* Unwieldy variable names used here to avoid shadowing passed-in variables. *
*****************************************************************************/
#define LL_SORT(list, cmp) \
LL_SORT2(list, cmp, next)
#define LL_SORT2(list, cmp, next) \
do { \
LDECLTYPE(list) _ls_p; \
LDECLTYPE(list) _ls_q; \
LDECLTYPE(list) _ls_e; \
LDECLTYPE(list) _ls_tail; \
int _ls_insize, _ls_nmerges, _ls_psize, _ls_qsize, _ls_i, _ls_looping; \
if (list) { \
_ls_insize = 1; \
_ls_looping = 1; \
while (_ls_looping) { \
_CASTASGN(_ls_p,list); \
list = NULL; \
_ls_tail = NULL; \
_ls_nmerges = 0; \
while (_ls_p) { \
_ls_nmerges++; \
_ls_q = _ls_p; \
_ls_psize = 0; \
for (_ls_i = 0; _ls_i < _ls_insize; _ls_i++) { \
_ls_psize++; \
_SV(_ls_q,list); _ls_q = _NEXT(_ls_q,list,next); _RS(list); \
if (!_ls_q) break; \
} \
_ls_qsize = _ls_insize; \
while (_ls_psize > 0 || (_ls_qsize > 0 && _ls_q)) { \
if (_ls_psize == 0) { \
_ls_e = _ls_q; _SV(_ls_q,list); _ls_q = \
_NEXT(_ls_q,list,next); _RS(list); _ls_qsize--; \
} else if (_ls_qsize == 0 || !_ls_q) { \
_ls_e = _ls_p; _SV(_ls_p,list); _ls_p = \
_NEXT(_ls_p,list,next); _RS(list); _ls_psize--; \
} else if (cmp(_ls_p,_ls_q) <= 0) { \
_ls_e = _ls_p; _SV(_ls_p,list); _ls_p = \
_NEXT(_ls_p,list,next); _RS(list); _ls_psize--; \
} else { \
_ls_e = _ls_q; _SV(_ls_q,list); _ls_q = \
_NEXT(_ls_q,list,next); _RS(list); _ls_qsize--; \
} \
if (_ls_tail) { \
_SV(_ls_tail,list); _NEXTASGN(_ls_tail,list,_ls_e,next); _RS(list); \
} else { \
_CASTASGN(list,_ls_e); \
} \
_ls_tail = _ls_e; \
} \
_ls_p = _ls_q; \
} \
if (_ls_tail) { \
_SV(_ls_tail,list); _NEXTASGN(_ls_tail,list,NULL,next); _RS(list); \
} \
if (_ls_nmerges <= 1) { \
_ls_looping=0; \
} \
_ls_insize *= 2; \
} \
} \
} while (0)
#define DL_SORT(list, cmp) \
DL_SORT2(list, cmp, prev, next)
#define DL_SORT2(list, cmp, prev, next) \
do { \
LDECLTYPE(list) _ls_p; \
LDECLTYPE(list) _ls_q; \
LDECLTYPE(list) _ls_e; \
LDECLTYPE(list) _ls_tail; \
int _ls_insize, _ls_nmerges, _ls_psize, _ls_qsize, _ls_i, _ls_looping; \
if (list) { \
_ls_insize = 1; \
_ls_looping = 1; \
while (_ls_looping) { \
_CASTASGN(_ls_p,list); \
list = NULL; \
_ls_tail = NULL; \
_ls_nmerges = 0; \
while (_ls_p) { \
_ls_nmerges++; \
_ls_q = _ls_p; \
_ls_psize = 0; \
for (_ls_i = 0; _ls_i < _ls_insize; _ls_i++) { \
_ls_psize++; \
_SV(_ls_q,list); _ls_q = _NEXT(_ls_q,list,next); _RS(list); \
if (!_ls_q) break; \
} \
_ls_qsize = _ls_insize; \
while (_ls_psize > 0 || (_ls_qsize > 0 && _ls_q)) { \
if (_ls_psize == 0) { \
_ls_e = _ls_q; _SV(_ls_q,list); _ls_q = \
_NEXT(_ls_q,list,next); _RS(list); _ls_qsize--; \
} else if (_ls_qsize == 0 || !_ls_q) { \
_ls_e = _ls_p; _SV(_ls_p,list); _ls_p = \
_NEXT(_ls_p,list,next); _RS(list); _ls_psize--; \
} else if (cmp(_ls_p,_ls_q) <= 0) { \
_ls_e = _ls_p; _SV(_ls_p,list); _ls_p = \
_NEXT(_ls_p,list,next); _RS(list); _ls_psize--; \
} else { \
_ls_e = _ls_q; _SV(_ls_q,list); _ls_q = \
_NEXT(_ls_q,list,next); _RS(list); _ls_qsize--; \
} \
if (_ls_tail) { \
_SV(_ls_tail,list); _NEXTASGN(_ls_tail,list,_ls_e,next); _RS(list); \
} else { \
_CASTASGN(list,_ls_e); \
} \
_SV(_ls_e,list); _PREVASGN(_ls_e,list,_ls_tail,prev); _RS(list); \
_ls_tail = _ls_e; \
} \
_ls_p = _ls_q; \
} \
_CASTASGN(list->prev, _ls_tail); \
_SV(_ls_tail,list); _NEXTASGN(_ls_tail,list,NULL,next); _RS(list); \
if (_ls_nmerges <= 1) { \
_ls_looping=0; \
} \
_ls_insize *= 2; \
} \
} \
} while (0)
#define CDL_SORT(list, cmp) \
CDL_SORT2(list, cmp, prev, next)
#define CDL_SORT2(list, cmp, prev, next) \
do { \
LDECLTYPE(list) _ls_p; \
LDECLTYPE(list) _ls_q; \
LDECLTYPE(list) _ls_e; \
LDECLTYPE(list) _ls_tail; \
LDECLTYPE(list) _ls_oldhead; \
LDECLTYPE(list) _tmp; \
int _ls_insize, _ls_nmerges, _ls_psize, _ls_qsize, _ls_i, _ls_looping; \
if (list) { \
_ls_insize = 1; \
_ls_looping = 1; \
while (_ls_looping) { \
_CASTASGN(_ls_p,list); \
_CASTASGN(_ls_oldhead,list); \
list = NULL; \
_ls_tail = NULL; \
_ls_nmerges = 0; \
while (_ls_p) { \
_ls_nmerges++; \
_ls_q = _ls_p; \
_ls_psize = 0; \
for (_ls_i = 0; _ls_i < _ls_insize; _ls_i++) { \
_ls_psize++; \
_SV(_ls_q,list); \
if (_NEXT(_ls_q,list,next) == _ls_oldhead) { \
_ls_q = NULL; \
} else { \
_ls_q = _NEXT(_ls_q,list,next); \
} \
_RS(list); \
if (!_ls_q) break; \
} \
_ls_qsize = _ls_insize; \
while (_ls_psize > 0 || (_ls_qsize > 0 && _ls_q)) { \
if (_ls_psize == 0) { \
_ls_e = _ls_q; _SV(_ls_q,list); _ls_q = \
_NEXT(_ls_q,list,next); _RS(list); _ls_qsize--; \
if (_ls_q == _ls_oldhead) { _ls_q = NULL; } \
} else if (_ls_qsize == 0 || !_ls_q) { \
_ls_e = _ls_p; _SV(_ls_p,list); _ls_p = \
_NEXT(_ls_p,list,next); _RS(list); _ls_psize--; \
if (_ls_p == _ls_oldhead) { _ls_p = NULL; } \
} else if (cmp(_ls_p,_ls_q) <= 0) { \
_ls_e = _ls_p; _SV(_ls_p,list); _ls_p = \
_NEXT(_ls_p,list,next); _RS(list); _ls_psize--; \
if (_ls_p == _ls_oldhead) { _ls_p = NULL; } \
} else { \
_ls_e = _ls_q; _SV(_ls_q,list); _ls_q = \
_NEXT(_ls_q,list,next); _RS(list); _ls_qsize--; \
if (_ls_q == _ls_oldhead) { _ls_q = NULL; } \
} \
if (_ls_tail) { \
_SV(_ls_tail,list); _NEXTASGN(_ls_tail,list,_ls_e,next); _RS(list); \
} else { \
_CASTASGN(list,_ls_e); \
} \
_SV(_ls_e,list); _PREVASGN(_ls_e,list,_ls_tail,prev); _RS(list); \
_ls_tail = _ls_e; \
} \
_ls_p = _ls_q; \
} \
_CASTASGN(list->prev,_ls_tail); \
_CASTASGN(_tmp,list); \
_SV(_ls_tail,list); _NEXTASGN(_ls_tail,list,_tmp,next); _RS(list); \
if (_ls_nmerges <= 1) { \
_ls_looping=0; \
} \
_ls_insize *= 2; \
} \
} \
} while (0)
/******************************************************************************
* singly linked list macros (non-circular) *
*****************************************************************************/
#define LL_PREPEND(head,add) \
LL_PREPEND2(head,add,next)
#define LL_PREPEND2(head,add,next) \
do { \
(add)->next = head; \
head = add; \
} while (0)
#define LL_CONCAT(head1,head2) \
LL_CONCAT2(head1,head2,next)
#define LL_CONCAT2(head1,head2,next) \
do { \
LDECLTYPE(head1) _tmp; \
if (head1) { \
_tmp = head1; \
while (_tmp->next) { _tmp = _tmp->next; } \
_tmp->next=(head2); \
} else { \
(head1)=(head2); \
} \
} while (0)
#define LL_APPEND(head,add) \
LL_APPEND2(head,add,next)
#define LL_APPEND2(head,add,next) \
do { \
LDECLTYPE(head) _tmp; \
(add)->next=NULL; \
if (head) { \
_tmp = head; \
while (_tmp->next) { _tmp = _tmp->next; } \
_tmp->next=(add); \
} else { \
(head)=(add); \
} \
} while (0)
#define LL_DELETE(head,del) \
LL_DELETE2(head,del,next)
#define LL_DELETE2(head,del,next) \
do { \
LDECLTYPE(head) _tmp; \
if ((head) == (del)) { \
(head)=(head)->next; \
} else { \
_tmp = head; \
while (_tmp->next && (_tmp->next != (del))) { \
_tmp = _tmp->next; \
} \
if (_tmp->next) { \
_tmp->next = ((del)->next); \
} \
} \
} while (0)
/* Here are VS2008 replacements for LL_APPEND and LL_DELETE */
#define LL_APPEND_VS2008(head,add) \
LL_APPEND2_VS2008(head,add,next)
#define LL_APPEND2_VS2008(head,add,next) \
do { \
if (head) { \
(add)->next = head; /* use add->next as a temp variable */ \
while ((add)->next->next) { (add)->next = (add)->next->next; } \
(add)->next->next=(add); \
} else { \
(head)=(add); \
} \
(add)->next=NULL; \
} while (0)
#define LL_DELETE_VS2008(head,del) \
LL_DELETE2_VS2008(head,del,next)
#define LL_DELETE2_VS2008(head,del,next) \
do { \
if ((head) == (del)) { \
(head)=(head)->next; \
} else { \
char *_tmp = (char*)(head); \
while ((head)->next && ((head)->next != (del))) { \
head = (head)->next; \
} \
if ((head)->next) { \
(head)->next = ((del)->next); \
} \
{ \
char **_head_alias = (char**)&(head); \
*_head_alias = _tmp; \
} \
} \
} while (0)
#ifdef NO_DECLTYPE
#undef LL_APPEND
#define LL_APPEND LL_APPEND_VS2008
#undef LL_DELETE
#define LL_DELETE LL_DELETE_VS2008
#undef LL_DELETE2
#define LL_DELETE2_VS2008
#undef LL_APPEND2
#define LL_APPEND2 LL_APPEND2_VS2008
#undef LL_CONCAT /* no LL_CONCAT_VS2008 */
#undef DL_CONCAT /* no DL_CONCAT_VS2008 */
#endif
/* end VS2008 replacements */
#define LL_FOREACH(head,el) \
LL_FOREACH2(head,el,next)
#define LL_FOREACH2(head,el,next) \
for(el=head;el;el=(el)->next)
#define LL_FOREACH_SAFE(head,el,tmp) \
LL_FOREACH_SAFE2(head,el,tmp,next)
#define LL_FOREACH_SAFE2(head,el,tmp,next) \
for((el)=(head);(el) && (tmp = (el)->next, 1); (el) = tmp)
#define LL_SEARCH_SCALAR(head,out,field,val) \
LL_SEARCH_SCALAR2(head,out,field,val,next)
#define LL_SEARCH_SCALAR2(head,out,field,val,next) \
do { \
LL_FOREACH2(head,out,next) { \
if ((out)->field == (val)) break; \
} \
} while(0)
#define LL_SEARCH(head,out,elt,cmp) \
LL_SEARCH2(head,out,elt,cmp,next)
#define LL_SEARCH2(head,out,elt,cmp,next) \
do { \
LL_FOREACH2(head,out,next) { \
if ((cmp(out,elt))==0) break; \
} \
} while(0)
#define LL_REPLACE_ELEM(head, el, add) \
do { \
LDECLTYPE(head) _tmp; \
assert(head != NULL); \
assert(el != NULL); \
assert(add != NULL); \
(add)->next = (el)->next; \
if ((head) == (el)) { \
(head) = (add); \
} else { \
_tmp = head; \
while (_tmp->next && (_tmp->next != (el))) { \
_tmp = _tmp->next; \
} \
if (_tmp->next) { \
_tmp->next = (add); \
} \
} \
} while (0)
#define LL_PREPEND_ELEM(head, el, add) \
do { \
LDECLTYPE(head) _tmp; \
assert(head != NULL); \
assert(el != NULL); \
assert(add != NULL); \
(add)->next = (el); \
if ((head) == (el)) { \
(head) = (add); \
} else { \
_tmp = head; \
while (_tmp->next && (_tmp->next != (el))) { \
_tmp = _tmp->next; \
} \
if (_tmp->next) { \
_tmp->next = (add); \
} \
} \
} while (0) \
/******************************************************************************
* doubly linked list macros (non-circular) *
*****************************************************************************/
#define DL_PREPEND(head,add) \
DL_PREPEND2(head,add,prev,next)
#define DL_PREPEND2(head,add,prev,next) \
do { \
(add)->next = head; \
if (head) { \
(add)->prev = (head)->prev; \
(head)->prev = (add); \
} else { \
(add)->prev = (add); \
} \
(head) = (add); \
} while (0)
#define DL_APPEND(head,add) \
DL_APPEND2(head,add,prev,next)
#define DL_APPEND2(head,add,prev,next) \
do { \
if (head) { \
(add)->prev = (head)->prev; \
(head)->prev->next = (add); \
(head)->prev = (add); \
(add)->next = NULL; \
} else { \
(head)=(add); \
(head)->prev = (head); \
(head)->next = NULL; \
} \
} while (0)
#define DL_CONCAT(head1,head2) \
DL_CONCAT2(head1,head2,prev,next)
#define DL_CONCAT2(head1,head2,prev,next) \
do { \
LDECLTYPE(head1) _tmp; \
if (head2) { \
if (head1) { \
_tmp = (head2)->prev; \
(head2)->prev = (head1)->prev; \
(head1)->prev->next = (head2); \
(head1)->prev = _tmp; \
} else { \
(head1)=(head2); \
} \
} \
} while (0)
#define DL_DELETE(head,del) \
DL_DELETE2(head,del,prev,next)
#define DL_DELETE2(head,del,prev,next) \
do { \
assert((del)->prev != NULL); \
if ((del)->prev == (del)) { \
(head)=NULL; \
} else if ((del)==(head)) { \
(del)->next->prev = (del)->prev; \
(head) = (del)->next; \
} else { \
(del)->prev->next = (del)->next; \
if ((del)->next) { \
(del)->next->prev = (del)->prev; \
} else { \
(head)->prev = (del)->prev; \
} \
} \
} while (0)
#define DL_FOREACH(head,el) \
DL_FOREACH2(head,el,next)
#define DL_FOREACH2(head,el,next) \
for(el=head;el;el=(el)->next)
/* this version is safe for deleting the elements during iteration */
#define DL_FOREACH_SAFE(head,el,tmp) \
DL_FOREACH_SAFE2(head,el,tmp,next)
#define DL_FOREACH_SAFE2(head,el,tmp,next) \
for((el)=(head);(el) && (tmp = (el)->next, 1); (el) = tmp)
/* these are identical to their singly-linked list counterparts */
#define DL_SEARCH_SCALAR LL_SEARCH_SCALAR
#define DL_SEARCH LL_SEARCH
#define DL_SEARCH_SCALAR2 LL_SEARCH_SCALAR2
#define DL_SEARCH2 LL_SEARCH2
#define DL_REPLACE_ELEM(head, el, add) \
do { \
assert(head != NULL); \
assert(el != NULL); \
assert(add != NULL); \
if ((head) == (el)) { \
(head) = (add); \
(add)->next = (el)->next; \
if ((el)->next == NULL) { \
(add)->prev = (add); \
} else { \
(add)->prev = (el)->prev; \
(add)->next->prev = (add); \
} \
} else { \
(add)->next = (el)->next; \
(add)->prev = (el)->prev; \
(add)->prev->next = (add); \
if ((el)->next == NULL) { \
(head)->prev = (add); \
} else { \
(add)->next->prev = (add); \
} \
} \
} while (0)
#define DL_PREPEND_ELEM(head, el, add) \
do { \
assert(head != NULL); \
assert(el != NULL); \
assert(add != NULL); \
(add)->next = (el); \
(add)->prev = (el)->prev; \
(el)->prev = (add); \
if ((head) == (el)) { \
(head) = (add); \
} else { \
(add)->prev->next = (add); \
} \
} while (0) \
/******************************************************************************
* circular doubly linked list macros *
*****************************************************************************/
#define CDL_PREPEND(head,add) \
CDL_PREPEND2(head,add,prev,next)
#define CDL_PREPEND2(head,add,prev,next) \
do { \
if (head) { \
(add)->prev = (head)->prev; \
(add)->next = (head); \
(head)->prev = (add); \
(add)->prev->next = (add); \
} else { \
(add)->prev = (add); \
(add)->next = (add); \
} \
(head)=(add); \
} while (0)
#define CDL_DELETE(head,del) \
CDL_DELETE2(head,del,prev,next)
#define CDL_DELETE2(head,del,prev,next) \
do { \
if ( ((head)==(del)) && ((head)->next == (head))) { \
(head) = 0L; \
} else { \
(del)->next->prev = (del)->prev; \
(del)->prev->next = (del)->next; \
if ((del) == (head)) (head)=(del)->next; \
} \
} while (0)
#define CDL_FOREACH(head,el) \
CDL_FOREACH2(head,el,next)
#define CDL_FOREACH2(head,el,next) \
for(el=head;el;el=((el)->next==head ? 0L : (el)->next))
#define CDL_FOREACH_SAFE(head,el,tmp1,tmp2) \
CDL_FOREACH_SAFE2(head,el,tmp1,tmp2,prev,next)
#define CDL_FOREACH_SAFE2(head,el,tmp1,tmp2,prev,next) \
for((el)=(head), ((tmp1)=(head)?((head)->prev):NULL); \
(el) && ((tmp2)=(el)->next, 1); \
((el) = (((el)==(tmp1)) ? 0L : (tmp2))))
#define CDL_SEARCH_SCALAR(head,out,field,val) \
CDL_SEARCH_SCALAR2(head,out,field,val,next)
#define CDL_SEARCH_SCALAR2(head,out,field,val,next) \
do { \
CDL_FOREACH2(head,out,next) { \
if ((out)->field == (val)) break; \
} \
} while(0)
#define CDL_SEARCH(head,out,elt,cmp) \
CDL_SEARCH2(head,out,elt,cmp,next)
#define CDL_SEARCH2(head,out,elt,cmp,next) \
do { \
CDL_FOREACH2(head,out,next) { \
if ((cmp(out,elt))==0) break; \
} \
} while(0)
#define CDL_REPLACE_ELEM(head, el, add) \
do { \
assert(head != NULL); \
assert(el != NULL); \
assert(add != NULL); \
if ((el)->next == (el)) { \
(add)->next = (add); \
(add)->prev = (add); \
(head) = (add); \
} else { \
(add)->next = (el)->next; \
(add)->prev = (el)->prev; \
(add)->next->prev = (add); \
(add)->prev->next = (add); \
if ((head) == (el)) { \
(head) = (add); \
} \
} \
} while (0)
#define CDL_PREPEND_ELEM(head, el, add) \
do { \
assert(head != NULL); \
assert(el != NULL); \
assert(add != NULL); \
(add)->next = (el); \
(add)->prev = (el)->prev; \
(el)->prev = (add); \
(add)->prev->next = (add); \
if ((head) == (el)) { \
(head) = (add); \
} \
} while (0) \
#endif /* UTLIST_H */

1209
minix/llvm/include/magic.h Normal file

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,427 @@
#ifndef _MAGIC_ANALYSIS_H
#define _MAGIC_ANALYSIS_H
#include <magic.h>
#include <magic_mem.h>
/* Special convenience types. */
#define MAGIC_TYPE_SPECIAL_INIT(STR) { 0, STR, NULL, 0, STR, 0, 0, 0, 0, 0, 0, \
0, MAGIC_TYPE_FUNCTION, MAGIC_TYPE_EXTERNAL, 0 }
EXTERN char magic_ne_str[];
EXTERN char magic_enf_str[];
EXTERN char magic_bo_str[];
EXTERN char magic_be_str[];
EXTERN char magic_bv_str[];
EXTERN char magic_vf_str[];
EXTERN const struct _magic_type magic_NULL_ENTRY_TYPE;
EXTERN const struct _magic_type magic_ENTRY_NOT_FOUND_TYPE;
EXTERN const struct _magic_type magic_BAD_OFFSET_TYPE;
EXTERN const struct _magic_type magic_BAD_ENTRY_TYPE;
EXTERN const struct _magic_type magic_BAD_VALUE_TYPE;
EXTERN const struct _magic_type magic_VALUE_FOUND;
#define MAGIC_TYPE_NULL_ENTRY (&magic_NULL_ENTRY_TYPE)
#define MAGIC_TYPE_ENTRY_NOT_FOUND (&magic_ENTRY_NOT_FOUND_TYPE)
#define MAGIC_TYPE_BAD_OFFSET (&magic_BAD_OFFSET_TYPE)
#define MAGIC_TYPE_BAD_ENTRY (&magic_BAD_ENTRY_TYPE)
#define MAGIC_TYPE_BAD_VALUE (&magic_BAD_VALUE_TYPE)
#define MAGIC_TYPE_VALUE_FOUND (&magic_VALUE_FOUND)
#define MAGIC_TYPE_IS_SPECIAL(T) (T == MAGIC_TYPE_NULL_ENTRY \
|| T == MAGIC_TYPE_ENTRY_NOT_FOUND || T == MAGIC_TYPE_BAD_OFFSET \
|| T == MAGIC_TYPE_BAD_ENTRY || T == MAGIC_TYPE_BAD_VALUE \
|| T == MAGIC_TYPE_VALUE_FOUND)
/* Magic state element macros. */
#define MAGIC_SEL_ANALYZE_POINTERS 0x00001
#define MAGIC_SEL_ANALYZE_NONPOINTERS 0x00002
#define MAGIC_SEL_ANALYZE_LIKELYPOINTERS 0x00004
#define MAGIC_SEL_ANALYZE_DATA 0x00008
#define MAGIC_SEL_ANALYZE_INVARIANTS 0x00010
#define MAGIC_SEL_ANALYZE_VIOLATIONS 0x00020
#define MAGIC_SEL_ANALYZE_WALKABLE 0x00040
#define MAGIC_SEL_ANALYZE_DYNAMIC 0x00080
#define MAGIC_SEL_ANALYZE_OUT_OF_BAND 0x00100
#define MAGIC_SEL_ANALYZE_LIB_SRC 0x00200
#define MAGIC_SEL_ANALYZE_ALL \
(MAGIC_SEL_ANALYZE_POINTERS | MAGIC_SEL_ANALYZE_NONPOINTERS \
| MAGIC_SEL_ANALYZE_DATA | MAGIC_SEL_ANALYZE_INVARIANTS \
| MAGIC_SEL_ANALYZE_VIOLATIONS | MAGIC_SEL_ANALYZE_WALKABLE \
| MAGIC_SEL_ANALYZE_DYNAMIC | MAGIC_SEL_ANALYZE_OUT_OF_BAND \
| MAGIC_SEL_ANALYZE_LIB_SRC)
#define MAGIC_SEL_SKIP_UNIONS 0x00400
#define MAGIC_SEL_SKIP_INTEGERS 0x00800
#define MAGIC_SEL_ANALYZE_NONPTRS_AS_PTRS 0x01000
#define MAGIC_SEL_ANALYZE_RETURN_TRG_PTRS 0x02000
#define MAGIC_SEL_FOUND_DATA 0x04000
#define MAGIC_SEL_FOUND_INVARIANTS 0x08000
#define MAGIC_SEL_FOUND_VIOLATIONS 0X10000
#define MAGIC_SEL_FOUND_WALKABLE 0x20000
/* Magic state element analyzed. */
typedef enum {
_ptr_type_found,
_other_types_found,
_void_type_found,
_comp_trg_types_found,
_badentry_found
} _magic_trg_stats_t;
struct _magic_sel_analyzed_s {
unsigned type_id, contained_type_id;
int flags;
int num;
union {
struct {
void *value;
union {
struct _magic_dsentry dsentry;
struct _magic_dfunction dfunction;
} trg;
struct {
struct _magic_dsentry *dsentry;
struct _magic_dfunction *dfunction;
} trg_p;
int trg_flags;
int trg_offset;
_magic_selement_t trg_selements[MAGIC_MAX_RECURSIVE_TYPES + 1];
_magic_trg_stats_t trg_stats[MAGIC_MAX_RECURSIVE_TYPES + 1];
int first_legal_trg_type;
unsigned num_legal_trg_types;
unsigned num_trg_types;
} ptr;
struct {
int value;
int trg_flags;
} nonptr;
} u;
};
typedef struct _magic_sel_analyzed_s _magic_sel_analyzed_t;
#define MAGIC_SEL_ANALYZED_PTR_HAS_TRG_FUNCTION(E) \
(((E)->u.ptr.trg_flags & MAGIC_STATE_TEXT) != 0)
#define MAGIC_SEL_ANALYZED_PTR_HAS_TRG_SENTRY(E) \
((E)->u.ptr.trg_flags && !MAGIC_SEL_ANALYZED_PTR_HAS_TRG_FUNCTION(E))
#define MAGIC_SEL_ANALYZED_PTR_SENTRY(E) \
((E)->u.ptr.trg_flags & MAGIC_SEL_ANALYZE_RETURN_TRG_PTRS) \
? (E)->u.ptr.trg_p.dsentry->sentry \
: (E)->u.ptr.trg.dsentry.sentry
#define MAGIC_SEL_ANALYZED_PTR_SENTRY_ADDRESS(E) \
((E)->u.ptr.trg_flags & MAGIC_SEL_ANALYZE_RETURN_TRG_PTRS) \
? &((E)->u.ptr.trg_p.dsentry->sentry) \
: &((E)->u.ptr.trg.dsentry.sentry)
#define MAGIC_SEL_ANALYZED_PTR_FUNCTION(E) \
((E)->u.ptr.trg_flags & MAGIC_SEL_ANALYZE_RETURN_TRG_PTRS) \
? (E)->u.ptr.trg_p.dfunction->function \
: (E)->u.ptr.trg.dfunction.function
#define MAGIC_SEL_ANALYZED_PTR_TRG_NAME(E) \
(MAGIC_SEL_ANALYZED_PTR_HAS_SPECIAL_TRG_TYPE(E) ? "" \
: MAGIC_SEL_ANALYZED_PTR_HAS_TRG_FUNCTION(E) \
? (MAGIC_SEL_ANALYZED_PTR_FUNCTION(E)).name \
: (MAGIC_SEL_ANALYZED_PTR_HAS_TRG_SENTRY(E) \
? (MAGIC_SEL_ANALYZED_PTR_SENTRY(E)).name : "?"))
#define MAGIC_SEL_ANALYZED_PTR_TRG_ADDRESS(E) \
(MAGIC_SEL_ANALYZED_PTR_HAS_SPECIAL_TRG_TYPE(E) ? NULL \
: MAGIC_SEL_ANALYZED_PTR_HAS_TRG_FUNCTION(E) \
? (MAGIC_SEL_ANALYZED_PTR_FUNCTION(E)).address \
: (MAGIC_SEL_ANALYZED_PTR_SENTRY(E)).address)
#define MAGIC_SEL_ANALYZED_PTR_PRINT_TRG_ABS_NAME(E) \
do { \
if (MAGIC_SEL_ANALYZED_PTR_HAS_SPECIAL_TRG_TYPE(E) \
|| MAGIC_SEL_ANALYZED_PTR_HAS_TRG_FUNCTION(E)) { \
_magic_printf(MAGIC_SEL_ANALYZED_PTR_TRG_NAME(E)); \
} else { \
magic_print_sentry_abs_name( \
MAGIC_SEL_ANALYZED_PTR_SENTRY_ADDRESS(E)); \
} \
} while(0)
#define MAGIC_SEL_ANALYZED_PTR_FIRST_TRG_TYPE(E) \
((E)->u.ptr.trg_selements[0].type)
#define MAGIC_SEL_ANALYZED_PTR_HAS_SPECIAL_TRG_TYPE(E) \
(MAGIC_TYPE_IS_SPECIAL(MAGIC_SEL_ANALYZED_PTR_FIRST_TRG_TYPE(E)))
#define MAGIC_SEL_ANALYZED_PTR_SET_SPECIAL_TRG_TYPE(E,T) \
do { \
(E)->u.ptr.trg_selements[0].type = T; \
(E)->u.ptr.num_trg_types = 1; \
(E)->u.ptr.num_legal_trg_types = 0; \
(E)->u.ptr.first_legal_trg_type = -1; \
} while(0)
#define MAGIC_SEL_ANALYZED_TRG_FLAGS(E) \
((E)->type_id == MAGIC_TYPE_POINTER ? (E)->u.ptr.trg_flags \
: (E)->u.nonptr.trg_flags)
#define MAGIC_SEL_ANALYZED_FLAG(E,F) (((E)->flags & F) != 0)
#define MAGIC_SEL_ANALYZED_TRG_STATS_HAS_VIOLATIONS(E) \
((E) == _other_types_found || (E) == _badentry_found)
#define MAGIC_SEL_ANALYZED_TRG_STATS_C(E) \
((E) == _ptr_type_found ? 'p' : (E) == _other_types_found ? 'o' \
: (E) == _void_type_found ? 'v' : (E) == _comp_trg_types_found ? 'c' \
: (E) == _badentry_found ? 'b' : '?')
#define MAGIC_SEL_ANALYZED_PRINT(E, FLAGS) do { \
_magic_printf("SEL_ANALYZED: (num=%d, type=%s, flags(DIVW)=%d%d%d%d", \
(E)->num, (E)->type_id == MAGIC_TYPE_POINTER ? "ptr" : "nonptr", \
MAGIC_SEL_ANALYZED_FLAG(E, MAGIC_SEL_FOUND_DATA), \
MAGIC_SEL_ANALYZED_FLAG(E, MAGIC_SEL_FOUND_INVARIANTS), \
MAGIC_SEL_ANALYZED_FLAG(E, MAGIC_SEL_FOUND_VIOLATIONS), \
MAGIC_SEL_ANALYZED_FLAG(E, MAGIC_SEL_FOUND_WALKABLE)); \
if((E)->type_id == MAGIC_TYPE_POINTER) { \
_magic_printf(", value=0x%08x, trg_name=", (E)->u.ptr.value); \
MAGIC_SEL_ANALYZED_PTR_PRINT_TRG_ABS_NAME(E); \
_magic_printf(", trg_offset=%d, trg_flags(RL)=%c%c", \
(E)->u.ptr.trg_offset, \
(E)->u.ptr.trg_flags \
? MAGIC_STATE_FLAGS_REGION_C((E)->u.ptr.trg_flags) : 0, \
(E)->u.ptr.trg_flags \
? MAGIC_STATE_FLAGS_LIBSPEC_C((E)->u.ptr.trg_flags) : 0); \
if((E)->u.ptr.num_trg_types > 0) { \
_magic_printf(", trg_selements=("); \
magic_sel_analyzed_trg_selements_print(E, FLAGS); \
_magic_printf(")"); \
} \
} else { \
_magic_printf(", value=%d/0x%08x", \
(E)->u.nonptr.value, (E)->u.nonptr.value); \
if((E)->u.nonptr.trg_flags) { \
_magic_printf(", trg_flags(RL)=%c%c", \
MAGIC_STATE_FLAGS_REGION_C((E)->u.nonptr.trg_flags), \
MAGIC_STATE_FLAGS_LIBSPEC_C((E)->u.nonptr.trg_flags)); \
} \
} \
_magic_printf(")"); \
} while(0)
/* Magic state element stats. */
struct _magic_sel_stats_s {
unsigned ptr_found;
unsigned nonptr_found;
unsigned nonptr_unconstrained_found;
int trg_flags;
int ptr_type_found;
int other_types_found;
int null_type_found;
int badoffset_found;
int unknown_found;
int void_type_found;
int comp_trg_types_found;
int value_found;
int badvalue_found;
int badentry_found;
};
typedef struct _magic_sel_stats_s _magic_sel_stats_t;
/* Magic state element stats. */
#define MAGIC_SEL_STAT_INCR(S,I,F) ((S)->F += (I)->F)
#define MAGIC_SEL_STATS_INCR(S,I) do { \
MAGIC_SEL_STAT_INCR(S,I, ptr_found); \
MAGIC_SEL_STAT_INCR(S,I, nonptr_found); \
MAGIC_SEL_STAT_INCR(S,I, nonptr_unconstrained_found); \
S->trg_flags |= I->trg_flags; \
MAGIC_SEL_STAT_INCR(S,I, ptr_type_found); \
MAGIC_SEL_STAT_INCR(S,I, other_types_found); \
MAGIC_SEL_STAT_INCR(S,I, null_type_found); \
MAGIC_SEL_STAT_INCR(S,I, badoffset_found); \
MAGIC_SEL_STAT_INCR(S,I, unknown_found); \
MAGIC_SEL_STAT_INCR(S,I, void_type_found); \
MAGIC_SEL_STAT_INCR(S,I, comp_trg_types_found); \
MAGIC_SEL_STAT_INCR(S,I, value_found); \
MAGIC_SEL_STAT_INCR(S,I, badvalue_found); \
MAGIC_SEL_STAT_INCR(S,I, badentry_found); \
} while(0)
#define MAGIC_SEL_STATS_HAS_VIOLATIONS(S) \
(MAGIC_SEL_STATS_NUM_VIOLATIONS(S) > 0)
#define MAGIC_SEL_STATS_NUM_VIOLATIONS(S) \
((S)->ptr_found ? MAGIC_SEL_PTR_STATS_NUM_VIOLATIONS(S) \
: MAGIC_SEL_NONPTR_STATS_NUM_VIOLATIONS(S))
#define MAGIC_SEL_PTR_STATS_NUM_VIOLATIONS(S) ((S)->other_types_found \
+ (S)->badoffset_found + (S)->unknown_found + (S)->badvalue_found \
+ (S)->badentry_found)
#define MAGIC_SEL_NONPTR_STATS_NUM_VIOLATIONS(S) ((S)->badvalue_found)
#define MAGIC_SEL_STATS_PRINT(E) do { \
_magic_printf("SEL_STATS: (type=%s", \
(E)->ptr_found ? "ptr" : "nonptr"); \
if((E)->trg_flags) { \
_magic_printf(", trg_flags(RL)=%c%c", \
MAGIC_STATE_FLAGS_REGION_C((E)->trg_flags), \
MAGIC_STATE_FLAGS_LIBSPEC_C((E)->trg_flags)); \
} \
if((E)->ptr_found) _magic_printf(", ptr_found=%d", (E)->ptr_found); \
if((E)->nonptr_found) \
_magic_printf(", nonptr_found=%d", (E)->nonptr_found); \
if((E)->nonptr_unconstrained_found) \
_magic_printf(", nonptr_unconstrained_found=%d", \
(E)->nonptr_unconstrained_found); \
if((E)->ptr_type_found) \
_magic_printf(", ptr_type_found=%d", (E)->ptr_type_found); \
if((E)->other_types_found) \
_magic_printf(", other_types_found=%d", (E)->other_types_found); \
if((E)->null_type_found) \
_magic_printf(", null_type_found=%d", (E)->null_type_found); \
if((E)->badoffset_found) \
_magic_printf(", badoffset_found=%d", (E)->badoffset_found); \
if((E)->unknown_found) \
_magic_printf(", unknown_found=%d", (E)->unknown_found); \
if((E)->void_type_found) \
_magic_printf(", void_type_found=%d", (E)->void_type_found); \
if((E)->comp_trg_types_found) \
_magic_printf(", comp_trg_types_found=%d", \
(E)->comp_trg_types_found); \
if((E)->value_found) \
_magic_printf(", value_found=%d", (E)->value_found); \
if((E)->badvalue_found) \
_magic_printf(", badvalue_found=%d", (E)->badvalue_found); \
if((E)->badentry_found) \
_magic_printf(", badentry_found=%d", (E)->badentry_found); \
_magic_printf(", violations=%d", MAGIC_SEL_STATS_NUM_VIOLATIONS(E)); \
_magic_printf(")"); \
} while(0)
/* Magic sentry macros. */
#define MAGIC_SENTRY_ANALYZE_STOP 1
#define MAGIC_SENTRY_ANALYZE_CONTINUE 2
#define MAGIC_SENTRY_ANALYZE_SKIP_PATH 3
#define MAGIC_SENTRY_ANALYZE_IS_VALID_RET(R) \
((R)>=MAGIC_SENTRY_ANALYZE_STOP && (R)<=MAGIC_SENTRY_ANALYZE_SKIP_PATH)
#ifndef __MINIX
#define MAGIC_PTR_LIKELY_INTS_START 0xFFFFF000
#else
#define MAGIC_PTR_LIKELY_INTS_START 0xE0000000
#endif
#define MAGIC_PTR_LIKELY_INTS_END 0xFFF
#define MAGIC_PTR_IS_LIKELY_INT(V) \
((V) && ((unsigned)(V)>=MAGIC_PTR_LIKELY_INTS_START \
|| (unsigned)(V)<=MAGIC_PTR_LIKELY_INTS_END))
#define MAGIC_INT_IS_LIKELY_PTR(V) \
((V) && !MAGIC_PTR_IS_LIKELY_INT((void*)V))
/* Magic callbacks. */
typedef int (*magic_cb_sentries_analyze_pre_t)();
PUBLIC void magic_setcb_sentries_analyze_pre(magic_cb_sentries_analyze_pre_t cb);
/* Magic state entry functions. */
typedef int (*magic_sentry_analyze_cb_t)(_magic_selement_t* selement,
_magic_sel_analyzed_t *sel_analyzed, _magic_sel_stats_t *sel_stats,
void* cb_args);
PUBLIC int magic_sentry_print_ptr_types(struct _magic_sentry* entry);
PUBLIC int magic_sentry_extract_ptrs(struct _magic_sentry* entry,
void ****ptr_map, const struct _magic_type ***ptr_type_map, int *ptr_num);
PUBLIC int magic_sentry_analyze(struct _magic_sentry* sentry, int flags,
const magic_sentry_analyze_cb_t cb, void* cb_args,
_magic_sel_stats_t *sentry_stats);
PUBLIC int magic_sentries_analyze(int flags, const magic_sentry_analyze_cb_t cb,
void* cb_args, _magic_sel_stats_t *sentries_stats);
PUBLIC int magic_sentry_print_selements(struct _magic_sentry* sentry);
PUBLIC int magic_sentry_print_ptr_selements(struct _magic_sentry* sentry,
int skip_null_ptrs, int max_target_recusions);
/* Magic dynamic state entry functions. */
PUBLIC int magic_dsentries_analyze(int flags,
const magic_sentry_analyze_cb_t cb, void* cb_args,
_magic_sel_stats_t *dsentries_stats);
/* Magic sentry analyze callbacks. */
PUBLIC int magic_sentry_print_el_cb(_magic_selement_t* selement,
_magic_sel_analyzed_t *sel_analyzed, _magic_sel_stats_t *sel_stats,
void* cb_args);
PUBLIC int magic_sentry_print_ptr_el_cb(_magic_selement_t* selement,
_magic_sel_analyzed_t *sel_analyzed, _magic_sel_stats_t *sel_stats,
void* cb_args);
PUBLIC int magic_sentry_print_el_with_trg_reg_cb(_magic_selement_t* selement,
_magic_sel_analyzed_t *sel_analyzed, _magic_sel_stats_t *sel_stats,
void* cb_args);
PUBLIC int magic_sentry_print_el_with_trg_cb(_magic_selement_t* selement,
_magic_sel_analyzed_t *sel_analyzed, _magic_sel_stats_t *sel_stats,
void* cb_args);
/* Magic sentry analyze helpers. */
#define magic_sentry_analyze_invariants(sentry, cb, cb_args, sentry_stats) \
magic_sentry_analyze(sentry, MAGIC_SEL_ANALYZE_POINTERS \
| MAGIC_SEL_ANALYZE_NONPOINTERS | MAGIC_SEL_ANALYZE_INVARIANTS, cb, \
cb_args, sentry_stats)
#define magic_sentries_analyze_invariants(cb, cb_args, sentries_stats) \
magic_sentries_analyze(MAGIC_SEL_ANALYZE_POINTERS \
| MAGIC_SEL_ANALYZE_NONPOINTERS | MAGIC_SEL_ANALYZE_INVARIANTS, cb, \
cb_args, sentries_stats)
#define magic_dsentries_analyze_invariants(cb, cb_args, dsentries_stats) \
magic_dsentries_analyze(MAGIC_SEL_ANALYZE_POINTERS \
| MAGIC_SEL_ANALYZE_NONPOINTERS | MAGIC_SEL_ANALYZE_INVARIANTS, cb, \
cb_args, dsentries_stats)
#define magic_allsentries_analyze_invariants(cb, cb_args, sentries_stats) \
magic_sentries_analyze(MAGIC_SEL_ANALYZE_POINTERS \
| MAGIC_SEL_ANALYZE_NONPOINTERS | MAGIC_SEL_ANALYZE_INVARIANTS \
| MAGIC_SEL_ANALYZE_DYNAMIC, cb, cb_args, sentries_stats)
#define magic_sentry_analyze_violations(sentry, cb, cb_args, sentry_stats) \
magic_sentry_analyze(sentry, MAGIC_SEL_ANALYZE_POINTERS \
| MAGIC_SEL_ANALYZE_NONPOINTERS | MAGIC_SEL_ANALYZE_VIOLATIONS, cb, \
cb_args, sentry_stats)
#define magic_sentries_analyze_violations(cb, cb_args, sentries_stats) \
magic_sentries_analyze(MAGIC_SEL_ANALYZE_POINTERS \
| MAGIC_SEL_ANALYZE_NONPOINTERS | MAGIC_SEL_ANALYZE_VIOLATIONS, cb, \
cb_args, sentries_stats)
#define magic_dsentries_analyze_violations(cb, cb_args, dsentries_stats) \
magic_dsentries_analyze(MAGIC_SEL_ANALYZE_POINTERS \
| MAGIC_SEL_ANALYZE_NONPOINTERS | MAGIC_SEL_ANALYZE_VIOLATIONS, cb, \
cb_args, dsentries_stats)
#define magic_allsentries_analyze_violations(cb, cb_args, sentries_stats) \
magic_sentries_analyze(MAGIC_SEL_ANALYZE_POINTERS \
| MAGIC_SEL_ANALYZE_NONPOINTERS | MAGIC_SEL_ANALYZE_VIOLATIONS \
| MAGIC_SEL_ANALYZE_DYNAMIC, cb, cb_args, sentries_stats)
#define magic_sentry_analyze_likely_pointers(sentry, cb, cb_args, sentry_stats)\
magic_sentry_analyze(sentry, MAGIC_SEL_ANALYZE_LIKELYPOINTERS \
| MAGIC_SEL_ANALYZE_DATA, cb, cb_args, sentry_stats)
#define magic_sentries_analyze_likely_pointers(cb, cb_args, sentries_stats) \
magic_sentries_analyze(MAGIC_SEL_ANALYZE_LIKELYPOINTERS \
| MAGIC_SEL_ANALYZE_DATA, cb, cb_args, sentries_stats)
#define magic_dsentries_analyze_likely_pointers(cb, cb_args, dsentries_stats) \
magic_dsentries_analyze(MAGIC_SEL_ANALYZE_LIKELYPOINTERS \
| MAGIC_SEL_ANALYZE_DATA, cb, cb_args, dsentries_stats)
#define magic_allsentries_analyze_likely_pointers(cb, cb_args, sentries_stats) \
magic_sentries_analyze(MAGIC_SEL_ANALYZE_LIKELYPOINTERS \
| MAGIC_SEL_ANALYZE_DATA | MAGIC_SEL_ANALYZE_DYNAMIC, cb, cb_args, \
sentries_stats)
/* Magic state type functions. */
PUBLIC int magic_type_count_ptrs(const struct _magic_type* type, int *ptr_num);
/* Magic type walk callbacks. */
PUBLIC int magic_type_examine_ptr_cb(const struct _magic_type* parent_type,
const unsigned parent_offset, int child_num, const struct _magic_type* type,
const unsigned offset, int depth, void* cb_args);
PUBLIC int magic_type_extract_ptr_cb(const struct _magic_type* parent_type,
const unsigned parent_offset, int child_num, const struct _magic_type* type,
const unsigned offset, int depth, void* cb_args);
PUBLIC int magic_type_analyzer_cb(const struct _magic_type* parent_type,
const unsigned parent_offset, int child_num, const struct _magic_type* type,
const unsigned offset, int depth, void* cb_args);
/* Magic state element functions. */
PUBLIC int magic_selement_analyze(_magic_selement_t *selement, int flags,
_magic_sel_analyzed_t *sel_analyzed, _magic_sel_stats_t *sel_stats);
PUBLIC int magic_selement_analyze_ptr(_magic_selement_t *selement, int flags,
_magic_sel_analyzed_t *sel_analyzed, _magic_sel_stats_t *sel_stats);
PUBLIC int magic_selement_analyze_nonptr(_magic_selement_t *selement, int flags,
_magic_sel_analyzed_t *sel_analyzed, _magic_sel_stats_t *sel_stats);
PUBLIC int magic_selement_analyze_ptr_value_invs(_magic_selement_t *selement,
_magic_sel_analyzed_t *sel_analyzed, _magic_sel_stats_t *sel_stats);
PUBLIC int magic_selement_analyze_ptr_trg_invs(_magic_selement_t *selement,
_magic_sel_analyzed_t *sel_analyzed, _magic_sel_stats_t *sel_stats);
PUBLIC _magic_trg_stats_t
magic_selement_analyze_ptr_target(const struct _magic_type *ptr_type,
const struct _magic_type *trg_type, int trg_flags);
PUBLIC int magic_selement_analyze_ptr_type_invs(_magic_selement_t *selement,
_magic_sel_analyzed_t *sel_analyzed, _magic_sel_stats_t *sel_stats);
PUBLIC int magic_selement_recurse_ptr(_magic_selement_t *selement,
_magic_selement_t *new_selement, int max_steps);
PUBLIC void
magic_sel_analyzed_trg_selements_print(_magic_sel_analyzed_t *sel_analyzed,
int flags);
PUBLIC _magic_selement_t*
magic_selement_type_cast(_magic_selement_t *selement, int flags,
const struct _magic_type* type, _magic_sel_analyzed_t *sel_analyzed,
_magic_sel_stats_t *sel_stats);
#endif /* _MAGIC_ANALYSIS_H */

View file

@ -0,0 +1,11 @@
#include <magic_def.h>
#include <magic.h>
#include <magic_mem.h>
#include <stdlib.h>
#include <stdio.h>
#include <time.h>
PUBLIC int magic_asr_get_padding_size(int region);
PUBLIC void magic_asr_permute_dsentries(struct _magic_dsentry
**first_dsentry_ptr);
PUBLIC void magic_asr_init();

View file

@ -0,0 +1,188 @@
#ifndef _MAGIC_DEF_H
#define _MAGIC_DEF_H
#if defined(_MINIX) || defined(_MINIX_SYSTEM)
#ifndef __MINIX
#define __MINIX 1
#endif
#endif
#include <limits.h>
/* Type macros. */
#ifdef __MINIX
#define MAGIC_LONG_LONG_SUPPORTED 1
#define MAGIC_LONG_DOUBLE_SUPPORTED 0
#else
#ifdef LLONG_MAX
#define MAGIC_LONG_LONG_SUPPORTED 1
#endif
#ifdef __LDBL_MAX__
#define MAGIC_LONG_DOUBLE_SUPPORTED 1
#endif
#endif
/* Modifier macros. */
#define EXTERN extern
#define PRIVATE static
#ifdef __SHARED__
#define PUBLIC EXTERN
#else
#define PUBLIC
#endif
#ifdef __MINIX
#define INLINE __inline__
#define THREAD_LOCAL
#undef UNUSED
#define FUNCTION_BLOCK(B) B
#else
#define INLINE inline
#define THREAD_LOCAL __thread
#ifdef __cplusplus
#define FUNCTION_BLOCK(B) extern "C"{ B }
#else
#define FUNCTION_BLOCK(B) B
#endif
#endif
#define UNUSED(VAR) VAR __attribute__((unused))
#define USED __attribute__((used))
#define VOLATILE volatile
/* Magic macros. */
#define MAGIC_VAR USED
#define MAGIC_FUNC PUBLIC USED __attribute__((noinline))
#define MAGIC_FUNC_BODY() __asm__("")
#define MAGIC_HOOK PUBLIC USED __attribute__((always_inline)) inline
#define MAGIC_MACRO_FUNC __attribute__((always_inline))
#define TRUE 1
#define FALSE 0
#ifdef __MINIX
#define SYS_PAGESIZE 4096
#else
#define SYS_PAGESIZE sysconf(_SC_PAGESIZE)
#endif
#define MAGIC_ROUND_DOWN(val, round) ((val) & ~((round) - 1))
#define MAGIC_ROUND_UP(val, round) (MAGIC_ROUND_DOWN(val, round) == \
(val) ? (val) : MAGIC_ROUND_DOWN((val) + (round), (round)))
#define MAGIC_ROUND_DOWN_TO_PAGESIZE(addr) MAGIC_ROUND_DOWN(addr, SYS_PAGESIZE)
#define MAGIC_ROUND_UP_TO_PAGESIZE(addr) MAGIC_ROUND_UP(addr, SYS_PAGESIZE)
#ifdef __MINIX
#define _MAGIC_CAS(P, O, N) (*(P) == (O) ? *(P)=(N) : (N)+1)
#define MAGIC_CAS(P, O, N) (_MAGIC_CAS(P, O, N) == (N) ? (O) : *(P))
#define MAGIC_FAA(P, V) (((*P)+=V)-V)
#define MAGIC_FAS(P, V) (((*P)-=V)+V)
#else
#define MAGIC_CAS(P, O, N) __sync_val_compare_and_swap((P), (O), (N))
#define MAGIC_FAA(P, V) __sync_fetch_and_add(P, V)
#define MAGIC_FAS(P, V) __sync_fetch_and_sub(P, V)
#endif
/* Magic arch-specific macros. */
#define MAGIC_FRAMEADDR_TO_RETADDR_PTR(F) (((char*)(F))+4)
/* Magic ranges. */
#define MAGIC_LINKER_VAR_NAMES "end", "etext", "edata", NULL
#ifdef __MINIX
#define MAGIC_TEXT_START ((void*)(0x1000))
#define MAGIC_STACK_GAP (4*1024)
#else
#define MAGIC_TEXT_START ((void*)(0x08048000))
#define MAGIC_STACK_GAP (4*1024*1024)
#endif
#define MAGIC_TEXT_END 0 /* 0 if right before data. */
#define MAGIC_HEAP_START 0 /* 0 if right after data. */
#define MAGIC_HEAP_GAP (4*1024)
#define MAGIC_RANGE_ROUND_DATA 1
#define MAGIC_RANGE_ROUND_TEXT 1
#define MAGIC_RANGE_ROUND_STACK 1
/* Magic IDs */
#define MAGIC_ID_NONE 0
#define MAGIC_ID_FORCE_LONG 1
#if defined(__MINIX) || MAGIC_ID_FORCE_LONG
typedef unsigned long _magic_id_t;
#define MAGIC_ID_MAX ULONG_MAX
#define MAGIC_ID_FORMAT "%lu"
#else
typedef unsigned long long _magic_id_t;
#define MAGIC_ID_MAX ULLONG_MAX
#define MAGIC_ID_FORMAT "%llu"
#endif
/* Magic error codes. */
#define MAGIC_ENOENT (-100)
#define MAGIC_EBADENT (-101)
#define MAGIC_EBADMSTATE (-102)
#define MAGIC_EINVAL (-103)
#define MAGIC_EGENERIC (-104)
#define MAGIC_EBADWALK (-105)
#define MAGIC_ERANGE (-106)
#define MAGIC_ESIGN (-107)
#define MAGIC_ENOMEM (-108)
#define MAGIC_ENOPTR ((void*)-1)
/*
* Basic return type definitions. Not really needed, but they make
* the code easier to read.
*/
#ifndef OK
#define OK 0
#endif
#ifndef EGENERIC
#define EGENERIC -1
#endif
/* Magic printf. */
#ifdef __MINIX
#define MAGIC_PRINTF_DEFAULT printf
#else
#define MAGIC_PRINTF_DEFAULT magic_err_printf
#endif
FUNCTION_BLOCK(
typedef int (*printf_ptr_t) (char const *str, ...);
EXTERN printf_ptr_t _magic_printf;
EXTERN void magic_assert_failed(const char *assertion, const char *file,
const char *function, const int line);
)
/* assert() override. */
#define ENABLE_ASSERTIONS 1
#ifndef __MINIX
#define CUSTOM_ASSERTIONS 0
#else
#define CUSTOM_ASSERTIONS 1
#endif
#include <assert.h>
#if CUSTOM_ASSERTIONS
#ifdef assert
#undef assert
#endif
#ifndef __ASSERT_FUNCTION
#define __ASSERT_FUNCTION ""
#endif
#if ENABLE_ASSERTIONS
#define assert(X) do{ \
if(!(X)) { \
magic_assert_failed(#X, __FILE__, __ASSERT_FUNCTION, __LINE__); \
} \
} while(0)
#else
# define assert(X)
#endif
#endif
#endif

View file

@ -0,0 +1,25 @@
#ifndef _MAGIC_EVAL_H
#define _MAGIC_EVAL_H
#include <magic_def.h>
typedef long (*magic_eval_func_t) (long arg);
PUBLIC void magic_eval_init();
/* Eval frontends. */
PUBLIC int magic_eval_int(char *expr, long *result);
PUBLIC int magic_eval_bool(char *expr, char *result);
PUBLIC int magic_eval_float(char *expr, double *result);
/* Printing. */
#define MAGIC_EVAL_PRINT_FUNC_RESULTS 0x01
#define MAGIC_EVAL_PRINT_VAR_VALUES 0x02
#define MAGIC_EVAL_PRINT_STYLE_DEFAULT 0
#define MAGIC_EVAL_PRINT_STYLE_ALL (MAGIC_EVAL_PRINT_FUNC_RESULTS|MAGIC_EVAL_PRINT_VAR_VALUES)
PUBLIC int magic_eval_get_print_style(void);
PUBLIC void magic_eval_set_print_style(int style);
#endif

View file

@ -0,0 +1,74 @@
/* evaluate.h (C) 2000-2002 Kyzer/CSG. */
/* Released under the terms of the GNU General Public Licence version 2. */
/* http://www.kyzer.me.uk/code/evaluate/ */
#include <stddef.h>
#include <stdlib.h>
#define T_INT 0
#define T_REAL 1
/* value */
struct val {
long ival; /* if type = T_INT, this is the result */
double rval; /* if type = T_REAL, this is the result */
char type; /* either T_INT or T_REAL */
};
/* variable */
struct var {
struct var *next; /* next variable in table or NULL */
struct val val; /* value of variable */
char *name; /* name of variable */
};
/* variable table */
struct vartable {
struct var *first; /* first entry in variable table */
struct memh *mh;
};
/* creates a new variable table (NULL if no memory) */
struct vartable *create_vartable();
/* frees a variable table */
void free_vartable(struct vartable *vt);
/* gets a variable from a variable table (NULL if not found) */
struct var *get_var(struct vartable *vt, char *name);
/* puts a variable into a variable table (NULL if no memory) */
struct var *put_var(struct vartable *vt, char *name, struct val *value);
/* callbacks */
typedef struct val*(*get_var_cb_t)(char*, struct val*);
typedef struct val*(*get_func_result_cb_t)(char*, struct val*, struct val*);
void eval_set_cb_get_var(get_var_cb_t cb);
void eval_set_cb_get_func_result(get_func_result_cb_t cb);
/* THE FUNCTION YOU WANT TO CALL */
/* given a string to evaluate (not NULL), a result to put the answer in
* (not NULL) and optionally your own variable table (NULL for 'internal
* only' vartable), will return an error code (and result, etc)
*/
int evaluate(char *eval, struct val *result, struct vartable *variables);
/* errors */
#define RESULT_OK 0 /* all OK */
#define ERROR_SYNTAX 2 /* invalid expression */
#define ERROR_VARNOTFOUND 3 /* variable not found */
#define ERROR_FUNCNOTFOUND 4 /* function not found */
#define ERROR_NOMEM 8 /* not enough memory available */
#define ERROR_DIV0 9 /* division by zero */
#define ERROR_BUSY 10 /* busy now */
/* configuration */
#define TOKEN_DEBUG 0
#define EVAL_DEBUG 0
#define EVAL_MALLOC 0
#define USE_MATH_LIB 0
#define MEM_DEBUG 0
#define MEM_LOW_FOOTPRINT 1
#define VAR_FROM_ENV 0

View file

@ -0,0 +1,284 @@
#ifndef _MAGIC_MEM_H
#define _MAGIC_MEM_H
#include <magic.h>
#define __MA_ARGS__ struct _magic_type *type, char *name, char *parent_name,
#define __MA_VALUES__ type, name, parent_name,
#define __MA_VALUES_EXT__ MAGIC_VOID_TYPE, MAGIC_ALLOC_EXT_NAME, MAGIC_ALLOC_EXT_PARENT_NAME,
#define __MD_ARGS__
#define __MD_VALUES__
#define __MD_VALUES_EXT__
#define __MD_VALUES_DEFAULT__
/* External callbacks. */
typedef void *(*magic_mem_heap_alloc_cb_t)(size_t size, char *name, char *parent_name);
typedef void (*magic_mem_create_dsentry_cb_t)(struct _magic_dsentry *dsentry);
typedef int (*magic_mem_heap_free_cb_t)(struct _magic_dsentry *dsentry);
extern magic_mem_heap_alloc_cb_t magic_mem_heap_alloc_cb;
extern magic_mem_create_dsentry_cb_t magic_mem_create_dsentry_cb;
extern magic_mem_heap_free_cb_t magic_mem_heap_free_cb;
/* Public dsentry functions. */
typedef void (*magic_dsentry_cb_t)(struct _magic_dsentry*);
PUBLIC int magic_create_dsentry(struct _magic_dsentry *dsentry,
void *data_ptr, struct _magic_type *type, size_t size, int flags,
char *name, char *parent_name);
PUBLIC struct _magic_obdsentry* magic_create_obdsentry(void *data_ptr,
struct _magic_type *type, size_t size, int flags,
char *name, char *parent_name);
PUBLIC int magic_update_dsentry_state(struct _magic_dsentry *dsentry,
unsigned long mstate);
PUBLIC void magic_free_dead_dsentries();
PUBLIC void magic_destroy_dsentry(struct _magic_dsentry *dsentry,
struct _magic_dsentry *prev_dsentry);
PUBLIC void magic_destroy_dsentry_set_ext_cb(const magic_dsentry_cb_t cb);
PUBLIC int magic_destroy_obdsentry_by_addr(void *data_ptr);
PUBLIC int magic_update_dsentry(void* addr, struct _magic_type *type);
PUBLIC void magic_stack_dsentries_create(
struct _magic_dsentry **prev_last_stack_dsentry, int num_dsentries,
/* struct _magic_dsentry *dsentry, struct _magic_type *type, void* data_ptr, char* function_name, char* name, */ ...);
PUBLIC void magic_stack_dsentries_destroy(
struct _magic_dsentry **prev_last_stack_dsentry, int num_dsentries,
/* struct _magic_dsentry *dsentry, */ ...);
/* Public dfunction functions. */
PUBLIC int magic_create_dfunction(struct _magic_dfunction *dfunction,
void *data_ptr, struct _magic_type *type, int flags,
char *name, char *parent_name);
PUBLIC void magic_destroy_dfunction(struct _magic_dfunction *dfunction);
/* Public sodesc functions. */
PUBLIC int magic_create_sodesc(struct _magic_sodesc *sodesc);
PUBLIC int magic_destroy_sodesc(struct _magic_sodesc *sodesc);
/* Public dsodesc functions. */
PUBLIC int magic_create_dsodesc(struct _magic_dsodesc *dsodesc);
PUBLIC int magic_destroy_dsodesc(struct _magic_dsodesc *dsodesc);
/* Memory usage logging support. */
#if MAGIC_MEM_USAGE_OUTPUT_CTL
/* CPU frequency (used for timestamp generation) */
EXTERN double magic_cycles_per_ns;
#endif
/* Magic malloc wrappers. */
#include <stdlib.h>
#ifndef __MINIX
#include <malloc.h>
#endif
PUBLIC void *magic_alloc(__MA_ARGS__ void *ptr, size_t size, int flags);
PUBLIC void *magic_malloc( __MA_ARGS__ size_t size);
PUBLIC void *magic_calloc( __MA_ARGS__ size_t nmemb, size_t size);
PUBLIC void magic_free( __MD_ARGS__ void *ptr);
PUBLIC void *magic_realloc(__MA_ARGS__ void *ptr, size_t size);
PUBLIC void *(*magic_real_malloc)(size_t size);
PUBLIC void *(*magic_real_calloc)(size_t nmemb, size_t size);
PUBLIC void (*magic_real_free)(void *ptr);
PUBLIC void *(*magic_real_realloc)(void *ptr, size_t size);
PUBLIC int magic_posix_memalign(__MA_ARGS__ void **memptr, size_t alignment, size_t size);
PUBLIC int (*magic_real_posix_memalign)(void **memptr, size_t alignment, size_t size);
#ifndef __MINIX
PUBLIC void *magic_valloc( __MA_ARGS__ size_t size);
PUBLIC void *magic_memalign( __MA_ARGS__ size_t boundary, size_t size);
PUBLIC void *(*magic_real_valloc)(size_t size);
PUBLIC void *(*magic_real_memalign)(size_t boundary, size_t size);
#endif
/* Magic mmap wrappers. */
#include <sys/mman.h>
#ifdef __MINIX
#ifndef MAP_ANONYMOUS
#define MAP_ANONYMOUS MAP_ANON
#endif
#endif
#ifndef _GNU_SOURCE
void *mmap64(void *addr, size_t length, int prot, int flags, int fd, off_t pgoffset);
#endif
PUBLIC void *magic_mmap(__MA_ARGS__ void *start, size_t length, int prot, int flags,
int fd, off_t offset);
PUBLIC int magic_munmap(__MD_ARGS__ void *start, size_t length);
PUBLIC void *(*magic_real_mmap)(void *start, size_t length, int prot, int flags,
int fd, off_t offset);
PUBLIC int (*magic_real_munmap)(void *start, size_t length);
/* Magic brk wrappers. */
#include <unistd.h>
PUBLIC int magic_brk( __MA_ARGS__ void *addr);
PUBLIC void *magic_sbrk(__MA_ARGS__ intptr_t increment);
PUBLIC int (*magic_real_brk)(void *addr);
PUBLIC void *(*magic_real_sbrk)(intptr_t increment);
#ifndef __MINIX
/* Magic shm wrappers. */
#include <sys/types.h>
#include <sys/shm.h>
PUBLIC void *magic_shmat(__MA_ARGS__ int shmid, const void *shmaddr, int shmflg);
PUBLIC int magic_shmdt( __MD_ARGS__ const void *shmaddr);
PUBLIC void *(*magic_real_shmat)(int shmid, const void *shmaddr, int shmflg);
PUBLIC int (*magic_real_shmdt)(const void *shmaddr);
/* Magic other wrappers. */
PUBLIC void *magic_mmap64(__MA_ARGS__ void *start, size_t length, int prot, int flags,
int fd, off_t pgoffset);
PUBLIC void *(*magic_real_mmap64)(void *start, size_t length, int prot, int flags,
int fd, off_t pgoffset);
#else
#include <minix/vm.h>
PUBLIC void *magic_vm_map_cacheblock(__MA_ARGS__ dev_t dev, off_t dev_offset,
ino_t ino, off_t ino_offset, u32_t *flags, int blocksize);
PUBLIC void *(*magic_real_vm_map_cacheblock)(dev_t dev, off_t dev_offset,
ino_t ino, off_t ino_offset, u32_t *flags, int blocksize);
#endif
/* wrappers to skip alloction */
PUBLIC void *magic_malloc_positioned( __MA_ARGS__ size_t size, void *ptr);
PUBLIC void *magic_mmap_positioned(__MA_ARGS__ void *start, size_t length, int prot, int flags,
int fd, off_t offset, struct _magic_dsentry *cached_dsentry);
/* Macros. */
#define MAGIC_ALLOC_SIZE (sizeof(struct _magic_dsentry))
#define MAGIC_SIZE_TO_REAL(S) (S + MAGIC_ALLOC_SIZE)
#define MAGIC_SIZE_TO_SOURCE(S) (S - MAGIC_ALLOC_SIZE)
#define MAGIC_PTR_TO_DSENTRY(P) \
((struct _magic_dsentry *) (((char *)P)))
#define MAGIC_PTR_FROM_DSENTRY(P) ((void *) P)
#define MAGIC_PTR_TO_DATA(P) \
((void *) (((char *)P) + MAGIC_ALLOC_SIZE))
#define MAGIC_PTR_FROM_DATA(P) \
((void *) (((char *)P) - MAGIC_ALLOC_SIZE))
/* Variables to keep track of magic mem wrappers. */
EXTERN THREAD_LOCAL short magic_mem_wrapper_active;
EXTERN short magic_mem_create_dsentry_site_id;
/* Variables to indicate if dsentry site_ids should be created. */
#if MAGIC_ALLOW_DYN_MEM_WRAPPER_NESTING
#define MAGIC_MEM_WRAPPER_IS_ACTIVE() (magic_mem_wrapper_active > 0)
#define MAGIC_MEM_WRAPPER_BEGIN() do { \
magic_mem_wrapper_active++; \
} while(0)
#define MAGIC_MEM_WRAPPER_END() do { \
assert(MAGIC_MEM_WRAPPER_IS_ACTIVE()); \
magic_mem_wrapper_active--; \
} while(0)
#else
#define MAGIC_MEM_WRAPPER_IS_ACTIVE() (magic_mem_wrapper_active == 1)
#define MAGIC_MEM_WRAPPER_BEGIN() do { \
assert(!MAGIC_MEM_WRAPPER_IS_ACTIVE()); \
magic_mem_wrapper_active = 1; \
} while(0)
#define MAGIC_MEM_WRAPPER_END() do { \
assert(MAGIC_MEM_WRAPPER_IS_ACTIVE()); \
magic_mem_wrapper_active = 0; \
} while(0)
#endif
#define MAGIC_MEM_WRAPPER_LBEGIN() do { \
MAGIC_MEM_WRAPPER_BEGIN(); \
MAGIC_DSENTRY_LOCK(); \
} while(0)
#define MAGIC_MEM_WRAPPER_LEND() do { \
MAGIC_MEM_WRAPPER_END(); \
MAGIC_DSENTRY_UNLOCK(); \
} while(0)
#define MAGIC_MEM_WRAPPER_BLOCK(BLOCK) do { \
MAGIC_MEM_WRAPPER_BEGIN(); \
BLOCK \
MAGIC_MEM_WRAPPER_END(); \
} while(0)
#define MAGIC_MEM_WRAPPER_LBLOCK(BLOCK) do { \
MAGIC_MEM_WRAPPER_LBEGIN(); \
BLOCK \
MAGIC_MEM_WRAPPER_LEND(); \
} while(0)
/* Variables to keep track of memory pool management functions. */
#define MAGIC_MEMPOOL_ID_UNKNOWN -1
#define MAGIC_MEMPOOL_ID_DETACHED -2
#define MAGIC_MEMPOOL_MAX_FUNC_RECURSIONS 100
EXTERN THREAD_LOCAL short magic_mempool_mgmt_active_level;
EXTERN THREAD_LOCAL short magic_mempool_ids[MAGIC_MEMPOOL_MAX_FUNC_RECURSIONS];
EXTERN int magic_mempool_allow_reset;
EXTERN int magic_mempool_allow_reuse;
/* TLS flags to be set when pool management functions are active. */
#define MAGIC_MEMPOOL_MGMT_SET_ACTIVE() \
assert((++magic_mempool_mgmt_active_level <= MAGIC_MEMPOOL_MAX_FUNC_RECURSIONS) \
&& "Reached the maximum number of nested pool function calls!")
#define MAGIC_MEMPOOL_MGMT_IS_ACTIVE() \
(magic_mempool_mgmt_active_level > 0)
#define MAGIC_MEMPOOL_MGMT_UNSET_ACTIVE() \
assert((--magic_mempool_mgmt_active_level >= 0) && "Invalid nested pool call level!")
#define MAGIC_MEMPOOL_SET_ID(ID) \
(magic_mempool_ids[magic_mempool_mgmt_active_level - 1] = ID)
#define MAGIC_MEMPOOL_GET_ID() \
(magic_mempool_ids[magic_mempool_mgmt_active_level - 1])
#define MAGIC_MEMPOOL_ID_IS_SET() \
(magic_mempool_ids[magic_mempool_mgmt_active_level - 1] > 0)
#define MAGIC_MEMPOOL_GET_NAME() \
(MAGIC_MEMPOOL_ID_IS_SET() ? \
_magic_mpdescs[MAGIC_MEMPOOL_GET_ID() - 1].name : \
((MAGIC_MEMPOOL_GET_ID() == MAGIC_MEMPOOL_ID_UNKNOWN) ? \
MAGIC_MEMPOOL_NAME_UNKNOWN : MAGIC_MEMPOOL_NAME_DETACHED))
/* Store dynamic type in TLS if memory usage logging is enabled */
#if MAGIC_MEM_USAGE_OUTPUT_CTL
#define MAGIC_MEMPOOL_SET_DTYPE(TYPE) \
do { \
if (MAGIC_MEMPOOL_ID_IS_SET()) { \
_magic_mpdescs[MAGIC_MEMPOOL_GET_ID() - 1].dtype_id = TYPE; \
} \
} while(0)
#define MAGIC_MEMPOOL_GET_DTYPE() \
(MAGIC_MEMPOOL_ID_IS_SET() ? \
_magic_mpdescs[MAGIC_MEMPOOL_GET_ID() - 1].dtype_id : 0)
#else
#define MAGIC_MEMPOOL_SET_DTYPE(TYPE)
#define MAGIC_MEMPOOL_GET_DTYPE() 0
#endif
/* Pass call site information when logging is activated. */
#if (MAGIC_MEM_USAGE_OUTPUT_CTL == 1)
#define __MDEBUG_ARGS__ char* name
#else
#define __MDEBUG_ARGS__
#endif
/* Specific wrapper for the memory pool creation. */
MAGIC_HOOK void magic_mempool_create_begin(__MDEBUG_ARGS__);
MAGIC_HOOK void magic_mempool_create_end(void* addr, int indirection);
/* Specific wrappers for the memory pool destruction. */
MAGIC_HOOK void magic_mempool_destroy_begin(void* addr, int memory_reuse);
MAGIC_HOOK void magic_mempool_destroy_end();
/* Specific wrappers for the memory pool resetting */
MAGIC_HOOK void magic_mempool_reset_begin(void* addr);
/* Generic wrappers for the rest of the memory pool management functions. */
MAGIC_HOOK void magic_mempool_mgmt_begin(void* addr);
MAGIC_HOOK void magic_mempool_mgmt_end();
/* Pool block allocation template function and magic wrapper. */
MAGIC_FUNC void *mempool_block_alloc_template(void* addr, size_t size);
PUBLIC void *magic_mempool_block_alloc_template(__MA_ARGS__ void* addr, size_t size);
#endif

View file

@ -0,0 +1,100 @@
#ifndef _MAGIC_RANGE_H
#define _MAGIC_RANGE_H
#include <magic.h>
#include <magic_def.h>
#include <magic_common.h>
#include <magic_structs.h>
/* Magic memory ranges */
#define magic_null_range _magic_vars->null_range
#define magic_data_range _magic_vars->data_range
#define magic_heap_range _magic_vars->heap_range
#define magic_map_range _magic_vars->map_range
#define magic_shm_range _magic_vars->shm_range
#define magic_stack_range _magic_vars->stack_range
#define magic_text_range _magic_vars->text_range
#define magic_sentry_range _magic_vars->sentry_range
#define magic_function_range _magic_vars->function_range
#define magic_dfunction_range _magic_vars->dfunction_range
#define magic_heap_start _magic_vars->heap_start
#define magic_heap_end _magic_vars->heap_end
#define magic_update_dsentry_ranges _magic_vars->update_dsentry_ranges
#define magic_update_dfunction_ranges _magic_vars->update_dfunction_ranges
/* Magic address ranges. */
#define MAGIC_ADDR_IS_WITHIN(A, MIN, MAX) ((MIN) <= (A) && (A) <= (MAX))
#define MAGIC_ADDR_IS_IN_RANGE(A, R) \
MAGIC_ADDR_IS_WITHIN(A, (R)[0], (R)[1])
#define MAGIC_RANGE_IS_IN_RANGE(r, R) \
(MAGIC_ADDR_IS_IN_RANGE((r)[0], R) && MAGIC_ADDR_IS_IN_RANGE((r)[1], R))
#define MAGIC_RANGE_COPY(RS, RD) memcpy(RD, RS, 2 * sizeof(void *))
#define MAGIC_RANGE_INIT(R) MAGIC_RANGE_COPY(magic_null_range,R)
#define MAGIC_RANGE_IS_NULL(R) \
((R)[0] == magic_null_range[0] && (R)[1] == magic_null_range[1])
#define MAGIC_RANGE_IS_VALID(R) \
(MAGIC_RANGE_IS_NULL(R) || ((R)[0] <= (R)[1]))
#define MAGIC_RANGE_UPDATE(R, MIN, MAX) \
do { \
if(MIN < (R)[0]) \
(R)[0] = MIN; \
if(MAX > (R)[1]) \
(R)[1] = MAX; \
} while(0)
#define MAGIC_RANGE_SET_MIN(R, MIN) ((R)[0] = MIN)
#define MAGIC_RANGE_SET_MAX(R, MAX) ((R)[1] = MAX)
#define MAGIC_RANGE_SET(R, MIN, MAX) \
do { \
MAGIC_RANGE_SET_MIN(R, MIN); \
MAGIC_RANGE_SET_MAX(R, MAX); \
} while(0)
#define MAGIC_RANGE_PAGE_ROUND_MIN(R) \
((R)[0] = (char*)(R)[0] - (unsigned long)(R)[0] % MAGIC_PAGE_SIZE)
#define MAGIC_RANGE_PAGE_ROUND_MAX(R) \
do { \
unsigned long diff = (unsigned long)(R)[1] % MAGIC_PAGE_SIZE; \
if(diff) \
(R)[1] = (char *)(R)[1] + MAGIC_PAGE_SIZE - diff - 1; \
} while(0)
#define MAGIC_RANGE_PAGE_ROUND(R) \
do { \
MAGIC_RANGE_PAGE_ROUND_MIN(R); \
MAGIC_RANGE_PAGE_ROUND_MAX(R); \
} while(0)
#define MAGIC_RANGE_PRINT(R) \
_magic_printf("RANGE %s=[0x%08x;0x%08x]", #R, (unsigned long)((R)[0]), \
(unsigned long)((R)[1]))
#define MAGIC_RANGE_CHECK(R) \
assert(MAGIC_RANGE_IS_VALID(R) && "Invalid range " #R);
#define MAGIC_RANGE_SIZE(R) \
(!MAGIC_RANGE_IS_VALID(R) || MAGIC_RANGE_IS_NULL(R) ? \
0 : (char *)(R)[1] - (char *)(R)[0])
#if MAGIC_RANGE_DEBUG
#define MAGIC_RANGE_DEBUG_ADDR(A, R) \
do { \
char *what = MAGIC_ADDR_IS_IN_RANGE(A, R) ? "" : "not "; \
_magic_printf("MRD: Address 0x%08x %sin ", A, what); \
MAGIC_RANGE_PRINT(R); \
_magic_printf("\n"); \
MAGIC_RANGE_CHECK(R); \
} while(0);
#else
#define MAGIC_RANGE_DEBUG_ADDR(A,R) MAGIC_RANGE_CHECK(R)
#endif
#define MAGIC_ADDR_LOOKUP_USE_DSENTRY_RANGES 1
#define MAGIC_ADDR_LOOKUP_USE_DFUNCTION_RANGES 1
/* Magic range functions. */
PUBLIC void magic_ranges_init(void);
PUBLIC int magic_range_is_dfunction(void* addr);
PUBLIC int magic_range_is_dsentry(void* addr);
PUBLIC int magic_range_is_stack(void* addr);
/* Lookup functions. */
PUBLIC int magic_range_lookup_by_addr(void *addr, void **container);
#endif /* _MAGIC_RANGE_H */

View file

@ -0,0 +1,19 @@
#ifndef _MAGIC_RCU_H
#define _MAGIC_RCU_H
void magic_rcu_quiescent_begin();
void magic_rcu_quiescent_end();
void magic_rcu_quiescent_state();
void magic_rcu_quiescent_state_start();
void magic_rcu_quiescent_state_end();
void magic_rcu_init();
void magic_synchronize_rcu();
void magic_rcu_read_lock();
void magic_rcu_read_unlock();
#define magic_rcu_has_atomic_quiescent_state() magic_rcu_has_atomic_qs
extern int magic_rcu_has_atomic_qs;
#endif /* _MAGIC_RCU_H */

View file

@ -0,0 +1,28 @@
#ifndef _MAGIC_REAL_MEM_H
#define _MAGIC_REAL_MEM_H
#include <magic_mem.h>
#define malloc magic_real_malloc
#define calloc magic_real_calloc
#define free magic_real_free
#define realloc magic_real_realloc
#define posix_memalign magic_real_posix_memalign
#define valloc magic_real_valloc
#define memalign magic_real_memalign
#define mmap magic_real_mmap
#define munmap magic_real_munmap
#define brk magic_real_brk
#define sbrk magic_real_sbrk
#define shmat magic_real_shmat
#define shmdt magic_real_shmdt
#define mmap64 magic_real_mmap64
#define vm_map_cacheblock magic_real_vm_map_cacheblock
#endif

View file

@ -0,0 +1,53 @@
#ifndef _MAGIC_SELEMENT_H
#define _MAGIC_SELEMENT_H
#include <magic.h>
#include <magic_def.h>
#include <magic_common.h>
#include <magic_structs.h>
#include <magic_analysis.h>
/* Magic state element functions. */
PUBLIC void magic_selement_print_value(const _magic_selement_t *selement);
PUBLIC unsigned long
magic_selement_to_unsigned(const _magic_selement_t *selement);
PUBLIC long magic_selement_to_int(const _magic_selement_t *selement);
#if MAGIC_LONG_LONG_SUPPORTED
PUBLIC unsigned long long
magic_selement_to_llu(const _magic_selement_t *selement);
PUBLIC long long magic_selement_to_ll(const _magic_selement_t *selement);
#endif
PUBLIC double magic_selement_to_float(const _magic_selement_t *selement);
PUBLIC void* magic_selement_to_ptr(const _magic_selement_t *selement);
PUBLIC void magic_selement_from_unsigned(const _magic_selement_t *selement,
unsigned long value);
PUBLIC void magic_selement_from_int(const _magic_selement_t *selement,
long value);
PUBLIC void magic_selement_from_float(const _magic_selement_t *selement,
double value);
PUBLIC int magic_selement_ptr_value_cast(const _magic_selement_t *src_selement,
const _magic_selement_t *dst_selement, void* value_buffer);
PUBLIC int
magic_selement_unsigned_value_cast(const _magic_selement_t *src_selement,
const _magic_selement_t *dst_selement, void* value_buffer);
PUBLIC int magic_selement_int_value_cast(const _magic_selement_t *src_selement,
const _magic_selement_t *dst_selement, void* value_buffer);
PUBLIC int
magic_selement_float_value_cast(const _magic_selement_t *src_selement,
const _magic_selement_t *dst_selement, void* value_buffer);
PUBLIC int magic_selement_value_cast(const _magic_selement_t *src_selement,
const _magic_selement_t *dst_selement, void* value_buffer);
PUBLIC _magic_selement_t*
magic_selement_get_parent(const _magic_selement_t *selement,
_magic_selement_t *parent_selement);
PUBLIC void magic_selement_fill_from_parent_info(_magic_selement_t *selement,
int walk_flags);
PUBLIC _magic_selement_t*
magic_selement_from_sentry(struct _magic_sentry *sentry,
_magic_selement_t *selement);
PUBLIC _magic_selement_t*
magic_selement_from_relative_name(_magic_selement_t *parent_selement,
_magic_selement_t *selement, char* name);
#endif /* _MAGIC_SELEMENT_H */

View file

@ -0,0 +1,181 @@
#ifndef _MAGIC_SENTRY_H
#define _MAGIC_SENTRY_H
#include <magic.h>
#include <magic_def.h>
#include <magic_common.h>
#include <magic_structs.h>
#include <common/ut/utlist.h>
/* Magic state entry macros. */
#define MAGIC_SENTRY_SITE_ID(E) \
(MAGIC_STATE_FLAG(E, MAGIC_STATE_DYNAMIC) ? \
MAGIC_DSENTRY_FROM_SENTRY(E)->site_id : MAGIC_DSENTRY_SITE_ID_NULL)
#define MAGIC_SENTRY_PARENT(E) \
(MAGIC_STATE_FLAG(E, MAGIC_STATE_DYNAMIC) ? \
MAGIC_DSENTRY_FROM_SENTRY(E)->parent_name : "")
#define MAGIC_SENTRY_ID(E) ((E)->id)
#define MAGIC_SENTRY_IS_STRING(E) MAGIC_STATE_FLAG(E,MAGIC_STATE_STRING)
#define MAGIC_SENTRY_IS_NAMED_STRING(E) \
MAGIC_STATE_FLAG(E,MAGIC_STATE_NAMED_STRING)
#define MAGIC_SENTRY_IS_DSENTRY(E) MAGIC_STATE_FLAG(E,MAGIC_STATE_DYNAMIC)
/* XXX: Be careful when negating the following macros! */
#define MAGIC_SENTRY_IS_ALLOC(E) \
(MAGIC_SENTRY_IS_DSENTRY(E) && !MAGIC_STATE_FLAG(E,MAGIC_STATE_STACK))
#define MAGIC_SENTRY_IS_EXT_ALLOC(E) \
(MAGIC_SENTRY_IS_ALLOC(E) && !strcmp((E)->name, MAGIC_ALLOC_EXT_NAME) && \
!strcmp(MAGIC_DSENTRY_FROM_SENTRY(E)->parent_name, \
MAGIC_ALLOC_EXT_PARENT_NAME))
#define MAGIC_SENTRY_IS_LIB_ALLOC(E) \
(MAGIC_SENTRY_IS_ALLOC(E) && \
!strncmp((E)->name, MAGIC_ALLOC_EXT_NAME, strlen(MAGIC_ALLOC_EXT_NAME)) && \
strlen((E)->name) > strlen(MAGIC_ALLOC_EXT_NAME))
#define MAGIC_SENTRY_PRINT(E, EXPAND_TYPE_STR) do { \
_magic_printf("SENTRY: (id=%5lu, name=%s, parent=%s, address=0x%08x, " \
"flags(RLDCdeTAOSNrwxtpbEZIiP)=" \
"%c%c%d%d%d%d%d%d%d%d%d%d%d%d%d%d%d%d%d%d%d, type=", \
(unsigned long) MAGIC_SENTRY_ID(E), (E)->name, \
MAGIC_SENTRY_PARENT(E), (unsigned) (E)->address, \
MAGIC_STATE_REGION_C(E), MAGIC_STATE_LIBSPEC_C(E), \
MAGIC_STATE_FLAG(E,MAGIC_STATE_DIRTY), \
MAGIC_STATE_FLAG(E,MAGIC_STATE_CONSTANT), \
MAGIC_STATE_FLAG(E,MAGIC_STATE_DYNAMIC), \
MAGIC_STATE_FLAG(E,MAGIC_STATE_EXT), \
MAGIC_STATE_FLAG(E,MAGIC_STATE_DETACHED), \
MAGIC_STATE_FLAG(E,MAGIC_STATE_ADDR_NOT_TAKEN), \
MAGIC_STATE_FLAG(E,MAGIC_STATE_OUT_OF_BAND), \
MAGIC_STATE_FLAG(E,MAGIC_STATE_STRING), \
MAGIC_STATE_FLAG(E,MAGIC_STATE_NAMED_STRING), \
MAGIC_STATE_FLAG(E,MAGIC_STATE_MODE_R), \
MAGIC_STATE_FLAG(E,MAGIC_STATE_MODE_W), \
MAGIC_STATE_FLAG(E,MAGIC_STATE_MODE_X), \
MAGIC_STATE_FLAG(E,MAGIC_STATE_THREAD_LOCAL), \
MAGIC_STATE_FLAG(E,MAGIC_STATE_MEMPOOL), \
MAGIC_STATE_FLAG(E,MAGIC_STATE_MEMBLOCK), \
MAGIC_STATE_FLAG(E,MAGIC_STATE_EXTERNAL), \
MAGIC_STATE_FLAG(E,MAGIC_STATE_TYPE_SIZE_MISMATCH), \
MAGIC_STATE_FLAG(E,MAGIC_STATE_IMMUTABLE), \
MAGIC_STATE_FLAG(E,MAGIC_STATE_INIT), \
MAGIC_STATE_FLAG(E,MAGIC_STATE_DIRTY_PAGE)); \
MAGIC_TYPE_PRINT((E)->type, EXPAND_TYPE_STR); \
_magic_printf(")"); \
} while(0)
#define MAGIC_SENTRY_OFF_BY_N_NO_DUPLICATES 0x01
#define MAGIC_SENTRY_OFF_BY_N_POSITIVE 0x02
#define MAGIC_SENTRY_OFF_BY_N_NEGATIVE 0x04
#define MAGIC_SENTRY_OFF_BY_N_ZERO 0x08
#define MAGIC_SENTRY_OFF_BY_N_ALL_N (MAGIC_SENTRY_OFF_BY_N_POSITIVE | \
MAGIC_SENTRY_OFF_BY_N_NEGATIVE | MAGIC_SENTRY_OFF_BY_N_ZERO)
/* Magic state entry array. */
#define _magic_sentries (_magic_vars->sentries)
#define _magic_sentries_num (_magic_vars->sentries_num)
#define _magic_sentries_str_num (_magic_vars->sentries_str_num)
#define _magic_sentries_next_id (_magic_vars->sentries_next_id)
/* Range lookup index */
#define magic_sentry_rl_buff (_magic_vars->sentry_rl_buff)
#define magic_sentry_rl_buff_offset (_magic_vars->sentry_rl_buff_offset)
#define magic_sentry_rl_buff_size (_magic_vars->sentry_rl_buff_size)
#define magic_sentry_rl_index (_magic_vars->sentry_rl_index)
/* Hash vars */
#define magic_sentry_hash_buff (_magic_vars->sentry_hash_buff)
#define magic_sentry_hash_buff_offset (_magic_vars->sentry_hash_buff_offset)
#define magic_sentry_hash_buff_size (_magic_vars->sentry_hash_buff_size)
#define magic_sentry_hash_head (_magic_vars->sentry_hash_head)
/* Estimated maximum number of buckets needed. Increase as necessary. */
#define MAGIC_SENTRY_NAME_EST_MAX_BUCKETS 32768
/*
* Since we don't support freeing memory, we need to allocate _all_ the
* intermediate buckets as well. For simplicity, just assume 1 + 2 + 4 + ...
* + 2^n, though it will probably be less than that.
*/
#define MAGIC_SENTRY_NAME_EST_TOTAL_BUCKETS \
((MAGIC_SENTRY_NAME_EST_MAX_BUCKETS << 1) - 1)
#define MAGIC_SENTRY_NAME_HASH_OVERHEAD \
(MAGIC_SENTRY_NAME_EST_TOTAL_BUCKETS * sizeof(UT_hash_bucket) + \
sizeof(UT_hash_table))
#define MAGIC_SENTRY_TO_HASH_EL(sentry, sentry_hash, sentry_list) \
do { \
assert(strlen(sentry->name) + 2 * strlen(MAGIC_DSENTRY_ABS_NAME_SEP) \
+ 2 < MAGIC_SENTRY_NAME_MAX_KEY_LEN \
&& "Sentry key length too long!"); \
\
sentry_hash->key[0] = 0; \
sprintf(sentry_hash->key, "%s%s%s" MAGIC_ID_FORMAT, \
MAGIC_DSENTRY_ABS_NAME_SEP, sentry->name, \
MAGIC_DSENTRY_ABS_NAME_SEP, \
(_magic_id_t) MAGIC_DSENTRY_SITE_ID_NULL); \
sentry_list->sentry = sentry; \
sentry_hash->sentry_list = sentry_list; \
} while (0)
#define MAGIC_DSENTRY_TO_HASH_EL(dsentry, sentry, sentry_hash, sentry_list) \
do { \
assert(strlen(sentry->name) + strlen(dsentry->parent_name) \
+ 2 * strlen(MAGIC_DSENTRY_ABS_NAME_SEP) \
+ 10 + \
+ 1 < MAGIC_SENTRY_NAME_MAX_KEY_LEN \
&& "Dsentry key length too long!"); \
\
sentry_hash->key[0] = 0; \
sprintf(sentry_hash->key, "%s%s%s%s" MAGIC_ID_FORMAT, \
dsentry->parent_name, MAGIC_DSENTRY_ABS_NAME_SEP, sentry->name, \
MAGIC_DSENTRY_ABS_NAME_SEP, dsentry->site_id); \
sentry_list->sentry = sentry; \
sentry_hash->sentry_list = sentry_list; \
} while (0)
/* Lookup functions. */
PUBLIC struct _magic_sentry *magic_sentry_lookup_by_id(_magic_id_t id,
struct _magic_dsentry *dsentry_buff);
PUBLIC struct _magic_sentry *magic_sentry_lookup_by_addr(void *addr,
struct _magic_dsentry *dsentry_buff);
PUBLIC struct _magic_sentry *magic_sentry_lookup_by_name(char *parent_name,
char *name, _magic_id_t site_id, struct _magic_dsentry *dsentry_buff);
PUBLIC struct _magic_sentry *magic_sentry_lookup_by_range(void *addr,
struct _magic_dsentry *dsentry_buff);
PUBLIC struct _magic_sentry *magic_sentry_lookup_by_min_off_by_n(void *addr,
int flags, long *min_n_ptr, struct _magic_dsentry *dsentry_buff);
PUBLIC struct _magic_sentry *magic_sentry_lookup_by_string(char *string);
/* Lookup index functions. */
PUBLIC void magic_sentry_rl_build_index(void *buff, size_t buff_size);
PUBLIC void magic_sentry_rl_destroy_index(void);
PUBLIC size_t magic_sentry_rl_estimate_index_buff_size(int sentries_num);
PUBLIC void magic_sentry_rl_print_index(void);
PUBLIC struct _magic_sentry *magic_sentry_rl_lookup(void* start_addr);
PUBLIC struct _magic_sentry *magic_sentry_rl_insert(void* start_addr,
struct _magic_sentry *sentry);
PUBLIC struct _magic_sentry *magic_sentry_rl_pred_lookup(void* addr);
PUBLIC struct _magic_sentry *magic_sentry_lookup_by_range_index(void *addr,
struct _magic_dsentry *dsentry_buff);
/* Lookup hash functions. */
PUBLIC void magic_sentry_hash_build(void *buff, size_t buff_size);
PUBLIC void magic_sentry_hash_destroy(void);
PUBLIC size_t magic_sentry_hash_estimate_buff_size(int sentries_num);
PUBLIC struct _magic_sentry *magic_sentry_lookup_by_name_hash(char *parent_name,
char *name, _magic_id_t site_id, struct _magic_dsentry *dsentry_buff);
PUBLIC void *magic_sentry_hash_alloc(size_t size);
PUBLIC void magic_sentry_hash_dealloc(void *object, size_t size);
PUBLIC struct _magic_sentry_list *magic_sentry_list_lookup_by_name_hash(
char *parent_name, char *name, _magic_id_t site_id,
struct _magic_dsentry *dsentry_buff);
/* Magic state entry functions. */
PUBLIC int magic_check_sentry(struct _magic_sentry *entry);
PUBLIC int magic_check_sentries();
PUBLIC void magic_print_sentry(struct _magic_sentry* entry);
PUBLIC void magic_print_sentry_abs_name(struct _magic_sentry *sentry);
PUBLIC void magic_print_sentries();
PUBLIC void magic_print_nonstr_sentries();
PUBLIC void magic_print_str_sentries();
PUBLIC long magic_sentry_get_off_by_n(struct _magic_sentry* sentry,
void *addr, int flags);
#endif /* _MAGIC_SENTRY_H */

View file

@ -0,0 +1,147 @@
/* A splay-tree datatype.
Copyright 1998, 1999, 2000, 2002 Free Software Foundation, Inc.
Contributed by Mark Mitchell (mark@markmitchell.com).
This file is part of GCC.
GCC 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, or (at your option)
any later version.
GCC 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 GCC; see the file COPYING. If not, write to
the Free Software Foundation, 51 Franklin Street - Fifth Floor,
Boston, MA 02110-1301, USA. */
/* For an easily readable description of splay-trees, see:
Lewis, Harry R. and Denenberg, Larry. Data Structures and Their
Algorithms. Harper-Collins, Inc. 1991.
The major feature of splay trees is that all basic tree operations
are amortized O(log n) time for a tree with n nodes. */
#ifndef _SPLAY_TREE_H
#define _SPLAY_TREE_H
#ifdef __cplusplus
extern "C" {
#endif /* __cplusplus */
#ifndef GTY
#define GTY(X)
#endif
#ifndef ATTRIBUTE_UNUSED
#define ATTRIBUTE_UNUSED __attribute__ ((__unused__))
#endif /* ATTRIBUTE_UNUSED */
/* Use typedefs for the key and data types to facilitate changing
these types, if necessary. These types should be sufficiently wide
that any pointer or scalar can be cast to these types, and then
cast back, without loss of precision. */
typedef unsigned long int splay_tree_key;
typedef unsigned long int splay_tree_value;
/* Forward declaration for a node in the tree. */
typedef struct splay_tree_node_s *splay_tree_node;
/* The type of a function which compares two splay-tree keys. The
function should return values as for qsort. */
typedef int (*splay_tree_compare_fn) (splay_tree_key, splay_tree_key);
/* The type of a function used to deallocate any resources associated
with the key. */
typedef void (*splay_tree_delete_key_fn) (splay_tree_key);
/* The type of a function used to deallocate any resources associated
with the value. */
typedef void (*splay_tree_delete_value_fn) (splay_tree_value);
/* The type of a function used to iterate over the tree. */
typedef int (*splay_tree_foreach_fn) (splay_tree_node, void*);
/* The type of a function used to allocate memory for tree root and
node structures. The first argument is the number of bytes needed;
the second is a data pointer the splay tree functions pass through
to the allocator. This function must never return zero. */
typedef void *(*splay_tree_allocate_fn) (int, void *);
/* The type of a function used to free memory allocated using the
corresponding splay_tree_allocate_fn. The first argument is the
memory to be freed; the latter is a data pointer the splay tree
functions pass through to the freer. */
typedef void (*splay_tree_deallocate_fn) (void *, void *);
/* The nodes in the splay tree. */
struct splay_tree_node_s GTY(())
{
/* The key. */
splay_tree_key GTY ((use_param1)) key;
/* The value. */
splay_tree_value GTY ((use_param2)) value;
/* The left and right children, respectively. */
splay_tree_node GTY ((use_params)) left;
splay_tree_node GTY ((use_params)) right;
};
/* The splay tree itself. */
struct splay_tree_s GTY(())
{
/* The root of the tree. */
splay_tree_node GTY ((use_params)) root;
/* The comparision function. */
splay_tree_compare_fn comp;
/* The deallocate-key function. NULL if no cleanup is necessary. */
splay_tree_delete_key_fn delete_key;
/* The deallocate-value function. NULL if no cleanup is necessary. */
splay_tree_delete_value_fn delete_value;
/* Allocate/free functions, and a data pointer to pass to them. */
splay_tree_allocate_fn allocate;
splay_tree_deallocate_fn deallocate;
void * GTY((skip)) allocate_data;
};
typedef struct splay_tree_s *splay_tree;
extern splay_tree splay_tree_new (splay_tree_compare_fn,
splay_tree_delete_key_fn,
splay_tree_delete_value_fn);
extern splay_tree splay_tree_new_with_allocator (splay_tree_compare_fn,
splay_tree_delete_key_fn,
splay_tree_delete_value_fn,
splay_tree_allocate_fn,
splay_tree_deallocate_fn,
void *);
extern void splay_tree_delete (splay_tree);
extern splay_tree_node splay_tree_insert (splay_tree,
splay_tree_key,
splay_tree_value);
extern void splay_tree_remove (splay_tree, splay_tree_key);
extern splay_tree_node splay_tree_lookup (splay_tree, splay_tree_key);
extern splay_tree_node splay_tree_predecessor (splay_tree, splay_tree_key);
extern splay_tree_node splay_tree_successor (splay_tree, splay_tree_key);
extern splay_tree_node splay_tree_max (splay_tree);
extern splay_tree_node splay_tree_min (splay_tree);
extern int splay_tree_foreach (splay_tree, splay_tree_foreach_fn, void*);
extern int splay_tree_compare_ints (splay_tree_key, splay_tree_key);
extern int splay_tree_compare_pointers (splay_tree_key, splay_tree_key);
#ifdef __cplusplus
}
#endif /* __cplusplus */
#endif /* _SPLAY_TREE_H */

View file

@ -0,0 +1,312 @@
#ifndef _MAGIC_STRUCTS_H
#define _MAGIC_STRUCTS_H
#include <magic_def.h>
#include <magic_common.h>
#include <stddef.h>
#include <common/ut/uthash.h>
/* Magic state type struct. */
struct _magic_type {
_magic_id_t id;
char *name;
char **names;
unsigned num_names;
char *type_str;
unsigned size;
unsigned num_child_types;
struct _magic_type **contained_types;
struct _magic_type **compatible_types;
char **member_names;
unsigned *member_offsets;
void *value_set;
unsigned type_id;
int flags;
unsigned bit_width;
void *ext;
};
/* Magic state entry struct. */
struct _magic_sentry {
_magic_id_t id;
char *name;
struct _magic_type *type;
int flags;
void *address;
void *shadow_address;
};
/* Magic state entry list struct. */
struct _magic_sentry_list {
struct _magic_sentry *sentry;
struct _magic_sentry_list *next;
};
/* Magic state entry hash struct. */
#define MAGIC_SENTRY_NAME_MAX_KEY_LEN 512
struct _magic_sentry_hash {
struct _magic_sentry_list *sentry_list;
char key[MAGIC_SENTRY_NAME_MAX_KEY_LEN];
UT_hash_handle hh;
};
/* Magic state function struct. */
struct _magic_function {
_magic_id_t id;
char *name;
struct _magic_type *type;
int flags;
void *address;
};
/* Magic state function hash struct. */
struct _magic_function_hash {
struct _magic_function *function;
void *key;
UT_hash_handle hh;
};
/* Magic dynamic function struct. */
struct _magic_dfunction {
unsigned long magic_number;
char *parent_name;
struct _magic_function function;
struct _magic_dfunction *prev;
struct _magic_dfunction *next;
};
/* Magic dynamic state index struct. */
struct _magic_dsindex {
struct _magic_type *type;
char *name;
char *parent_name;
int flags;
};
/* Magic dynamic state entry struct. */
#define MAGIC_DSENTRY_ALLOW_PREV 0
/*
* The name of an externally allocated dsentry will be:
* strlen("MAGIC_EXT_ALLOC_NAME") + strlen("MAGIC_ALLOC_NAME_SEP") +
* strlen(0xffffffff) + strlen("MAGIC_ALLOC_NAME_SUFFIX") + 1 =
* 4 + 1 + 10 + 1 + 1 = 17
*/
#define MAGIC_DSENTRY_EXT_NAME_BUFF_SIZE 17
struct _magic_dsentry {
unsigned long magic_number;
char *parent_name;
char name_ext_buff[MAGIC_DSENTRY_EXT_NAME_BUFF_SIZE];
struct _magic_sentry sentry;
struct _magic_type type;
struct _magic_type *type_array[1];
#if MAGIC_DSENTRY_ALLOW_PREV
struct _magic_dsentry *prev;
#endif
struct _magic_dsentry *next;
struct _magic_dsentry *next_mpool;
struct _magic_dsentry *next_mblock;
/*
* The following 2 fields are only set if the dsentry
* is part of a super object.
* See llvm/shared/magic/libst/include/heap.h for more details.
*/
#ifndef __MINIX
struct _magic_dsentry *next_sobject;
void *sobject_base_addr;
#endif
void *ext;
unsigned long magic_state;
union __alloc_flags {
struct {
int flags;
int prot;
} mmap_call;
#define mmap_flags mmap_call.flags
#define mmap_prot mmap_call.prot
struct {
int flags;
int shmid;
} shmat_call;
#define shmat_flags shmat_call.flags
#define shmat_shmid shmat_call.shmid
} alloc_flags;
#define alloc_mmap_flags alloc_flags.mmap_call.flags
#define alloc_mmap_prot alloc_flags.mmap_call.prot
#define alloc_shmat_flags alloc_flags.shmat_call.flags
#define alloc_shmat_shmid alloc_flags.shmat_call.shmid
_magic_id_t site_id; /* Identifier of the call at a callsite. */
};
/* Magic out-of-band dynamic state entry struct. */
#define MAGIC_MAX_OBDSENTRIES 32
#define MAGIC_MAX_OBDSENTRY_NAME_LEN 32
#define MAGIC_MAX_OBDSENTRY_PARENT_NAME_LEN 32
struct _magic_obdsentry {
char name[MAGIC_MAX_OBDSENTRY_NAME_LEN];
char parent_name[MAGIC_MAX_OBDSENTRY_PARENT_NAME_LEN];
struct _magic_dsentry dsentry;
};
EXTERN struct _magic_obdsentry _magic_obdsentries[MAGIC_MAX_OBDSENTRIES];
/* Magic memory pool state struct. */
#define MAGIC_MAX_MEMPOOLS 1024
#define MAGIC_MAX_MEMPOOL_NAME_LEN 32
#define MAGIC_MEMPOOL_NAME_PREFIX "_magic_mempool_"
EXTERN char *const MAGIC_MEMPOOL_NAME_UNKNOWN;
EXTERN char *const MAGIC_MEMPOOL_NAME_DETACHED;
struct _magic_mpdesc {
int is_alive;
char name[MAGIC_MAX_MEMPOOL_NAME_LEN];
/* pointer to the pool object */
void *addr;
#if MAGIC_MEM_USAGE_OUTPUT_CTL
unsigned long dtype_id;
#endif
};
EXTERN struct _magic_mpdesc _magic_mpdescs[MAGIC_MAX_MEMPOOLS];
/* Magic state element. */
struct _magic_selement_s {
struct _magic_dsentry dsentry_buff;
struct _magic_sentry *sentry;
const struct _magic_type *parent_type;
void *parent_address;
int child_num;
const struct _magic_type *type;
void *address;
int depth;
int num;
void *cb_args;
};
typedef struct _magic_selement_s _magic_selement_t;
/* Magic external library descriptor. */
struct _magic_libdesc {
const char *name;
void *text_range[2];
void *data_range[2];
void *alloc_address;
size_t alloc_size;
};
/* Magic SO library descriptor. */
struct _magic_sodesc {
struct _magic_libdesc lib;
struct _magic_sodesc *prev;
struct _magic_sodesc *next;
};
/* Magic DSO library descriptor. */
struct _magic_dsodesc {
struct _magic_libdesc lib;
void *handle;
int ref_count;
struct _magic_dsodesc *prev;
struct _magic_dsodesc *next;
};
/* Magic vars. */
struct _magic_vars_t {
/* Magic Address Space Randomization (ASRPass) */
int asr_seed;
int asr_heap_map_do_permutate;
int asr_heap_max_offset;
int asr_heap_max_padding;
int asr_map_max_offset_pages;
int asr_map_max_padding_pages;
/* Magic type array. */
struct _magic_type *types;
int types_num;
_magic_id_t types_next_id;
/* Magic function array. */
struct _magic_function *functions;
int functions_num;
_magic_id_t functions_next_id;
/* Magic state entry array. */
struct _magic_sentry *sentries;
int sentries_num;
int sentries_str_num;
_magic_id_t sentries_next_id;
/* Magic dynamic state index array. */
struct _magic_dsindex *dsindexes;
int dsindexes_num;
/* Magic dynamic state entry list. */
struct _magic_dsentry *first_dsentry;
unsigned long num_dead_dsentries;
unsigned long size_dead_dsentries;
/* Magic memory pool dynamic state entry list. */
struct _magic_dsentry *first_mempool_dsentry;
/* Magic dynamic function list. */
struct _magic_dfunction *first_dfunction;
struct _magic_dfunction *last_dfunction;
int dfunctions_num;
/* Magic SO library descriptor list. */
struct _magic_sodesc *first_sodesc;
struct _magic_sodesc *last_sodesc;
int sodescs_num;
/* Magic DSO library descriptor list. */
struct _magic_dsodesc *first_dsodesc;
struct _magic_dsodesc *last_dsodesc;
int dsodescs_num;
/* Magic stack-related variables. */
struct _magic_dsentry *first_stack_dsentry;
struct _magic_dsentry *last_stack_dsentry;
/* Magic memory ranges */
void *null_range[2];
void *data_range[2];
void *heap_range[2];
void *map_range[2];
void *shm_range[2];
void *stack_range[2];
void *text_range[2];
void *sentry_range[2];
void *function_range[2];
void *dfunction_range[2];
void *heap_start;
void *heap_end;
int update_dsentry_ranges;
int update_dfunction_ranges;
/* Range lookup index */
void *sentry_rl_buff;
size_t sentry_rl_buff_offset;
size_t sentry_rl_buff_size;
void *sentry_rl_index;
/* Sentry hash */
void *sentry_hash_buff;
size_t sentry_hash_buff_offset;
size_t sentry_hash_buff_size;
void *sentry_hash_head;
/* Function hash */
void *function_hash_buff;
size_t function_hash_buff_offset;
size_t function_hash_buff_size;
void *function_hash_head;
/*
* Don't call malloc() in magic_malloc_positioned().
* Used in ST after RAW COPY.
*/
int fake_malloc;
};
#endif /* _MAGIC_STRUCTS_H */

View file

@ -0,0 +1,127 @@
#ifndef ST_CALLBACK_H
#define ST_CALLBACK_H
#include <st/state_transfer.h>
#define NUM_CB_ARRAYS 8
#define MAX_NUM_CBS 20
/* Struct for holding info for selement transfer callbacks. */
struct st_cb_info {
_magic_selement_t *local_selement;
_magic_selement_t *local_selements;
int walk_flags;
int st_cb_flags;
int *st_cb_saved_flags;
st_init_info_t *init_info;
};
/* Callback type definitions and call registration helpers. */
#define CALLBACK_PREFIX st
#undef CALLBACK_FAMILY
#include <st/cb_template.h>
DEFINE_DECL_CALLBACK(void *, pages_allocate, (st_init_info_t *info, uint32_t *phys, int num_pages));
DEFINE_DECL_CALLBACK(void, pages_free, (st_init_info_t *info, st_alloc_pages *current_page));
DEFINE_DECL_CALLBACK(int, state_cleanup, (void));
typedef magic_sentry_analyze_cb_t st_cb_state_checking_t;
PUBLIC void st_setcb_state_checking(st_cb_state_checking_t cb);
DEFINE_DECL_CALLBACK(void, selement_map, (_magic_selement_t *cached_selement, _magic_selement_t *local_selement, struct st_cb_info *cb_info, int is_trg_mapping));
DEFINE_DECL_CALLBACK_CUSTOM(int, selement_transfer, (_magic_selement_t *selement, _magic_sel_analyzed_t *sel_analyzed, _magic_sel_stats_t *sel_stats, struct st_cb_info *cb_info), (CALLBACK_TYPENAME(selement_transfer) cb, int flags));
/* Struct for holding state transfer callback functions. */
struct st_cbs_t {
st_cb_pages_allocate_t st_cb_pages_allocate;
st_cb_pages_free_t st_cb_pages_free;
st_cb_state_cleanup_t st_cb_state_cleanup;
st_cb_state_checking_t st_cb_state_checking;
st_cb_selement_map_t st_cb_selement_map;
st_cb_selement_transfer_t st_cb_selement_transfer[NUM_CB_ARRAYS][MAX_NUM_CBS];
};
/* Predefined callback implementations. */
PUBLIC void *st_cb_pages_allocate(st_init_info_t *info, uint32_t *phys, int num_pages);
PUBLIC void st_cb_pages_free(st_init_info_t *info, st_alloc_pages *current_page);
PUBLIC int st_cb_state_cleanup_null(void);
PUBLIC int st_cb_state_checking_null(_magic_selement_t* selement,
_magic_sel_analyzed_t *sel_analyzed, _magic_sel_stats_t *sel_stats,
void* cb_args);
PUBLIC int st_cb_state_checking_print(_magic_selement_t* selement,
_magic_sel_analyzed_t *sel_analyzed, _magic_sel_stats_t *sel_stats,
void* cb_args);
PUBLIC int st_cb_state_checking_panic(_magic_selement_t* selement,
_magic_sel_analyzed_t *sel_analyzed, _magic_sel_stats_t *sel_stats,
void* cb_args);
PUBLIC int st_cb_transfer_sentry_default(_magic_selement_t *selement, _magic_sel_analyzed_t *sel_analyzed, _magic_sel_stats_t *sel_stats, struct st_cb_info *cb_info);
PUBLIC int st_cb_transfer_typename_default(_magic_selement_t *selement, _magic_sel_analyzed_t *sel_analyzed, _magic_sel_stats_t *sel_stats, struct st_cb_info *cb_info);
PUBLIC int st_cb_transfer_walkable(_magic_selement_t *selement, _magic_sel_analyzed_t *sel_analyzed, _magic_sel_stats_t *sel_stats, struct st_cb_info *cb_info);
PUBLIC int st_cb_transfer_ptr(_magic_selement_t *selement, _magic_sel_analyzed_t *sel_analyzed, _magic_sel_stats_t *sel_stats, struct st_cb_info *cb_info);
PUBLIC int st_cb_transfer_identity(_magic_selement_t *selement, _magic_sel_analyzed_t *sel_analyzed, _magic_sel_stats_t *sel_stats, struct st_cb_info *cb_info);
PUBLIC int st_cb_transfer_cond_identity(_magic_selement_t *selement, _magic_sel_analyzed_t *sel_analyzed, _magic_sel_stats_t *sel_stats, struct st_cb_info *cb_info);
PUBLIC int st_cb_transfer_nonptr(_magic_selement_t *selement, _magic_sel_analyzed_t *sel_analyzed, _magic_sel_stats_t *sel_stats, struct st_cb_info *cb_info);
PUBLIC int st_cb_transfer_struct(_magic_selement_t *selement, _magic_sel_analyzed_t *sel_analyzed, _magic_sel_stats_t *sel_stats, struct st_cb_info *cb_info);
PUBLIC int st_cb_transfer_selement_base(_magic_selement_t *selement, _magic_sel_analyzed_t *sel_analyzed, _magic_sel_stats_t *sel_stats, struct st_cb_info *cb_info);
PUBLIC int st_cb_transfer_selement_generic(_magic_selement_t *selement, _magic_sel_analyzed_t *sel_analyzed, _magic_sel_stats_t *sel_stats, struct st_cb_info *cb_info);
PUBLIC void st_cb_map_from_parent_array_selement_generic(_magic_selement_t *cached_selement, _magic_selement_t *local_selement, struct st_cb_info *cb_info, int is_trg_mapping);
PUBLIC void st_cb_map_child_array_selement_generic(_magic_selement_t *cached_selement, _magic_selement_t *local_selement, struct st_cb_info *cb_info, int is_trg_mapping);
PUBLIC void st_cb_map_from_parent_union_selement_generic(_magic_selement_t *cached_selement, _magic_selement_t *local_selement, struct st_cb_info *cb_info, int is_trg_mapping);
PUBLIC void st_cb_map_child_union_selement_generic(_magic_selement_t *cached_selement, _magic_selement_t *local_selement, struct st_cb_info *cb_info, int is_trg_mapping);
PUBLIC void st_cb_map_from_parent_struct_selement_generic(_magic_selement_t *cached_selement, _magic_selement_t *local_selement, struct st_cb_info *cb_info, int is_trg_mapping);
PUBLIC void st_cb_map_child_struct_selement_generic(_magic_selement_t *cached_selement, _magic_selement_t *local_selement, struct st_cb_info *cb_info, int is_trg_mapping);
PUBLIC void st_cb_map_child_primitive_selement_generic(_magic_selement_t *cached_selement, _magic_selement_t *local_selement, struct st_cb_info *cb_info, int is_trg_mapping);
PUBLIC void st_cb_map_child_ptr_selement_generic(_magic_selement_t *cached_selement, _magic_selement_t *local_selement, struct st_cb_info *cb_info, int is_trg_mapping);
PUBLIC void st_cb_map_from_parent_selement_generic(_magic_selement_t *cached_selement, _magic_selement_t *local_selement, struct st_cb_info *cb_info, int is_trg_mapping);
PUBLIC void st_cb_map_child_selement_generic(_magic_selement_t *cached_selement, _magic_selement_t *local_selement, struct st_cb_info *cb_info, int is_trg_mapping);
PUBLIC void st_cb_map_selement_generic(_magic_selement_t *cached_selement, _magic_selement_t *local_selement, struct st_cb_info *cb_info, int is_trg_mapping);
/* Macros for callbacks not defined statically. */
#define ST_CB_SELEMENT_TRANSFER_EMPTY {{0}}
/* Macros for predefined callback implementations. */
#define ST_CB_PAGES_ALLOCATE_DEFAULT st_cb_pages_allocate
#define ST_CB_PAGES_FREE_DEFAULT st_cb_pages_free
#define ST_CB_STATE_CLEANUP_DEFAULT st_cb_state_cleanup_null
#define ST_CB_STATE_CHECKING_DEFAULT st_cb_state_checking_print
#define ST_CB_SELEMENT_MAP_DEFAULT st_cb_map_selement_generic
#define ST_CB_PRINT st_cb_print
#define ST_TYPE_NAME_KEY(TYPE) ((char *) (TYPE)->ext)
#define ST_TYPE_NAME_MATCH(REGISTERED_TYPE_NAME_KEY, KEY) \
(REGISTERED_TYPE_NAME_KEY == KEY)
#define ST_TYPE_NAME_MATCH_ANY(REGISTERED_TYPE_NAME_KEYS, KEY) \
st_type_name_match_any(REGISTERED_TYPE_NAME_KEYS, KEY)
#define ST_SENTRY_NAME_MATCH(SENTRY_WILDCARD_NAME, NAME) \
(!st_strcmp_wildcard(SENTRY_WILDCARD_NAME, NAME))
#define ST_SENTRY_NAME_MATCH_ANY(SENTRY_WILDCARD_NAMES, NAME) \
st_sentry_name_match_any(SENTRY_WILDCARD_NAMES, NAME)
#define ST_DSENTRY_PARENT_NAME_MATCH(DSENTRY_WILDCARD_PARENT_NAME, PARENT_NAME)\
(!st_strcmp_wildcard(DSENTRY_WILDCARD_PARENT_NAME, PARENT_NAME))
#define ST_DSENTRY_PARENT_NAME_MATCH_ANY(DSENTRY_WILDCARD_PARENT_NAMES, \
PARENT_NAME) \
st_dsentry_parent_name_match_any(DSENTRY_WILDCARD_PARENT_NAMES, PARENT_NAME)
#define ST_CB_TYPE_TYPENAME 1
#define ST_CB_TYPE_SENTRY 2
#define ST_CB_TYPE_SELEMENT 4
#define ST_CB_NOT_PROCESSED 1000
#define ST_CB_CHECK_ONLY 0x01
#define ST_CB_PRINT_DBG 0x02
#define ST_CB_PRINT_ERR 0x04
#define ST_CB_FORCE_IXFER 0x08
#define ST_CB_DEFAULT_FLAGS (ST_CB_PRINT_DBG|ST_CB_PRINT_ERR)
#define ST_CB_FLAG(F) (cb_info->st_cb_flags & F)
#define ST_CB_DBG ST_CB_PRINT_DBG
#define ST_CB_ERR ST_CB_PRINT_ERR
#define ST_CB_PRINT_LEVEL(L) ST_CB_FLAG(L)
#define ST_CB_LEVEL_TO_STR(L) \
(L == ST_CB_DBG ? "DEBUG" : \
L == ST_CB_ERR ? "ERROR" : "???")
#endif /* ST_CALLBACK_H */

View file

@ -0,0 +1,28 @@
#undef xglue
#undef glue
#undef CALLBACK_TYPENAME
#undef CALLBACK_SETTERNAME
#undef DEFINE_CALLBACK
#undef DECLARE_CALLBACK
#define xglue(x, y) x ## y
#define glue(x, y) xglue(x, y)
#ifdef CALLBACK_FAMILY
#define CALLBACK_TYPENAME(name) glue(glue(glue(glue(glue(CALLBACK_PREFIX, _cb_), CALLBACK_FAMILY), _), name), _t)
#define CALLBACK_SETTERNAME(name) glue(glue(glue(glue(CALLBACK_PREFIX, _setcb_), CALLBACK_FAMILY), _), name)
#else
#define CALLBACK_TYPENAME(name) glue(glue(glue(CALLBACK_PREFIX, _cb_), name), _t)
#define CALLBACK_SETTERNAME(name) glue(glue(CALLBACK_PREFIX, _setcb_), name)
#endif
#define DECLARE_CALLBACK(ret_type, name, args) \
typedef ret_type(*CALLBACK_TYPENAME(name))args
#define DEFINE_DECL_CALLBACK(ret_type, name, args) \
DECLARE_CALLBACK(ret_type, name, args); \
void CALLBACK_SETTERNAME(name)(CALLBACK_TYPENAME(name) cb)
#define DEFINE_DECL_CALLBACK_CUSTOM(ret_type, name, args, setter_args) \
DECLARE_CALLBACK(ret_type, name, args); \
void CALLBACK_SETTERNAME(name)setter_args

View file

@ -0,0 +1,60 @@
#ifndef METADATA_TRANSFER_H
#define METADATA_TRANSFER_H
#include <st/state_transfer.h>
/* Metadata transfer and adjustment functions */
PRIVATE int transfer_metadata_functions(st_init_info_t *info,
struct _magic_vars_t *cached_magic_vars,
struct _magic_vars_t *remote_magic_vars,
st_counterparts_t *counterparts);
PRIVATE int transfer_metadata_dfunctions(st_init_info_t *info,
struct _magic_vars_t *cached_magic_vars,
struct _magic_vars_t *remote_magic_vars,
st_counterparts_t *counterparts);
PRIVATE int transfer_metadata_type_members(st_init_info_t *info,
struct _magic_type *type, struct _magic_vars_t *cached_magic_vars,
struct _magic_vars_t *remote_magic_vars);
PRIVATE int transfer_metadata_sentries(st_init_info_t *info,
struct _magic_vars_t *cached_magic_vars,
struct _magic_vars_t *remote_magic_vars, st_counterparts_t *counterparts,
int *max_buff_sz);
PRIVATE int transfer_metadata_sentry_members(st_init_info_t *info,
struct _magic_sentry *sentry);
PRIVATE int pair_metadata_types(st_init_info_t *info,
struct _magic_vars_t *cached_magic_vars,
st_counterparts_t *counterparts, int allow_unpaired_types);
PRIVATE int pair_metadata_functions(st_init_info_t *info,
struct _magic_vars_t *cached_magic_vars, st_counterparts_t *counterparts);
PRIVATE int pair_metadata_sentries(st_init_info_t *info,
struct _magic_vars_t *cached_magic_vars, st_counterparts_t *counterparts);
#if !ST_ASSUME_RAW_COPY_BEFORE_TRANSFER
PRIVATE int allocate_pair_metadata_dsentries(st_init_info_t *info,
struct _magic_vars_t *cached_magic_vars, st_counterparts_t *counterparts);
#else
PRIVATE int allocate_pair_metadata_dsentries_from_raw_copy(st_init_info_t *info,
struct _magic_vars_t *cached_magic_vars, st_counterparts_t *counterparts);
#endif
/* metadata transfer helper functions */
PRIVATE int md_transfer_str(st_init_info_t *info, char **str_pt);
#define MD_TRANSFER_STR(INFO, STR_PT) \
do { \
if (md_transfer_str(INFO, STR_PT)) { \
printf("%s, line %d. md_transfer_str(): ERROR transferring.\n", \
__FILE__, __LINE__); \
return EGENERIC; \
} \
} while(0)
PRIVATE int md_transfer(st_init_info_t *info, void *from, void **to, int len);
#define MD_TRANSFER(INFO, FROM, TO, LEN) \
do { \
if (md_transfer(INFO, FROM, TO, LEN)) { \
printf("%s, line %d. md_transfer(): ERROR transferring.\n", \
__FILE__, __LINE__); \
return EGENERIC; \
} \
} while(0)
#endif /* METADATA_TRANSFER_H */

View file

@ -0,0 +1,39 @@
#ifndef ST_OS_CALLBACK_H
#define ST_OS_CALLBACK_H
#include <magic_analysis.h>
/* Callback type definitions and call registration helpers. */
#define CALLBACK_PREFIX st
#define CALLBACK_FAMILY os
#include <st/cb_template.h>
DEFINE_DECL_CALLBACK(void, panic, (const char *fmt, ...));
DEFINE_DECL_CALLBACK(int, old_state_table_lookup, (void *state_info_opaque, void *vars));
DEFINE_DECL_CALLBACK(int, copy_state_region, (void *state_info_opaque, uint32_t address, size_t size, uint32_t dst_address));
DEFINE_DECL_CALLBACK(void *, alloc_contig, (size_t len, int flags, uint32_t *phys));
DEFINE_DECL_CALLBACK(int, free_contig, (void *ptr, size_t length));
DEFINE_DECL_CALLBACK(char *, debug_header, (void));
/* Default callback values. */
#define ST_CB_OS_PANIC_EMPTY NULL
#define ST_CB_OS_OLD_STATE_TABLE_LOOKUP_EMPTY NULL
#define ST_CB_OS_COPY_STATE_REGION_EMPTY NULL
#define ST_CB_OS_ALLOC_CONTIG_EMPTY NULL
#define ST_CB_OS_FREE_CONTIG_EMPTY NULL
#define ST_CB_OS_DEBUG_HEADER_EMPTY NULL
struct st_cbs_os_t {
CALLBACK_TYPENAME(panic) panic;
CALLBACK_TYPENAME(old_state_table_lookup) old_state_table_lookup;
CALLBACK_TYPENAME(copy_state_region) copy_state_region;
CALLBACK_TYPENAME(alloc_contig) alloc_contig;
CALLBACK_TYPENAME(free_contig) free_contig;
CALLBACK_TYPENAME(debug_header) debug_header;
};
/* General callback registration helper. */
PUBLIC void st_setcb_os_all(struct st_cbs_os_t *cbs);
#endif /* ST_OS_CALLBACK_H */

View file

@ -0,0 +1,34 @@
#ifndef ST_PRIVATE_H
#define ST_PRIVATE_H
#include <magic.h>
#include <magic_mem.h>
#include <magic_analysis.h>
#include <magic_asr.h>
#include <stdarg.h>
#include <stdint.h>
#include <st/os_callback.h>
#include <st/state_transfer.h>
/* Data transfer and adjustment functions */
#if !ST_ASSUME_RAW_COPY_BEFORE_TRANSFER
PRIVATE int deallocate_nonxferred_dsentries(struct _magic_dsentry *first_dsentry, st_counterparts_t *counterparts);
#endif
PRIVATE void deallocate_local_dsentry(struct _magic_dsentry *local_dsentry);
PRIVATE int allocate_local_dsentry(st_init_info_t *info, struct _magic_dsindex *local_dsindex, int num_elements, int is_type_mismatch, const union __alloc_flags *p_alloc_flags, struct _magic_dsentry** local_dsentry_ptr, struct _magic_dsentry *cached_dsentry, void *ptr);
PRIVATE int check_unpaired_sentry(st_init_info_t *info, struct _magic_sentry* cached_sentry);
PRIVATE int transfer_data_sentry(st_init_info_t *info, struct _magic_sentry* cached_sentry);
PRIVATE int transfer_data_selement(_magic_selement_t *selement, _magic_sel_analyzed_t *sel_analyzed, _magic_sel_stats_t *sel_stats, void *cb_args);
PRIVATE int lookup_trg_info(_magic_selement_t *selement, _magic_sel_analyzed_t *sel_analyzed, _magic_sel_stats_t *sel_stats, struct st_cb_info *cb_info,
_magic_selement_t *cached_trg_selement, _magic_selement_t *local_trg_selement);
PRIVATE INLINE void st_set_transfer_status(int status_flags, int status_op,
struct _magic_sentry *cached_sentry, struct _magic_function *cached_function);
PRIVATE INLINE void st_map_selement(_magic_selement_t *cached_selement, _magic_selement_t *local_selement, struct st_cb_info *cb_info, int is_trg_mapping);
/* Buffer allocation */
PRIVATE void *persistent_mmap(__MA_ARGS__ st_init_info_t *info, void *start, size_t length, int prot, int flags, int fd, off_t offset, struct _magic_dsentry *dsentry);
#endif /* ST_PRIVATE_H */

View file

@ -0,0 +1,10 @@
#ifndef ST_SPECIAL_H
#define ST_SPECIAL_H
/* Public functions for special types and regions. */
PUBLIC void st_register_typename_key(char *key);
PUBLIC void st_register_typename_keys(char **keys);
PUBLIC int st_add_special_mmapped_region(void *address, size_t size, char* name);
PUBLIC int st_del_special_mmapped_region_by_addr(void *address);
#endif /* ST_SPECIAL_H */

View file

@ -0,0 +1,362 @@
#ifndef ST_STATE_TRANSFER_H
#define ST_STATE_TRANSFER_H
#include <magic.h>
#include <magic_mem.h>
#include <magic_analysis.h>
#include <magic_asr.h>
#include <stdarg.h>
#include <stdint.h>
#ifdef __MINIX
#include <minix/com.h>
#include <minix/sef.h>
#endif
/*
* Used for debugging: Iterate the type transformations X times.
*/
#define MAGIC_ST_TYPE_TRANS_ITERATIONS 1
#include <st/os_callback.h>
#include <st/special.h>
#define ST_LU_ASR (1 << 1)
#define ST_LU_NOMMAP (1 << 2)
/*
* Type definitions. These need to be OS independent.
*/
typedef struct _st_init_info_t {
int flags;
void *init_buff_start;
void *init_buff_cleanup_start;
size_t init_buff_len;
struct st_cbs_os_t st_cbs_os;
void *info_opaque;
} st_init_info_t;
typedef struct st_alloc_pages {
int num_pages;
void *virt_addr;
uint32_t phys_addr;
struct st_alloc_pages *previous;
} st_alloc_pages;
#include <st/callback.h>
/* struct for holding a mapping between pointers */
typedef struct {
void *counterpart;
} st_ptr_mapping;
/* struct for holding arrays of local counterparts to cached variables */
typedef struct {
st_ptr_mapping *functions;
int functions_size;
st_ptr_mapping *types;
st_ptr_mapping *ptr_types;
int types_size;
st_ptr_mapping *sentries;
st_ptr_mapping *sentries_data;
int sentries_size;
} st_counterparts_t;
#define ST_STATE_CHECKING_DEFAULT_MAX_CYCLES LONG_MAX
#define ST_STATE_CHECKING_DEFAULT_MAX_VIOLATIONS 50
#define ST_SEL_ANALYZE_FLAGS (MAGIC_SEL_ANALYZE_ALL & (~MAGIC_SEL_ANALYZE_OUT_OF_BAND))
#define ST_MAX_COMPATIBLE_TYPES 32
/* Fields of _magic_vars_t that need to be zeroed out after transferring. */
#define ST_MAGIC_VARS_PTR_CLEAR_LIST \
__X(first_sodesc), __X(last_sodesc), \
__X(first_dsodesc), __X(last_dsodesc), \
__X(sentry_rl_buff), __X(sentry_rl_index), \
__X(sentry_hash_buff), __X(sentry_hash_head), \
__X(function_hash_buff), __X(function_hash_head)
/* Public utility functions. */
PUBLIC int st_strcmp_wildcard(char *with_wildcard, char *without_wildcard);
PUBLIC void st_cb_print(int level, char *msg, _magic_selement_t *selement, _magic_sel_analyzed_t *sel_analyzed, _magic_sel_stats_t *sel_stats, struct st_cb_info *cb_info);
PUBLIC void st_map_str_sentries(struct _magic_sentry **cached_sentry_ptr, struct _magic_sentry **local_sentry_ptr);
PUBLIC void st_map_sentries(struct _magic_sentry **cached_sentry_ptr, struct _magic_sentry **local_sentry_ptr);
PUBLIC void st_lookup_sentry_pair(struct _magic_sentry **cached_sentry_ptr, struct _magic_sentry **local_sentry_ptr);
PUBLIC void st_add_sentry_pair(struct _magic_sentry *cached_sentry, struct _magic_sentry *local_sentry);
PUBLIC int st_add_sentry_pair_alloc_by_dsindex(st_init_info_t *info, struct _magic_sentry *cached_sentry, struct _magic_dsindex *local_dsindex, int num_elements, const union __alloc_flags *p_alloc_flags);
PUBLIC void st_map_functions(struct _magic_function **cached_function_ptr, struct _magic_function **local_function_ptr);
PUBLIC void st_lookup_function_pair(struct _magic_function **cached_function_ptr, struct _magic_function **local_function_ptr);
PUBLIC void st_add_function_pair(struct _magic_function *cached_function, struct _magic_function *local_function);
PUBLIC int st_sentry_equals(struct _magic_sentry *cached_sentry, struct _magic_sentry *local_sentry);
PUBLIC int st_function_equals(struct _magic_function *cached_function, struct _magic_function *local_function);
PUBLIC void st_print_sentry_diff(st_init_info_t *info, struct _magic_sentry *cached_sentry, struct _magic_sentry *local_sentry, int raw_diff, int print_changed);
PUBLIC void st_print_function_diff(st_init_info_t *info, struct _magic_function *cached_function, struct _magic_function *local_function, int raw_diff, int print_changed);
PUBLIC void st_cb_selement_type_cast(const struct _magic_type* new_selement_type, const struct _magic_type* new_local_selement_type, _magic_selement_t *selement, _magic_sel_analyzed_t *sel_analyzed, _magic_sel_stats_t *sel_stats, struct st_cb_info *cb_info);
PUBLIC void st_map_local_selement_from_child_num(_magic_selement_t *local_selement, struct st_cb_info *cb_info, int child_num);
/* Stack refs save/restore. */
PUBLIC void st_stack_refs_save_restore(char *stack_buff, int is_save);
#define st_stack_refs_save(B) st_stack_refs_save_restore(B,1)
#define st_stack_refs_restore(B) st_stack_refs_save_restore(B,0)
#define ST_STACK_REFS_BUFF_SIZE (sizeof(struct st_stack_refs_buff))
/*
* The stack pointers to the environment and arguments differ from MINIX
* to Linux.
*/
#if defined(__MINIX)
#define ST_STACK_REFS_INT_NUM 3
#define ST_STACK_REFS_INT_LIST \
__X(environ), __X(env_argv), __X(env_argc)
#define ST_STACK_REFS_CUSTOM_NUM 0
#define ST_STACK_REFS_CUSTOM_LIST
#else
/*
* TODO: Complete the list of Linux stack pointer aliases.
*/
#define ST_STACK_REFS_INT_NUM 3
#define ST_STACK_REFS_INT_LIST __X(_environ), __X(__progname), \
__X(__progname_full)
#ifndef __USE_GNU
extern char *program_invocation_name, *program_invocation_short_name;
extern char **environ;
#endif
#define ST_STACK_REFS_CUSTOM_NUM 4
#define ST_STACK_REFS_CUSTOM_LIST __X(environ), __X(__environ), \
__X(program_invocation_name), __X(program_invocation_short_name)
#endif
#define ST_STACK_REFS_NUM (ST_STACK_REFS_INT_NUM + ST_STACK_REFS_CUSTOM_NUM)
struct st_stack_refs_buff {
struct _magic_dsentry *first_stack_dsentry;
struct _magic_dsentry *last_stack_dsentry;
struct _magic_obdsentry first_stack_obdsentry_buff;
void* stack_range[2];
int stack_int_refs[ST_STACK_REFS_NUM];
};
/* Public functions for metadata transfer. */
PUBLIC int st_transfer_metadata_types(st_init_info_t *info,
struct _magic_vars_t *cached_magic_vars,
struct _magic_vars_t *remote_magic_vars,
st_counterparts_t *counterparts);
PUBLIC int st_transfer_metadata_dsentries(st_init_info_t *info,
struct _magic_vars_t *cached_magic_vars,
struct _magic_vars_t *remote_magic_vars, st_counterparts_t *counterparts,
int *max_buff_sz, int *dsentries_num);
/* Public functions for state transfer. */
PUBLIC int st_state_transfer(st_init_info_t *info);
PUBLIC void st_msync_all_shm_dsentries(void);
PUBLIC int st_init(st_init_info_t *info);
PUBLIC void st_set_status_defaults(st_init_info_t *info);
PUBLIC int st_data_transfer(st_init_info_t *info);
PUBLIC void st_cleanup(st_init_info_t *info);
PUBLIC void st_set_unpaired_types_ratios(float unpaired_types_ratio, float unpaired_struct_types_ratio);
PUBLIC struct _magic_sentry* st_cached_to_remote_sentry(st_init_info_t *info, struct _magic_sentry *cached_sentry);
PUBLIC void st_print_sentries_diff(st_init_info_t *info, int raw_diff, int print_changed);
PUBLIC void st_print_dsentries_diff(st_init_info_t *info, int raw_diff, int print_changed);
PUBLIC void st_print_functions_diff(st_init_info_t *info, int raw_diff, int print_changed);
PUBLIC void st_print_state_diff(st_init_info_t *info, int raw_diff, int print_changed);
PUBLIC void st_set_status_by_state_flags(int status_flags, int status_op, int match_state_flags, int skip_state_flags);
PUBLIC int st_set_status_by_function_ids(int status_flags, int status_op, unsigned long *ids);
PUBLIC int st_set_status_by_sentry_ids(int status_flags, int status_op, unsigned long *ids);
PUBLIC int st_set_status_by_names(int status_flags, int status_op, char **parent_names, char **names, _magic_id_t *dsentry_site_ids);
PUBLIC int st_set_status_by_local_addrs(int status_flags, int status_op, void **addrs);
PUBLIC void st_set_status_by_sentry(int status_flags, int status_op, void *cached_sentry);
PUBLIC void st_set_status_by_function(int status_flags, int status_op, void *cached_function);
PUBLIC int st_set_status_by_function_id(int status_flags, int status_op, unsigned long id);
PUBLIC int st_set_status_by_sentry_id(int status_flags, int status_op, unsigned long id);
PUBLIC int st_set_status_by_name(int status_flags, int status_op, char *parent_name, char *name, _magic_id_t dsentry_site_id);
PUBLIC int st_set_status_by_local_addr(int status_flags, int status_op, void *addr);
PUBLIC int st_pair_by_function_ids(unsigned long *cached_ids, unsigned long *local_ids, int status_flags, int status_op);
PUBLIC int st_pair_by_sentry_ids(unsigned long *cached_ids, unsigned long *local_ids, int status_flags, int status_op);
PUBLIC int st_pair_by_names(char **cached_parent_names, char **cached_names, char **local_parent_names, char **local_names, _magic_id_t *dsentry_site_ids, int status_flags, int status_op);
PUBLIC void st_pair_by_sentry(void *cached_sentry, void *local_sentry, int status_flags, int status_op);
PUBLIC void st_pair_by_function(void *cached_function, void* local_function, int status_flags, int status_op);
PUBLIC int st_pair_alloc_by_dsindex(st_init_info_t *info, void *cached_sentry, void *local_dsindex, int num_elements, const union __alloc_flags *p_alloc_flags, int status_flags, int status_op);
PUBLIC int st_pair_by_function_id(unsigned long cached_id, unsigned long local_id, int status_flags, int status_op);
PUBLIC int st_pair_by_sentry_id(unsigned long cached_id, unsigned long local_id, int status_flags, int status_op);
PUBLIC int st_pair_by_name(char *cached_parent_name, char *cached_name, char *local_parent_name, char *local_name, _magic_id_t dsentry_site_id, int status_flags, int status_op);
PUBLIC int st_pair_by_alloc_name(st_init_info_t *info, char *cached_parent_name, char *cached_name, _magic_id_t cached_dsentry_site_id, char *local_parent_name, char *local_name, _magic_id_t local_dsentry_site_id, int num_elements, const union __alloc_flags *p_alloc_flags, int status_flags, int status_op);
PUBLIC int st_pair_by_alloc_name_policies(st_init_info_t *info, char *cached_parent_name, char *cached_name, _magic_id_t cached_dsentry_site_id, char *local_parent_name, char *local_name, _magic_id_t local_dsentry_site_id, int num_elements, const union __alloc_flags *p_alloc_flags, int alloc_policies, int status_flags, int status_op);
/* Public functions for state checking. */
PUBLIC int st_do_state_cleanup(void);
PUBLIC int st_do_state_checking(void);
PUBLIC int st_state_checking_before_receive_is_enabled(void);
PUBLIC int st_state_checking_before_receive_set_enabled(int enabled, int max_cycles, int max_violations);
/* State transfer status flags and operations. */
#define ST_NEEDS_TRANSFER 0x01
#define ST_TRANSFER_DONE 0x02
#define ST_ON_PTRXFER_CASCADE 0x04
#define ST_ON_PTRXFER_SET_NULL 0x08
#define ST_ON_PTRXFER_SET_DEFAULT 0x10
#define ST_ON_PTRXFER_SKIP 0x20
#define ST_OP_NONE 0
#define ST_OP_ADD 1
#define ST_OP_DEL 2
#define ST_OP_SET 3
#define ST_OP_CLEAR 4
/* State transfer policies. */
#define ST_DEFAULT_TRANSFER_NONE 0x00000001
#define ST_DEFAULT_ALLOC_CASCADE_XFER 0x00000002
#define ST_DEFAULT_SKIP_STACK 0x00000004
#define ST_DEFAULT_SKIP_LIB_STATE 0x00000008
#define ST_TRANSFER_DIRTY_ONLY 0x00000010
#define ST_IXFER_UNCAUGHT_UNIONS 0x00000020
#define ST_REPORT_UNCAUGHT_UNIONS 0x00000040
#define ST_REPORT_NONXFERRED_ALLOCS 0x00000080
#define ST_REPORT_NONXFERRED_UNPAIRED_ALLOCS 0x00000100
#define ST_REPORT_UNPAIRED_SENTRIES 0x00000200
#define ST_REPORT_UNPAIRED_DSENTRIES 0x00000400
#define ST_REPORT_UNPAIRED_STRINGS 0x00000800
#define ST_REPORT_UNPAIRED_SELEMENTS 0x00001000
#define ST_MAP_NAMED_STRINGS_BY_NAME 0x00002000
#define ST_MAP_NAMED_STRINGS_BY_CONTENT 0x00004000
#define ST_MAP_STRINGS_BY_CONTENT 0x00008000
#define ST_ON_ALLOC_UNPAIR_ERROR 0x00010000
#define ST_ON_ALLOC_UNPAIR_DEALLOCATE 0x00020000
#define ST_ON_ALLOC_UNPAIR_IGNORE 0x00040000
#define ST_DEFAULT_MAP_GUARD_PTRS_TO_ARRAY_END 0x00080000
#define ST_DEFAULT_MAP_GUARD_PTRS_TO_STR_END 0x00100000
#define ST_REPORT_PRECISION_LOSS 0x00200000
#define ST_REPORT_SIGN_CHANGE 0x00400000
#define ST_REPORT_SMALLER_ARRAYS 0x00800000
#define ST_REPORT_LARGER_ARRAYS 0x01000000
#define ST_REPORT_SMALLER_STRINGS 0x02000000
#define ST_REPORT_LARGER_STRINGS 0x04000000
#define ST_REPORT_UNPAIRED_ALL \
(ST_REPORT_UNPAIRED_SENTRIES | ST_REPORT_UNPAIRED_DSENTRIES | \
ST_REPORT_UNPAIRED_STRINGS | ST_REPORT_UNPAIRED_SELEMENTS)
#define ST_MAP_STRINGS_DEFAULT \
(ST_MAP_NAMED_STRINGS_BY_NAME | ST_MAP_STRINGS_BY_CONTENT)
#define ST_ON_ALLOC_UNPAIR_DEFAULT (ST_ON_ALLOC_UNPAIR_ERROR)
#define ST_ON_ALLOC_UNPAIR_MASK \
(ST_ON_ALLOC_UNPAIR_ERROR | ST_ON_ALLOC_UNPAIR_DEALLOCATE | \
ST_ON_ALLOC_UNPAIR_IGNORE)
#define ST_TYPE_TRANSFORM_DEFAULT \
(ST_DEFAULT_MAP_GUARD_PTRS_TO_STR_END | ST_REPORT_PRECISION_LOSS | \
ST_REPORT_SIGN_CHANGE | ST_REPORT_SMALLER_ARRAYS | ST_REPORT_LARGER_ARRAYS)
#define ST_POLICIES_DEFAULT_TRANSFER_ALL \
(ST_DEFAULT_ALLOC_CASCADE_XFER | ST_DEFAULT_SKIP_STACK | \
ST_DEFAULT_SKIP_LIB_STATE | ST_REPORT_NONXFERRED_ALLOCS | \
ST_REPORT_NONXFERRED_UNPAIRED_ALLOCS | ST_MAP_STRINGS_DEFAULT | \
ST_ON_ALLOC_UNPAIR_DEFAULT | ST_TYPE_TRANSFORM_DEFAULT)
#define ST_POLICIES_DEFAULT_TRANSFER_NONE \
(ST_DEFAULT_TRANSFER_NONE | ST_DEFAULT_SKIP_STACK | \
ST_DEFAULT_SKIP_LIB_STATE | ST_REPORT_NONXFERRED_ALLOCS | \
ST_REPORT_NONXFERRED_UNPAIRED_ALLOCS | ST_MAP_STRINGS_DEFAULT | \
ST_ON_ALLOC_UNPAIR_DEFAULT | ST_TYPE_TRANSFORM_DEFAULT)
#define ST_POLICIES_DEFAULT_TRANSFER_ASR \
(ST_POLICIES_DEFAULT_TRANSFER_ALL | ST_REPORT_UNPAIRED_ALL)
#define ST_POLICIES_DEFAULT ST_POLICIES_DEFAULT_TRANSFER_ALL
/* Macros for predefined state transfer names. */
#define ADJUST_POINTER(local, remote, pointer) ( (local) + ((pointer) - (remote)) )
#define ST_STR_BUFF_SIZE (MAGIC_MAX_NAME_LEN > MAGIC_MAX_TYPE_STR_LEN ? MAGIC_MAX_NAME_LEN : MAGIC_MAX_TYPE_STR_LEN)
#define USE_PRE_ALLOCATED_BUFFER(INFO) ((INFO)->init_buff_start)
#define EXEC_WITH_MAGIC_VARS(CMD, MAGIC_VARS) \
do { \
struct _magic_vars_t *__saved_vars = _magic_vars; \
_magic_vars = (MAGIC_VARS); \
CMD; \
_magic_vars = __saved_vars; \
} while(0);
#define MAX_NUM_TYPENAMES 20
#define CHECK_SENTITY_PAIRS 1
#define ST_DEBUG_LEVEL 1
#define ST_DEBUG_DATA_TRANSFER 0
#define CHECK_ASR 0
#define ST_ALLOW_RAW_UNPAIRED_TYPES 1
#define ST_UNPAIRED_TYPES_RATIO_DEFAULT 0
#define ST_UNPAIRED_STRUCT_TYPES_RATIO_DEFAULT 0
#define FORCE_SOME_UNPAIRED_TYPES 1
#define ST_TRANSFER_IDENTITY_FOR_NO_INNER_PTRS 1
#ifndef ST_ASSUME_RAW_COPY_BEFORE_TRANSFER
#define ST_ASSUME_RAW_COPY_BEFORE_TRANSFER 0
#endif
#if defined(__MINIX)
#define ST_IS_UNPAIRABLE_TYPE_OS(T) (sef_self_endpoint != VM_PROC_NR || strcmp((T)->name, "void"))
#else
#define ST_IS_UNPAIRABLE_TYPE_OS(T) 1
#endif
#if ST_ALLOW_RAW_UNPAIRED_TYPES
#define ST_IS_UNPAIRABLE_TYPE(T) (ST_IS_UNPAIRABLE_TYPE_OS(T) && (T)->type_id != MAGIC_TYPE_UNION)
#else
#define ST_IS_UNPAIRABLE_TYPE(T) \
(ST_IS_UNPAIRABLE_TYPE_OS(T) \
&& !MAGIC_TYPE_IS_RAW_ARRAY(T) \
&& !((T)->type_id == MAGIC_TYPE_ARRAY && !strcmp((T)->contained_types[0]->type_str, "i8")) \
&& !(T)->ext)
#endif
#define ST_IS_UNPAIRABLE_STRUCT_TYPE(T) \
((T)->type_id == MAGIC_TYPE_STRUCT)
#define ST_FLAGS_PRINT(E) printf(", sf_flags(NDndsc)=%d%d%d%d%d%d", \
MAGIC_STATE_EXTF_FLAG(E,ST_NEEDS_TRANSFER), MAGIC_STATE_EXTF_FLAG(E,ST_TRANSFER_DONE), \
MAGIC_STATE_EXTF_FLAG(E,ST_ON_PTRXFER_SET_NULL), MAGIC_STATE_EXTF_FLAG(E,ST_ON_PTRXFER_SET_DEFAULT), \
MAGIC_STATE_EXTF_FLAG(E,ST_ON_PTRXFER_SKIP), MAGIC_STATE_EXTF_FLAG(E,ST_ON_PTRXFER_CASCADE));
#define ST_SENTRY_PRINT(E,T) do { MAGIC_SENTRY_PRINT(E, T); ST_FLAGS_PRINT(E); if (MAGIC_SENTRY_IS_STRING(E)) printf(", string=\"%s\"", (ST_SENTRY_IS_CACHED(E) ? st_lookup_str_local_data(E) : (char*)(E)->address)); } while(0)
#define ST_DSENTRY_PRINT(E,T) do { MAGIC_DSENTRY_PRINT(E, T); ST_FLAGS_PRINT(&E->sentry); } while(0)
#define ST_FUNCTION_PRINT(E,T) do { MAGIC_FUNCTION_PRINT(E, T); ST_FLAGS_PRINT(E); } while(0)
#define ST_CHECK_INIT() assert(st_init_done && "st_init() should be called first!")
#define ST_SENTRY_IS_CACHED(E) (MAGIC_SENTRY_ID(E) >= 1 && MAGIC_SENTRY_ID(E) <= st_cached_magic_vars.sentries_num && st_cached_magic_vars.sentries[MAGIC_SENTRY_ID(E)-1].address == (E)->address)
#define ST_GET_CACHED_COUNTERPART(CE,T,CT,LE) do { \
int i = (CE)->id - 1; \
assert(i >= 0 && i < st_counterparts.T##_size); \
LE = st_counterparts.CT[i].counterpart; \
} while(0)
#define ST_SET_CACHED_COUNTERPART(CE,T,CT,LE) do { \
int i = (CE)->id - 1; \
assert(i >= 0 && i < st_counterparts.T##_size); \
st_counterparts.CT[i].counterpart = LE; \
} while(0)
#define ST_HAS_CACHED_COUNTERPART(CE,CT) (st_counterparts.CT[(CE)->id - 1].counterpart != NULL)
#define ST_TYPE_IS_STATIC_CACHED_COUNTERPART(CE,LE) (((CE) >= &st_cached_magic_vars.types[0] && (CE) < &st_cached_magic_vars.types[st_cached_magic_vars.types_num]) && st_counterparts.types[(CE)->id - 1].counterpart == (LE))
#define ST_TYPE_IS_DYNAMIC_CACHED_COUNTERPART(CE,LE) (MAGIC_TYPE_FLAG(CE,MAGIC_TYPE_DYNAMIC) && (CE)->type_id == MAGIC_TYPE_ARRAY && (LE)->type_id == MAGIC_TYPE_ARRAY && (CE)->num_child_types == (LE)->num_child_types && ST_TYPE_IS_STATIC_CACHED_COUNTERPART((CE)->contained_types[0], (LE)->contained_types[0]))
#define ST_TYPE_IS_CACHED_COUNTERPART(CE,LE) (ST_TYPE_IS_STATIC_CACHED_COUNTERPART(CE,LE) || ST_TYPE_IS_DYNAMIC_CACHED_COUNTERPART(CE,LE))
#define ST_PTR_TYPE_IS_STATIC_CACHED_COUNTERPART(CE,LE) (((CE) >= &st_cached_magic_vars.types[0] && (CE) < &st_cached_magic_vars.types[st_cached_magic_vars.types_num]) && st_counterparts.ptr_types[(CE)->id - 1].counterpart == (LE))
#define ST_PTR_TYPE_IS_DYNAMIC_CACHED_COUNTERPART(CE,LE) (MAGIC_TYPE_FLAG(CE,MAGIC_TYPE_DYNAMIC) && (CE)->type_id == MAGIC_TYPE_ARRAY && (LE)->type_id == MAGIC_TYPE_ARRAY && (CE)->num_child_types == (LE)->num_child_types && ST_PTR_TYPE_IS_STATIC_CACHED_COUNTERPART((CE)->contained_types[0], (LE)->contained_types[0]))
#define ST_PTR_TYPE_IS_CACHED_COUNTERPART(CE,LE) (ST_PTR_TYPE_IS_STATIC_CACHED_COUNTERPART(CE,LE) || ST_PTR_TYPE_IS_DYNAMIC_CACHED_COUNTERPART(CE,LE))
/* Buffer allocation */
PUBLIC void *st_cb_pages_allocate(st_init_info_t *info, uint32_t *phys, int num_pages);
PUBLIC void st_cb_pages_free(st_init_info_t *info, st_alloc_pages *current_page);
PUBLIC void *st_buff_allocate(st_init_info_t *info, size_t size);
PUBLIC void st_buff_cleanup(st_init_info_t *info);
#endif /* ST_STATE_TRANSFER_H */

View file

@ -0,0 +1,54 @@
#ifndef ST_TYPEDEFS_H
#define ST_TYPEDEFS_H
#include <stdint.h>
/* Typedefs for predefined state transfer names. */
#define ST_DECLARE_STD_PTR_TYPEDEFS(PREFIX) \
typedef void* PREFIX ## void_ptr_t; \
typedef char* PREFIX ## char_ptr_t; \
typedef short* PREFIX ## short_ptr_t; \
typedef int* PREFIX ## int_ptr_t; \
typedef long* PREFIX ## long_ptr_t; \
typedef unsigned char* PREFIX ## uchar_ptr_t; \
typedef unsigned short* PREFIX ## ushort_ptr_t; \
typedef unsigned int* PREFIX ## uint_ptr_t; \
typedef unsigned long* PREFIX ## ulong_ptr_t; \
typedef float* PREFIX ## float_ptr_t; \
typedef double* PREFIX ## double_ptr_t; \
typedef uint8_t* PREFIX ## u8_ptr_t; \
typedef uint16_t* PREFIX ## u16_ptr_t; \
typedef uint32_t* PREFIX ## u32_ptr_t; \
typedef uint64_t* PREFIX ## u64_ptr_t; \
typedef int8_t* PREFIX ## i8_ptr_t; \
typedef int16_t* PREFIX ## i16_ptr_t; \
typedef int32_t* PREFIX ## i32_ptr_t
#define ST_DECLARE_STD_PTRINT_TYPEDEFS(PREFIX) \
typedef uint32_t PREFIX ## u32_t; \
typedef int PREFIX ## int_t; \
typedef long PREFIX ## long_t; \
typedef unsigned int PREFIX ## uint_t; \
typedef unsigned long PREFIX ## ulong_t
#define ST_TYPENAME_NO_TRANSFER_NAMES "noxfer_*", "pthread_mutex_t", "siginfo_t", "epoll_data_t", "YYSTYPE"
ST_DECLARE_STD_PTR_TYPEDEFS(noxfer_);
#define ST_TYPENAME_IDENTITY_TRANSFER_NAMES "ixfer_*"
ST_DECLARE_STD_PTR_TYPEDEFS(ixfer_);
#define ST_TYPENAME_CIDENTITY_TRANSFER_NAMES "cixfer_*"
ST_DECLARE_STD_PTR_TYPEDEFS(cixfer_);
#define ST_TYPENAME_PTR_TRANSFER_NAMES "pxfer_*"
ST_DECLARE_STD_PTRINT_TYPEDEFS(pxfer_);
#define ST_TYPENAME_STRUCT_TRANSFER_NAMES "sxfer_*"
#ifdef __MINIX
#define ST_SENTRYNAME_NO_TRANSFER_NAMES "noxfer_*", "sef_*", "st_*", "_brksize", "etext"
#else
#define ST_SENTRYNAME_NO_TRANSFER_NAMES "noxfer_*", "st_*", "_brksize", "etext", "allocatedDescs*", "ep.*" /* nginx specific */
#define ST_DSENTRYLIB_NO_TRANSFER_NAMES "*/libst.so", "*/libcommon.so", "*/libtaskctl.so"
#endif
#define ST_SENTRYNAME_IDENTITY_TRANSFER_NAMES "ixfer_*"
#define ST_SENTRYNAME_CIDENTITY_TRANSFER_NAMES "cixfer_*"
#define ST_SENTRYNAME_PTR_TRANSFER_NAMES "pxfer_*"
#endif /* ST_TYPEDEFS_H */

View file

@ -0,0 +1,80 @@
# THIS FILE IS AN EDITED VERSION OF A FILE GENERATED BY LLVM-APPS
# XXX EDIT AT LEAST THIS PART
_MINIX_ARCH=i386
_MINIX_ROOT=/home/myname/path/to/minix
_MINIX_TOOLS_DIR=/home/myname/path/to/obj.i386/tooldir.Linux-myversion
###########################################################
# llvm-apps settings for Minix binary instrumentation
###########################################################
_MINIX_LLVM_DIR=$(_MINIX_ROOT)/minix/llvm
_MINIX_OBJ_DIR=$(_MINIX_ROOT)/../obj.$(_MINIX_ARCH)
_MINIX_OBJ_LLVM_DIR=$(_MINIX_ROOT)/../obj_llvm.$(_MINIX_ARCH)
_MINIX_SYSROOT=$(_MINIX_OBJ_DIR)/destdir.$(_MINIX_ARCH)
###########################################################
# Main configuration (override in common.overrides.*inc to match your settings)
###########################################################
HAVE_LLVM=1
LLVMBASEDIR=$(_MINIX_LLVM_DIR)
LLVMPREFIX=$(_MINIX_OBJ_LLVM_DIR)/Release+Asserts
LLVM_TWOSTEP_LINKING_WITH_GOLD=0
LLVM_TWOSTEP_LINKING_WITH_GOLD_USES_LLC=0
LLVM_OUTPUT_TRG_DIR=
LLVM_CAP_ALL=CAP_AUDIT_CONTROL,CAP_AUDIT_WRITE,CAP_CHOWN,CAP_DAC_OVERRIDE,CAP_DAC_READ_SEARCH,CAP_FOWNER,CAP_FSETID,CAP_IPC_LOCK,CAP_IPC_OWNER,CAP_KILL,CAP_LEASE,CAP_LINUX_IMMUTABLE,CAP_MAC_ADMIN,CAP_MAC_OVERRIDE,CAP_MKNOD,CAP_NET_ADMIN,CAP_NET_BIND_SERVICE,CAP_NET_BROADCAST,CAP_NET_RAW,CAP_SETGID,CAP_SETFCAP,CAP_SETPCAP,CAP_SETUID,CAP_SYS_ADMIN,CAP_SYS_BOOT,CAP_SYS_CHROOT,CAP_SYS_MODULE,CAP_SYS_NICE,CAP_SYS_PACCT,CAP_SYS_PTRACE,CAP_SYS_RAWIO,CAP_SYS_RESOURCE,CAP_SYS_TIME,CAP_SYS_TTY_CONFIG,CAP_SYSLOG,CAP_SYS_MODULE
###########################################################
###########################################################
# Common variables
###########################################################
ABS_ROOT=$(LLVMBASEDIR)
PERF_PATH=/usr/bin/perf
LLVMDIR=$(ABS_ROOT)
LLVMINC=$(LLVMDIR)/include
LLVMLIB=$(LLVMDIR)/lib
INSTALL_DIR=$(ABS_ROOT)/bin
LLVMSECTIONIFY_SO=$(INSTALL_DIR)/sectionify.so
LLVMAOPIFY_SO=$(INSTALL_DIR)/aopify.so
LLVMMAGIC_ST_IN_LIBST=0
CC=clang
CXX=clang++
CFLAGS=-fasynchronous-unwind-tables -g -I$(LLVMINC)
###########################################################
###########################################################
# LLVM gold plugin support (see README.llvm for details)
#
# Note: LLVMGOLD_PREFIX below should point to a valid LLVM 2.9 (+LLVMGOLD_CC=llvm-gcc) [or LLVM >= 3.0 (+LLVMGOLD_CC=clang)] installation with gold plugin support (binutils >=2.22)
###########################################################
LLVMGOLD_HAS_LTO_DISABLE_OPT=1
LLVMGOLD_PREFIX=$(LLVMPREFIX)
LLVMGOLD_PLUGIN=$(_MINIX_LLVM_DIR)/bin/LLVMgold.so
LLVMGOLD_CC=$(_MINIX_TOOLS_DIR)/bin/i586-elf32-minix-clang -flto
LLVMGOLD_CXX=$(_MINIX_TOOLS_DIR)/bin/i586-elf32-minix-clang++ -flto
LLVMGOLD_AR=ar --plugin $(LLVMGOLD_PLUGIN)
LLVMGOLD_RANLIB=$(LLVMGOLD_AR) -s
LLVMGOLD_AR_FLAGS=--plugin $(LLVMGOLD_PLUGIN) -cru
LLVMGOLD_CFLAGS=-fasynchronous-unwind-tables -g -D_MINIX -D_POSIX_SOURCE -D_SYSTEM -Wno-long-long --sysroot=$(_MINIX_SYSROOT) -I$(LLVMINC) -I$(_MINIX_OBJ_LLVM_DIR)/include/llvm -I$(_MINIX_ROOT)/external/bsd/llvm/dist/llvm/include -I$(_MINIX_OBJ_LLVM_DIR)/include -I$(_MINIX_SYSROOT)/usr/include
LLVMGOLD_LINK=-Wl,--plugin -Wl,$(LLVMGOLD_PLUGIN)
LLVMGOLD_LINKFLAGS=-Wl,-plugin-opt=-disable-fp-elim -Wl,-plugin-opt=-disable-inlining -Wl,-plugin-opt=also-emit-llvm
LLVMGOLD_LINKCOMMONFLAGS=-L$(_MINIX_OBJ_DIR)/destdir.$(_MINIX_ARCH)/usr/lib -rdynamic
LLVMGOLD_LIBS=
LLVMGOLD_LDFLAGS=$(LLVMGOLD_LINK) $(LLVMGOLD_LINKFLAGS) $(LLVMGOLD_LINKCOMMONFLAGS) $(LLVMGOLD_LIBS)
LLVMGOLD_OPTFLAGS=-disable-internalize -mem2reg -std-compile-opts
LLVMGOLD_LLCFLAGS=--disable-fp-elim
LLVMGOLD_TSLINK_PARTIALFLAGS=-Wl,-r -nostdlib
LLVMGOLD_TSLINK_FINALFLAGS=-B$(LLVMGOLD_PREFIX)/bfd_bin
LLVMGOLD_OPTIMIZED=1
###########################################################
BUILD_LLVMAPPS_FOR_MINIX=yes
GEN_GOLD_PLUGIN=yes
REBUILD_MINIX=yes
ARCH_NAME=x86
ARCH_BITS=32

View file

@ -0,0 +1,29 @@
#Makefile for creating the magic static library
MODULE = magic
OBJS = magic.o magic_analysis.o magic_asr.o magic_eval_lib.o magic_eval.o magic_mem.o magic_range.o magic_splay_tree.o magic_sentry.o magic_selement.o
HEADERS = $(wildcard $(LLVMINC)/*.h) $(wildcard $(LLVMINC)/st/*.h)
USE_SECTIONIFY=YES
SECTIONIFY_NO_OVERRIDE=yes
SECTIONIFY_DATA_SECTION_MAP=^_____magic_instr_.*/magic_instr_data,.*/magic_data
SECTIONIFY_FUNCTION_SECTION_MAP=.*/magic_functions
OBJS += minix/magic_util.o minix/magic_ds.o
HEADERS += $(wildcard minix/*.h)
OBJS+=magic_st.bcc
include Makefile.inc
CFLAGS += -I$(_MINIX_ROOT)/minix/servers
# XXX: there is essential code in assert() statements, so force asserts on..
CFLAGS += -UNDEBUG
magic_st.bcc:
make -f Makefile.magic_st $@
magic_st.o:
make -f Makefile.magic_st $@

View file

@ -0,0 +1,57 @@
include ../Makefile.settings
MODULE_NAME=$(MODULE).bcc
CFLAGS += $(CXXFLAGS) -Wall -g -Wno-long-long
CFLAGS += -D__MINIX -D_MINIX_SYSTEM
LLVM_VERSION=$(shell $(LLVMPREFIX)/bin/llvm-config --version | cut -d"." -f1,2 | sed "s/[^0-9]//g")
HAVE_NOCONSTRUCTOR_PRIORITY = $(shell expr $(LLVM_VERSION) \>= 30)
ifeq ($(HAVE_NOCONSTRUCTOR_PRIORITY),0)
CFLAGS += -DHAVE_NOCONSTRUCTOR_PRIORITY=1
endif
ifeq ($(USE_SECTIONIFY),YES)
LOPT_FLAGS+=-load=$(LLVMSECTIONIFY_SO) -sectionify -sectionify-no-override -sectionify-data-section-map=$(SECTIONIFY_DATA_SECTION_MAP) -sectionify-function-section-map=$(SECTIONIFY_FUNCTION_SECTION_MAP)
ifeq (SECTIONIFY_NO_OVERRIDE,YES)
LOPT_FLAGS+=-sectionify-no-override
endif
endif
V?=0
ifneq ($V,0)
QUIET=
ECHO:=@\#
QMAKE=VERBOSE=1 make
else
QUIET= @
ECHO= echo
QMAKE=make -s
endif
$(MODULE_NAME): $(OBJS) $(HEADERS) $(COMMON_BCCS)
$(QUIET) $(ECHO) " [GOLD_LINK] $@.o"
$(QUIET) $(LLVMGOLD_CC) $(CFLAGS) $(LLVMGOLD_CFLAGS) $(LLVMGOLD_LDFLAGS) -shared -o $@.o $(OBJS) $(COMMON_BCCS)
$(QUIET) $(ECHO) " [OPT] $@"
$(QUIET) $(LLVMPREFIX)/bin/opt $(LOPT_FLAGS) -o $@ $@.o.bc
all: $(MODULE_NAME)
%.o: %.c $(HEADERS)
$(QUIET) $(ECHO) " [GOLD_CC] $<"
$(QUIET) $(LLVMGOLD_CC) $(CFLAGS) $(LLVMGOLD_CFLAGS) $(INCLUDES) $(INCLUDES_$<) -c -o $@ $<
install: $(INSTALL_DIR)/$(MODULE_NAME)
$(INSTALL_DIR)/$(MODULE_NAME): $(MODULE_NAME)
install -c -D -m 744 $? $@
clean: $(EXTRA_CLEAN)
$(QUIET) $(ECHO) " [RM] *.BCC *.bcc *.bc *.BCL *.BCL.sh *.bcl $(OBJS) *.s $(COMMON_BCCS)"
$(QUIET) rm -f *.BCC *.bcc *.bc *.BCL *.BCL.sh *.bcl *.o $(OBJS) *.s $(COMMON_BCCS)
distclean: clean
$(QUIET) $(ECHO) " [RM] $(INSTALL_DIR)/$(MODULE_NAME)"
$(QUIET) rm -f $(INSTALL_DIR)/$(MODULE_NAME)

View file

@ -0,0 +1,11 @@
MODULE = magic_st
OBJS = magic_st.o
USE_SECTIONIFY=YES
SECTIONIFY_DATA_SECTION_MAP=.*/magic_data_st
SECTIONIFY_FUNCTION_SECTION_MAP=.*/magic_functions_st
include Makefile.inc

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,129 @@
#include <unistd.h>
#include <stdlib.h>
#include <time.h>
#include <magic_def.h>
#include <magic_mem.h>
#include <magic_asr.h>
#include <magic.h>
#ifdef __MINIX
static unsigned long magic_rand_next;
static void magic_srand(unsigned int seed)
{
magic_rand_next = (unsigned long) seed;
}
static int magic_rand()
{
magic_rand_next = magic_rand_next * 1103515245 + 12345;
return (int)(magic_rand_next % ((unsigned long)RAND_MAX + 1));
}
static int magic_rand_seed()
{
int x;
return (int)&x + (int)&magic_rand_seed;
}
#else
#define magic_srand srand
#define magic_rand rand
#define magic_rand_seed() time(0)
#endif
#define MINIMUM_PADDING 1
PUBLIC int magic_asr_get_padding_size(int region) {
int padding = 0;
switch(region) {
case MAGIC_STATE_HEAP | MAGIC_ASR_FLAG_INIT:
if(_magic_asr_heap_max_offset){
padding = (magic_rand() % _magic_asr_heap_max_offset) + MINIMUM_PADDING;
}
break;
case MAGIC_STATE_HEAP:
if(_magic_asr_heap_max_padding){
padding = (magic_rand() % _magic_asr_heap_max_padding) + MINIMUM_PADDING;
}
break;
case MAGIC_STATE_MAP | MAGIC_ASR_FLAG_INIT:
if(_magic_asr_map_max_offset_pages){
padding = ((magic_rand() % _magic_asr_map_max_offset_pages) + MINIMUM_PADDING) * magic_get_sys_pagesize();
}
break;
case MAGIC_STATE_MAP:
if(_magic_asr_map_max_padding_pages){
padding = ((magic_rand() % _magic_asr_map_max_padding_pages) + MINIMUM_PADDING) * magic_get_sys_pagesize();
}
break;
default:
padding = -1;
}
return padding;
}
PUBLIC void magic_asr_permute_dsentries(struct _magic_dsentry **first_dsentry_ptr){
struct _magic_dsentry *first_dsentry = *first_dsentry_ptr, *dsentry = first_dsentry, *last_dsentry;
int n_dsentries = 0;
int i;
if(!_magic_asr_heap_map_do_permutate){
/*
* Dsentries order is reversed anyway, because newer dsentries are
* placed at the start of the linked list, instead of the end
*/
return;
}
while(dsentry != NULL){
last_dsentry = dsentry;
n_dsentries++;
dsentry = dsentry->next;
}
for(i=0; i < n_dsentries; i++){
int j;
int pos = magic_rand() % (n_dsentries - i);
struct _magic_dsentry *prev_dsentry = NULL;
if((i == 0) && (pos == (n_dsentries -1))){
/*
* Rest of for-loop won't function correctly when last dsentry is chosen first.
* Instead, nothing has to be done in this case.
*/
continue;
}
dsentry = first_dsentry;
for(j=0;j<pos;j++){
prev_dsentry = dsentry;
dsentry = dsentry->next;
}
if(pos == 0){
first_dsentry = first_dsentry->next;
}else{
prev_dsentry->next = dsentry->next;
}
dsentry->next = NULL;
last_dsentry->next = dsentry;
last_dsentry = dsentry;
}
*first_dsentry_ptr = first_dsentry;
}
PUBLIC void magic_asr_init(){
int seed, heap_offset;
if(_magic_asr_seed){
seed = _magic_asr_seed;
}else{
seed = magic_rand_seed();
}
magic_srand(seed);
heap_offset = magic_asr_get_padding_size(MAGIC_STATE_HEAP|MAGIC_ASR_FLAG_INIT);
if(heap_offset){
sbrk(heap_offset);
}
}

View file

@ -0,0 +1,216 @@
#include <magic_eval.h>
#include <magic.h>
#include <magic_eval_lib.h>
#define DEBUG MAGIC_DEBUG_SET(0)
#if DEBUG
#define MAGIC_EVAL_PRINTF _magic_printf
#else
#define MAGIC_EVAL_PRINTF magic_null_printf
#endif
PRIVATE int magic_eval_print_style = MAGIC_EVAL_PRINT_STYLE_DEFAULT;
/*===========================================================================*
* magic_eval_get_var_cb *
*===========================================================================*/
PRIVATE struct val* magic_eval_get_var_cb(char* name, struct val* val)
{
_magic_selement_t selement;
int ret;
double dvalue;
void *pvalue;
unsigned long uvalue;
long ivalue;
char vvalue;
struct _magic_dsentry dsentry_buff;
MAGIC_EVAL_PRINTF("magic_eval_get_var_cb: %s requested\n", name);
ret = magic_selement_lookup_by_name(name, &selement, &dsentry_buff);
if(ret < 0) {
return NULL;
}
val->type = T_INT;
switch(selement.type->type_id) {
case MAGIC_TYPE_FLOAT:
dvalue = magic_selement_to_float(&selement);
val->type = T_REAL;
val->rval = dvalue;
break;
case MAGIC_TYPE_POINTER:
pvalue = magic_selement_to_ptr(&selement);
val->ival = (long) pvalue;
break;
case MAGIC_TYPE_INTEGER:
case MAGIC_TYPE_ENUM:
if(MAGIC_TYPE_FLAG(selement.type, MAGIC_TYPE_UNSIGNED)) {
uvalue = magic_selement_to_unsigned(&selement);
val->ival = (long) uvalue;
}
else {
ivalue = magic_selement_to_int(&selement);
val->ival = ivalue;
}
break;
case MAGIC_TYPE_VOID:
vvalue = *((char*) selement.address);
val->ival = (long) vvalue;
break;
default:
return NULL;
break;
}
if(magic_eval_print_style & MAGIC_EVAL_PRINT_VAR_VALUES) {
if(val->type == T_INT) {
_magic_printf("VAR: %s = %ld\n", name, val->ival);
}
else {
_magic_printf("VAR: %s = %g\n", name, val->rval);
}
}
return val;
}
/*===========================================================================*
* magic_eval_get_func_result_cb *
*===========================================================================*/
PRIVATE struct val* magic_eval_get_func_result_cb(char* name, struct val* arg,
struct val* ret)
{
struct _magic_function *function;
magic_eval_func_t magic_eval_func;
long result, iarg;
MAGIC_EVAL_PRINTF("magic_eval_get_func_result_cb: %s requested\n", name);
if(strncmp(MAGIC_EVAL_FUNC_PREFIX, name, strlen(MAGIC_EVAL_FUNC_PREFIX))) {
return NULL;
}
function = magic_function_lookup_by_name(NULL, name);
if(!function) {
return NULL;
}
magic_eval_func = (magic_eval_func_t) (long) function->address;
iarg = arg->type == T_INT ? arg->ival : (long) arg->rval;
result = magic_eval_func(iarg);
ret->type = T_INT;
ret->ival = result;
if(magic_eval_print_style & MAGIC_EVAL_PRINT_FUNC_RESULTS) {
_magic_printf("FUNCTION: %s(%ld) = %ld\n", name, iarg, result);
}
return ret;
}
/*===========================================================================*
* magic_eval_init *
*===========================================================================*/
PUBLIC void magic_eval_init()
{
eval_set_cb_get_var(magic_eval_get_var_cb);
eval_set_cb_get_func_result(magic_eval_get_func_result_cb);
}
/*===========================================================================*
* magic_eval *
*===========================================================================*/
PRIVATE int magic_eval(char *expr, struct val* result)
{
int ret;
MAGIC_EVAL_PRINTF("magic_eval: Evaluating expression %s\n", expr);
ret = evaluate(expr, result, NULL);
switch(ret) {
case ERROR_SYNTAX:
ret = MAGIC_EINVAL;
break;
case ERROR_FUNCNOTFOUND:
case ERROR_VARNOTFOUND:
ret = MAGIC_ENOENT;
break;
case ERROR_NOMEM:
ret = MAGIC_ENOMEM;
break;
case ERROR_DIV0:
ret = MAGIC_EBADMSTATE;
break;
case RESULT_OK:
ret = 0;
break;
default:
ret = MAGIC_EGENERIC;
break;
}
return ret;
}
/*===========================================================================*
* magic_eval_int *
*===========================================================================*/
PUBLIC int magic_eval_int(char *expr, long *result)
{
struct val val_res;
int ret;
ret = magic_eval(expr, &val_res);
if(ret < 0) {
return ret;
}
*result = val_res.type == T_INT ? val_res.ival : (long) val_res.rval;
return 0;
}
/*===========================================================================*
* magic_eval_bool *
*===========================================================================*/
PUBLIC int magic_eval_bool(char *expr, char *result)
{
struct val val_res;
int ret;
ret = magic_eval(expr, &val_res);
if(ret < 0) {
return ret;
}
if(val_res.type != T_INT) {
return MAGIC_EINVAL;
}
*result = val_res.ival == 0 ? 0 : 1;
return 0;
}
/*===========================================================================*
* magic_eval_float *
*===========================================================================*/
PUBLIC int magic_eval_float(char *expr, double *result)
{
struct val val_res;
int ret;
ret = magic_eval(expr, &val_res);
if(ret < 0) {
return ret;
}
*result = val_res.type == T_INT ? (double) val_res.ival : val_res.rval;
return 0;
}
/*===========================================================================*
* magic_eval_get_print_style *
*===========================================================================*/
PUBLIC int magic_eval_get_print_style()
{
return magic_eval_print_style;
}
/*===========================================================================*
* magic_eval_set_print_style *
*===========================================================================*/
PUBLIC void magic_eval_set_print_style(int style)
{
magic_eval_print_style = style;
}

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,321 @@
#define MAGIC_RANGE_DEBUG MAGIC_DEBUG_SET(0)
#include <magic_range.h>
/*===========================================================================*
* magic_range_is_shlib *
*===========================================================================*/
PRIVATE int magic_range_is_shlib(void *addr, void **container)
{
/*
* NB!: This function requires the calling thread to already
* hold the DSODESC lock.
*/
int ret = 0;
struct _magic_sodesc *sodesc;
struct _magic_dsodesc *dsodesc;
/* First iterate through the SO descriptors. */
MAGIC_SODESC_ITER(_magic_first_sodesc, sodesc,
/* First check the text range. */
MAGIC_RANGE_DEBUG_ADDR(addr, sodesc->lib.text_range);
if (MAGIC_ADDR_IS_IN_RANGE(addr, sodesc->lib.text_range)) {
ret |= MAGIC_STATE_TEXT;
goto found_so;
}
/* Next check the data range. */
MAGIC_RANGE_DEBUG_ADDR(addr, sodesc->lib.data_range);
if (MAGIC_ADDR_IS_IN_RANGE(addr, sodesc->lib.data_range)) {
ret |= MAGIC_STATE_DATA;
goto found_so;
}
);
/* Next iterate through the DSO descriptors. */
MAGIC_SODESC_ITER(_magic_first_dsodesc, dsodesc,
/* First check the text range. */
MAGIC_RANGE_DEBUG_ADDR(addr, dsodesc->lib.text_range);
if (MAGIC_ADDR_IS_IN_RANGE(addr, dsodesc->lib.text_range)) {
ret |= MAGIC_STATE_TEXT;
goto found_dso;
}
/* Next check the data range. */
MAGIC_RANGE_DEBUG_ADDR(addr, dsodesc->lib.data_range);
if (MAGIC_ADDR_IS_IN_RANGE(addr, dsodesc->lib.data_range)) {
ret |= MAGIC_STATE_DATA;
goto found_dso;
}
);
out:
return ret;
found_so:
ret |= MAGIC_STATE_LIB | MAGIC_STATE_LIB_SO;
if (container != NULL)
*container = (void *)(sodesc);
goto out;
found_dso:
ret |= MAGIC_STATE_LIB | MAGIC_STATE_LIB_DSO;
if (container != NULL) {
*container = (void *)(dsodesc);
}
goto out;
}
/*===========================================================================*
* magic_range_is_data *
*===========================================================================*/
PRIVATE INLINE int magic_range_is_data(void *addr)
{
MAGIC_RANGE_DEBUG_ADDR(addr, magic_data_range);
return MAGIC_ADDR_IS_IN_RANGE(addr, magic_data_range) ? MAGIC_STATE_DATA : 0;
}
/*===========================================================================*
* magic_range_is_text *
*===========================================================================*/
PRIVATE INLINE int magic_range_is_text(void *addr)
{
MAGIC_RANGE_DEBUG_ADDR(addr, magic_text_range);
return MAGIC_ADDR_IS_IN_RANGE(addr, magic_text_range) ? MAGIC_STATE_TEXT : 0;
}
/*===========================================================================*
* magic_range_is_heap *
*===========================================================================*/
PRIVATE INLINE int magic_range_is_heap(void *addr)
{
void* heap_range[2];
MAGIC_RANGE_SET_MIN(heap_range, magic_heap_start);
MAGIC_RANGE_SET_MAX(heap_range, (char *)magic_heap_end + MAGIC_HEAP_GAP);
MAGIC_RANGE_DEBUG_ADDR(addr, heap_range);
return MAGIC_ADDR_IS_IN_RANGE(addr, heap_range) ? MAGIC_STATE_HEAP : 0;
}
/*===========================================================================*
* magic_range_is_stack *
*===========================================================================*/
PUBLIC int magic_range_is_stack(void *addr)
{
/*
* NB!: This function requires the calling thread to already
* hold the DSENTRY lock.
*/
struct _magic_sentry *sentry;
int ret;
void *stack_range[2];
MAGIC_RANGE_INIT(stack_range);
assert(_magic_first_stack_dsentry && _magic_last_stack_dsentry);
sentry = MAGIC_DSENTRY_TO_SENTRY(_magic_first_stack_dsentry);
MAGIC_RANGE_SET_MIN(stack_range,
(char *) MAGIC_DSENTRY_TO_SENTRY(_magic_last_stack_dsentry)->address -
MAGIC_STACK_GAP);
MAGIC_RANGE_SET_MAX(stack_range,
((char *) sentry->address) + sentry->type->size - 1);
#if MAGIC_RANGE_ROUND_STACK
MAGIC_RANGE_PAGE_ROUND(stack_range);
#endif
MAGIC_RANGE_DEBUG_ADDR(addr, stack_range);
ret = MAGIC_ADDR_IS_IN_RANGE(addr, stack_range) ? MAGIC_STATE_STACK : 0;
return ret;
}
/*===========================================================================*
* magic_range_is_dsentry *
*===========================================================================*/
PUBLIC int magic_range_is_dsentry(void *addr)
{
/*
* NB!: This function requires the calling thread to already
* hold the DSENTRY lock.
*/
int ret = 0;
void *start_address, *end_address;
struct _magic_dsentry *prev_dsentry, *dsentry;
struct _magic_sentry *sentry;
int region;
if(magic_update_dsentry_ranges) {
MAGIC_RANGE_INIT(magic_heap_range);
MAGIC_RANGE_INIT(magic_map_range);
MAGIC_RANGE_INIT(magic_shm_range);
MAGIC_RANGE_INIT(magic_stack_range);
MAGIC_DSENTRY_ALIVE_ITER(_magic_first_dsentry, prev_dsentry, dsentry, sentry,
start_address = sentry->address;
end_address = (void *) (((char *)sentry->address) +
sentry->type->size - 1);
region = MAGIC_STATE_REGION(sentry);
if(region & MAGIC_STATE_HEAP) {
MAGIC_RANGE_UPDATE(magic_heap_range, start_address, end_address);
}
else if(region & MAGIC_STATE_MAP) {
MAGIC_RANGE_UPDATE(magic_map_range, start_address, end_address);
}
else if(region & MAGIC_STATE_SHM) {
MAGIC_RANGE_UPDATE(magic_shm_range, start_address, end_address);
}
else if(region & MAGIC_STATE_STACK) {
MAGIC_RANGE_UPDATE(magic_stack_range, start_address, end_address);
}
);
magic_update_dsentry_ranges = 0;
}
MAGIC_RANGE_DEBUG_ADDR(addr, magic_heap_range);
if(MAGIC_ADDR_IS_IN_RANGE(addr, magic_heap_range)) {
ret |= MAGIC_STATE_HEAP;
}
MAGIC_RANGE_DEBUG_ADDR(addr, magic_map_range);
if(MAGIC_ADDR_IS_IN_RANGE(addr, magic_map_range)) {
ret |= MAGIC_STATE_MAP;
}
MAGIC_RANGE_DEBUG_ADDR(addr, magic_shm_range);
if(MAGIC_ADDR_IS_IN_RANGE(addr, magic_shm_range)) {
ret |= MAGIC_STATE_SHM;
}
MAGIC_RANGE_DEBUG_ADDR(addr, magic_stack_range);
if(MAGIC_ADDR_IS_IN_RANGE(addr, magic_stack_range)) {
ret |= MAGIC_STATE_STACK;
}
return ret;
}
/*===========================================================================*
* magic_range_is_dfunction *
*===========================================================================*/
PUBLIC int magic_range_is_dfunction(void *addr)
{
/*
* NB!: This function requires the calling thread to already
* hold the DFUNCTION lock.
*/
int ret = 0;
void *start_address;
struct _magic_dfunction* dfunction;
struct _magic_function* function;
int region;
if(magic_update_dfunction_ranges) {
MAGIC_RANGE_INIT(magic_dfunction_range);
MAGIC_DFUNCTION_FUNC_ITER(_magic_first_dfunction, dfunction, function,
start_address = function->address;
region = MAGIC_STATE_REGION(function);
assert(region & MAGIC_STATE_TEXT);
MAGIC_RANGE_UPDATE(magic_dfunction_range, start_address, start_address);
);
magic_update_dfunction_ranges = 0;
}
MAGIC_RANGE_DEBUG_ADDR(addr, magic_dfunction_range);
if(MAGIC_ADDR_IS_IN_RANGE(addr, magic_dfunction_range)) {
ret |= MAGIC_STATE_TEXT;
}
return ret;
}
/*===========================================================================*
* magic_ranges_init *
*===========================================================================*/
PUBLIC void magic_ranges_init(void)
{
int i,j;
void *start_address, *end_address;
void* linker_vars[] = { MAGIC_LINKER_VAR_NAMES };
/* Init sentry and data range. */
MAGIC_RANGE_INIT(magic_data_range);
MAGIC_RANGE_INIT(magic_sentry_range);
for (i = 0 ; i < _magic_sentries_num ; i++) {
start_address = _magic_sentries[i].address;
end_address = (void *) (((char *)_magic_sentries[i].address)+_magic_sentries[i].type->size-1);
MAGIC_RANGE_UPDATE(magic_sentry_range, start_address, end_address);
j = 0;
while (linker_vars[j] && strcmp(linker_vars[j], _magic_sentries[i].name)) j++;
if (linker_vars[j] || MAGIC_STATE_FLAG(&_magic_sentries[i], MAGIC_STATE_THREAD_LOCAL)
|| MAGIC_STATE_FLAG(&_magic_sentries[i], MAGIC_STATE_EXTERNAL)) {
continue;
}
MAGIC_RANGE_UPDATE(magic_data_range, start_address, end_address);
}
#if MAGIC_RANGE_ROUND_DATA
MAGIC_RANGE_PAGE_ROUND(magic_data_range);
#endif
/* Init function range. */
MAGIC_RANGE_INIT(magic_function_range);
for (i = 0 ; i < _magic_functions_num ; i++) {
start_address = _magic_functions[i].address;
MAGIC_RANGE_UPDATE(magic_function_range, start_address, start_address);
}
/* Init text range. */
#ifdef __MINIX
MAGIC_RANGE_SET(magic_text_range, MAGIC_TEXT_START,
MAGIC_TEXT_END ? MAGIC_TEXT_END : ((char *)magic_function_range[1]));
#else
MAGIC_RANGE_SET(magic_text_range, MAGIC_TEXT_START,
MAGIC_TEXT_END ? MAGIC_TEXT_END : ((char *)magic_data_range[0] - 1));
#endif
#if MAGIC_RANGE_ROUND_TEXT
MAGIC_RANGE_PAGE_ROUND(magic_text_range);
#endif
/* Init heap start. */
magic_heap_start = MAGIC_HEAP_START ? MAGIC_HEAP_START : ((char *)magic_data_range[1] + 1);
magic_heap_end = ((char *)sbrk(0)) - 1;
/* Defaults for other ranges. */
MAGIC_RANGE_INIT(magic_heap_range);
MAGIC_RANGE_INIT(magic_map_range);
MAGIC_RANGE_INIT(magic_shm_range);
MAGIC_RANGE_INIT(magic_stack_range);
MAGIC_RANGE_INIT(magic_dfunction_range);
}
/*===========================================================================*
* magic_range_lookup_by_addr *
*===========================================================================*/
PUBLIC int magic_range_lookup_by_addr(void *addr, void **container)
{
/*
* NB!: This function requires the calling thread to already
* hold the DSENTRY, DFUNCTION and DSODESC locks.
*/
int ret;
/* Constant ranges first. */
if (magic_range_is_data(addr)) {
return MAGIC_STATE_DATA;
}
if (magic_range_is_text(addr)) {
return MAGIC_STATE_TEXT;
}
/* Non-dsentry ranges next. */
if (magic_range_is_heap(addr)) {
return MAGIC_STATE_HEAP;
}
if (magic_range_is_stack(addr)) {
return MAGIC_STATE_STACK;
}
/* Shared library ranges. */
#if 0
/* XXX: This kind of range isn't very accurate. */
if (magic_range_is_dfunction(addr)) {
return MAGIC_STATE_LIB | MAGIC_STATE_TEXT;
}
#endif
if ((ret = magic_range_is_shlib(addr, container))) {
return ret;
}
/* Dsentry ranges last. */
return magic_range_is_dsentry(addr);
}

View file

@ -0,0 +1,935 @@
#include <magic_selement.h>
/*===========================================================================*
* magic_selement_lookup_by_name *
*===========================================================================*/
PUBLIC int magic_selement_lookup_by_name(char *name,
_magic_selement_t *selement, struct _magic_dsentry *dsentry_buff)
{
char token_buff[MAGIC_MAX_NAME_LEN * 2 + 2];
char *token_start = name;
int last_num_seps = 0;
char *s;
if (!name || *name == '\0' || *name == MAGIC_SELEMENT_SEP[0]) {
return MAGIC_ENOENT;
}
for (s = name; *s; s++) {
if (*(s + 1) == '\0' || *(s + 1) == MAGIC_SELEMENT_SEP[0]) {
size_t len = s - token_start + 1;
if (len >= MAGIC_MAX_NAME_LEN * 2 + 1) {
return MAGIC_ENOMEM;
}
strncpy(token_buff, token_start, len);
token_buff[len] = '\0';
if (token_start == name) {
struct _magic_sentry *sentry;
char *sentry_parent_name = "", *sentry_name = NULL;
char *delim = NULL;
_magic_id_t dsentry_site_id = MAGIC_DSENTRY_SITE_ID_NULL;
if (!(delim = strchr(token_buff, MAGIC_DSENTRY_ABS_NAME_SEP[0]))) {
/* Regular sentry, no parent name or site_id. */
sentry_name = token_buff;
} else {
/*
* Dsentry. Will contain: sentry_id<DELIM>parent_name<DELIM>name<DELIM>site_id.
*/
delim = '\0';
/* Skip sentry_id */
sentry_parent_name = delim + 1;
delim = strchr(delim + 1, MAGIC_DSENTRY_ABS_NAME_SEP[0]);
assert(!delim && "No dsentry name found in selement name!");
delim = '\0';
sentry_name = delim + 1;
delim = strchr(delim + 1, MAGIC_DSENTRY_ABS_NAME_SEP[0]);
assert(!delim && "No dsentry site id found in selement name!");
delim = '\0';
dsentry_site_id = strtoul((const char*)delim+1, NULL, 10);
}
sentry = magic_sentry_lookup_by_name(sentry_parent_name, sentry_name,
dsentry_site_id, dsentry_buff);
if (!sentry) {
return MAGIC_ENOENT;
}
magic_selement_from_sentry(sentry, selement);
}
else {
_magic_selement_t child_selement;
if (!magic_selement_from_relative_name(selement, &child_selement, token_buff)) {
return MAGIC_ENOENT;
}
*selement = child_selement;
}
s++;
last_num_seps = 0;
while (*s == MAGIC_SELEMENT_SEP[0]) {
s++;
last_num_seps++;
}
token_start = s;
s--;
}
}
if (last_num_seps > 0 && selement->type->type_id == MAGIC_TYPE_POINTER) {
int steps = magic_selement_recurse_ptr(selement, selement, last_num_seps);
if(steps != last_num_seps) {
return MAGIC_EINVAL;
}
}
return 0;
}
/*===========================================================================*
* magic_selement_name_print_cb *
*===========================================================================*/
PUBLIC int magic_selement_name_print_cb(const struct _magic_type* parent_type,
const unsigned parent_offset, int child_num,
const struct _magic_type* type, const unsigned offset, int depth, void* cb_args)
{
_magic_selement_t *selement = (_magic_selement_t*) cb_args;
struct _magic_sentry* sentry = selement->sentry;
void *address = (char*)sentry->address + offset;
void *range[2];
MAGIC_RANGE_SET_MIN(range, address);
MAGIC_RANGE_SET_MAX(range, (char*) address + type->size-1);
if(!MAGIC_ADDR_IS_IN_RANGE(selement->address, range)) {
return MAGIC_TYPE_WALK_SKIP_PATH;
}
if(address == sentry->address && type == sentry->type) {
magic_print_sentry_abs_name(sentry);
}
else {
short is_parent_array = parent_type->type_id == MAGIC_TYPE_ARRAY || parent_type->type_id == MAGIC_TYPE_VECTOR;
if(is_parent_array) {
_magic_printf("%s%d", MAGIC_SELEMENT_SEP, child_num);
}
else {
_magic_printf("%s%s", MAGIC_SELEMENT_SEP, parent_type->member_names[child_num]);
}
}
if(type->num_child_types == 0
|| (address == selement->address && type == selement->type)) {
return MAGIC_TYPE_WALK_STOP;
}
return MAGIC_TYPE_WALK_CONTINUE;
}
/*===========================================================================*
* magic_selement_name_get_cb *
*===========================================================================*/
PUBLIC int magic_selement_name_get_cb(const struct _magic_type *parent_type,
const unsigned parent_offset, int child_num, const struct _magic_type *type,
const unsigned offset, int depth, void *args_array)
{
void **cb_args = (void **) args_array;
_magic_selement_t *selement = (_magic_selement_t*) cb_args[0];
char **buf = (char **) cb_args + 1;
int count, *buf_size = (int *) cb_args + 2;
short is_array = type->type_id == MAGIC_TYPE_ARRAY || type->type_id == MAGIC_TYPE_VECTOR;
struct _magic_sentry *sentry = selement->sentry;
void *address = (char *)sentry->address + offset;
void *range[2];
MAGIC_RANGE_SET_MIN(range, address);
MAGIC_RANGE_SET_MAX(range, (char *) address + type->size - 1);
if (!MAGIC_ADDR_IS_IN_RANGE(selement->address, range)) {
return MAGIC_TYPE_WALK_SKIP_PATH;
}
if (address == sentry->address && type == sentry->type) {
if (!(sentry->flags & MAGIC_STATE_DYNAMIC)) {
count = snprintf(*buf, *buf_size, "%s", sentry->name);
if (count >= *buf_size) return MAGIC_TYPE_WALK_STOP; /* Buffer too small. */
*buf += count;
*buf_size -= count;
} else {
struct _magic_dsentry *dsentry = MAGIC_DSENTRY_FROM_SENTRY(sentry);
assert(dsentry->parent_name && strcmp(dsentry->parent_name, ""));
assert(sentry->name && strcmp(sentry->name, ""));
count = snprintf(*buf, *buf_size, "%lu%s%s%s%s%s" MAGIC_ID_FORMAT,
(unsigned long)MAGIC_SENTRY_ID(sentry), MAGIC_DSENTRY_ABS_NAME_SEP,
dsentry->parent_name, MAGIC_DSENTRY_ABS_NAME_SEP, sentry->name,
MAGIC_DSENTRY_ABS_NAME_SEP, dsentry->site_id);
if (count >= *buf_size) return MAGIC_TYPE_WALK_STOP; /* Buffer too small. */
*buf += count;
*buf_size -= count;
}
} else {
short is_parent_array = parent_type->type_id == MAGIC_TYPE_ARRAY ||
parent_type->type_id == MAGIC_TYPE_VECTOR;
if (is_parent_array) {
count = snprintf(*buf, *buf_size, "%s%d",
MAGIC_SELEMENT_SEP, child_num);
if (count >= *buf_size) return MAGIC_TYPE_WALK_STOP; /* Buffer too small. */
*buf += count;
*buf_size -= count;
} else {
count = snprintf(*buf, *buf_size, "%s%s",
MAGIC_SELEMENT_SEP, parent_type->member_names[child_num]);
if (count >= *buf_size) return MAGIC_TYPE_WALK_STOP; /* Buffer too small. */
*buf += count;
*buf_size -= count;
}
}
if (type->num_child_types == 0
|| (address == selement->address && type == selement->type)
|| (is_array && address == selement->address && type == selement->parent_type)) {
return MAGIC_TYPE_WALK_STOP;
}
return MAGIC_TYPE_WALK_CONTINUE;
}
/*===========================================================================*
* magic_selement_print_value *
*===========================================================================*/
PUBLIC void magic_selement_print_value(const _magic_selement_t *selement)
{
int type_id = selement->type->type_id;
unsigned size = selement->type->size;
double dvalue;
void *pvalue;
unsigned long uvalue;
long ivalue;
char vvalue;
switch(type_id) {
case MAGIC_TYPE_FLOAT:
dvalue = magic_selement_to_float(selement);
_magic_printf("float(%d):%g", size, dvalue);
_magic_printf("/%d", (long) dvalue);
break;
case MAGIC_TYPE_POINTER:
pvalue = magic_selement_to_ptr(selement);
_magic_printf("ptr:%08x", pvalue);
break;
case MAGIC_TYPE_INTEGER:
case MAGIC_TYPE_ENUM:
if(MAGIC_TYPE_FLAG(selement->type, MAGIC_TYPE_UNSIGNED)) {
uvalue = magic_selement_to_unsigned(selement);
_magic_printf("unsigned %s(%d):%u", type_id == MAGIC_TYPE_INTEGER ? "int" : "enum", size, uvalue);
}
else {
ivalue = magic_selement_to_int(selement);
_magic_printf("%s(%d):%d", type_id == MAGIC_TYPE_INTEGER ? "int" : "enum", size, ivalue);
}
break;
case MAGIC_TYPE_VOID:
vvalue = *((char*) selement->address);
_magic_printf("void(%d):%d", size, vvalue);
break;
default:
_magic_printf("???");
break;
}
}
/*===========================================================================*
* magic_selement_to_unsigned *
*===========================================================================*/
PUBLIC unsigned long magic_selement_to_unsigned(const _magic_selement_t *selement)
{
void *address = selement->address;
const struct _magic_type* type = selement->type;
unsigned long value = 0;
unsigned size = type->size;
assert(size > 0);
assert(type->type_id == MAGIC_TYPE_INTEGER
|| type->type_id == MAGIC_TYPE_ENUM);
if(address == NULL)
return 0;
if(size == sizeof(unsigned char)) {
value = (unsigned long) *((unsigned char*) address);
}
else if(size == sizeof(unsigned short)) {
value = (unsigned long) *((unsigned short*) address);
}
#ifdef MAGIC_LONG_LONG_SUPPORTED
else if(size == sizeof(unsigned long long)) {
value = (unsigned long) *((unsigned long long*) address);
}
#endif
else {
assert(size == sizeof(unsigned long));
value = *((unsigned long*) address);
}
return value;
}
/*===========================================================================*
* magic_selement_to_int *
*===========================================================================*/
PUBLIC long magic_selement_to_int(const _magic_selement_t *selement)
{
void *address = selement->address;
const struct _magic_type* type = selement->type;
long value = 0;
unsigned size = type->size;
assert(size > 0);
assert(type->type_id == MAGIC_TYPE_INTEGER
|| type->type_id == MAGIC_TYPE_ENUM);
if(address == NULL)
return 0;
if(size == sizeof(char)) {
value = (long) *((char*) address);
}
else if(size == sizeof(short)) {
value = (long) *((short*) address);
}
#ifdef MAGIC_LONG_LONG_SUPPORTED
else if(size == sizeof(long long)) {
value = (long) *((long long*) address);
}
#endif
else {
assert(size == sizeof(long));
value = *((long*) address);
}
return value;
}
#ifdef MAGIC_LONG_LONG_SUPPORTED
/*===========================================================================*
* magic_selement_to_llu *
*===========================================================================*/
PUBLIC unsigned long long magic_selement_to_llu(const _magic_selement_t *selement)
{
void *address = selement->address;
const struct _magic_type* type = selement->type;
unsigned long long value;
unsigned size = type->size;
if(address == NULL)
return 0;
if (size == sizeof(unsigned long long))
value = *((unsigned long long*) address);
else
value = (unsigned long long) magic_selement_to_unsigned(selement);
return value;
}
/*===========================================================================*
* magic_selement_to_ll *
*===========================================================================*/
PUBLIC long long magic_selement_to_ll(const _magic_selement_t *selement)
{
void *address = selement->address;
const struct _magic_type* type = selement->type;
long long value;
unsigned size = type->size;
if(address == NULL)
return 0;
if (size == sizeof(long long))
value = *((long long*) address);
else
value = (long long) magic_selement_to_int(selement);
return value;
}
#endif
/*===========================================================================*
* magic_selement_to_float *
*===========================================================================*/
PUBLIC double magic_selement_to_float(const _magic_selement_t *selement)
{
void *address = selement->address;
const struct _magic_type* type = selement->type;
double value = 0.0;
unsigned size = type->size;
assert(size > 0);
assert(type->type_id == MAGIC_TYPE_FLOAT);
if(address == NULL)
return 0;
if(size == sizeof(float)) {
value = (double) *((float*) address);
}
#ifdef MAGIC_LONG_DOUBLE_SUPPORTED
else if(size == sizeof(long double)) {
value = (double) *((long double*) address);
}
#endif
else {
assert(size == sizeof(double));
value = *((double*) address);
}
return value;
}
/*===========================================================================*
* magic_selement_to_ptr *
*===========================================================================*/
PUBLIC void* magic_selement_to_ptr(const _magic_selement_t *selement)
{
void *address = selement->address;
const struct _magic_type* type = selement->type;
void* value = NULL;
assert(type->type_id == MAGIC_TYPE_POINTER);
if (!address)
return NULL;
value = *((void**) address);
return value;
}
/*===========================================================================*
* magic_selement_from_unsigned *
*===========================================================================*/
PUBLIC void magic_selement_from_unsigned(const _magic_selement_t *selement, unsigned long value)
{
void *address = selement->address;
const struct _magic_type* type = selement->type;
unsigned size = type->size;
assert(size > 0);
assert(type->type_id == MAGIC_TYPE_INTEGER
|| type->type_id == MAGIC_TYPE_ENUM);
/* Prevent a store to NULL. */
if(address == NULL)
return;
if(size == sizeof(unsigned char)) {
*((unsigned char*) address) = (unsigned char) value;
}
else if(size == sizeof(unsigned short)) {
*((unsigned short*) address) = (unsigned short) value;
}
#ifdef MAGIC_LONG_LONG_SUPPORTED
else if(size == sizeof(unsigned long long)) {
*((unsigned long long*) address) = (unsigned long long) value;
}
#endif
else {
assert(size == sizeof(unsigned long));
*((unsigned long*) address) = (unsigned long) value;
}
}
/*===========================================================================*
* magic_selement_from_int *
*===========================================================================*/
PUBLIC void magic_selement_from_int(const _magic_selement_t *selement, long value)
{
void *address = selement->address;
const struct _magic_type* type = selement->type;
unsigned size = type->size;
assert(size > 0);
assert(type->type_id == MAGIC_TYPE_INTEGER
|| type->type_id == MAGIC_TYPE_ENUM);
/* Prevent a store to NULL. */
if(address == NULL)
return;
if(size == sizeof(char)) {
*((char*) address) = (char) value;
}
else if(size == sizeof(short)) {
*((short*) address) = (short) value;
}
#ifdef MAGIC_LONG_LONG_SUPPORTED
else if(size == sizeof(long long)) {
*((long long*) address) = (long long) value;
}
#endif
else {
assert(size == sizeof(long));
*((long*) address) = (long) value;
}
}
/*===========================================================================*
* magic_selement_from_float *
*===========================================================================*/
PUBLIC void magic_selement_from_float(const _magic_selement_t *selement, double value)
{
void *address = selement->address;
const struct _magic_type* type = selement->type;
unsigned size = type->size;
assert(size > 0);
assert(type->type_id == MAGIC_TYPE_FLOAT);
/* Prevent a store to NULL. */
if(address == NULL)
return;
if(size == sizeof(float)) {
*((float*) address) = (float) value;
}
#ifdef MAGIC_LONG_DOUBLE_SUPPORTED
else if(size == sizeof(long double)) {
*((long double*) address) = (long double) value;
}
#endif
else {
assert(size == sizeof(double));
*((double*) address) = (double) value;
}
}
/*===========================================================================*
* magic_selement_ptr_value_cast *
*===========================================================================*/
PUBLIC int magic_selement_ptr_value_cast(const _magic_selement_t *src_selement, const _magic_selement_t *dst_selement, void* value_buffer)
{
int src_type_id = src_selement->type->type_id;
int dst_type_id = dst_selement->type->type_id;
unsigned src_size = src_selement->type->size;
unsigned dst_size = dst_selement->type->size;
void* src_value;
int r = 0;
assert(dst_size > 0);
if(dst_type_id != MAGIC_TYPE_POINTER) {
return EINVAL;
}
assert(dst_size == sizeof(void*));
if(src_size != sizeof(void*)) {
return EINVAL;
}
switch(src_type_id) {
case MAGIC_TYPE_POINTER:
return 0;
break;
case MAGIC_TYPE_INTEGER:
if(MAGIC_TYPE_FLAG(src_selement->type, MAGIC_TYPE_UNSIGNED)) {
MAGIC_CHECKED_VALUE_SRC_CAST(magic_selement_to_unsigned(src_selement), unsigned long, src_value, void*, &r, 0);
assert(r == 0);
}
else {
MAGIC_CHECKED_VALUE_SRC_CAST(magic_selement_to_int(src_selement), long, src_value, void*, &r, 0);
assert(r == 0);
}
break;
default:
return EINVAL;
break;
}
MAGIC_CHECKED_VALUE_DST_CAST(src_value, void*, value_buffer, void*, &r);
assert(r == 0);
return dst_size;
}
/*===========================================================================*
* magic_selement_unsigned_value_cast *
*===========================================================================*/
PUBLIC int magic_selement_unsigned_value_cast(const _magic_selement_t *src_selement, const _magic_selement_t *dst_selement, void* value_buffer)
{
int src_type_id = src_selement->type->type_id;
int dst_type_id = dst_selement->type->type_id;
int r = 0;
unsigned src_size = src_selement->type->size;
unsigned dst_size = dst_selement->type->size;
unsigned long src_value;
assert(dst_size > 0);
if(dst_type_id != MAGIC_TYPE_INTEGER && dst_type_id != MAGIC_TYPE_ENUM) {
return EINVAL;
}
switch(src_type_id) {
case MAGIC_TYPE_FLOAT:
MAGIC_CHECKED_VALUE_SRC_CAST(magic_selement_to_float(src_selement), double, src_value, unsigned long, &r, 1);
break;
case MAGIC_TYPE_POINTER:
if(dst_size != sizeof(void*)) {
return EINVAL;
}
MAGIC_CHECKED_VALUE_SRC_CAST(magic_selement_to_ptr(src_selement), void*, src_value, unsigned long, &r, 0);
assert(r == 0);
break;
case MAGIC_TYPE_INTEGER:
case MAGIC_TYPE_ENUM:
if(src_size == dst_size && MAGIC_TYPE_FLAG(src_selement->type, MAGIC_TYPE_UNSIGNED) == MAGIC_TYPE_FLAG(dst_selement->type, MAGIC_TYPE_UNSIGNED)) {
return 0;
}
if(MAGIC_TYPE_FLAG(src_selement->type, MAGIC_TYPE_UNSIGNED)) {
MAGIC_CHECKED_VALUE_SRC_CAST(magic_selement_to_unsigned(src_selement), unsigned long, src_value, unsigned long, &r, 0);
assert(r == 0);
}
else {
MAGIC_CHECKED_VALUE_SRC_CAST(magic_selement_to_int(src_selement), long, src_value, unsigned long, &r, 1);
}
break;
default:
return EINVAL;
break;
}
switch(dst_size) {
case sizeof(unsigned char):
MAGIC_CHECKED_VALUE_DST_CAST(src_value, unsigned long, value_buffer, unsigned char, &r);
break;
case sizeof(unsigned short):
MAGIC_CHECKED_VALUE_DST_CAST(src_value, unsigned long, value_buffer, unsigned short, &r);
break;
case sizeof(unsigned int):
MAGIC_CHECKED_VALUE_DST_CAST(src_value, unsigned long, value_buffer, unsigned int, &r);
break;
#ifdef MAGIC_LONG_LONG_SUPPORTED
case sizeof(unsigned long long):
MAGIC_CHECKED_VALUE_DST_CAST(src_value, unsigned long, value_buffer, unsigned long long, &r);
break;
#endif
default:
return EINVAL;
break;
}
if(r == 0) {
r = dst_size;
}
return r;
}
/*===========================================================================*
* magic_selement_int_value_cast *
*===========================================================================*/
PUBLIC int magic_selement_int_value_cast(const _magic_selement_t *src_selement, const _magic_selement_t *dst_selement, void* value_buffer)
{
int src_type_id = src_selement->type->type_id;
int dst_type_id = dst_selement->type->type_id;
int r = 0;
unsigned src_size = src_selement->type->size;
unsigned dst_size = dst_selement->type->size;
long src_value;
assert(dst_size > 0);
if(dst_type_id != MAGIC_TYPE_INTEGER && dst_type_id != MAGIC_TYPE_ENUM) {
return EINVAL;
}
switch(src_type_id) {
case MAGIC_TYPE_FLOAT:
MAGIC_CHECKED_VALUE_SRC_CAST(magic_selement_to_float(src_selement), double, src_value, long, &r, 1);
break;
case MAGIC_TYPE_POINTER:
if(dst_size != sizeof(void*)) {
return EINVAL;
}
MAGIC_CHECKED_VALUE_SRC_CAST(magic_selement_to_ptr(src_selement), void*, src_value, long, &r, 0);
assert(r == 0);
break;
case MAGIC_TYPE_INTEGER:
case MAGIC_TYPE_ENUM:
if(src_size == dst_size && MAGIC_TYPE_FLAG(src_selement->type, MAGIC_TYPE_UNSIGNED) == MAGIC_TYPE_FLAG(dst_selement->type, MAGIC_TYPE_UNSIGNED)) {
return 0;
}
if(MAGIC_TYPE_FLAG(src_selement->type, MAGIC_TYPE_UNSIGNED)) {
MAGIC_CHECKED_VALUE_SRC_CAST(magic_selement_to_unsigned(src_selement), unsigned long, src_value, long, &r, 1);
}
else {
MAGIC_CHECKED_VALUE_SRC_CAST(magic_selement_to_int(src_selement), long, src_value, long, &r, 0);
assert(r == 0);
}
break;
default:
return EINVAL;
break;
}
switch(dst_size) {
case sizeof(char):
MAGIC_CHECKED_VALUE_DST_CAST(src_value, long, value_buffer, char, &r);
break;
case sizeof(short):
MAGIC_CHECKED_VALUE_DST_CAST(src_value, long, value_buffer, short, &r);
break;
case sizeof(int):
MAGIC_CHECKED_VALUE_DST_CAST(src_value, long, value_buffer, int, &r);
break;
#ifdef MAGIC_LONG_LONG_SUPPORTED
case sizeof(long long):
MAGIC_CHECKED_VALUE_DST_CAST(src_value, long, value_buffer, long long, &r);
break;
#endif
default:
return EINVAL;
break;
}
if(r == 0) {
r = dst_size;
}
return r;
}
/*===========================================================================*
* magic_selement_float_value_cast *
*===========================================================================*/
PUBLIC int magic_selement_float_value_cast(const _magic_selement_t *src_selement, const _magic_selement_t *dst_selement, void* value_buffer)
{
int src_type_id = src_selement->type->type_id;
int dst_type_id = dst_selement->type->type_id;
int r = 0;
unsigned src_size = src_selement->type->size;
unsigned dst_size = dst_selement->type->size;
double src_value;
assert(dst_size > 0);
if(dst_type_id != MAGIC_TYPE_FLOAT) {
return EINVAL;
}
switch(src_type_id) {
case MAGIC_TYPE_FLOAT:
if(src_size == dst_size) {
return 0;
}
MAGIC_CHECKED_VALUE_SRC_CAST(magic_selement_to_float(src_selement), double, src_value, double, &r, 0);
assert(r == 0);
break;
case MAGIC_TYPE_INTEGER:
case MAGIC_TYPE_ENUM:
if(MAGIC_TYPE_FLAG(src_selement->type, MAGIC_TYPE_UNSIGNED)) {
MAGIC_CHECKED_VALUE_SRC_CAST(magic_selement_to_unsigned(src_selement), unsigned long, src_value, double, &r, 1);
}
else {
MAGIC_CHECKED_VALUE_SRC_CAST(magic_selement_to_int(src_selement), long, src_value, double, &r, 1);
}
break;
default:
return EINVAL;
break;
}
switch(dst_size) {
case sizeof(float):
MAGIC_CHECKED_VALUE_DST_CAST(src_value, double, value_buffer, float, &r);
break;
case sizeof(double):
MAGIC_CHECKED_VALUE_DST_CAST(src_value, double, value_buffer, double, &r);
break;
#ifdef MAGIC_LONG_DOUBLE_SUPPORTED
case sizeof(long double):
MAGIC_CHECKED_VALUE_DST_CAST(src_value, double, value_buffer, long double, &r);
break;
#endif
default:
return EINVAL;
break;
}
if(r == 0) {
r = dst_size;
}
return r;
}
/*===========================================================================*
* magic_selement_value_cast *
*===========================================================================*/
PUBLIC int magic_selement_value_cast(const _magic_selement_t *src_selement, const _magic_selement_t *dst_selement, void* value_buffer)
{
int r, src_type_id, dst_type_id;
size_t src_size, dst_size;
src_type_id = src_selement->type->type_id;
dst_type_id = dst_selement->type->type_id;
src_size = src_selement->type->size;
dst_size = dst_selement->type->size;
if(src_type_id == dst_type_id && src_size == dst_size && MAGIC_TYPE_FLAG(src_selement->type, MAGIC_TYPE_UNSIGNED) == MAGIC_TYPE_FLAG(dst_selement->type, MAGIC_TYPE_UNSIGNED)) {
return 0;
}
/* No size change allowed in opaque value casts. */
if(src_type_id == MAGIC_TYPE_OPAQUE || dst_type_id == MAGIC_TYPE_OPAQUE) {
return src_size == dst_size ? 0 : EINVAL;
}
/* No size change allowed in void value casts. */
if(src_type_id == MAGIC_TYPE_VOID || dst_type_id == MAGIC_TYPE_VOID) {
return src_size == dst_size ? 0 : EINVAL;
}
switch(dst_type_id) {
case MAGIC_TYPE_POINTER:
/* Cast to pointer values. */
r = magic_selement_ptr_value_cast(src_selement, dst_selement, value_buffer);
break;
case MAGIC_TYPE_FLOAT:
/* Cast to float values. */
r = magic_selement_float_value_cast(src_selement, dst_selement, value_buffer);
break;
case MAGIC_TYPE_INTEGER:
case MAGIC_TYPE_ENUM:
if(MAGIC_TYPE_FLAG(dst_selement->type, MAGIC_TYPE_UNSIGNED)) {
/* Cast to unsigned values. */
r = magic_selement_unsigned_value_cast(src_selement, dst_selement, value_buffer);
}
else {
/* Cast to integer values. */
r = magic_selement_int_value_cast(src_selement, dst_selement, value_buffer);
}
break;
default:
r = EINVAL;
break;
}
return r;
}
/*===========================================================================*
* magic_selement_get_parent *
*===========================================================================*/
PUBLIC _magic_selement_t* magic_selement_get_parent(
const _magic_selement_t *selement, _magic_selement_t *parent_selement)
{
if(!selement->parent_type) {
return NULL;
}
parent_selement->sentry = selement->sentry;
parent_selement->parent_type = NULL;
parent_selement->child_num = 0;
parent_selement->type = selement->parent_type;
parent_selement->address = selement->parent_address;
parent_selement->num = 0;
assert(parent_selement->address >= parent_selement->sentry->address);
return parent_selement;
}
/*===========================================================================*
* magic_selement_fill_from_parent_info *
*===========================================================================*/
PUBLIC void magic_selement_fill_from_parent_info(_magic_selement_t *selement,
int walk_flags)
{
unsigned offset;
magic_type_walk_step(selement->parent_type,
selement->child_num, &selement->type, &offset, walk_flags);
selement->address = (char*) selement->parent_address + offset;
}
/*===========================================================================*
* magic_selement_from_sentry *
*===========================================================================*/
PUBLIC _magic_selement_t* magic_selement_from_sentry(struct _magic_sentry *sentry,
_magic_selement_t *selement)
{
selement->sentry = sentry;
selement->parent_type = NULL;
selement->child_num = 0;
selement->type = sentry->type;
selement->address = sentry->address;
selement->num = 1;
return selement;
}
/*===========================================================================*
* magic_selement_from_relative_name *
*===========================================================================*/
PUBLIC _magic_selement_t* magic_selement_from_relative_name(
_magic_selement_t *parent_selement, _magic_selement_t *selement, char* name)
{
_magic_selement_t new_parent_selement;
const struct _magic_type* parent_type = parent_selement->type;
int parent_type_id = parent_type->type_id;
int walk_flags = 0;
int i, child_num = -1;
char *end;
if(!name || *name == '\0') {
return NULL;
}
if(parent_type_id == MAGIC_TYPE_UNION && (*name >= '0' && *name <= '9')) {
parent_type_id = MAGIC_TYPE_ARRAY;
walk_flags = MAGIC_TYPE_WALK_UNIONS_AS_VOID;
}
switch(parent_type_id) {
case MAGIC_TYPE_ARRAY:
case MAGIC_TYPE_VECTOR:
child_num = (int) strtol(name, &end, 10);
if(end == name || *end != '\0' || errno == ERANGE) {
return NULL;
}
break;
case MAGIC_TYPE_STRUCT:
case MAGIC_TYPE_UNION:
for(i=0;i<parent_type->num_child_types;i++) {
if(!strcmp(parent_type->member_names[i], name)) {
child_num = i;
break;
}
}
if(i == parent_type->num_child_types) {
return NULL;
}
break;
case MAGIC_TYPE_POINTER:
i = magic_selement_recurse_ptr(parent_selement, selement, MAGIC_SELEMENT_MAX_PTR_RECURSIONS);
if(i <= 0 || i >= MAGIC_SELEMENT_MAX_PTR_RECURSIONS) {
return NULL;
}
new_parent_selement = *selement;
return magic_selement_from_relative_name(&new_parent_selement, selement, name);
break;
default:
return NULL;
break;
}
if(child_num != -1) {
selement->sentry = parent_selement->sentry;
selement->parent_type = parent_type;
selement->parent_address = parent_selement->address;
selement->child_num = child_num;
selement->num = parent_selement->num+1;
magic_selement_fill_from_parent_info(selement, walk_flags);
}
return selement;
}

View file

@ -0,0 +1,919 @@
#include <magic_sentry.h>
#include <magic_splay_tree.h>
/*===========================================================================*
* magic_sentry_get_off_by_n *
*===========================================================================*/
PUBLIC long magic_sentry_get_off_by_n(struct _magic_sentry *sentry,
void *addr, int flags)
{
char *el_addr = (char*) addr, *first_el_addr, *last_el_addr;
size_t el_size;
unsigned long n, diff;
long long_n;
if (sentry->type->type_id != MAGIC_TYPE_ARRAY) {
return LONG_MAX;
}
el_size = sentry->type->contained_types[0]->size;
first_el_addr = (char*) sentry->address;
last_el_addr = (first_el_addr+sentry->type->size-el_size);
if (el_addr >= last_el_addr) {
diff = (unsigned long) (el_addr - last_el_addr);
}
else if (el_addr <= first_el_addr) {
diff = (unsigned long) (first_el_addr - el_addr);
}
else {
return LONG_MAX;
}
if (diff % el_size != 0) {
return LONG_MAX;
}
n = diff / el_size;
if (n >= LONG_MAX) {
return LONG_MAX;
}
long_n = (el_addr >= last_el_addr ? (long) n : -((long)n));
if ((long_n < 0 && !(flags & MAGIC_SENTRY_OFF_BY_N_NEGATIVE))
|| (long_n > 0 && !(flags & MAGIC_SENTRY_OFF_BY_N_POSITIVE))
|| (long_n == 0 && !(flags & MAGIC_SENTRY_OFF_BY_N_ZERO))) {
return LONG_MAX;
}
return long_n;
}
/*===========================================================================*
* magic_do_check_sentry *
*===========================================================================*/
PRIVATE INLINE int magic_do_check_sentry(struct _magic_sentry *sentry)
{
int is_size_ok;
assert(sentry && "NULL sentry found!");
is_size_ok = sentry->type->size > 0;
if (!is_size_ok) {
_magic_printf("magic_do_check_sentry: bad sentry, checks: %d\n", is_size_ok);
MAGIC_SENTRY_PRINT(sentry, MAGIC_EXPAND_TYPE_STR);
_magic_printf("\n");
return FALSE;
}
return TRUE;
}
/*===========================================================================*
* magic_check_sentry *
*===========================================================================*/
PUBLIC int magic_check_sentry(struct _magic_sentry *sentry)
{
int check;
check = magic_do_check_sentry(sentry);
if (!check) {
return FALSE;
}
#if MAGIC_CHECK_LEVEL == 2
check = magic_check_sentries();
if (!check) {
_magic_printf("magic_check_sentry: bad other sentry\n");
return FALSE;
}
#endif
return TRUE;
}
/*===========================================================================*
* magic_check_sentries *
*===========================================================================*/
PUBLIC int magic_check_sentries()
{
int i, ret, check = TRUE;
for (i = 0 ; i < _magic_sentries_num ; i++) {
ret = magic_do_check_sentry(&_magic_sentries[i]);
if (ret == FALSE) {
check = FALSE;
}
}
return check;
}
/*===========================================================================*
* magic_sentry_lookup_by_id *
*===========================================================================*/
PUBLIC struct _magic_sentry *magic_sentry_lookup_by_id(_magic_id_t id,
struct _magic_dsentry *dsentry_buff)
{
struct _magic_sentry *entry = NULL;
struct _magic_dsentry *prev_dsentry, *dsentry;
struct _magic_sentry *sentry;
if (id <= 0) {
return NULL;
}
/* O(1) ID lookup for sentries. */
#if MAGIC_LOOKUP_SENTRY
if (id <= _magic_sentries_num) {
return &_magic_sentries[id - 1];
}
#endif
/* O(N) ID lookup for dsentries. */
#if MAGIC_LOOKUP_DSENTRY
MAGIC_DSENTRY_LOCK();
MAGIC_DSENTRY_ALIVE_NESTED_ITER(_magic_first_dsentry, prev_dsentry, dsentry, sentry,
if(sentry->id == id) {
if(dsentry_buff) {
magic_copy_dsentry(dsentry, dsentry_buff);
entry = MAGIC_DSENTRY_TO_SENTRY(dsentry_buff);
}
else {
entry = sentry;
}
break;
}
);
MAGIC_DSENTRY_UNLOCK();
#endif
return entry;
}
/*===========================================================================*
* magic_sentry_lookup_by_addr *
*===========================================================================*/
PUBLIC struct _magic_sentry *magic_sentry_lookup_by_addr(void *addr,
struct _magic_dsentry *dsentry_buff)
{
int i;
struct _magic_sentry *entry = NULL;
struct _magic_dsentry *prev_dsentry, *dsentry;
struct _magic_sentry *sentry;
#if MAGIC_LOOKUP_SENTRY_ALLOW_RANGE_INDEX
if (magic_sentry_rl_index) {
sentry = magic_sentry_lookup_by_range_index(addr, dsentry_buff);
if (sentry && sentry->address == addr) {
return sentry;
} else {
return NULL;
}
}
#endif
/* Scan all the entries and return the one matching the provided address. */
#if MAGIC_LOOKUP_SENTRY
if (MAGIC_ADDR_IS_IN_RANGE(addr, magic_sentry_range)) {
for (i = 0 ; i < _magic_sentries_num ; i++) {
if (_magic_sentries[i].address == addr) {
entry = &_magic_sentries[i];
break;
}
}
if (entry) {
return entry;
}
}
#endif
#if MAGIC_LOOKUP_DSENTRY
MAGIC_DSENTRY_LOCK();
if (!MAGIC_ADDR_LOOKUP_USE_DSENTRY_RANGES || magic_range_is_dsentry(addr)) {
MAGIC_DSENTRY_ALIVE_BLOCK_ITER(_magic_first_dsentry, prev_dsentry, dsentry, sentry,
if (sentry->address == addr) {
if (dsentry_buff) {
magic_copy_dsentry(dsentry, dsentry_buff);
entry = MAGIC_DSENTRY_TO_SENTRY(dsentry_buff);
}
else {
entry = sentry;
}
break;
}
);
}
MAGIC_DSENTRY_UNLOCK();
#endif
return entry;
}
/*===========================================================================*
* magic_sentry_lookup_by_name *
*===========================================================================*/
PUBLIC struct _magic_sentry *magic_sentry_lookup_by_name(char *parent_name,
char *name, _magic_id_t site_id, struct _magic_dsentry *dsentry_buff)
{
int i;
struct _magic_sentry *entry = NULL;
struct _magic_dsentry *prev_dsentry, *dsentry;
struct _magic_sentry *sentry;
#if MAGIC_LOOKUP_SENTRY_ALLOW_NAME_HASH
if (magic_sentry_hash_head) {
return magic_sentry_lookup_by_name_hash(parent_name, name,
site_id, dsentry_buff);
}
#endif
/* Scan all the entries and return the one matching the provided name. */
#if MAGIC_LOOKUP_SENTRY
for (i = 0 ; i < _magic_sentries_num ; i++) {
if (!strcmp(_magic_sentries[i].name, name)) {
if (!parent_name ||
!strcmp(MAGIC_SENTRY_PARENT(&_magic_sentries[i]),
parent_name)) {
if (MAGIC_SENTRY_SITE_ID(&_magic_sentries[i]) == site_id) {
entry = &_magic_sentries[i];
break;
}
}
}
}
if (entry) {
return entry;
}
#endif
#if MAGIC_LOOKUP_DSENTRY
MAGIC_DSENTRY_LOCK();
MAGIC_DSENTRY_ALIVE_ITER(_magic_first_dsentry, prev_dsentry,
dsentry, sentry,
if (!strcmp(sentry->name, name)) {
if (!parent_name ||
!strcmp(MAGIC_SENTRY_PARENT(sentry), parent_name)) {
if (site_id == MAGIC_DSENTRY_SITE_ID_NULL ||
dsentry->site_id == site_id) {
if (dsentry_buff) {
magic_copy_dsentry(dsentry, dsentry_buff);
entry = MAGIC_DSENTRY_TO_SENTRY(dsentry_buff);
}
else {
entry = sentry;
}
break;
}
}
}
);
MAGIC_DSENTRY_UNLOCK();
#endif
return entry;
}
/*===========================================================================*
* magic_sentry_lookup_by_range *
*===========================================================================*/
PUBLIC struct _magic_sentry *magic_sentry_lookup_by_range(void *addr,
struct _magic_dsentry *dsentry_buff)
{
int i;
struct _magic_sentry *entry = NULL;
struct _magic_dsentry *prev_dsentry, *dsentry;
struct _magic_sentry *sentry;
void *start_address, *end_address;
#if MAGIC_LOOKUP_SENTRY_ALLOW_RANGE_INDEX
if (magic_sentry_rl_index) {
return magic_sentry_lookup_by_range_index(addr, dsentry_buff);
}
#endif
/* Scan all the entries and return the one with a valid range. */
#if MAGIC_LOOKUP_SENTRY
if (MAGIC_ADDR_IS_IN_RANGE(addr, magic_sentry_range)) {
for (i = 0 ; i < _magic_sentries_num ; i++) {
start_address = _magic_sentries[i].address;
end_address = (void *) (((char *)_magic_sentries[i].address) +
_magic_sentries[i].type->size - 1);
if (MAGIC_ADDR_IS_WITHIN(addr, start_address, end_address)) {
entry = &_magic_sentries[i];
break;
}
}
if (entry) {
return entry;
}
}
#endif
#if MAGIC_LOOKUP_DSENTRY
MAGIC_DSENTRY_LOCK();
if (!MAGIC_ADDR_LOOKUP_USE_DSENTRY_RANGES || magic_range_is_dsentry(addr)) {
MAGIC_DSENTRY_ALIVE_BLOCK_ITER(_magic_first_dsentry, prev_dsentry, dsentry, sentry,
start_address = sentry->address;
end_address = (void *) (((char *)sentry->address) +
sentry->type->size - 1);
if (MAGIC_ADDR_IS_WITHIN(addr, start_address, end_address)) {
if (dsentry_buff) {
magic_copy_dsentry(dsentry, dsentry_buff);
entry = MAGIC_DSENTRY_TO_SENTRY(dsentry_buff);
}
else {
entry = sentry;
}
break;
}
);
}
MAGIC_DSENTRY_UNLOCK();
#endif
return entry;
}
/*===========================================================================*
* magic_sentry_lookup_by_min_off_by_n *
*===========================================================================*/
PUBLIC struct _magic_sentry *magic_sentry_lookup_by_min_off_by_n(void *addr,
int flags, long *min_n_ptr, struct _magic_dsentry *dsentry_buff)
{
int i;
struct _magic_sentry *entry = NULL;
struct _magic_dsentry *prev_dsentry, *dsentry;
struct _magic_sentry *sentry;
long n, abs_n, min_n, min_abs_n = LONG_MAX;
int has_multiple_min_entries = FALSE;
/* Scan all the entries and return the one with the minimum off-by-n. */
#if MAGIC_LOOKUP_SENTRY
for (i = 0 ; i < _magic_sentries_num ; i++) {
n = magic_sentry_get_off_by_n(&_magic_sentries[i], addr, flags);
abs_n = MAGIC_ABS(n);
if (n == LONG_MAX || abs_n > min_abs_n) {
continue;
}
if (abs_n == min_abs_n) {
has_multiple_min_entries = TRUE;
}
else {
min_abs_n = abs_n;
min_n = n;
has_multiple_min_entries = FALSE;
entry = &_magic_sentries[i];
}
}
#endif
#if MAGIC_LOOKUP_DSENTRY
MAGIC_DSENTRY_LOCK();
MAGIC_DSENTRY_ALIVE_BLOCK_ITER(_magic_first_dsentry, prev_dsentry, dsentry, sentry,
n = magic_sentry_get_off_by_n(sentry, addr, flags);
abs_n = MAGIC_ABS(n);
if (n == LONG_MAX || abs_n > min_abs_n) {
continue;
}
if (abs_n == min_abs_n) {
has_multiple_min_entries = TRUE;
}
else {
min_abs_n = abs_n;
min_n = n;
has_multiple_min_entries = FALSE;
if (dsentry_buff) {
magic_copy_dsentry(dsentry, dsentry_buff);
entry = MAGIC_DSENTRY_TO_SENTRY(dsentry_buff);
}
else {
entry = sentry;
}
}
);
MAGIC_DSENTRY_UNLOCK();
#endif
if (has_multiple_min_entries && (flags & MAGIC_SENTRY_OFF_BY_N_NO_DUPLICATES)) {
entry = NULL;
}
if (entry && min_n_ptr) {
*min_n_ptr = min_n;
}
return entry;
}
/*===========================================================================*
* magic_sentry_lookup_by_string *
*===========================================================================*/
PUBLIC struct _magic_sentry *magic_sentry_lookup_by_string(char *string)
{
int i;
struct _magic_sentry *entry = NULL;
/* Scan all the string entries and return the matching one. */
#if MAGIC_LOOKUP_SENTRY
for(i = 0 ; i < _magic_sentries_num ; i++) {
if (MAGIC_STATE_FLAG(&_magic_sentries[i], MAGIC_STATE_STRING)
&& !strcmp((char *)_magic_sentries[i].address, string)) {
entry = &_magic_sentries[i];
break;
}
}
#endif
return entry;
}
/*===========================================================================*
* magic_print_sentry *
*===========================================================================*/
PUBLIC void magic_print_sentry(struct _magic_sentry *sentry)
{
MAGIC_SENTRY_PRINT(sentry, MAGIC_EXPAND_TYPE_STR);
}
/*===========================================================================*
* magic_print_sentry_abs_name *
*===========================================================================*/
PUBLIC void magic_print_sentry_abs_name(struct _magic_sentry *sentry)
{
if (!(sentry->flags & MAGIC_STATE_DYNAMIC)) {
_magic_printf(sentry->name);
}
else {
struct _magic_dsentry *dsentry = MAGIC_DSENTRY_FROM_SENTRY(sentry);
assert(dsentry->parent_name && strcmp(dsentry->parent_name, ""));
assert(sentry->name);
assert(strcmp(sentry->name, ""));
_magic_printf("%lu%s%s%s%s%s" MAGIC_ID_FORMAT, (unsigned long)MAGIC_SENTRY_ID(sentry),
MAGIC_DSENTRY_ABS_NAME_SEP, dsentry->parent_name,
MAGIC_DSENTRY_ABS_NAME_SEP, sentry->name,
MAGIC_DSENTRY_ABS_NAME_SEP, dsentry->site_id);
}
}
/*===========================================================================*
* magic_print_sentries *
*===========================================================================*/
PUBLIC void magic_print_sentries()
{
int i;
struct _magic_sentry* sentry;
_magic_printf("magic_print_sentries: Printing %d entries\n", _magic_sentries_num);
for (i = 0 ; i < _magic_sentries_num ; i++) {
sentry = &_magic_sentries[i];
MAGIC_SENTRY_PRINT(sentry, MAGIC_EXPAND_TYPE_STR);
_magic_printf("\n");
}
}
/*===========================================================================*
* magic_print_nonstr_sentries *
*===========================================================================*/
PUBLIC void magic_print_nonstr_sentries()
{
int i;
struct _magic_sentry *sentry;
_magic_printf("magic_print_nonstr_sentries: Printing %d/%d non-string entries\n",
_magic_sentries_num - _magic_sentries_str_num, _magic_sentries_num);
for (i = 0 ; i < _magic_sentries_num ; i++) {
sentry = &_magic_sentries[i];
if (MAGIC_SENTRY_IS_STRING(sentry)) {
continue;
}
MAGIC_SENTRY_PRINT(sentry, MAGIC_EXPAND_TYPE_STR);
_magic_printf("\n");
}
}
/*===========================================================================*
* magic_print_str_sentries *
*===========================================================================*/
PUBLIC void magic_print_str_sentries()
{
int i;
struct _magic_sentry *sentry;
_magic_printf("magic_print_str_sentries: Printing %d/%d string entries\n",
_magic_sentries_str_num, _magic_sentries_num);
for (i = 0 ; i < _magic_sentries_num ; i++) {
sentry = &_magic_sentries[i];
if (!MAGIC_SENTRY_IS_STRING(sentry)) {
continue;
}
MAGIC_SENTRY_PRINT(sentry, MAGIC_EXPAND_TYPE_STR);
_magic_printf(", string=\"%s\"\n", (char*)sentry->address);
}
}
/*===========================================================================*
* magic_sentry_rl_alloc *
*===========================================================================*/
PRIVATE void *magic_sentry_rl_alloc(int size, UNUSED(void *data))
{
void *addr;
assert(magic_sentry_rl_buff);
assert(magic_sentry_rl_buff_offset + size <= magic_sentry_rl_buff_size);
addr = (char*) magic_sentry_rl_buff + magic_sentry_rl_buff_offset;
magic_sentry_rl_buff_offset += size;
return addr;
}
/*===========================================================================*
* magic_sentry_rl_dealloc *
*===========================================================================*/
PRIVATE void magic_sentry_rl_dealloc(UNUSED(void *object), UNUSED(void *data))
{
return;
}
/*===========================================================================*
* magic_sentry_rl_build_index *
*===========================================================================*/
PUBLIC void magic_sentry_rl_build_index(void *buff, size_t buff_size)
{
/*
* Warning: this implementation is thread unsafe and also makes
* magic_sentry_lookup_by_range thread unsafe!
*/
int i;
struct _magic_dsentry *prev_dsentry, *dsentry;
struct _magic_sentry *sentry;
void *start_address;
splay_tree index;
assert(buff && buff_size > 0);
magic_sentry_rl_buff = buff;
magic_sentry_rl_buff_offset = 0;
magic_sentry_rl_buff_size = buff_size;
index = splay_tree_new_with_allocator(
splay_tree_compare_pointers,
NULL, NULL,
magic_sentry_rl_alloc, magic_sentry_rl_dealloc,
NULL);
magic_sentry_rl_index = index;
assert(magic_sentry_rl_index);
/* Add all the sentries to the index. */
#if MAGIC_LOOKUP_SENTRY
for (i = 0 ; i < _magic_sentries_num ; i++) {
start_address = _magic_sentries[i].address;
sentry = &_magic_sentries[i];
magic_sentry_rl_insert(start_address, sentry);
}
#endif
/* Add all the dsentries to the index. */
#if MAGIC_LOOKUP_DSENTRY
MAGIC_DSENTRY_LOCK();
MAGIC_DSENTRY_ALIVE_BLOCK_ITER(_magic_first_dsentry, prev_dsentry, dsentry, sentry,
start_address = sentry->address;
magic_sentry_rl_insert(start_address, sentry);
);
MAGIC_DSENTRY_UNLOCK();
#endif
}
/*===========================================================================*
* magic_sentry_rl_destroy_index *
*===========================================================================*/
PUBLIC void magic_sentry_rl_destroy_index(void)
{
magic_sentry_rl_buff = NULL;
magic_sentry_rl_buff_offset = 0;
magic_sentry_rl_buff_size = 0;
magic_sentry_rl_index = NULL;
}
/*===========================================================================*
* magic_sentry_rl_estimate_index_buff_size *
*===========================================================================*/
PUBLIC size_t magic_sentry_rl_estimate_index_buff_size(int sentries_num)
{
if (sentries_num == 0) {
MAGIC_DSENTRY_ALIVE_BLOCK_NUM(_magic_first_dsentry, &sentries_num);
sentries_num += _magic_sentries_num;
}
return (sentries_num * sizeof(struct splay_tree_node_s)) +
(sizeof(struct splay_tree_s) * 2);
}
/*===========================================================================*
* magic_sentry_rl_count_index_cb *
*===========================================================================*/
PRIVATE int magic_sentry_rl_count_index_cb(splay_tree_node node, void *data)
{
size_t *count = (size_t *) data;
(*count)++;
return 0;
}
/*===========================================================================*
* magic_sentry_rl_print_index_cb *
*===========================================================================*/
PRIVATE int magic_sentry_rl_print_index_cb(splay_tree_node node, void *data)
{
_magic_printf("NODE<key, value>: <%08x, %08x>\n", (unsigned int) node->key,
(unsigned int) node->value);
return 0;
}
/*===========================================================================*
* magic_sentry_rl_print_index *
*===========================================================================*/
PUBLIC void magic_sentry_rl_print_index(void)
{
size_t num_nodes = 0;
assert(magic_sentry_rl_index);
splay_tree_foreach((splay_tree) magic_sentry_rl_index,
magic_sentry_rl_count_index_cb, &num_nodes);
_magic_printf("magic_sentry_rl_print_index: Found %d nodes:\n", num_nodes);
splay_tree_foreach((splay_tree) magic_sentry_rl_index,
magic_sentry_rl_print_index_cb, NULL);
}
/*===========================================================================*
* magic_sentry_rl_lookup *
*===========================================================================*/
PUBLIC struct _magic_sentry *magic_sentry_rl_lookup(void *start_addr)
{
splay_tree_node node;
struct _magic_sentry *sentry = NULL;
node = splay_tree_lookup((splay_tree) magic_sentry_rl_index,
(splay_tree_key) start_addr);
if (node) {
sentry = (struct _magic_sentry*) node->value;
}
return sentry;
}
/*===========================================================================*
* magic_sentry_rl_insert *
*===========================================================================*/
PUBLIC struct _magic_sentry *magic_sentry_rl_insert(void *start_addr,
struct _magic_sentry *sentry)
{
if (!splay_tree_lookup((splay_tree) magic_sentry_rl_index,
(splay_tree_key) start_addr)) {
splay_tree_insert((splay_tree) magic_sentry_rl_index,
(splay_tree_key) start_addr,
(splay_tree_value) sentry);
}
else {
sentry = NULL;
}
return sentry;
}
/*===========================================================================*
* magic_sentry_rl_pred_lookup *
*===========================================================================*/
PUBLIC struct _magic_sentry *magic_sentry_rl_pred_lookup(void *addr)
{
splay_tree_node node;
struct _magic_sentry *sentry = NULL;
node = splay_tree_predecessor((splay_tree) magic_sentry_rl_index,
(splay_tree_key) addr);
if (node) {
sentry = (struct _magic_sentry*) node->value;
}
return sentry;
}
/*===========================================================================*
* magic_sentry_lookup_by_range_index *
*===========================================================================*/
PUBLIC struct _magic_sentry *magic_sentry_lookup_by_range_index(
void *addr, struct _magic_dsentry *dsentry_buff)
{
/*
* Warning: this implementation is thread unsafe!
*/
void *start_address, *end_address;
struct _magic_sentry *sentry =
magic_sentry_rl_pred_lookup((char *)addr + 1);
if (sentry) {
start_address = sentry->address;
end_address = (void *) (((char *)start_address) +
sentry->type->size - 1);
if (!MAGIC_ADDR_IS_WITHIN(addr, start_address, end_address)) {
sentry = NULL;
} else {
if (MAGIC_STATE_FLAG(sentry, MAGIC_STATE_DYNAMIC) &&
dsentry_buff != NULL) {
magic_copy_dsentry(MAGIC_DSENTRY_FROM_SENTRY(sentry),
dsentry_buff);
}
}
}
return sentry;
}
/*===========================================================================*
* magic_sentry_hash_insert *
*===========================================================================*/
PRIVATE void magic_sentry_hash_insert(struct _magic_sentry_hash **head,
struct _magic_sentry_hash *elem)
{
if (head != NULL) {
struct _magic_sentry_hash *tmp;
HASH_FIND_STR(*head, elem->key, tmp);
if (tmp) {
LL_APPEND(tmp->sentry_list, elem->sentry_list);
return;
}
}
/*
* **** START UTHASH SPECIFIC DEFINITIONS ****
*/
#undef uthash_malloc
#undef uthash_free
#define uthash_malloc(size) magic_sentry_hash_alloc(size)
#define uthash_free(addr, size) magic_sentry_hash_dealloc(addr, size)
/*
* Since we have a limited buffer, we need to stop bucket expansion when
* reaching a certain limit.
*/
#undef uthash_expand_fyi
#define uthash_expand_fyi(tbl) \
do { \
if (tbl->num_buckets == MAGIC_SENTRY_NAME_EST_MAX_BUCKETS) { \
_magic_printf("Warning! Sentry name hash maximum bucket number " \
"reached! Consider increasing " \
"MAGIC_SENTRY_NAME_EST_MAX_BUCKETS, unless you are comfortable"\
" with the current performance.\n"); \
tbl->noexpand = 1; \
} \
} while(0);
/*
* **** FINISH UTHASH SPECIFIC DEFINITIONS ****
*/
HASH_ADD_STR(*head, key, elem);
/*
* **** START UTHASH DEFINITION REMOVAL ****
*/
#undef uthash_malloc
#undef uthash_free
#undef uthash_expand_fyi
/*
* **** FINISH UTHASH DEFINITION REMOVAL ****
*/
}
/*===========================================================================*
* magic_sentry_hash_build *
*===========================================================================*/
PUBLIC void magic_sentry_hash_build(void *buff, size_t buff_size)
{
/*
* XXX:
* Warning: this implementation is thread unsafe and also makes
* magic_sentry_lookup_by_name thread unsafe!
*/
int i;
struct _magic_dsentry *prev_dsentry, *dsentry;
struct _magic_sentry *sentry;
struct _magic_sentry_hash *sentry_hash, *head;
struct _magic_sentry_list *sentry_list;
assert(buff && buff_size > 0);
magic_sentry_hash_buff = buff;
magic_sentry_hash_buff_offset = 0;
magic_sentry_hash_buff_size = buff_size;
head = NULL;
/* Add all the sentries to the hash. */
#if MAGIC_LOOKUP_SENTRY
for(i = 0 ; i < _magic_sentries_num ; i++) {
sentry_hash = (struct _magic_sentry_hash *)
magic_sentry_hash_alloc(sizeof(struct _magic_sentry_hash));
sentry_list = (struct _magic_sentry_list *)
magic_sentry_hash_alloc(sizeof(struct _magic_sentry_list));
sentry = &_magic_sentries[i];
MAGIC_SENTRY_TO_HASH_EL(sentry, sentry_hash, sentry_list);
magic_sentry_hash_insert(&head, sentry_hash);
}
#endif
/* Add all the dsentries to the hash. */
#if MAGIC_LOOKUP_DSENTRY
MAGIC_DSENTRY_LOCK();
MAGIC_DSENTRY_ALIVE_ITER(_magic_first_dsentry, prev_dsentry, dsentry, sentry,
sentry_hash = (struct _magic_sentry_hash *)
magic_sentry_hash_alloc(sizeof(struct _magic_sentry_hash));
sentry_list = (struct _magic_sentry_list *)
magic_sentry_hash_alloc(sizeof(struct _magic_sentry_list));
MAGIC_DSENTRY_TO_HASH_EL(dsentry, sentry, sentry_hash, sentry_list);
magic_sentry_hash_insert(&head, sentry_hash);
);
MAGIC_DSENTRY_UNLOCK();
#endif
magic_sentry_hash_head = (void *)head;
assert(magic_sentry_hash_head || (!_magic_sentries_num && _magic_first_dsentry == NULL));
}
/*===========================================================================*
* magic_sentry_hash_destroy *
*===========================================================================*/
PUBLIC void magic_sentry_hash_destroy(void)
{
magic_sentry_hash_buff = NULL;
magic_sentry_hash_buff_offset = 0;
magic_sentry_hash_buff_size = 0;
magic_sentry_hash_head = NULL;
}
/*===========================================================================*
* magic_sentry_hash_estimate_buff_size *
*===========================================================================*/
PUBLIC size_t magic_sentry_hash_estimate_buff_size(int sentries_num)
{
if (sentries_num == 0) {
MAGIC_DSENTRY_ALIVE_NUM(_magic_first_dsentry, &sentries_num);
sentries_num += _magic_sentries_num;
}
return (sentries_num * (sizeof(struct _magic_sentry_hash) +
sizeof(struct _magic_sentry_list))) + MAGIC_SENTRY_NAME_HASH_OVERHEAD;
}
/*===========================================================================*
* magic_sentry_hash_alloc *
*===========================================================================*/
PUBLIC void *magic_sentry_hash_alloc(size_t size)
{
void *addr;
assert(magic_sentry_hash_buff);
assert(magic_sentry_hash_buff_offset + size <= magic_sentry_hash_buff_size);
addr = (char *) magic_sentry_hash_buff + magic_sentry_hash_buff_offset;
magic_sentry_hash_buff_offset += size;
return addr;
}
/*===========================================================================*
* magic_sentry_hash_dealloc *
*===========================================================================*/
PUBLIC void magic_sentry_hash_dealloc(UNUSED(void *object), UNUSED(size_t sz))
{
return;
}
/*===========================================================================*
* magic_sentry_lookup_by_name_hash *
*===========================================================================*/
PUBLIC struct _magic_sentry *magic_sentry_lookup_by_name_hash(
char *parent_name, char *name, _magic_id_t site_id,
struct _magic_dsentry *dsentry_buff)
{
/*
* Warning: this implementation is thread unsafe!
*/
char key[MAGIC_SENTRY_NAME_MAX_KEY_LEN];
struct _magic_sentry_hash *res, *head;
key[0] = 0;
sprintf(key, "%s%s%s%s" MAGIC_ID_FORMAT, parent_name,
MAGIC_DSENTRY_ABS_NAME_SEP, name, MAGIC_DSENTRY_ABS_NAME_SEP, site_id);
head = (struct _magic_sentry_hash *) magic_sentry_hash_head;
HASH_FIND_STR(head, key, res);
if (res == NULL)
return NULL;
return res->sentry_list->sentry;
}
/*===========================================================================*
* magic_sentry_list_lookup_by_name_hash *
*===========================================================================*/
PUBLIC struct _magic_sentry_list *magic_sentry_list_lookup_by_name_hash(
char *parent_name, char *name, _magic_id_t site_id,
struct _magic_dsentry *dsentry_buff)
{
/*
* Warning: this implementation is thread unsafe!
*/
char key[MAGIC_SENTRY_NAME_MAX_KEY_LEN];
struct _magic_sentry_hash *res, *head;
key[0] = 0;
sprintf(key, "%s%s%s%s" MAGIC_ID_FORMAT, parent_name,
MAGIC_DSENTRY_ABS_NAME_SEP, name, MAGIC_DSENTRY_ABS_NAME_SEP, site_id);
head = (struct _magic_sentry_hash *) magic_sentry_hash_head;
HASH_FIND_STR(head, key, res);
if (res == NULL)
return NULL;
return res->sentry_list;
}

View file

@ -0,0 +1,523 @@
/* A splay-tree datatype.
Copyright (C) 1998, 1999, 2000, 2001 Free Software Foundation, Inc.
Contributed by Mark Mitchell (mark@markmitchell.com).
This file is part of GNU CC.
GNU CC 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, or (at your option)
any later version.
GNU CC 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 GNU CC; see the file COPYING. If not, write to
the Free Software Foundation, 51 Franklin Street - Fifth Floor,
Boston, MA 02110-1301, USA. */
/* For an easily readable description of splay-trees, see:
Lewis, Harry R. and Denenberg, Larry. Data Structures and Their
Algorithms. Harper-Collins, Inc. 1991. */
#include <stdlib.h>
#include <stdio.h>
#include "magic_splay_tree.h"
#ifndef xmalloc
#define xmalloc malloc
#endif
static void splay_tree_delete_helper (splay_tree, splay_tree_node);
static inline void rotate_left (splay_tree_node *,
splay_tree_node, splay_tree_node);
static inline void rotate_right (splay_tree_node *,
splay_tree_node, splay_tree_node);
static void splay_tree_splay (splay_tree, splay_tree_key);
static int splay_tree_foreach_helper (splay_tree, splay_tree_node,
splay_tree_foreach_fn, void*);
/* Deallocate NODE (a member of SP), and all its sub-trees. */
static void
splay_tree_delete_helper (splay_tree sp, splay_tree_node node)
{
splay_tree_node pending = 0;
splay_tree_node active = 0;
if (!node)
return;
#define KDEL(x) if (sp->delete_key) (*sp->delete_key)(x);
#define VDEL(x) if (sp->delete_value) (*sp->delete_value)(x);
KDEL (node->key);
VDEL (node->value);
/* We use the "key" field to hold the "next" pointer. */
node->key = (splay_tree_key)pending;
pending = (splay_tree_node)node;
/* Now, keep processing the pending list until there aren't any
more. This is a little more complicated than just recursing, but
it doesn't toast the stack for large trees. */
while (pending)
{
active = pending;
pending = 0;
while (active)
{
splay_tree_node temp;
/* active points to a node which has its key and value
deallocated, we just need to process left and right. */
if (active->left)
{
KDEL (active->left->key);
VDEL (active->left->value);
active->left->key = (splay_tree_key)pending;
pending = (splay_tree_node)(active->left);
}
if (active->right)
{
KDEL (active->right->key);
VDEL (active->right->value);
active->right->key = (splay_tree_key)pending;
pending = (splay_tree_node)(active->right);
}
temp = active;
active = (splay_tree_node)(temp->key);
(*sp->deallocate) ((char*) temp, sp->allocate_data);
}
}
#undef KDEL
#undef VDEL
}
/* Rotate the edge joining the left child N with its parent P. PP is the
grandparents pointer to P. */
static inline void
rotate_left (splay_tree_node *pp, splay_tree_node p, splay_tree_node n)
{
splay_tree_node tmp;
tmp = n->right;
n->right = p;
p->left = tmp;
*pp = n;
}
/* Rotate the edge joining the right child N with its parent P. PP is the
grandparents pointer to P. */
static inline void
rotate_right (splay_tree_node *pp, splay_tree_node p, splay_tree_node n)
{
splay_tree_node tmp;
tmp = n->left;
n->left = p;
p->right = tmp;
*pp = n;
}
/* Bottom up splay of key. */
static void
splay_tree_splay (splay_tree sp, splay_tree_key key)
{
if (sp->root == 0)
return;
do {
int cmp1, cmp2;
splay_tree_node n, c;
n = sp->root;
cmp1 = (*sp->comp) (key, n->key);
/* Found. */
if (cmp1 == 0)
return;
/* Left or right? If no child, then we're done. */
if (cmp1 < 0)
c = n->left;
else
c = n->right;
if (!c)
return;
/* Next one left or right? If found or no child, we're done
after one rotation. */
cmp2 = (*sp->comp) (key, c->key);
if (cmp2 == 0
|| (cmp2 < 0 && !c->left)
|| (cmp2 > 0 && !c->right))
{
if (cmp1 < 0)
rotate_left (&sp->root, n, c);
else
rotate_right (&sp->root, n, c);
return;
}
/* Now we have the four cases of double-rotation. */
if (cmp1 < 0 && cmp2 < 0)
{
rotate_left (&n->left, c, c->left);
rotate_left (&sp->root, n, n->left);
}
else if (cmp1 > 0 && cmp2 > 0)
{
rotate_right (&n->right, c, c->right);
rotate_right (&sp->root, n, n->right);
}
else if (cmp1 < 0 && cmp2 > 0)
{
rotate_right (&n->left, c, c->right);
rotate_left (&sp->root, n, n->left);
}
else if (cmp1 > 0 && cmp2 < 0)
{
rotate_left (&n->right, c, c->left);
rotate_right (&sp->root, n, n->right);
}
} while (1);
}
/* Call FN, passing it the DATA, for every node below NODE, all of
which are from SP, following an in-order traversal. If FN every
returns a non-zero value, the iteration ceases immediately, and the
value is returned. Otherwise, this function returns 0. */
static int
splay_tree_foreach_helper (splay_tree sp, splay_tree_node node,
splay_tree_foreach_fn fn, void *data)
{
int val;
if (!node)
return 0;
val = splay_tree_foreach_helper (sp, node->left, fn, data);
if (val)
return val;
val = (*fn)(node, data);
if (val)
return val;
return splay_tree_foreach_helper (sp, node->right, fn, data);
}
/* An allocator and deallocator based on xmalloc. */
static void *
splay_tree_xmalloc_allocate (int size, void *data ATTRIBUTE_UNUSED)
{
return (void *) xmalloc (size);
}
static void
splay_tree_xmalloc_deallocate (void *object, void *data ATTRIBUTE_UNUSED)
{
free (object);
}
/* Allocate a new splay tree, using COMPARE_FN to compare nodes,
DELETE_KEY_FN to deallocate keys, and DELETE_VALUE_FN to deallocate
values. Use xmalloc to allocate the splay tree structure, and any
nodes added. */
splay_tree
splay_tree_new (splay_tree_compare_fn compare_fn,
splay_tree_delete_key_fn delete_key_fn,
splay_tree_delete_value_fn delete_value_fn)
{
return (splay_tree_new_with_allocator
(compare_fn, delete_key_fn, delete_value_fn,
splay_tree_xmalloc_allocate, splay_tree_xmalloc_deallocate, 0));
}
/* Allocate a new splay tree, using COMPARE_FN to compare nodes,
DELETE_KEY_FN to deallocate keys, and DELETE_VALUE_FN to deallocate
values. */
splay_tree
splay_tree_new_with_allocator (splay_tree_compare_fn compare_fn,
splay_tree_delete_key_fn delete_key_fn,
splay_tree_delete_value_fn delete_value_fn,
splay_tree_allocate_fn allocate_fn,
splay_tree_deallocate_fn deallocate_fn,
void *allocate_data)
{
splay_tree sp = (splay_tree) (*allocate_fn) (sizeof (struct splay_tree_s),
allocate_data);
sp->root = 0;
sp->comp = compare_fn;
sp->delete_key = delete_key_fn;
sp->delete_value = delete_value_fn;
sp->allocate = allocate_fn;
sp->deallocate = deallocate_fn;
sp->allocate_data = allocate_data;
return sp;
}
/* Deallocate SP. */
void
splay_tree_delete (splay_tree sp)
{
splay_tree_delete_helper (sp, sp->root);
(*sp->deallocate) ((char*) sp, sp->allocate_data);
}
/* Insert a new node (associating KEY with DATA) into SP. If a
previous node with the indicated KEY exists, its data is replaced
with the new value. Returns the new node. */
splay_tree_node
splay_tree_insert (splay_tree sp, splay_tree_key key, splay_tree_value value)
{
int comparison = 0;
splay_tree_splay (sp, key);
if (sp->root)
comparison = (*sp->comp)(sp->root->key, key);
if (sp->root && comparison == 0)
{
/* If the root of the tree already has the indicated KEY, just
replace the value with VALUE. */
if (sp->delete_value)
(*sp->delete_value)(sp->root->value);
sp->root->value = value;
}
else
{
/* Create a new node, and insert it at the root. */
splay_tree_node node;
node = ((splay_tree_node)
(*sp->allocate) (sizeof (struct splay_tree_node_s),
sp->allocate_data));
node->key = key;
node->value = value;
if (!sp->root)
node->left = node->right = 0;
else if (comparison < 0)
{
node->left = sp->root;
node->right = node->left->right;
node->left->right = 0;
}
else
{
node->right = sp->root;
node->left = node->right->left;
node->right->left = 0;
}
sp->root = node;
}
return sp->root;
}
/* Remove KEY from SP. It is not an error if it did not exist. */
void
splay_tree_remove (splay_tree sp, splay_tree_key key)
{
splay_tree_splay (sp, key);
if (sp->root && (*sp->comp) (sp->root->key, key) == 0)
{
splay_tree_node left, right;
left = sp->root->left;
right = sp->root->right;
/* Delete the root node itself. */
if (sp->delete_value)
(*sp->delete_value) (sp->root->value);
(*sp->deallocate) (sp->root, sp->allocate_data);
/* One of the children is now the root. Doesn't matter much
which, so long as we preserve the properties of the tree. */
if (left)
{
sp->root = left;
/* If there was a right child as well, hang it off the
right-most leaf of the left child. */
if (right)
{
while (left->right)
left = left->right;
left->right = right;
}
}
else
sp->root = right;
}
}
/* Lookup KEY in SP, returning VALUE if present, and NULL
otherwise. */
splay_tree_node
splay_tree_lookup (splay_tree sp, splay_tree_key key)
{
splay_tree_splay (sp, key);
if (sp->root && (*sp->comp)(sp->root->key, key) == 0)
return sp->root;
else
return 0;
}
/* Return the node in SP with the greatest key. */
splay_tree_node
splay_tree_max (splay_tree sp)
{
splay_tree_node n = sp->root;
if (!n)
return NULL;
while (n->right)
n = n->right;
return n;
}
/* Return the node in SP with the smallest key. */
splay_tree_node
splay_tree_min (splay_tree sp)
{
splay_tree_node n = sp->root;
if (!n)
return NULL;
while (n->left)
n = n->left;
return n;
}
/* Return the immediate predecessor KEY, or NULL if there is no
predecessor. KEY need not be present in the tree. */
splay_tree_node
splay_tree_predecessor (splay_tree sp, splay_tree_key key)
{
int comparison;
splay_tree_node node;
/* If the tree is empty, there is certainly no predecessor. */
if (!sp->root)
return NULL;
/* Splay the tree around KEY. That will leave either the KEY
itself, its predecessor, or its successor at the root. */
splay_tree_splay (sp, key);
comparison = (*sp->comp)(sp->root->key, key);
/* If the predecessor is at the root, just return it. */
if (comparison < 0)
return sp->root;
/* Otherwise, find the rightmost element of the left subtree. */
node = sp->root->left;
if (node)
while (node->right)
node = node->right;
return node;
}
/* Return the immediate successor KEY, or NULL if there is no
successor. KEY need not be present in the tree. */
splay_tree_node
splay_tree_successor (splay_tree sp, splay_tree_key key)
{
int comparison;
splay_tree_node node;
/* If the tree is empty, there is certainly no successor. */
if (!sp->root)
return NULL;
/* Splay the tree around KEY. That will leave either the KEY
itself, its predecessor, or its successor at the root. */
splay_tree_splay (sp, key);
comparison = (*sp->comp)(sp->root->key, key);
/* If the successor is at the root, just return it. */
if (comparison > 0)
return sp->root;
/* Otherwise, find the leftmost element of the right subtree. */
node = sp->root->right;
if (node)
while (node->left)
node = node->left;
return node;
}
/* Call FN, passing it the DATA, for every node in SP, following an
in-order traversal. If FN every returns a non-zero value, the
iteration ceases immediately, and the value is returned.
Otherwise, this function returns 0. */
int
splay_tree_foreach (splay_tree sp, splay_tree_foreach_fn fn, void *data)
{
return splay_tree_foreach_helper (sp, sp->root, fn, data);
}
/* Splay-tree comparison function, treating the keys as ints. */
int
splay_tree_compare_ints (splay_tree_key k1, splay_tree_key k2)
{
if ((int) k1 < (int) k2)
return -1;
else if ((int) k1 > (int) k2)
return 1;
else
return 0;
}
/* Splay-tree comparison function, treating the keys as pointers. */
int
splay_tree_compare_pointers (splay_tree_key k1, splay_tree_key k2)
{
if ((char*) k1 < (char*) k2)
return -1;
else if ((char*) k1 > (char*) k2)
return 1;
else
return 0;
}

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,82 @@
#include <minix/syslib.h>
#include <minix/sysutil.h>
#include <minix/com.h>
#include <minix/type.h>
#include <minix/ds.h>
#include "ds/store.h"
#include <magic_analysis.h>
#include <st/state_transfer.h>
char* sef_sf_typename_keys[] = { "dsi_u", NULL };
#define dsi_u_idx 0
/*===========================================================================*
* sef_cb_sf_transfer_dsi_u *
*===========================================================================*/
static int sef_cb_sf_transfer_dsi_u(_magic_selement_t *selement, _magic_sel_analyzed_t *sel_analyzed, _magic_sel_stats_t *sel_stats, struct st_cb_info *cb_info) {
static struct dsi_mem noxfer_dsi_mem_stub;
static const struct _magic_type* _magic_dsi_mem_type = NULL;
struct data_store* dsp;
_magic_selement_t parent_selement;
int ret = EGENERIC;
VOLATILE int keep_stubs = (int)&noxfer_dsi_mem_stub;
assert(keep_stubs);
if(magic_selement_get_parent(selement, &parent_selement) == NULL) {
ST_CB_PRINT(ST_CB_ERR, "sef_cb_sf_transfer_dsi_u: magic_selement_get_parent failed", selement, sel_analyzed, sel_stats, cb_info);
return EINVAL;
}
dsp = (struct data_store*) parent_selement.address;
if(!(dsp->flags & DSF_IN_USE)) {
/* Skip when unused. */
return MAGIC_SENTRY_ANALYZE_SKIP_PATH;
}
switch(dsp->flags & DSF_MASK_TYPE) {
case DSF_TYPE_U32:
case DSF_TYPE_LABEL:
/* Identity transfer when no ptr is involved. */
ret = st_cb_transfer_identity(selement, sel_analyzed, sel_stats, cb_info);
break;
case DSF_TYPE_STR:
case DSF_TYPE_MEM:
/* Transfer as dsp->u.mem struct. */
if(!_magic_dsi_mem_type && !(_magic_dsi_mem_type = magic_type_lookup_by_name("dsi_mem"))) {
ST_CB_PRINT(ST_CB_ERR, "sef_cb_sf_transfer_dsi_u: type dsi_mem not found", selement, sel_analyzed, sel_stats, cb_info);
return ENOENT;
}
st_cb_selement_type_cast(_magic_dsi_mem_type, _magic_dsi_mem_type, selement, sel_analyzed, sel_stats, cb_info);
ret = st_cb_transfer_selement_generic(selement, sel_analyzed, sel_stats, cb_info);
break;
default:
/* Unknown? Report error. */
ST_CB_PRINT(ST_CB_ERR, "sef_cb_sf_transfer_dsi_u: bad flags", selement, sel_analyzed, sel_stats, cb_info);
ret = EFAULT;
break;
}
return ret;
}
/*===========================================================================*
* sef_cb_sf_transfer_typename *
*===========================================================================*/
int sef_cb_sf_transfer_typename(_magic_selement_t *selement, _magic_sel_analyzed_t *sel_analyzed, _magic_sel_stats_t *sel_stats, struct st_cb_info *cb_info) {
const char *typename_key = ST_TYPE_NAME_KEY(selement->type);
if(ST_TYPE_NAME_MATCH(sef_sf_typename_keys[dsi_u_idx],typename_key))
{
return sef_cb_sf_transfer_dsi_u(selement, sel_analyzed, sel_stats, cb_info);
}
return ST_CB_NOT_PROCESSED;
}
/*===========================================================================*
* _magic_ds_st_init *
*===========================================================================*/
void _magic_ds_st_init(void)
{
st_register_typename_keys(sef_sf_typename_keys);
st_setcb_selement_transfer(sef_cb_sf_transfer_typename, ST_CB_TYPE_TYPENAME);
}

View file

@ -0,0 +1,103 @@
#include <assert.h>
#include <string.h>
#include <unistd.h>
#include <sys/mman.h>
#include <minix/syslib.h>
#include <minix/sysutil.h>
#include <magic.h>
#include <magic_mem.h>
#include <st/state_transfer.h>
#include <st/special.h>
void *_magic_real_alloc_contig(size_t len, int flags, uint32_t *phys);
int _magic_real_free_contig(void *addr, size_t len);
static char* _magic_generic_debug_header(void)
{
return (char*) "[DEBUG]";
}
/*===========================================================================*
* _magic_state_transfer *
*===========================================================================*/
int _magic_state_transfer(sef_init_info_t *info)
{
st_init_info_t st_info;
/* Convert SEF flags into ST flags. */
st_info.flags = 0;
if (info->flags & SEF_LU_ASR)
st_info.flags |= ST_LU_ASR;
if (info->flags & SEF_LU_NOMMAP)
st_info.flags |= ST_LU_NOMMAP;
st_info.init_buff_start = info->init_buff_start;
st_info.init_buff_cleanup_start = info->init_buff_cleanup_start;
st_info.init_buff_len = info->init_buff_len;
/* Transmit sef_init_info opaquely to the state transfer framework. */
st_info.info_opaque = (void *) (info);
/* Add the OS callbacks. */
st_info.st_cbs_os.panic = &(panic); /* panic() callback. */
st_info.st_cbs_os.old_state_table_lookup = &(sef_old_state_table_lookup_opaque); /* old_state_table_lookup() callback. */
st_info.st_cbs_os.copy_state_region = &(sef_copy_state_region_opaque); /* copy_state_region() callback. */
st_info.st_cbs_os.alloc_contig = &(_magic_real_alloc_contig); /* alloc_contig() callback. */
st_info.st_cbs_os.free_contig = &(_magic_real_free_contig); /* free_contig() callback. */
st_info.st_cbs_os.debug_header = &(_magic_generic_debug_header); /* debug_header() callback. */
return st_state_transfer(&st_info);
}
/*===========================================================================*
* _magic_dump_eval_bool *
*===========================================================================*/
void _magic_dump_eval_bool(char *expr)
{
extern char *sef_lu_state_eval;
char result;
int print_style;
(void)(result);
print_style = magic_eval_get_print_style();
magic_eval_set_print_style(MAGIC_EVAL_PRINT_STYLE_ALL);
magic_eval_bool(sef_lu_state_eval, &result);
magic_eval_set_print_style(print_style);
}
/*===========================================================================*
* _magic_real_alloc_contig *
*===========================================================================*/
void *_magic_real_alloc_contig(size_t len, int flags, uint32_t *phys)
{
return magic_real_mmap(NULL, len, PROT_READ|PROT_WRITE,
MAP_ANONYMOUS|MAP_PRIVATE, -1, 0);
}
/*===========================================================================*
* _magic_real_free_contig *
*===========================================================================*/
int _magic_real_free_contig(void *addr, size_t len)
{
return munmap(addr, len);
}
/*===========================================================================*
* _magic_real_brk *
*===========================================================================*/
int _magic_real_brk(char *newbrk)
{
return magic_real_brk(newbrk);
}
/*===========================================================================*
* _magic_real_mmap *
*===========================================================================*/
void* _magic_real_mmap(void *buf, size_t len, int prot, int flags, int fd, off_t offset)
{
return magic_real_mmap(buf, len, prot, flags, fd, offset);
}
/*===========================================================================*
* _magic_real_munmap *
*===========================================================================*/
int _magic_real_munmap(void *addr, size_t length)
{
return magic_real_munmap(addr, length);
}