Import magic library from llvm-apps
Change-Id: Icfbcfae6afc731a23e71448a7a5d0045b2c219e5
This commit is contained in:
parent
3e457fe321
commit
0acd3f1ae0
41 changed files with 20304 additions and 0 deletions
940
minix/llvm/include/common/ut/uthash.h
Normal file
940
minix/llvm/include/common/ut/uthash.h
Normal 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 */
|
728
minix/llvm/include/common/ut/utlist.h
Normal file
728
minix/llvm/include/common/ut/utlist.h
Normal 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
1209
minix/llvm/include/magic.h
Normal file
File diff suppressed because it is too large
Load diff
427
minix/llvm/include/magic_analysis.h
Normal file
427
minix/llvm/include/magic_analysis.h
Normal 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 */
|
||||||
|
|
11
minix/llvm/include/magic_asr.h
Normal file
11
minix/llvm/include/magic_asr.h
Normal 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();
|
188
minix/llvm/include/magic_def.h
Normal file
188
minix/llvm/include/magic_def.h
Normal 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
|
||||||
|
|
25
minix/llvm/include/magic_eval.h
Normal file
25
minix/llvm/include/magic_eval.h
Normal 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
|
||||||
|
|
74
minix/llvm/include/magic_eval_lib.h
Normal file
74
minix/llvm/include/magic_eval_lib.h
Normal 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
|
||||||
|
|
284
minix/llvm/include/magic_mem.h
Normal file
284
minix/llvm/include/magic_mem.h
Normal 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
|
||||||
|
|
100
minix/llvm/include/magic_range.h
Normal file
100
minix/llvm/include/magic_range.h
Normal 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 */
|
19
minix/llvm/include/magic_rcu.h
Normal file
19
minix/llvm/include/magic_rcu.h
Normal 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 */
|
28
minix/llvm/include/magic_real_mem.h
Normal file
28
minix/llvm/include/magic_real_mem.h
Normal 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
|
||||||
|
|
53
minix/llvm/include/magic_selement.h
Normal file
53
minix/llvm/include/magic_selement.h
Normal 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 */
|
181
minix/llvm/include/magic_sentry.h
Normal file
181
minix/llvm/include/magic_sentry.h
Normal 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 */
|
147
minix/llvm/include/magic_splay_tree.h
Normal file
147
minix/llvm/include/magic_splay_tree.h
Normal 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 */
|
||||||
|
|
312
minix/llvm/include/magic_structs.h
Normal file
312
minix/llvm/include/magic_structs.h
Normal 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 */
|
127
minix/llvm/include/st/callback.h
Normal file
127
minix/llvm/include/st/callback.h
Normal 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 */
|
28
minix/llvm/include/st/cb_template.h
Normal file
28
minix/llvm/include/st/cb_template.h
Normal 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
|
60
minix/llvm/include/st/metadata_transfer.h
Normal file
60
minix/llvm/include/st/metadata_transfer.h
Normal 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 */
|
39
minix/llvm/include/st/os_callback.h
Normal file
39
minix/llvm/include/st/os_callback.h
Normal 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 */
|
34
minix/llvm/include/st/private.h
Normal file
34
minix/llvm/include/st/private.h
Normal 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 */
|
10
minix/llvm/include/st/special.h
Normal file
10
minix/llvm/include/st/special.h
Normal 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 */
|
362
minix/llvm/include/st/state_transfer.h
Normal file
362
minix/llvm/include/st/state_transfer.h
Normal 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 */
|
54
minix/llvm/include/st/typedefs.h
Normal file
54
minix/llvm/include/st/typedefs.h
Normal 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 */
|
80
minix/llvm/static/Makefile.settings
Normal file
80
minix/llvm/static/Makefile.settings
Normal 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
|
29
minix/llvm/static/magic/Makefile
Normal file
29
minix/llvm/static/magic/Makefile
Normal 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 $@
|
||||||
|
|
57
minix/llvm/static/magic/Makefile.inc
Normal file
57
minix/llvm/static/magic/Makefile.inc
Normal 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)
|
11
minix/llvm/static/magic/Makefile.magic_st
Normal file
11
minix/llvm/static/magic/Makefile.magic_st
Normal 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
|
||||||
|
|
2585
minix/llvm/static/magic/magic.c
Normal file
2585
minix/llvm/static/magic/magic.c
Normal file
File diff suppressed because it is too large
Load diff
1065
minix/llvm/static/magic/magic_analysis.c
Normal file
1065
minix/llvm/static/magic/magic_analysis.c
Normal file
File diff suppressed because it is too large
Load diff
129
minix/llvm/static/magic/magic_asr.c
Normal file
129
minix/llvm/static/magic/magic_asr.c
Normal 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);
|
||||||
|
}
|
||||||
|
}
|
216
minix/llvm/static/magic/magic_eval.c
Normal file
216
minix/llvm/static/magic/magic_eval.c
Normal 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;
|
||||||
|
}
|
||||||
|
|
1159
minix/llvm/static/magic/magic_eval_lib.c
Normal file
1159
minix/llvm/static/magic/magic_eval_lib.c
Normal file
File diff suppressed because it is too large
Load diff
2108
minix/llvm/static/magic/magic_mem.c
Normal file
2108
minix/llvm/static/magic/magic_mem.c
Normal file
File diff suppressed because it is too large
Load diff
321
minix/llvm/static/magic/magic_range.c
Normal file
321
minix/llvm/static/magic/magic_range.c
Normal 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);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
935
minix/llvm/static/magic/magic_selement.c
Normal file
935
minix/llvm/static/magic/magic_selement.c
Normal 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;
|
||||||
|
}
|
||||||
|
|
919
minix/llvm/static/magic/magic_sentry.c
Normal file
919
minix/llvm/static/magic/magic_sentry.c
Normal 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;
|
||||||
|
}
|
||||||
|
|
523
minix/llvm/static/magic/magic_splay_tree.c
Normal file
523
minix/llvm/static/magic/magic_splay_tree.c
Normal 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;
|
||||||
|
}
|
||||||
|
|
4542
minix/llvm/static/magic/magic_st.c
Normal file
4542
minix/llvm/static/magic/magic_st.c
Normal file
File diff suppressed because it is too large
Load diff
82
minix/llvm/static/magic/minix/magic_ds.c
Normal file
82
minix/llvm/static/magic/minix/magic_ds.c
Normal 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);
|
||||||
|
}
|
||||||
|
|
103
minix/llvm/static/magic/minix/magic_util.c
Normal file
103
minix/llvm/static/magic/minix/magic_util.c
Normal 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);
|
||||||
|
}
|
Loading…
Reference in a new issue