xref: /minix3/minix/lib/libmagicrt/magic_st.c (revision b2ed49a5d83e311ee0fa9e5ff613639b1bf77aaf)
1*b2ed49a5SDavid van Moolenbroek #include <magic.h>
2*b2ed49a5SDavid van Moolenbroek #include <magic_mem.h>
3*b2ed49a5SDavid van Moolenbroek #include <magic_analysis.h>
4*b2ed49a5SDavid van Moolenbroek #include <magic_asr.h>
5*b2ed49a5SDavid van Moolenbroek #include <stdarg.h>
6*b2ed49a5SDavid van Moolenbroek #include <st/state_transfer.h>
7*b2ed49a5SDavid van Moolenbroek #include <st/metadata_transfer.h>
8*b2ed49a5SDavid van Moolenbroek #include <st/typedefs.h>
9*b2ed49a5SDavid van Moolenbroek #include <st/private.h>
10*b2ed49a5SDavid van Moolenbroek 
11*b2ed49a5SDavid van Moolenbroek #define printf _magic_printf
12*b2ed49a5SDavid van Moolenbroek 
13*b2ed49a5SDavid van Moolenbroek #ifdef __MINIX
14*b2ed49a5SDavid van Moolenbroek EXTERN endpoint_t sef_self_endpoint;
15*b2ed49a5SDavid van Moolenbroek #else
16*b2ed49a5SDavid van Moolenbroek #define DO_SKIP_ENVIRON_HACK 1
17*b2ed49a5SDavid van Moolenbroek #define TODO_DSENTRY_PARENT_NAME_BUG 1
18*b2ed49a5SDavid van Moolenbroek #define DO_SKIP_UNPAIRED_PTR_TARGETS 1
19*b2ed49a5SDavid van Moolenbroek #endif
20*b2ed49a5SDavid van Moolenbroek 
21*b2ed49a5SDavid van Moolenbroek #define DO_SKIP_INVARIANTS_VIOLATIONS 0
22*b2ed49a5SDavid van Moolenbroek 
23*b2ed49a5SDavid van Moolenbroek PRIVATE st_alloc_pages *st_alloc_pages_current = NULL;
24*b2ed49a5SDavid van Moolenbroek PRIVATE size_t st_alloc_buff_available = 0;
25*b2ed49a5SDavid van Moolenbroek PRIVATE char *st_alloc_buff_pt = NULL;
26*b2ed49a5SDavid van Moolenbroek PRIVATE char *st_pre_allocated_page_pt = NULL;
27*b2ed49a5SDavid van Moolenbroek PRIVATE struct _magic_dsentry *st_dsentry_buff = NULL;
28*b2ed49a5SDavid van Moolenbroek PRIVATE void *st_data_buff = NULL;
29*b2ed49a5SDavid van Moolenbroek PRIVATE unsigned st_num_type_transformations = 0;
30*b2ed49a5SDavid van Moolenbroek 
31*b2ed49a5SDavid van Moolenbroek /* Magic variables and counterparts. */
32*b2ed49a5SDavid van Moolenbroek struct _magic_vars_t st_remote_magic_vars, st_cached_magic_vars;
33*b2ed49a5SDavid van Moolenbroek struct _magic_vars_t *st_local_magic_vars_ptr = &_magic_vars_buff;
34*b2ed49a5SDavid van Moolenbroek st_counterparts_t st_counterparts;
35*b2ed49a5SDavid van Moolenbroek 
36*b2ed49a5SDavid van Moolenbroek /* Private variables. */
37*b2ed49a5SDavid van Moolenbroek PRIVATE int st_init_done = FALSE;
38*b2ed49a5SDavid van Moolenbroek PRIVATE int st_policies = ST_POLICIES_DEFAULT;
39*b2ed49a5SDavid van Moolenbroek PRIVATE double st_unpaired_types_ratio = ST_UNPAIRED_TYPES_RATIO_DEFAULT;
40*b2ed49a5SDavid van Moolenbroek PRIVATE double st_unpaired_struct_types_ratio = ST_UNPAIRED_STRUCT_TYPES_RATIO_DEFAULT;
41*b2ed49a5SDavid van Moolenbroek 
42*b2ed49a5SDavid van Moolenbroek /* Forward declarations. */
43*b2ed49a5SDavid van Moolenbroek PRIVATE INLINE int default_transfer_selement_sel_cb(_magic_selement_t *selement, _magic_sel_analyzed_t *sel_analyzed, _magic_sel_stats_t *sel_stats, struct st_cb_info *cb_info);
44*b2ed49a5SDavid van Moolenbroek 
45*b2ed49a5SDavid van Moolenbroek /* State transfer callbacks. */
46*b2ed49a5SDavid van Moolenbroek 
47*b2ed49a5SDavid van Moolenbroek PRIVATE struct st_cbs_t st_cbs = {
48*b2ed49a5SDavid van Moolenbroek     ST_CB_PAGES_ALLOCATE_DEFAULT,
49*b2ed49a5SDavid van Moolenbroek     ST_CB_PAGES_FREE_DEFAULT,
50*b2ed49a5SDavid van Moolenbroek     ST_CB_STATE_CLEANUP_DEFAULT,
51*b2ed49a5SDavid van Moolenbroek     ST_CB_STATE_CHECKING_DEFAULT,
52*b2ed49a5SDavid van Moolenbroek     ST_CB_SELEMENT_MAP_DEFAULT,
53*b2ed49a5SDavid van Moolenbroek     ST_CB_SELEMENT_TRANSFER_EMPTY
54*b2ed49a5SDavid van Moolenbroek };
55*b2ed49a5SDavid van Moolenbroek 
56*b2ed49a5SDavid van Moolenbroek /* OS dependent callbacks. */
57*b2ed49a5SDavid van Moolenbroek PRIVATE struct st_cbs_os_t st_cbs_os = {
58*b2ed49a5SDavid van Moolenbroek     ST_CB_OS_PANIC_EMPTY,
59*b2ed49a5SDavid van Moolenbroek     ST_CB_OS_OLD_STATE_TABLE_LOOKUP_EMPTY,
60*b2ed49a5SDavid van Moolenbroek     ST_CB_OS_COPY_STATE_REGION_EMPTY,
61*b2ed49a5SDavid van Moolenbroek     ST_CB_OS_ALLOC_CONTIG_EMPTY,
62*b2ed49a5SDavid van Moolenbroek     ST_CB_OS_FREE_CONTIG_EMPTY,
63*b2ed49a5SDavid van Moolenbroek     ST_CB_OS_DEBUG_HEADER_EMPTY
64*b2ed49a5SDavid van Moolenbroek };
65*b2ed49a5SDavid van Moolenbroek 
66*b2ed49a5SDavid van Moolenbroek /* State transfer prototypes for st_receive(). */
67*b2ed49a5SDavid van Moolenbroek PUBLIC void do_st_before_receive(void);
68*b2ed49a5SDavid van Moolenbroek 
69*b2ed49a5SDavid van Moolenbroek /* Callback setters */
70*b2ed49a5SDavid van Moolenbroek 
st_setcb_pages_allocate(st_cb_pages_allocate_t cb)71*b2ed49a5SDavid van Moolenbroek PUBLIC void st_setcb_pages_allocate (st_cb_pages_allocate_t cb)
72*b2ed49a5SDavid van Moolenbroek {
73*b2ed49a5SDavid van Moolenbroek   assert(cb != NULL);
74*b2ed49a5SDavid van Moolenbroek   st_cbs.st_cb_pages_allocate = cb;
75*b2ed49a5SDavid van Moolenbroek }
76*b2ed49a5SDavid van Moolenbroek 
st_setcb_pages_free(st_cb_pages_free_t cb)77*b2ed49a5SDavid van Moolenbroek PUBLIC void st_setcb_pages_free (st_cb_pages_free_t cb)
78*b2ed49a5SDavid van Moolenbroek {
79*b2ed49a5SDavid van Moolenbroek   assert(cb != NULL);
80*b2ed49a5SDavid van Moolenbroek   st_cbs.st_cb_pages_free = cb;
81*b2ed49a5SDavid van Moolenbroek }
82*b2ed49a5SDavid van Moolenbroek 
st_setcb_state_cleanup(st_cb_state_cleanup_t cb)83*b2ed49a5SDavid van Moolenbroek PUBLIC void st_setcb_state_cleanup (st_cb_state_cleanup_t cb)
84*b2ed49a5SDavid van Moolenbroek {
85*b2ed49a5SDavid van Moolenbroek   assert(cb != NULL);
86*b2ed49a5SDavid van Moolenbroek   st_cbs.st_cb_state_cleanup = cb;
87*b2ed49a5SDavid van Moolenbroek   magic_setcb_sentries_analyze_pre(cb);
88*b2ed49a5SDavid van Moolenbroek }
89*b2ed49a5SDavid van Moolenbroek 
st_setcb_state_checking(st_cb_state_checking_t cb)90*b2ed49a5SDavid van Moolenbroek PUBLIC void st_setcb_state_checking (st_cb_state_checking_t cb)
91*b2ed49a5SDavid van Moolenbroek {
92*b2ed49a5SDavid van Moolenbroek   assert(cb != NULL);
93*b2ed49a5SDavid van Moolenbroek   st_cbs.st_cb_state_checking = cb;
94*b2ed49a5SDavid van Moolenbroek }
95*b2ed49a5SDavid van Moolenbroek 
st_setcb_selement_map(st_cb_selement_map_t cb)96*b2ed49a5SDavid van Moolenbroek PUBLIC void st_setcb_selement_map(st_cb_selement_map_t cb)
97*b2ed49a5SDavid van Moolenbroek {
98*b2ed49a5SDavid van Moolenbroek   assert(cb != NULL);
99*b2ed49a5SDavid van Moolenbroek   st_cbs.st_cb_selement_map = cb;
100*b2ed49a5SDavid van Moolenbroek }
101*b2ed49a5SDavid van Moolenbroek 
st_setcb_selement_transfer(st_cb_selement_transfer_t cb,int flags)102*b2ed49a5SDavid van Moolenbroek PUBLIC void st_setcb_selement_transfer(st_cb_selement_transfer_t cb, int flags)
103*b2ed49a5SDavid van Moolenbroek {
104*b2ed49a5SDavid van Moolenbroek     int i, j;
105*b2ed49a5SDavid van Moolenbroek     for (i = 0 ; i < NUM_CB_ARRAYS ; i++) {
106*b2ed49a5SDavid van Moolenbroek         if (i & flags) {
107*b2ed49a5SDavid van Moolenbroek             int is_registered = FALSE;
108*b2ed49a5SDavid van Moolenbroek             for (j = 0; j < MAX_NUM_CBS ; j++) {
109*b2ed49a5SDavid van Moolenbroek                 if (st_cbs.st_cb_selement_transfer[i][j] == NULL) {
110*b2ed49a5SDavid van Moolenbroek                     st_cbs.st_cb_selement_transfer[i][j] = cb;
111*b2ed49a5SDavid van Moolenbroek                     is_registered = TRUE;
112*b2ed49a5SDavid van Moolenbroek                     break;
113*b2ed49a5SDavid van Moolenbroek                 }
114*b2ed49a5SDavid van Moolenbroek             }
115*b2ed49a5SDavid van Moolenbroek             assert(is_registered && "Number of registered callbacks exceeds MAX_NUM_CBS");
116*b2ed49a5SDavid van Moolenbroek         }
117*b2ed49a5SDavid van Moolenbroek     }
118*b2ed49a5SDavid van Moolenbroek }
119*b2ed49a5SDavid van Moolenbroek 
120*b2ed49a5SDavid van Moolenbroek /* OS Callback setters. */
121*b2ed49a5SDavid van Moolenbroek 
st_setcb_os_panic(st_cb_os_panic_t cb)122*b2ed49a5SDavid van Moolenbroek PUBLIC void st_setcb_os_panic(st_cb_os_panic_t cb)
123*b2ed49a5SDavid van Moolenbroek {
124*b2ed49a5SDavid van Moolenbroek     assert(cb != NULL && "No callback defined for panic().");
125*b2ed49a5SDavid van Moolenbroek     st_cbs_os.panic = cb;
126*b2ed49a5SDavid van Moolenbroek }
127*b2ed49a5SDavid van Moolenbroek 
st_setcb_os_old_state_table_lookup(st_cb_os_old_state_table_lookup_t cb)128*b2ed49a5SDavid van Moolenbroek PUBLIC void st_setcb_os_old_state_table_lookup(st_cb_os_old_state_table_lookup_t cb)
129*b2ed49a5SDavid van Moolenbroek {
130*b2ed49a5SDavid van Moolenbroek     assert(cb != NULL && "No callback defined for old_state_table_lookup().");
131*b2ed49a5SDavid van Moolenbroek     st_cbs_os.old_state_table_lookup = cb;
132*b2ed49a5SDavid van Moolenbroek }
133*b2ed49a5SDavid van Moolenbroek 
st_setcb_os_copy_state_region(st_cb_os_copy_state_region_t cb)134*b2ed49a5SDavid van Moolenbroek PUBLIC void st_setcb_os_copy_state_region(st_cb_os_copy_state_region_t cb)
135*b2ed49a5SDavid van Moolenbroek {
136*b2ed49a5SDavid van Moolenbroek     assert(cb != NULL && "No callback defined for copy_state_region().");
137*b2ed49a5SDavid van Moolenbroek     st_cbs_os.copy_state_region = cb;
138*b2ed49a5SDavid van Moolenbroek }
139*b2ed49a5SDavid van Moolenbroek 
st_setcb_os_alloc_contig(st_cb_os_alloc_contig_t cb)140*b2ed49a5SDavid van Moolenbroek PUBLIC void st_setcb_os_alloc_contig(st_cb_os_alloc_contig_t cb)
141*b2ed49a5SDavid van Moolenbroek {
142*b2ed49a5SDavid van Moolenbroek     assert(cb != NULL && "No callback defined for alloc_contig().");
143*b2ed49a5SDavid van Moolenbroek     st_cbs_os.alloc_contig = cb;
144*b2ed49a5SDavid van Moolenbroek }
145*b2ed49a5SDavid van Moolenbroek 
st_setcb_os_free_contig(st_cb_os_free_contig_t cb)146*b2ed49a5SDavid van Moolenbroek PUBLIC void st_setcb_os_free_contig(st_cb_os_free_contig_t cb)
147*b2ed49a5SDavid van Moolenbroek {
148*b2ed49a5SDavid van Moolenbroek     assert(cb != NULL && "No callback defined for free_contig().");
149*b2ed49a5SDavid van Moolenbroek     st_cbs_os.free_contig = cb;
150*b2ed49a5SDavid van Moolenbroek }
151*b2ed49a5SDavid van Moolenbroek 
st_setcb_os_debug_header(st_cb_os_debug_header_t cb)152*b2ed49a5SDavid van Moolenbroek PUBLIC void st_setcb_os_debug_header(st_cb_os_debug_header_t cb)
153*b2ed49a5SDavid van Moolenbroek {
154*b2ed49a5SDavid van Moolenbroek     assert(cb != NULL && "No callback defined for debug_header().");
155*b2ed49a5SDavid van Moolenbroek     st_cbs_os.debug_header = cb;
156*b2ed49a5SDavid van Moolenbroek }
157*b2ed49a5SDavid van Moolenbroek 
158*b2ed49a5SDavid van Moolenbroek 
st_setcb_os_all(struct st_cbs_os_t * cbs)159*b2ed49a5SDavid van Moolenbroek PUBLIC void st_setcb_os_all(struct st_cbs_os_t *cbs)
160*b2ed49a5SDavid van Moolenbroek {
161*b2ed49a5SDavid van Moolenbroek     st_setcb_os_panic(cbs->panic);
162*b2ed49a5SDavid van Moolenbroek     st_setcb_os_old_state_table_lookup(cbs->old_state_table_lookup);
163*b2ed49a5SDavid van Moolenbroek     st_setcb_os_copy_state_region(cbs->copy_state_region);
164*b2ed49a5SDavid van Moolenbroek     st_setcb_os_alloc_contig(cbs->alloc_contig);
165*b2ed49a5SDavid van Moolenbroek     st_setcb_os_free_contig(cbs->free_contig);
166*b2ed49a5SDavid van Moolenbroek     st_setcb_os_debug_header(cbs->debug_header);
167*b2ed49a5SDavid van Moolenbroek }
168*b2ed49a5SDavid van Moolenbroek 
169*b2ed49a5SDavid van Moolenbroek /* Status variables to be transfered at state transfer time. */
170*b2ed49a5SDavid van Moolenbroek PUBLIC int __st_before_receive_enabled = 0;
171*b2ed49a5SDavid van Moolenbroek PRIVATE int __st_before_receive_sc_max_cycles;
172*b2ed49a5SDavid van Moolenbroek PRIVATE int __st_before_receive_sc_max_violations;
173*b2ed49a5SDavid van Moolenbroek 
174*b2ed49a5SDavid van Moolenbroek /* Typedef registration and lookup */
175*b2ed49a5SDavid van Moolenbroek 
st_strcmp_wildcard(const char * with_wildcard,const char * without_wildcard)176*b2ed49a5SDavid van Moolenbroek int st_strcmp_wildcard(const char *with_wildcard, const char *without_wildcard)
177*b2ed49a5SDavid van Moolenbroek {
178*b2ed49a5SDavid van Moolenbroek     /* Note: this implementation only supports basic regexes with a '*'
179*b2ed49a5SDavid van Moolenbroek      * at the beginning or the end of the string.
180*b2ed49a5SDavid van Moolenbroek      */
181*b2ed49a5SDavid van Moolenbroek     const char *star = strchr(with_wildcard, '*');
182*b2ed49a5SDavid van Moolenbroek     if (star) {
183*b2ed49a5SDavid van Moolenbroek         if (star == with_wildcard) {
184*b2ed49a5SDavid van Moolenbroek             size_t len = strlen(with_wildcard+1);
185*b2ed49a5SDavid van Moolenbroek             size_t len_without_wildcard = strlen(without_wildcard);
186*b2ed49a5SDavid van Moolenbroek             const char *match_without_wildcard = without_wildcard+
187*b2ed49a5SDavid van Moolenbroek                 len_without_wildcard-len;
188*b2ed49a5SDavid van Moolenbroek             if (match_without_wildcard < without_wildcard) {
189*b2ed49a5SDavid van Moolenbroek                 return -1;
190*b2ed49a5SDavid van Moolenbroek             }
191*b2ed49a5SDavid van Moolenbroek             return strncmp(with_wildcard+1, match_without_wildcard, len);
192*b2ed49a5SDavid van Moolenbroek         }
193*b2ed49a5SDavid van Moolenbroek         return strncmp(with_wildcard, without_wildcard, star - with_wildcard);
194*b2ed49a5SDavid van Moolenbroek     }
195*b2ed49a5SDavid van Moolenbroek     return strcmp(with_wildcard, without_wildcard);
196*b2ed49a5SDavid van Moolenbroek }
197*b2ed49a5SDavid van Moolenbroek 
198*b2ed49a5SDavid van Moolenbroek const char *st_typename_noxfers[] =   { ST_TYPENAME_NO_TRANSFER_NAMES, NULL         };
199*b2ed49a5SDavid van Moolenbroek const char *st_typename_ixfers[] =    { ST_TYPENAME_IDENTITY_TRANSFER_NAMES, NULL   };
200*b2ed49a5SDavid van Moolenbroek const char *st_typename_cixfers[] =   { ST_TYPENAME_CIDENTITY_TRANSFER_NAMES, NULL  };
201*b2ed49a5SDavid van Moolenbroek const char *st_typename_pxfers[] =    { ST_TYPENAME_PTR_TRANSFER_NAMES, NULL        };
202*b2ed49a5SDavid van Moolenbroek const char *st_typename_sxfers[] =    { ST_TYPENAME_STRUCT_TRANSFER_NAMES, NULL     };
203*b2ed49a5SDavid van Moolenbroek const char *st_sentryname_ixfers[] =  { ST_SENTRYNAME_IDENTITY_TRANSFER_NAMES, NULL };
204*b2ed49a5SDavid van Moolenbroek const char *st_sentryname_cixfers[] = { ST_SENTRYNAME_CIDENTITY_TRANSFER_NAMES, NULL};
205*b2ed49a5SDavid van Moolenbroek const char *st_sentryname_pxfers[] =  { ST_SENTRYNAME_PTR_TRANSFER_NAMES, NULL      };
206*b2ed49a5SDavid van Moolenbroek 
207*b2ed49a5SDavid van Moolenbroek /* Exclude stack references in addition to the default sentry names from state transfer. */
208*b2ed49a5SDavid van Moolenbroek const char *st_sentryname_noxfers[] = {
209*b2ed49a5SDavid van Moolenbroek     ST_SENTRYNAME_NO_TRANSFER_NAMES,
210*b2ed49a5SDavid van Moolenbroek #define __X(R) #R   /* Stringify the symbol names. */
211*b2ed49a5SDavid van Moolenbroek     ST_STACK_REFS_INT_LIST,
212*b2ed49a5SDavid van Moolenbroek #if ST_STACK_REFS_CUSTOM_NUM > 0
213*b2ed49a5SDavid van Moolenbroek     ST_STACK_REFS_CUSTOM_LIST,
214*b2ed49a5SDavid van Moolenbroek #endif
215*b2ed49a5SDavid van Moolenbroek #undef __X
216*b2ed49a5SDavid van Moolenbroek     NULL };
217*b2ed49a5SDavid van Moolenbroek const char *st_sentryname_noxfers_mem[] = { ST_SENTRYNAME_NO_TRANSFER_MEM_NAMES, NULL };
218*b2ed49a5SDavid van Moolenbroek 
219*b2ed49a5SDavid van Moolenbroek /* Exclude the data segments of certain libs from state transfer. */
220*b2ed49a5SDavid van Moolenbroek const char *st_dsentry_lib_noxfer[] = {
221*b2ed49a5SDavid van Moolenbroek #ifdef ST_DSENTRYLIB_NO_TRANSFER_NAMES
222*b2ed49a5SDavid van Moolenbroek     ST_DSENTRYLIB_NO_TRANSFER_NAMES,
223*b2ed49a5SDavid van Moolenbroek #endif
224*b2ed49a5SDavid van Moolenbroek     NULL };
225*b2ed49a5SDavid van Moolenbroek 
226*b2ed49a5SDavid van Moolenbroek const char *st_typename_key_registrations[MAX_NUM_TYPENAMES];
227*b2ed49a5SDavid van Moolenbroek 
is_typename(const char * search_key,struct _magic_type * type)228*b2ed49a5SDavid van Moolenbroek static int is_typename(const char *search_key, struct _magic_type *type)
229*b2ed49a5SDavid van Moolenbroek {
230*b2ed49a5SDavid van Moolenbroek     unsigned int i;
231*b2ed49a5SDavid van Moolenbroek     /* We can't use a cached lookup result */
232*b2ed49a5SDavid van Moolenbroek     if (!st_strcmp_wildcard(search_key, type->name)) {
233*b2ed49a5SDavid van Moolenbroek         /* The name matches */
234*b2ed49a5SDavid van Moolenbroek         return TRUE;
235*b2ed49a5SDavid van Moolenbroek     }
236*b2ed49a5SDavid van Moolenbroek     for (i = 0 ; i < type->num_names ; i++) {
237*b2ed49a5SDavid van Moolenbroek         if(!st_strcmp_wildcard(search_key, type->names[i])) {
238*b2ed49a5SDavid van Moolenbroek             /* One of the typename names matches */
239*b2ed49a5SDavid van Moolenbroek             return TRUE;
240*b2ed49a5SDavid van Moolenbroek         }
241*b2ed49a5SDavid van Moolenbroek     }
242*b2ed49a5SDavid van Moolenbroek     /* No match is found */
243*b2ed49a5SDavid van Moolenbroek     return FALSE;
244*b2ed49a5SDavid van Moolenbroek }
245*b2ed49a5SDavid van Moolenbroek 
st_register_typename_key(const char * key)246*b2ed49a5SDavid van Moolenbroek PUBLIC void st_register_typename_key(const char *key)
247*b2ed49a5SDavid van Moolenbroek {
248*b2ed49a5SDavid van Moolenbroek     int i, is_registered = FALSE;
249*b2ed49a5SDavid van Moolenbroek     for(i = 0 ; i < MAX_NUM_TYPENAMES ; i++) {
250*b2ed49a5SDavid van Moolenbroek         if (st_typename_key_registrations[i] == NULL) {
251*b2ed49a5SDavid van Moolenbroek             st_typename_key_registrations[i] = key;
252*b2ed49a5SDavid van Moolenbroek             is_registered = TRUE;
253*b2ed49a5SDavid van Moolenbroek             break;
254*b2ed49a5SDavid van Moolenbroek         }
255*b2ed49a5SDavid van Moolenbroek     }
256*b2ed49a5SDavid van Moolenbroek     assert(is_registered && "Error, number of typename registrations > MAX_NUM_TYPENAMES.\n");
257*b2ed49a5SDavid van Moolenbroek }
258*b2ed49a5SDavid van Moolenbroek 
st_register_typename_keys(const char ** keys)259*b2ed49a5SDavid van Moolenbroek PUBLIC void st_register_typename_keys(const char **keys)
260*b2ed49a5SDavid van Moolenbroek {
261*b2ed49a5SDavid van Moolenbroek     int i = 0;
262*b2ed49a5SDavid van Moolenbroek     while (keys[i] != NULL) {
263*b2ed49a5SDavid van Moolenbroek         st_register_typename_key(keys[i]);
264*b2ed49a5SDavid van Moolenbroek         i++;
265*b2ed49a5SDavid van Moolenbroek     }
266*b2ed49a5SDavid van Moolenbroek }
267*b2ed49a5SDavid van Moolenbroek 
set_typename_key(struct _magic_type * type)268*b2ed49a5SDavid van Moolenbroek PRIVATE void set_typename_key(struct _magic_type *type)
269*b2ed49a5SDavid van Moolenbroek {
270*b2ed49a5SDavid van Moolenbroek     const char **registration = st_typename_key_registrations;
271*b2ed49a5SDavid van Moolenbroek 
272*b2ed49a5SDavid van Moolenbroek     while (*registration != NULL) {
273*b2ed49a5SDavid van Moolenbroek         if (is_typename(*registration, type)) {
274*b2ed49a5SDavid van Moolenbroek             type->ext = *registration;
275*b2ed49a5SDavid van Moolenbroek             break;
276*b2ed49a5SDavid van Moolenbroek         }
277*b2ed49a5SDavid van Moolenbroek         registration++;
278*b2ed49a5SDavid van Moolenbroek     }
279*b2ed49a5SDavid van Moolenbroek }
280*b2ed49a5SDavid van Moolenbroek 
register_typenames(void)281*b2ed49a5SDavid van Moolenbroek PRIVATE void register_typenames(void)
282*b2ed49a5SDavid van Moolenbroek {
283*b2ed49a5SDavid van Moolenbroek 
284*b2ed49a5SDavid van Moolenbroek     int i;
285*b2ed49a5SDavid van Moolenbroek 
286*b2ed49a5SDavid van Moolenbroek     /* Register typenames */
287*b2ed49a5SDavid van Moolenbroek     st_register_typename_keys(st_typename_noxfers);
288*b2ed49a5SDavid van Moolenbroek     st_register_typename_keys(st_typename_ixfers);
289*b2ed49a5SDavid van Moolenbroek     st_register_typename_keys(st_typename_cixfers);
290*b2ed49a5SDavid van Moolenbroek     st_register_typename_keys(st_typename_pxfers);
291*b2ed49a5SDavid van Moolenbroek     st_register_typename_keys(st_typename_sxfers);
292*b2ed49a5SDavid van Moolenbroek 
293*b2ed49a5SDavid van Moolenbroek     for(i = 0 ; i < _magic_types_num ; i++) {
294*b2ed49a5SDavid van Moolenbroek         set_typename_key(&_magic_types[i]);
295*b2ed49a5SDavid van Moolenbroek     }
296*b2ed49a5SDavid van Moolenbroek 
297*b2ed49a5SDavid van Moolenbroek }
298*b2ed49a5SDavid van Moolenbroek 
register_typenames_and_callbacks(void)299*b2ed49a5SDavid van Moolenbroek PRIVATE INLINE void register_typenames_and_callbacks(void)
300*b2ed49a5SDavid van Moolenbroek {
301*b2ed49a5SDavid van Moolenbroek 
302*b2ed49a5SDavid van Moolenbroek     static int st_is_registered = FALSE;
303*b2ed49a5SDavid van Moolenbroek     if(st_is_registered) {
304*b2ed49a5SDavid van Moolenbroek         return;
305*b2ed49a5SDavid van Moolenbroek     }
306*b2ed49a5SDavid van Moolenbroek 
307*b2ed49a5SDavid van Moolenbroek     register_typenames();
308*b2ed49a5SDavid van Moolenbroek 
309*b2ed49a5SDavid van Moolenbroek     st_setcb_selement_transfer(st_cb_transfer_sentry_default, ST_CB_TYPE_SENTRY);
310*b2ed49a5SDavid van Moolenbroek     st_setcb_selement_transfer(st_cb_transfer_typename_default, ST_CB_TYPE_TYPENAME);
311*b2ed49a5SDavid van Moolenbroek 
312*b2ed49a5SDavid van Moolenbroek     st_is_registered = TRUE;
313*b2ed49a5SDavid van Moolenbroek 
314*b2ed49a5SDavid van Moolenbroek }
315*b2ed49a5SDavid van Moolenbroek 
st_type_name_match_any(const char ** registered_type_name_keys,const char * key)316*b2ed49a5SDavid van Moolenbroek PRIVATE int st_type_name_match_any(const char **registered_type_name_keys,
317*b2ed49a5SDavid van Moolenbroek     const char *key)
318*b2ed49a5SDavid van Moolenbroek {
319*b2ed49a5SDavid van Moolenbroek     int i = 0;
320*b2ed49a5SDavid van Moolenbroek     while (registered_type_name_keys[i] != NULL) {
321*b2ed49a5SDavid van Moolenbroek         if (ST_TYPE_NAME_MATCH(registered_type_name_keys[i], key)) {
322*b2ed49a5SDavid van Moolenbroek             return TRUE;
323*b2ed49a5SDavid van Moolenbroek         }
324*b2ed49a5SDavid van Moolenbroek         i++;
325*b2ed49a5SDavid van Moolenbroek     }
326*b2ed49a5SDavid van Moolenbroek     return FALSE;
327*b2ed49a5SDavid van Moolenbroek }
328*b2ed49a5SDavid van Moolenbroek 
st_sentry_name_match_any(const char ** sentry_wildcard_names,const char * name)329*b2ed49a5SDavid van Moolenbroek PRIVATE int st_sentry_name_match_any(const char **sentry_wildcard_names,
330*b2ed49a5SDavid van Moolenbroek     const char *name)
331*b2ed49a5SDavid van Moolenbroek {
332*b2ed49a5SDavid van Moolenbroek     int i = 0;
333*b2ed49a5SDavid van Moolenbroek     while (sentry_wildcard_names[i] != NULL) {
334*b2ed49a5SDavid van Moolenbroek         if (ST_SENTRY_NAME_MATCH(sentry_wildcard_names[i], name)) {
335*b2ed49a5SDavid van Moolenbroek             return TRUE;
336*b2ed49a5SDavid van Moolenbroek         }
337*b2ed49a5SDavid van Moolenbroek         i++;
338*b2ed49a5SDavid van Moolenbroek     }
339*b2ed49a5SDavid van Moolenbroek     return FALSE;
340*b2ed49a5SDavid van Moolenbroek }
341*b2ed49a5SDavid van Moolenbroek 
st_dsentry_parent_name_match_any(const char ** wildcard_names,const char * name)342*b2ed49a5SDavid van Moolenbroek PRIVATE int st_dsentry_parent_name_match_any(const char **wildcard_names,
343*b2ed49a5SDavid van Moolenbroek     const char *name)
344*b2ed49a5SDavid van Moolenbroek {
345*b2ed49a5SDavid van Moolenbroek     int i = 0;
346*b2ed49a5SDavid van Moolenbroek     while (wildcard_names[i] != NULL) {
347*b2ed49a5SDavid van Moolenbroek         if (ST_DSENTRY_PARENT_NAME_MATCH(wildcard_names[i], name)) {
348*b2ed49a5SDavid van Moolenbroek             return TRUE;
349*b2ed49a5SDavid van Moolenbroek         }
350*b2ed49a5SDavid van Moolenbroek         i++;
351*b2ed49a5SDavid van Moolenbroek     }
352*b2ed49a5SDavid van Moolenbroek     return FALSE;
353*b2ed49a5SDavid van Moolenbroek }
354*b2ed49a5SDavid van Moolenbroek 
355*b2ed49a5SDavid van Moolenbroek /* Utilities. */
st_cb_print(int level,const char * msg,_magic_selement_t * selement,_magic_sel_analyzed_t * sel_analyzed,_magic_sel_stats_t * sel_stats,struct st_cb_info * cb_info)356*b2ed49a5SDavid van Moolenbroek PUBLIC void st_cb_print(int level, const char *msg, _magic_selement_t *selement, _magic_sel_analyzed_t *sel_analyzed, _magic_sel_stats_t *sel_stats, struct st_cb_info *cb_info)
357*b2ed49a5SDavid van Moolenbroek {
358*b2ed49a5SDavid van Moolenbroek     if (ST_CB_PRINT_LEVEL(level)) {
359*b2ed49a5SDavid van Moolenbroek         _magic_printf("[%s] %s. Current state element:\n",
360*b2ed49a5SDavid van Moolenbroek             ST_CB_LEVEL_TO_STR(level), msg);
361*b2ed49a5SDavid van Moolenbroek         MAGIC_SELEMENT_PRINT(selement, MAGIC_EXPAND_TYPE_STR);
362*b2ed49a5SDavid van Moolenbroek         _magic_printf("\n");
363*b2ed49a5SDavid van Moolenbroek         MAGIC_SEL_ANALYZED_PRINT(sel_analyzed, MAGIC_EXPAND_TYPE_STR);
364*b2ed49a5SDavid van Moolenbroek         _magic_printf("\n");
365*b2ed49a5SDavid van Moolenbroek         MAGIC_SEL_STATS_PRINT(sel_stats);
366*b2ed49a5SDavid van Moolenbroek         _magic_printf("\n\n");
367*b2ed49a5SDavid van Moolenbroek     }
368*b2ed49a5SDavid van Moolenbroek }
369*b2ed49a5SDavid van Moolenbroek 
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)370*b2ed49a5SDavid van Moolenbroek 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)
371*b2ed49a5SDavid van Moolenbroek {
372*b2ed49a5SDavid van Moolenbroek     magic_selement_type_cast(selement, ST_SEL_ANALYZE_FLAGS,
373*b2ed49a5SDavid van Moolenbroek             new_selement_type, sel_analyzed, sel_stats);
374*b2ed49a5SDavid van Moolenbroek     if (!ST_CB_FLAG(ST_CB_CHECK_ONLY)) {
375*b2ed49a5SDavid van Moolenbroek         cb_info->local_selement->type = new_local_selement_type;
376*b2ed49a5SDavid van Moolenbroek     }
377*b2ed49a5SDavid van Moolenbroek }
378*b2ed49a5SDavid van Moolenbroek 
379*b2ed49a5SDavid van Moolenbroek /* Stack management. */
380*b2ed49a5SDavid van Moolenbroek 
st_stack_refs_save_restore(char * stack_buff,int is_save)381*b2ed49a5SDavid van Moolenbroek PUBLIC void st_stack_refs_save_restore(char* stack_buff, int is_save)
382*b2ed49a5SDavid van Moolenbroek {
383*b2ed49a5SDavid van Moolenbroek     struct _magic_dsentry *prev_dsentry, *dsentry;
384*b2ed49a5SDavid van Moolenbroek     struct _magic_sentry* sentry;
385*b2ed49a5SDavid van Moolenbroek     struct st_stack_refs_buff *buff_ptr;
386*b2ed49a5SDavid van Moolenbroek     int i;
387*b2ed49a5SDavid van Moolenbroek 
388*b2ed49a5SDavid van Moolenbroek #define __X(P) P
389*b2ed49a5SDavid van Moolenbroek     extern int ST_STACK_REFS_INT_LIST;
390*b2ed49a5SDavid van Moolenbroek #undef __X
391*b2ed49a5SDavid van Moolenbroek #define __X(P) ((int *)&(P))
392*b2ed49a5SDavid van Moolenbroek     int* int_ptrs[] = { ST_STACK_REFS_INT_LIST, ST_STACK_REFS_CUSTOM_LIST };
393*b2ed49a5SDavid van Moolenbroek #undef __X
394*b2ed49a5SDavid van Moolenbroek 
395*b2ed49a5SDavid van Moolenbroek     assert((ST_STACK_REFS_NUM) == sizeof(int_ptrs)/sizeof(int_ptrs[0]));
396*b2ed49a5SDavid van Moolenbroek     assert(sizeof(int) == sizeof(void*));
397*b2ed49a5SDavid van Moolenbroek     buff_ptr = (struct st_stack_refs_buff*) stack_buff;
398*b2ed49a5SDavid van Moolenbroek 
399*b2ed49a5SDavid van Moolenbroek     /* Save. */
400*b2ed49a5SDavid van Moolenbroek     if (is_save) {
401*b2ed49a5SDavid van Moolenbroek         buff_ptr->first_stack_dsentry = _magic_first_stack_dsentry;
402*b2ed49a5SDavid van Moolenbroek         buff_ptr->last_stack_dsentry = _magic_last_stack_dsentry;
403*b2ed49a5SDavid van Moolenbroek         if (_magic_first_stack_dsentry) {
404*b2ed49a5SDavid van Moolenbroek             buff_ptr->first_stack_obdsentry_buff = *MAGIC_OBDSENTRY_FROM_DSENTRY(_magic_first_stack_dsentry);
405*b2ed49a5SDavid van Moolenbroek         }
406*b2ed49a5SDavid van Moolenbroek         memcpy(buff_ptr->stack_range, magic_stack_range, 2*sizeof(void*));
407*b2ed49a5SDavid van Moolenbroek         for (i = 0 ; i < ST_STACK_REFS_NUM ; i++) {
408*b2ed49a5SDavid van Moolenbroek             memcpy(&buff_ptr->stack_int_refs[i], int_ptrs[i], sizeof(int));
409*b2ed49a5SDavid van Moolenbroek         }
410*b2ed49a5SDavid van Moolenbroek         return;
411*b2ed49a5SDavid van Moolenbroek     }
412*b2ed49a5SDavid van Moolenbroek 
413*b2ed49a5SDavid van Moolenbroek     /* Restore. */
414*b2ed49a5SDavid van Moolenbroek     if (_magic_first_dsentry == _magic_last_stack_dsentry) {
415*b2ed49a5SDavid van Moolenbroek         _magic_first_dsentry = buff_ptr->last_stack_dsentry;
416*b2ed49a5SDavid van Moolenbroek     }
417*b2ed49a5SDavid van Moolenbroek     else {
418*b2ed49a5SDavid van Moolenbroek         MAGIC_DSENTRY_ITER(_magic_first_dsentry, prev_dsentry, dsentry, sentry,
419*b2ed49a5SDavid van Moolenbroek             if (MAGIC_DSENTRY_HAS_NEXT(dsentry)
420*b2ed49a5SDavid van Moolenbroek                 && MAGIC_DSENTRY_NEXT(dsentry) == _magic_last_stack_dsentry) {
421*b2ed49a5SDavid van Moolenbroek                 MAGIC_DSENTRY_NEXT(dsentry) = buff_ptr->last_stack_dsentry;
422*b2ed49a5SDavid van Moolenbroek                 break;
423*b2ed49a5SDavid van Moolenbroek             }
424*b2ed49a5SDavid van Moolenbroek         );
425*b2ed49a5SDavid van Moolenbroek     }
426*b2ed49a5SDavid van Moolenbroek 
427*b2ed49a5SDavid van Moolenbroek     _magic_first_stack_dsentry = buff_ptr->first_stack_dsentry;
428*b2ed49a5SDavid van Moolenbroek     _magic_last_stack_dsentry = buff_ptr->last_stack_dsentry;
429*b2ed49a5SDavid van Moolenbroek     if (_magic_first_stack_dsentry) {
430*b2ed49a5SDavid van Moolenbroek         *MAGIC_OBDSENTRY_FROM_DSENTRY(_magic_first_stack_dsentry) = buff_ptr->first_stack_obdsentry_buff;
431*b2ed49a5SDavid van Moolenbroek     }
432*b2ed49a5SDavid van Moolenbroek     memcpy(magic_stack_range, buff_ptr->stack_range, 2*sizeof(void*));
433*b2ed49a5SDavid van Moolenbroek     for (i = 0 ; i < ST_STACK_REFS_NUM ; i++) {
434*b2ed49a5SDavid van Moolenbroek         memcpy(int_ptrs[i], &buff_ptr->stack_int_refs[i], sizeof(int));
435*b2ed49a5SDavid van Moolenbroek     }
436*b2ed49a5SDavid van Moolenbroek }
437*b2ed49a5SDavid van Moolenbroek 
438*b2ed49a5SDavid van Moolenbroek /* Metadata management. */
st_add_special_mmapped_region(void * address,size_t size,const char * name)439*b2ed49a5SDavid van Moolenbroek PUBLIC int st_add_special_mmapped_region(void *address, size_t size,
440*b2ed49a5SDavid van Moolenbroek     const char* name)
441*b2ed49a5SDavid van Moolenbroek {
442*b2ed49a5SDavid van Moolenbroek     struct _magic_obdsentry* obdsentry;
443*b2ed49a5SDavid van Moolenbroek     char addr_name[24];
444*b2ed49a5SDavid van Moolenbroek 
445*b2ed49a5SDavid van Moolenbroek     if (!_magic_enabled) return OK;
446*b2ed49a5SDavid van Moolenbroek 
447*b2ed49a5SDavid van Moolenbroek     if (!name) {
448*b2ed49a5SDavid van Moolenbroek         snprintf(addr_name, sizeof(addr_name), "%%MMAP_0x%08x",
449*b2ed49a5SDavid van Moolenbroek           (unsigned int) address);
450*b2ed49a5SDavid van Moolenbroek         name = addr_name;
451*b2ed49a5SDavid van Moolenbroek     }
452*b2ed49a5SDavid van Moolenbroek     obdsentry = magic_create_obdsentry(address, MAGIC_VOID_TYPE,
453*b2ed49a5SDavid van Moolenbroek         size, MAGIC_STATE_MAP, name, NULL);
454*b2ed49a5SDavid van Moolenbroek     return obdsentry ? OK : EINVAL;
455*b2ed49a5SDavid van Moolenbroek }
456*b2ed49a5SDavid van Moolenbroek 
st_del_special_mmapped_region_by_addr(void * address)457*b2ed49a5SDavid van Moolenbroek PUBLIC int st_del_special_mmapped_region_by_addr(void *address)
458*b2ed49a5SDavid van Moolenbroek {
459*b2ed49a5SDavid van Moolenbroek     int ret;
460*b2ed49a5SDavid van Moolenbroek 
461*b2ed49a5SDavid van Moolenbroek     if (!_magic_enabled) return OK;
462*b2ed49a5SDavid van Moolenbroek 
463*b2ed49a5SDavid van Moolenbroek     ret = magic_destroy_obdsentry_by_addr(address);
464*b2ed49a5SDavid van Moolenbroek     if (ret < 0) {
465*b2ed49a5SDavid van Moolenbroek         return EINVAL;
466*b2ed49a5SDavid van Moolenbroek     }
467*b2ed49a5SDavid van Moolenbroek     return OK;
468*b2ed49a5SDavid van Moolenbroek }
469*b2ed49a5SDavid van Moolenbroek 
470*b2ed49a5SDavid van Moolenbroek /* Selement transfer callbacks. */
471*b2ed49a5SDavid van Moolenbroek 
transfer_walkable_sel_cb(_magic_selement_t * selement,_magic_sel_analyzed_t * sel_analyzed,_magic_sel_stats_t * sel_stats,struct st_cb_info * cb_info)472*b2ed49a5SDavid van Moolenbroek PRIVATE INLINE int transfer_walkable_sel_cb(_magic_selement_t *selement, _magic_sel_analyzed_t *sel_analyzed, _magic_sel_stats_t *sel_stats, struct st_cb_info *cb_info)
473*b2ed49a5SDavid van Moolenbroek {
474*b2ed49a5SDavid van Moolenbroek     /* Do nothing for complex type. process only its members, not the complex type itself */
475*b2ed49a5SDavid van Moolenbroek     return MAGIC_SENTRY_ANALYZE_CONTINUE;
476*b2ed49a5SDavid van Moolenbroek }
477*b2ed49a5SDavid van Moolenbroek 
transfer_try_raw_copy_sel_cb(_magic_selement_t * selement,struct st_cb_info * cb_info)478*b2ed49a5SDavid van Moolenbroek PRIVATE INLINE int transfer_try_raw_copy_sel_cb(_magic_selement_t *selement, struct st_cb_info *cb_info)
479*b2ed49a5SDavid van Moolenbroek {
480*b2ed49a5SDavid van Moolenbroek     /* Only do raw copying if there are no type transformations. */
481*b2ed49a5SDavid van Moolenbroek     if ((selement->type->num_child_types == 0 && selement->type->size == cb_info->local_selement->type->size) || selement->type == cb_info->local_selement->type || ST_TYPE_IS_CACHED_COUNTERPART(selement->type, cb_info->local_selement->type)) {
482*b2ed49a5SDavid van Moolenbroek         memcpy(cb_info->local_selement->address, selement->address, cb_info->local_selement->type->size);
483*b2ed49a5SDavid van Moolenbroek         return MAGIC_SENTRY_ANALYZE_SKIP_PATH;
484*b2ed49a5SDavid van Moolenbroek     }
485*b2ed49a5SDavid van Moolenbroek 
486*b2ed49a5SDavid van Moolenbroek     return MAGIC_SENTRY_ANALYZE_CONTINUE;
487*b2ed49a5SDavid van Moolenbroek }
488*b2ed49a5SDavid van Moolenbroek 
transfer_identity_sel_cb(_magic_selement_t * selement,_magic_sel_analyzed_t * sel_analyzed,_magic_sel_stats_t * sel_stats,struct st_cb_info * cb_info)489*b2ed49a5SDavid van Moolenbroek PRIVATE INLINE int transfer_identity_sel_cb(_magic_selement_t *selement, _magic_sel_analyzed_t *sel_analyzed, _magic_sel_stats_t *sel_stats, struct st_cb_info *cb_info)
490*b2ed49a5SDavid van Moolenbroek {
491*b2ed49a5SDavid van Moolenbroek     if (!ST_CB_FLAG(ST_CB_CHECK_ONLY)) {
492*b2ed49a5SDavid van Moolenbroek         /* First try to do raw copying, assuming there are no type transformations. */
493*b2ed49a5SDavid van Moolenbroek         if (transfer_try_raw_copy_sel_cb(selement, cb_info) == MAGIC_SENTRY_ANALYZE_SKIP_PATH)
494*b2ed49a5SDavid van Moolenbroek             return MAGIC_SENTRY_ANALYZE_SKIP_PATH;
495*b2ed49a5SDavid van Moolenbroek 
496*b2ed49a5SDavid van Moolenbroek #if CHECK_ASR && !FORCE_SOME_UNPAIRED_TYPES
497*b2ed49a5SDavid van Moolenbroek         if (cb_info->init_info->flags & ST_LU_ASR) {
498*b2ed49a5SDavid van Moolenbroek             st_cbs_os.panic("ASR should never get here!");
499*b2ed49a5SDavid van Moolenbroek         }
500*b2ed49a5SDavid van Moolenbroek #endif
501*b2ed49a5SDavid van Moolenbroek         if (selement->type->type_id == MAGIC_TYPE_UNION) {
502*b2ed49a5SDavid van Moolenbroek             ST_CB_PRINT(ST_CB_ERR, "uncaught ixfer union with type changes", selement, sel_analyzed, sel_stats, cb_info);
503*b2ed49a5SDavid van Moolenbroek             return EFAULT;
504*b2ed49a5SDavid van Moolenbroek         }
505*b2ed49a5SDavid van Moolenbroek         cb_info->st_cb_flags |= ST_CB_FORCE_IXFER;
506*b2ed49a5SDavid van Moolenbroek         return MAGIC_SENTRY_ANALYZE_CONTINUE;
507*b2ed49a5SDavid van Moolenbroek     }
508*b2ed49a5SDavid van Moolenbroek     return MAGIC_SENTRY_ANALYZE_SKIP_PATH;
509*b2ed49a5SDavid van Moolenbroek }
510*b2ed49a5SDavid van Moolenbroek 
transfer_cond_identity_sel_cb(_magic_selement_t * selement,_magic_sel_analyzed_t * sel_analyzed,_magic_sel_stats_t * sel_stats,struct st_cb_info * cb_info)511*b2ed49a5SDavid van Moolenbroek PRIVATE INLINE int transfer_cond_identity_sel_cb(_magic_selement_t *selement, _magic_sel_analyzed_t *sel_analyzed, _magic_sel_stats_t *sel_stats, struct st_cb_info *cb_info)
512*b2ed49a5SDavid van Moolenbroek {
513*b2ed49a5SDavid van Moolenbroek     int r;
514*b2ed49a5SDavid van Moolenbroek     int saved_flags = cb_info->st_cb_flags;
515*b2ed49a5SDavid van Moolenbroek     cb_info->st_cb_flags &= ~ST_CB_PRINT_ERR;
516*b2ed49a5SDavid van Moolenbroek     r = default_transfer_selement_sel_cb(selement, sel_analyzed, sel_stats, cb_info);
517*b2ed49a5SDavid van Moolenbroek     cb_info->st_cb_flags = saved_flags;
518*b2ed49a5SDavid van Moolenbroek     if (r < 0) {
519*b2ed49a5SDavid van Moolenbroek         ST_CB_PRINT(ST_CB_DBG, "conditional ixfer resorting to ixfer", selement, sel_analyzed, sel_stats, cb_info);
520*b2ed49a5SDavid van Moolenbroek         return transfer_identity_sel_cb(selement, sel_analyzed, sel_stats, cb_info);
521*b2ed49a5SDavid van Moolenbroek     }
522*b2ed49a5SDavid van Moolenbroek     return r;
523*b2ed49a5SDavid van Moolenbroek }
524*b2ed49a5SDavid van Moolenbroek 
transfer_nonptr_sel_cb(_magic_selement_t * selement,_magic_sel_analyzed_t * sel_analyzed,_magic_sel_stats_t * sel_stats,struct st_cb_info * cb_info)525*b2ed49a5SDavid van Moolenbroek PRIVATE INLINE int transfer_nonptr_sel_cb(_magic_selement_t *selement, _magic_sel_analyzed_t *sel_analyzed, _magic_sel_stats_t *sel_stats, struct st_cb_info *cb_info)
526*b2ed49a5SDavid van Moolenbroek {
527*b2ed49a5SDavid van Moolenbroek     if (sel_analyzed->flags & MAGIC_SEL_FOUND_VIOLATIONS) {
528*b2ed49a5SDavid van Moolenbroek         ST_CB_PRINT(ST_CB_ERR, "uncaught non-ptr with violations", selement, sel_analyzed, sel_stats, cb_info);
529*b2ed49a5SDavid van Moolenbroek         return EFAULT;
530*b2ed49a5SDavid van Moolenbroek     }
531*b2ed49a5SDavid van Moolenbroek     return transfer_identity_sel_cb(selement, sel_analyzed, sel_stats, cb_info);
532*b2ed49a5SDavid van Moolenbroek }
533*b2ed49a5SDavid van Moolenbroek 
transfer_ptr_sel_with_trg_cb(_magic_selement_t * selement,_magic_sel_analyzed_t * sel_analyzed,_magic_sel_stats_t * sel_stats,struct st_cb_info * cb_info)534*b2ed49a5SDavid van Moolenbroek PRIVATE int transfer_ptr_sel_with_trg_cb(_magic_selement_t *selement, _magic_sel_analyzed_t *sel_analyzed, _magic_sel_stats_t *sel_stats, struct st_cb_info *cb_info)
535*b2ed49a5SDavid van Moolenbroek {
536*b2ed49a5SDavid van Moolenbroek     int trg_flags, trg_extf_flags, trg_transferred, trg_paired;
537*b2ed49a5SDavid van Moolenbroek     _magic_selement_t cached_trg_selement, local_trg_selement;
538*b2ed49a5SDavid van Moolenbroek     void **local_selement_address = cb_info->local_selement->address;
539*b2ed49a5SDavid van Moolenbroek     int r;
540*b2ed49a5SDavid van Moolenbroek 
541*b2ed49a5SDavid van Moolenbroek     r = lookup_trg_info(selement, sel_analyzed, sel_stats, cb_info, &cached_trg_selement, &local_trg_selement);
542*b2ed49a5SDavid van Moolenbroek     if (r != OK) {
543*b2ed49a5SDavid van Moolenbroek         return r;
544*b2ed49a5SDavid van Moolenbroek     }
545*b2ed49a5SDavid van Moolenbroek 
546*b2ed49a5SDavid van Moolenbroek     trg_flags = sel_analyzed->u.ptr.trg_flags;
547*b2ed49a5SDavid van Moolenbroek     trg_extf_flags = MAGIC_STATE_FLAGS_TO_EXTF(trg_flags);
548*b2ed49a5SDavid van Moolenbroek     trg_transferred = (trg_extf_flags & (ST_NEEDS_TRANSFER | ST_TRANSFER_DONE));
549*b2ed49a5SDavid van Moolenbroek     trg_paired = (local_trg_selement.type != NULL);
550*b2ed49a5SDavid van Moolenbroek 
551*b2ed49a5SDavid van Moolenbroek     if (!trg_transferred && trg_paired && (trg_extf_flags & ST_ON_PTRXFER_CASCADE)) {
552*b2ed49a5SDavid van Moolenbroek         /* Propagate transfer on the target. */
553*b2ed49a5SDavid van Moolenbroek         if (cached_trg_selement.sentry && !(trg_extf_flags & ST_NEEDS_TRANSFER)) {
554*b2ed49a5SDavid van Moolenbroek             ST_CB_PRINT(ST_CB_DBG, "ptr lookup results in cascade transfer for the target", selement, sel_analyzed, sel_stats, cb_info);
555*b2ed49a5SDavid van Moolenbroek             st_set_status_by_sentry_id(ST_NEEDS_TRANSFER, ST_OP_ADD, MAGIC_SENTRY_ID(cached_trg_selement.sentry));
556*b2ed49a5SDavid van Moolenbroek         }
557*b2ed49a5SDavid van Moolenbroek         /* Force code below to transfer the pointer normally. */
558*b2ed49a5SDavid van Moolenbroek         trg_transferred = TRUE;
559*b2ed49a5SDavid van Moolenbroek     }
560*b2ed49a5SDavid van Moolenbroek 
561*b2ed49a5SDavid van Moolenbroek     if (trg_transferred && trg_paired) {
562*b2ed49a5SDavid van Moolenbroek         *local_selement_address = local_trg_selement.address;
563*b2ed49a5SDavid van Moolenbroek     }
564*b2ed49a5SDavid van Moolenbroek     else if (trg_extf_flags & ST_ON_PTRXFER_SET_NULL) {
565*b2ed49a5SDavid van Moolenbroek         ST_CB_PRINT(ST_CB_DBG, "ptr lookup results in forcefully setting ptr to NULL", selement, sel_analyzed, sel_stats, cb_info);
566*b2ed49a5SDavid van Moolenbroek         *local_selement_address = NULL;
567*b2ed49a5SDavid van Moolenbroek     }
568*b2ed49a5SDavid van Moolenbroek     else if(trg_extf_flags & ST_ON_PTRXFER_SET_DEFAULT) {
569*b2ed49a5SDavid van Moolenbroek         ST_CB_PRINT(ST_CB_DBG, "ptr lookup results in forcefully setting ptr to default value", selement, sel_analyzed, sel_stats, cb_info);
570*b2ed49a5SDavid van Moolenbroek         if (trg_flags & MAGIC_STATE_STRING) {
571*b2ed49a5SDavid van Moolenbroek             *((char**)local_selement_address) = __UNCONST("");
572*b2ed49a5SDavid van Moolenbroek         }
573*b2ed49a5SDavid van Moolenbroek         else {
574*b2ed49a5SDavid van Moolenbroek             *local_selement_address = NULL;
575*b2ed49a5SDavid van Moolenbroek         }
576*b2ed49a5SDavid van Moolenbroek     }
577*b2ed49a5SDavid van Moolenbroek     else if (trg_extf_flags & ST_ON_PTRXFER_SKIP) {
578*b2ed49a5SDavid van Moolenbroek         ST_CB_PRINT(ST_CB_DBG, "ptr lookup results in skipping ptr transfer", selement, sel_analyzed, sel_stats, cb_info);
579*b2ed49a5SDavid van Moolenbroek     }
580*b2ed49a5SDavid van Moolenbroek     else {
581*b2ed49a5SDavid van Moolenbroek         if (trg_paired) {
582*b2ed49a5SDavid van Moolenbroek             ST_CB_PRINT(ST_CB_ERR, "uncaught ptr lookup for non-transferred target", selement, sel_analyzed, sel_stats, cb_info);
583*b2ed49a5SDavid van Moolenbroek         }
584*b2ed49a5SDavid van Moolenbroek         else {
585*b2ed49a5SDavid van Moolenbroek             ST_CB_PRINT(ST_CB_ERR, "uncaught ptr lookup for unpaired target", selement, sel_analyzed, sel_stats, cb_info);
586*b2ed49a5SDavid van Moolenbroek         }
587*b2ed49a5SDavid van Moolenbroek #if DO_SKIP_UNPAIRED_PTR_TARGETS
588*b2ed49a5SDavid van Moolenbroek         return MAGIC_SENTRY_ANALYZE_SKIP_PATH;
589*b2ed49a5SDavid van Moolenbroek #else
590*b2ed49a5SDavid van Moolenbroek         return ENOENT;
591*b2ed49a5SDavid van Moolenbroek #endif
592*b2ed49a5SDavid van Moolenbroek     }
593*b2ed49a5SDavid van Moolenbroek 
594*b2ed49a5SDavid van Moolenbroek     return MAGIC_SENTRY_ANALYZE_SKIP_PATH;
595*b2ed49a5SDavid van Moolenbroek }
596*b2ed49a5SDavid van Moolenbroek 
transfer_ptr_sel_cb(_magic_selement_t * selement,_magic_sel_analyzed_t * sel_analyzed,_magic_sel_stats_t * sel_stats,struct st_cb_info * cb_info)597*b2ed49a5SDavid van Moolenbroek PRIVATE INLINE int transfer_ptr_sel_cb(_magic_selement_t *selement, _magic_sel_analyzed_t *sel_analyzed, _magic_sel_stats_t *sel_stats, struct st_cb_info *cb_info)
598*b2ed49a5SDavid van Moolenbroek {
599*b2ed49a5SDavid van Moolenbroek     const struct _magic_type *first_trg_type;
600*b2ed49a5SDavid van Moolenbroek     if (selement->type->type_id != MAGIC_TYPE_POINTER) {
601*b2ed49a5SDavid van Moolenbroek         if (selement->type->size != sizeof(void*)) {
602*b2ed49a5SDavid van Moolenbroek             ST_CB_PRINT(ST_CB_ERR, "wrong pointer size", selement, sel_analyzed, sel_stats, cb_info);
603*b2ed49a5SDavid van Moolenbroek             return EFAULT;
604*b2ed49a5SDavid van Moolenbroek         }
605*b2ed49a5SDavid van Moolenbroek         ST_CB_PRINT(ST_CB_DBG, "casting non-ptr to ptr element", selement, sel_analyzed, sel_stats, cb_info);
606*b2ed49a5SDavid van Moolenbroek         st_cb_selement_type_cast(MAGIC_VOID_PTR_INT_CAST_TYPE, MAGIC_VOID_PTR_INT_CAST_TYPE, selement, sel_analyzed, sel_stats, cb_info);
607*b2ed49a5SDavid van Moolenbroek     }
608*b2ed49a5SDavid van Moolenbroek     first_trg_type = MAGIC_SEL_ANALYZED_PTR_FIRST_TRG_TYPE(sel_analyzed);
609*b2ed49a5SDavid van Moolenbroek     if (first_trg_type == MAGIC_TYPE_NULL_ENTRY
610*b2ed49a5SDavid van Moolenbroek         || first_trg_type == MAGIC_TYPE_VALUE_FOUND) {
611*b2ed49a5SDavid van Moolenbroek 
612*b2ed49a5SDavid van Moolenbroek         /* NULL pointer or special value. Don't adjust value */
613*b2ed49a5SDavid van Moolenbroek         return transfer_identity_sel_cb(selement, sel_analyzed, sel_stats, cb_info);
614*b2ed49a5SDavid van Moolenbroek 
615*b2ed49a5SDavid van Moolenbroek     } else if (!(sel_analyzed->flags & MAGIC_SEL_FOUND_VIOLATIONS)) {
616*b2ed49a5SDavid van Moolenbroek         /* Valid pointer found */
617*b2ed49a5SDavid van Moolenbroek         if (!ST_CB_FLAG(ST_CB_CHECK_ONLY)) {
618*b2ed49a5SDavid van Moolenbroek             return transfer_ptr_sel_with_trg_cb(selement, sel_analyzed, sel_stats, cb_info);
619*b2ed49a5SDavid van Moolenbroek         }
620*b2ed49a5SDavid van Moolenbroek 
621*b2ed49a5SDavid van Moolenbroek         return MAGIC_SENTRY_ANALYZE_SKIP_PATH;
622*b2ed49a5SDavid van Moolenbroek 
623*b2ed49a5SDavid van Moolenbroek     } else if(MAGIC_STATE_FLAG(selement->sentry, MAGIC_STATE_STACK)) {
624*b2ed49a5SDavid van Moolenbroek         struct _magic_sentry *trg_sentry = magic_sentry_lookup_by_range(sel_analyzed->u.ptr.value, NULL);
625*b2ed49a5SDavid van Moolenbroek         if (trg_sentry && !strcmp(trg_sentry->name, MAGIC_ALLOC_INITIAL_STACK_NAME)) {
626*b2ed49a5SDavid van Moolenbroek             /* Stack pointer to initial stack area. This is common (e.g., argv).
627*b2ed49a5SDavid van Moolenbroek              * We can safely assume the pointer will be already correctly
628*b2ed49a5SDavid van Moolenbroek              * initialized in the new version and simply skip transfer.
629*b2ed49a5SDavid van Moolenbroek              */
630*b2ed49a5SDavid van Moolenbroek             ST_CB_PRINT(ST_CB_DBG, "skipping stack ptr element pointing to initial stack area", selement, sel_analyzed, sel_stats, cb_info);
631*b2ed49a5SDavid van Moolenbroek             return MAGIC_SENTRY_ANALYZE_SKIP_PATH;
632*b2ed49a5SDavid van Moolenbroek         }
633*b2ed49a5SDavid van Moolenbroek     }
634*b2ed49a5SDavid van Moolenbroek #ifdef __MINIX
635*b2ed49a5SDavid van Moolenbroek #define IS_KERNEL_PTR(p) (((intptr_t)(p) & 0xf0000000) == 0xf0000000) /* TODO: make this more dynamic */
636*b2ed49a5SDavid van Moolenbroek     else if (IS_KERNEL_PTR(sel_analyzed->u.ptr.value))
637*b2ed49a5SDavid van Moolenbroek         return MAGIC_SENTRY_ANALYZE_SKIP_PATH; /* Kernel-mapped pointer */
638*b2ed49a5SDavid van Moolenbroek #endif
639*b2ed49a5SDavid van Moolenbroek 
640*b2ed49a5SDavid van Moolenbroek     /* Pointer with violations found */
641*b2ed49a5SDavid van Moolenbroek     ST_CB_PRINT(ST_CB_ERR, "uncaught ptr with violations", selement, sel_analyzed, sel_stats, cb_info);
642*b2ed49a5SDavid van Moolenbroek #if DO_SKIP_INVARIANTS_VIOLATIONS
643*b2ed49a5SDavid van Moolenbroek     return MAGIC_SENTRY_ANALYZE_SKIP_PATH;
644*b2ed49a5SDavid van Moolenbroek #else
645*b2ed49a5SDavid van Moolenbroek     return EFAULT;
646*b2ed49a5SDavid van Moolenbroek #endif
647*b2ed49a5SDavid van Moolenbroek }
648*b2ed49a5SDavid van Moolenbroek 
transfer_struct_sel_cb(_magic_selement_t * selement,_magic_sel_analyzed_t * sel_analyzed,_magic_sel_stats_t * sel_stats,struct st_cb_info * cb_info)649*b2ed49a5SDavid van Moolenbroek PRIVATE INLINE int transfer_struct_sel_cb(_magic_selement_t *selement, _magic_sel_analyzed_t *sel_analyzed, _magic_sel_stats_t *sel_stats, struct st_cb_info *cb_info)
650*b2ed49a5SDavid van Moolenbroek {
651*b2ed49a5SDavid van Moolenbroek     static int st_counter = 0;
652*b2ed49a5SDavid van Moolenbroek     unsigned parent_offset, offset;
653*b2ed49a5SDavid van Moolenbroek     int walk_flags, ret;
654*b2ed49a5SDavid van Moolenbroek 
655*b2ed49a5SDavid van Moolenbroek     if (selement->type->type_id != MAGIC_TYPE_UNION && selement->type->type_id != MAGIC_TYPE_STRUCT) {
656*b2ed49a5SDavid van Moolenbroek         ST_CB_PRINT(ST_CB_ERR, "struct transfer is only for structs and unions!", selement, sel_analyzed, sel_stats, cb_info);
657*b2ed49a5SDavid van Moolenbroek         return EFAULT;
658*b2ed49a5SDavid van Moolenbroek     }
659*b2ed49a5SDavid van Moolenbroek     if (selement->type->type_id == MAGIC_TYPE_STRUCT || st_counter > 0) {
660*b2ed49a5SDavid van Moolenbroek         return MAGIC_SENTRY_ANALYZE_CONTINUE;
661*b2ed49a5SDavid van Moolenbroek     }
662*b2ed49a5SDavid van Moolenbroek 
663*b2ed49a5SDavid van Moolenbroek     /* Walk the union as a struct. */
664*b2ed49a5SDavid van Moolenbroek     walk_flags = cb_info->walk_flags;
665*b2ed49a5SDavid van Moolenbroek     cb_info->walk_flags = (MAGIC_TYPE_WALK_DEFAULT_FLAGS & (~MAGIC_TYPE_WALK_UNIONS_AS_VOID));
666*b2ed49a5SDavid van Moolenbroek     st_counter++;
667*b2ed49a5SDavid van Moolenbroek     parent_offset = (unsigned)selement->parent_address - (unsigned)selement->sentry->address;
668*b2ed49a5SDavid van Moolenbroek     offset = (unsigned)selement->address - (unsigned)selement->sentry->address;
669*b2ed49a5SDavid van Moolenbroek     ret =  magic_type_walk_flags(selement->parent_type, parent_offset,
670*b2ed49a5SDavid van Moolenbroek         selement->child_num, selement->type, offset,
671*b2ed49a5SDavid van Moolenbroek         0, ULONG_MAX, magic_type_analyzer_cb, selement->cb_args, cb_info->walk_flags);
672*b2ed49a5SDavid van Moolenbroek     st_counter--;
673*b2ed49a5SDavid van Moolenbroek     cb_info->walk_flags = walk_flags;
674*b2ed49a5SDavid van Moolenbroek     if (ret != 0) {
675*b2ed49a5SDavid van Moolenbroek         return ret == MAGIC_TYPE_WALK_STOP ? MAGIC_SENTRY_ANALYZE_STOP : ret;
676*b2ed49a5SDavid van Moolenbroek     }
677*b2ed49a5SDavid van Moolenbroek 
678*b2ed49a5SDavid van Moolenbroek     return MAGIC_SENTRY_ANALYZE_SKIP_PATH;
679*b2ed49a5SDavid van Moolenbroek }
680*b2ed49a5SDavid van Moolenbroek 
default_transfer_selement_sel_cb(_magic_selement_t * selement,_magic_sel_analyzed_t * sel_analyzed,_magic_sel_stats_t * sel_stats,struct st_cb_info * cb_info)681*b2ed49a5SDavid van Moolenbroek PRIVATE INLINE int default_transfer_selement_sel_cb(_magic_selement_t *selement, _magic_sel_analyzed_t *sel_analyzed, _magic_sel_stats_t *sel_stats, struct st_cb_info *cb_info)
682*b2ed49a5SDavid van Moolenbroek {
683*b2ed49a5SDavid van Moolenbroek     /* Default handler for walkable, ptr and nonptr types. */
684*b2ed49a5SDavid van Moolenbroek #if ST_TRANSFER_IDENTITY_FOR_NO_INNER_PTRS
685*b2ed49a5SDavid van Moolenbroek     if (MAGIC_TYPE_FLAG(selement->type, MAGIC_TYPE_NO_INNER_PTRS)) {
686*b2ed49a5SDavid van Moolenbroek         /* If the type has no inner pointers, try to do raw copying. */
687*b2ed49a5SDavid van Moolenbroek         if (transfer_try_raw_copy_sel_cb(selement, cb_info) == MAGIC_SENTRY_ANALYZE_SKIP_PATH)
688*b2ed49a5SDavid van Moolenbroek             return MAGIC_SENTRY_ANALYZE_SKIP_PATH;
689*b2ed49a5SDavid van Moolenbroek     }
690*b2ed49a5SDavid van Moolenbroek #endif
691*b2ed49a5SDavid van Moolenbroek     if (selement->type->type_id == MAGIC_TYPE_UNION) {
692*b2ed49a5SDavid van Moolenbroek         if (!(st_policies & ST_IXFER_UNCAUGHT_UNIONS) && !MAGIC_TYPE_FLAG(selement->type, MAGIC_TYPE_NO_INNER_PTRS)) {
693*b2ed49a5SDavid van Moolenbroek             ST_CB_PRINT(ST_CB_ERR, "uncaught union", selement, sel_analyzed, sel_stats, cb_info);
694*b2ed49a5SDavid van Moolenbroek             return EFAULT;
695*b2ed49a5SDavid van Moolenbroek         }
696*b2ed49a5SDavid van Moolenbroek         else {
697*b2ed49a5SDavid van Moolenbroek             int level = (st_policies & ST_REPORT_UNCAUGHT_UNIONS) ? ST_CB_ERR : ST_CB_DBG;
698*b2ed49a5SDavid van Moolenbroek             ST_CB_PRINT(level, "uncaught union", selement, sel_analyzed, sel_stats, cb_info);
699*b2ed49a5SDavid van Moolenbroek             return transfer_identity_sel_cb(selement, sel_analyzed, sel_stats, cb_info);
700*b2ed49a5SDavid van Moolenbroek         }
701*b2ed49a5SDavid van Moolenbroek     } else if (MAGIC_TYPE_IS_WALKABLE(selement->type)) {
702*b2ed49a5SDavid van Moolenbroek         return transfer_walkable_sel_cb(selement, sel_analyzed, sel_stats, cb_info);
703*b2ed49a5SDavid van Moolenbroek     } else if (selement->type->type_id == MAGIC_TYPE_POINTER) {
704*b2ed49a5SDavid van Moolenbroek         return transfer_ptr_sel_cb(selement, sel_analyzed, sel_stats, cb_info);
705*b2ed49a5SDavid van Moolenbroek     } else {
706*b2ed49a5SDavid van Moolenbroek         return transfer_nonptr_sel_cb(selement, sel_analyzed, sel_stats, cb_info);
707*b2ed49a5SDavid van Moolenbroek     }
708*b2ed49a5SDavid van Moolenbroek 
709*b2ed49a5SDavid van Moolenbroek     /* Not reachable. */
710*b2ed49a5SDavid van Moolenbroek     ST_CB_PRINT(ST_CB_ERR, "Bug!", selement, sel_analyzed, sel_stats, cb_info);
711*b2ed49a5SDavid van Moolenbroek     return EINTR;
712*b2ed49a5SDavid van Moolenbroek }
713*b2ed49a5SDavid van Moolenbroek 
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)714*b2ed49a5SDavid van Moolenbroek 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)
715*b2ed49a5SDavid van Moolenbroek {
716*b2ed49a5SDavid van Moolenbroek     const char *sentry_name = selement->sentry->name;
717*b2ed49a5SDavid van Moolenbroek 
718*b2ed49a5SDavid van Moolenbroek #if ST_ASSUME_RAW_COPY_BEFORE_TRANSFER
719*b2ed49a5SDavid van Moolenbroek     if (MAGIC_STATE_FLAGS(selement->sentry, MAGIC_STATE_DYNAMIC)) {
720*b2ed49a5SDavid van Moolenbroek         if (MAGIC_STATE_FLAG(selement->sentry, MAGIC_STATE_LIB) || MAGIC_SENTRY_IS_EXT_ALLOC(selement->sentry))
721*b2ed49a5SDavid van Moolenbroek             return MAGIC_SENTRY_ANALYZE_SKIP_PATH;
722*b2ed49a5SDavid van Moolenbroek     }
723*b2ed49a5SDavid van Moolenbroek #endif
724*b2ed49a5SDavid van Moolenbroek 
725*b2ed49a5SDavid van Moolenbroek     if (ST_SENTRY_NAME_MATCH_ANY(st_sentryname_ixfers, sentry_name)) {
726*b2ed49a5SDavid van Moolenbroek         ST_CB_PRINT(ST_CB_DBG, "sentry name matches ixfer", selement, sel_analyzed, sel_stats, cb_info);
727*b2ed49a5SDavid van Moolenbroek         return transfer_identity_sel_cb(selement, sel_analyzed, sel_stats, cb_info);
728*b2ed49a5SDavid van Moolenbroek     }
729*b2ed49a5SDavid van Moolenbroek 
730*b2ed49a5SDavid van Moolenbroek     if (ST_SENTRY_NAME_MATCH_ANY(st_sentryname_cixfers, sentry_name)) {
731*b2ed49a5SDavid van Moolenbroek         ST_CB_PRINT(ST_CB_DBG, "sentry name matches cixfer", selement, sel_analyzed, sel_stats, cb_info);
732*b2ed49a5SDavid van Moolenbroek         return transfer_cond_identity_sel_cb(selement, sel_analyzed, sel_stats, cb_info);
733*b2ed49a5SDavid van Moolenbroek     }
734*b2ed49a5SDavid van Moolenbroek 
735*b2ed49a5SDavid van Moolenbroek     if (ST_SENTRY_NAME_MATCH_ANY(st_sentryname_noxfers, sentry_name)) {
736*b2ed49a5SDavid van Moolenbroek         ST_CB_PRINT(ST_CB_DBG, "sentry name matches noxfer", selement, sel_analyzed, sel_stats, cb_info);
737*b2ed49a5SDavid van Moolenbroek         return MAGIC_SENTRY_ANALYZE_SKIP_PATH;
738*b2ed49a5SDavid van Moolenbroek     }
739*b2ed49a5SDavid van Moolenbroek 
740*b2ed49a5SDavid van Moolenbroek     /* Skip memory management related sentries only when memory functions have
741*b2ed49a5SDavid van Moolenbroek      * been instrumented (which is *not* the case for the MINIX3 VM service).
742*b2ed49a5SDavid van Moolenbroek      */
743*b2ed49a5SDavid van Moolenbroek     if (_magic_no_mem_inst == 0 && ST_SENTRY_NAME_MATCH_ANY(st_sentryname_noxfers_mem, sentry_name)) {
744*b2ed49a5SDavid van Moolenbroek         ST_CB_PRINT(ST_CB_DBG, "sentry name matches noxfer", selement, sel_analyzed, sel_stats, cb_info);
745*b2ed49a5SDavid van Moolenbroek         return MAGIC_SENTRY_ANALYZE_SKIP_PATH;
746*b2ed49a5SDavid van Moolenbroek     }
747*b2ed49a5SDavid van Moolenbroek 
748*b2ed49a5SDavid van Moolenbroek     if (ST_SENTRY_NAME_MATCH_ANY(st_sentryname_pxfers, sentry_name)) {
749*b2ed49a5SDavid van Moolenbroek         ST_CB_PRINT(ST_CB_DBG, "sentry name matches pxfer", selement, sel_analyzed, sel_stats, cb_info);
750*b2ed49a5SDavid van Moolenbroek         return transfer_ptr_sel_cb(selement, sel_analyzed, sel_stats, cb_info);
751*b2ed49a5SDavid van Moolenbroek     }
752*b2ed49a5SDavid van Moolenbroek 
753*b2ed49a5SDavid van Moolenbroek     if (MAGIC_STATE_FLAGS(selement->sentry, MAGIC_STATE_DYNAMIC | MAGIC_STATE_MAP | MAGIC_STATE_LIB)) {
754*b2ed49a5SDavid van Moolenbroek         struct _magic_dsentry *dsentry = MAGIC_DSENTRY_FROM_SENTRY(selement->sentry);
755*b2ed49a5SDavid van Moolenbroek         if (ST_DSENTRY_PARENT_NAME_MATCH_ANY(st_dsentry_lib_noxfer, dsentry->parent_name)) {
756*b2ed49a5SDavid van Moolenbroek             ST_CB_PRINT(ST_CB_DBG, "dsentry is a lib map and parent_name matches dsentry_lib_noxfer", selement, sel_analyzed, sel_stats, cb_info);
757*b2ed49a5SDavid van Moolenbroek             return MAGIC_SENTRY_ANALYZE_SKIP_PATH;
758*b2ed49a5SDavid van Moolenbroek         }
759*b2ed49a5SDavid van Moolenbroek     }
760*b2ed49a5SDavid van Moolenbroek 
761*b2ed49a5SDavid van Moolenbroek     return ST_CB_NOT_PROCESSED;
762*b2ed49a5SDavid van Moolenbroek }
763*b2ed49a5SDavid van Moolenbroek 
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)764*b2ed49a5SDavid van Moolenbroek 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)
765*b2ed49a5SDavid van Moolenbroek {
766*b2ed49a5SDavid van Moolenbroek     const char *typename_key = ST_TYPE_NAME_KEY(selement->type);
767*b2ed49a5SDavid van Moolenbroek     if (ST_TYPE_NAME_MATCH_ANY(st_typename_ixfers, typename_key)) {
768*b2ed49a5SDavid van Moolenbroek         return transfer_identity_sel_cb(selement, sel_analyzed, sel_stats, cb_info);
769*b2ed49a5SDavid van Moolenbroek     }
770*b2ed49a5SDavid van Moolenbroek 
771*b2ed49a5SDavid van Moolenbroek     if (ST_TYPE_NAME_MATCH_ANY(st_typename_cixfers, typename_key)) {
772*b2ed49a5SDavid van Moolenbroek         return transfer_cond_identity_sel_cb(selement, sel_analyzed, sel_stats, cb_info);
773*b2ed49a5SDavid van Moolenbroek     }
774*b2ed49a5SDavid van Moolenbroek 
775*b2ed49a5SDavid van Moolenbroek     if (ST_TYPE_NAME_MATCH_ANY(st_typename_noxfers, typename_key)) {
776*b2ed49a5SDavid van Moolenbroek         return MAGIC_SENTRY_ANALYZE_SKIP_PATH;
777*b2ed49a5SDavid van Moolenbroek     }
778*b2ed49a5SDavid van Moolenbroek 
779*b2ed49a5SDavid van Moolenbroek     if (ST_TYPE_NAME_MATCH_ANY(st_typename_pxfers, typename_key)) {
780*b2ed49a5SDavid van Moolenbroek         return transfer_ptr_sel_cb(selement, sel_analyzed, sel_stats, cb_info);
781*b2ed49a5SDavid van Moolenbroek     }
782*b2ed49a5SDavid van Moolenbroek 
783*b2ed49a5SDavid van Moolenbroek     if (ST_TYPE_NAME_MATCH_ANY(st_typename_sxfers, typename_key)) {
784*b2ed49a5SDavid van Moolenbroek         return transfer_struct_sel_cb(selement, sel_analyzed, sel_stats, cb_info);
785*b2ed49a5SDavid van Moolenbroek     }
786*b2ed49a5SDavid van Moolenbroek 
787*b2ed49a5SDavid van Moolenbroek     return ST_CB_NOT_PROCESSED;
788*b2ed49a5SDavid van Moolenbroek }
789*b2ed49a5SDavid van Moolenbroek 
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)790*b2ed49a5SDavid van Moolenbroek 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)
791*b2ed49a5SDavid van Moolenbroek {
792*b2ed49a5SDavid van Moolenbroek     return transfer_walkable_sel_cb(selement, sel_analyzed, sel_stats, cb_info);
793*b2ed49a5SDavid van Moolenbroek }
794*b2ed49a5SDavid van Moolenbroek 
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)795*b2ed49a5SDavid van Moolenbroek 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)
796*b2ed49a5SDavid van Moolenbroek {
797*b2ed49a5SDavid van Moolenbroek     return transfer_ptr_sel_cb(selement, sel_analyzed, sel_stats, cb_info);
798*b2ed49a5SDavid van Moolenbroek }
799*b2ed49a5SDavid van Moolenbroek 
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)800*b2ed49a5SDavid van Moolenbroek 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)
801*b2ed49a5SDavid van Moolenbroek {
802*b2ed49a5SDavid van Moolenbroek     return transfer_identity_sel_cb(selement, sel_analyzed, sel_stats, cb_info);
803*b2ed49a5SDavid van Moolenbroek }
804*b2ed49a5SDavid van Moolenbroek 
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)805*b2ed49a5SDavid van Moolenbroek 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)
806*b2ed49a5SDavid van Moolenbroek {
807*b2ed49a5SDavid van Moolenbroek     return transfer_cond_identity_sel_cb(selement, sel_analyzed, sel_stats, cb_info);
808*b2ed49a5SDavid van Moolenbroek }
809*b2ed49a5SDavid van Moolenbroek 
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)810*b2ed49a5SDavid van Moolenbroek 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)
811*b2ed49a5SDavid van Moolenbroek {
812*b2ed49a5SDavid van Moolenbroek     return transfer_nonptr_sel_cb(selement, sel_analyzed, sel_stats, cb_info);
813*b2ed49a5SDavid van Moolenbroek }
814*b2ed49a5SDavid van Moolenbroek 
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)815*b2ed49a5SDavid van Moolenbroek 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)
816*b2ed49a5SDavid van Moolenbroek {
817*b2ed49a5SDavid van Moolenbroek     return transfer_struct_sel_cb(selement, sel_analyzed, sel_stats, cb_info);
818*b2ed49a5SDavid van Moolenbroek }
819*b2ed49a5SDavid van Moolenbroek 
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)820*b2ed49a5SDavid van Moolenbroek 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)
821*b2ed49a5SDavid van Moolenbroek {
822*b2ed49a5SDavid van Moolenbroek     return default_transfer_selement_sel_cb(selement, sel_analyzed, sel_stats, cb_info);
823*b2ed49a5SDavid van Moolenbroek }
824*b2ed49a5SDavid van Moolenbroek 
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)825*b2ed49a5SDavid van Moolenbroek 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)
826*b2ed49a5SDavid van Moolenbroek {
827*b2ed49a5SDavid van Moolenbroek     return transfer_data_selement(selement, sel_analyzed, sel_stats, cb_info);
828*b2ed49a5SDavid van Moolenbroek }
829*b2ed49a5SDavid van Moolenbroek 
830*b2ed49a5SDavid van Moolenbroek /* Selement mapping functions and callbacks. */
831*b2ed49a5SDavid van Moolenbroek 
st_map_selement_from_sentry_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)832*b2ed49a5SDavid van Moolenbroek PRIVATE int st_map_selement_from_sentry_cb(const struct _magic_type* parent_type,
833*b2ed49a5SDavid van Moolenbroek     const unsigned parent_offset, int child_num,
834*b2ed49a5SDavid van Moolenbroek     const struct _magic_type* type, const unsigned offset, int depth, void* cb_args)
835*b2ed49a5SDavid van Moolenbroek {
836*b2ed49a5SDavid van Moolenbroek     void **args_array = (void**) cb_args;
837*b2ed49a5SDavid van Moolenbroek     _magic_selement_t cached_selement;
838*b2ed49a5SDavid van Moolenbroek     _magic_selement_t *local_selement = (_magic_selement_t*) args_array[1];
839*b2ed49a5SDavid van Moolenbroek     _magic_selement_t *selement = (_magic_selement_t*) args_array[0];
840*b2ed49a5SDavid van Moolenbroek     struct _magic_sentry *sentry = selement->sentry;
841*b2ed49a5SDavid van Moolenbroek     void *address = (char*)sentry->address + offset;
842*b2ed49a5SDavid van Moolenbroek     void *selement_address = selement->address;
843*b2ed49a5SDavid van Moolenbroek     int is_trg_mapping;
844*b2ed49a5SDavid van Moolenbroek     struct st_cb_info *cb_info;
845*b2ed49a5SDavid van Moolenbroek     if ((char*) selement_address >= ((char*) address + type->size)) {
846*b2ed49a5SDavid van Moolenbroek         return MAGIC_TYPE_WALK_SKIP_PATH;
847*b2ed49a5SDavid van Moolenbroek     }
848*b2ed49a5SDavid van Moolenbroek     cb_info = (struct st_cb_info*) args_array[2];
849*b2ed49a5SDavid van Moolenbroek     is_trg_mapping = (int) args_array[3];
850*b2ed49a5SDavid van Moolenbroek     cached_selement.sentry = sentry;
851*b2ed49a5SDavid van Moolenbroek     cached_selement.parent_type = parent_type;
852*b2ed49a5SDavid van Moolenbroek     cached_selement.parent_address = (char*)sentry->address + parent_offset;
853*b2ed49a5SDavid van Moolenbroek     cached_selement.child_num = child_num;
854*b2ed49a5SDavid van Moolenbroek     cached_selement.type = type;
855*b2ed49a5SDavid van Moolenbroek     cached_selement.address = address;
856*b2ed49a5SDavid van Moolenbroek     cached_selement.depth = depth;
857*b2ed49a5SDavid van Moolenbroek     st_map_selement(&cached_selement, local_selement, cb_info, is_trg_mapping);
858*b2ed49a5SDavid van Moolenbroek     if (local_selement->type == NULL) {
859*b2ed49a5SDavid van Moolenbroek         return ENOENT;
860*b2ed49a5SDavid van Moolenbroek     }
861*b2ed49a5SDavid van Moolenbroek     if (address == selement_address && type == selement->type) {
862*b2ed49a5SDavid van Moolenbroek         return MAGIC_TYPE_WALK_STOP;
863*b2ed49a5SDavid van Moolenbroek     }
864*b2ed49a5SDavid van Moolenbroek     if (type->num_child_types == 0) {
865*b2ed49a5SDavid van Moolenbroek         return EINVAL;
866*b2ed49a5SDavid van Moolenbroek     }
867*b2ed49a5SDavid van Moolenbroek     local_selement->parent_type = local_selement->type;
868*b2ed49a5SDavid van Moolenbroek     local_selement->parent_address = local_selement->address;
869*b2ed49a5SDavid van Moolenbroek     return MAGIC_TYPE_WALK_CONTINUE;
870*b2ed49a5SDavid van Moolenbroek }
871*b2ed49a5SDavid van Moolenbroek 
st_map_selement_from_sentry(_magic_selement_t * cached_selement,_magic_selement_t * local_selement,struct _magic_sentry * local_sentry,struct st_cb_info * cb_info,int is_trg_mapping)872*b2ed49a5SDavid van Moolenbroek PRIVATE INLINE void st_map_selement_from_sentry(_magic_selement_t *cached_selement, _magic_selement_t *local_selement, struct _magic_sentry *local_sentry, struct st_cb_info *cb_info, int is_trg_mapping)
873*b2ed49a5SDavid van Moolenbroek {
874*b2ed49a5SDavid van Moolenbroek     unsigned max_offset;
875*b2ed49a5SDavid van Moolenbroek     int r;
876*b2ed49a5SDavid van Moolenbroek     void *args_array[4];
877*b2ed49a5SDavid van Moolenbroek     max_offset = (unsigned) ( (char *)cached_selement->address - (char *)cached_selement->sentry->address);
878*b2ed49a5SDavid van Moolenbroek     args_array[0] = cached_selement;
879*b2ed49a5SDavid van Moolenbroek     args_array[1] = magic_selement_from_sentry(local_sentry, local_selement);
880*b2ed49a5SDavid van Moolenbroek     args_array[2] = cb_info;
881*b2ed49a5SDavid van Moolenbroek     args_array[3] = (void*) is_trg_mapping;
882*b2ed49a5SDavid van Moolenbroek     r = magic_type_walk_root(cached_selement->sentry->type, 0, max_offset, st_map_selement_from_sentry_cb, (void*) args_array);
883*b2ed49a5SDavid van Moolenbroek     if (r < 0) {
884*b2ed49a5SDavid van Moolenbroek         assert(r == ENOENT);
885*b2ed49a5SDavid van Moolenbroek         local_selement->type = NULL;
886*b2ed49a5SDavid van Moolenbroek     }
887*b2ed49a5SDavid van Moolenbroek }
888*b2ed49a5SDavid van Moolenbroek 
st_map_sel_analyzed_from_target(_magic_sel_analyzed_t * cached_sel_analyzed,_magic_sel_analyzed_t * local_sel_analyzed,struct _magic_sentry * local_trg_sentry,struct _magic_function * local_trg_function,struct st_cb_info * cb_info)889*b2ed49a5SDavid van Moolenbroek PRIVATE INLINE void st_map_sel_analyzed_from_target(_magic_sel_analyzed_t *cached_sel_analyzed, _magic_sel_analyzed_t *local_sel_analyzed, struct _magic_sentry *local_trg_sentry, struct _magic_function *local_trg_function, struct st_cb_info *cb_info)
890*b2ed49a5SDavid van Moolenbroek {
891*b2ed49a5SDavid van Moolenbroek     _magic_selement_t *csel, *lsel;
892*b2ed49a5SDavid van Moolenbroek     assert(local_trg_sentry || local_trg_function);
893*b2ed49a5SDavid van Moolenbroek     assert(cached_sel_analyzed->type_id == MAGIC_TYPE_POINTER);
894*b2ed49a5SDavid van Moolenbroek     assert(cached_sel_analyzed->u.ptr.first_legal_trg_type>=0);
895*b2ed49a5SDavid van Moolenbroek     local_sel_analyzed->type_id = cached_sel_analyzed->type_id;
896*b2ed49a5SDavid van Moolenbroek     local_sel_analyzed->num = cached_sel_analyzed->num;
897*b2ed49a5SDavid van Moolenbroek     local_sel_analyzed->flags = cached_sel_analyzed->flags;
898*b2ed49a5SDavid van Moolenbroek     local_sel_analyzed->u.ptr.trg_flags = local_trg_sentry ? local_trg_sentry->flags : local_trg_function->flags;
899*b2ed49a5SDavid van Moolenbroek     local_sel_analyzed->u.ptr.first_legal_trg_type = -1;
900*b2ed49a5SDavid van Moolenbroek     local_sel_analyzed->u.ptr.num_legal_trg_types = 0;
901*b2ed49a5SDavid van Moolenbroek     if (local_trg_function) {
902*b2ed49a5SDavid van Moolenbroek         assert(cached_sel_analyzed->u.ptr.num_legal_trg_types == 1);
903*b2ed49a5SDavid van Moolenbroek         lsel = &local_sel_analyzed->u.ptr.trg_selements[0];
904*b2ed49a5SDavid van Moolenbroek         memset(lsel, 0, sizeof(_magic_selement_t));
905*b2ed49a5SDavid van Moolenbroek         lsel->sentry = NULL;
906*b2ed49a5SDavid van Moolenbroek         lsel->type = local_trg_function->type;
907*b2ed49a5SDavid van Moolenbroek         lsel->address = local_trg_function->address;
908*b2ed49a5SDavid van Moolenbroek         local_sel_analyzed->u.ptr.num_trg_types = 1;
909*b2ed49a5SDavid van Moolenbroek     }
910*b2ed49a5SDavid van Moolenbroek     else {
911*b2ed49a5SDavid van Moolenbroek         unsigned int i;
912*b2ed49a5SDavid van Moolenbroek         void *address = NULL;
913*b2ed49a5SDavid van Moolenbroek         local_sel_analyzed->u.ptr.num_trg_types = 0;
914*b2ed49a5SDavid van Moolenbroek         for (i = cached_sel_analyzed->u.ptr.first_legal_trg_type ; i < cached_sel_analyzed->u.ptr.num_trg_types ; i++) {
915*b2ed49a5SDavid van Moolenbroek             _magic_trg_stats_t trg_stats = cached_sel_analyzed->u.ptr.trg_stats[i];
916*b2ed49a5SDavid van Moolenbroek             if (MAGIC_SEL_ANALYZED_TRG_STATS_HAS_VIOLATIONS(trg_stats)) {
917*b2ed49a5SDavid van Moolenbroek                 continue;
918*b2ed49a5SDavid van Moolenbroek             }
919*b2ed49a5SDavid van Moolenbroek             csel = &cached_sel_analyzed->u.ptr.trg_selements[i];
920*b2ed49a5SDavid van Moolenbroek             lsel = &local_sel_analyzed->u.ptr.trg_selements[local_sel_analyzed->u.ptr.num_trg_types++];
921*b2ed49a5SDavid van Moolenbroek             st_map_selement_from_sentry(csel, lsel, local_trg_sentry, cb_info, TRUE);
922*b2ed49a5SDavid van Moolenbroek             if (lsel->type == NULL || (address && lsel->address != address)) {
923*b2ed49a5SDavid van Moolenbroek                 /* Unpaired selement or ambiguous local address. */
924*b2ed49a5SDavid van Moolenbroek                 local_sel_analyzed->u.ptr.num_trg_types = 0;
925*b2ed49a5SDavid van Moolenbroek                 return;
926*b2ed49a5SDavid van Moolenbroek             }
927*b2ed49a5SDavid van Moolenbroek             address = lsel->address;
928*b2ed49a5SDavid van Moolenbroek         }
929*b2ed49a5SDavid van Moolenbroek         assert(local_sel_analyzed->u.ptr.num_trg_types > 0);
930*b2ed49a5SDavid van Moolenbroek     }
931*b2ed49a5SDavid van Moolenbroek }
932*b2ed49a5SDavid van Moolenbroek 
st_map_local_selement_from_child_num(_magic_selement_t * local_selement,struct st_cb_info * cb_info,int child_num)933*b2ed49a5SDavid van Moolenbroek PUBLIC void st_map_local_selement_from_child_num(_magic_selement_t *local_selement, struct st_cb_info *cb_info, int child_num)
934*b2ed49a5SDavid van Moolenbroek {
935*b2ed49a5SDavid van Moolenbroek     local_selement->child_num = child_num;
936*b2ed49a5SDavid van Moolenbroek     magic_selement_fill_from_parent_info(local_selement, cb_info->walk_flags);
937*b2ed49a5SDavid van Moolenbroek }
938*b2ed49a5SDavid van Moolenbroek 
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)939*b2ed49a5SDavid van Moolenbroek 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)
940*b2ed49a5SDavid van Moolenbroek {
941*b2ed49a5SDavid van Moolenbroek     int cached_num_elements, local_num_elements, is_trg_at_array_end, is_trg_at_str_end;
942*b2ed49a5SDavid van Moolenbroek     /* Match arrays/vectors with arrays/vectors. */
943*b2ed49a5SDavid van Moolenbroek     assert(cached_selement->parent_type->type_id == MAGIC_TYPE_ARRAY || cached_selement->parent_type->type_id == MAGIC_TYPE_VECTOR);
944*b2ed49a5SDavid van Moolenbroek     if (local_selement->parent_type->type_id != MAGIC_TYPE_ARRAY && local_selement->parent_type->type_id != MAGIC_TYPE_VECTOR) {
945*b2ed49a5SDavid van Moolenbroek         local_selement->type = NULL;
946*b2ed49a5SDavid van Moolenbroek         return;
947*b2ed49a5SDavid van Moolenbroek     }
948*b2ed49a5SDavid van Moolenbroek     cached_num_elements = cached_selement->parent_type->num_child_types;
949*b2ed49a5SDavid van Moolenbroek     local_num_elements = local_selement->parent_type->num_child_types;
950*b2ed49a5SDavid van Moolenbroek     /* Same size or first child? We are done. */
951*b2ed49a5SDavid van Moolenbroek     if (cached_num_elements == local_num_elements || local_selement->child_num == 0) {
952*b2ed49a5SDavid van Moolenbroek          st_map_local_selement_from_child_num(local_selement, cb_info, cached_selement->child_num);
953*b2ed49a5SDavid van Moolenbroek          return;
954*b2ed49a5SDavid van Moolenbroek     }
955*b2ed49a5SDavid van Moolenbroek     assert(local_num_elements > 0);
956*b2ed49a5SDavid van Moolenbroek     is_trg_at_str_end = FALSE;
957*b2ed49a5SDavid van Moolenbroek     is_trg_at_array_end = FALSE;
958*b2ed49a5SDavid van Moolenbroek     if (is_trg_mapping && cached_selement->child_num == cached_num_elements-1) {
959*b2ed49a5SDavid van Moolenbroek         is_trg_at_str_end = MAGIC_SENTRY_IS_STRING(cached_selement->sentry) || MAGIC_SENTRY_IS_STRING(local_selement->sentry);
960*b2ed49a5SDavid van Moolenbroek         is_trg_at_array_end = !is_trg_at_str_end;
961*b2ed49a5SDavid van Moolenbroek     }
962*b2ed49a5SDavid van Moolenbroek     if (is_trg_at_array_end && (st_policies & ST_DEFAULT_MAP_GUARD_PTRS_TO_ARRAY_END)) {
963*b2ed49a5SDavid van Moolenbroek         /* This should be interpreted as a target of a guard pointer pointing to the last element of an array and needs to be remapped as such. */
964*b2ed49a5SDavid van Moolenbroek         st_map_local_selement_from_child_num(local_selement, cb_info, local_num_elements-1);
965*b2ed49a5SDavid van Moolenbroek     }
966*b2ed49a5SDavid van Moolenbroek     else if (is_trg_at_str_end && (st_policies & ST_DEFAULT_MAP_GUARD_PTRS_TO_STR_END)) {
967*b2ed49a5SDavid van Moolenbroek         /* This should be interpreted as a target of a guard pointer pointing to the last element of a string and needs to be remapped as such. */
968*b2ed49a5SDavid van Moolenbroek         st_map_local_selement_from_child_num(local_selement, cb_info, local_num_elements-1);
969*b2ed49a5SDavid van Moolenbroek     }
970*b2ed49a5SDavid van Moolenbroek     else if (cached_selement->child_num >= local_num_elements) {
971*b2ed49a5SDavid van Moolenbroek         /* New array got truncated and this element is gone. */
972*b2ed49a5SDavid van Moolenbroek         local_selement->type = NULL;
973*b2ed49a5SDavid van Moolenbroek     }
974*b2ed49a5SDavid van Moolenbroek     else {
975*b2ed49a5SDavid van Moolenbroek         /* New array is bigger, just keep the original position in the array. */
976*b2ed49a5SDavid van Moolenbroek         st_map_local_selement_from_child_num(local_selement, cb_info, cached_selement->child_num);
977*b2ed49a5SDavid van Moolenbroek     }
978*b2ed49a5SDavid van Moolenbroek }
979*b2ed49a5SDavid van Moolenbroek 
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)980*b2ed49a5SDavid van Moolenbroek 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)
981*b2ed49a5SDavid van Moolenbroek {
982*b2ed49a5SDavid van Moolenbroek     size_t cached_size = cached_selement->type->num_child_types, local_size = local_selement->type->num_child_types;
983*b2ed49a5SDavid van Moolenbroek 
984*b2ed49a5SDavid van Moolenbroek     /* Match arrays/vectors with arrays/vectors. */
985*b2ed49a5SDavid van Moolenbroek     assert(cached_selement->type->type_id == MAGIC_TYPE_ARRAY || cached_selement->type->type_id == MAGIC_TYPE_VECTOR);
986*b2ed49a5SDavid van Moolenbroek     if (local_selement->type->type_id != MAGIC_TYPE_ARRAY && local_selement->type->type_id != MAGIC_TYPE_VECTOR) {
987*b2ed49a5SDavid van Moolenbroek         local_selement->type = NULL;
988*b2ed49a5SDavid van Moolenbroek         return;
989*b2ed49a5SDavid van Moolenbroek     }
990*b2ed49a5SDavid van Moolenbroek 
991*b2ed49a5SDavid van Moolenbroek     /* Varsized arrays have to be consistent across versions. */
992*b2ed49a5SDavid van Moolenbroek     if (MAGIC_TYPE_FLAG(cached_selement->type, MAGIC_TYPE_VARSIZE) != MAGIC_TYPE_FLAG(local_selement->type, MAGIC_TYPE_VARSIZE)) {
993*b2ed49a5SDavid van Moolenbroek         local_selement->type = NULL;
994*b2ed49a5SDavid van Moolenbroek         return;
995*b2ed49a5SDavid van Moolenbroek     }
996*b2ed49a5SDavid van Moolenbroek 
997*b2ed49a5SDavid van Moolenbroek     /* Check size. */
998*b2ed49a5SDavid van Moolenbroek     if (cached_size != local_size) {
999*b2ed49a5SDavid van Moolenbroek         int report;
1000*b2ed49a5SDavid van Moolenbroek         int is_string = MAGIC_SENTRY_IS_STRING(cached_selement->sentry) || MAGIC_SENTRY_IS_STRING(local_selement->sentry);
1001*b2ed49a5SDavid van Moolenbroek         if (local_size < cached_size) {
1002*b2ed49a5SDavid van Moolenbroek             report = is_string ? (st_policies & ST_REPORT_SMALLER_STRINGS) : (st_policies & ST_REPORT_SMALLER_ARRAYS);
1003*b2ed49a5SDavid van Moolenbroek         }
1004*b2ed49a5SDavid van Moolenbroek         else {
1005*b2ed49a5SDavid van Moolenbroek             report = is_string ? (st_policies & ST_REPORT_LARGER_STRINGS) : (st_policies & ST_REPORT_LARGER_ARRAYS);
1006*b2ed49a5SDavid van Moolenbroek         }
1007*b2ed49a5SDavid van Moolenbroek 
1008*b2ed49a5SDavid van Moolenbroek         if (report) {
1009*b2ed49a5SDavid van Moolenbroek             printf("st_cb_map_child_array_selement_generic: %s size found while mapping array selements:\n", local_size < cached_size ? "Smaller" : "Larger");
1010*b2ed49a5SDavid van Moolenbroek             MAGIC_SELEMENT_PRINT(cached_selement, MAGIC_EXPAND_TYPE_STR); printf("\n");
1011*b2ed49a5SDavid van Moolenbroek             MAGIC_SELEMENT_PRINT(local_selement, MAGIC_EXPAND_TYPE_STR); printf("\n");
1012*b2ed49a5SDavid van Moolenbroek         }
1013*b2ed49a5SDavid van Moolenbroek     }
1014*b2ed49a5SDavid van Moolenbroek }
1015*b2ed49a5SDavid van Moolenbroek 
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)1016*b2ed49a5SDavid van Moolenbroek 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)
1017*b2ed49a5SDavid van Moolenbroek {
1018*b2ed49a5SDavid van Moolenbroek     /* This should only be called in case of unions transferred as structs. */
1019*b2ed49a5SDavid van Moolenbroek     st_cb_map_from_parent_struct_selement_generic(cached_selement, local_selement, cb_info, is_trg_mapping);
1020*b2ed49a5SDavid van Moolenbroek }
1021*b2ed49a5SDavid van Moolenbroek 
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)1022*b2ed49a5SDavid van Moolenbroek 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)
1023*b2ed49a5SDavid van Moolenbroek {
1024*b2ed49a5SDavid van Moolenbroek     /* Match unions just like structs. */
1025*b2ed49a5SDavid van Moolenbroek     st_cb_map_child_struct_selement_generic(cached_selement, local_selement, cb_info, is_trg_mapping);
1026*b2ed49a5SDavid van Moolenbroek }
1027*b2ed49a5SDavid van Moolenbroek 
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)1028*b2ed49a5SDavid van Moolenbroek 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)
1029*b2ed49a5SDavid van Moolenbroek {
1030*b2ed49a5SDavid van Moolenbroek     unsigned int i;
1031*b2ed49a5SDavid van Moolenbroek     const char *cached_member_name;
1032*b2ed49a5SDavid van Moolenbroek     /* Match struct/unions with struct/unions. */
1033*b2ed49a5SDavid van Moolenbroek     assert(cached_selement->parent_type->type_id == MAGIC_TYPE_STRUCT || cached_selement->parent_type->type_id == MAGIC_TYPE_UNION);
1034*b2ed49a5SDavid van Moolenbroek     if (local_selement->parent_type->type_id != MAGIC_TYPE_STRUCT && local_selement->parent_type->type_id != MAGIC_TYPE_UNION) {
1035*b2ed49a5SDavid van Moolenbroek         local_selement->type = NULL;
1036*b2ed49a5SDavid van Moolenbroek         return;
1037*b2ed49a5SDavid van Moolenbroek     }
1038*b2ed49a5SDavid van Moolenbroek     /* Match struct/unions members by name. */
1039*b2ed49a5SDavid van Moolenbroek     cached_member_name = cached_selement->parent_type->member_names[cached_selement->child_num];
1040*b2ed49a5SDavid van Moolenbroek     for (i = 0 ; i < local_selement->parent_type->num_child_types ; i++) {
1041*b2ed49a5SDavid van Moolenbroek         if (!strcmp(local_selement->parent_type->member_names[i], cached_member_name)) {
1042*b2ed49a5SDavid van Moolenbroek             st_map_local_selement_from_child_num(local_selement, cb_info, i);
1043*b2ed49a5SDavid van Moolenbroek             return;
1044*b2ed49a5SDavid van Moolenbroek         }
1045*b2ed49a5SDavid van Moolenbroek     }
1046*b2ed49a5SDavid van Moolenbroek     local_selement->type = NULL;
1047*b2ed49a5SDavid van Moolenbroek }
1048*b2ed49a5SDavid van Moolenbroek 
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)1049*b2ed49a5SDavid van Moolenbroek 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)
1050*b2ed49a5SDavid van Moolenbroek {
1051*b2ed49a5SDavid van Moolenbroek     unsigned int i, j;
1052*b2ed49a5SDavid van Moolenbroek     const struct _magic_type *cached_type = cached_selement->type;
1053*b2ed49a5SDavid van Moolenbroek     const struct _magic_type *local_type = local_selement->type;
1054*b2ed49a5SDavid van Moolenbroek     assert(cached_type->type_id == MAGIC_TYPE_STRUCT || cached_type->type_id == MAGIC_TYPE_UNION);
1055*b2ed49a5SDavid van Moolenbroek     if (local_type->type_id != MAGIC_TYPE_STRUCT && local_type->type_id != MAGIC_TYPE_UNION) {
1056*b2ed49a5SDavid van Moolenbroek         local_selement->type = NULL;
1057*b2ed49a5SDavid van Moolenbroek         return;
1058*b2ed49a5SDavid van Moolenbroek     }
1059*b2ed49a5SDavid van Moolenbroek     /* Match struct/unions by name(s). */
1060*b2ed49a5SDavid van Moolenbroek     if (!strcmp(cached_type->name, local_type->name)) {
1061*b2ed49a5SDavid van Moolenbroek         return;
1062*b2ed49a5SDavid van Moolenbroek     }
1063*b2ed49a5SDavid van Moolenbroek     if (cached_type->num_names > 1 || local_type->num_names > 1 ) {
1064*b2ed49a5SDavid van Moolenbroek         for (i = 0 ; i < cached_type->num_names ; i++) {
1065*b2ed49a5SDavid van Moolenbroek             for (j = 0 ; j < local_type->num_names ; j++) {
1066*b2ed49a5SDavid van Moolenbroek                 if (!strcmp(cached_type->names[i], local_type->names[j])) {
1067*b2ed49a5SDavid van Moolenbroek                     return;
1068*b2ed49a5SDavid van Moolenbroek                 }
1069*b2ed49a5SDavid van Moolenbroek             }
1070*b2ed49a5SDavid van Moolenbroek         }
1071*b2ed49a5SDavid van Moolenbroek     }
1072*b2ed49a5SDavid van Moolenbroek 
1073*b2ed49a5SDavid van Moolenbroek     local_selement->type = NULL;
1074*b2ed49a5SDavid van Moolenbroek }
1075*b2ed49a5SDavid van Moolenbroek 
st_cb_map_child_nonaggr_selement_generic(_magic_selement_t * cached_selement,_magic_selement_t * local_selement,struct st_cb_info * cb_info,int is_trg_mapping)1076*b2ed49a5SDavid van Moolenbroek PUBLIC void st_cb_map_child_nonaggr_selement_generic(_magic_selement_t *cached_selement, _magic_selement_t *local_selement, struct st_cb_info *cb_info, int is_trg_mapping)
1077*b2ed49a5SDavid van Moolenbroek {
1078*b2ed49a5SDavid van Moolenbroek     int r;
1079*b2ed49a5SDavid van Moolenbroek     static char magic_value_buffer[32];
1080*b2ed49a5SDavid van Moolenbroek 
1081*b2ed49a5SDavid van Moolenbroek     r = magic_selement_value_cast(cached_selement, local_selement, magic_value_buffer);
1082*b2ed49a5SDavid van Moolenbroek     if (r == 0) {
1083*b2ed49a5SDavid van Moolenbroek         return;
1084*b2ed49a5SDavid van Moolenbroek     }
1085*b2ed49a5SDavid van Moolenbroek     if (r < 0 && r != MAGIC_ERANGE && r != MAGIC_ESIGN) {
1086*b2ed49a5SDavid van Moolenbroek         local_selement->type = NULL;
1087*b2ed49a5SDavid van Moolenbroek         return;
1088*b2ed49a5SDavid van Moolenbroek     }
1089*b2ed49a5SDavid van Moolenbroek     if ((r == MAGIC_ERANGE && (st_policies & ST_REPORT_PRECISION_LOSS))
1090*b2ed49a5SDavid van Moolenbroek         || (r == MAGIC_ESIGN && (st_policies & ST_REPORT_SIGN_CHANGE))) {
1091*b2ed49a5SDavid van Moolenbroek         _magic_selement_t converted_selement = *cached_selement;
1092*b2ed49a5SDavid van Moolenbroek         converted_selement.address = magic_value_buffer;
1093*b2ed49a5SDavid van Moolenbroek         converted_selement.type = local_selement->type;
1094*b2ed49a5SDavid van Moolenbroek         printf("st_cb_map_child_nonaggr_selement_generic: %s while mapping non-aggregate selements:\n", r == MAGIC_ERANGE ? "Precision loss" : "Sign change");
1095*b2ed49a5SDavid van Moolenbroek         MAGIC_SELEMENT_PRINT(cached_selement, MAGIC_EXPAND_TYPE_STR); printf("\n");
1096*b2ed49a5SDavid van Moolenbroek         MAGIC_SELEMENT_PRINT(local_selement, MAGIC_EXPAND_TYPE_STR); printf("\n");
1097*b2ed49a5SDavid van Moolenbroek         printf(" - ORIGINAL VALUE: "); magic_selement_print_value(cached_selement); printf("\n");
1098*b2ed49a5SDavid van Moolenbroek         printf(" - MAPPED   VALUE: "); magic_selement_print_value(&converted_selement); printf("\n");
1099*b2ed49a5SDavid van Moolenbroek     }
1100*b2ed49a5SDavid van Moolenbroek     cached_selement->address = magic_value_buffer;
1101*b2ed49a5SDavid van Moolenbroek }
1102*b2ed49a5SDavid van Moolenbroek 
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)1103*b2ed49a5SDavid van Moolenbroek 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)
1104*b2ed49a5SDavid van Moolenbroek {
1105*b2ed49a5SDavid van Moolenbroek     assert(cached_selement->parent_type && local_selement->parent_type);
1106*b2ed49a5SDavid van Moolenbroek     switch(cached_selement->parent_type->type_id) {
1107*b2ed49a5SDavid van Moolenbroek         case MAGIC_TYPE_ARRAY:
1108*b2ed49a5SDavid van Moolenbroek         case MAGIC_TYPE_VECTOR:
1109*b2ed49a5SDavid van Moolenbroek              st_cb_map_from_parent_array_selement_generic(cached_selement, local_selement, cb_info, is_trg_mapping);
1110*b2ed49a5SDavid van Moolenbroek         break;
1111*b2ed49a5SDavid van Moolenbroek 
1112*b2ed49a5SDavid van Moolenbroek         case MAGIC_TYPE_UNION:
1113*b2ed49a5SDavid van Moolenbroek             st_cb_map_from_parent_union_selement_generic(cached_selement, local_selement, cb_info, is_trg_mapping);
1114*b2ed49a5SDavid van Moolenbroek         break;
1115*b2ed49a5SDavid van Moolenbroek 
1116*b2ed49a5SDavid van Moolenbroek         case MAGIC_TYPE_STRUCT:
1117*b2ed49a5SDavid van Moolenbroek             st_cb_map_from_parent_struct_selement_generic(cached_selement, local_selement, cb_info, is_trg_mapping);
1118*b2ed49a5SDavid van Moolenbroek         break;
1119*b2ed49a5SDavid van Moolenbroek 
1120*b2ed49a5SDavid van Moolenbroek         default:
1121*b2ed49a5SDavid van Moolenbroek             st_cbs_os.panic("Invalid parent type!");
1122*b2ed49a5SDavid van Moolenbroek         break;
1123*b2ed49a5SDavid van Moolenbroek     }
1124*b2ed49a5SDavid van Moolenbroek }
1125*b2ed49a5SDavid van Moolenbroek 
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)1126*b2ed49a5SDavid van Moolenbroek 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)
1127*b2ed49a5SDavid van Moolenbroek {
1128*b2ed49a5SDavid van Moolenbroek     assert(cached_selement->type);
1129*b2ed49a5SDavid van Moolenbroek     if (local_selement->type == NULL) {
1130*b2ed49a5SDavid van Moolenbroek         return;
1131*b2ed49a5SDavid van Moolenbroek     }
1132*b2ed49a5SDavid van Moolenbroek     if (cached_selement->type->num_child_types == 0 || cached_selement->type->type_id == MAGIC_TYPE_POINTER) {
1133*b2ed49a5SDavid van Moolenbroek         st_cb_map_child_nonaggr_selement_generic(cached_selement, local_selement, cb_info, is_trg_mapping);
1134*b2ed49a5SDavid van Moolenbroek         return;
1135*b2ed49a5SDavid van Moolenbroek     }
1136*b2ed49a5SDavid van Moolenbroek     switch (cached_selement->type->type_id) {
1137*b2ed49a5SDavid van Moolenbroek         case MAGIC_TYPE_ARRAY:
1138*b2ed49a5SDavid van Moolenbroek         case MAGIC_TYPE_VECTOR:
1139*b2ed49a5SDavid van Moolenbroek             st_cb_map_child_array_selement_generic(cached_selement, local_selement, cb_info, is_trg_mapping);
1140*b2ed49a5SDavid van Moolenbroek         break;
1141*b2ed49a5SDavid van Moolenbroek 
1142*b2ed49a5SDavid van Moolenbroek         case MAGIC_TYPE_UNION:
1143*b2ed49a5SDavid van Moolenbroek             st_cb_map_child_union_selement_generic(cached_selement, local_selement, cb_info, is_trg_mapping);
1144*b2ed49a5SDavid van Moolenbroek         break;
1145*b2ed49a5SDavid van Moolenbroek 
1146*b2ed49a5SDavid van Moolenbroek         case MAGIC_TYPE_STRUCT:
1147*b2ed49a5SDavid van Moolenbroek             st_cb_map_child_struct_selement_generic(cached_selement, local_selement, cb_info, is_trg_mapping);
1148*b2ed49a5SDavid van Moolenbroek         break;
1149*b2ed49a5SDavid van Moolenbroek 
1150*b2ed49a5SDavid van Moolenbroek         default:
1151*b2ed49a5SDavid van Moolenbroek             st_cbs_os.panic("Invalid parent type!");
1152*b2ed49a5SDavid van Moolenbroek         break;
1153*b2ed49a5SDavid van Moolenbroek     }
1154*b2ed49a5SDavid van Moolenbroek }
1155*b2ed49a5SDavid van Moolenbroek 
1156*b2ed49a5SDavid van Moolenbroek 
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)1157*b2ed49a5SDavid van Moolenbroek 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)
1158*b2ed49a5SDavid van Moolenbroek {
1159*b2ed49a5SDavid van Moolenbroek     int i;
1160*b2ed49a5SDavid van Moolenbroek     assert(cached_selement->type->type_id != MAGIC_TYPE_FUNCTION);
1161*b2ed49a5SDavid van Moolenbroek     for (i = 0 ; i < MAGIC_ST_TYPE_TRANS_ITERATIONS ; i++) {
1162*b2ed49a5SDavid van Moolenbroek         if (cached_selement->parent_type) {
1163*b2ed49a5SDavid van Moolenbroek             st_cb_map_from_parent_selement_generic(cached_selement, local_selement, cb_info, is_trg_mapping);
1164*b2ed49a5SDavid van Moolenbroek         }
1165*b2ed49a5SDavid van Moolenbroek         st_cb_map_child_selement_generic(cached_selement, local_selement, cb_info, is_trg_mapping);
1166*b2ed49a5SDavid van Moolenbroek     }
1167*b2ed49a5SDavid van Moolenbroek }
1168*b2ed49a5SDavid van Moolenbroek 
st_map_selement(_magic_selement_t * cached_selement,_magic_selement_t * local_selement,struct st_cb_info * cb_info,int is_trg_mapping)1169*b2ed49a5SDavid van Moolenbroek 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)
1170*b2ed49a5SDavid van Moolenbroek {
1171*b2ed49a5SDavid van Moolenbroek     const struct _magic_type *cached_parent_type = cached_selement->parent_type;
1172*b2ed49a5SDavid van Moolenbroek     const struct _magic_type *local_parent_type = local_selement->parent_type;
1173*b2ed49a5SDavid van Moolenbroek     const struct _magic_type *cached_type = cached_selement->type;
1174*b2ed49a5SDavid van Moolenbroek 
1175*b2ed49a5SDavid van Moolenbroek     if (cached_parent_type) {
1176*b2ed49a5SDavid van Moolenbroek         if (cached_parent_type == local_parent_type) {
1177*b2ed49a5SDavid van Moolenbroek             /* Quickly propagate perfect type pairs from parents. */
1178*b2ed49a5SDavid van Moolenbroek             local_selement->address = (char *)local_selement->parent_address + ((char *)cached_selement->address - (char *)cached_selement->parent_address);
1179*b2ed49a5SDavid van Moolenbroek             local_selement->type = cached_type;
1180*b2ed49a5SDavid van Moolenbroek             return;
1181*b2ed49a5SDavid van Moolenbroek         }
1182*b2ed49a5SDavid van Moolenbroek         else if (ST_TYPE_IS_CACHED_COUNTERPART(cached_parent_type, local_parent_type)) {
1183*b2ed49a5SDavid van Moolenbroek             /* Quickly propagate type pairs from parents. */
1184*b2ed49a5SDavid van Moolenbroek             st_map_local_selement_from_child_num(local_selement, cb_info, cached_selement->child_num);
1185*b2ed49a5SDavid van Moolenbroek             return;
1186*b2ed49a5SDavid van Moolenbroek         }
1187*b2ed49a5SDavid van Moolenbroek         else {
1188*b2ed49a5SDavid van Moolenbroek             local_selement->type = NULL;
1189*b2ed49a5SDavid van Moolenbroek         }
1190*b2ed49a5SDavid van Moolenbroek     }
1191*b2ed49a5SDavid van Moolenbroek     else {
1192*b2ed49a5SDavid van Moolenbroek         /* In case of target mapping, we don't care about compatible types. When paired types are found, add a perfect type pair to speed up subsequent lookups. */
1193*b2ed49a5SDavid van Moolenbroek         if (ST_TYPE_IS_CACHED_COUNTERPART(cached_type, local_selement->type)) {
1194*b2ed49a5SDavid van Moolenbroek             if (is_trg_mapping) local_selement->type = cached_type;
1195*b2ed49a5SDavid van Moolenbroek             return;
1196*b2ed49a5SDavid van Moolenbroek         }
1197*b2ed49a5SDavid van Moolenbroek     }
1198*b2ed49a5SDavid van Moolenbroek #if CHECK_ASR && !FORCE_SOME_UNPAIRED_TYPES
1199*b2ed49a5SDavid van Moolenbroek     if (cb_info->init_info->flags & ST_LU_ASR) {
1200*b2ed49a5SDavid van Moolenbroek         st_cbs_os.panic("ASR should never get here!");
1201*b2ed49a5SDavid van Moolenbroek     }
1202*b2ed49a5SDavid van Moolenbroek #endif
1203*b2ed49a5SDavid van Moolenbroek 
1204*b2ed49a5SDavid van Moolenbroek     st_num_type_transformations++;
1205*b2ed49a5SDavid van Moolenbroek     st_cbs.st_cb_selement_map(cached_selement, local_selement, cb_info, is_trg_mapping);
1206*b2ed49a5SDavid van Moolenbroek 
1207*b2ed49a5SDavid van Moolenbroek     /* Check again for paired types and add a perfect type pair to speed up subsequent lookups in case of target mapping. */
1208*b2ed49a5SDavid van Moolenbroek     if (is_trg_mapping && local_selement->type != NULL && local_selement->type != cached_selement->type) {
1209*b2ed49a5SDavid van Moolenbroek         if (ST_TYPE_IS_CACHED_COUNTERPART(cached_selement->type, local_selement->type)) {
1210*b2ed49a5SDavid van Moolenbroek             local_selement->type = cached_selement->type;
1211*b2ed49a5SDavid van Moolenbroek         }
1212*b2ed49a5SDavid van Moolenbroek     }
1213*b2ed49a5SDavid van Moolenbroek }
1214*b2ed49a5SDavid van Moolenbroek 
1215*b2ed49a5SDavid van Moolenbroek /* main functions */
1216*b2ed49a5SDavid van Moolenbroek 
st_state_transfer(st_init_info_t * info)1217*b2ed49a5SDavid van Moolenbroek PUBLIC int st_state_transfer(st_init_info_t *info)
1218*b2ed49a5SDavid van Moolenbroek {
1219*b2ed49a5SDavid van Moolenbroek     int r;
1220*b2ed49a5SDavid van Moolenbroek 
1221*b2ed49a5SDavid van Moolenbroek     /*
1222*b2ed49a5SDavid van Moolenbroek      * Set all OS dependent callbacks first.
1223*b2ed49a5SDavid van Moolenbroek      */
1224*b2ed49a5SDavid van Moolenbroek     st_setcb_os_all(&info->st_cbs_os);
1225*b2ed49a5SDavid van Moolenbroek 
1226*b2ed49a5SDavid van Moolenbroek #if ST_ASSUME_RAW_COPY_BEFORE_TRANSFER
1227*b2ed49a5SDavid van Moolenbroek     _magic_vars->fake_malloc = 1;
1228*b2ed49a5SDavid van Moolenbroek #endif
1229*b2ed49a5SDavid van Moolenbroek 
1230*b2ed49a5SDavid van Moolenbroek     r = st_init(info);
1231*b2ed49a5SDavid van Moolenbroek 
1232*b2ed49a5SDavid van Moolenbroek #if ST_ASSUME_RAW_COPY_BEFORE_TRANSFER
1233*b2ed49a5SDavid van Moolenbroek     _magic_vars->fake_malloc = 0;
1234*b2ed49a5SDavid van Moolenbroek #endif
1235*b2ed49a5SDavid van Moolenbroek 
1236*b2ed49a5SDavid van Moolenbroek     if (r != OK) {
1237*b2ed49a5SDavid van Moolenbroek         return r;
1238*b2ed49a5SDavid van Moolenbroek     }
1239*b2ed49a5SDavid van Moolenbroek 
1240*b2ed49a5SDavid van Moolenbroek     r = st_data_transfer(info);
1241*b2ed49a5SDavid van Moolenbroek     if (r != OK) {
1242*b2ed49a5SDavid van Moolenbroek         return r;
1243*b2ed49a5SDavid van Moolenbroek     }
1244*b2ed49a5SDavid van Moolenbroek 
1245*b2ed49a5SDavid van Moolenbroek #if ST_DEBUG_LEVEL > 0
1246*b2ed49a5SDavid van Moolenbroek     printf("st_state_transfer: state transfer is done, num type transformations: %u.\n", st_num_type_transformations);
1247*b2ed49a5SDavid van Moolenbroek #endif
1248*b2ed49a5SDavid van Moolenbroek 
1249*b2ed49a5SDavid van Moolenbroek     st_cleanup(info);
1250*b2ed49a5SDavid van Moolenbroek 
1251*b2ed49a5SDavid van Moolenbroek     return OK;
1252*b2ed49a5SDavid van Moolenbroek }
1253*b2ed49a5SDavid van Moolenbroek 
1254*b2ed49a5SDavid van Moolenbroek #if APPARENTLY_UNUSED
st_set_policies(int policies)1255*b2ed49a5SDavid van Moolenbroek PUBLIC void st_set_policies(int policies)
1256*b2ed49a5SDavid van Moolenbroek {
1257*b2ed49a5SDavid van Moolenbroek     st_policies = policies;
1258*b2ed49a5SDavid van Moolenbroek }
1259*b2ed49a5SDavid van Moolenbroek #endif
1260*b2ed49a5SDavid van Moolenbroek 
1261*b2ed49a5SDavid van Moolenbroek #if MAGIC_LOOKUP_SENTRY_ALLOW_RANGE_INDEX
st_init_rl_index(st_init_info_t * info,struct _magic_vars_t * magic_vars)1262*b2ed49a5SDavid van Moolenbroek PRIVATE void st_init_rl_index(st_init_info_t *info,
1263*b2ed49a5SDavid van Moolenbroek     struct _magic_vars_t *magic_vars)
1264*b2ed49a5SDavid van Moolenbroek {
1265*b2ed49a5SDavid van Moolenbroek     size_t buff_size;
1266*b2ed49a5SDavid van Moolenbroek     void *buff;
1267*b2ed49a5SDavid van Moolenbroek 
1268*b2ed49a5SDavid van Moolenbroek     EXEC_WITH_MAGIC_VARS(
1269*b2ed49a5SDavid van Moolenbroek         buff_size = magic_sentry_rl_estimate_index_buff_size(0);
1270*b2ed49a5SDavid van Moolenbroek         , magic_vars
1271*b2ed49a5SDavid van Moolenbroek     );
1272*b2ed49a5SDavid van Moolenbroek     buff = st_buff_allocate(info, buff_size);
1273*b2ed49a5SDavid van Moolenbroek 
1274*b2ed49a5SDavid van Moolenbroek     EXEC_WITH_MAGIC_VARS(
1275*b2ed49a5SDavid van Moolenbroek         magic_sentry_rl_build_index(buff, buff_size);
1276*b2ed49a5SDavid van Moolenbroek         , magic_vars
1277*b2ed49a5SDavid van Moolenbroek     );
1278*b2ed49a5SDavid van Moolenbroek }
1279*b2ed49a5SDavid van Moolenbroek 
st_cleanup_rl_index(st_init_info_t * info,struct _magic_vars_t * magic_vars)1280*b2ed49a5SDavid van Moolenbroek PRIVATE void st_cleanup_rl_index(st_init_info_t *info,
1281*b2ed49a5SDavid van Moolenbroek     struct _magic_vars_t *magic_vars)
1282*b2ed49a5SDavid van Moolenbroek {
1283*b2ed49a5SDavid van Moolenbroek     EXEC_WITH_MAGIC_VARS(
1284*b2ed49a5SDavid van Moolenbroek         magic_sentry_rl_destroy_index();
1285*b2ed49a5SDavid van Moolenbroek         , magic_vars
1286*b2ed49a5SDavid van Moolenbroek     );
1287*b2ed49a5SDavid van Moolenbroek }
1288*b2ed49a5SDavid van Moolenbroek #endif
1289*b2ed49a5SDavid van Moolenbroek 
1290*b2ed49a5SDavid van Moolenbroek #if MAGIC_LOOKUP_SENTRY_ALLOW_NAME_HASH
st_init_sentry_hash(st_init_info_t * info,struct _magic_vars_t * magic_vars)1291*b2ed49a5SDavid van Moolenbroek PRIVATE void st_init_sentry_hash(st_init_info_t *info,
1292*b2ed49a5SDavid van Moolenbroek     struct _magic_vars_t *magic_vars)
1293*b2ed49a5SDavid van Moolenbroek {
1294*b2ed49a5SDavid van Moolenbroek     size_t buff_size;
1295*b2ed49a5SDavid van Moolenbroek     void *buff;
1296*b2ed49a5SDavid van Moolenbroek 
1297*b2ed49a5SDavid van Moolenbroek     EXEC_WITH_MAGIC_VARS(
1298*b2ed49a5SDavid van Moolenbroek         buff_size = magic_sentry_hash_estimate_buff_size(0);
1299*b2ed49a5SDavid van Moolenbroek         , magic_vars
1300*b2ed49a5SDavid van Moolenbroek     );
1301*b2ed49a5SDavid van Moolenbroek     buff = st_buff_allocate(info, buff_size);
1302*b2ed49a5SDavid van Moolenbroek 
1303*b2ed49a5SDavid van Moolenbroek     EXEC_WITH_MAGIC_VARS(
1304*b2ed49a5SDavid van Moolenbroek         magic_sentry_hash_build(buff, buff_size);
1305*b2ed49a5SDavid van Moolenbroek         , magic_vars
1306*b2ed49a5SDavid van Moolenbroek     );
1307*b2ed49a5SDavid van Moolenbroek }
1308*b2ed49a5SDavid van Moolenbroek 
st_cleanup_sentry_hash(st_init_info_t * info,struct _magic_vars_t * magic_vars)1309*b2ed49a5SDavid van Moolenbroek PRIVATE void st_cleanup_sentry_hash(st_init_info_t *info,
1310*b2ed49a5SDavid van Moolenbroek     struct _magic_vars_t *magic_vars)
1311*b2ed49a5SDavid van Moolenbroek {
1312*b2ed49a5SDavid van Moolenbroek     EXEC_WITH_MAGIC_VARS(
1313*b2ed49a5SDavid van Moolenbroek         magic_sentry_hash_destroy();
1314*b2ed49a5SDavid van Moolenbroek         , magic_vars
1315*b2ed49a5SDavid van Moolenbroek     );
1316*b2ed49a5SDavid van Moolenbroek }
1317*b2ed49a5SDavid van Moolenbroek #endif
1318*b2ed49a5SDavid van Moolenbroek 
1319*b2ed49a5SDavid van Moolenbroek #if MAGIC_LOOKUP_FUNCTION_ALLOW_ADDR_HASH
st_init_function_hash(st_init_info_t * info,struct _magic_vars_t * magic_vars)1320*b2ed49a5SDavid van Moolenbroek PRIVATE void st_init_function_hash(st_init_info_t *info,
1321*b2ed49a5SDavid van Moolenbroek     struct _magic_vars_t *magic_vars)
1322*b2ed49a5SDavid van Moolenbroek {
1323*b2ed49a5SDavid van Moolenbroek     size_t buff_size;
1324*b2ed49a5SDavid van Moolenbroek     void *buff;
1325*b2ed49a5SDavid van Moolenbroek 
1326*b2ed49a5SDavid van Moolenbroek     EXEC_WITH_MAGIC_VARS(
1327*b2ed49a5SDavid van Moolenbroek         buff_size = magic_function_hash_estimate_buff_size(0);
1328*b2ed49a5SDavid van Moolenbroek         , magic_vars
1329*b2ed49a5SDavid van Moolenbroek     );
1330*b2ed49a5SDavid van Moolenbroek     buff = st_buff_allocate(info, buff_size);
1331*b2ed49a5SDavid van Moolenbroek 
1332*b2ed49a5SDavid van Moolenbroek     EXEC_WITH_MAGIC_VARS(
1333*b2ed49a5SDavid van Moolenbroek         magic_function_hash_build(buff, buff_size);
1334*b2ed49a5SDavid van Moolenbroek         , magic_vars
1335*b2ed49a5SDavid van Moolenbroek     );
1336*b2ed49a5SDavid van Moolenbroek }
1337*b2ed49a5SDavid van Moolenbroek 
st_cleanup_function_hash(st_init_info_t * info,struct _magic_vars_t * magic_vars)1338*b2ed49a5SDavid van Moolenbroek PRIVATE void st_cleanup_function_hash(st_init_info_t *info,
1339*b2ed49a5SDavid van Moolenbroek     struct _magic_vars_t *magic_vars)
1340*b2ed49a5SDavid van Moolenbroek {
1341*b2ed49a5SDavid van Moolenbroek     EXEC_WITH_MAGIC_VARS(
1342*b2ed49a5SDavid van Moolenbroek         magic_function_hash_destroy();
1343*b2ed49a5SDavid van Moolenbroek         , magic_vars
1344*b2ed49a5SDavid van Moolenbroek     );
1345*b2ed49a5SDavid van Moolenbroek }
1346*b2ed49a5SDavid van Moolenbroek #endif
1347*b2ed49a5SDavid van Moolenbroek 
st_vars_clear_ptrs(struct _magic_vars_t * magic_vars)1348*b2ed49a5SDavid van Moolenbroek PRIVATE void st_vars_clear_ptrs(struct _magic_vars_t *magic_vars)
1349*b2ed49a5SDavid van Moolenbroek {
1350*b2ed49a5SDavid van Moolenbroek #undef __X
1351*b2ed49a5SDavid van Moolenbroek #define __X(x) offsetof(struct _magic_vars_t, x)
1352*b2ed49a5SDavid van Moolenbroek     size_t offset_list[] = { ST_MAGIC_VARS_PTR_CLEAR_LIST };
1353*b2ed49a5SDavid van Moolenbroek #undef __X
1354*b2ed49a5SDavid van Moolenbroek     unsigned int i;
1355*b2ed49a5SDavid van Moolenbroek 
1356*b2ed49a5SDavid van Moolenbroek     for (i = 0 ; i < sizeof(offset_list) / sizeof(size_t) ; i++)
1357*b2ed49a5SDavid van Moolenbroek         *((void **)(((char *)magic_vars) + offset_list[i])) = NULL;
1358*b2ed49a5SDavid van Moolenbroek }
1359*b2ed49a5SDavid van Moolenbroek 
1360*b2ed49a5SDavid van Moolenbroek 
1361*b2ed49a5SDavid van Moolenbroek #ifdef __MINIX
st_unmap_mem(struct _magic_vars_t * magic_vars)1362*b2ed49a5SDavid van Moolenbroek PRIVATE void st_unmap_mem(struct _magic_vars_t *magic_vars)
1363*b2ed49a5SDavid van Moolenbroek {
1364*b2ed49a5SDavid van Moolenbroek     int i, r;
1365*b2ed49a5SDavid van Moolenbroek 
1366*b2ed49a5SDavid van Moolenbroek     for (i = 0; i < MAGIC_UNMAP_MEM_ENTRIES; i++) {
1367*b2ed49a5SDavid van Moolenbroek         if (magic_vars->unmap_mem[i].length != 0) {
1368*b2ed49a5SDavid van Moolenbroek #if ST_DEBUG_LEVEL > 0
1369*b2ed49a5SDavid van Moolenbroek             printf("st_unmap_mem: unmapping (%p, %zu)\n",
1370*b2ed49a5SDavid van Moolenbroek                 magic_vars->unmap_mem[i].start,
1371*b2ed49a5SDavid van Moolenbroek                 magic_vars->unmap_mem[i].length);
1372*b2ed49a5SDavid van Moolenbroek #endif
1373*b2ed49a5SDavid van Moolenbroek             r = munmap(magic_vars->unmap_mem[i].start,
1374*b2ed49a5SDavid van Moolenbroek                 magic_vars->unmap_mem[i].length);
1375*b2ed49a5SDavid van Moolenbroek             assert(r == 0);
1376*b2ed49a5SDavid van Moolenbroek         }
1377*b2ed49a5SDavid van Moolenbroek     }
1378*b2ed49a5SDavid van Moolenbroek }
1379*b2ed49a5SDavid van Moolenbroek #endif
1380*b2ed49a5SDavid van Moolenbroek 
st_init(st_init_info_t * info)1381*b2ed49a5SDavid van Moolenbroek PUBLIC int st_init(st_init_info_t *info)
1382*b2ed49a5SDavid van Moolenbroek {
1383*b2ed49a5SDavid van Moolenbroek     size_t max_buff_sz = 0;
1384*b2ed49a5SDavid van Moolenbroek     int r, dsentries_num;
1385*b2ed49a5SDavid van Moolenbroek     int allow_unpaired_types = TRUE;
1386*b2ed49a5SDavid van Moolenbroek     if (st_init_done) {
1387*b2ed49a5SDavid van Moolenbroek         return OK;
1388*b2ed49a5SDavid van Moolenbroek     }
1389*b2ed49a5SDavid van Moolenbroek     if (!_magic_enabled) return ENOSYS;
1390*b2ed49a5SDavid van Moolenbroek     st_init_done = TRUE;
1391*b2ed49a5SDavid van Moolenbroek 
1392*b2ed49a5SDavid van Moolenbroek     /* Ignore nested mempool dsentries for now. */
1393*b2ed49a5SDavid van Moolenbroek     magic_lookup_nested_dsentries = 0;
1394*b2ed49a5SDavid van Moolenbroek 
1395*b2ed49a5SDavid van Moolenbroek     /* Override default state transfer policies for ASR. */
1396*b2ed49a5SDavid van Moolenbroek     if ((info->flags & ST_LU_ASR) && st_policies == ST_POLICIES_DEFAULT) {
1397*b2ed49a5SDavid van Moolenbroek         st_policies = ST_POLICIES_DEFAULT_TRANSFER_ASR;
1398*b2ed49a5SDavid van Moolenbroek     }
1399*b2ed49a5SDavid van Moolenbroek 
1400*b2ed49a5SDavid van Moolenbroek     /* Fixup state transfer policies based on current configuration. */
1401*b2ed49a5SDavid van Moolenbroek #if ST_ASSUME_RAW_COPY_BEFORE_TRANSFER
1402*b2ed49a5SDavid van Moolenbroek     st_policies &= (~ST_DEFAULT_ALLOC_CASCADE_XFER);
1403*b2ed49a5SDavid van Moolenbroek #elif !defined(__MINIX)
1404*b2ed49a5SDavid van Moolenbroek     st_policies |= ST_TRANSFER_DIRTY_ONLY;
1405*b2ed49a5SDavid van Moolenbroek #endif
1406*b2ed49a5SDavid van Moolenbroek 
1407*b2ed49a5SDavid van Moolenbroek     assert((!info->init_buff_start || (info->flags & ST_LU_NOMMAP)) && "st_init: no mmapping allowed, and no buffer is available");
1408*b2ed49a5SDavid van Moolenbroek     register_typenames_and_callbacks();
1409*b2ed49a5SDavid van Moolenbroek 
1410*b2ed49a5SDavid van Moolenbroek     /* Transfer _magic_vars, which contain addresses of the magic variables */
1411*b2ed49a5SDavid van Moolenbroek     r = st_cbs_os.old_state_table_lookup(info->info_opaque, &st_remote_magic_vars);
1412*b2ed49a5SDavid van Moolenbroek     assert( r == OK && "ERROR occurred during transfer of _magic_vars.");
1413*b2ed49a5SDavid van Moolenbroek     /*
1414*b2ed49a5SDavid van Moolenbroek      * Clear all pointers not explictly transferred, as they are not valid in
1415*b2ed49a5SDavid van Moolenbroek      * the new address space.
1416*b2ed49a5SDavid van Moolenbroek      */
1417*b2ed49a5SDavid van Moolenbroek     st_vars_clear_ptrs(&st_remote_magic_vars);
1418*b2ed49a5SDavid van Moolenbroek 
1419*b2ed49a5SDavid van Moolenbroek     /*
1420*b2ed49a5SDavid van Moolenbroek      * Some magic_vars members do not need transfer or adjustment
1421*b2ed49a5SDavid van Moolenbroek      * (e.g. the memory ranges). They are copied to st_cached_magic_vars
1422*b2ed49a5SDavid van Moolenbroek      * this way.
1423*b2ed49a5SDavid van Moolenbroek      */
1424*b2ed49a5SDavid van Moolenbroek     st_cached_magic_vars = st_remote_magic_vars;
1425*b2ed49a5SDavid van Moolenbroek 
1426*b2ed49a5SDavid van Moolenbroek     /* Transfer and adjust metadata */
1427*b2ed49a5SDavid van Moolenbroek     r = st_transfer_metadata_types(info, &st_cached_magic_vars, &st_remote_magic_vars, &st_counterparts);
1428*b2ed49a5SDavid van Moolenbroek     assert( r == OK && "ERROR occurred during transfer of type metadata.");
1429*b2ed49a5SDavid van Moolenbroek     r = transfer_metadata_functions(info, &st_cached_magic_vars, &st_remote_magic_vars, &st_counterparts);
1430*b2ed49a5SDavid van Moolenbroek     assert( r == OK && "ERROR occurred during transfer of function metadata.");
1431*b2ed49a5SDavid van Moolenbroek     r = transfer_metadata_dfunctions(info, &st_cached_magic_vars, &st_remote_magic_vars, &st_counterparts);
1432*b2ed49a5SDavid van Moolenbroek     assert( r == OK && "ERROR occurred during transfer of dfunction metadata.");
1433*b2ed49a5SDavid van Moolenbroek     r = transfer_metadata_sentries(info, &st_cached_magic_vars, &st_remote_magic_vars, &st_counterparts, &max_buff_sz);
1434*b2ed49a5SDavid van Moolenbroek     assert( r == OK && "ERROR occurred during transfer of sentry metadata.");
1435*b2ed49a5SDavid van Moolenbroek     r = st_transfer_metadata_dsentries(info, &st_cached_magic_vars, &st_remote_magic_vars, &st_counterparts, &max_buff_sz, &dsentries_num);
1436*b2ed49a5SDavid van Moolenbroek     assert( r == OK && "ERROR occurred during transfer of dsentry metadata.");
1437*b2ed49a5SDavid van Moolenbroek 
1438*b2ed49a5SDavid van Moolenbroek     /* Allocate buffer for data transfer */
1439*b2ed49a5SDavid van Moolenbroek     st_dsentry_buff = st_buff_allocate(info, max_buff_sz + sizeof(struct _magic_dsentry));
1440*b2ed49a5SDavid van Moolenbroek     if (!st_dsentry_buff) {
1441*b2ed49a5SDavid van Moolenbroek         printf("st_dsentry_buff could not be allocated.\n");
1442*b2ed49a5SDavid van Moolenbroek         return EGENERIC;
1443*b2ed49a5SDavid van Moolenbroek     }
1444*b2ed49a5SDavid van Moolenbroek     st_data_buff = &st_dsentry_buff[1];
1445*b2ed49a5SDavid van Moolenbroek 
1446*b2ed49a5SDavid van Moolenbroek     /* Allocate and initialize counterparts buffers. */
1447*b2ed49a5SDavid van Moolenbroek     st_counterparts.functions_size = st_cached_magic_vars.functions_num;
1448*b2ed49a5SDavid van Moolenbroek     st_counterparts.functions = st_buff_allocate(info, st_counterparts.functions_size * sizeof(st_ptr_mapping));
1449*b2ed49a5SDavid van Moolenbroek     assert(st_counterparts.functions && "st_counterparts.functions could not be allocated.");
1450*b2ed49a5SDavid van Moolenbroek 
1451*b2ed49a5SDavid van Moolenbroek     st_counterparts.types_size = st_cached_magic_vars.types_num;
1452*b2ed49a5SDavid van Moolenbroek     st_counterparts.types = st_buff_allocate(info, st_counterparts.types_size * sizeof(st_ptr_mapping));
1453*b2ed49a5SDavid van Moolenbroek     assert(st_counterparts.types && "st_counterparts.types could not be allocated.");
1454*b2ed49a5SDavid van Moolenbroek     st_counterparts.ptr_types = st_buff_allocate(info, st_counterparts.types_size * sizeof(st_ptr_mapping));
1455*b2ed49a5SDavid van Moolenbroek     assert(st_counterparts.ptr_types && "st_counterparts.ptr_types could not be allocated.");
1456*b2ed49a5SDavid van Moolenbroek 
1457*b2ed49a5SDavid van Moolenbroek     st_counterparts.sentries_size = st_cached_magic_vars.sentries_num + dsentries_num;
1458*b2ed49a5SDavid van Moolenbroek     st_counterparts.sentries = st_buff_allocate(info, st_counterparts.sentries_size * sizeof(st_ptr_mapping));
1459*b2ed49a5SDavid van Moolenbroek     assert(st_counterparts.sentries && "st_counterparts.sentries could not be allocated.");
1460*b2ed49a5SDavid van Moolenbroek     st_counterparts.sentries_data = st_buff_allocate(info, st_counterparts.sentries_size * sizeof(st_ptr_mapping));
1461*b2ed49a5SDavid van Moolenbroek     assert(st_counterparts.sentries_data && "st_counterparts.sentries_data could not be allocated.");
1462*b2ed49a5SDavid van Moolenbroek 
1463*b2ed49a5SDavid van Moolenbroek #if MAGIC_LOOKUP_SENTRY_ALLOW_RANGE_INDEX
1464*b2ed49a5SDavid van Moolenbroek     st_init_rl_index(info, &st_cached_magic_vars);
1465*b2ed49a5SDavid van Moolenbroek #endif
1466*b2ed49a5SDavid van Moolenbroek 
1467*b2ed49a5SDavid van Moolenbroek #if MAGIC_LOOKUP_SENTRY_ALLOW_NAME_HASH
1468*b2ed49a5SDavid van Moolenbroek     st_init_sentry_hash(info, &st_cached_magic_vars);
1469*b2ed49a5SDavid van Moolenbroek     st_init_sentry_hash(info, _magic_vars);
1470*b2ed49a5SDavid van Moolenbroek #endif
1471*b2ed49a5SDavid van Moolenbroek 
1472*b2ed49a5SDavid van Moolenbroek #if MAGIC_LOOKUP_FUNCTION_ALLOW_ADDR_HASH
1473*b2ed49a5SDavid van Moolenbroek     st_init_function_hash(info, &st_cached_magic_vars);
1474*b2ed49a5SDavid van Moolenbroek     st_init_function_hash(info, _magic_vars);
1475*b2ed49a5SDavid van Moolenbroek #endif
1476*b2ed49a5SDavid van Moolenbroek 
1477*b2ed49a5SDavid van Moolenbroek #ifdef __MINIX
1478*b2ed49a5SDavid van Moolenbroek     /* Unmap any memory ranges that are not needed in the new process. */
1479*b2ed49a5SDavid van Moolenbroek     st_unmap_mem(&st_cached_magic_vars);
1480*b2ed49a5SDavid van Moolenbroek #endif
1481*b2ed49a5SDavid van Moolenbroek 
1482*b2ed49a5SDavid van Moolenbroek     /* Pair metadata entities */
1483*b2ed49a5SDavid van Moolenbroek     r = pair_metadata_types(info, &st_cached_magic_vars, &st_counterparts, allow_unpaired_types);
1484*b2ed49a5SDavid van Moolenbroek     assert( r == OK && "ERROR occurred during call to pair_metadata_types().");
1485*b2ed49a5SDavid van Moolenbroek     r = pair_metadata_functions(info, &st_cached_magic_vars, &st_counterparts);
1486*b2ed49a5SDavid van Moolenbroek     assert( r == OK && "ERROR occurred during call to pair_metadata_functions().");
1487*b2ed49a5SDavid van Moolenbroek     r = pair_metadata_sentries(info, &st_cached_magic_vars, &st_counterparts);
1488*b2ed49a5SDavid van Moolenbroek     assert( r == OK && "ERROR occurred during call to pair_metadata_sentries().");
1489*b2ed49a5SDavid van Moolenbroek #if ST_ASSUME_RAW_COPY_BEFORE_TRANSFER
1490*b2ed49a5SDavid van Moolenbroek     r = allocate_pair_metadata_dsentries_from_raw_copy(info, &st_cached_magic_vars, &st_counterparts);
1491*b2ed49a5SDavid van Moolenbroek     assert( r == OK && "ERROR occurred during call to allocate_pair_metadata_dsentries().");
1492*b2ed49a5SDavid van Moolenbroek #else
1493*b2ed49a5SDavid van Moolenbroek     r = allocate_pair_metadata_dsentries(info, &st_cached_magic_vars, &st_counterparts);
1494*b2ed49a5SDavid van Moolenbroek     assert( r == OK && "ERROR occurred during call to allocate_pair_metadata_dsentries().");
1495*b2ed49a5SDavid van Moolenbroek #endif
1496*b2ed49a5SDavid van Moolenbroek 
1497*b2ed49a5SDavid van Moolenbroek     /* Set state transfer status defaults from the predefined policies. */
1498*b2ed49a5SDavid van Moolenbroek     st_set_status_defaults(info);
1499*b2ed49a5SDavid van Moolenbroek 
1500*b2ed49a5SDavid van Moolenbroek #if MAGIC_LOOKUP_SENTRY_ALLOW_RANGE_INDEX
1501*b2ed49a5SDavid van Moolenbroek     st_init_rl_index(info, _magic_vars);
1502*b2ed49a5SDavid van Moolenbroek #endif
1503*b2ed49a5SDavid van Moolenbroek 
1504*b2ed49a5SDavid van Moolenbroek     return OK;
1505*b2ed49a5SDavid van Moolenbroek }
1506*b2ed49a5SDavid van Moolenbroek 
st_lookup_str_local_data(struct _magic_sentry * cached_sentry)1507*b2ed49a5SDavid van Moolenbroek PRIVATE INLINE char* st_lookup_str_local_data(struct _magic_sentry *cached_sentry)
1508*b2ed49a5SDavid van Moolenbroek {
1509*b2ed49a5SDavid van Moolenbroek     void *local_data_addr;
1510*b2ed49a5SDavid van Moolenbroek     assert(cached_sentry && MAGIC_SENTRY_IS_STRING(cached_sentry));
1511*b2ed49a5SDavid van Moolenbroek     ST_GET_CACHED_COUNTERPART(cached_sentry, sentries, sentries_data, local_data_addr);
1512*b2ed49a5SDavid van Moolenbroek     assert(local_data_addr && "String data not in cache!");
1513*b2ed49a5SDavid van Moolenbroek     return (char*) local_data_addr;
1514*b2ed49a5SDavid van Moolenbroek }
1515*b2ed49a5SDavid van Moolenbroek 
1516*b2ed49a5SDavid van Moolenbroek #if ST_DEBUG_DATA_TRANSFER
st_print_sentities(struct _magic_vars_t * magic_vars)1517*b2ed49a5SDavid van Moolenbroek PRIVATE void st_print_sentities(struct _magic_vars_t *magic_vars)
1518*b2ed49a5SDavid van Moolenbroek {
1519*b2ed49a5SDavid van Moolenbroek     struct _magic_dsentry *dsentry = magic_vars->first_dsentry;
1520*b2ed49a5SDavid van Moolenbroek     int i;
1521*b2ed49a5SDavid van Moolenbroek 
1522*b2ed49a5SDavid van Moolenbroek     for (i = 0 ; i < magic_vars->sentries_num ; i++) {
1523*b2ed49a5SDavid van Moolenbroek         struct _magic_sentry *sentry = &magic_vars->sentries[i];
1524*b2ed49a5SDavid van Moolenbroek         ST_SENTRY_PRINT(sentry, 0);
1525*b2ed49a5SDavid van Moolenbroek         printf("\n");
1526*b2ed49a5SDavid van Moolenbroek     }
1527*b2ed49a5SDavid van Moolenbroek 
1528*b2ed49a5SDavid van Moolenbroek     while (dsentry != NULL) {
1529*b2ed49a5SDavid van Moolenbroek         ST_DSENTRY_PRINT(dsentry, 0);
1530*b2ed49a5SDavid van Moolenbroek         printf("\n");
1531*b2ed49a5SDavid van Moolenbroek         dsentry = dsentry->next;
1532*b2ed49a5SDavid van Moolenbroek     }
1533*b2ed49a5SDavid van Moolenbroek 
1534*b2ed49a5SDavid van Moolenbroek     for (i = 0 ; i < magic_vars->functions_num ; i++) {
1535*b2ed49a5SDavid van Moolenbroek         struct _magic_function *function = &magic_vars->functions[i];
1536*b2ed49a5SDavid van Moolenbroek         ST_FUNCTION_PRINT(function, 0);
1537*b2ed49a5SDavid van Moolenbroek         printf("\n");
1538*b2ed49a5SDavid van Moolenbroek     }
1539*b2ed49a5SDavid van Moolenbroek }
1540*b2ed49a5SDavid van Moolenbroek #endif
1541*b2ed49a5SDavid van Moolenbroek 
st_map_str_sentries(struct _magic_sentry ** cached_sentry_ptr,struct _magic_sentry ** local_sentry_ptr)1542*b2ed49a5SDavid van Moolenbroek PUBLIC void st_map_str_sentries(struct _magic_sentry **cached_sentry_ptr, struct _magic_sentry **local_sentry_ptr)
1543*b2ed49a5SDavid van Moolenbroek {
1544*b2ed49a5SDavid van Moolenbroek     struct _magic_sentry *cached_sentry = *cached_sentry_ptr;
1545*b2ed49a5SDavid van Moolenbroek     struct _magic_sentry *local_sentry = *local_sentry_ptr;
1546*b2ed49a5SDavid van Moolenbroek     struct _magic_sentry *sentry = cached_sentry ? cached_sentry : local_sentry;
1547*b2ed49a5SDavid van Moolenbroek     int string_flags, match_by_name, match_by_content;
1548*b2ed49a5SDavid van Moolenbroek     ST_CHECK_INIT();
1549*b2ed49a5SDavid van Moolenbroek     assert((cached_sentry == NULL) ^ (local_sentry == NULL));
1550*b2ed49a5SDavid van Moolenbroek 
1551*b2ed49a5SDavid van Moolenbroek     string_flags = sentry->flags & (MAGIC_STATE_STRING|MAGIC_STATE_NAMED_STRING);
1552*b2ed49a5SDavid van Moolenbroek     assert(string_flags & MAGIC_STATE_STRING);
1553*b2ed49a5SDavid van Moolenbroek     match_by_name = (string_flags & MAGIC_STATE_NAMED_STRING) && (st_policies & ST_MAP_NAMED_STRINGS_BY_NAME);
1554*b2ed49a5SDavid van Moolenbroek     match_by_content = ((string_flags & MAGIC_STATE_NAMED_STRING) && (st_policies & ST_MAP_NAMED_STRINGS_BY_CONTENT))
1555*b2ed49a5SDavid van Moolenbroek         || (!(string_flags & MAGIC_STATE_NAMED_STRING) && (st_policies & ST_MAP_STRINGS_BY_CONTENT));
1556*b2ed49a5SDavid van Moolenbroek     if (match_by_name) {
1557*b2ed49a5SDavid van Moolenbroek         /* Pretend it's a regular sentry and match by name */
1558*b2ed49a5SDavid van Moolenbroek         sentry->flags &= ~string_flags;
1559*b2ed49a5SDavid van Moolenbroek         st_map_sentries(cached_sentry_ptr, local_sentry_ptr);
1560*b2ed49a5SDavid van Moolenbroek         sentry->flags |= string_flags;
1561*b2ed49a5SDavid van Moolenbroek         if (*cached_sentry_ptr && *local_sentry_ptr) {
1562*b2ed49a5SDavid van Moolenbroek             /* Found by name. */
1563*b2ed49a5SDavid van Moolenbroek             return;
1564*b2ed49a5SDavid van Moolenbroek         }
1565*b2ed49a5SDavid van Moolenbroek     }
1566*b2ed49a5SDavid van Moolenbroek     if (!match_by_content) {
1567*b2ed49a5SDavid van Moolenbroek         /* No match. */
1568*b2ed49a5SDavid van Moolenbroek         return;
1569*b2ed49a5SDavid van Moolenbroek     }
1570*b2ed49a5SDavid van Moolenbroek     if (cached_sentry) {
1571*b2ed49a5SDavid van Moolenbroek         EXEC_WITH_MAGIC_VARS(
1572*b2ed49a5SDavid van Moolenbroek             local_sentry = magic_sentry_lookup_by_string(st_lookup_str_local_data(cached_sentry));
1573*b2ed49a5SDavid van Moolenbroek             , st_local_magic_vars_ptr
1574*b2ed49a5SDavid van Moolenbroek         );
1575*b2ed49a5SDavid van Moolenbroek     }
1576*b2ed49a5SDavid van Moolenbroek     else {
1577*b2ed49a5SDavid van Moolenbroek         int i;
1578*b2ed49a5SDavid van Moolenbroek         for(i = 0 ; i < st_cached_magic_vars.sentries_num ; i++) {
1579*b2ed49a5SDavid van Moolenbroek             sentry = &st_cached_magic_vars.sentries[i];
1580*b2ed49a5SDavid van Moolenbroek             if (MAGIC_SENTRY_IS_STRING(sentry) && !strcmp(st_lookup_str_local_data(sentry), (char*)local_sentry->address)) {
1581*b2ed49a5SDavid van Moolenbroek                 cached_sentry = sentry;
1582*b2ed49a5SDavid van Moolenbroek                 break;
1583*b2ed49a5SDavid van Moolenbroek             }
1584*b2ed49a5SDavid van Moolenbroek         }
1585*b2ed49a5SDavid van Moolenbroek     }
1586*b2ed49a5SDavid van Moolenbroek     *cached_sentry_ptr = cached_sentry;
1587*b2ed49a5SDavid van Moolenbroek     *local_sentry_ptr = local_sentry;
1588*b2ed49a5SDavid van Moolenbroek }
1589*b2ed49a5SDavid van Moolenbroek 
st_map_sentries(struct _magic_sentry ** cached_sentry_ptr,struct _magic_sentry ** local_sentry_ptr)1590*b2ed49a5SDavid van Moolenbroek PUBLIC void st_map_sentries(struct _magic_sentry **cached_sentry_ptr, struct _magic_sentry **local_sentry_ptr)
1591*b2ed49a5SDavid van Moolenbroek {
1592*b2ed49a5SDavid van Moolenbroek     struct _magic_sentry *cached_sentry = *cached_sentry_ptr;
1593*b2ed49a5SDavid van Moolenbroek     struct _magic_sentry *local_sentry = *local_sentry_ptr;
1594*b2ed49a5SDavid van Moolenbroek     struct _magic_dsentry *cached_dsentry = cached_sentry ? (MAGIC_STATE_FLAG(cached_sentry, MAGIC_STATE_DYNAMIC) ? MAGIC_DSENTRY_FROM_SENTRY(cached_sentry) : NULL) : NULL;
1595*b2ed49a5SDavid van Moolenbroek     struct _magic_dsentry *local_dsentry = local_sentry ? (MAGIC_STATE_FLAG(local_sentry, MAGIC_STATE_DYNAMIC) ? MAGIC_DSENTRY_FROM_SENTRY(local_sentry) : NULL) : NULL;
1596*b2ed49a5SDavid van Moolenbroek     ST_CHECK_INIT();
1597*b2ed49a5SDavid van Moolenbroek     assert((cached_sentry == NULL) ^ (local_sentry == NULL));
1598*b2ed49a5SDavid van Moolenbroek 
1599*b2ed49a5SDavid van Moolenbroek     if ((cached_sentry && MAGIC_STATE_FLAG(cached_sentry, MAGIC_STATE_STRING))
1600*b2ed49a5SDavid van Moolenbroek         || (local_sentry && MAGIC_STATE_FLAG(local_sentry, MAGIC_STATE_STRING))) {
1601*b2ed49a5SDavid van Moolenbroek             st_map_str_sentries(cached_sentry_ptr, local_sentry_ptr);
1602*b2ed49a5SDavid van Moolenbroek             return;
1603*b2ed49a5SDavid van Moolenbroek     }
1604*b2ed49a5SDavid van Moolenbroek     else if (cached_sentry) {
1605*b2ed49a5SDavid van Moolenbroek         EXEC_WITH_MAGIC_VARS(
1606*b2ed49a5SDavid van Moolenbroek             local_sentry = magic_sentry_lookup_by_name(cached_dsentry ? cached_dsentry->parent_name : "", cached_sentry->name, cached_dsentry ? cached_dsentry->site_id : 0, NULL);
1607*b2ed49a5SDavid van Moolenbroek             , st_local_magic_vars_ptr
1608*b2ed49a5SDavid van Moolenbroek         );
1609*b2ed49a5SDavid van Moolenbroek         assert(!local_sentry || MAGIC_STATE_FLAG(cached_sentry, MAGIC_STATE_DYNAMIC) == MAGIC_STATE_FLAG(local_sentry, MAGIC_STATE_DYNAMIC));
1610*b2ed49a5SDavid van Moolenbroek     }
1611*b2ed49a5SDavid van Moolenbroek     else {
1612*b2ed49a5SDavid van Moolenbroek         EXEC_WITH_MAGIC_VARS(
1613*b2ed49a5SDavid van Moolenbroek             cached_sentry = magic_sentry_lookup_by_name(local_dsentry ? local_dsentry->parent_name : "", local_sentry->name, local_dsentry ? local_dsentry->site_id : 0, NULL);
1614*b2ed49a5SDavid van Moolenbroek             , &st_cached_magic_vars
1615*b2ed49a5SDavid van Moolenbroek         );
1616*b2ed49a5SDavid van Moolenbroek         assert(!cached_sentry || MAGIC_STATE_FLAG(local_sentry, MAGIC_STATE_DYNAMIC) == MAGIC_STATE_FLAG(cached_sentry, MAGIC_STATE_DYNAMIC));
1617*b2ed49a5SDavid van Moolenbroek     }
1618*b2ed49a5SDavid van Moolenbroek     *cached_sentry_ptr = cached_sentry;
1619*b2ed49a5SDavid van Moolenbroek     *local_sentry_ptr = local_sentry;
1620*b2ed49a5SDavid van Moolenbroek }
1621*b2ed49a5SDavid van Moolenbroek 
st_lookup_cached_sentry(struct _magic_sentry * local_sentry)1622*b2ed49a5SDavid van Moolenbroek PRIVATE struct _magic_sentry *st_lookup_cached_sentry(struct _magic_sentry *local_sentry)
1623*b2ed49a5SDavid van Moolenbroek {
1624*b2ed49a5SDavid van Moolenbroek     int i;
1625*b2ed49a5SDavid van Moolenbroek     struct _magic_dsentry *cached_dsentry;
1626*b2ed49a5SDavid van Moolenbroek     assert(local_sentry);
1627*b2ed49a5SDavid van Moolenbroek 
1628*b2ed49a5SDavid van Moolenbroek     for (i = 0 ; i < st_counterparts.sentries_size ; i++) {
1629*b2ed49a5SDavid van Moolenbroek         if (st_counterparts.sentries[i].counterpart == local_sentry) {
1630*b2ed49a5SDavid van Moolenbroek             break;
1631*b2ed49a5SDavid van Moolenbroek         }
1632*b2ed49a5SDavid van Moolenbroek     }
1633*b2ed49a5SDavid van Moolenbroek     if (i >= st_counterparts.sentries_size) {
1634*b2ed49a5SDavid van Moolenbroek         return NULL;
1635*b2ed49a5SDavid van Moolenbroek     }
1636*b2ed49a5SDavid van Moolenbroek     if (i < st_cached_magic_vars.sentries_num) {
1637*b2ed49a5SDavid van Moolenbroek         return &st_cached_magic_vars.sentries[i];
1638*b2ed49a5SDavid van Moolenbroek     }
1639*b2ed49a5SDavid van Moolenbroek     i -= st_cached_magic_vars.sentries_num;
1640*b2ed49a5SDavid van Moolenbroek     cached_dsentry = st_cached_magic_vars.first_dsentry;
1641*b2ed49a5SDavid van Moolenbroek     assert(i >= 0);
1642*b2ed49a5SDavid van Moolenbroek     assert(cached_dsentry);
1643*b2ed49a5SDavid van Moolenbroek     while (i > 0) {
1644*b2ed49a5SDavid van Moolenbroek         cached_dsentry = cached_dsentry->next;
1645*b2ed49a5SDavid van Moolenbroek         assert(cached_dsentry);
1646*b2ed49a5SDavid van Moolenbroek         i--;
1647*b2ed49a5SDavid van Moolenbroek     }
1648*b2ed49a5SDavid van Moolenbroek     return MAGIC_DSENTRY_TO_SENTRY(cached_dsentry);
1649*b2ed49a5SDavid van Moolenbroek }
1650*b2ed49a5SDavid van Moolenbroek 
st_lookup_sentry_pair(struct _magic_sentry ** cached_sentry_ptr,struct _magic_sentry ** local_sentry_ptr)1651*b2ed49a5SDavid van Moolenbroek PUBLIC void st_lookup_sentry_pair(struct _magic_sentry **cached_sentry_ptr, struct _magic_sentry **local_sentry_ptr)
1652*b2ed49a5SDavid van Moolenbroek {
1653*b2ed49a5SDavid van Moolenbroek     struct _magic_sentry *cached_sentry = *cached_sentry_ptr;
1654*b2ed49a5SDavid van Moolenbroek     struct _magic_sentry *local_sentry = *local_sentry_ptr;
1655*b2ed49a5SDavid van Moolenbroek     ST_CHECK_INIT();
1656*b2ed49a5SDavid van Moolenbroek     assert((cached_sentry == NULL) ^ (local_sentry == NULL));
1657*b2ed49a5SDavid van Moolenbroek 
1658*b2ed49a5SDavid van Moolenbroek     if (cached_sentry) {
1659*b2ed49a5SDavid van Moolenbroek         ST_GET_CACHED_COUNTERPART(cached_sentry, sentries, sentries, local_sentry);
1660*b2ed49a5SDavid van Moolenbroek     }
1661*b2ed49a5SDavid van Moolenbroek     else if (MAGIC_SENTRY_IS_STRING(local_sentry)) {
1662*b2ed49a5SDavid van Moolenbroek         /* strings are special, they may have multiple local duplicates */
1663*b2ed49a5SDavid van Moolenbroek         struct _magic_sentry *csentry = NULL, *lsentry = NULL;
1664*b2ed49a5SDavid van Moolenbroek         st_map_str_sentries(&csentry, &local_sentry);
1665*b2ed49a5SDavid van Moolenbroek         if (csentry) {
1666*b2ed49a5SDavid van Moolenbroek             st_lookup_sentry_pair(&csentry, &lsentry);
1667*b2ed49a5SDavid van Moolenbroek             if (lsentry) {
1668*b2ed49a5SDavid van Moolenbroek                 cached_sentry = csentry;
1669*b2ed49a5SDavid van Moolenbroek             }
1670*b2ed49a5SDavid van Moolenbroek         }
1671*b2ed49a5SDavid van Moolenbroek     }
1672*b2ed49a5SDavid van Moolenbroek     else {
1673*b2ed49a5SDavid van Moolenbroek         cached_sentry = st_lookup_cached_sentry(local_sentry);
1674*b2ed49a5SDavid van Moolenbroek     }
1675*b2ed49a5SDavid van Moolenbroek     *cached_sentry_ptr = cached_sentry;
1676*b2ed49a5SDavid van Moolenbroek     *local_sentry_ptr = local_sentry;
1677*b2ed49a5SDavid van Moolenbroek }
1678*b2ed49a5SDavid van Moolenbroek 
st_unpair_local_alloc_sentry(struct _magic_sentry * local_sentry)1679*b2ed49a5SDavid van Moolenbroek PRIVATE INLINE void st_unpair_local_alloc_sentry(struct _magic_sentry *local_sentry)
1680*b2ed49a5SDavid van Moolenbroek {
1681*b2ed49a5SDavid van Moolenbroek     if (st_policies & ST_ON_ALLOC_UNPAIR_ERROR) {
1682*b2ed49a5SDavid van Moolenbroek         st_cbs_os.panic("st_unpair_local_alloc_sentry: Error: attempting to unpair a local alloc sentry!");
1683*b2ed49a5SDavid van Moolenbroek     }
1684*b2ed49a5SDavid van Moolenbroek     else if (st_policies & ST_ON_ALLOC_UNPAIR_DEALLOCATE) {
1685*b2ed49a5SDavid van Moolenbroek         deallocate_local_dsentry(MAGIC_DSENTRY_FROM_SENTRY(local_sentry));
1686*b2ed49a5SDavid van Moolenbroek     }
1687*b2ed49a5SDavid van Moolenbroek }
1688*b2ed49a5SDavid van Moolenbroek 
st_add_sentry_pair(struct _magic_sentry * cached_sentry,struct _magic_sentry * local_sentry)1689*b2ed49a5SDavid van Moolenbroek PUBLIC void st_add_sentry_pair(struct _magic_sentry *cached_sentry, struct _magic_sentry *local_sentry)
1690*b2ed49a5SDavid van Moolenbroek {
1691*b2ed49a5SDavid van Moolenbroek     ST_CHECK_INIT();
1692*b2ed49a5SDavid van Moolenbroek     assert(cached_sentry || local_sentry);
1693*b2ed49a5SDavid van Moolenbroek 
1694*b2ed49a5SDavid van Moolenbroek     if (local_sentry) {
1695*b2ed49a5SDavid van Moolenbroek         struct _magic_sentry *csentry = NULL;
1696*b2ed49a5SDavid van Moolenbroek         st_lookup_sentry_pair(&csentry, &local_sentry);
1697*b2ed49a5SDavid van Moolenbroek         if (csentry) {
1698*b2ed49a5SDavid van Moolenbroek             ST_SET_CACHED_COUNTERPART(csentry, sentries, sentries, NULL);
1699*b2ed49a5SDavid van Moolenbroek         }
1700*b2ed49a5SDavid van Moolenbroek         if (!cached_sentry && MAGIC_SENTRY_IS_ALLOC(local_sentry)) {
1701*b2ed49a5SDavid van Moolenbroek             st_unpair_local_alloc_sentry(local_sentry);
1702*b2ed49a5SDavid van Moolenbroek         }
1703*b2ed49a5SDavid van Moolenbroek     }
1704*b2ed49a5SDavid van Moolenbroek     if (cached_sentry) {
1705*b2ed49a5SDavid van Moolenbroek         struct _magic_sentry *lsentry = NULL;
1706*b2ed49a5SDavid van Moolenbroek         st_lookup_sentry_pair(&cached_sentry, &lsentry);
1707*b2ed49a5SDavid van Moolenbroek         if (lsentry && MAGIC_SENTRY_IS_ALLOC(lsentry)) {
1708*b2ed49a5SDavid van Moolenbroek             st_unpair_local_alloc_sentry(lsentry);
1709*b2ed49a5SDavid van Moolenbroek         }
1710*b2ed49a5SDavid van Moolenbroek         ST_SET_CACHED_COUNTERPART(cached_sentry, sentries, sentries, local_sentry);
1711*b2ed49a5SDavid van Moolenbroek     }
1712*b2ed49a5SDavid van Moolenbroek }
1713*b2ed49a5SDavid van Moolenbroek 
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)1714*b2ed49a5SDavid van Moolenbroek 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)
1715*b2ed49a5SDavid van Moolenbroek {
1716*b2ed49a5SDavid van Moolenbroek     int r;
1717*b2ed49a5SDavid van Moolenbroek     struct _magic_dsentry *local_dsentry;
1718*b2ed49a5SDavid van Moolenbroek     ST_CHECK_INIT();
1719*b2ed49a5SDavid van Moolenbroek     assert(cached_sentry);
1720*b2ed49a5SDavid van Moolenbroek 
1721*b2ed49a5SDavid van Moolenbroek     if (!local_dsindex) {
1722*b2ed49a5SDavid van Moolenbroek         st_add_sentry_pair(cached_sentry, NULL);
1723*b2ed49a5SDavid van Moolenbroek         return OK;
1724*b2ed49a5SDavid van Moolenbroek     }
1725*b2ed49a5SDavid van Moolenbroek 
1726*b2ed49a5SDavid van Moolenbroek     r = allocate_local_dsentry(info, local_dsindex, num_elements, MAGIC_STATE_FLAG(cached_sentry, MAGIC_STATE_TYPE_SIZE_MISMATCH), p_alloc_flags, &local_dsentry, NULL, MAGIC_PTR_TO_DSENTRY(cached_sentry->address));
1727*b2ed49a5SDavid van Moolenbroek     if (r != OK) {
1728*b2ed49a5SDavid van Moolenbroek         return r;
1729*b2ed49a5SDavid van Moolenbroek     }
1730*b2ed49a5SDavid van Moolenbroek     st_add_sentry_pair(cached_sentry, MAGIC_DSENTRY_TO_SENTRY(local_dsentry));
1731*b2ed49a5SDavid van Moolenbroek     return OK;
1732*b2ed49a5SDavid van Moolenbroek }
1733*b2ed49a5SDavid van Moolenbroek 
st_map_functions(struct _magic_function ** cached_function_ptr,struct _magic_function ** local_function_ptr)1734*b2ed49a5SDavid van Moolenbroek PUBLIC void st_map_functions(struct _magic_function **cached_function_ptr, struct _magic_function **local_function_ptr)
1735*b2ed49a5SDavid van Moolenbroek {
1736*b2ed49a5SDavid van Moolenbroek     struct _magic_function *cached_function = *cached_function_ptr;
1737*b2ed49a5SDavid van Moolenbroek     struct _magic_function *local_function = *local_function_ptr;
1738*b2ed49a5SDavid van Moolenbroek     ST_CHECK_INIT();
1739*b2ed49a5SDavid van Moolenbroek     assert((cached_function == NULL) ^ (local_function == NULL));
1740*b2ed49a5SDavid van Moolenbroek 
1741*b2ed49a5SDavid van Moolenbroek     if (cached_function) {
1742*b2ed49a5SDavid van Moolenbroek         EXEC_WITH_MAGIC_VARS(
1743*b2ed49a5SDavid van Moolenbroek             local_function = magic_function_lookup_by_name(NULL, cached_function->name);
1744*b2ed49a5SDavid van Moolenbroek             , st_local_magic_vars_ptr
1745*b2ed49a5SDavid van Moolenbroek         );
1746*b2ed49a5SDavid van Moolenbroek     }
1747*b2ed49a5SDavid van Moolenbroek     else {
1748*b2ed49a5SDavid van Moolenbroek         EXEC_WITH_MAGIC_VARS(
1749*b2ed49a5SDavid van Moolenbroek             cached_function = magic_function_lookup_by_name(NULL, local_function->name);
1750*b2ed49a5SDavid van Moolenbroek             , &st_cached_magic_vars
1751*b2ed49a5SDavid van Moolenbroek         );
1752*b2ed49a5SDavid van Moolenbroek     }
1753*b2ed49a5SDavid van Moolenbroek     *cached_function_ptr = cached_function;
1754*b2ed49a5SDavid van Moolenbroek     *local_function_ptr = local_function;
1755*b2ed49a5SDavid van Moolenbroek }
1756*b2ed49a5SDavid van Moolenbroek 
st_lookup_function_pair(struct _magic_function ** cached_function_ptr,struct _magic_function ** local_function_ptr)1757*b2ed49a5SDavid van Moolenbroek PUBLIC void st_lookup_function_pair(struct _magic_function **cached_function_ptr, struct _magic_function **local_function_ptr)
1758*b2ed49a5SDavid van Moolenbroek {
1759*b2ed49a5SDavid van Moolenbroek     struct _magic_function *cached_function = *cached_function_ptr;
1760*b2ed49a5SDavid van Moolenbroek     struct _magic_function *local_function = *local_function_ptr;
1761*b2ed49a5SDavid van Moolenbroek     int i;
1762*b2ed49a5SDavid van Moolenbroek     ST_CHECK_INIT();
1763*b2ed49a5SDavid van Moolenbroek     assert((cached_function == NULL) ^ (local_function == NULL));
1764*b2ed49a5SDavid van Moolenbroek 
1765*b2ed49a5SDavid van Moolenbroek     if (cached_function) {
1766*b2ed49a5SDavid van Moolenbroek         if ((int)cached_function->id - 1 >= st_counterparts.functions_size) {
1767*b2ed49a5SDavid van Moolenbroek             /*
1768*b2ed49a5SDavid van Moolenbroek              * Try to check if this is a function
1769*b2ed49a5SDavid van Moolenbroek              * from an external shared object.
1770*b2ed49a5SDavid van Moolenbroek              * XXX: The number of dfunctions can be quite large,
1771*b2ed49a5SDavid van Moolenbroek              * so this needs to be done more efficiently.
1772*b2ed49a5SDavid van Moolenbroek              */
1773*b2ed49a5SDavid van Moolenbroek             struct _magic_dfunction *dfunc;
1774*b2ed49a5SDavid van Moolenbroek             struct _magic_function *func;
1775*b2ed49a5SDavid van Moolenbroek             MAGIC_DFUNCTION_FUNC_ITER(_magic_vars->first_dfunction, dfunc, func,
1776*b2ed49a5SDavid van Moolenbroek                 if (func->address == cached_function->address) {
1777*b2ed49a5SDavid van Moolenbroek                     local_function = func;
1778*b2ed49a5SDavid van Moolenbroek                     break;
1779*b2ed49a5SDavid van Moolenbroek                 }
1780*b2ed49a5SDavid van Moolenbroek             );
1781*b2ed49a5SDavid van Moolenbroek             assert(local_function != NULL && "No counterpart found for function.");
1782*b2ed49a5SDavid van Moolenbroek         } else {
1783*b2ed49a5SDavid van Moolenbroek             ST_GET_CACHED_COUNTERPART(cached_function, functions, functions, local_function);
1784*b2ed49a5SDavid van Moolenbroek         }
1785*b2ed49a5SDavid van Moolenbroek     }
1786*b2ed49a5SDavid van Moolenbroek     else {
1787*b2ed49a5SDavid van Moolenbroek         assert(st_counterparts.functions_size == st_cached_magic_vars.functions_num);
1788*b2ed49a5SDavid van Moolenbroek         for(i = 0 ; i < st_counterparts.functions_size ; i++) {
1789*b2ed49a5SDavid van Moolenbroek             if(st_counterparts.functions[i].counterpart == local_function) {
1790*b2ed49a5SDavid van Moolenbroek                 cached_function = &st_cached_magic_vars.functions[i];
1791*b2ed49a5SDavid van Moolenbroek                 break;
1792*b2ed49a5SDavid van Moolenbroek             }
1793*b2ed49a5SDavid van Moolenbroek         }
1794*b2ed49a5SDavid van Moolenbroek     }
1795*b2ed49a5SDavid van Moolenbroek     *cached_function_ptr = cached_function;
1796*b2ed49a5SDavid van Moolenbroek     *local_function_ptr = local_function;
1797*b2ed49a5SDavid van Moolenbroek }
1798*b2ed49a5SDavid van Moolenbroek 
st_add_function_pair(struct _magic_function * cached_function,struct _magic_function * local_function)1799*b2ed49a5SDavid van Moolenbroek PUBLIC void st_add_function_pair(struct _magic_function *cached_function, struct _magic_function *local_function)
1800*b2ed49a5SDavid van Moolenbroek {
1801*b2ed49a5SDavid van Moolenbroek     ST_CHECK_INIT();
1802*b2ed49a5SDavid van Moolenbroek     assert(cached_function || local_function);
1803*b2ed49a5SDavid van Moolenbroek 
1804*b2ed49a5SDavid van Moolenbroek     if (local_function) {
1805*b2ed49a5SDavid van Moolenbroek         struct _magic_function *cfunction = NULL;
1806*b2ed49a5SDavid van Moolenbroek         st_lookup_function_pair(&cfunction, &local_function);
1807*b2ed49a5SDavid van Moolenbroek         if (cfunction) {
1808*b2ed49a5SDavid van Moolenbroek             ST_SET_CACHED_COUNTERPART(cfunction, functions, functions, NULL);
1809*b2ed49a5SDavid van Moolenbroek         }
1810*b2ed49a5SDavid van Moolenbroek     }
1811*b2ed49a5SDavid van Moolenbroek     if (cached_function) {
1812*b2ed49a5SDavid van Moolenbroek         ST_SET_CACHED_COUNTERPART(cached_function, functions, functions, local_function);
1813*b2ed49a5SDavid van Moolenbroek     }
1814*b2ed49a5SDavid van Moolenbroek }
1815*b2ed49a5SDavid van Moolenbroek 
st_sentry_equals(struct _magic_sentry * cached_sentry,struct _magic_sentry * local_sentry)1816*b2ed49a5SDavid van Moolenbroek PUBLIC int st_sentry_equals(struct _magic_sentry *cached_sentry, struct _magic_sentry *local_sentry)
1817*b2ed49a5SDavid van Moolenbroek {
1818*b2ed49a5SDavid van Moolenbroek     const char *cached_parent_name = "", *local_parent_name = "";
1819*b2ed49a5SDavid van Moolenbroek     int cached_flags = MAGIC_STATE_FLAGS_TO_NONEXTF(cached_sentry->flags) & (~MAGIC_STATE_ADDR_NOT_TAKEN);
1820*b2ed49a5SDavid van Moolenbroek     int local_flags = MAGIC_STATE_FLAGS_TO_NONEXTF(local_sentry->flags) & (~MAGIC_STATE_ADDR_NOT_TAKEN);
1821*b2ed49a5SDavid van Moolenbroek     if (cached_flags != local_flags) {
1822*b2ed49a5SDavid van Moolenbroek         return FALSE;
1823*b2ed49a5SDavid van Moolenbroek     }
1824*b2ed49a5SDavid van Moolenbroek     if (MAGIC_STATE_FLAG(cached_sentry, MAGIC_STATE_STRING)) {
1825*b2ed49a5SDavid van Moolenbroek         return !strcmp(st_lookup_str_local_data(cached_sentry), (char*)local_sentry->address);
1826*b2ed49a5SDavid van Moolenbroek     }
1827*b2ed49a5SDavid van Moolenbroek     if (MAGIC_STATE_FLAG(cached_sentry, MAGIC_STATE_DYNAMIC)) {
1828*b2ed49a5SDavid van Moolenbroek         cached_parent_name = MAGIC_DSENTRY_FROM_SENTRY(cached_sentry)->parent_name;
1829*b2ed49a5SDavid van Moolenbroek         local_parent_name = MAGIC_DSENTRY_FROM_SENTRY(local_sentry)->parent_name;
1830*b2ed49a5SDavid van Moolenbroek     }
1831*b2ed49a5SDavid van Moolenbroek     if (strcmp(cached_sentry->name, local_sentry->name) || strcmp(cached_parent_name, local_parent_name)) {
1832*b2ed49a5SDavid van Moolenbroek         return FALSE;
1833*b2ed49a5SDavid van Moolenbroek     }
1834*b2ed49a5SDavid van Moolenbroek     return magic_type_compatible(cached_sentry->type, local_sentry->type, MAGIC_TYPE_COMPARE_ALL);
1835*b2ed49a5SDavid van Moolenbroek }
1836*b2ed49a5SDavid van Moolenbroek 
st_function_equals(struct _magic_function * cached_function,struct _magic_function * local_function)1837*b2ed49a5SDavid van Moolenbroek PUBLIC int st_function_equals(struct _magic_function *cached_function, struct _magic_function *local_function)
1838*b2ed49a5SDavid van Moolenbroek {
1839*b2ed49a5SDavid van Moolenbroek     if (MAGIC_STATE_FLAGS_TO_NONEXTF(local_function->flags) != MAGIC_STATE_FLAGS_TO_NONEXTF(cached_function->flags)) {
1840*b2ed49a5SDavid van Moolenbroek         return FALSE;
1841*b2ed49a5SDavid van Moolenbroek     }
1842*b2ed49a5SDavid van Moolenbroek     return !strcmp(cached_function->name, local_function->name);
1843*b2ed49a5SDavid van Moolenbroek }
1844*b2ed49a5SDavid van Moolenbroek 
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)1845*b2ed49a5SDavid van Moolenbroek 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)
1846*b2ed49a5SDavid van Moolenbroek {
1847*b2ed49a5SDavid van Moolenbroek     int is_paired_sentry;
1848*b2ed49a5SDavid van Moolenbroek     ST_CHECK_INIT();
1849*b2ed49a5SDavid van Moolenbroek 
1850*b2ed49a5SDavid van Moolenbroek     if (!cached_sentry || !local_sentry) {
1851*b2ed49a5SDavid van Moolenbroek         if (raw_diff) {
1852*b2ed49a5SDavid van Moolenbroek             st_map_sentries(&cached_sentry, &local_sentry);
1853*b2ed49a5SDavid van Moolenbroek         }
1854*b2ed49a5SDavid van Moolenbroek         else {
1855*b2ed49a5SDavid van Moolenbroek             st_lookup_sentry_pair(&cached_sentry, &local_sentry);
1856*b2ed49a5SDavid van Moolenbroek         }
1857*b2ed49a5SDavid van Moolenbroek     }
1858*b2ed49a5SDavid van Moolenbroek     is_paired_sentry = (cached_sentry != NULL && local_sentry != NULL);
1859*b2ed49a5SDavid van Moolenbroek     if (is_paired_sentry && st_sentry_equals(cached_sentry, local_sentry)) {
1860*b2ed49a5SDavid van Moolenbroek         return;
1861*b2ed49a5SDavid van Moolenbroek     }
1862*b2ed49a5SDavid van Moolenbroek     if (is_paired_sentry && !print_changed) {
1863*b2ed49a5SDavid van Moolenbroek         return;
1864*b2ed49a5SDavid van Moolenbroek     }
1865*b2ed49a5SDavid van Moolenbroek     if (cached_sentry) {
1866*b2ed49a5SDavid van Moolenbroek         printf("-"); ST_SENTRY_PRINT(cached_sentry, MAGIC_EXPAND_TYPE_STR); printf("\n");
1867*b2ed49a5SDavid van Moolenbroek     }
1868*b2ed49a5SDavid van Moolenbroek     if (local_sentry) {
1869*b2ed49a5SDavid van Moolenbroek         printf("+"); ST_SENTRY_PRINT(local_sentry, MAGIC_EXPAND_TYPE_STR); printf("\n");
1870*b2ed49a5SDavid van Moolenbroek     }
1871*b2ed49a5SDavid van Moolenbroek     printf("\n");
1872*b2ed49a5SDavid van Moolenbroek }
1873*b2ed49a5SDavid van Moolenbroek 
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)1874*b2ed49a5SDavid van Moolenbroek 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)
1875*b2ed49a5SDavid van Moolenbroek {
1876*b2ed49a5SDavid van Moolenbroek     int is_paired_function;
1877*b2ed49a5SDavid van Moolenbroek     ST_CHECK_INIT();
1878*b2ed49a5SDavid van Moolenbroek 
1879*b2ed49a5SDavid van Moolenbroek     if (!cached_function || !local_function) {
1880*b2ed49a5SDavid van Moolenbroek         if (raw_diff) {
1881*b2ed49a5SDavid van Moolenbroek             st_map_functions(&cached_function, &local_function);
1882*b2ed49a5SDavid van Moolenbroek         }
1883*b2ed49a5SDavid van Moolenbroek         else {
1884*b2ed49a5SDavid van Moolenbroek             st_lookup_function_pair(&cached_function, &local_function);
1885*b2ed49a5SDavid van Moolenbroek         }
1886*b2ed49a5SDavid van Moolenbroek     }
1887*b2ed49a5SDavid van Moolenbroek     is_paired_function = (cached_function != NULL && local_function != NULL);
1888*b2ed49a5SDavid van Moolenbroek     if (is_paired_function && st_function_equals(cached_function, local_function)) {
1889*b2ed49a5SDavid van Moolenbroek         return;
1890*b2ed49a5SDavid van Moolenbroek     }
1891*b2ed49a5SDavid van Moolenbroek     if (is_paired_function && !print_changed) {
1892*b2ed49a5SDavid van Moolenbroek         return;
1893*b2ed49a5SDavid van Moolenbroek     }
1894*b2ed49a5SDavid van Moolenbroek     if (cached_function) {
1895*b2ed49a5SDavid van Moolenbroek         printf("-"); ST_FUNCTION_PRINT(cached_function, MAGIC_EXPAND_TYPE_STR); printf("\n");
1896*b2ed49a5SDavid van Moolenbroek     }
1897*b2ed49a5SDavid van Moolenbroek     if (local_function) {
1898*b2ed49a5SDavid van Moolenbroek         printf("+"); ST_FUNCTION_PRINT(local_function, MAGIC_EXPAND_TYPE_STR); printf("\n");
1899*b2ed49a5SDavid van Moolenbroek     }
1900*b2ed49a5SDavid van Moolenbroek     printf("\n");
1901*b2ed49a5SDavid van Moolenbroek }
1902*b2ed49a5SDavid van Moolenbroek 
st_print_sentries_diff(st_init_info_t * info,int raw_diff,int print_changed)1903*b2ed49a5SDavid van Moolenbroek PUBLIC void st_print_sentries_diff(st_init_info_t *info, int raw_diff, int print_changed)
1904*b2ed49a5SDavid van Moolenbroek {
1905*b2ed49a5SDavid van Moolenbroek     int i;
1906*b2ed49a5SDavid van Moolenbroek     ST_CHECK_INIT();
1907*b2ed49a5SDavid van Moolenbroek 
1908*b2ed49a5SDavid van Moolenbroek     for (i = 0 ; i < st_cached_magic_vars.sentries_num ; i++) {
1909*b2ed49a5SDavid van Moolenbroek         struct _magic_sentry *cached_sentry = &st_cached_magic_vars.sentries[i];
1910*b2ed49a5SDavid van Moolenbroek         st_print_sentry_diff(info, cached_sentry, NULL, raw_diff, print_changed);
1911*b2ed49a5SDavid van Moolenbroek     }
1912*b2ed49a5SDavid van Moolenbroek 
1913*b2ed49a5SDavid van Moolenbroek     print_changed = FALSE;
1914*b2ed49a5SDavid van Moolenbroek     for (i = 0 ; i < st_local_magic_vars_ptr->sentries_num ; i++) {
1915*b2ed49a5SDavid van Moolenbroek         struct _magic_sentry *local_sentry = &st_local_magic_vars_ptr->sentries[i];
1916*b2ed49a5SDavid van Moolenbroek         st_print_sentry_diff(info, NULL, local_sentry, raw_diff, print_changed);
1917*b2ed49a5SDavid van Moolenbroek     }
1918*b2ed49a5SDavid van Moolenbroek }
1919*b2ed49a5SDavid van Moolenbroek 
st_print_dsentries_diff(st_init_info_t * info,int raw_diff,int print_changed)1920*b2ed49a5SDavid van Moolenbroek PUBLIC void st_print_dsentries_diff(st_init_info_t *info, int raw_diff, int print_changed)
1921*b2ed49a5SDavid van Moolenbroek {
1922*b2ed49a5SDavid van Moolenbroek     struct _magic_dsentry *dsentry;
1923*b2ed49a5SDavid van Moolenbroek     ST_CHECK_INIT();
1924*b2ed49a5SDavid van Moolenbroek 
1925*b2ed49a5SDavid van Moolenbroek     dsentry = st_cached_magic_vars.first_dsentry;
1926*b2ed49a5SDavid van Moolenbroek     while (dsentry != NULL) {
1927*b2ed49a5SDavid van Moolenbroek         struct _magic_sentry *cached_sentry = MAGIC_DSENTRY_TO_SENTRY(dsentry);
1928*b2ed49a5SDavid van Moolenbroek         st_print_sentry_diff(info, cached_sentry, NULL, raw_diff, print_changed);
1929*b2ed49a5SDavid van Moolenbroek         dsentry = dsentry->next;
1930*b2ed49a5SDavid van Moolenbroek     }
1931*b2ed49a5SDavid van Moolenbroek 
1932*b2ed49a5SDavid van Moolenbroek     dsentry = st_local_magic_vars_ptr->first_dsentry;
1933*b2ed49a5SDavid van Moolenbroek     print_changed = FALSE;
1934*b2ed49a5SDavid van Moolenbroek     while (dsentry != NULL) {
1935*b2ed49a5SDavid van Moolenbroek         struct _magic_sentry *local_sentry = MAGIC_DSENTRY_TO_SENTRY(dsentry);
1936*b2ed49a5SDavid van Moolenbroek         st_print_sentry_diff(info, NULL, local_sentry, raw_diff, print_changed);
1937*b2ed49a5SDavid van Moolenbroek         dsentry = dsentry->next;
1938*b2ed49a5SDavid van Moolenbroek     }
1939*b2ed49a5SDavid van Moolenbroek }
1940*b2ed49a5SDavid van Moolenbroek 
st_print_functions_diff(st_init_info_t * info,int raw_diff,int print_changed)1941*b2ed49a5SDavid van Moolenbroek PUBLIC void st_print_functions_diff(st_init_info_t *info, int raw_diff, int print_changed)
1942*b2ed49a5SDavid van Moolenbroek {
1943*b2ed49a5SDavid van Moolenbroek     int i;
1944*b2ed49a5SDavid van Moolenbroek     ST_CHECK_INIT();
1945*b2ed49a5SDavid van Moolenbroek 
1946*b2ed49a5SDavid van Moolenbroek     for(i = 0 ; i < st_cached_magic_vars.functions_num ; i++) {
1947*b2ed49a5SDavid van Moolenbroek         struct _magic_function *cached_function = &st_cached_magic_vars.functions[i];
1948*b2ed49a5SDavid van Moolenbroek         st_print_function_diff(info, cached_function, NULL, raw_diff, print_changed);
1949*b2ed49a5SDavid van Moolenbroek     }
1950*b2ed49a5SDavid van Moolenbroek 
1951*b2ed49a5SDavid van Moolenbroek     print_changed = FALSE;
1952*b2ed49a5SDavid van Moolenbroek     for (i = 0 ; i < st_local_magic_vars_ptr->functions_num ; i++) {
1953*b2ed49a5SDavid van Moolenbroek         struct _magic_function *local_function = &st_local_magic_vars_ptr->functions[i];
1954*b2ed49a5SDavid van Moolenbroek         st_print_function_diff(info, NULL, local_function, raw_diff, print_changed);
1955*b2ed49a5SDavid van Moolenbroek     }
1956*b2ed49a5SDavid van Moolenbroek }
1957*b2ed49a5SDavid van Moolenbroek 
st_print_state_diff(st_init_info_t * info,int raw_diff,int print_changed)1958*b2ed49a5SDavid van Moolenbroek PUBLIC void st_print_state_diff(st_init_info_t *info, int raw_diff, int print_changed)
1959*b2ed49a5SDavid van Moolenbroek {
1960*b2ed49a5SDavid van Moolenbroek     ST_CHECK_INIT();
1961*b2ed49a5SDavid van Moolenbroek 
1962*b2ed49a5SDavid van Moolenbroek     printf("Index: sentries\n");
1963*b2ed49a5SDavid van Moolenbroek     printf("===================================================================\n");
1964*b2ed49a5SDavid van Moolenbroek     st_print_sentries_diff(info, raw_diff, print_changed);
1965*b2ed49a5SDavid van Moolenbroek 
1966*b2ed49a5SDavid van Moolenbroek     printf("\nIndex: dsentries\n");
1967*b2ed49a5SDavid van Moolenbroek     printf("===================================================================\n");
1968*b2ed49a5SDavid van Moolenbroek     st_print_dsentries_diff(info, raw_diff, print_changed);
1969*b2ed49a5SDavid van Moolenbroek 
1970*b2ed49a5SDavid van Moolenbroek     printf("\nIndex: functions\n");
1971*b2ed49a5SDavid van Moolenbroek     printf("===================================================================\n");
1972*b2ed49a5SDavid van Moolenbroek     st_print_functions_diff(info, raw_diff, print_changed);
1973*b2ed49a5SDavid van Moolenbroek     printf("\n");
1974*b2ed49a5SDavid van Moolenbroek }
1975*b2ed49a5SDavid van Moolenbroek 
st_data_transfer(st_init_info_t * info)1976*b2ed49a5SDavid van Moolenbroek PUBLIC int st_data_transfer(st_init_info_t *info)
1977*b2ed49a5SDavid van Moolenbroek {
1978*b2ed49a5SDavid van Moolenbroek     struct _magic_dsentry *dsentry;
1979*b2ed49a5SDavid van Moolenbroek     int i, r;
1980*b2ed49a5SDavid van Moolenbroek     int sentry_transferred;
1981*b2ed49a5SDavid van Moolenbroek #if ST_DEBUG_DATA_TRANSFER
1982*b2ed49a5SDavid van Moolenbroek     int counter = 1;
1983*b2ed49a5SDavid van Moolenbroek #endif
1984*b2ed49a5SDavid van Moolenbroek     ST_CHECK_INIT();
1985*b2ed49a5SDavid van Moolenbroek 
1986*b2ed49a5SDavid van Moolenbroek     /* Check unpaired sentries. */
1987*b2ed49a5SDavid van Moolenbroek     for (i = 0 ; i < st_cached_magic_vars.sentries_num ; i++) {
1988*b2ed49a5SDavid van Moolenbroek         struct _magic_sentry *sentry = &st_cached_magic_vars.sentries[i];
1989*b2ed49a5SDavid van Moolenbroek         int is_paired_sentry = ST_HAS_CACHED_COUNTERPART(sentry, sentries);
1990*b2ed49a5SDavid van Moolenbroek         if (!is_paired_sentry) {
1991*b2ed49a5SDavid van Moolenbroek             r = check_unpaired_sentry(info, sentry);
1992*b2ed49a5SDavid van Moolenbroek             if (r != OK) {
1993*b2ed49a5SDavid van Moolenbroek                 return r;
1994*b2ed49a5SDavid van Moolenbroek             }
1995*b2ed49a5SDavid van Moolenbroek         }
1996*b2ed49a5SDavid van Moolenbroek     }
1997*b2ed49a5SDavid van Moolenbroek 
1998*b2ed49a5SDavid van Moolenbroek     /* Check unpaired dsentries. */
1999*b2ed49a5SDavid van Moolenbroek     dsentry = st_cached_magic_vars.first_dsentry;
2000*b2ed49a5SDavid van Moolenbroek     while (dsentry != NULL) {
2001*b2ed49a5SDavid van Moolenbroek         struct _magic_sentry *sentry = MAGIC_DSENTRY_TO_SENTRY(dsentry);
2002*b2ed49a5SDavid van Moolenbroek         int is_paired_sentry = ST_HAS_CACHED_COUNTERPART(sentry, sentries);
2003*b2ed49a5SDavid van Moolenbroek         if (!is_paired_sentry) {
2004*b2ed49a5SDavid van Moolenbroek             r = check_unpaired_sentry(info, sentry);
2005*b2ed49a5SDavid van Moolenbroek             if (r != OK) {
2006*b2ed49a5SDavid van Moolenbroek                 return r;
2007*b2ed49a5SDavid van Moolenbroek             }
2008*b2ed49a5SDavid van Moolenbroek         }
2009*b2ed49a5SDavid van Moolenbroek         dsentry = dsentry->next;
2010*b2ed49a5SDavid van Moolenbroek     }
2011*b2ed49a5SDavid van Moolenbroek 
2012*b2ed49a5SDavid van Moolenbroek     /* Data transfer. */
2013*b2ed49a5SDavid van Moolenbroek     do {
2014*b2ed49a5SDavid van Moolenbroek         sentry_transferred = 0;
2015*b2ed49a5SDavid van Moolenbroek 
2016*b2ed49a5SDavid van Moolenbroek #if ST_DEBUG_DATA_TRANSFER
2017*b2ed49a5SDavid van Moolenbroek         printf("st_data_transfer: Round %d\n", counter++);
2018*b2ed49a5SDavid van Moolenbroek         st_print_sentities(&st_cached_magic_vars);
2019*b2ed49a5SDavid van Moolenbroek #endif
2020*b2ed49a5SDavid van Moolenbroek 
2021*b2ed49a5SDavid van Moolenbroek         /* process sentries */
2022*b2ed49a5SDavid van Moolenbroek #if ST_DEBUG_LEVEL > 0
2023*b2ed49a5SDavid van Moolenbroek         printf("st_data_transfer: processing sentries\n");
2024*b2ed49a5SDavid van Moolenbroek #endif
2025*b2ed49a5SDavid van Moolenbroek         for(i = 0 ; i < st_cached_magic_vars.sentries_num ; i++) {
2026*b2ed49a5SDavid van Moolenbroek             struct _magic_sentry *sentry = &st_cached_magic_vars.sentries[i];
2027*b2ed49a5SDavid van Moolenbroek             int is_paired_sentry = ST_HAS_CACHED_COUNTERPART(sentry, sentries);
2028*b2ed49a5SDavid van Moolenbroek             int sentry_needs_transfer = MAGIC_STATE_EXTF_GET(sentry, ST_NEEDS_TRANSFER | ST_TRANSFER_DONE) == ST_NEEDS_TRANSFER;
2029*b2ed49a5SDavid van Moolenbroek             if (sentry_needs_transfer && is_paired_sentry) {
2030*b2ed49a5SDavid van Moolenbroek                 r = transfer_data_sentry(info, sentry);
2031*b2ed49a5SDavid van Moolenbroek                 if (r != OK) {
2032*b2ed49a5SDavid van Moolenbroek                     return r;
2033*b2ed49a5SDavid van Moolenbroek                 }
2034*b2ed49a5SDavid van Moolenbroek                 sentry_transferred = 1;
2035*b2ed49a5SDavid van Moolenbroek             }
2036*b2ed49a5SDavid van Moolenbroek         }
2037*b2ed49a5SDavid van Moolenbroek 
2038*b2ed49a5SDavid van Moolenbroek         /* process dsentries */
2039*b2ed49a5SDavid van Moolenbroek #if ST_DEBUG_LEVEL > 0
2040*b2ed49a5SDavid van Moolenbroek         printf("st_data_transfer: processing dsentries\n");
2041*b2ed49a5SDavid van Moolenbroek #endif
2042*b2ed49a5SDavid van Moolenbroek         dsentry = st_cached_magic_vars.first_dsentry;
2043*b2ed49a5SDavid van Moolenbroek         while (dsentry != NULL) {
2044*b2ed49a5SDavid van Moolenbroek             struct _magic_sentry *sentry = MAGIC_DSENTRY_TO_SENTRY(dsentry);
2045*b2ed49a5SDavid van Moolenbroek             int is_paired_sentry = ST_HAS_CACHED_COUNTERPART(sentry, sentries);
2046*b2ed49a5SDavid van Moolenbroek             int sentry_needs_transfer = MAGIC_STATE_EXTF_GET(sentry, ST_NEEDS_TRANSFER | ST_TRANSFER_DONE) == ST_NEEDS_TRANSFER;
2047*b2ed49a5SDavid van Moolenbroek             if (sentry_needs_transfer && is_paired_sentry) {
2048*b2ed49a5SDavid van Moolenbroek                 r = transfer_data_sentry(info, sentry);
2049*b2ed49a5SDavid van Moolenbroek                 if (r != OK) {
2050*b2ed49a5SDavid van Moolenbroek                     return r;
2051*b2ed49a5SDavid van Moolenbroek                 }
2052*b2ed49a5SDavid van Moolenbroek                 sentry_transferred = 1;
2053*b2ed49a5SDavid van Moolenbroek             }
2054*b2ed49a5SDavid van Moolenbroek             dsentry = dsentry->next;
2055*b2ed49a5SDavid van Moolenbroek         }
2056*b2ed49a5SDavid van Moolenbroek 
2057*b2ed49a5SDavid van Moolenbroek     } while(sentry_transferred);
2058*b2ed49a5SDavid van Moolenbroek 
2059*b2ed49a5SDavid van Moolenbroek     return OK;
2060*b2ed49a5SDavid van Moolenbroek }
2061*b2ed49a5SDavid van Moolenbroek 
st_set_transfer_status(int status_flags,int status_op,struct _magic_sentry * cached_sentry,struct _magic_function * cached_function)2062*b2ed49a5SDavid van Moolenbroek PRIVATE INLINE void st_set_transfer_status(int status_flags, int status_op,
2063*b2ed49a5SDavid van Moolenbroek     struct _magic_sentry *cached_sentry, struct _magic_function *cached_function)
2064*b2ed49a5SDavid van Moolenbroek {
2065*b2ed49a5SDavid van Moolenbroek #define __st_set_transfer_status(X)                         \
2066*b2ed49a5SDavid van Moolenbroek     switch(status_op) {                                     \
2067*b2ed49a5SDavid van Moolenbroek         case ST_OP_NONE:                                    \
2068*b2ed49a5SDavid van Moolenbroek             return;                                         \
2069*b2ed49a5SDavid van Moolenbroek         break;                                              \
2070*b2ed49a5SDavid van Moolenbroek         case ST_OP_ADD:                                     \
2071*b2ed49a5SDavid van Moolenbroek             MAGIC_STATE_EXTF_ADD(X, status_flags);          \
2072*b2ed49a5SDavid van Moolenbroek         break;                                              \
2073*b2ed49a5SDavid van Moolenbroek         case ST_OP_DEL:                                     \
2074*b2ed49a5SDavid van Moolenbroek             MAGIC_STATE_EXTF_DEL(X, status_flags);          \
2075*b2ed49a5SDavid van Moolenbroek         break;                                              \
2076*b2ed49a5SDavid van Moolenbroek         case ST_OP_SET:                                     \
2077*b2ed49a5SDavid van Moolenbroek             MAGIC_STATE_EXTF_SET(X, status_flags);          \
2078*b2ed49a5SDavid van Moolenbroek         break;                                              \
2079*b2ed49a5SDavid van Moolenbroek         case ST_OP_CLEAR:                                   \
2080*b2ed49a5SDavid van Moolenbroek             MAGIC_STATE_EXTF_CLEAR(X);                      \
2081*b2ed49a5SDavid van Moolenbroek         break;                                              \
2082*b2ed49a5SDavid van Moolenbroek         default:                                            \
2083*b2ed49a5SDavid van Moolenbroek             st_cbs_os.panic("Invalid operation!");          \
2084*b2ed49a5SDavid van Moolenbroek         break;                                              \
2085*b2ed49a5SDavid van Moolenbroek     }                                                       \
2086*b2ed49a5SDavid van Moolenbroek 
2087*b2ed49a5SDavid van Moolenbroek     if (cached_sentry) {
2088*b2ed49a5SDavid van Moolenbroek         __st_set_transfer_status(cached_sentry);
2089*b2ed49a5SDavid van Moolenbroek     }
2090*b2ed49a5SDavid van Moolenbroek     else {
2091*b2ed49a5SDavid van Moolenbroek         assert(cached_function);
2092*b2ed49a5SDavid van Moolenbroek         __st_set_transfer_status(cached_function);
2093*b2ed49a5SDavid van Moolenbroek     }
2094*b2ed49a5SDavid van Moolenbroek }
2095*b2ed49a5SDavid van Moolenbroek 
st_set_unpaired_types_ratios(float unpaired_types_ratio,float unpaired_struct_types_ratio)2096*b2ed49a5SDavid van Moolenbroek PUBLIC void st_set_unpaired_types_ratios(float unpaired_types_ratio,
2097*b2ed49a5SDavid van Moolenbroek     float unpaired_struct_types_ratio)
2098*b2ed49a5SDavid van Moolenbroek {
2099*b2ed49a5SDavid van Moolenbroek     st_unpaired_types_ratio = unpaired_types_ratio;
2100*b2ed49a5SDavid van Moolenbroek     st_unpaired_struct_types_ratio = unpaired_struct_types_ratio;
2101*b2ed49a5SDavid van Moolenbroek }
2102*b2ed49a5SDavid van Moolenbroek 
st_set_status_defaults(st_init_info_t * info)2103*b2ed49a5SDavid van Moolenbroek PUBLIC void st_set_status_defaults(st_init_info_t *info)
2104*b2ed49a5SDavid van Moolenbroek {
2105*b2ed49a5SDavid van Moolenbroek     int match_all = ~0, skip_none = 0;
2106*b2ed49a5SDavid van Moolenbroek     int skip_state_flags = (st_policies & ST_DEFAULT_SKIP_STACK) ? MAGIC_STATE_STACK : 0;
2107*b2ed49a5SDavid van Moolenbroek 
2108*b2ed49a5SDavid van Moolenbroek     if (!(st_policies & ST_DEFAULT_TRANSFER_NONE)) {
2109*b2ed49a5SDavid van Moolenbroek         /*
2110*b2ed49a5SDavid van Moolenbroek          * Transfer all the (d)sentries by default. Skip stack dsentries when
2111*b2ed49a5SDavid van Moolenbroek          * requested. In that case, stack dsentries won't be transferred and an
2112*b2ed49a5SDavid van Moolenbroek          * error will be raised on stack pointer transfer.
2113*b2ed49a5SDavid van Moolenbroek          */
2114*b2ed49a5SDavid van Moolenbroek         st_set_status_by_state_flags(ST_NEEDS_TRANSFER, ST_OP_SET,
2115*b2ed49a5SDavid van Moolenbroek             match_all, skip_state_flags);
2116*b2ed49a5SDavid van Moolenbroek         if (st_policies & ST_DEFAULT_ALLOC_CASCADE_XFER) {
2117*b2ed49a5SDavid van Moolenbroek             /*
2118*b2ed49a5SDavid van Moolenbroek              * If requested, mark non-stack dsentries for cascade transfer
2119*b2ed49a5SDavid van Moolenbroek              * instead of regular transfer.
2120*b2ed49a5SDavid van Moolenbroek              */
2121*b2ed49a5SDavid van Moolenbroek             st_set_status_by_state_flags(ST_ON_PTRXFER_CASCADE, ST_OP_SET,
2122*b2ed49a5SDavid van Moolenbroek                 MAGIC_STATE_HEAP | MAGIC_STATE_MAP, skip_none);
2123*b2ed49a5SDavid van Moolenbroek         }
2124*b2ed49a5SDavid van Moolenbroek     }
2125*b2ed49a5SDavid van Moolenbroek     else {
2126*b2ed49a5SDavid van Moolenbroek         /*
2127*b2ed49a5SDavid van Moolenbroek          * Don't transfer any (d)sentries by default. Mark all the (d)sentries
2128*b2ed49a5SDavid van Moolenbroek          * for cascade transfer (except for stack dsentries when requested).
2129*b2ed49a5SDavid van Moolenbroek          */
2130*b2ed49a5SDavid van Moolenbroek         st_set_status_by_state_flags(ST_ON_PTRXFER_CASCADE, ST_OP_SET,
2131*b2ed49a5SDavid van Moolenbroek             match_all, skip_state_flags);
2132*b2ed49a5SDavid van Moolenbroek     }
2133*b2ed49a5SDavid van Moolenbroek 
2134*b2ed49a5SDavid van Moolenbroek     /*
2135*b2ed49a5SDavid van Moolenbroek      * Always transfer all immutable objects.
2136*b2ed49a5SDavid van Moolenbroek      */
2137*b2ed49a5SDavid van Moolenbroek     st_set_status_by_state_flags(ST_NEEDS_TRANSFER, ST_OP_SET,
2138*b2ed49a5SDavid van Moolenbroek         MAGIC_STATE_IMMUTABLE, skip_none);
2139*b2ed49a5SDavid van Moolenbroek 
2140*b2ed49a5SDavid van Moolenbroek     /*
2141*b2ed49a5SDavid van Moolenbroek      * If requested, mark library state dsentries as already transferred too.
2142*b2ed49a5SDavid van Moolenbroek      */
2143*b2ed49a5SDavid van Moolenbroek     if (st_policies & ST_DEFAULT_SKIP_LIB_STATE) {
2144*b2ed49a5SDavid van Moolenbroek         st_set_status_by_state_flags(ST_NEEDS_TRANSFER | ST_TRANSFER_DONE,
2145*b2ed49a5SDavid van Moolenbroek             ST_OP_ADD, MAGIC_STATE_LIB, skip_none);
2146*b2ed49a5SDavid van Moolenbroek     }
2147*b2ed49a5SDavid van Moolenbroek 
2148*b2ed49a5SDavid van Moolenbroek     /*
2149*b2ed49a5SDavid van Moolenbroek      * In addition, mark functions, out-of-band/string sentries
2150*b2ed49a5SDavid van Moolenbroek      * and shared dsentries as already transferred.
2151*b2ed49a5SDavid van Moolenbroek      */
2152*b2ed49a5SDavid van Moolenbroek     st_set_status_by_state_flags(ST_NEEDS_TRANSFER | ST_TRANSFER_DONE,
2153*b2ed49a5SDavid van Moolenbroek         ST_OP_ADD, MAGIC_STATE_TEXT | MAGIC_STATE_OUT_OF_BAND |
2154*b2ed49a5SDavid van Moolenbroek         MAGIC_STATE_STRING | MAGIC_STATE_CONSTANT | MAGIC_STATE_SHM, skip_none);
2155*b2ed49a5SDavid van Moolenbroek 
2156*b2ed49a5SDavid van Moolenbroek     /*
2157*b2ed49a5SDavid van Moolenbroek      * Finally, if we only want to transfer dirty sentries, mark all the other ones
2158*b2ed49a5SDavid van Moolenbroek      * as already transferred.
2159*b2ed49a5SDavid van Moolenbroek      */
2160*b2ed49a5SDavid van Moolenbroek     if (st_policies & ST_TRANSFER_DIRTY_ONLY) {
2161*b2ed49a5SDavid van Moolenbroek         st_set_status_by_state_flags(ST_TRANSFER_DONE, ST_OP_ADD, match_all, MAGIC_STATE_DIRTY_PAGE);
2162*b2ed49a5SDavid van Moolenbroek     }
2163*b2ed49a5SDavid van Moolenbroek 
2164*b2ed49a5SDavid van Moolenbroek #if DO_SKIP_ENVIRON_HACK
2165*b2ed49a5SDavid van Moolenbroek     st_set_status_by_name(ST_NEEDS_TRANSFER | ST_TRANSFER_DONE,
2166*b2ed49a5SDavid van Moolenbroek         ST_OP_ADD, NULL, "__environ", MAGIC_DSENTRY_SITE_ID_NULL);
2167*b2ed49a5SDavid van Moolenbroek     st_set_status_by_name(ST_NEEDS_TRANSFER | ST_TRANSFER_DONE,
2168*b2ed49a5SDavid van Moolenbroek         ST_OP_ADD, NULL, "stderr", MAGIC_DSENTRY_SITE_ID_NULL);
2169*b2ed49a5SDavid van Moolenbroek #endif
2170*b2ed49a5SDavid van Moolenbroek }
2171*b2ed49a5SDavid van Moolenbroek 
st_set_status_by_state_flags(int status_flags,int status_op,int match_state_flags,int skip_state_flags)2172*b2ed49a5SDavid van Moolenbroek PUBLIC void st_set_status_by_state_flags(int status_flags, int status_op,
2173*b2ed49a5SDavid van Moolenbroek     int match_state_flags, int skip_state_flags)
2174*b2ed49a5SDavid van Moolenbroek {
2175*b2ed49a5SDavid van Moolenbroek     struct _magic_dsentry *dsentry = st_cached_magic_vars.first_dsentry;
2176*b2ed49a5SDavid van Moolenbroek     int i;
2177*b2ed49a5SDavid van Moolenbroek     int candidate_sentry_flags = MAGIC_STATE_DATA | MAGIC_STATE_STRING | MAGIC_STATE_CONSTANT | MAGIC_STATE_ADDR_NOT_TAKEN;
2178*b2ed49a5SDavid van Moolenbroek     int candidate_function_flags = MAGIC_STATE_TEXT;
2179*b2ed49a5SDavid van Moolenbroek     int candidate_dsentry_flags = ~(candidate_sentry_flags | candidate_function_flags);
2180*b2ed49a5SDavid van Moolenbroek     ST_CHECK_INIT();
2181*b2ed49a5SDavid van Moolenbroek 
2182*b2ed49a5SDavid van Moolenbroek     /* process sentries */
2183*b2ed49a5SDavid van Moolenbroek     if (match_state_flags & candidate_sentry_flags) {
2184*b2ed49a5SDavid van Moolenbroek         for (i = 0 ; i < st_cached_magic_vars.sentries_num ; i++) {
2185*b2ed49a5SDavid van Moolenbroek             int state_flags = st_cached_magic_vars.sentries[i].flags;
2186*b2ed49a5SDavid van Moolenbroek             if ((state_flags & match_state_flags) && !(state_flags & skip_state_flags)) {
2187*b2ed49a5SDavid van Moolenbroek                 st_set_transfer_status(status_flags, status_op, &st_cached_magic_vars.sentries[i], NULL);
2188*b2ed49a5SDavid van Moolenbroek             }
2189*b2ed49a5SDavid van Moolenbroek         }
2190*b2ed49a5SDavid van Moolenbroek     }
2191*b2ed49a5SDavid van Moolenbroek 
2192*b2ed49a5SDavid van Moolenbroek     /* process dsentries */
2193*b2ed49a5SDavid van Moolenbroek     if (match_state_flags & candidate_dsentry_flags) {
2194*b2ed49a5SDavid van Moolenbroek         while (dsentry != NULL) {
2195*b2ed49a5SDavid van Moolenbroek             int state_flags = dsentry->sentry.flags;
2196*b2ed49a5SDavid van Moolenbroek             if ((state_flags & match_state_flags) && !(state_flags & skip_state_flags)) {
2197*b2ed49a5SDavid van Moolenbroek                 st_set_transfer_status(status_flags, status_op, MAGIC_DSENTRY_TO_SENTRY(dsentry), NULL);
2198*b2ed49a5SDavid van Moolenbroek             }
2199*b2ed49a5SDavid van Moolenbroek             dsentry = dsentry->next;
2200*b2ed49a5SDavid van Moolenbroek         }
2201*b2ed49a5SDavid van Moolenbroek     }
2202*b2ed49a5SDavid van Moolenbroek 
2203*b2ed49a5SDavid van Moolenbroek     /* process functions */
2204*b2ed49a5SDavid van Moolenbroek     if (match_state_flags & candidate_function_flags) {
2205*b2ed49a5SDavid van Moolenbroek         for (i = 0 ; i < st_cached_magic_vars.functions_num ; i++) {
2206*b2ed49a5SDavid van Moolenbroek             int state_flags = st_cached_magic_vars.functions[i].flags;
2207*b2ed49a5SDavid van Moolenbroek             if ((state_flags & match_state_flags) && !(state_flags & skip_state_flags)) {
2208*b2ed49a5SDavid van Moolenbroek                 st_set_transfer_status(status_flags, status_op, NULL, &st_cached_magic_vars.functions[i]);
2209*b2ed49a5SDavid van Moolenbroek             }
2210*b2ed49a5SDavid van Moolenbroek         }
2211*b2ed49a5SDavid van Moolenbroek     }
2212*b2ed49a5SDavid van Moolenbroek }
2213*b2ed49a5SDavid van Moolenbroek 
st_set_status_by_function_ids(int status_flags,int status_op,_magic_id_t * ids)2214*b2ed49a5SDavid van Moolenbroek PUBLIC int st_set_status_by_function_ids(int status_flags, int status_op, _magic_id_t *ids)
2215*b2ed49a5SDavid van Moolenbroek {
2216*b2ed49a5SDavid van Moolenbroek     int r, i = 0;
2217*b2ed49a5SDavid van Moolenbroek     while (ids[i] != 0) {
2218*b2ed49a5SDavid van Moolenbroek         r = st_set_status_by_function_id(status_flags, status_op, ids[i]);
2219*b2ed49a5SDavid van Moolenbroek         if (r != OK) {
2220*b2ed49a5SDavid van Moolenbroek             return r;
2221*b2ed49a5SDavid van Moolenbroek         }
2222*b2ed49a5SDavid van Moolenbroek         i++;
2223*b2ed49a5SDavid van Moolenbroek     }
2224*b2ed49a5SDavid van Moolenbroek     return OK;
2225*b2ed49a5SDavid van Moolenbroek }
2226*b2ed49a5SDavid van Moolenbroek 
st_set_status_by_sentry_ids(int status_flags,int status_op,_magic_id_t * ids)2227*b2ed49a5SDavid van Moolenbroek PUBLIC int st_set_status_by_sentry_ids(int status_flags, int status_op, _magic_id_t *ids)
2228*b2ed49a5SDavid van Moolenbroek {
2229*b2ed49a5SDavid van Moolenbroek     int r, i=0;
2230*b2ed49a5SDavid van Moolenbroek     while (ids[i] != 0) {
2231*b2ed49a5SDavid van Moolenbroek         r = st_set_status_by_sentry_id(status_flags, status_op, ids[i]);
2232*b2ed49a5SDavid van Moolenbroek         if (r != OK) {
2233*b2ed49a5SDavid van Moolenbroek             return r;
2234*b2ed49a5SDavid van Moolenbroek         }
2235*b2ed49a5SDavid van Moolenbroek         i++;
2236*b2ed49a5SDavid van Moolenbroek     }
2237*b2ed49a5SDavid van Moolenbroek     return OK;
2238*b2ed49a5SDavid van Moolenbroek }
2239*b2ed49a5SDavid van Moolenbroek 
st_set_status_by_names(int status_flags,int status_op,const char ** parent_names,const char ** names,_magic_id_t * dsentry_site_ids)2240*b2ed49a5SDavid van Moolenbroek PUBLIC int st_set_status_by_names(int status_flags, int status_op,
2241*b2ed49a5SDavid van Moolenbroek     const char **parent_names, const char **names,
2242*b2ed49a5SDavid van Moolenbroek     _magic_id_t *dsentry_site_ids)
2243*b2ed49a5SDavid van Moolenbroek {
2244*b2ed49a5SDavid van Moolenbroek     int r, i = 0;
2245*b2ed49a5SDavid van Moolenbroek     while (names[i] != NULL) {
2246*b2ed49a5SDavid van Moolenbroek         r = st_set_status_by_name(status_flags, status_op,
2247*b2ed49a5SDavid van Moolenbroek             parent_names ? parent_names[i] : NULL, names[i],
2248*b2ed49a5SDavid van Moolenbroek             dsentry_site_ids ? dsentry_site_ids[i] :
2249*b2ed49a5SDavid van Moolenbroek                 MAGIC_DSENTRY_SITE_ID_NULL);
2250*b2ed49a5SDavid van Moolenbroek         if (r != OK) {
2251*b2ed49a5SDavid van Moolenbroek             return r;
2252*b2ed49a5SDavid van Moolenbroek         }
2253*b2ed49a5SDavid van Moolenbroek         i++;
2254*b2ed49a5SDavid van Moolenbroek     }
2255*b2ed49a5SDavid van Moolenbroek     return OK;
2256*b2ed49a5SDavid van Moolenbroek }
2257*b2ed49a5SDavid van Moolenbroek 
st_set_status_by_local_addrs(int status_flags,int status_op,void ** addrs)2258*b2ed49a5SDavid van Moolenbroek PUBLIC int st_set_status_by_local_addrs(int status_flags, int status_op,
2259*b2ed49a5SDavid van Moolenbroek     void **addrs)
2260*b2ed49a5SDavid van Moolenbroek {
2261*b2ed49a5SDavid van Moolenbroek     int r, i=0;
2262*b2ed49a5SDavid van Moolenbroek     while (addrs[i] != NULL) {
2263*b2ed49a5SDavid van Moolenbroek         r = st_set_status_by_local_addr(status_flags, status_op, addrs[i]);
2264*b2ed49a5SDavid van Moolenbroek         if (r != OK) {
2265*b2ed49a5SDavid van Moolenbroek             return r;
2266*b2ed49a5SDavid van Moolenbroek         }
2267*b2ed49a5SDavid van Moolenbroek         i++;
2268*b2ed49a5SDavid van Moolenbroek     }
2269*b2ed49a5SDavid van Moolenbroek     return OK;
2270*b2ed49a5SDavid van Moolenbroek }
2271*b2ed49a5SDavid van Moolenbroek 
st_set_status_by_sentry(int status_flags,int status_op,void * cached_sentry)2272*b2ed49a5SDavid van Moolenbroek PUBLIC void st_set_status_by_sentry(int status_flags, int status_op,
2273*b2ed49a5SDavid van Moolenbroek     void *cached_sentry)
2274*b2ed49a5SDavid van Moolenbroek {
2275*b2ed49a5SDavid van Moolenbroek     ST_CHECK_INIT();
2276*b2ed49a5SDavid van Moolenbroek 
2277*b2ed49a5SDavid van Moolenbroek     st_set_transfer_status(status_flags, status_op,
2278*b2ed49a5SDavid van Moolenbroek         (struct _magic_sentry*) cached_sentry, NULL);
2279*b2ed49a5SDavid van Moolenbroek }
2280*b2ed49a5SDavid van Moolenbroek 
st_set_status_by_function(int status_flags,int status_op,void * cached_function)2281*b2ed49a5SDavid van Moolenbroek PUBLIC void st_set_status_by_function(int status_flags, int status_op,
2282*b2ed49a5SDavid van Moolenbroek     void *cached_function)
2283*b2ed49a5SDavid van Moolenbroek {
2284*b2ed49a5SDavid van Moolenbroek     ST_CHECK_INIT();
2285*b2ed49a5SDavid van Moolenbroek 
2286*b2ed49a5SDavid van Moolenbroek     st_set_transfer_status(status_flags, status_op,
2287*b2ed49a5SDavid van Moolenbroek         NULL, (struct _magic_function*) cached_function);
2288*b2ed49a5SDavid van Moolenbroek }
2289*b2ed49a5SDavid van Moolenbroek 
st_set_status_by_name(int status_flags,int status_op,const char * parent_name,const char * name,_magic_id_t dsentry_site_id)2290*b2ed49a5SDavid van Moolenbroek PUBLIC int st_set_status_by_name(int status_flags, int status_op,
2291*b2ed49a5SDavid van Moolenbroek     const char *parent_name, const char *name, _magic_id_t dsentry_site_id)
2292*b2ed49a5SDavid van Moolenbroek {
2293*b2ed49a5SDavid van Moolenbroek     struct _magic_sentry *cached_sentry = NULL;
2294*b2ed49a5SDavid van Moolenbroek     struct _magic_function *cached_function = NULL;
2295*b2ed49a5SDavid van Moolenbroek     ST_CHECK_INIT();
2296*b2ed49a5SDavid van Moolenbroek 
2297*b2ed49a5SDavid van Moolenbroek     EXEC_WITH_MAGIC_VARS(
2298*b2ed49a5SDavid van Moolenbroek         cached_sentry = magic_sentry_lookup_by_name(parent_name ? parent_name : "", name, dsentry_site_id, NULL);
2299*b2ed49a5SDavid van Moolenbroek         if (!cached_sentry) {
2300*b2ed49a5SDavid van Moolenbroek             cached_function = magic_function_lookup_by_name(parent_name, name);
2301*b2ed49a5SDavid van Moolenbroek         }
2302*b2ed49a5SDavid van Moolenbroek         , &st_cached_magic_vars
2303*b2ed49a5SDavid van Moolenbroek     );
2304*b2ed49a5SDavid van Moolenbroek     if (!cached_sentry && !cached_function) {
2305*b2ed49a5SDavid van Moolenbroek         return ENOENT;
2306*b2ed49a5SDavid van Moolenbroek     }
2307*b2ed49a5SDavid van Moolenbroek     st_set_transfer_status(status_flags, status_op, cached_sentry, cached_function);
2308*b2ed49a5SDavid van Moolenbroek     if (cached_sentry && MAGIC_SENTRY_IS_ALLOC(cached_sentry)) {
2309*b2ed49a5SDavid van Moolenbroek         struct _magic_dsentry *prev_dsentry, *dsentry, *next_dsentry = MAGIC_DSENTRY_NEXT(MAGIC_DSENTRY_FROM_SENTRY(cached_sentry));
2310*b2ed49a5SDavid van Moolenbroek         struct _magic_sentry* sentry;
2311*b2ed49a5SDavid van Moolenbroek         /*
2312*b2ed49a5SDavid van Moolenbroek          * Alloc sentries may have multiple instances with the same name.
2313*b2ed49a5SDavid van Moolenbroek          * Use the site_id to distinguish between them.
2314*b2ed49a5SDavid van Moolenbroek          */
2315*b2ed49a5SDavid van Moolenbroek         assert(parent_name && name);
2316*b2ed49a5SDavid van Moolenbroek         MAGIC_DSENTRY_ALIVE_NAME_ID_ITER(next_dsentry, prev_dsentry, dsentry, sentry,
2317*b2ed49a5SDavid van Moolenbroek             parent_name, name, dsentry_site_id,
2318*b2ed49a5SDavid van Moolenbroek             st_set_transfer_status(status_flags, status_op, sentry, NULL);
2319*b2ed49a5SDavid van Moolenbroek         );
2320*b2ed49a5SDavid van Moolenbroek     }
2321*b2ed49a5SDavid van Moolenbroek     return OK;
2322*b2ed49a5SDavid van Moolenbroek }
2323*b2ed49a5SDavid van Moolenbroek 
st_set_status_by_function_id(int status_flags,int status_op,_magic_id_t id)2324*b2ed49a5SDavid van Moolenbroek PUBLIC int st_set_status_by_function_id(int status_flags, int status_op,
2325*b2ed49a5SDavid van Moolenbroek     _magic_id_t id)
2326*b2ed49a5SDavid van Moolenbroek {
2327*b2ed49a5SDavid van Moolenbroek     struct _magic_function *cached_function = NULL;
2328*b2ed49a5SDavid van Moolenbroek     ST_CHECK_INIT();
2329*b2ed49a5SDavid van Moolenbroek 
2330*b2ed49a5SDavid van Moolenbroek     EXEC_WITH_MAGIC_VARS(
2331*b2ed49a5SDavid van Moolenbroek         cached_function = magic_function_lookup_by_id(id, NULL);
2332*b2ed49a5SDavid van Moolenbroek         , &st_cached_magic_vars
2333*b2ed49a5SDavid van Moolenbroek     );
2334*b2ed49a5SDavid van Moolenbroek 
2335*b2ed49a5SDavid van Moolenbroek     if (!cached_function) {
2336*b2ed49a5SDavid van Moolenbroek         return ENOENT;
2337*b2ed49a5SDavid van Moolenbroek     }
2338*b2ed49a5SDavid van Moolenbroek 
2339*b2ed49a5SDavid van Moolenbroek     st_set_transfer_status(status_flags, status_op, NULL, cached_function);
2340*b2ed49a5SDavid van Moolenbroek     return OK;
2341*b2ed49a5SDavid van Moolenbroek }
2342*b2ed49a5SDavid van Moolenbroek 
st_set_status_by_sentry_id(int status_flags,int status_op,_magic_id_t id)2343*b2ed49a5SDavid van Moolenbroek PUBLIC int st_set_status_by_sentry_id(int status_flags, int status_op,
2344*b2ed49a5SDavid van Moolenbroek     _magic_id_t id)
2345*b2ed49a5SDavid van Moolenbroek {
2346*b2ed49a5SDavid van Moolenbroek     struct _magic_sentry *cached_sentry = NULL;
2347*b2ed49a5SDavid van Moolenbroek     ST_CHECK_INIT();
2348*b2ed49a5SDavid van Moolenbroek 
2349*b2ed49a5SDavid van Moolenbroek     EXEC_WITH_MAGIC_VARS(
2350*b2ed49a5SDavid van Moolenbroek         cached_sentry = magic_sentry_lookup_by_id(id, NULL);
2351*b2ed49a5SDavid van Moolenbroek         , &st_cached_magic_vars
2352*b2ed49a5SDavid van Moolenbroek     );
2353*b2ed49a5SDavid van Moolenbroek 
2354*b2ed49a5SDavid van Moolenbroek     if (!cached_sentry) {
2355*b2ed49a5SDavid van Moolenbroek         return ENOENT;
2356*b2ed49a5SDavid van Moolenbroek     }
2357*b2ed49a5SDavid van Moolenbroek 
2358*b2ed49a5SDavid van Moolenbroek     st_set_transfer_status(status_flags, status_op, cached_sentry, NULL);
2359*b2ed49a5SDavid van Moolenbroek     return OK;
2360*b2ed49a5SDavid van Moolenbroek }
2361*b2ed49a5SDavid van Moolenbroek 
st_set_status_by_local_addr(int status_flags,int status_op,void * addr)2362*b2ed49a5SDavid van Moolenbroek PUBLIC int st_set_status_by_local_addr(int status_flags, int status_op,
2363*b2ed49a5SDavid van Moolenbroek     void *addr)
2364*b2ed49a5SDavid van Moolenbroek {
2365*b2ed49a5SDavid van Moolenbroek     const char *parent_name, *name;
2366*b2ed49a5SDavid van Moolenbroek     _magic_id_t dsentry_site_id = MAGIC_DSENTRY_SITE_ID_NULL;
2367*b2ed49a5SDavid van Moolenbroek     struct _magic_sentry *sentry = NULL;
2368*b2ed49a5SDavid van Moolenbroek     struct _magic_function *function = NULL;
2369*b2ed49a5SDavid van Moolenbroek     ST_CHECK_INIT();
2370*b2ed49a5SDavid van Moolenbroek 
2371*b2ed49a5SDavid van Moolenbroek     sentry = magic_sentry_lookup_by_addr(addr, NULL);
2372*b2ed49a5SDavid van Moolenbroek     if (!sentry) {
2373*b2ed49a5SDavid van Moolenbroek         function = magic_function_lookup_by_addr(addr, NULL);
2374*b2ed49a5SDavid van Moolenbroek     }
2375*b2ed49a5SDavid van Moolenbroek     if (sentry && !MAGIC_STATE_FLAG(sentry, MAGIC_STATE_DYNAMIC)) {
2376*b2ed49a5SDavid van Moolenbroek         name = sentry->name;
2377*b2ed49a5SDavid van Moolenbroek         parent_name = MAGIC_SENTRY_PARENT(sentry);
2378*b2ed49a5SDavid van Moolenbroek         dsentry_site_id = MAGIC_SENTRY_SITE_ID(sentry);
2379*b2ed49a5SDavid van Moolenbroek     }
2380*b2ed49a5SDavid van Moolenbroek     else if (function && !MAGIC_STATE_FLAG(function, MAGIC_STATE_DYNAMIC)) {
2381*b2ed49a5SDavid van Moolenbroek        name = function->name;
2382*b2ed49a5SDavid van Moolenbroek        parent_name = MAGIC_FUNCTION_PARENT(function);
2383*b2ed49a5SDavid van Moolenbroek     }
2384*b2ed49a5SDavid van Moolenbroek     else {
2385*b2ed49a5SDavid van Moolenbroek         return ENOENT;
2386*b2ed49a5SDavid van Moolenbroek     }
2387*b2ed49a5SDavid van Moolenbroek     st_set_status_by_name(status_flags, status_op, parent_name, name, dsentry_site_id);
2388*b2ed49a5SDavid van Moolenbroek     return OK;
2389*b2ed49a5SDavid van Moolenbroek }
2390*b2ed49a5SDavid van Moolenbroek 
st_pair_by_function_ids(unsigned long * cached_ids,unsigned long * local_ids,int status_flags,int status_op)2391*b2ed49a5SDavid van Moolenbroek PUBLIC int st_pair_by_function_ids(unsigned long *cached_ids, unsigned long *local_ids, int status_flags, int status_op)
2392*b2ed49a5SDavid van Moolenbroek {
2393*b2ed49a5SDavid van Moolenbroek     int r, i=0;
2394*b2ed49a5SDavid van Moolenbroek     ST_CHECK_INIT();
2395*b2ed49a5SDavid van Moolenbroek 
2396*b2ed49a5SDavid van Moolenbroek     while (cached_ids[i] != 0) {
2397*b2ed49a5SDavid van Moolenbroek         assert(local_ids[i] != 0);
2398*b2ed49a5SDavid van Moolenbroek         r = st_pair_by_function_id(cached_ids[i], local_ids[i], status_flags, status_op);
2399*b2ed49a5SDavid van Moolenbroek         if (r != OK) {
2400*b2ed49a5SDavid van Moolenbroek             return r;
2401*b2ed49a5SDavid van Moolenbroek         }
2402*b2ed49a5SDavid van Moolenbroek         i++;
2403*b2ed49a5SDavid van Moolenbroek     }
2404*b2ed49a5SDavid van Moolenbroek     return OK;
2405*b2ed49a5SDavid van Moolenbroek }
2406*b2ed49a5SDavid van Moolenbroek 
st_pair_by_sentry_ids(unsigned long * cached_ids,unsigned long * local_ids,int status_flags,int status_op)2407*b2ed49a5SDavid van Moolenbroek PUBLIC int st_pair_by_sentry_ids(unsigned long *cached_ids, unsigned long *local_ids, int status_flags, int status_op)
2408*b2ed49a5SDavid van Moolenbroek {
2409*b2ed49a5SDavid van Moolenbroek     int r, i=0;
2410*b2ed49a5SDavid van Moolenbroek     ST_CHECK_INIT();
2411*b2ed49a5SDavid van Moolenbroek 
2412*b2ed49a5SDavid van Moolenbroek     while (cached_ids[i] != 0) {
2413*b2ed49a5SDavid van Moolenbroek         assert(local_ids[i] != 0);
2414*b2ed49a5SDavid van Moolenbroek         r = st_pair_by_sentry_id(cached_ids[i], local_ids[i], status_flags, status_op);
2415*b2ed49a5SDavid van Moolenbroek         if (r != OK) {
2416*b2ed49a5SDavid van Moolenbroek             return r;
2417*b2ed49a5SDavid van Moolenbroek         }
2418*b2ed49a5SDavid van Moolenbroek         i++;
2419*b2ed49a5SDavid van Moolenbroek     }
2420*b2ed49a5SDavid van Moolenbroek     return OK;
2421*b2ed49a5SDavid van Moolenbroek }
2422*b2ed49a5SDavid van Moolenbroek 
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)2423*b2ed49a5SDavid van Moolenbroek PUBLIC int st_pair_by_names(char **cached_parent_names, char **cached_names,
2424*b2ed49a5SDavid van Moolenbroek     char **local_parent_names, char **local_names, _magic_id_t *dsentry_site_ids,
2425*b2ed49a5SDavid van Moolenbroek     int status_flags, int status_op)
2426*b2ed49a5SDavid van Moolenbroek {
2427*b2ed49a5SDavid van Moolenbroek     int r, i=0;
2428*b2ed49a5SDavid van Moolenbroek     while (cached_names[i] != NULL) {
2429*b2ed49a5SDavid van Moolenbroek         assert(local_names[i]);
2430*b2ed49a5SDavid van Moolenbroek         r = st_pair_by_name(cached_parent_names ? cached_parent_names[i] : NULL, cached_names[i],
2431*b2ed49a5SDavid van Moolenbroek             local_parent_names ? local_parent_names[i] : NULL, local_names[i],
2432*b2ed49a5SDavid van Moolenbroek             dsentry_site_ids ? dsentry_site_ids[i] : MAGIC_DSENTRY_SITE_ID_NULL,
2433*b2ed49a5SDavid van Moolenbroek             status_flags, status_op);
2434*b2ed49a5SDavid van Moolenbroek         if (r != OK) {
2435*b2ed49a5SDavid van Moolenbroek             return r;
2436*b2ed49a5SDavid van Moolenbroek         }
2437*b2ed49a5SDavid van Moolenbroek         i++;
2438*b2ed49a5SDavid van Moolenbroek     }
2439*b2ed49a5SDavid van Moolenbroek     return OK;
2440*b2ed49a5SDavid van Moolenbroek }
2441*b2ed49a5SDavid van Moolenbroek 
st_pair_by_sentry(void * cached_sentry,void * local_sentry,int status_flags,int status_op)2442*b2ed49a5SDavid van Moolenbroek PUBLIC void st_pair_by_sentry(void *cached_sentry, void *local_sentry, int status_flags, int status_op)
2443*b2ed49a5SDavid van Moolenbroek {
2444*b2ed49a5SDavid van Moolenbroek     ST_CHECK_INIT();
2445*b2ed49a5SDavid van Moolenbroek 
2446*b2ed49a5SDavid van Moolenbroek     st_add_sentry_pair(cached_sentry, local_sentry);
2447*b2ed49a5SDavid van Moolenbroek     if (cached_sentry) {
2448*b2ed49a5SDavid van Moolenbroek         st_set_status_by_sentry(status_flags, status_op, cached_sentry);
2449*b2ed49a5SDavid van Moolenbroek     }
2450*b2ed49a5SDavid van Moolenbroek }
2451*b2ed49a5SDavid van Moolenbroek 
st_pair_by_function(void * cached_function,void * local_function,int status_flags,int status_op)2452*b2ed49a5SDavid van Moolenbroek PUBLIC void st_pair_by_function(void *cached_function, void* local_function, int status_flags, int status_op)
2453*b2ed49a5SDavid van Moolenbroek {
2454*b2ed49a5SDavid van Moolenbroek     ST_CHECK_INIT();
2455*b2ed49a5SDavid van Moolenbroek 
2456*b2ed49a5SDavid van Moolenbroek     st_add_function_pair(cached_function, local_function);
2457*b2ed49a5SDavid van Moolenbroek     if (cached_function) {
2458*b2ed49a5SDavid van Moolenbroek         st_set_status_by_function(status_flags, status_op, cached_function);
2459*b2ed49a5SDavid van Moolenbroek     }
2460*b2ed49a5SDavid van Moolenbroek }
2461*b2ed49a5SDavid van Moolenbroek 
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)2462*b2ed49a5SDavid van Moolenbroek 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)
2463*b2ed49a5SDavid van Moolenbroek {
2464*b2ed49a5SDavid van Moolenbroek     int r;
2465*b2ed49a5SDavid van Moolenbroek     ST_CHECK_INIT();
2466*b2ed49a5SDavid van Moolenbroek 
2467*b2ed49a5SDavid van Moolenbroek     r = st_add_sentry_pair_alloc_by_dsindex(info, cached_sentry, local_dsindex, num_elements, p_alloc_flags);
2468*b2ed49a5SDavid van Moolenbroek     if (r != OK) {
2469*b2ed49a5SDavid van Moolenbroek         return r;
2470*b2ed49a5SDavid van Moolenbroek     }
2471*b2ed49a5SDavid van Moolenbroek     if (cached_sentry) {
2472*b2ed49a5SDavid van Moolenbroek         st_set_status_by_sentry(status_flags, status_op, cached_sentry);
2473*b2ed49a5SDavid van Moolenbroek     }
2474*b2ed49a5SDavid van Moolenbroek     return OK;
2475*b2ed49a5SDavid van Moolenbroek }
2476*b2ed49a5SDavid van Moolenbroek 
st_pair_by_function_id(unsigned long cached_id,unsigned long local_id,int status_flags,int status_op)2477*b2ed49a5SDavid van Moolenbroek PUBLIC int st_pair_by_function_id(unsigned long cached_id, unsigned long local_id, int status_flags, int status_op)
2478*b2ed49a5SDavid van Moolenbroek {
2479*b2ed49a5SDavid van Moolenbroek     struct _magic_function *cached_function = NULL, *local_function = NULL;
2480*b2ed49a5SDavid van Moolenbroek     ST_CHECK_INIT();
2481*b2ed49a5SDavid van Moolenbroek     assert(cached_id || local_id);
2482*b2ed49a5SDavid van Moolenbroek 
2483*b2ed49a5SDavid van Moolenbroek     if (cached_id) {
2484*b2ed49a5SDavid van Moolenbroek         EXEC_WITH_MAGIC_VARS(
2485*b2ed49a5SDavid van Moolenbroek             cached_function = magic_function_lookup_by_id(cached_id, NULL);
2486*b2ed49a5SDavid van Moolenbroek             , &st_cached_magic_vars
2487*b2ed49a5SDavid van Moolenbroek         );
2488*b2ed49a5SDavid van Moolenbroek         if (!cached_function) {
2489*b2ed49a5SDavid van Moolenbroek             return ENOENT;
2490*b2ed49a5SDavid van Moolenbroek         }
2491*b2ed49a5SDavid van Moolenbroek     }
2492*b2ed49a5SDavid van Moolenbroek     if (local_id) {
2493*b2ed49a5SDavid van Moolenbroek         EXEC_WITH_MAGIC_VARS(
2494*b2ed49a5SDavid van Moolenbroek             local_function = magic_function_lookup_by_id(local_id, NULL);
2495*b2ed49a5SDavid van Moolenbroek             , st_local_magic_vars_ptr
2496*b2ed49a5SDavid van Moolenbroek         );
2497*b2ed49a5SDavid van Moolenbroek         if (!local_function) {
2498*b2ed49a5SDavid van Moolenbroek             return ENOENT;
2499*b2ed49a5SDavid van Moolenbroek         }
2500*b2ed49a5SDavid van Moolenbroek     }
2501*b2ed49a5SDavid van Moolenbroek 
2502*b2ed49a5SDavid van Moolenbroek     st_pair_by_function(cached_function, local_function, status_flags, status_op);
2503*b2ed49a5SDavid van Moolenbroek     return OK;
2504*b2ed49a5SDavid van Moolenbroek }
2505*b2ed49a5SDavid van Moolenbroek 
st_pair_by_sentry_id(unsigned long cached_id,unsigned long local_id,int status_flags,int status_op)2506*b2ed49a5SDavid van Moolenbroek PUBLIC int st_pair_by_sentry_id(unsigned long cached_id, unsigned long local_id, int status_flags, int status_op)
2507*b2ed49a5SDavid van Moolenbroek {
2508*b2ed49a5SDavid van Moolenbroek     struct _magic_sentry *cached_sentry = NULL, *local_sentry = NULL;
2509*b2ed49a5SDavid van Moolenbroek     ST_CHECK_INIT();
2510*b2ed49a5SDavid van Moolenbroek     assert(cached_id || local_id);
2511*b2ed49a5SDavid van Moolenbroek 
2512*b2ed49a5SDavid van Moolenbroek     if (cached_id) {
2513*b2ed49a5SDavid van Moolenbroek         EXEC_WITH_MAGIC_VARS(
2514*b2ed49a5SDavid van Moolenbroek             cached_sentry = magic_sentry_lookup_by_id(cached_id, NULL);
2515*b2ed49a5SDavid van Moolenbroek             , &st_cached_magic_vars
2516*b2ed49a5SDavid van Moolenbroek         );
2517*b2ed49a5SDavid van Moolenbroek         if (!cached_sentry) {
2518*b2ed49a5SDavid van Moolenbroek             return ENOENT;
2519*b2ed49a5SDavid van Moolenbroek         }
2520*b2ed49a5SDavid van Moolenbroek     }
2521*b2ed49a5SDavid van Moolenbroek     if (local_id) {
2522*b2ed49a5SDavid van Moolenbroek         EXEC_WITH_MAGIC_VARS(
2523*b2ed49a5SDavid van Moolenbroek             local_sentry = magic_sentry_lookup_by_id(local_id, NULL);
2524*b2ed49a5SDavid van Moolenbroek             , st_local_magic_vars_ptr
2525*b2ed49a5SDavid van Moolenbroek         );
2526*b2ed49a5SDavid van Moolenbroek         if (!local_sentry) {
2527*b2ed49a5SDavid van Moolenbroek             return ENOENT;
2528*b2ed49a5SDavid van Moolenbroek         }
2529*b2ed49a5SDavid van Moolenbroek     }
2530*b2ed49a5SDavid van Moolenbroek 
2531*b2ed49a5SDavid van Moolenbroek     st_pair_by_sentry(cached_sentry, local_sentry, status_flags, status_op);
2532*b2ed49a5SDavid van Moolenbroek     return OK;
2533*b2ed49a5SDavid van Moolenbroek }
2534*b2ed49a5SDavid van Moolenbroek 
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)2535*b2ed49a5SDavid van Moolenbroek PUBLIC int st_pair_by_name(char *cached_parent_name, char *cached_name,
2536*b2ed49a5SDavid van Moolenbroek     char *local_parent_name, char *local_name, _magic_id_t dsentry_site_id,
2537*b2ed49a5SDavid van Moolenbroek     int status_flags, int status_op)
2538*b2ed49a5SDavid van Moolenbroek {
2539*b2ed49a5SDavid van Moolenbroek     struct _magic_function *cached_function = NULL, *local_function = NULL;
2540*b2ed49a5SDavid van Moolenbroek     struct _magic_sentry *cached_sentry = NULL, *local_sentry = NULL;
2541*b2ed49a5SDavid van Moolenbroek     ST_CHECK_INIT();
2542*b2ed49a5SDavid van Moolenbroek     assert(cached_name || local_name);
2543*b2ed49a5SDavid van Moolenbroek 
2544*b2ed49a5SDavid van Moolenbroek     if (cached_name) {
2545*b2ed49a5SDavid van Moolenbroek         EXEC_WITH_MAGIC_VARS(
2546*b2ed49a5SDavid van Moolenbroek             cached_sentry = magic_sentry_lookup_by_name(cached_parent_name ? cached_parent_name : "", cached_name, dsentry_site_id, NULL);
2547*b2ed49a5SDavid van Moolenbroek             if (cached_sentry && MAGIC_SENTRY_IS_ALLOC(cached_sentry)) {
2548*b2ed49a5SDavid van Moolenbroek                 return EINVAL;
2549*b2ed49a5SDavid van Moolenbroek             }
2550*b2ed49a5SDavid van Moolenbroek             if (!cached_sentry) {
2551*b2ed49a5SDavid van Moolenbroek                 cached_function = magic_function_lookup_by_name(NULL, cached_name);
2552*b2ed49a5SDavid van Moolenbroek             }
2553*b2ed49a5SDavid van Moolenbroek             , &st_cached_magic_vars
2554*b2ed49a5SDavid van Moolenbroek         );
2555*b2ed49a5SDavid van Moolenbroek         if (!cached_sentry && !cached_function) {
2556*b2ed49a5SDavid van Moolenbroek             return ENOENT;
2557*b2ed49a5SDavid van Moolenbroek         }
2558*b2ed49a5SDavid van Moolenbroek     }
2559*b2ed49a5SDavid van Moolenbroek     if (local_name) {
2560*b2ed49a5SDavid van Moolenbroek         EXEC_WITH_MAGIC_VARS(
2561*b2ed49a5SDavid van Moolenbroek             if (!cached_function) {
2562*b2ed49a5SDavid van Moolenbroek                 local_sentry = magic_sentry_lookup_by_name(local_parent_name ? local_parent_name : "", local_name, dsentry_site_id, NULL);
2563*b2ed49a5SDavid van Moolenbroek                 if (local_sentry && MAGIC_SENTRY_IS_ALLOC(local_sentry)) {
2564*b2ed49a5SDavid van Moolenbroek                     return EINVAL;
2565*b2ed49a5SDavid van Moolenbroek                 }
2566*b2ed49a5SDavid van Moolenbroek             }
2567*b2ed49a5SDavid van Moolenbroek             if (!cached_sentry && !local_sentry) {
2568*b2ed49a5SDavid van Moolenbroek                 local_function = magic_function_lookup_by_name(NULL, local_name);
2569*b2ed49a5SDavid van Moolenbroek             }
2570*b2ed49a5SDavid van Moolenbroek             , st_local_magic_vars_ptr
2571*b2ed49a5SDavid van Moolenbroek         );
2572*b2ed49a5SDavid van Moolenbroek         if (!local_sentry && !local_function) {
2573*b2ed49a5SDavid van Moolenbroek             return ENOENT;
2574*b2ed49a5SDavid van Moolenbroek         }
2575*b2ed49a5SDavid van Moolenbroek     }
2576*b2ed49a5SDavid van Moolenbroek     if (cached_function || local_function) {
2577*b2ed49a5SDavid van Moolenbroek         assert(!cached_sentry && !local_sentry);
2578*b2ed49a5SDavid van Moolenbroek         st_pair_by_function(cached_function, local_function, status_flags, status_op);
2579*b2ed49a5SDavid van Moolenbroek         return OK;
2580*b2ed49a5SDavid van Moolenbroek     }
2581*b2ed49a5SDavid van Moolenbroek     assert(cached_sentry || local_sentry);
2582*b2ed49a5SDavid van Moolenbroek     st_pair_by_sentry(cached_sentry, local_sentry, status_flags, status_op);
2583*b2ed49a5SDavid van Moolenbroek     return OK;
2584*b2ed49a5SDavid van Moolenbroek }
2585*b2ed49a5SDavid van Moolenbroek 
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)2586*b2ed49a5SDavid van Moolenbroek 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)
2587*b2ed49a5SDavid van Moolenbroek {
2588*b2ed49a5SDavid van Moolenbroek     int r, saved_policies = st_policies;
2589*b2ed49a5SDavid van Moolenbroek     st_policies &= ~(ST_ON_ALLOC_UNPAIR_MASK);
2590*b2ed49a5SDavid van Moolenbroek     st_policies |= (alloc_policies & ST_ON_ALLOC_UNPAIR_MASK);
2591*b2ed49a5SDavid van Moolenbroek     r = st_pair_by_alloc_name(info, cached_parent_name, cached_name, cached_dsentry_site_id, local_parent_name, local_name, local_dsentry_site_id, num_elements, p_alloc_flags, status_flags, status_op);
2592*b2ed49a5SDavid van Moolenbroek     st_policies = saved_policies;
2593*b2ed49a5SDavid van Moolenbroek     return r;
2594*b2ed49a5SDavid van Moolenbroek }
2595*b2ed49a5SDavid van Moolenbroek 
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)2596*b2ed49a5SDavid van Moolenbroek 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)
2597*b2ed49a5SDavid van Moolenbroek {
2598*b2ed49a5SDavid van Moolenbroek     struct _magic_sentry *cached_sentry = NULL, *local_sentry = NULL;
2599*b2ed49a5SDavid van Moolenbroek     struct _magic_dsindex *local_dsindex = NULL;
2600*b2ed49a5SDavid van Moolenbroek     struct _magic_dsentry *prev_dsentry, *dsentry, *head_dsentry;
2601*b2ed49a5SDavid van Moolenbroek     struct _magic_sentry* sentry;
2602*b2ed49a5SDavid van Moolenbroek     int r;
2603*b2ed49a5SDavid van Moolenbroek     int is_cached_alloc = FALSE, is_local_alloc = FALSE;
2604*b2ed49a5SDavid van Moolenbroek     ST_CHECK_INIT();
2605*b2ed49a5SDavid van Moolenbroek     assert(cached_name || local_name);
2606*b2ed49a5SDavid van Moolenbroek     assert(!((cached_name == NULL) ^ (cached_parent_name == NULL)));
2607*b2ed49a5SDavid van Moolenbroek     assert(!((local_name == NULL) ^ (local_parent_name == NULL)));
2608*b2ed49a5SDavid van Moolenbroek 
2609*b2ed49a5SDavid van Moolenbroek     if (cached_name) {
2610*b2ed49a5SDavid van Moolenbroek         EXEC_WITH_MAGIC_VARS(
2611*b2ed49a5SDavid van Moolenbroek             cached_sentry = magic_sentry_lookup_by_name(cached_parent_name,
2612*b2ed49a5SDavid van Moolenbroek                 cached_name, cached_dsentry_site_id, NULL);
2613*b2ed49a5SDavid van Moolenbroek             if (cached_sentry && MAGIC_SENTRY_IS_ALLOC(cached_sentry)) {
2614*b2ed49a5SDavid van Moolenbroek                 is_cached_alloc = TRUE;
2615*b2ed49a5SDavid van Moolenbroek             }
2616*b2ed49a5SDavid van Moolenbroek             , &st_cached_magic_vars
2617*b2ed49a5SDavid van Moolenbroek         );
2618*b2ed49a5SDavid van Moolenbroek     }
2619*b2ed49a5SDavid van Moolenbroek     if (local_name) {
2620*b2ed49a5SDavid van Moolenbroek         EXEC_WITH_MAGIC_VARS(
2621*b2ed49a5SDavid van Moolenbroek             local_sentry = magic_sentry_lookup_by_name(local_parent_name,
2622*b2ed49a5SDavid van Moolenbroek                 local_name, local_dsentry_site_id, NULL);
2623*b2ed49a5SDavid van Moolenbroek             if (local_sentry && MAGIC_SENTRY_IS_ALLOC(local_sentry)) {
2624*b2ed49a5SDavid van Moolenbroek                 is_local_alloc = TRUE;
2625*b2ed49a5SDavid van Moolenbroek             }
2626*b2ed49a5SDavid van Moolenbroek             if (!local_sentry || is_local_alloc) {
2627*b2ed49a5SDavid van Moolenbroek                 local_dsindex = magic_dsindex_lookup_by_name(local_parent_name, local_name);
2628*b2ed49a5SDavid van Moolenbroek                 if (local_dsindex && !MAGIC_DSINDEX_IS_ALLOC(local_dsindex)) {
2629*b2ed49a5SDavid van Moolenbroek                     local_dsindex = NULL;
2630*b2ed49a5SDavid van Moolenbroek                 }
2631*b2ed49a5SDavid van Moolenbroek                 if (local_sentry) assert(local_dsindex);
2632*b2ed49a5SDavid van Moolenbroek                 is_local_alloc = is_local_alloc || local_dsindex != NULL;
2633*b2ed49a5SDavid van Moolenbroek             }
2634*b2ed49a5SDavid van Moolenbroek             , st_local_magic_vars_ptr
2635*b2ed49a5SDavid van Moolenbroek         );
2636*b2ed49a5SDavid van Moolenbroek     }
2637*b2ed49a5SDavid van Moolenbroek     if (!is_cached_alloc && !is_local_alloc) {
2638*b2ed49a5SDavid van Moolenbroek         if (cached_sentry || local_sentry) {
2639*b2ed49a5SDavid van Moolenbroek             st_pair_by_sentry(cached_sentry, local_sentry, status_flags, status_op);
2640*b2ed49a5SDavid van Moolenbroek             return OK;
2641*b2ed49a5SDavid van Moolenbroek         }
2642*b2ed49a5SDavid van Moolenbroek         return ENOENT;
2643*b2ed49a5SDavid van Moolenbroek     }
2644*b2ed49a5SDavid van Moolenbroek     if (local_sentry) {
2645*b2ed49a5SDavid van Moolenbroek         if (!is_local_alloc) {
2646*b2ed49a5SDavid van Moolenbroek             /* Alloc sentries may have multiple instances with the same name. */
2647*b2ed49a5SDavid van Moolenbroek             assert(cached_sentry && is_cached_alloc);
2648*b2ed49a5SDavid van Moolenbroek             head_dsentry = MAGIC_DSENTRY_NEXT(MAGIC_DSENTRY_FROM_SENTRY(cached_sentry));
2649*b2ed49a5SDavid van Moolenbroek             assert(cached_parent_name && cached_name);
2650*b2ed49a5SDavid van Moolenbroek             MAGIC_DSENTRY_ALIVE_NAME_ID_ITER(head_dsentry, prev_dsentry, dsentry, sentry, cached_parent_name, cached_name, cached_dsentry_site_id,
2651*b2ed49a5SDavid van Moolenbroek                 /* Cannot map multiple cached alloc sentries to a single local non-alloc sentry. */
2652*b2ed49a5SDavid van Moolenbroek                 return E2BIG;
2653*b2ed49a5SDavid van Moolenbroek             );
2654*b2ed49a5SDavid van Moolenbroek             /* Map a single cached alloc sentry to a single local non-alloc sentry. */
2655*b2ed49a5SDavid van Moolenbroek             st_pair_by_sentry(cached_sentry, local_sentry, status_flags, status_op);
2656*b2ed49a5SDavid van Moolenbroek             return OK;
2657*b2ed49a5SDavid van Moolenbroek         }
2658*b2ed49a5SDavid van Moolenbroek         else {
2659*b2ed49a5SDavid van Moolenbroek             /* Unpair all the local alloc sentries. */
2660*b2ed49a5SDavid van Moolenbroek             head_dsentry = MAGIC_DSENTRY_FROM_SENTRY(local_sentry);
2661*b2ed49a5SDavid van Moolenbroek             assert(local_parent_name && local_name);
2662*b2ed49a5SDavid van Moolenbroek             MAGIC_DSENTRY_ALIVE_NAME_ID_ITER(head_dsentry, prev_dsentry, dsentry, sentry, local_parent_name, local_name, local_dsentry_site_id,
2663*b2ed49a5SDavid van Moolenbroek                 st_pair_by_sentry(NULL, sentry, status_flags, status_op);
2664*b2ed49a5SDavid van Moolenbroek             );
2665*b2ed49a5SDavid van Moolenbroek         }
2666*b2ed49a5SDavid van Moolenbroek     }
2667*b2ed49a5SDavid van Moolenbroek     if (!cached_sentry) {
2668*b2ed49a5SDavid van Moolenbroek         return OK;
2669*b2ed49a5SDavid van Moolenbroek     }
2670*b2ed49a5SDavid van Moolenbroek 
2671*b2ed49a5SDavid van Moolenbroek     /* Map a single cached non-alloc sentry to a local to-be-alloc sentry. */
2672*b2ed49a5SDavid van Moolenbroek     if (!is_cached_alloc) {
2673*b2ed49a5SDavid van Moolenbroek         assert(local_dsindex);
2674*b2ed49a5SDavid van Moolenbroek         return st_pair_alloc_by_dsindex(info, cached_sentry, local_dsindex, num_elements, p_alloc_flags, status_flags, status_op);
2675*b2ed49a5SDavid van Moolenbroek     }
2676*b2ed49a5SDavid van Moolenbroek 
2677*b2ed49a5SDavid van Moolenbroek     /* Map all the cached alloc sentries to the corresponding local to-be-alloc sentries (or NULL). */
2678*b2ed49a5SDavid van Moolenbroek     head_dsentry = MAGIC_DSENTRY_FROM_SENTRY(cached_sentry);
2679*b2ed49a5SDavid van Moolenbroek     assert(cached_parent_name && cached_name);
2680*b2ed49a5SDavid van Moolenbroek     MAGIC_DSENTRY_ALIVE_NAME_ID_ITER(head_dsentry, prev_dsentry, dsentry,
2681*b2ed49a5SDavid van Moolenbroek         sentry, cached_parent_name, cached_name, cached_dsentry_site_id,
2682*b2ed49a5SDavid van Moolenbroek         r = st_pair_alloc_by_dsindex(info, sentry, local_dsindex, num_elements, p_alloc_flags, status_flags, status_op);
2683*b2ed49a5SDavid van Moolenbroek         if (r != OK) {
2684*b2ed49a5SDavid van Moolenbroek             return r;
2685*b2ed49a5SDavid van Moolenbroek         }
2686*b2ed49a5SDavid van Moolenbroek     );
2687*b2ed49a5SDavid van Moolenbroek 
2688*b2ed49a5SDavid van Moolenbroek     return OK;
2689*b2ed49a5SDavid van Moolenbroek }
2690*b2ed49a5SDavid van Moolenbroek 
2691*b2ed49a5SDavid van Moolenbroek /* Metadata transfer and adjustment functions */
2692*b2ed49a5SDavid van Moolenbroek 
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)2693*b2ed49a5SDavid van Moolenbroek PRIVATE int transfer_metadata_functions(st_init_info_t *info,
2694*b2ed49a5SDavid van Moolenbroek     struct _magic_vars_t *cached_magic_vars,
2695*b2ed49a5SDavid van Moolenbroek     struct _magic_vars_t *remote_magic_vars,
2696*b2ed49a5SDavid van Moolenbroek     st_counterparts_t *counterparts)
2697*b2ed49a5SDavid van Moolenbroek {
2698*b2ed49a5SDavid van Moolenbroek 
2699*b2ed49a5SDavid van Moolenbroek     int i;
2700*b2ed49a5SDavid van Moolenbroek     struct _magic_function *cached_function;
2701*b2ed49a5SDavid van Moolenbroek 
2702*b2ed49a5SDavid van Moolenbroek     /* transfer magic_functions */
2703*b2ed49a5SDavid van Moolenbroek     MD_TRANSFER(info, remote_magic_vars->functions, (void **)&cached_magic_vars->functions, remote_magic_vars->functions_num * sizeof(struct _magic_function));
2704*b2ed49a5SDavid van Moolenbroek 
2705*b2ed49a5SDavid van Moolenbroek     /* adjust magic_functions */
2706*b2ed49a5SDavid van Moolenbroek     for (i = 0 ; i < cached_magic_vars->functions_num ; i++) {
2707*b2ed49a5SDavid van Moolenbroek         cached_function = &cached_magic_vars->functions[i];
2708*b2ed49a5SDavid van Moolenbroek         MD_TRANSFER_STR(info, &cached_function->name);
2709*b2ed49a5SDavid van Moolenbroek         cached_function->type = &cached_magic_vars->types[cached_function->type - remote_magic_vars->types];
2710*b2ed49a5SDavid van Moolenbroek     }
2711*b2ed49a5SDavid van Moolenbroek 
2712*b2ed49a5SDavid van Moolenbroek     return OK;
2713*b2ed49a5SDavid van Moolenbroek }
2714*b2ed49a5SDavid van Moolenbroek 
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)2715*b2ed49a5SDavid van Moolenbroek PRIVATE int transfer_metadata_dfunctions(st_init_info_t *info,
2716*b2ed49a5SDavid van Moolenbroek     struct _magic_vars_t *cached_magic_vars,
2717*b2ed49a5SDavid van Moolenbroek     struct _magic_vars_t *remote_magic_vars,
2718*b2ed49a5SDavid van Moolenbroek     st_counterparts_t *counterparts)
2719*b2ed49a5SDavid van Moolenbroek {
2720*b2ed49a5SDavid van Moolenbroek 
2721*b2ed49a5SDavid van Moolenbroek     struct _magic_dfunction **dfunction_ptr;
2722*b2ed49a5SDavid van Moolenbroek     struct _magic_dfunction *cached_dfunction, *prev_dfunction = NULL;
2723*b2ed49a5SDavid van Moolenbroek     struct _magic_function *cached_function;
2724*b2ed49a5SDavid van Moolenbroek 
2725*b2ed49a5SDavid van Moolenbroek     /* Transfer dfunctions. */
2726*b2ed49a5SDavid van Moolenbroek     cached_magic_vars->first_dfunction = remote_magic_vars->first_dfunction;
2727*b2ed49a5SDavid van Moolenbroek     dfunction_ptr = &cached_magic_vars->first_dfunction;
2728*b2ed49a5SDavid van Moolenbroek     while (*dfunction_ptr != NULL) {
2729*b2ed49a5SDavid van Moolenbroek         MD_TRANSFER(info, *dfunction_ptr, (void **)dfunction_ptr, sizeof(struct _magic_dfunction));
2730*b2ed49a5SDavid van Moolenbroek         cached_dfunction = *dfunction_ptr;
2731*b2ed49a5SDavid van Moolenbroek 
2732*b2ed49a5SDavid van Moolenbroek         /* Adjust dfunction parent_name and next/prev links. */
2733*b2ed49a5SDavid van Moolenbroek         if (cached_dfunction->parent_name != NULL) {
2734*b2ed49a5SDavid van Moolenbroek             MD_TRANSFER_STR(info, &cached_dfunction->parent_name);
2735*b2ed49a5SDavid van Moolenbroek             if (strlen(cached_dfunction->parent_name) == 0) {
2736*b2ed49a5SDavid van Moolenbroek                 printf("ERROR. strlen(dfunction->parent_name) == 0.\n");
2737*b2ed49a5SDavid van Moolenbroek                 return EGENERIC;
2738*b2ed49a5SDavid van Moolenbroek             }
2739*b2ed49a5SDavid van Moolenbroek         } else {
2740*b2ed49a5SDavid van Moolenbroek             printf("ERROR. dfunction->parent_name == NULL.\n");
2741*b2ed49a5SDavid van Moolenbroek             return EGENERIC;
2742*b2ed49a5SDavid van Moolenbroek         }
2743*b2ed49a5SDavid van Moolenbroek 
2744*b2ed49a5SDavid van Moolenbroek         /* Adjust function name and type. */
2745*b2ed49a5SDavid van Moolenbroek         cached_function = &cached_dfunction->function;
2746*b2ed49a5SDavid van Moolenbroek         MD_TRANSFER_STR(info, &cached_function->name);
2747*b2ed49a5SDavid van Moolenbroek         cached_function->type = &cached_magic_vars->types[cached_function->type - remote_magic_vars->types];
2748*b2ed49a5SDavid van Moolenbroek 
2749*b2ed49a5SDavid van Moolenbroek         if (cached_dfunction->prev != NULL)
2750*b2ed49a5SDavid van Moolenbroek             cached_dfunction->prev = prev_dfunction;
2751*b2ed49a5SDavid van Moolenbroek 
2752*b2ed49a5SDavid van Moolenbroek         dfunction_ptr = &cached_dfunction->next;
2753*b2ed49a5SDavid van Moolenbroek         prev_dfunction = cached_dfunction;
2754*b2ed49a5SDavid van Moolenbroek     }
2755*b2ed49a5SDavid van Moolenbroek 
2756*b2ed49a5SDavid van Moolenbroek     cached_magic_vars->last_dfunction = prev_dfunction;
2757*b2ed49a5SDavid van Moolenbroek 
2758*b2ed49a5SDavid van Moolenbroek     return OK;
2759*b2ed49a5SDavid van Moolenbroek }
2760*b2ed49a5SDavid van Moolenbroek 
2761*b2ed49a5SDavid van Moolenbroek 
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)2762*b2ed49a5SDavid van Moolenbroek PUBLIC int st_transfer_metadata_types(st_init_info_t *info, struct _magic_vars_t *cached_magic_vars
2763*b2ed49a5SDavid van Moolenbroek     , struct _magic_vars_t *remote_magic_vars, st_counterparts_t *counterparts)
2764*b2ed49a5SDavid van Moolenbroek {
2765*b2ed49a5SDavid van Moolenbroek 
2766*b2ed49a5SDavid van Moolenbroek     int i;
2767*b2ed49a5SDavid van Moolenbroek 
2768*b2ed49a5SDavid van Moolenbroek     /* transfer types */
2769*b2ed49a5SDavid van Moolenbroek     MD_TRANSFER(info, remote_magic_vars->types, (void **)&cached_magic_vars->types, remote_magic_vars->types_num * sizeof(struct _magic_type));
2770*b2ed49a5SDavid van Moolenbroek 
2771*b2ed49a5SDavid van Moolenbroek     /* type adjustments */
2772*b2ed49a5SDavid van Moolenbroek     for (i = 0 ; i < cached_magic_vars->types_num ; i++) {
2773*b2ed49a5SDavid van Moolenbroek         if (transfer_metadata_type_members(info, &cached_magic_vars->types[i], cached_magic_vars, remote_magic_vars)) {
2774*b2ed49a5SDavid van Moolenbroek             printf("ERROR transferring type members metadata.\n");
2775*b2ed49a5SDavid van Moolenbroek             return EGENERIC;
2776*b2ed49a5SDavid van Moolenbroek         }
2777*b2ed49a5SDavid van Moolenbroek         set_typename_key(&cached_magic_vars->types[i]);
2778*b2ed49a5SDavid van Moolenbroek     }
2779*b2ed49a5SDavid van Moolenbroek 
2780*b2ed49a5SDavid van Moolenbroek     return OK;
2781*b2ed49a5SDavid van Moolenbroek }
2782*b2ed49a5SDavid van Moolenbroek 
transfer_metadata_type_value_set(st_init_info_t * info,struct _magic_type * type,struct _magic_vars_t * cached_magic_vars,struct _magic_vars_t * remote_magic_vars)2783*b2ed49a5SDavid van Moolenbroek PRIVATE int transfer_metadata_type_value_set(st_init_info_t *info, struct _magic_type *type, struct _magic_vars_t *cached_magic_vars, struct _magic_vars_t *remote_magic_vars)
2784*b2ed49a5SDavid van Moolenbroek {
2785*b2ed49a5SDavid van Moolenbroek     int num_elements;
2786*b2ed49a5SDavid van Moolenbroek     /* MD_TRANSFER cannot be used, because it will allocate space for num_elements */
2787*b2ed49a5SDavid van Moolenbroek     if (st_cbs_os.copy_state_region(info->info_opaque, (uint32_t) type->value_set, sizeof(int), (uint32_t) &num_elements)) {
2788*b2ed49a5SDavid van Moolenbroek         printf("ERROR transferring type value set metadata.\n");
2789*b2ed49a5SDavid van Moolenbroek         return EGENERIC;
2790*b2ed49a5SDavid van Moolenbroek     }
2791*b2ed49a5SDavid van Moolenbroek     num_elements++;
2792*b2ed49a5SDavid van Moolenbroek     MD_TRANSFER(info, type->value_set, (void **)&type->value_set, num_elements *sizeof(int));
2793*b2ed49a5SDavid van Moolenbroek     return OK;
2794*b2ed49a5SDavid van Moolenbroek }
2795*b2ed49a5SDavid van Moolenbroek 
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)2796*b2ed49a5SDavid van Moolenbroek 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)
2797*b2ed49a5SDavid van Moolenbroek {
2798*b2ed49a5SDavid van Moolenbroek     int r;
2799*b2ed49a5SDavid van Moolenbroek     int num_child = MAGIC_TYPE_NUM_CONTAINED_TYPES(type), i;
2800*b2ed49a5SDavid van Moolenbroek 
2801*b2ed49a5SDavid van Moolenbroek     MD_TRANSFER_STR(info, &type->name);
2802*b2ed49a5SDavid van Moolenbroek     MD_TRANSFER_STR(info, &type->type_str);
2803*b2ed49a5SDavid van Moolenbroek 
2804*b2ed49a5SDavid van Moolenbroek     if (type->names != NULL && type->num_names > 0) {
2805*b2ed49a5SDavid van Moolenbroek         /* transfer array of name pointers */
2806*b2ed49a5SDavid van Moolenbroek         MD_TRANSFER(info, type->names, (void **)&type->names, type->num_names * sizeof(char *));
2807*b2ed49a5SDavid van Moolenbroek         for (i = 0 ; (unsigned int)i < type->num_names ; i++) {
2808*b2ed49a5SDavid van Moolenbroek             /* transfer individual name */
2809*b2ed49a5SDavid van Moolenbroek             MD_TRANSFER_STR(info, &type->names[i]);
2810*b2ed49a5SDavid van Moolenbroek         }
2811*b2ed49a5SDavid van Moolenbroek     }
2812*b2ed49a5SDavid van Moolenbroek 
2813*b2ed49a5SDavid van Moolenbroek 
2814*b2ed49a5SDavid van Moolenbroek #define MD_TRANSFER_ADJUST_MEMBER_PTR(NUM_ELEMENTS,                            \
2815*b2ed49a5SDavid van Moolenbroek     ELEMENT_SIZE,PTR_ARRAY,INDEX)                                              \
2816*b2ed49a5SDavid van Moolenbroek     if((NUM_ELEMENTS) > 0 && (PTR_ARRAY) != NULL) {                            \
2817*b2ed49a5SDavid van Moolenbroek         MD_TRANSFER(info, PTR_ARRAY, (void **)&PTR_ARRAY,                      \
2818*b2ed49a5SDavid van Moolenbroek             NUM_ELEMENTS * ELEMENT_SIZE);                                      \
2819*b2ed49a5SDavid van Moolenbroek         for(INDEX = 0 ; (INDEX) < (NUM_ELEMENTS) ; INDEX++) {                  \
2820*b2ed49a5SDavid van Moolenbroek             PTR_ARRAY[INDEX] = ADJUST_POINTER(cached_magic_vars->types,        \
2821*b2ed49a5SDavid van Moolenbroek                 remote_magic_vars->types, PTR_ARRAY[INDEX]);                   \
2822*b2ed49a5SDavid van Moolenbroek         }                                                                      \
2823*b2ed49a5SDavid van Moolenbroek     }
2824*b2ed49a5SDavid van Moolenbroek 
2825*b2ed49a5SDavid van Moolenbroek     MD_TRANSFER_ADJUST_MEMBER_PTR(
2826*b2ed49a5SDavid van Moolenbroek         (type->type_id == MAGIC_TYPE_FUNCTION ? num_child + 1 : num_child),
2827*b2ed49a5SDavid van Moolenbroek         sizeof(struct _magic_type *), type->contained_types, i
2828*b2ed49a5SDavid van Moolenbroek     );
2829*b2ed49a5SDavid van Moolenbroek 
2830*b2ed49a5SDavid van Moolenbroek     if (type->compatible_types) {
2831*b2ed49a5SDavid van Moolenbroek         struct _magic_type *comp_types_element;
2832*b2ed49a5SDavid van Moolenbroek         int comp_types_size=0;
2833*b2ed49a5SDavid van Moolenbroek         /* determine size of array */
2834*b2ed49a5SDavid van Moolenbroek         do {
2835*b2ed49a5SDavid van Moolenbroek             if (st_cbs_os.copy_state_region(info->info_opaque, (uint32_t) &type->compatible_types[comp_types_size]
2836*b2ed49a5SDavid van Moolenbroek                 , sizeof(struct _magic_type *), (uint32_t) &comp_types_element))
2837*b2ed49a5SDavid van Moolenbroek             {
2838*b2ed49a5SDavid van Moolenbroek                 printf("ERROR transferring compatible types array metadata.\n");
2839*b2ed49a5SDavid van Moolenbroek                 return EGENERIC;
2840*b2ed49a5SDavid van Moolenbroek             }
2841*b2ed49a5SDavid van Moolenbroek             comp_types_size++;
2842*b2ed49a5SDavid van Moolenbroek         } while(comp_types_element != NULL);
2843*b2ed49a5SDavid van Moolenbroek         /* We know the size, now transfer the whole array */
2844*b2ed49a5SDavid van Moolenbroek         MD_TRANSFER(info, type->compatible_types, (void **) &type->compatible_types, comp_types_size * sizeof(struct _magic_type *));
2845*b2ed49a5SDavid van Moolenbroek         for (i = 0; i < comp_types_size; i++) {
2846*b2ed49a5SDavid van Moolenbroek             if (type->compatible_types[i] != NULL) {
2847*b2ed49a5SDavid van Moolenbroek                 /* Adjust the pointer to point to the local counterpart */
2848*b2ed49a5SDavid van Moolenbroek                 type->compatible_types[i] = ADJUST_POINTER(cached_magic_vars->types,  remote_magic_vars->types, type->compatible_types[i]);
2849*b2ed49a5SDavid van Moolenbroek             }
2850*b2ed49a5SDavid van Moolenbroek         }
2851*b2ed49a5SDavid van Moolenbroek     }
2852*b2ed49a5SDavid van Moolenbroek 
2853*b2ed49a5SDavid van Moolenbroek     if (num_child>0 && type->member_names != NULL) {
2854*b2ed49a5SDavid van Moolenbroek         MD_TRANSFER(info, type->member_names, (void **)&type->member_names, num_child * sizeof(char *));
2855*b2ed49a5SDavid van Moolenbroek         for (i = 0 ; i < num_child ; i++) {
2856*b2ed49a5SDavid van Moolenbroek             MD_TRANSFER_STR(info, &type->member_names[i]);
2857*b2ed49a5SDavid van Moolenbroek         }
2858*b2ed49a5SDavid van Moolenbroek     }
2859*b2ed49a5SDavid van Moolenbroek 
2860*b2ed49a5SDavid van Moolenbroek     if (num_child>0 && type->member_offsets != NULL) {
2861*b2ed49a5SDavid van Moolenbroek         MD_TRANSFER(info, type->member_offsets, (void **)&type->member_offsets, num_child * sizeof(unsigned));
2862*b2ed49a5SDavid van Moolenbroek     }
2863*b2ed49a5SDavid van Moolenbroek 
2864*b2ed49a5SDavid van Moolenbroek     if (MAGIC_TYPE_HAS_VALUE_SET(type)) {
2865*b2ed49a5SDavid van Moolenbroek         r = transfer_metadata_type_value_set(info, type, cached_magic_vars, remote_magic_vars);
2866*b2ed49a5SDavid van Moolenbroek         if (r != OK) {
2867*b2ed49a5SDavid van Moolenbroek             return r;
2868*b2ed49a5SDavid van Moolenbroek         }
2869*b2ed49a5SDavid van Moolenbroek     }
2870*b2ed49a5SDavid van Moolenbroek     return OK;
2871*b2ed49a5SDavid van Moolenbroek }
2872*b2ed49a5SDavid van Moolenbroek 
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,size_t * max_buff_sz)2873*b2ed49a5SDavid van Moolenbroek PRIVATE int transfer_metadata_sentries(st_init_info_t *info, struct _magic_vars_t *cached_magic_vars
2874*b2ed49a5SDavid van Moolenbroek     , struct _magic_vars_t *remote_magic_vars, st_counterparts_t *counterparts
2875*b2ed49a5SDavid van Moolenbroek     , size_t *max_buff_sz)
2876*b2ed49a5SDavid van Moolenbroek {
2877*b2ed49a5SDavid van Moolenbroek 
2878*b2ed49a5SDavid van Moolenbroek     int i;
2879*b2ed49a5SDavid van Moolenbroek     int skipped_sentries = 0;
2880*b2ed49a5SDavid van Moolenbroek     struct _magic_sentry *cached_sentry;
2881*b2ed49a5SDavid van Moolenbroek 
2882*b2ed49a5SDavid van Moolenbroek     /* transfer sentries */
2883*b2ed49a5SDavid van Moolenbroek     MD_TRANSFER(info, remote_magic_vars->sentries, (void **)&cached_magic_vars->sentries, remote_magic_vars->sentries_num * sizeof(struct _magic_sentry));
2884*b2ed49a5SDavid van Moolenbroek     /* todo: try to use only remote_magic_vars or cached magic_vars */
2885*b2ed49a5SDavid van Moolenbroek     /* todo: if transfer is complete, and argument 2 and 3 are always the same, remove 2nd argument */
2886*b2ed49a5SDavid van Moolenbroek 
2887*b2ed49a5SDavid van Moolenbroek     /* adjust sentries */
2888*b2ed49a5SDavid van Moolenbroek     for (i = 0 ; i < cached_magic_vars->sentries_num ; i++) {
2889*b2ed49a5SDavid van Moolenbroek         cached_sentry = &cached_magic_vars->sentries[i];
2890*b2ed49a5SDavid van Moolenbroek 
2891*b2ed49a5SDavid van Moolenbroek         if ((st_policies & ST_TRANSFER_DIRTY_ONLY) &&
2892*b2ed49a5SDavid van Moolenbroek             !MAGIC_STATE_FLAG(cached_sentry, MAGIC_STATE_DIRTY_PAGE) &&
2893*b2ed49a5SDavid van Moolenbroek             !MAGIC_STATE_FLAG(cached_sentry, MAGIC_STATE_IMMUTABLE)) {
2894*b2ed49a5SDavid van Moolenbroek             skipped_sentries++;
2895*b2ed49a5SDavid van Moolenbroek             continue;
2896*b2ed49a5SDavid van Moolenbroek         }
2897*b2ed49a5SDavid van Moolenbroek         if (skipped_sentries > 0) {
2898*b2ed49a5SDavid van Moolenbroek             cached_magic_vars->sentries[i - skipped_sentries] =
2899*b2ed49a5SDavid van Moolenbroek                 cached_magic_vars->sentries[i];
2900*b2ed49a5SDavid van Moolenbroek             cached_magic_vars->sentries[i - skipped_sentries].id -=
2901*b2ed49a5SDavid van Moolenbroek                 skipped_sentries;
2902*b2ed49a5SDavid van Moolenbroek             cached_sentry = &cached_magic_vars->sentries[i - skipped_sentries];
2903*b2ed49a5SDavid van Moolenbroek         }
2904*b2ed49a5SDavid van Moolenbroek 
2905*b2ed49a5SDavid van Moolenbroek 
2906*b2ed49a5SDavid van Moolenbroek         if (transfer_metadata_sentry_members(info, cached_sentry)) {
2907*b2ed49a5SDavid van Moolenbroek             printf("ERROR transferring sentry members metadata.\n");
2908*b2ed49a5SDavid van Moolenbroek             return EGENERIC;
2909*b2ed49a5SDavid van Moolenbroek         }
2910*b2ed49a5SDavid van Moolenbroek 
2911*b2ed49a5SDavid van Moolenbroek         /*
2912*b2ed49a5SDavid van Moolenbroek          * We have to change the type to its cached counterpart,
2913*b2ed49a5SDavid van Moolenbroek          * so that it may be compared to the local type of the local sentry counterpart.
2914*b2ed49a5SDavid van Moolenbroek          */
2915*b2ed49a5SDavid van Moolenbroek         cached_sentry->type = &cached_magic_vars->types[cached_sentry->type - remote_magic_vars->types];
2916*b2ed49a5SDavid van Moolenbroek 
2917*b2ed49a5SDavid van Moolenbroek         if (cached_sentry->type->size > *max_buff_sz) {
2918*b2ed49a5SDavid van Moolenbroek             *max_buff_sz = cached_sentry->type->size;
2919*b2ed49a5SDavid van Moolenbroek         }
2920*b2ed49a5SDavid van Moolenbroek     }
2921*b2ed49a5SDavid van Moolenbroek 
2922*b2ed49a5SDavid van Moolenbroek     if (skipped_sentries > 0)
2923*b2ed49a5SDavid van Moolenbroek         cached_magic_vars->sentries_num -= skipped_sentries;
2924*b2ed49a5SDavid van Moolenbroek 
2925*b2ed49a5SDavid van Moolenbroek     return OK;
2926*b2ed49a5SDavid van Moolenbroek }
2927*b2ed49a5SDavid van Moolenbroek 
transfer_metadata_sentry_members(st_init_info_t * info,struct _magic_sentry * sentry)2928*b2ed49a5SDavid van Moolenbroek PRIVATE int transfer_metadata_sentry_members(st_init_info_t *info, struct _magic_sentry *sentry)
2929*b2ed49a5SDavid van Moolenbroek {
2930*b2ed49a5SDavid van Moolenbroek     if (sentry->name != NULL) {
2931*b2ed49a5SDavid van Moolenbroek         MD_TRANSFER_STR(info, &sentry->name);
2932*b2ed49a5SDavid van Moolenbroek     } else {
2933*b2ed49a5SDavid van Moolenbroek         printf("ERROR. sentry->name == NULL.\n");
2934*b2ed49a5SDavid van Moolenbroek         return EGENERIC;
2935*b2ed49a5SDavid van Moolenbroek     }
2936*b2ed49a5SDavid van Moolenbroek     return OK;
2937*b2ed49a5SDavid van Moolenbroek }
2938*b2ed49a5SDavid van Moolenbroek 
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,size_t * max_buff_sz,int * dsentries_num)2939*b2ed49a5SDavid van Moolenbroek PUBLIC int st_transfer_metadata_dsentries(st_init_info_t *info, struct _magic_vars_t *cached_magic_vars
2940*b2ed49a5SDavid van Moolenbroek     , struct _magic_vars_t *remote_magic_vars, st_counterparts_t *counterparts, size_t *max_buff_sz, int *dsentries_num)
2941*b2ed49a5SDavid van Moolenbroek {
2942*b2ed49a5SDavid van Moolenbroek 
2943*b2ed49a5SDavid van Moolenbroek     struct _magic_dsentry **dsentry_ptr;
2944*b2ed49a5SDavid van Moolenbroek #if MAGIC_DSENTRY_ALLOW_PREV
2945*b2ed49a5SDavid van Moolenbroek     struct _magic_dsentry *prev_dsentry = NULL;
2946*b2ed49a5SDavid van Moolenbroek #endif
2947*b2ed49a5SDavid van Moolenbroek     int r;
2948*b2ed49a5SDavid van Moolenbroek 
2949*b2ed49a5SDavid van Moolenbroek     *dsentries_num = 0;
2950*b2ed49a5SDavid van Moolenbroek 
2951*b2ed49a5SDavid van Moolenbroek     cached_magic_vars->first_dsentry = remote_magic_vars->first_dsentry;
2952*b2ed49a5SDavid van Moolenbroek     dsentry_ptr = &cached_magic_vars->first_dsentry;
2953*b2ed49a5SDavid van Moolenbroek     while (*dsentry_ptr != NULL) {
2954*b2ed49a5SDavid van Moolenbroek 
2955*b2ed49a5SDavid van Moolenbroek         struct _magic_dsentry *cached_dsentry, *remote_dsentry = *dsentry_ptr;
2956*b2ed49a5SDavid van Moolenbroek         struct _magic_sentry *sentry;
2957*b2ed49a5SDavid van Moolenbroek 
2958*b2ed49a5SDavid van Moolenbroek         /* transfer dsentry */
2959*b2ed49a5SDavid van Moolenbroek         MD_TRANSFER(info, *dsentry_ptr, (void **) dsentry_ptr, sizeof(struct _magic_dsentry));
2960*b2ed49a5SDavid van Moolenbroek         cached_dsentry = *dsentry_ptr;
2961*b2ed49a5SDavid van Moolenbroek 
2962*b2ed49a5SDavid van Moolenbroek         if ((st_policies & ST_TRANSFER_DIRTY_ONLY) &&
2963*b2ed49a5SDavid van Moolenbroek             !MAGIC_STATE_FLAG((&cached_dsentry->sentry), MAGIC_STATE_DIRTY_PAGE) &&
2964*b2ed49a5SDavid van Moolenbroek             !MAGIC_STATE_FLAG((&cached_dsentry->sentry), MAGIC_STATE_IMMUTABLE)) {
2965*b2ed49a5SDavid van Moolenbroek             *dsentry_ptr = cached_dsentry->next;
2966*b2ed49a5SDavid van Moolenbroek             continue;
2967*b2ed49a5SDavid van Moolenbroek         }
2968*b2ed49a5SDavid van Moolenbroek 
2969*b2ed49a5SDavid van Moolenbroek         if (cached_magic_vars->first_stack_dsentry == remote_dsentry) {
2970*b2ed49a5SDavid van Moolenbroek             cached_magic_vars->first_stack_dsentry = cached_dsentry;
2971*b2ed49a5SDavid van Moolenbroek         } else if(cached_magic_vars->last_stack_dsentry == remote_dsentry) {
2972*b2ed49a5SDavid van Moolenbroek             cached_magic_vars->last_stack_dsentry = cached_dsentry;
2973*b2ed49a5SDavid van Moolenbroek         }
2974*b2ed49a5SDavid van Moolenbroek 
2975*b2ed49a5SDavid van Moolenbroek         /* adjust dsentry */
2976*b2ed49a5SDavid van Moolenbroek         if (cached_dsentry->parent_name != NULL) {
2977*b2ed49a5SDavid van Moolenbroek             MD_TRANSFER_STR(info, &cached_dsentry->parent_name);
2978*b2ed49a5SDavid van Moolenbroek             if (strlen(cached_dsentry->parent_name) == 0) {
2979*b2ed49a5SDavid van Moolenbroek                 printf("ERROR. strlen(dsentry->parent_name) == 0.\n");
2980*b2ed49a5SDavid van Moolenbroek #if TODO_DSENTRY_PARENT_NAME_BUG
2981*b2ed49a5SDavid van Moolenbroek                 if (cached_dsentry->next != NULL)
2982*b2ed49a5SDavid van Moolenbroek #endif
2983*b2ed49a5SDavid van Moolenbroek                     return EGENERIC;
2984*b2ed49a5SDavid van Moolenbroek             }
2985*b2ed49a5SDavid van Moolenbroek         } else {
2986*b2ed49a5SDavid van Moolenbroek             printf("ERROR. dsentry->parent_name == NULL.\n");
2987*b2ed49a5SDavid van Moolenbroek             return EGENERIC;
2988*b2ed49a5SDavid van Moolenbroek         }
2989*b2ed49a5SDavid van Moolenbroek 
2990*b2ed49a5SDavid van Moolenbroek         sentry = &cached_dsentry->sentry;
2991*b2ed49a5SDavid van Moolenbroek         if (transfer_metadata_sentry_members(info, sentry)) {
2992*b2ed49a5SDavid van Moolenbroek             printf("ERROR transferring sentry members metadata.\n");
2993*b2ed49a5SDavid van Moolenbroek             return EGENERIC;
2994*b2ed49a5SDavid van Moolenbroek         }
2995*b2ed49a5SDavid van Moolenbroek 
2996*b2ed49a5SDavid van Moolenbroek         /* Override original id to simplify pairing later. */
2997*b2ed49a5SDavid van Moolenbroek         sentry->id = cached_magic_vars->sentries_num + *dsentries_num + 1;
2998*b2ed49a5SDavid van Moolenbroek 
2999*b2ed49a5SDavid van Moolenbroek         /*
3000*b2ed49a5SDavid van Moolenbroek          * Report violations for all the pointers pointing to the initial stack area.
3001*b2ed49a5SDavid van Moolenbroek          * This is to make sure no assumption is incorrectly made about this area.
3002*b2ed49a5SDavid van Moolenbroek          */
3003*b2ed49a5SDavid van Moolenbroek         if (!strcmp(sentry->name, MAGIC_ALLOC_INITIAL_STACK_NAME)) {
3004*b2ed49a5SDavid van Moolenbroek             sentry->flags |= MAGIC_STATE_ADDR_NOT_TAKEN;
3005*b2ed49a5SDavid van Moolenbroek         }
3006*b2ed49a5SDavid van Moolenbroek 
3007*b2ed49a5SDavid van Moolenbroek         /*
3008*b2ed49a5SDavid van Moolenbroek          * Adjust the type, so that the local and remote type can be compared
3009*b2ed49a5SDavid van Moolenbroek          * during a server version update
3010*b2ed49a5SDavid van Moolenbroek          */
3011*b2ed49a5SDavid van Moolenbroek         if (sentry->type == &remote_dsentry->type) {
3012*b2ed49a5SDavid van Moolenbroek 
3013*b2ed49a5SDavid van Moolenbroek             /*
3014*b2ed49a5SDavid van Moolenbroek              * sentry->type is contained in dsentry.type. Therefore, this is an
3015*b2ed49a5SDavid van Moolenbroek              * array type. In order to allocate a new memory region, we only
3016*b2ed49a5SDavid van Moolenbroek              * need the size of the type, and the contained type as arguments
3017*b2ed49a5SDavid van Moolenbroek              * to the magic allocation function. Therefore, other members of
3018*b2ed49a5SDavid van Moolenbroek              * the type do need to be cached or adjusted.
3019*b2ed49a5SDavid van Moolenbroek              */
3020*b2ed49a5SDavid van Moolenbroek 
3021*b2ed49a5SDavid van Moolenbroek             /* Adjust pointer to cached location */
3022*b2ed49a5SDavid van Moolenbroek             sentry->type = &cached_dsentry->type;
3023*b2ed49a5SDavid van Moolenbroek 
3024*b2ed49a5SDavid van Moolenbroek             /* Adjust contained_types to type_array located in dsentry struct. */
3025*b2ed49a5SDavid van Moolenbroek             sentry->type->contained_types = cached_dsentry->type_array;
3026*b2ed49a5SDavid van Moolenbroek 
3027*b2ed49a5SDavid van Moolenbroek             /*
3028*b2ed49a5SDavid van Moolenbroek              * Adjust only pointer in type_array. It currently has the same
3029*b2ed49a5SDavid van Moolenbroek              * value as the remote copy, but it has to point to the cached
3030*b2ed49a5SDavid van Moolenbroek              * of the contained type.
3031*b2ed49a5SDavid van Moolenbroek              */
3032*b2ed49a5SDavid van Moolenbroek             sentry->type->contained_types[0] = &cached_magic_vars->types[sentry->type->contained_types[0] - remote_magic_vars->types];
3033*b2ed49a5SDavid van Moolenbroek 
3034*b2ed49a5SDavid van Moolenbroek             /* Adjust empty strings. */
3035*b2ed49a5SDavid van Moolenbroek             sentry->type->name = "";
3036*b2ed49a5SDavid van Moolenbroek             sentry->type->type_str = "";
3037*b2ed49a5SDavid van Moolenbroek 
3038*b2ed49a5SDavid van Moolenbroek             /* Adjust value set if necessary. */
3039*b2ed49a5SDavid van Moolenbroek             if (MAGIC_TYPE_HAS_VALUE_SET(sentry->type)) {
3040*b2ed49a5SDavid van Moolenbroek                 r = transfer_metadata_type_value_set(info, sentry->type, cached_magic_vars, remote_magic_vars);
3041*b2ed49a5SDavid van Moolenbroek                 if (r != OK) {
3042*b2ed49a5SDavid van Moolenbroek                     return r;
3043*b2ed49a5SDavid van Moolenbroek                 }
3044*b2ed49a5SDavid van Moolenbroek             }
3045*b2ed49a5SDavid van Moolenbroek         } else {
3046*b2ed49a5SDavid van Moolenbroek 
3047*b2ed49a5SDavid van Moolenbroek             /*
3048*b2ed49a5SDavid van Moolenbroek              * sentry.type must be in the global type array. Adjust pointer accordingly.
3049*b2ed49a5SDavid van Moolenbroek              * The pointer is still pointing to the remote version.
3050*b2ed49a5SDavid van Moolenbroek              * We have to change it to the cached version.
3051*b2ed49a5SDavid van Moolenbroek              */
3052*b2ed49a5SDavid van Moolenbroek             sentry->type = &cached_magic_vars->types[sentry->type - remote_magic_vars->types];
3053*b2ed49a5SDavid van Moolenbroek 
3054*b2ed49a5SDavid van Moolenbroek         }
3055*b2ed49a5SDavid van Moolenbroek 
3056*b2ed49a5SDavid van Moolenbroek         /* see if the buffer needs to be bigger for the dsentry data region. */
3057*b2ed49a5SDavid van Moolenbroek         if (!MAGIC_STATE_FLAG(sentry, MAGIC_STATE_OUT_OF_BAND) && *max_buff_sz < sentry->type->size) {
3058*b2ed49a5SDavid van Moolenbroek             *max_buff_sz = sentry->type->size;
3059*b2ed49a5SDavid van Moolenbroek         }
3060*b2ed49a5SDavid van Moolenbroek 
3061*b2ed49a5SDavid van Moolenbroek         dsentry_ptr = &cached_dsentry->next;
3062*b2ed49a5SDavid van Moolenbroek #if MAGIC_DSENTRY_ALLOW_PREV
3063*b2ed49a5SDavid van Moolenbroek         if (cached_dsentry->prev != NULL)
3064*b2ed49a5SDavid van Moolenbroek             cached_dsentry->prev = prev_dsentry;
3065*b2ed49a5SDavid van Moolenbroek         prev_dsentry = cached_dsentry;
3066*b2ed49a5SDavid van Moolenbroek #endif
3067*b2ed49a5SDavid van Moolenbroek         *dsentries_num = *dsentries_num + 1;
3068*b2ed49a5SDavid van Moolenbroek     }
3069*b2ed49a5SDavid van Moolenbroek 
3070*b2ed49a5SDavid van Moolenbroek     return OK;
3071*b2ed49a5SDavid van Moolenbroek }
3072*b2ed49a5SDavid van Moolenbroek 
pair_metadata_types(st_init_info_t * info,struct _magic_vars_t * cached_magic_vars,st_counterparts_t * counterparts,int allow_unpaired_types)3073*b2ed49a5SDavid van Moolenbroek PRIVATE int pair_metadata_types(st_init_info_t *info,
3074*b2ed49a5SDavid van Moolenbroek     struct _magic_vars_t *cached_magic_vars, st_counterparts_t *counterparts, int allow_unpaired_types)
3075*b2ed49a5SDavid van Moolenbroek {
3076*b2ed49a5SDavid van Moolenbroek     int i, j, num_unpaired_struct_types = 0;
3077*b2ed49a5SDavid van Moolenbroek     int num_unpaired_types = 0;
3078*b2ed49a5SDavid van Moolenbroek     int num_total_types = 0;
3079*b2ed49a5SDavid van Moolenbroek     int num_struct_types = 0;
3080*b2ed49a5SDavid van Moolenbroek     int num_unpaired_types_left, num_unpaired_struct_types_left;
3081*b2ed49a5SDavid van Moolenbroek 
3082*b2ed49a5SDavid van Moolenbroek     if (st_unpaired_types_ratio > 0 || st_unpaired_struct_types_ratio > 0) {
3083*b2ed49a5SDavid van Moolenbroek         for (i = 0 ; i < cached_magic_vars->types_num ; i++) {
3084*b2ed49a5SDavid van Moolenbroek             struct _magic_type *type = &cached_magic_vars->types[i];
3085*b2ed49a5SDavid van Moolenbroek             if (ST_IS_UNPAIRABLE_STRUCT_TYPE(type)) {
3086*b2ed49a5SDavid van Moolenbroek                 num_struct_types++;
3087*b2ed49a5SDavid van Moolenbroek             }
3088*b2ed49a5SDavid van Moolenbroek             if (ST_IS_UNPAIRABLE_TYPE(type)) {
3089*b2ed49a5SDavid van Moolenbroek                 num_total_types++;
3090*b2ed49a5SDavid van Moolenbroek             }
3091*b2ed49a5SDavid van Moolenbroek         }
3092*b2ed49a5SDavid van Moolenbroek         num_unpaired_types = (int) (st_unpaired_types_ratio*num_total_types);
3093*b2ed49a5SDavid van Moolenbroek         num_unpaired_struct_types = (int) (st_unpaired_struct_types_ratio*num_struct_types);
3094*b2ed49a5SDavid van Moolenbroek     }
3095*b2ed49a5SDavid van Moolenbroek     num_unpaired_types_left = num_unpaired_types;
3096*b2ed49a5SDavid van Moolenbroek     num_unpaired_struct_types_left = num_unpaired_struct_types;
3097*b2ed49a5SDavid van Moolenbroek 
3098*b2ed49a5SDavid van Moolenbroek     /* type pairing, remote->local */
3099*b2ed49a5SDavid van Moolenbroek     for(i = 0 ; i < cached_magic_vars->types_num ; i++) {
3100*b2ed49a5SDavid van Moolenbroek         struct _magic_type *type = &cached_magic_vars->types[i];
3101*b2ed49a5SDavid van Moolenbroek         counterparts->types[i].counterpart = NULL;
3102*b2ed49a5SDavid van Moolenbroek 
3103*b2ed49a5SDavid van Moolenbroek         if (num_unpaired_types_left > 0 && ST_IS_UNPAIRABLE_TYPE(type)) {
3104*b2ed49a5SDavid van Moolenbroek             num_unpaired_types_left--;
3105*b2ed49a5SDavid van Moolenbroek             continue;
3106*b2ed49a5SDavid van Moolenbroek         }
3107*b2ed49a5SDavid van Moolenbroek         else if (num_unpaired_struct_types_left > 0 && ST_IS_UNPAIRABLE_STRUCT_TYPE(type)) {
3108*b2ed49a5SDavid van Moolenbroek             num_unpaired_struct_types_left--;
3109*b2ed49a5SDavid van Moolenbroek             continue;
3110*b2ed49a5SDavid van Moolenbroek         }
3111*b2ed49a5SDavid van Moolenbroek 
3112*b2ed49a5SDavid van Moolenbroek         for (j = 0 ; j < _magic_types_num ; j++) {
3113*b2ed49a5SDavid van Moolenbroek             /* A remote type may be paired to multiple local types.
3114*b2ed49a5SDavid van Moolenbroek              * It is safe to index only the first type since counterparts
3115*b2ed49a5SDavid van Moolenbroek              * are only used to speed up type matching.
3116*b2ed49a5SDavid van Moolenbroek              */
3117*b2ed49a5SDavid van Moolenbroek             if (magic_type_compatible(type, &_magic_types[j], MAGIC_TYPE_COMPARE_ALL)) {
3118*b2ed49a5SDavid van Moolenbroek                 counterparts->types[i].counterpart = &_magic_types[j];
3119*b2ed49a5SDavid van Moolenbroek                 break;
3120*b2ed49a5SDavid van Moolenbroek             }
3121*b2ed49a5SDavid van Moolenbroek         }
3122*b2ed49a5SDavid van Moolenbroek 
3123*b2ed49a5SDavid van Moolenbroek         if (!allow_unpaired_types && counterparts->types[i].counterpart == NULL) {
3124*b2ed49a5SDavid van Moolenbroek              printf("ERROR, remote type cannot be paired with a local type: ");
3125*b2ed49a5SDavid van Moolenbroek              MAGIC_TYPE_PRINT(type, MAGIC_EXPAND_TYPE_STR);
3126*b2ed49a5SDavid van Moolenbroek              printf("\n");
3127*b2ed49a5SDavid van Moolenbroek              return EGENERIC;
3128*b2ed49a5SDavid van Moolenbroek         }
3129*b2ed49a5SDavid van Moolenbroek     }
3130*b2ed49a5SDavid van Moolenbroek     if (st_unpaired_types_ratio > 0 || st_unpaired_struct_types_ratio > 0) {
3131*b2ed49a5SDavid van Moolenbroek         assert(num_unpaired_types_left == 0 && (st_unpaired_types_ratio > 0 || num_unpaired_struct_types == 0));
3132*b2ed49a5SDavid van Moolenbroek         _magic_printf("Unpaired types stats: unpaired types: %d, total types: %d, unpaired struct types: %d, struct types: %d\n", num_unpaired_types, num_total_types, num_unpaired_struct_types, num_struct_types);
3133*b2ed49a5SDavid van Moolenbroek     }
3134*b2ed49a5SDavid van Moolenbroek 
3135*b2ed49a5SDavid van Moolenbroek     for (i = 0 ; i < cached_magic_vars->types_num ; i++) {
3136*b2ed49a5SDavid van Moolenbroek         struct _magic_type *type = &cached_magic_vars->types[i];
3137*b2ed49a5SDavid van Moolenbroek         struct _magic_type *local_type = (struct _magic_type*) counterparts->types[i].counterpart;
3138*b2ed49a5SDavid van Moolenbroek         counterparts->ptr_types[i].counterpart = NULL;
3139*b2ed49a5SDavid van Moolenbroek         if (local_type && type->type_id == MAGIC_TYPE_POINTER) {
3140*b2ed49a5SDavid van Moolenbroek             if (MAGIC_TYPE_HAS_COMP_TYPES(type) != MAGIC_TYPE_HAS_COMP_TYPES(local_type)) {
3141*b2ed49a5SDavid van Moolenbroek                 continue;
3142*b2ed49a5SDavid van Moolenbroek             }
3143*b2ed49a5SDavid van Moolenbroek             if (MAGIC_TYPE_HAS_COMP_TYPES(type)) {
3144*b2ed49a5SDavid van Moolenbroek                 j = 0;
3145*b2ed49a5SDavid van Moolenbroek                 while (MAGIC_TYPE_HAS_COMP_TYPE(type, j) && MAGIC_TYPE_HAS_COMP_TYPE(local_type, j)) {
3146*b2ed49a5SDavid van Moolenbroek                     struct _magic_type *ctype = MAGIC_TYPE_COMP_TYPE(type, j);
3147*b2ed49a5SDavid van Moolenbroek                     struct _magic_type *local_ctype = MAGIC_TYPE_COMP_TYPE(local_type, j);
3148*b2ed49a5SDavid van Moolenbroek                     if (!ST_TYPE_IS_CACHED_COUNTERPART(ctype, local_ctype)) {
3149*b2ed49a5SDavid van Moolenbroek                         break;
3150*b2ed49a5SDavid van Moolenbroek                     }
3151*b2ed49a5SDavid van Moolenbroek                     j++;
3152*b2ed49a5SDavid van Moolenbroek                 }
3153*b2ed49a5SDavid van Moolenbroek                 if (MAGIC_TYPE_HAS_COMP_TYPE(type, j) || MAGIC_TYPE_HAS_COMP_TYPE(local_type, j)) {
3154*b2ed49a5SDavid van Moolenbroek                     continue;
3155*b2ed49a5SDavid van Moolenbroek                 }
3156*b2ed49a5SDavid van Moolenbroek             }
3157*b2ed49a5SDavid van Moolenbroek             counterparts->ptr_types[i].counterpart = local_type;
3158*b2ed49a5SDavid van Moolenbroek         }
3159*b2ed49a5SDavid van Moolenbroek     }
3160*b2ed49a5SDavid van Moolenbroek 
3161*b2ed49a5SDavid van Moolenbroek     return OK;
3162*b2ed49a5SDavid van Moolenbroek }
3163*b2ed49a5SDavid van Moolenbroek 
pair_metadata_functions(st_init_info_t * info,struct _magic_vars_t * cached_magic_vars,st_counterparts_t * counterparts)3164*b2ed49a5SDavid van Moolenbroek PRIVATE int pair_metadata_functions(st_init_info_t *info,
3165*b2ed49a5SDavid van Moolenbroek     struct _magic_vars_t *cached_magic_vars, st_counterparts_t *counterparts)
3166*b2ed49a5SDavid van Moolenbroek {
3167*b2ed49a5SDavid van Moolenbroek     int i;
3168*b2ed49a5SDavid van Moolenbroek     struct _magic_function *cached_function, *local_function;
3169*b2ed49a5SDavid van Moolenbroek #if ST_DEBUG_LEVEL > 0
3170*b2ed49a5SDavid van Moolenbroek     int num_relocated = 0;
3171*b2ed49a5SDavid van Moolenbroek #endif
3172*b2ed49a5SDavid van Moolenbroek 
3173*b2ed49a5SDavid van Moolenbroek     /* map remote functions to local functions */
3174*b2ed49a5SDavid van Moolenbroek     for(i = 0 ; i < cached_magic_vars->functions_num ; i++) {
3175*b2ed49a5SDavid van Moolenbroek         cached_function = &cached_magic_vars->functions[i];
3176*b2ed49a5SDavid van Moolenbroek         local_function = NULL;
3177*b2ed49a5SDavid van Moolenbroek         st_map_functions(&cached_function, &local_function);
3178*b2ed49a5SDavid van Moolenbroek         ST_SET_CACHED_COUNTERPART(cached_function, functions, functions, local_function);
3179*b2ed49a5SDavid van Moolenbroek 
3180*b2ed49a5SDavid van Moolenbroek #if CHECK_SENTITY_PAIRS
3181*b2ed49a5SDavid van Moolenbroek         if (local_function) {
3182*b2ed49a5SDavid van Moolenbroek             /* debug: see if the function is paired more than once */
3183*b2ed49a5SDavid van Moolenbroek             struct _magic_function *cfunction = NULL;
3184*b2ed49a5SDavid van Moolenbroek             st_map_functions(&cfunction, &local_function);
3185*b2ed49a5SDavid van Moolenbroek             if (cfunction != cached_function) {
3186*b2ed49a5SDavid van Moolenbroek                 printf("function pairing failed for (1) local function linked to multiple remote functions (2), (3)\n");
3187*b2ed49a5SDavid van Moolenbroek                 printf("(1) "); MAGIC_FUNCTION_PRINT(local_function, 0); printf("\n");
3188*b2ed49a5SDavid van Moolenbroek                 printf("(2) "); MAGIC_FUNCTION_PRINT(cached_function, 0); printf("\n");
3189*b2ed49a5SDavid van Moolenbroek                 printf("(3) "); MAGIC_FUNCTION_PRINT(cfunction, 0); printf("\n");
3190*b2ed49a5SDavid van Moolenbroek                 return EGENERIC;
3191*b2ed49a5SDavid van Moolenbroek             }
3192*b2ed49a5SDavid van Moolenbroek         }
3193*b2ed49a5SDavid van Moolenbroek #endif
3194*b2ed49a5SDavid van Moolenbroek 
3195*b2ed49a5SDavid van Moolenbroek #if ST_DEBUG_LEVEL > 0
3196*b2ed49a5SDavid van Moolenbroek         if (local_function && cached_function->address != local_function->address) {
3197*b2ed49a5SDavid van Moolenbroek             num_relocated++;
3198*b2ed49a5SDavid van Moolenbroek             if (ST_DEBUG_LEVEL > 1) {
3199*b2ed49a5SDavid van Moolenbroek                 printf("- relocated function: '%s'\n", cached_magic_vars->functions[i].name);
3200*b2ed49a5SDavid van Moolenbroek             }
3201*b2ed49a5SDavid van Moolenbroek         }
3202*b2ed49a5SDavid van Moolenbroek #endif
3203*b2ed49a5SDavid van Moolenbroek     }
3204*b2ed49a5SDavid van Moolenbroek 
3205*b2ed49a5SDavid van Moolenbroek #if ST_DEBUG_LEVEL > 0
3206*b2ed49a5SDavid van Moolenbroek     printf("total remote functions: %d. relocated: %d\n", cached_magic_vars->functions_num, num_relocated);
3207*b2ed49a5SDavid van Moolenbroek #endif
3208*b2ed49a5SDavid van Moolenbroek 
3209*b2ed49a5SDavid van Moolenbroek     return OK;
3210*b2ed49a5SDavid van Moolenbroek }
3211*b2ed49a5SDavid van Moolenbroek 
pair_metadata_sentries(st_init_info_t * info,struct _magic_vars_t * cached_magic_vars,st_counterparts_t * counterparts)3212*b2ed49a5SDavid van Moolenbroek PRIVATE int pair_metadata_sentries(st_init_info_t *info,
3213*b2ed49a5SDavid van Moolenbroek     struct _magic_vars_t *cached_magic_vars, st_counterparts_t *counterparts)
3214*b2ed49a5SDavid van Moolenbroek {
3215*b2ed49a5SDavid van Moolenbroek     int i, r;
3216*b2ed49a5SDavid van Moolenbroek     struct _magic_sentry *cached_sentry, *local_sentry;
3217*b2ed49a5SDavid van Moolenbroek #if ST_DEBUG_LEVEL > 0
3218*b2ed49a5SDavid van Moolenbroek     int num_relocated_str = 0, num_relocated_normal = 0;
3219*b2ed49a5SDavid van Moolenbroek #endif
3220*b2ed49a5SDavid van Moolenbroek 
3221*b2ed49a5SDavid van Moolenbroek     /* pair sentries remote->local */
3222*b2ed49a5SDavid van Moolenbroek     for (i = 0 ; i < cached_magic_vars->sentries_num ; i++) {
3223*b2ed49a5SDavid van Moolenbroek         void *local_data_addr = NULL;
3224*b2ed49a5SDavid van Moolenbroek         cached_sentry = &cached_magic_vars->sentries[i];
3225*b2ed49a5SDavid van Moolenbroek 
3226*b2ed49a5SDavid van Moolenbroek         /* String data is transferred directly. */
3227*b2ed49a5SDavid van Moolenbroek         if (MAGIC_SENTRY_IS_STRING(cached_sentry)) {
3228*b2ed49a5SDavid van Moolenbroek             char *string = st_buff_allocate(info, cached_sentry->type->size);
3229*b2ed49a5SDavid van Moolenbroek             if (!string) {
3230*b2ed49a5SDavid van Moolenbroek                 printf("ERROR allocating string.\n");
3231*b2ed49a5SDavid van Moolenbroek                 return EGENERIC;
3232*b2ed49a5SDavid van Moolenbroek             }
3233*b2ed49a5SDavid van Moolenbroek             r = st_cbs_os.copy_state_region(info->info_opaque, (uint32_t) cached_sentry->address,
3234*b2ed49a5SDavid van Moolenbroek                  cached_sentry->type->size, (uint32_t) string);
3235*b2ed49a5SDavid van Moolenbroek             if(r != OK) {
3236*b2ed49a5SDavid van Moolenbroek                 printf("ERROR transferring string.\n");
3237*b2ed49a5SDavid van Moolenbroek                 return EGENERIC;
3238*b2ed49a5SDavid van Moolenbroek             }
3239*b2ed49a5SDavid van Moolenbroek             local_data_addr = string;
3240*b2ed49a5SDavid van Moolenbroek         }
3241*b2ed49a5SDavid van Moolenbroek         ST_SET_CACHED_COUNTERPART(cached_sentry, sentries, sentries_data, local_data_addr);
3242*b2ed49a5SDavid van Moolenbroek 
3243*b2ed49a5SDavid van Moolenbroek         local_sentry = NULL;
3244*b2ed49a5SDavid van Moolenbroek         st_map_sentries(&cached_sentry, &local_sentry);
3245*b2ed49a5SDavid van Moolenbroek         ST_SET_CACHED_COUNTERPART(cached_sentry, sentries, sentries, local_sentry);
3246*b2ed49a5SDavid van Moolenbroek 
3247*b2ed49a5SDavid van Moolenbroek #if CHECK_SENTITY_PAIRS
3248*b2ed49a5SDavid van Moolenbroek         if (local_sentry && !MAGIC_SENTRY_IS_STRING(cached_sentry)) {
3249*b2ed49a5SDavid van Moolenbroek             /* debug: see if the non-string sentry is paired more than once */
3250*b2ed49a5SDavid van Moolenbroek             struct _magic_sentry *csentry = NULL;
3251*b2ed49a5SDavid van Moolenbroek             st_map_sentries(&csentry, &local_sentry);
3252*b2ed49a5SDavid van Moolenbroek             if (csentry != cached_sentry) {
3253*b2ed49a5SDavid van Moolenbroek                 printf("sentry pairing failed for (1) local sentry linked to multiple remote sentries (2), (3)\n");
3254*b2ed49a5SDavid van Moolenbroek                 printf("(1) "); MAGIC_SENTRY_PRINT(local_sentry, 0); printf("\n");
3255*b2ed49a5SDavid van Moolenbroek                 printf("(2) "); MAGIC_SENTRY_PRINT(cached_sentry, 0); printf("\n");
3256*b2ed49a5SDavid van Moolenbroek                 printf("(3) "); MAGIC_SENTRY_PRINT(csentry, 0); printf("\n");
3257*b2ed49a5SDavid van Moolenbroek                 return EGENERIC;
3258*b2ed49a5SDavid van Moolenbroek             }
3259*b2ed49a5SDavid van Moolenbroek         }
3260*b2ed49a5SDavid van Moolenbroek #endif
3261*b2ed49a5SDavid van Moolenbroek 
3262*b2ed49a5SDavid van Moolenbroek #if ST_DEBUG_LEVEL > 0
3263*b2ed49a5SDavid van Moolenbroek         if (local_sentry && cached_sentry->address != local_sentry->address) {
3264*b2ed49a5SDavid van Moolenbroek             if (MAGIC_SENTRY_IS_STRING(cached_sentry)) {
3265*b2ed49a5SDavid van Moolenbroek                 num_relocated_str++;
3266*b2ed49a5SDavid van Moolenbroek             }
3267*b2ed49a5SDavid van Moolenbroek             else {
3268*b2ed49a5SDavid van Moolenbroek                 num_relocated_normal++;
3269*b2ed49a5SDavid van Moolenbroek                 if (ST_DEBUG_LEVEL > 1) {
3270*b2ed49a5SDavid van Moolenbroek                     printf("- relocated non-string sentry: '%s'\n", cached_sentry->name);
3271*b2ed49a5SDavid van Moolenbroek                 }
3272*b2ed49a5SDavid van Moolenbroek             }
3273*b2ed49a5SDavid van Moolenbroek         }
3274*b2ed49a5SDavid van Moolenbroek #endif
3275*b2ed49a5SDavid van Moolenbroek     }
3276*b2ed49a5SDavid van Moolenbroek 
3277*b2ed49a5SDavid van Moolenbroek #if ST_DEBUG_LEVEL > 0
3278*b2ed49a5SDavid van Moolenbroek     printf("total remote sentries: %d. relocated normal: %d relocated string: %d\n", cached_magic_vars->sentries_num, num_relocated_normal, num_relocated_str);
3279*b2ed49a5SDavid van Moolenbroek #endif
3280*b2ed49a5SDavid van Moolenbroek 
3281*b2ed49a5SDavid van Moolenbroek     return OK;
3282*b2ed49a5SDavid van Moolenbroek }
3283*b2ed49a5SDavid van Moolenbroek 
3284*b2ed49a5SDavid van Moolenbroek #if ST_ASSUME_RAW_COPY_BEFORE_TRANSFER
allocate_pair_metadata_dsentries_from_raw_copy(st_init_info_t * info,struct _magic_vars_t * cached_magic_vars,st_counterparts_t * counterparts)3285*b2ed49a5SDavid van Moolenbroek PRIVATE int allocate_pair_metadata_dsentries_from_raw_copy(st_init_info_t *info,
3286*b2ed49a5SDavid van Moolenbroek     struct _magic_vars_t *cached_magic_vars, st_counterparts_t *counterparts)
3287*b2ed49a5SDavid van Moolenbroek {
3288*b2ed49a5SDavid van Moolenbroek     struct _magic_dsentry *dsentry;
3289*b2ed49a5SDavid van Moolenbroek     int remote_dsentries = 0, unpaired_dsentries = 0;
3290*b2ed49a5SDavid van Moolenbroek 
3291*b2ed49a5SDavid van Moolenbroek #if ST_DEBUG_LEVEL > 3
3292*b2ed49a5SDavid van Moolenbroek     EXEC_WITH_MAGIC_VARS(
3293*b2ed49a5SDavid van Moolenbroek         magic_print_dsentries();
3294*b2ed49a5SDavid van Moolenbroek         , &st_cached_magic_vars
3295*b2ed49a5SDavid van Moolenbroek     );
3296*b2ed49a5SDavid van Moolenbroek     magic_print_dsentries();
3297*b2ed49a5SDavid van Moolenbroek #endif
3298*b2ed49a5SDavid van Moolenbroek 
3299*b2ed49a5SDavid van Moolenbroek     dsentry = cached_magic_vars->first_dsentry;
3300*b2ed49a5SDavid van Moolenbroek     while (dsentry != NULL) {
3301*b2ed49a5SDavid van Moolenbroek         struct _magic_sentry *local_sentry = NULL, *sentry = MAGIC_DSENTRY_TO_SENTRY(dsentry);
3302*b2ed49a5SDavid van Moolenbroek 
3303*b2ed49a5SDavid van Moolenbroek         /* Initialize counterpart to NULL. */
3304*b2ed49a5SDavid van Moolenbroek         ST_SET_CACHED_COUNTERPART(sentry, sentries, sentries, NULL);
3305*b2ed49a5SDavid van Moolenbroek 
3306*b2ed49a5SDavid van Moolenbroek         remote_dsentries++;
3307*b2ed49a5SDavid van Moolenbroek 
3308*b2ed49a5SDavid van Moolenbroek         if (!MAGIC_STATE_FLAG(sentry, MAGIC_STATE_STACK) && !MAGIC_STATE_FLAG(sentry, MAGIC_STATE_LIB)) {
3309*b2ed49a5SDavid van Moolenbroek             local_sentry = MAGIC_DSENTRY_TO_SENTRY((struct _magic_dsentry *)MAGIC_PTR_FROM_DATA(sentry->address));
3310*b2ed49a5SDavid van Moolenbroek         } else {
3311*b2ed49a5SDavid van Moolenbroek #if MAGIC_LOOKUP_SENTRY_ALLOW_RANGE_INDEX
3312*b2ed49a5SDavid van Moolenbroek             EXEC_WITH_MAGIC_VARS(
3313*b2ed49a5SDavid van Moolenbroek                 local_sentry = magic_sentry_lookup_by_range(sentry->address, NULL);
3314*b2ed49a5SDavid van Moolenbroek                 , &st_cached_magic_vars
3315*b2ed49a5SDavid van Moolenbroek             );
3316*b2ed49a5SDavid van Moolenbroek #else
3317*b2ed49a5SDavid van Moolenbroek             local_sentry = magic_sentry_lookup_by_addr(sentry->address, NULL);
3318*b2ed49a5SDavid van Moolenbroek #endif
3319*b2ed49a5SDavid van Moolenbroek         }
3320*b2ed49a5SDavid van Moolenbroek 
3321*b2ed49a5SDavid van Moolenbroek         if (!local_sentry) {
3322*b2ed49a5SDavid van Moolenbroek              unpaired_dsentries++;
3323*b2ed49a5SDavid van Moolenbroek #if ST_DEBUG_LEVEL > 2
3324*b2ed49a5SDavid van Moolenbroek              printf("allocate_pair_metadata_dsentries_from_raw_copy: found unpaired "); MAGIC_DSENTRY_PRINT(dsentry, MAGIC_EXPAND_TYPE_STR); _magic_printf("\n");
3325*b2ed49a5SDavid van Moolenbroek #endif
3326*b2ed49a5SDavid van Moolenbroek         }
3327*b2ed49a5SDavid van Moolenbroek         ST_SET_CACHED_COUNTERPART(sentry, sentries, sentries, local_sentry);
3328*b2ed49a5SDavid van Moolenbroek         dsentry = dsentry->next;
3329*b2ed49a5SDavid van Moolenbroek     }
3330*b2ed49a5SDavid van Moolenbroek 
3331*b2ed49a5SDavid van Moolenbroek #if ST_DEBUG_LEVEL > 0
3332*b2ed49a5SDavid van Moolenbroek     printf("total remote dsentries: %d (%d unpaired)\n", remote_dsentries, unpaired_dsentries);
3333*b2ed49a5SDavid van Moolenbroek #endif
3334*b2ed49a5SDavid van Moolenbroek 
3335*b2ed49a5SDavid van Moolenbroek     return OK;
3336*b2ed49a5SDavid van Moolenbroek }
3337*b2ed49a5SDavid van Moolenbroek 
3338*b2ed49a5SDavid van Moolenbroek #else
3339*b2ed49a5SDavid van Moolenbroek 
allocate_pair_metadata_dsentries(st_init_info_t * info,struct _magic_vars_t * cached_magic_vars,st_counterparts_t * counterparts)3340*b2ed49a5SDavid van Moolenbroek PRIVATE int allocate_pair_metadata_dsentries(st_init_info_t *info,
3341*b2ed49a5SDavid van Moolenbroek     struct _magic_vars_t *cached_magic_vars, st_counterparts_t *counterparts)
3342*b2ed49a5SDavid van Moolenbroek {
3343*b2ed49a5SDavid van Moolenbroek     struct _magic_dsentry *dsentry = cached_magic_vars->first_dsentry, *local_dsentry;
3344*b2ed49a5SDavid van Moolenbroek     int remote_dsentries = 0;
3345*b2ed49a5SDavid van Moolenbroek #ifndef __MINIX
3346*b2ed49a5SDavid van Moolenbroek     int *local_sentry_paired_by_id = st_buff_allocate(info, (_magic_sentries_next_id + 1) * sizeof(int));
3347*b2ed49a5SDavid van Moolenbroek #endif
3348*b2ed49a5SDavid van Moolenbroek 
3349*b2ed49a5SDavid van Moolenbroek #if ST_DEBUG_LEVEL > 3
3350*b2ed49a5SDavid van Moolenbroek     EXEC_WITH_MAGIC_VARS(
3351*b2ed49a5SDavid van Moolenbroek         magic_print_dsentries();
3352*b2ed49a5SDavid van Moolenbroek         , &st_cached_magic_vars
3353*b2ed49a5SDavid van Moolenbroek     );
3354*b2ed49a5SDavid van Moolenbroek     magic_print_dsentries();
3355*b2ed49a5SDavid van Moolenbroek #endif
3356*b2ed49a5SDavid van Moolenbroek 
3357*b2ed49a5SDavid van Moolenbroek #ifdef __MINIX
3358*b2ed49a5SDavid van Moolenbroek     /*
3359*b2ed49a5SDavid van Moolenbroek      * Since on MINIX the mmaped regions are inherited in the new process,
3360*b2ed49a5SDavid van Moolenbroek      * we must first deallocate them. This is not the case on Linux.
3361*b2ed49a5SDavid van Moolenbroek      */
3362*b2ed49a5SDavid van Moolenbroek     while (dsentry != NULL) {
3363*b2ed49a5SDavid van Moolenbroek         int res = 0;
3364*b2ed49a5SDavid van Moolenbroek         struct _magic_sentry *sentry = MAGIC_DSENTRY_TO_SENTRY(dsentry);
3365*b2ed49a5SDavid van Moolenbroek         int size = sentry->type->size;
3366*b2ed49a5SDavid van Moolenbroek         /* For mmap first unmap the old region that is already mapped into this new instance */
3367*b2ed49a5SDavid van Moolenbroek         if (!MAGIC_STATE_FLAG(sentry, MAGIC_STATE_OUT_OF_BAND)
3368*b2ed49a5SDavid van Moolenbroek                 && MAGIC_STATE_REGION(sentry) == MAGIC_STATE_MAP
3369*b2ed49a5SDavid van Moolenbroek                 && !USE_PRE_ALLOCATED_BUFFER(info)
3370*b2ed49a5SDavid van Moolenbroek            )
3371*b2ed49a5SDavid van Moolenbroek             {
3372*b2ed49a5SDavid van Moolenbroek             /*
3373*b2ed49a5SDavid van Moolenbroek              * The 'ext' field in the dsentry is used here to record
3374*b2ed49a5SDavid van Moolenbroek              * the padding for ASR.
3375*b2ed49a5SDavid van Moolenbroek              */
3376*b2ed49a5SDavid van Moolenbroek             size_t padding = (size_t) dsentry->ext;
3377*b2ed49a5SDavid van Moolenbroek             /*
3378*b2ed49a5SDavid van Moolenbroek              * call munmap(). ptr and size have to be altered,
3379*b2ed49a5SDavid van Moolenbroek              * in order to free the preceding page, containing the dsentry struct, too.
3380*b2ed49a5SDavid van Moolenbroek              */
3381*b2ed49a5SDavid van Moolenbroek             MAGIC_MEM_WRAPPER_BLOCK(
3382*b2ed49a5SDavid van Moolenbroek                 res = munmap((char *)sentry->address - magic_get_sys_pagesize(), size + magic_get_sys_pagesize() + padding);
3383*b2ed49a5SDavid van Moolenbroek             );
3384*b2ed49a5SDavid van Moolenbroek             if (res != 0) {
3385*b2ed49a5SDavid van Moolenbroek                 printf("ERROR, munmap returned NULL.\n");
3386*b2ed49a5SDavid van Moolenbroek                 return EGENERIC;
3387*b2ed49a5SDavid van Moolenbroek             }
3388*b2ed49a5SDavid van Moolenbroek         }
3389*b2ed49a5SDavid van Moolenbroek         dsentry = dsentry->next;
3390*b2ed49a5SDavid van Moolenbroek     }
3391*b2ed49a5SDavid van Moolenbroek #endif
3392*b2ed49a5SDavid van Moolenbroek 
3393*b2ed49a5SDavid van Moolenbroek     /* Permute dsentries in case of ASR. */
3394*b2ed49a5SDavid van Moolenbroek     if (info->flags & ST_LU_ASR) {
3395*b2ed49a5SDavid van Moolenbroek         magic_asr_permute_dsentries(&cached_magic_vars->first_dsentry);
3396*b2ed49a5SDavid van Moolenbroek     }
3397*b2ed49a5SDavid van Moolenbroek 
3398*b2ed49a5SDavid van Moolenbroek     dsentry = cached_magic_vars->first_dsentry;
3399*b2ed49a5SDavid van Moolenbroek     while (dsentry != NULL) {
3400*b2ed49a5SDavid van Moolenbroek         struct _magic_sentry *local_sentry, *sentry = MAGIC_DSENTRY_TO_SENTRY(dsentry);
3401*b2ed49a5SDavid van Moolenbroek         int is_alloc_dsentry = MAGIC_SENTRY_IS_ALLOC(sentry);
3402*b2ed49a5SDavid van Moolenbroek         int res = 0;
3403*b2ed49a5SDavid van Moolenbroek         struct _magic_dsindex *local_dsindex;
3404*b2ed49a5SDavid van Moolenbroek 
3405*b2ed49a5SDavid van Moolenbroek         remote_dsentries++;
3406*b2ed49a5SDavid van Moolenbroek 
3407*b2ed49a5SDavid van Moolenbroek #ifdef __MINIX
3408*b2ed49a5SDavid van Moolenbroek         /* Cannot deal with dead dsentries. */
3409*b2ed49a5SDavid van Moolenbroek         assert(dsentry->magic_state == MAGIC_DSENTRY_MSTATE_ALIVE);
3410*b2ed49a5SDavid van Moolenbroek #else
3411*b2ed49a5SDavid van Moolenbroek         /*
3412*b2ed49a5SDavid van Moolenbroek          * If there are dead dsentries, we simply skip them.
3413*b2ed49a5SDavid van Moolenbroek          */
3414*b2ed49a5SDavid van Moolenbroek         if (dsentry->magic_state != MAGIC_DSENTRY_MSTATE_ALIVE) {
3415*b2ed49a5SDavid van Moolenbroek             dsentry = dsentry->next;
3416*b2ed49a5SDavid van Moolenbroek             continue;
3417*b2ed49a5SDavid van Moolenbroek         }
3418*b2ed49a5SDavid van Moolenbroek #endif
3419*b2ed49a5SDavid van Moolenbroek 
3420*b2ed49a5SDavid van Moolenbroek         /* Initialize counterpart to NULL. */
3421*b2ed49a5SDavid van Moolenbroek         ST_SET_CACHED_COUNTERPART(sentry, sentries, sentries, NULL);
3422*b2ed49a5SDavid van Moolenbroek 
3423*b2ed49a5SDavid van Moolenbroek         /* Handle non-alloc dsentries first. */
3424*b2ed49a5SDavid van Moolenbroek         if (!is_alloc_dsentry) {
3425*b2ed49a5SDavid van Moolenbroek             local_sentry = magic_sentry_lookup_by_name(dsentry->parent_name,
3426*b2ed49a5SDavid van Moolenbroek                 sentry->name, dsentry->site_id, NULL);
3427*b2ed49a5SDavid van Moolenbroek             if (local_sentry) {
3428*b2ed49a5SDavid van Moolenbroek                 assert(!MAGIC_SENTRY_IS_ALLOC(local_sentry));
3429*b2ed49a5SDavid van Moolenbroek                 ST_SET_CACHED_COUNTERPART(sentry, sentries, sentries, local_sentry);
3430*b2ed49a5SDavid van Moolenbroek             }
3431*b2ed49a5SDavid van Moolenbroek 
3432*b2ed49a5SDavid van Moolenbroek             dsentry = dsentry->next;
3433*b2ed49a5SDavid van Moolenbroek             continue;
3434*b2ed49a5SDavid van Moolenbroek         }
3435*b2ed49a5SDavid van Moolenbroek 
3436*b2ed49a5SDavid van Moolenbroek         /* Out-of-band alloc dsentries next. */
3437*b2ed49a5SDavid van Moolenbroek         if (MAGIC_STATE_FLAG(sentry, MAGIC_STATE_OUT_OF_BAND)) {
3438*b2ed49a5SDavid van Moolenbroek             struct _magic_type *type;
3439*b2ed49a5SDavid van Moolenbroek             /* We can only handle obdsentries with the magic void type, transferred as-is. */
3440*b2ed49a5SDavid van Moolenbroek             if (sentry->type != &dsentry->type) {
3441*b2ed49a5SDavid van Moolenbroek                 /* Not an array type */
3442*b2ed49a5SDavid van Moolenbroek                 type = sentry->type;
3443*b2ed49a5SDavid van Moolenbroek             } else {
3444*b2ed49a5SDavid van Moolenbroek                 /* This is an array type, use its contained type instead. */
3445*b2ed49a5SDavid van Moolenbroek                 type = sentry->type->contained_types[0];
3446*b2ed49a5SDavid van Moolenbroek             }
3447*b2ed49a5SDavid van Moolenbroek             /* We now have the cached version of the type. Compare it to magic void type */
3448*b2ed49a5SDavid van Moolenbroek             if (!magic_type_compatible(type, MAGIC_VOID_TYPE, MAGIC_TYPE_COMPARE_ALL)) {
3449*b2ed49a5SDavid van Moolenbroek                 printf("Can't handle obdsentry with non-void type\n");
3450*b2ed49a5SDavid van Moolenbroek                 return EGENERIC;
3451*b2ed49a5SDavid van Moolenbroek             }
3452*b2ed49a5SDavid van Moolenbroek #ifdef __MINIX
3453*b2ed49a5SDavid van Moolenbroek             /* On MINIX we need to recreate all the obdsentries. */
3454*b2ed49a5SDavid van Moolenbroek             struct _magic_obdsentry *obdsentry;
3455*b2ed49a5SDavid van Moolenbroek             int size = sentry->type->size;
3456*b2ed49a5SDavid van Moolenbroek             obdsentry = magic_create_obdsentry(sentry->address,
3457*b2ed49a5SDavid van Moolenbroek                 MAGIC_VOID_TYPE, size, MAGIC_STATE_REGION(sentry), sentry->name, dsentry->parent_name);
3458*b2ed49a5SDavid van Moolenbroek             if (obdsentry == NULL) {
3459*b2ed49a5SDavid van Moolenbroek                 printf("ERROR, magic_create_obdsentry returned NULL.\n");
3460*b2ed49a5SDavid van Moolenbroek                 return EGENERIC;
3461*b2ed49a5SDavid van Moolenbroek             }
3462*b2ed49a5SDavid van Moolenbroek             local_dsentry = MAGIC_OBDSENTRY_TO_DSENTRY(obdsentry);
3463*b2ed49a5SDavid van Moolenbroek #else
3464*b2ed49a5SDavid van Moolenbroek             /* On Linux we only need to pair them. */
3465*b2ed49a5SDavid van Moolenbroek             local_sentry = magic_sentry_lookup_by_name(
3466*b2ed49a5SDavid van Moolenbroek                 MAGIC_SENTRY_PARENT(sentry), sentry->name,
3467*b2ed49a5SDavid van Moolenbroek                 MAGIC_SENTRY_SITE_ID(sentry), NULL);
3468*b2ed49a5SDavid van Moolenbroek             if (local_sentry == NULL) {
3469*b2ed49a5SDavid van Moolenbroek                 printf("Unable to pair obdsentry.\n");
3470*b2ed49a5SDavid van Moolenbroek                 return EGENERIC;
3471*b2ed49a5SDavid van Moolenbroek             }
3472*b2ed49a5SDavid van Moolenbroek             local_dsentry = MAGIC_DSENTRY_FROM_SENTRY(local_sentry);
3473*b2ed49a5SDavid van Moolenbroek #endif
3474*b2ed49a5SDavid van Moolenbroek             ST_SET_CACHED_COUNTERPART(sentry, sentries, sentries, MAGIC_DSENTRY_TO_SENTRY(local_dsentry));
3475*b2ed49a5SDavid van Moolenbroek             dsentry = dsentry->next;
3476*b2ed49a5SDavid van Moolenbroek             continue;
3477*b2ed49a5SDavid van Moolenbroek         }
3478*b2ed49a5SDavid van Moolenbroek 
3479*b2ed49a5SDavid van Moolenbroek         /* Handle regular alloc dsentries last. */
3480*b2ed49a5SDavid van Moolenbroek #ifndef __MINIX
3481*b2ed49a5SDavid van Moolenbroek         /*
3482*b2ed49a5SDavid van Moolenbroek          * For Linux, first pair INIT time remote
3483*b2ed49a5SDavid van Moolenbroek          * dsentries with local dsentries.
3484*b2ed49a5SDavid van Moolenbroek          */
3485*b2ed49a5SDavid van Moolenbroek 
3486*b2ed49a5SDavid van Moolenbroek         if (MAGIC_STATE_FLAG(sentry, MAGIC_STATE_INIT)) {
3487*b2ed49a5SDavid van Moolenbroek             local_sentry = NULL;
3488*b2ed49a5SDavid van Moolenbroek 
3489*b2ed49a5SDavid van Moolenbroek             if (MAGIC_STATE_FLAG(sentry, MAGIC_STATE_IMMUTABLE)) {
3490*b2ed49a5SDavid van Moolenbroek                 /*
3491*b2ed49a5SDavid van Moolenbroek                  * Immutable init time dsentries should have already been
3492*b2ed49a5SDavid van Moolenbroek                  * preallocated, so just pair them by address.
3493*b2ed49a5SDavid van Moolenbroek                  */
3494*b2ed49a5SDavid van Moolenbroek                 local_sentry = magic_sentry_lookup_by_addr(sentry->address, NULL);
3495*b2ed49a5SDavid van Moolenbroek             } else {
3496*b2ed49a5SDavid van Moolenbroek #if MAGIC_LOOKUP_SENTRY_ALLOW_NAME_HASH
3497*b2ed49a5SDavid van Moolenbroek                 struct _magic_sentry_list *local_sentry_list;
3498*b2ed49a5SDavid van Moolenbroek                 local_sentry_list = magic_sentry_list_lookup_by_name_hash(
3499*b2ed49a5SDavid van Moolenbroek                     dsentry->parent_name, sentry->name, dsentry->site_id, NULL);
3500*b2ed49a5SDavid van Moolenbroek 
3501*b2ed49a5SDavid van Moolenbroek                 while (local_sentry_list) {
3502*b2ed49a5SDavid van Moolenbroek                     if (!local_sentry_paired_by_id[local_sentry_list->sentry->id]) {
3503*b2ed49a5SDavid van Moolenbroek                         local_sentry = local_sentry_list->sentry;
3504*b2ed49a5SDavid van Moolenbroek                         break;
3505*b2ed49a5SDavid van Moolenbroek                     }
3506*b2ed49a5SDavid van Moolenbroek                     local_sentry_list = local_sentry_list->next;
3507*b2ed49a5SDavid van Moolenbroek                 }
3508*b2ed49a5SDavid van Moolenbroek 
3509*b2ed49a5SDavid van Moolenbroek #else
3510*b2ed49a5SDavid van Moolenbroek                 do {
3511*b2ed49a5SDavid van Moolenbroek                     struct _magic_dsentry *prev_dsentry, *tmp_dsentry;
3512*b2ed49a5SDavid van Moolenbroek                     struct _magic_sentry *tmp_sentry;
3513*b2ed49a5SDavid van Moolenbroek                     MAGIC_DSENTRY_LOCK();
3514*b2ed49a5SDavid van Moolenbroek                     MAGIC_DSENTRY_ALIVE_ITER(_magic_first_dsentry, prev_dsentry,
3515*b2ed49a5SDavid van Moolenbroek                         tmp_dsentry, tmp_sentry,
3516*b2ed49a5SDavid van Moolenbroek                         if (!strcmp(tmp_sentry->name, sentry->name)) {
3517*b2ed49a5SDavid van Moolenbroek                             if (!dsentry->parent_name ||
3518*b2ed49a5SDavid van Moolenbroek                                     !strcmp(MAGIC_SENTRY_PARENT(tmp_sentry), dsentry->parent_name)) {
3519*b2ed49a5SDavid van Moolenbroek                                 if (dsentry->site_id == MAGIC_DSENTRY_SITE_ID_NULL ||
3520*b2ed49a5SDavid van Moolenbroek                                         tmp_dsentry->site_id == dsentry->site_id) {
3521*b2ed49a5SDavid van Moolenbroek                                     if (!local_sentry_paired_by_id[tmp_sentry->id]) {
3522*b2ed49a5SDavid van Moolenbroek                                         local_sentry = tmp_sentry;
3523*b2ed49a5SDavid van Moolenbroek                                         break;
3524*b2ed49a5SDavid van Moolenbroek                                     }
3525*b2ed49a5SDavid van Moolenbroek                                 }
3526*b2ed49a5SDavid van Moolenbroek                             }
3527*b2ed49a5SDavid van Moolenbroek                         }
3528*b2ed49a5SDavid van Moolenbroek                     );
3529*b2ed49a5SDavid van Moolenbroek                     MAGIC_DSENTRY_UNLOCK();
3530*b2ed49a5SDavid van Moolenbroek                 } while (0);
3531*b2ed49a5SDavid van Moolenbroek #endif
3532*b2ed49a5SDavid van Moolenbroek             }
3533*b2ed49a5SDavid van Moolenbroek             if (local_sentry) {
3534*b2ed49a5SDavid van Moolenbroek                 ST_SET_CACHED_COUNTERPART(sentry, sentries, sentries, local_sentry);
3535*b2ed49a5SDavid van Moolenbroek                 local_sentry_paired_by_id[local_sentry->id] = 1;
3536*b2ed49a5SDavid van Moolenbroek                 dsentry = dsentry->next;
3537*b2ed49a5SDavid van Moolenbroek                 continue;
3538*b2ed49a5SDavid van Moolenbroek             }
3539*b2ed49a5SDavid van Moolenbroek         }
3540*b2ed49a5SDavid van Moolenbroek #endif
3541*b2ed49a5SDavid van Moolenbroek 
3542*b2ed49a5SDavid van Moolenbroek         /*
3543*b2ed49a5SDavid van Moolenbroek          * Just recreate all the other dsentries. Immutable objects will
3544*b2ed49a5SDavid van Moolenbroek          * have already been inherited and allocate_local_dsentry() will
3545*b2ed49a5SDavid van Moolenbroek          * not reallocate them, but instead it will just create a new
3546*b2ed49a5SDavid van Moolenbroek          * local dsentry in the right place.
3547*b2ed49a5SDavid van Moolenbroek          */
3548*b2ed49a5SDavid van Moolenbroek         local_dsindex = magic_dsindex_lookup_by_name(dsentry->parent_name, sentry->name);
3549*b2ed49a5SDavid van Moolenbroek         if (local_dsindex || MAGIC_SENTRY_IS_LIB_ALLOC(sentry)) {
3550*b2ed49a5SDavid van Moolenbroek 
3551*b2ed49a5SDavid van Moolenbroek             /* Allocate a new local dsentry and pair it with the remote. */
3552*b2ed49a5SDavid van Moolenbroek             res = allocate_local_dsentry(info, local_dsindex, 0, 0, NULL, &local_dsentry, dsentry, NULL);
3553*b2ed49a5SDavid van Moolenbroek             if (res != ENOSYS) {
3554*b2ed49a5SDavid van Moolenbroek                 if (res != OK) {
3555*b2ed49a5SDavid van Moolenbroek                     return res;
3556*b2ed49a5SDavid van Moolenbroek                 }
3557*b2ed49a5SDavid van Moolenbroek                 assert(local_dsentry);
3558*b2ed49a5SDavid van Moolenbroek                 ST_SET_CACHED_COUNTERPART(sentry, sentries, sentries, MAGIC_DSENTRY_TO_SENTRY(local_dsentry));
3559*b2ed49a5SDavid van Moolenbroek             }
3560*b2ed49a5SDavid van Moolenbroek         }
3561*b2ed49a5SDavid van Moolenbroek         dsentry = dsentry->next;
3562*b2ed49a5SDavid van Moolenbroek     }
3563*b2ed49a5SDavid van Moolenbroek 
3564*b2ed49a5SDavid van Moolenbroek #if ST_DEBUG_LEVEL > 0
3565*b2ed49a5SDavid van Moolenbroek     printf("total remote dsentries: %d\n", remote_dsentries);
3566*b2ed49a5SDavid van Moolenbroek #endif
3567*b2ed49a5SDavid van Moolenbroek 
3568*b2ed49a5SDavid van Moolenbroek     return OK;
3569*b2ed49a5SDavid van Moolenbroek }
3570*b2ed49a5SDavid van Moolenbroek 
deallocate_nonxferred_dsentries(struct _magic_dsentry * first_dsentry,st_counterparts_t * counterparts)3571*b2ed49a5SDavid van Moolenbroek PRIVATE int deallocate_nonxferred_dsentries(struct _magic_dsentry *first_dsentry, st_counterparts_t *counterparts)
3572*b2ed49a5SDavid van Moolenbroek {
3573*b2ed49a5SDavid van Moolenbroek     struct _magic_dsentry *dsentry = first_dsentry;
3574*b2ed49a5SDavid van Moolenbroek     struct _magic_sentry *local_sentry;
3575*b2ed49a5SDavid van Moolenbroek 
3576*b2ed49a5SDavid van Moolenbroek     while (dsentry != NULL) {
3577*b2ed49a5SDavid van Moolenbroek         struct _magic_sentry *sentry = MAGIC_DSENTRY_TO_SENTRY(dsentry);
3578*b2ed49a5SDavid van Moolenbroek         int is_paired_dsentry = ST_HAS_CACHED_COUNTERPART(sentry, sentries);
3579*b2ed49a5SDavid van Moolenbroek         int is_alloc_dsentry = MAGIC_SENTRY_IS_ALLOC(sentry);
3580*b2ed49a5SDavid van Moolenbroek         ST_GET_CACHED_COUNTERPART(sentry, sentries, sentries, local_sentry);
3581*b2ed49a5SDavid van Moolenbroek 
3582*b2ed49a5SDavid van Moolenbroek         if (MAGIC_STATE_EXTF_GET(sentry, ST_TRANSFER_DONE) || !is_alloc_dsentry) {
3583*b2ed49a5SDavid van Moolenbroek             dsentry = dsentry->next;
3584*b2ed49a5SDavid van Moolenbroek             continue;
3585*b2ed49a5SDavid van Moolenbroek         }
3586*b2ed49a5SDavid van Moolenbroek 
3587*b2ed49a5SDavid van Moolenbroek         /* Report non-transferred alloc dsentries when requested. */
3588*b2ed49a5SDavid van Moolenbroek         if (is_paired_dsentry && (st_policies & ST_REPORT_NONXFERRED_ALLOCS)) {
3589*b2ed49a5SDavid van Moolenbroek             printf("deallocate_nonxferred_dsentries: Non-transferred dsentry found: ");
3590*b2ed49a5SDavid van Moolenbroek             MAGIC_DSENTRY_PRINT(dsentry, MAGIC_EXPAND_TYPE_STR);
3591*b2ed49a5SDavid van Moolenbroek             printf("\n");
3592*b2ed49a5SDavid van Moolenbroek         }
3593*b2ed49a5SDavid van Moolenbroek         if (!is_paired_dsentry && (st_policies & ST_REPORT_NONXFERRED_UNPAIRED_ALLOCS)) {
3594*b2ed49a5SDavid van Moolenbroek             printf("deallocate_nonxferred_dsentries: Non-transferred unpaired dsentry found: ");
3595*b2ed49a5SDavid van Moolenbroek             MAGIC_DSENTRY_PRINT(dsentry, MAGIC_EXPAND_TYPE_STR);
3596*b2ed49a5SDavid van Moolenbroek             printf("\n");
3597*b2ed49a5SDavid van Moolenbroek         }
3598*b2ed49a5SDavid van Moolenbroek 
3599*b2ed49a5SDavid van Moolenbroek         if (!is_paired_dsentry) {
3600*b2ed49a5SDavid van Moolenbroek             dsentry = dsentry->next;
3601*b2ed49a5SDavid van Moolenbroek             continue;
3602*b2ed49a5SDavid van Moolenbroek         }
3603*b2ed49a5SDavid van Moolenbroek         assert(local_sentry);
3604*b2ed49a5SDavid van Moolenbroek         if (MAGIC_SENTRY_IS_ALLOC(local_sentry)) {
3605*b2ed49a5SDavid van Moolenbroek             deallocate_local_dsentry(MAGIC_DSENTRY_FROM_SENTRY(local_sentry));
3606*b2ed49a5SDavid van Moolenbroek         }
3607*b2ed49a5SDavid van Moolenbroek         dsentry = dsentry->next;
3608*b2ed49a5SDavid van Moolenbroek     }
3609*b2ed49a5SDavid van Moolenbroek 
3610*b2ed49a5SDavid van Moolenbroek     return OK;
3611*b2ed49a5SDavid van Moolenbroek }
3612*b2ed49a5SDavid van Moolenbroek #endif
3613*b2ed49a5SDavid van Moolenbroek 
deallocate_local_dsentry(struct _magic_dsentry * local_dsentry)3614*b2ed49a5SDavid van Moolenbroek PRIVATE void deallocate_local_dsentry(struct _magic_dsentry *local_dsentry)
3615*b2ed49a5SDavid van Moolenbroek {
3616*b2ed49a5SDavid van Moolenbroek     int r, dsentry_type;
3617*b2ed49a5SDavid van Moolenbroek     struct _magic_sentry *local_sentry = MAGIC_DSENTRY_TO_SENTRY(local_dsentry);
3618*b2ed49a5SDavid van Moolenbroek 
3619*b2ed49a5SDavid van Moolenbroek     assert(MAGIC_SENTRY_IS_ALLOC(local_sentry));
3620*b2ed49a5SDavid van Moolenbroek     dsentry_type = MAGIC_STATE_FLAG(local_sentry, MAGIC_STATE_OUT_OF_BAND) ? MAGIC_STATE_OUT_OF_BAND : MAGIC_STATE_REGION(local_sentry);
3621*b2ed49a5SDavid van Moolenbroek     /* A MAP_SHARED region will have both MAGIC_STATE_MAP and MAGIC_STATE_SHM. */
3622*b2ed49a5SDavid van Moolenbroek     if (dsentry_type == (MAGIC_STATE_MAP | MAGIC_STATE_SHM))
3623*b2ed49a5SDavid van Moolenbroek         dsentry_type = MAGIC_STATE_MAP;
3624*b2ed49a5SDavid van Moolenbroek 
3625*b2ed49a5SDavid van Moolenbroek     MAGIC_MEM_WRAPPER_BEGIN();
3626*b2ed49a5SDavid van Moolenbroek     switch (dsentry_type) {
3627*b2ed49a5SDavid van Moolenbroek         case MAGIC_STATE_HEAP:
3628*b2ed49a5SDavid van Moolenbroek             /* free */
3629*b2ed49a5SDavid van Moolenbroek             magic_free(local_sentry->address);
3630*b2ed49a5SDavid van Moolenbroek             break;
3631*b2ed49a5SDavid van Moolenbroek 
3632*b2ed49a5SDavid van Moolenbroek         case MAGIC_STATE_MAP:
3633*b2ed49a5SDavid van Moolenbroek             /* munmap */
3634*b2ed49a5SDavid van Moolenbroek             r = magic_munmap(local_sentry->address, local_sentry->type->size);
3635*b2ed49a5SDavid van Moolenbroek             if (r != 0) {
3636*b2ed49a5SDavid van Moolenbroek                 printf("Warning: magic_munmap failed for ");
3637*b2ed49a5SDavid van Moolenbroek                 MAGIC_DSENTRY_PRINT(local_dsentry, 0);
3638*b2ed49a5SDavid van Moolenbroek                 printf("\n");
3639*b2ed49a5SDavid van Moolenbroek             }
3640*b2ed49a5SDavid van Moolenbroek             break;
3641*b2ed49a5SDavid van Moolenbroek 
3642*b2ed49a5SDavid van Moolenbroek #ifndef __MINIX
3643*b2ed49a5SDavid van Moolenbroek         case MAGIC_STATE_SHM:
3644*b2ed49a5SDavid van Moolenbroek             /* shmdt */
3645*b2ed49a5SDavid van Moolenbroek             r = magic_shmdt(local_sentry->address);
3646*b2ed49a5SDavid van Moolenbroek             if (r != 0) {
3647*b2ed49a5SDavid van Moolenbroek                 printf("Warning: magic_shmdt failed for ");
3648*b2ed49a5SDavid van Moolenbroek                 MAGIC_DSENTRY_PRINT(local_dsentry, 0);
3649*b2ed49a5SDavid van Moolenbroek                 printf("\n");
3650*b2ed49a5SDavid van Moolenbroek             }
3651*b2ed49a5SDavid van Moolenbroek             break;
3652*b2ed49a5SDavid van Moolenbroek #endif
3653*b2ed49a5SDavid van Moolenbroek 
3654*b2ed49a5SDavid van Moolenbroek         case MAGIC_STATE_OUT_OF_BAND:
3655*b2ed49a5SDavid van Moolenbroek             /* out-of-band dsentry. */
3656*b2ed49a5SDavid van Moolenbroek             r = magic_destroy_obdsentry_by_addr(local_sentry->address);
3657*b2ed49a5SDavid van Moolenbroek             if (r != 0) {
3658*b2ed49a5SDavid van Moolenbroek                 printf("Warning: magic_destroy_obdsentry_by_addr failed for ");
3659*b2ed49a5SDavid van Moolenbroek                 MAGIC_DSENTRY_PRINT(local_dsentry, 0);
3660*b2ed49a5SDavid van Moolenbroek                 printf("\n");
3661*b2ed49a5SDavid van Moolenbroek             }
3662*b2ed49a5SDavid van Moolenbroek             break;
3663*b2ed49a5SDavid van Moolenbroek 
3664*b2ed49a5SDavid van Moolenbroek         default:
3665*b2ed49a5SDavid van Moolenbroek             st_cbs_os.panic("ERROR. UNSUPPORTED DSENTRY TYPE: %d\n", dsentry_type);
3666*b2ed49a5SDavid van Moolenbroek     }
3667*b2ed49a5SDavid van Moolenbroek     MAGIC_MEM_WRAPPER_END();
3668*b2ed49a5SDavid van Moolenbroek }
3669*b2ed49a5SDavid van Moolenbroek 
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)3670*b2ed49a5SDavid van Moolenbroek 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)
3671*b2ed49a5SDavid van Moolenbroek {
3672*b2ed49a5SDavid van Moolenbroek     struct _magic_dsentry *local_dsentry = NULL;
3673*b2ed49a5SDavid van Moolenbroek     struct _magic_sentry *cached_sentry = NULL;
3674*b2ed49a5SDavid van Moolenbroek     const char *name, *parent_name;
3675*b2ed49a5SDavid van Moolenbroek     struct _magic_type *type;
3676*b2ed49a5SDavid van Moolenbroek     int region;
3677*b2ed49a5SDavid van Moolenbroek     size_t size;
3678*b2ed49a5SDavid van Moolenbroek     union __alloc_flags alloc_flags;
3679*b2ed49a5SDavid van Moolenbroek 
3680*b2ed49a5SDavid van Moolenbroek     /* Either a dsindex or a dsentry needs to be set. */
3681*b2ed49a5SDavid van Moolenbroek     assert(local_dsindex || cached_dsentry);
3682*b2ed49a5SDavid van Moolenbroek 
3683*b2ed49a5SDavid van Moolenbroek     if (cached_dsentry)
3684*b2ed49a5SDavid van Moolenbroek         cached_sentry = MAGIC_DSENTRY_TO_SENTRY(cached_dsentry);
3685*b2ed49a5SDavid van Moolenbroek 
3686*b2ed49a5SDavid van Moolenbroek     /* name, parent_name: local_dsindex || cached_dsentry. */
3687*b2ed49a5SDavid van Moolenbroek     if (local_dsindex) {
3688*b2ed49a5SDavid van Moolenbroek         assert(MAGIC_DSINDEX_IS_ALLOC(local_dsindex));
3689*b2ed49a5SDavid van Moolenbroek         name = local_dsindex->name;
3690*b2ed49a5SDavid van Moolenbroek         parent_name = local_dsindex->parent_name;
3691*b2ed49a5SDavid van Moolenbroek     } else {
3692*b2ed49a5SDavid van Moolenbroek         assert(MAGIC_SENTRY_IS_ALLOC(cached_sentry));
3693*b2ed49a5SDavid van Moolenbroek         /*
3694*b2ed49a5SDavid van Moolenbroek          * The external allocation parent_name needs to be readjusted.
3695*b2ed49a5SDavid van Moolenbroek          * The external allocation name is adjusted after the new dsentry
3696*b2ed49a5SDavid van Moolenbroek          * is created.
3697*b2ed49a5SDavid van Moolenbroek          */
3698*b2ed49a5SDavid van Moolenbroek         name = cached_sentry->name;
3699*b2ed49a5SDavid van Moolenbroek         if (!strcmp(cached_dsentry->parent_name, MAGIC_ALLOC_EXT_PARENT_NAME)) {
3700*b2ed49a5SDavid van Moolenbroek             parent_name = MAGIC_ALLOC_EXT_PARENT_NAME;
3701*b2ed49a5SDavid van Moolenbroek         } else {
3702*b2ed49a5SDavid van Moolenbroek             int found_parent_name = 0;
3703*b2ed49a5SDavid van Moolenbroek             struct _magic_sodesc *sodesc;
3704*b2ed49a5SDavid van Moolenbroek             struct _magic_dsodesc *dsodesc;
3705*b2ed49a5SDavid van Moolenbroek             MAGIC_DSODESC_LOCK();
3706*b2ed49a5SDavid van Moolenbroek             MAGIC_SODESC_ITER(_magic_first_sodesc, sodesc,
3707*b2ed49a5SDavid van Moolenbroek                 if (!strcmp(cached_dsentry->parent_name, sodesc->lib.name)) {
3708*b2ed49a5SDavid van Moolenbroek                     parent_name = (const char *)sodesc->lib.name;
3709*b2ed49a5SDavid van Moolenbroek                     found_parent_name = 1;
3710*b2ed49a5SDavid van Moolenbroek                     break;
3711*b2ed49a5SDavid van Moolenbroek                 }
3712*b2ed49a5SDavid van Moolenbroek             );
3713*b2ed49a5SDavid van Moolenbroek             if (!found_parent_name) {
3714*b2ed49a5SDavid van Moolenbroek                 MAGIC_DSODESC_ITER(_magic_first_dsodesc, dsodesc,
3715*b2ed49a5SDavid van Moolenbroek                     if (!strcmp(cached_dsentry->parent_name, dsodesc->lib.name)) {
3716*b2ed49a5SDavid van Moolenbroek                         parent_name = (const char *)dsodesc->lib.name;
3717*b2ed49a5SDavid van Moolenbroek                         found_parent_name = 1;
3718*b2ed49a5SDavid van Moolenbroek                         break;
3719*b2ed49a5SDavid van Moolenbroek                     }
3720*b2ed49a5SDavid van Moolenbroek                 );
3721*b2ed49a5SDavid van Moolenbroek             }
3722*b2ed49a5SDavid van Moolenbroek             MAGIC_DSODESC_UNLOCK();
3723*b2ed49a5SDavid van Moolenbroek             assert(found_parent_name && "Invalid parent name for cached dsentry!");
3724*b2ed49a5SDavid van Moolenbroek         }
3725*b2ed49a5SDavid van Moolenbroek     }
3726*b2ed49a5SDavid van Moolenbroek 
3727*b2ed49a5SDavid van Moolenbroek     /* num_elements: args || cached_sentry. */
3728*b2ed49a5SDavid van Moolenbroek     if (num_elements <= 0 && cached_sentry) {
3729*b2ed49a5SDavid van Moolenbroek         num_elements = cached_sentry->type->type_id == MAGIC_TYPE_ARRAY ?
3730*b2ed49a5SDavid van Moolenbroek             cached_sentry->type->num_child_types : 1;
3731*b2ed49a5SDavid van Moolenbroek     }
3732*b2ed49a5SDavid van Moolenbroek     assert(num_elements > 0);
3733*b2ed49a5SDavid van Moolenbroek 
3734*b2ed49a5SDavid van Moolenbroek     /* alloc_flags: args || cached_dsentry. */
3735*b2ed49a5SDavid van Moolenbroek     if (!p_alloc_flags) {
3736*b2ed49a5SDavid van Moolenbroek         if (cached_dsentry && MAGIC_SENTRY_IS_ALLOC(cached_sentry)) {
3737*b2ed49a5SDavid van Moolenbroek             alloc_flags = cached_dsentry->alloc_flags;
3738*b2ed49a5SDavid van Moolenbroek         }
3739*b2ed49a5SDavid van Moolenbroek     } else {
3740*b2ed49a5SDavid van Moolenbroek         alloc_flags = *p_alloc_flags;
3741*b2ed49a5SDavid van Moolenbroek     }
3742*b2ed49a5SDavid van Moolenbroek 
3743*b2ed49a5SDavid van Moolenbroek     /* is_type_mismatch: args || cached_dsentry. */
3744*b2ed49a5SDavid van Moolenbroek     if (!is_type_mismatch && cached_dsentry)
3745*b2ed49a5SDavid van Moolenbroek         is_type_mismatch = MAGIC_STATE_FLAG(cached_sentry, MAGIC_STATE_TYPE_SIZE_MISMATCH);
3746*b2ed49a5SDavid van Moolenbroek 
3747*b2ed49a5SDavid van Moolenbroek     /*
3748*b2ed49a5SDavid van Moolenbroek      * Use old address for immutable objects.
3749*b2ed49a5SDavid van Moolenbroek      */
3750*b2ed49a5SDavid van Moolenbroek     /* ptr: args || cached_sentry. */
3751*b2ed49a5SDavid van Moolenbroek     if (!ptr && cached_sentry &&
3752*b2ed49a5SDavid van Moolenbroek             MAGIC_STATE_FLAG(cached_sentry, MAGIC_STATE_IMMUTABLE))
3753*b2ed49a5SDavid van Moolenbroek         ptr = cached_sentry->address;
3754*b2ed49a5SDavid van Moolenbroek 
3755*b2ed49a5SDavid van Moolenbroek     /* region: local_dsindex || cached_sentry. */
3756*b2ed49a5SDavid van Moolenbroek     if (local_dsindex)
3757*b2ed49a5SDavid van Moolenbroek         region = MAGIC_STATE_REGION(local_dsindex);
3758*b2ed49a5SDavid van Moolenbroek     else
3759*b2ed49a5SDavid van Moolenbroek         region = MAGIC_STATE_REGION(cached_sentry);
3760*b2ed49a5SDavid van Moolenbroek 
3761*b2ed49a5SDavid van Moolenbroek     /* Check if the region is ambigous. This shouldn't happen. */
3762*b2ed49a5SDavid van Moolenbroek     assert(!((region & (MAGIC_STATE_HEAP | MAGIC_STATE_MAP)) ==
3763*b2ed49a5SDavid van Moolenbroek         (MAGIC_STATE_HEAP | MAGIC_STATE_MAP)) &&
3764*b2ed49a5SDavid van Moolenbroek         "MAGIC_STATE_HEAP | MAGIC_STATE_MAP detected!");
3765*b2ed49a5SDavid van Moolenbroek #if 0
3766*b2ed49a5SDavid van Moolenbroek     if ((region & (MAGIC_STATE_HEAP | MAGIC_STATE_MAP)) ==
3767*b2ed49a5SDavid van Moolenbroek         (MAGIC_STATE_HEAP | MAGIC_STATE_MAP)) {
3768*b2ed49a5SDavid van Moolenbroek         /* Check call flags to determine what to do in the ambiguous cases. */
3769*b2ed49a5SDavid van Moolenbroek         region = (alloc_flags.mmap_flags && alloc_flags.mmap_prot) ?
3770*b2ed49a5SDavid van Moolenbroek             MAGIC_STATE_MAP : MAGIC_STATE_HEAP;
3771*b2ed49a5SDavid van Moolenbroek     }
3772*b2ed49a5SDavid van Moolenbroek #endif
3773*b2ed49a5SDavid van Moolenbroek 
3774*b2ed49a5SDavid van Moolenbroek     /* type: local_dsindex || cached_sentry. */
3775*b2ed49a5SDavid van Moolenbroek     if (local_dsindex) {
3776*b2ed49a5SDavid van Moolenbroek         type = local_dsindex->type;
3777*b2ed49a5SDavid van Moolenbroek 
3778*b2ed49a5SDavid van Moolenbroek         if (num_elements > 1 && MAGIC_TYPE_FLAG(local_dsindex->type, MAGIC_TYPE_VARSIZE)) {
3779*b2ed49a5SDavid van Moolenbroek             size = magic_type_alloc_get_varsized_array_size(local_dsindex->type, num_elements);
3780*b2ed49a5SDavid van Moolenbroek             assert(size > 0);
3781*b2ed49a5SDavid van Moolenbroek         } else {
3782*b2ed49a5SDavid van Moolenbroek             if (is_type_mismatch) {
3783*b2ed49a5SDavid van Moolenbroek                 type = MAGIC_VOID_TYPE;
3784*b2ed49a5SDavid van Moolenbroek                 printf("WARNING: Type size mismatch dsentry detected! Ignoring dsindex type and reverting to MAGIC_TYPE_VOID.\n");
3785*b2ed49a5SDavid van Moolenbroek                 printf("name=%s, parent_name=%s\n", local_dsindex->name, local_dsindex->parent_name);
3786*b2ed49a5SDavid van Moolenbroek             }
3787*b2ed49a5SDavid van Moolenbroek             size = num_elements * type->size;
3788*b2ed49a5SDavid van Moolenbroek         }
3789*b2ed49a5SDavid van Moolenbroek     } else {
3790*b2ed49a5SDavid van Moolenbroek         /*
3791*b2ed49a5SDavid van Moolenbroek          * The type will need adjusting later.
3792*b2ed49a5SDavid van Moolenbroek          */
3793*b2ed49a5SDavid van Moolenbroek         type = cached_sentry->type;
3794*b2ed49a5SDavid van Moolenbroek         size = type->size;
3795*b2ed49a5SDavid van Moolenbroek     }
3796*b2ed49a5SDavid van Moolenbroek 
3797*b2ed49a5SDavid van Moolenbroek     *local_dsentry_ptr = NULL;
3798*b2ed49a5SDavid van Moolenbroek 
3799*b2ed49a5SDavid van Moolenbroek     if (region & MAGIC_STATE_HEAP) {
3800*b2ed49a5SDavid van Moolenbroek         /* malloc */
3801*b2ed49a5SDavid van Moolenbroek         ptr = magic_malloc_positioned(type, name, parent_name, size, (ptr == NULL ? NULL : MAGIC_PTR_FROM_DATA(ptr)));
3802*b2ed49a5SDavid van Moolenbroek         if (ptr == NULL) {
3803*b2ed49a5SDavid van Moolenbroek             printf("ERROR, magic_malloc_positioned returned NULL.\n");
3804*b2ed49a5SDavid van Moolenbroek             return ENOMEM;
3805*b2ed49a5SDavid van Moolenbroek         }
3806*b2ed49a5SDavid van Moolenbroek         memset(ptr, 0, size);
3807*b2ed49a5SDavid van Moolenbroek         local_dsentry = MAGIC_PTR_TO_DSENTRY(MAGIC_PTR_FROM_DATA(ptr));
3808*b2ed49a5SDavid van Moolenbroek     }
3809*b2ed49a5SDavid van Moolenbroek     else if (region & MAGIC_STATE_MAP) {
3810*b2ed49a5SDavid van Moolenbroek         /* mmap */
3811*b2ed49a5SDavid van Moolenbroek         if (!alloc_flags.mmap_flags || !alloc_flags.mmap_prot) {
3812*b2ed49a5SDavid van Moolenbroek             /* We need call_flags to perform mmap. */
3813*b2ed49a5SDavid van Moolenbroek             return ENOSYS;
3814*b2ed49a5SDavid van Moolenbroek         }
3815*b2ed49a5SDavid van Moolenbroek         ptr = persistent_mmap(type, name, parent_name, info, NULL, size,
3816*b2ed49a5SDavid van Moolenbroek             alloc_flags.mmap_prot, alloc_flags.mmap_flags, -1, 0, ptr);
3817*b2ed49a5SDavid van Moolenbroek         if (ptr == NULL) {
3818*b2ed49a5SDavid van Moolenbroek             printf("ERROR, persistent_mmap returned NULL.\n");
3819*b2ed49a5SDavid van Moolenbroek             return ENOMEM;
3820*b2ed49a5SDavid van Moolenbroek         }
3821*b2ed49a5SDavid van Moolenbroek         if (!(alloc_flags.mmap_flags & MAP_SHARED))
3822*b2ed49a5SDavid van Moolenbroek             memset(ptr, 0, size);
3823*b2ed49a5SDavid van Moolenbroek         local_dsentry = MAGIC_PTR_TO_DSENTRY(MAGIC_PTR_FROM_DATA(ptr));
3824*b2ed49a5SDavid van Moolenbroek     }
3825*b2ed49a5SDavid van Moolenbroek #ifndef __MINIX
3826*b2ed49a5SDavid van Moolenbroek     else if (region & MAGIC_STATE_SHM) {
3827*b2ed49a5SDavid van Moolenbroek         /* shmat */
3828*b2ed49a5SDavid van Moolenbroek         if (!alloc_flags.shmat_flags || !alloc_flags.shmat_shmid) {
3829*b2ed49a5SDavid van Moolenbroek             /* We need call_flags to perform shmat. */
3830*b2ed49a5SDavid van Moolenbroek             return ENOSYS;
3831*b2ed49a5SDavid van Moolenbroek         }
3832*b2ed49a5SDavid van Moolenbroek         ptr = magic_shmat(type, name, parent_name, alloc_flags.shmat_shmid,
3833*b2ed49a5SDavid van Moolenbroek             ptr, alloc_flags.shmat_flags);
3834*b2ed49a5SDavid van Moolenbroek         if (ptr == NULL) {
3835*b2ed49a5SDavid van Moolenbroek             printf("ERROR, magic_shmat returned NULL.\n");
3836*b2ed49a5SDavid van Moolenbroek             return ENOMEM;
3837*b2ed49a5SDavid van Moolenbroek         }
3838*b2ed49a5SDavid van Moolenbroek         local_dsentry = MAGIC_PTR_TO_DSENTRY(MAGIC_PTR_FROM_DATA(ptr));
3839*b2ed49a5SDavid van Moolenbroek     }
3840*b2ed49a5SDavid van Moolenbroek #endif
3841*b2ed49a5SDavid van Moolenbroek     else {
3842*b2ed49a5SDavid van Moolenbroek         if (local_dsindex) {
3843*b2ed49a5SDavid van Moolenbroek             printf("ERROR. UNSUPPORTED DSINDEX TYPE: ");
3844*b2ed49a5SDavid van Moolenbroek             MAGIC_DSINDEX_PRINT(local_dsindex, MAGIC_EXPAND_TYPE_STR);
3845*b2ed49a5SDavid van Moolenbroek         } else {
3846*b2ed49a5SDavid van Moolenbroek             printf("ERROR. UNSUPPORTED DSENTRY: ");
3847*b2ed49a5SDavid van Moolenbroek             MAGIC_DSENTRY_PRINT(cached_dsentry, MAGIC_EXPAND_TYPE_STR);
3848*b2ed49a5SDavid van Moolenbroek         }
3849*b2ed49a5SDavid van Moolenbroek         printf("\n");
3850*b2ed49a5SDavid van Moolenbroek         return EINVAL;
3851*b2ed49a5SDavid van Moolenbroek     }
3852*b2ed49a5SDavid van Moolenbroek 
3853*b2ed49a5SDavid van Moolenbroek     if (!local_dsindex) {
3854*b2ed49a5SDavid van Moolenbroek         /*
3855*b2ed49a5SDavid van Moolenbroek          * This was an externally allocated type and, as such, needs adjusting.
3856*b2ed49a5SDavid van Moolenbroek          */
3857*b2ed49a5SDavid van Moolenbroek         assert(cached_sentry->type == &cached_dsentry->type);
3858*b2ed49a5SDavid van Moolenbroek         local_dsentry->type = cached_dsentry->type;
3859*b2ed49a5SDavid van Moolenbroek         if (cached_dsentry->type_array[0]->type_id == MAGIC_TYPE_POINTER) {
3860*b2ed49a5SDavid van Moolenbroek             ST_GET_CACHED_COUNTERPART(cached_dsentry->type_array[0], types, ptr_types, local_dsentry->type_array[0]);
3861*b2ed49a5SDavid van Moolenbroek         } else {
3862*b2ed49a5SDavid van Moolenbroek             ST_GET_CACHED_COUNTERPART(cached_dsentry->type_array[0], types, types, local_dsentry->type_array[0]);
3863*b2ed49a5SDavid van Moolenbroek         }
3864*b2ed49a5SDavid van Moolenbroek         local_dsentry->sentry.type = &local_dsentry->type;
3865*b2ed49a5SDavid van Moolenbroek         local_dsentry->sentry.type->contained_types = local_dsentry->type_array;
3866*b2ed49a5SDavid van Moolenbroek     }
3867*b2ed49a5SDavid van Moolenbroek 
3868*b2ed49a5SDavid van Moolenbroek     assert(local_dsentry);
3869*b2ed49a5SDavid van Moolenbroek     assert(local_dsentry->parent_name && strcmp(local_dsentry->parent_name, ""));
3870*b2ed49a5SDavid van Moolenbroek     assert(local_dsentry->sentry.name && strcmp(local_dsentry->sentry.name, ""));
3871*b2ed49a5SDavid van Moolenbroek     assert(magic_check_dsentry(local_dsentry, 0));
3872*b2ed49a5SDavid van Moolenbroek     *local_dsentry_ptr = local_dsentry;
3873*b2ed49a5SDavid van Moolenbroek 
3874*b2ed49a5SDavid van Moolenbroek     if (is_type_mismatch)
3875*b2ed49a5SDavid van Moolenbroek         local_dsentry->sentry.flags |= MAGIC_STATE_TYPE_SIZE_MISMATCH;
3876*b2ed49a5SDavid van Moolenbroek 
3877*b2ed49a5SDavid van Moolenbroek     /*
3878*b2ed49a5SDavid van Moolenbroek      * Dsentries allocated by shared libraries have the names stored in dsentry
3879*b2ed49a5SDavid van Moolenbroek      * buffers (for now).
3880*b2ed49a5SDavid van Moolenbroek      * Readjust the local_sentry to do this as well, since after state transfer
3881*b2ed49a5SDavid van Moolenbroek      * cleanup the existing names will become invalid.
3882*b2ed49a5SDavid van Moolenbroek      */
3883*b2ed49a5SDavid van Moolenbroek     if (!local_dsindex && MAGIC_SENTRY_IS_LIB_ALLOC(cached_sentry)) {
3884*b2ed49a5SDavid van Moolenbroek         strncpy(local_dsentry->name_ext_buff, local_dsentry->sentry.name,
3885*b2ed49a5SDavid van Moolenbroek             MAGIC_DSENTRY_EXT_NAME_BUFF_SIZE);
3886*b2ed49a5SDavid van Moolenbroek         local_dsentry->sentry.name = local_dsentry->name_ext_buff;
3887*b2ed49a5SDavid van Moolenbroek     }
3888*b2ed49a5SDavid van Moolenbroek 
3889*b2ed49a5SDavid van Moolenbroek     return OK;
3890*b2ed49a5SDavid van Moolenbroek }
3891*b2ed49a5SDavid van Moolenbroek 
check_unpaired_sentry(st_init_info_t * info,struct _magic_sentry * cached_sentry)3892*b2ed49a5SDavid van Moolenbroek PRIVATE int check_unpaired_sentry(st_init_info_t *info,
3893*b2ed49a5SDavid van Moolenbroek     struct _magic_sentry* cached_sentry)
3894*b2ed49a5SDavid van Moolenbroek {
3895*b2ed49a5SDavid van Moolenbroek     int sentry_needs_transfer = MAGIC_STATE_EXTF_GET(cached_sentry, ST_NEEDS_TRANSFER | ST_TRANSFER_DONE) == ST_NEEDS_TRANSFER;
3896*b2ed49a5SDavid van Moolenbroek     int report;
3897*b2ed49a5SDavid van Moolenbroek 
3898*b2ed49a5SDavid van Moolenbroek     if (!sentry_needs_transfer && !MAGIC_SENTRY_IS_STRING(cached_sentry)) {
3899*b2ed49a5SDavid van Moolenbroek         return OK;
3900*b2ed49a5SDavid van Moolenbroek     }
3901*b2ed49a5SDavid van Moolenbroek 
3902*b2ed49a5SDavid van Moolenbroek     if (MAGIC_STATE_FLAG(cached_sentry, MAGIC_STATE_DYNAMIC)) {
3903*b2ed49a5SDavid van Moolenbroek         report = st_policies & ST_REPORT_UNPAIRED_DSENTRIES;
3904*b2ed49a5SDavid van Moolenbroek     }
3905*b2ed49a5SDavid van Moolenbroek     else if(MAGIC_SENTRY_IS_STRING(cached_sentry)) {
3906*b2ed49a5SDavid van Moolenbroek         report = st_policies & ST_REPORT_UNPAIRED_STRINGS;
3907*b2ed49a5SDavid van Moolenbroek     }
3908*b2ed49a5SDavid van Moolenbroek     else {
3909*b2ed49a5SDavid van Moolenbroek         report = st_policies & ST_REPORT_UNPAIRED_SENTRIES;
3910*b2ed49a5SDavid van Moolenbroek     }
3911*b2ed49a5SDavid van Moolenbroek     if (report) {
3912*b2ed49a5SDavid van Moolenbroek         printf("check_unpaired_sentry: Unpaired sentry found: ");
3913*b2ed49a5SDavid van Moolenbroek         ST_SENTRY_PRINT(cached_sentry,MAGIC_EXPAND_TYPE_STR);
3914*b2ed49a5SDavid van Moolenbroek         printf("\n");
3915*b2ed49a5SDavid van Moolenbroek     }
3916*b2ed49a5SDavid van Moolenbroek 
3917*b2ed49a5SDavid van Moolenbroek     return OK;
3918*b2ed49a5SDavid van Moolenbroek }
3919*b2ed49a5SDavid van Moolenbroek 
st_cached_to_remote_sentry(st_init_info_t * info,struct _magic_sentry * cached_sentry)3920*b2ed49a5SDavid van Moolenbroek PUBLIC struct _magic_sentry* st_cached_to_remote_sentry(st_init_info_t *info, struct _magic_sentry *cached_sentry)
3921*b2ed49a5SDavid van Moolenbroek {
3922*b2ed49a5SDavid van Moolenbroek     struct _magic_sentry *remote_sentry;
3923*b2ed49a5SDavid van Moolenbroek     void *local_data_addr;
3924*b2ed49a5SDavid van Moolenbroek     ST_CHECK_INIT();
3925*b2ed49a5SDavid van Moolenbroek 
3926*b2ed49a5SDavid van Moolenbroek     /* Copy metadata into metadata buffer. */
3927*b2ed49a5SDavid van Moolenbroek     if (MAGIC_STATE_FLAG(cached_sentry, MAGIC_STATE_DYNAMIC)) {
3928*b2ed49a5SDavid van Moolenbroek         magic_copy_dsentry(MAGIC_DSENTRY_FROM_SENTRY(cached_sentry), st_dsentry_buff);
3929*b2ed49a5SDavid van Moolenbroek         remote_sentry = MAGIC_DSENTRY_TO_SENTRY(st_dsentry_buff);
3930*b2ed49a5SDavid van Moolenbroek     }
3931*b2ed49a5SDavid van Moolenbroek     else {
3932*b2ed49a5SDavid van Moolenbroek         memcpy(&st_dsentry_buff->sentry, cached_sentry, sizeof(struct _magic_sentry));
3933*b2ed49a5SDavid van Moolenbroek         remote_sentry = &st_dsentry_buff->sentry;
3934*b2ed49a5SDavid van Moolenbroek     }
3935*b2ed49a5SDavid van Moolenbroek 
3936*b2ed49a5SDavid van Moolenbroek     /* Have the remote sentry point to local data. */
3937*b2ed49a5SDavid van Moolenbroek     local_data_addr = NULL;
3938*b2ed49a5SDavid van Moolenbroek     /* See if we have the data locally already first. */
3939*b2ed49a5SDavid van Moolenbroek     ST_GET_CACHED_COUNTERPART(cached_sentry, sentries, sentries_data, local_data_addr);
3940*b2ed49a5SDavid van Moolenbroek     if (!local_data_addr) {
3941*b2ed49a5SDavid van Moolenbroek         /* Copy remote data into local data buffer. */
3942*b2ed49a5SDavid van Moolenbroek         if (st_cbs_os.copy_state_region(info->info_opaque, (uint32_t) remote_sentry->address
3943*b2ed49a5SDavid van Moolenbroek                 , remote_sentry->type->size, (uint32_t) st_data_buff))
3944*b2ed49a5SDavid van Moolenbroek         {
3945*b2ed49a5SDavid van Moolenbroek             printf("ERROR transferring sentry data to local buffer.\n");
3946*b2ed49a5SDavid van Moolenbroek             return NULL;
3947*b2ed49a5SDavid van Moolenbroek         }
3948*b2ed49a5SDavid van Moolenbroek         local_data_addr = st_data_buff;
3949*b2ed49a5SDavid van Moolenbroek     }
3950*b2ed49a5SDavid van Moolenbroek     remote_sentry->address = local_data_addr;
3951*b2ed49a5SDavid van Moolenbroek 
3952*b2ed49a5SDavid van Moolenbroek     return remote_sentry;
3953*b2ed49a5SDavid van Moolenbroek }
3954*b2ed49a5SDavid van Moolenbroek 
transfer_data_sentry(st_init_info_t * info,struct _magic_sentry * cached_sentry)3955*b2ed49a5SDavid van Moolenbroek PRIVATE int transfer_data_sentry(st_init_info_t *info,
3956*b2ed49a5SDavid van Moolenbroek     struct _magic_sentry* cached_sentry)
3957*b2ed49a5SDavid van Moolenbroek {
3958*b2ed49a5SDavid van Moolenbroek 
3959*b2ed49a5SDavid van Moolenbroek     int r;
3960*b2ed49a5SDavid van Moolenbroek     int st_cb_flags = ST_CB_DEFAULT_FLAGS;
3961*b2ed49a5SDavid van Moolenbroek     struct _magic_sentry *local_sentry, *remote_sentry;
3962*b2ed49a5SDavid van Moolenbroek     int flags = ST_SEL_ANALYZE_FLAGS;
3963*b2ed49a5SDavid van Moolenbroek     struct st_cb_info cb_info_buff;
3964*b2ed49a5SDavid van Moolenbroek     struct st_cb_info *cb_info = &cb_info_buff;
3965*b2ed49a5SDavid van Moolenbroek     static _magic_selement_t magic_local_selements[MAGIC_MAX_RECURSIVE_TYPES+1];
3966*b2ed49a5SDavid van Moolenbroek     static int magic_flags_by_depth[MAGIC_MAX_RECURSIVE_TYPES+1];
3967*b2ed49a5SDavid van Moolenbroek 
3968*b2ed49a5SDavid van Moolenbroek     /* Skip extern weak symbols. */
3969*b2ed49a5SDavid van Moolenbroek     if (!cached_sentry->address) {
3970*b2ed49a5SDavid van Moolenbroek         assert(MAGIC_STATE_FLAG(cached_sentry, MAGIC_STATE_EXTERNAL));
3971*b2ed49a5SDavid van Moolenbroek         st_set_transfer_status(ST_TRANSFER_DONE, ST_OP_ADD, cached_sentry, NULL);
3972*b2ed49a5SDavid van Moolenbroek         return OK;
3973*b2ed49a5SDavid van Moolenbroek     }
3974*b2ed49a5SDavid van Moolenbroek 
3975*b2ed49a5SDavid van Moolenbroek     /* Determine local and remote sentries from the cached version. */
3976*b2ed49a5SDavid van Moolenbroek     local_sentry = NULL;
3977*b2ed49a5SDavid van Moolenbroek     st_lookup_sentry_pair(&cached_sentry, &local_sentry);
3978*b2ed49a5SDavid van Moolenbroek     assert(local_sentry && "Unexpected unpaired sentry!");
3979*b2ed49a5SDavid van Moolenbroek     remote_sentry = st_cached_to_remote_sentry(info, cached_sentry);
3980*b2ed49a5SDavid van Moolenbroek     if (!remote_sentry) {
3981*b2ed49a5SDavid van Moolenbroek         printf("No remote sentry found for cached sentry: ");
3982*b2ed49a5SDavid van Moolenbroek         MAGIC_SENTRY_PRINT(cached_sentry, 0);
3983*b2ed49a5SDavid van Moolenbroek         printf("\n");
3984*b2ed49a5SDavid van Moolenbroek         return EFAULT;
3985*b2ed49a5SDavid van Moolenbroek     }
3986*b2ed49a5SDavid van Moolenbroek 
3987*b2ed49a5SDavid van Moolenbroek     cb_info->local_selements = magic_local_selements;
3988*b2ed49a5SDavid van Moolenbroek     cb_info->local_selement = magic_selement_from_sentry(local_sentry, &magic_local_selements[0]);
3989*b2ed49a5SDavid van Moolenbroek     cb_info->walk_flags = MAGIC_TYPE_WALK_DEFAULT_FLAGS;
3990*b2ed49a5SDavid van Moolenbroek     cb_info->st_cb_flags = st_cb_flags;
3991*b2ed49a5SDavid van Moolenbroek     cb_info->init_info = info;
3992*b2ed49a5SDavid van Moolenbroek     cb_info->st_cb_saved_flags = magic_flags_by_depth;
3993*b2ed49a5SDavid van Moolenbroek     magic_flags_by_depth[0] = st_cb_flags;
3994*b2ed49a5SDavid van Moolenbroek 
3995*b2ed49a5SDavid van Moolenbroek     EXEC_WITH_MAGIC_VARS(
3996*b2ed49a5SDavid van Moolenbroek         r = magic_sentry_analyze(remote_sentry , flags, transfer_data_selement, cb_info, NULL);
3997*b2ed49a5SDavid van Moolenbroek         , &st_cached_magic_vars
3998*b2ed49a5SDavid van Moolenbroek     );
3999*b2ed49a5SDavid van Moolenbroek     if (r < 0) {
4000*b2ed49a5SDavid van Moolenbroek         return r;
4001*b2ed49a5SDavid van Moolenbroek     }
4002*b2ed49a5SDavid van Moolenbroek 
4003*b2ed49a5SDavid van Moolenbroek     st_set_transfer_status(ST_TRANSFER_DONE, ST_OP_ADD, cached_sentry, NULL);
4004*b2ed49a5SDavid van Moolenbroek     return OK;
4005*b2ed49a5SDavid van Moolenbroek }
4006*b2ed49a5SDavid van Moolenbroek 
transfer_data_selement(_magic_selement_t * selement,_magic_sel_analyzed_t * sel_analyzed,_magic_sel_stats_t * sel_stats,void * cb_args)4007*b2ed49a5SDavid van Moolenbroek PRIVATE int transfer_data_selement(_magic_selement_t *selement, _magic_sel_analyzed_t *sel_analyzed, _magic_sel_stats_t *sel_stats, void *cb_args)
4008*b2ed49a5SDavid van Moolenbroek {
4009*b2ed49a5SDavid van Moolenbroek 
4010*b2ed49a5SDavid van Moolenbroek     int r = ST_CB_NOT_PROCESSED;
4011*b2ed49a5SDavid van Moolenbroek     int depth, cb_flags;
4012*b2ed49a5SDavid van Moolenbroek     struct st_cb_info *cb_info = (struct st_cb_info *) cb_args;
4013*b2ed49a5SDavid van Moolenbroek     _magic_selement_t *local_selement, *local_parent_selement;
4014*b2ed49a5SDavid van Moolenbroek     st_cb_selement_transfer_t *cb;
4015*b2ed49a5SDavid van Moolenbroek 
4016*b2ed49a5SDavid van Moolenbroek     register_typenames_and_callbacks();
4017*b2ed49a5SDavid van Moolenbroek 
4018*b2ed49a5SDavid van Moolenbroek     if (!ST_CB_FLAG(ST_CB_CHECK_ONLY)) {
4019*b2ed49a5SDavid van Moolenbroek         depth = selement->depth;
4020*b2ed49a5SDavid van Moolenbroek         local_selement = &cb_info->local_selements[depth];
4021*b2ed49a5SDavid van Moolenbroek         if (depth > 0) {
4022*b2ed49a5SDavid van Moolenbroek             local_parent_selement = &cb_info->local_selements[depth-1];
4023*b2ed49a5SDavid van Moolenbroek             local_selement->sentry = local_parent_selement->sentry;
4024*b2ed49a5SDavid van Moolenbroek             local_selement->parent_type = local_parent_selement->type;
4025*b2ed49a5SDavid van Moolenbroek             local_selement->parent_address = local_parent_selement->address;
4026*b2ed49a5SDavid van Moolenbroek             cb_info->st_cb_flags = cb_info->st_cb_saved_flags[depth-1];
4027*b2ed49a5SDavid van Moolenbroek         }
4028*b2ed49a5SDavid van Moolenbroek         /* Map the cached and the local selement. */
4029*b2ed49a5SDavid van Moolenbroek         st_map_selement(selement, local_selement, cb_info, FALSE);
4030*b2ed49a5SDavid van Moolenbroek         if (local_selement->type == NULL) {
4031*b2ed49a5SDavid van Moolenbroek             /* Unpaired selement. */
4032*b2ed49a5SDavid van Moolenbroek             if (st_policies & ST_REPORT_UNPAIRED_SELEMENTS) {
4033*b2ed49a5SDavid van Moolenbroek                 printf("transfer_data_selement: Unpaired selement found: ");
4034*b2ed49a5SDavid van Moolenbroek                 MAGIC_SELEMENT_PRINT(selement, MAGIC_EXPAND_TYPE_STR);
4035*b2ed49a5SDavid van Moolenbroek                 printf("\n");
4036*b2ed49a5SDavid van Moolenbroek             }
4037*b2ed49a5SDavid van Moolenbroek             return MAGIC_SENTRY_ANALYZE_SKIP_PATH;
4038*b2ed49a5SDavid van Moolenbroek         }
4039*b2ed49a5SDavid van Moolenbroek         cb_info->local_selement = local_selement;
4040*b2ed49a5SDavid van Moolenbroek 
4041*b2ed49a5SDavid van Moolenbroek         /* See if identity transfer has been requested. */
4042*b2ed49a5SDavid van Moolenbroek         if (cb_info->st_cb_flags & ST_CB_FORCE_IXFER) {
4043*b2ed49a5SDavid van Moolenbroek             r = transfer_identity_sel_cb(selement, sel_analyzed, sel_stats, cb_info);
4044*b2ed49a5SDavid van Moolenbroek             assert(r != ST_CB_NOT_PROCESSED);
4045*b2ed49a5SDavid van Moolenbroek             cb_info->st_cb_saved_flags[depth] = cb_info->st_cb_flags;
4046*b2ed49a5SDavid van Moolenbroek             return r;
4047*b2ed49a5SDavid van Moolenbroek         }
4048*b2ed49a5SDavid van Moolenbroek     }
4049*b2ed49a5SDavid van Moolenbroek 
4050*b2ed49a5SDavid van Moolenbroek     cb_flags = ST_CB_TYPE_SELEMENT;
4051*b2ed49a5SDavid van Moolenbroek     if (ST_TYPE_NAME_KEY(selement->type) != NULL) {
4052*b2ed49a5SDavid van Moolenbroek         cb_flags |= ST_CB_TYPE_TYPENAME;
4053*b2ed49a5SDavid van Moolenbroek     }
4054*b2ed49a5SDavid van Moolenbroek     if (selement->num == 1) {
4055*b2ed49a5SDavid van Moolenbroek         cb_flags |= ST_CB_TYPE_SENTRY;
4056*b2ed49a5SDavid van Moolenbroek     }
4057*b2ed49a5SDavid van Moolenbroek 
4058*b2ed49a5SDavid van Moolenbroek     cb = st_cbs.st_cb_selement_transfer[cb_flags];
4059*b2ed49a5SDavid van Moolenbroek     while (TRUE) {
4060*b2ed49a5SDavid van Moolenbroek 
4061*b2ed49a5SDavid van Moolenbroek         if (*cb != NULL) {
4062*b2ed49a5SDavid van Moolenbroek             r = (*cb)(selement, sel_analyzed, sel_stats, cb_info);
4063*b2ed49a5SDavid van Moolenbroek         } else {
4064*b2ed49a5SDavid van Moolenbroek             r = default_transfer_selement_sel_cb(selement, sel_analyzed, sel_stats, cb_info);
4065*b2ed49a5SDavid van Moolenbroek             assert(r != ST_CB_NOT_PROCESSED
4066*b2ed49a5SDavid van Moolenbroek                 && "Default selement callback should always process the selement.");
4067*b2ed49a5SDavid van Moolenbroek         }
4068*b2ed49a5SDavid van Moolenbroek 
4069*b2ed49a5SDavid van Moolenbroek         if (r != ST_CB_NOT_PROCESSED) {
4070*b2ed49a5SDavid van Moolenbroek             assert((r<0 || MAGIC_SENTRY_ANALYZE_IS_VALID_RET(r)) && "Invalid callback return code!");
4071*b2ed49a5SDavid van Moolenbroek             if (!ST_CB_FLAG(ST_CB_CHECK_ONLY)) {
4072*b2ed49a5SDavid van Moolenbroek                 cb_info->st_cb_saved_flags[depth] = cb_info->st_cb_flags;
4073*b2ed49a5SDavid van Moolenbroek             }
4074*b2ed49a5SDavid van Moolenbroek             return r;
4075*b2ed49a5SDavid van Moolenbroek         }
4076*b2ed49a5SDavid van Moolenbroek 
4077*b2ed49a5SDavid van Moolenbroek         cb++;
4078*b2ed49a5SDavid van Moolenbroek     }
4079*b2ed49a5SDavid van Moolenbroek 
4080*b2ed49a5SDavid van Moolenbroek     /* Not reachable. */
4081*b2ed49a5SDavid van Moolenbroek     return EINTR;
4082*b2ed49a5SDavid van Moolenbroek }
4083*b2ed49a5SDavid van Moolenbroek 
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)4084*b2ed49a5SDavid van Moolenbroek PRIVATE int lookup_trg_info(_magic_selement_t *selement,
4085*b2ed49a5SDavid van Moolenbroek     _magic_sel_analyzed_t *sel_analyzed, _magic_sel_stats_t *sel_stats, struct st_cb_info *cb_info,
4086*b2ed49a5SDavid van Moolenbroek     _magic_selement_t *cached_trg_selement, _magic_selement_t *local_trg_selement)
4087*b2ed49a5SDavid van Moolenbroek {
4088*b2ed49a5SDavid van Moolenbroek     _magic_selement_t *local_selement, *trg_selement;
4089*b2ed49a5SDavid van Moolenbroek     struct _magic_sentry *cached_trg_sentry, *local_trg_sentry = NULL;
4090*b2ed49a5SDavid van Moolenbroek     struct _magic_function *cached_trg_function, *local_trg_function = NULL;
4091*b2ed49a5SDavid van Moolenbroek     _magic_sel_analyzed_t local_sel_analyzed;
4092*b2ed49a5SDavid van Moolenbroek     _magic_sel_stats_t local_sel_stats;
4093*b2ed49a5SDavid van Moolenbroek     void *local_trg_root_address;
4094*b2ed49a5SDavid van Moolenbroek     struct _magic_type *cached_trg_root_type, *local_trg_root_type;
4095*b2ed49a5SDavid van Moolenbroek     int first_legal_trg_type, is_same_type, is_same_trg_type, local_trg_has_addr_not_taken;
4096*b2ed49a5SDavid van Moolenbroek 
4097*b2ed49a5SDavid van Moolenbroek     local_selement = cb_info->local_selement;
4098*b2ed49a5SDavid van Moolenbroek     first_legal_trg_type = sel_analyzed->u.ptr.first_legal_trg_type;
4099*b2ed49a5SDavid van Moolenbroek     assert(first_legal_trg_type >= 0);
4100*b2ed49a5SDavid van Moolenbroek     trg_selement = &sel_analyzed->u.ptr.trg_selements[first_legal_trg_type];
4101*b2ed49a5SDavid van Moolenbroek     local_trg_root_type = NULL;
4102*b2ed49a5SDavid van Moolenbroek 
4103*b2ed49a5SDavid van Moolenbroek     /* Lookup cached and local targets. */
4104*b2ed49a5SDavid van Moolenbroek     if (MAGIC_SEL_ANALYZED_PTR_HAS_TRG_SENTRY(sel_analyzed)) {
4105*b2ed49a5SDavid van Moolenbroek         cached_trg_sentry = trg_selement->sentry;
4106*b2ed49a5SDavid van Moolenbroek         local_trg_sentry = NULL;
4107*b2ed49a5SDavid van Moolenbroek         st_lookup_sentry_pair(&cached_trg_sentry, &local_trg_sentry);
4108*b2ed49a5SDavid van Moolenbroek         *cached_trg_selement = *trg_selement;
4109*b2ed49a5SDavid van Moolenbroek         cached_trg_root_type = cached_trg_sentry->type;
4110*b2ed49a5SDavid van Moolenbroek         local_trg_has_addr_not_taken = local_trg_sentry && MAGIC_STATE_FLAG(local_trg_sentry, MAGIC_STATE_ADDR_NOT_TAKEN);
4111*b2ed49a5SDavid van Moolenbroek         local_trg_selement->sentry = local_trg_sentry;
4112*b2ed49a5SDavid van Moolenbroek         if (local_trg_sentry) {
4113*b2ed49a5SDavid van Moolenbroek             local_trg_root_address = local_trg_sentry->address;
4114*b2ed49a5SDavid van Moolenbroek             local_trg_root_type = local_trg_sentry->type;
4115*b2ed49a5SDavid van Moolenbroek         }
4116*b2ed49a5SDavid van Moolenbroek     }
4117*b2ed49a5SDavid van Moolenbroek     else if(MAGIC_SEL_ANALYZED_PTR_HAS_TRG_FUNCTION(sel_analyzed)) {
4118*b2ed49a5SDavid van Moolenbroek         cached_trg_function = MAGIC_DFUNCTION_TO_FUNCTION(&sel_analyzed->u.ptr.trg.dfunction);
4119*b2ed49a5SDavid van Moolenbroek         local_trg_function = NULL;
4120*b2ed49a5SDavid van Moolenbroek         st_lookup_function_pair(&cached_trg_function, &local_trg_function);
4121*b2ed49a5SDavid van Moolenbroek         *cached_trg_selement = *trg_selement;
4122*b2ed49a5SDavid van Moolenbroek         cached_trg_root_type = cached_trg_function->type;
4123*b2ed49a5SDavid van Moolenbroek         local_trg_has_addr_not_taken = local_trg_function && MAGIC_STATE_FLAG(local_trg_function, MAGIC_STATE_ADDR_NOT_TAKEN);
4124*b2ed49a5SDavid van Moolenbroek         local_trg_selement->sentry = NULL;
4125*b2ed49a5SDavid van Moolenbroek         if (local_trg_function) {
4126*b2ed49a5SDavid van Moolenbroek             local_trg_root_address = local_trg_function->address;
4127*b2ed49a5SDavid van Moolenbroek             local_trg_root_type = local_trg_function->type;
4128*b2ed49a5SDavid van Moolenbroek         }
4129*b2ed49a5SDavid van Moolenbroek     }
4130*b2ed49a5SDavid van Moolenbroek 
4131*b2ed49a5SDavid van Moolenbroek     /* Check unpaired targets. */
4132*b2ed49a5SDavid van Moolenbroek     if (!local_trg_root_type) {
4133*b2ed49a5SDavid van Moolenbroek         local_trg_selement->type = NULL;
4134*b2ed49a5SDavid van Moolenbroek         return OK;
4135*b2ed49a5SDavid van Moolenbroek     }
4136*b2ed49a5SDavid van Moolenbroek 
4137*b2ed49a5SDavid van Moolenbroek     /* Check address not taken violations. */
4138*b2ed49a5SDavid van Moolenbroek     if (local_trg_has_addr_not_taken) {
4139*b2ed49a5SDavid van Moolenbroek         ST_CB_PRINT(ST_CB_ERR, "uncaught ptr with paired target whose address is not taken", selement, sel_analyzed, sel_stats, cb_info);
4140*b2ed49a5SDavid van Moolenbroek         return EFAULT;
4141*b2ed49a5SDavid van Moolenbroek     }
4142*b2ed49a5SDavid van Moolenbroek 
4143*b2ed49a5SDavid van Moolenbroek     /* Check types and return immediately in case of perfect pointer match. */
4144*b2ed49a5SDavid van Moolenbroek     is_same_type = selement->type == local_selement->type || ST_PTR_TYPE_IS_CACHED_COUNTERPART(selement->type, local_selement->type);
4145*b2ed49a5SDavid van Moolenbroek     is_same_trg_type = ST_TYPE_IS_CACHED_COUNTERPART(cached_trg_root_type, local_trg_root_type);
4146*b2ed49a5SDavid van Moolenbroek     if (is_same_type && is_same_trg_type) {
4147*b2ed49a5SDavid van Moolenbroek         local_trg_selement->type = cached_trg_selement->type;
4148*b2ed49a5SDavid van Moolenbroek         local_trg_selement->address = (char*) local_trg_root_address + sel_analyzed->u.ptr.trg_offset;
4149*b2ed49a5SDavid van Moolenbroek         return OK;
4150*b2ed49a5SDavid van Moolenbroek     }
4151*b2ed49a5SDavid van Moolenbroek #if CHECK_ASR && !FORCE_SOME_UNPAIRED_TYPES
4152*b2ed49a5SDavid van Moolenbroek     if (cb_info->init_info->flags & ST_LU_ASR) {
4153*b2ed49a5SDavid van Moolenbroek         st_cbs_os.panic("ASR should never get here!");
4154*b2ed49a5SDavid van Moolenbroek     }
4155*b2ed49a5SDavid van Moolenbroek #endif
4156*b2ed49a5SDavid van Moolenbroek 
4157*b2ed49a5SDavid van Moolenbroek     /* Map sel_analyzed to its local counterpart. */
4158*b2ed49a5SDavid van Moolenbroek     if (is_same_trg_type) {
4159*b2ed49a5SDavid van Moolenbroek         local_sel_analyzed = *sel_analyzed;
4160*b2ed49a5SDavid van Moolenbroek         local_sel_analyzed.u.ptr.trg_selements[0].address = (char*) local_trg_root_address + sel_analyzed->u.ptr.trg_offset;
4161*b2ed49a5SDavid van Moolenbroek     }
4162*b2ed49a5SDavid van Moolenbroek     else {
4163*b2ed49a5SDavid van Moolenbroek         st_map_sel_analyzed_from_target(sel_analyzed, &local_sel_analyzed, local_trg_sentry, local_trg_function, cb_info);
4164*b2ed49a5SDavid van Moolenbroek         if (local_sel_analyzed.u.ptr.num_trg_types == 0) {
4165*b2ed49a5SDavid van Moolenbroek             /* Unpaired target selements. */
4166*b2ed49a5SDavid van Moolenbroek             local_trg_selement->type = NULL;
4167*b2ed49a5SDavid van Moolenbroek             return OK;
4168*b2ed49a5SDavid van Moolenbroek         }
4169*b2ed49a5SDavid van Moolenbroek     }
4170*b2ed49a5SDavid van Moolenbroek 
4171*b2ed49a5SDavid van Moolenbroek     /* Check violations on the local target. */
4172*b2ed49a5SDavid van Moolenbroek     memset(&local_sel_stats, 0, sizeof(local_sel_stats));
4173*b2ed49a5SDavid van Moolenbroek     magic_selement_analyze_ptr_type_invs(local_selement, &local_sel_analyzed, &local_sel_stats);
4174*b2ed49a5SDavid van Moolenbroek     if (MAGIC_SEL_STATS_HAS_VIOLATIONS(&local_sel_stats)) {
4175*b2ed49a5SDavid van Moolenbroek         /* Local pointer with violations found */
4176*b2ed49a5SDavid van Moolenbroek         ST_CB_PRINT(ST_CB_ERR, "uncaught ptr with after-transfer violations", selement, sel_analyzed, sel_stats, cb_info);
4177*b2ed49a5SDavid van Moolenbroek         ST_CB_PRINT(ST_CB_ERR, "transferred ptr with violations", local_selement, &local_sel_analyzed, &local_sel_stats, cb_info);
4178*b2ed49a5SDavid van Moolenbroek         return EFAULT;
4179*b2ed49a5SDavid van Moolenbroek     }
4180*b2ed49a5SDavid van Moolenbroek 
4181*b2ed49a5SDavid van Moolenbroek     /* All the targets mapped correctly. */
4182*b2ed49a5SDavid van Moolenbroek     local_trg_selement->type = local_sel_analyzed.u.ptr.trg_selements[0].type;
4183*b2ed49a5SDavid van Moolenbroek     local_trg_selement->address = local_sel_analyzed.u.ptr.trg_selements[0].address;
4184*b2ed49a5SDavid van Moolenbroek     return OK;
4185*b2ed49a5SDavid van Moolenbroek }
4186*b2ed49a5SDavid van Moolenbroek 
4187*b2ed49a5SDavid van Moolenbroek /* transfer helper functions */
4188*b2ed49a5SDavid van Moolenbroek 
md_transfer_str(st_init_info_t * info,char ** str_pt)4189*b2ed49a5SDavid van Moolenbroek PRIVATE int md_transfer_str(st_init_info_t *info, char **str_pt)
4190*b2ed49a5SDavid van Moolenbroek {
4191*b2ed49a5SDavid van Moolenbroek     char buff[ST_STR_BUFF_SIZE + 2];
4192*b2ed49a5SDavid van Moolenbroek 
4193*b2ed49a5SDavid van Moolenbroek     if (st_cbs_os.copy_state_region(info->info_opaque, (uint32_t) *str_pt, ST_STR_BUFF_SIZE + 1, (uint32_t) buff)) {
4194*b2ed49a5SDavid van Moolenbroek         st_cbs_os.panic("md_transfer_str(): ERROR transferring string.\n");
4195*b2ed49a5SDavid van Moolenbroek         return EGENERIC;
4196*b2ed49a5SDavid van Moolenbroek     }
4197*b2ed49a5SDavid van Moolenbroek     buff[ST_STR_BUFF_SIZE + 1] = '\0';
4198*b2ed49a5SDavid van Moolenbroek     if (strlen(buff) > ST_STR_BUFF_SIZE) {
4199*b2ed49a5SDavid van Moolenbroek         st_cbs_os.panic("md_transfer_str(): transferred string has a wrong size: %d\n", strlen(buff));
4200*b2ed49a5SDavid van Moolenbroek         return EGENERIC;
4201*b2ed49a5SDavid van Moolenbroek     }
4202*b2ed49a5SDavid van Moolenbroek 
4203*b2ed49a5SDavid van Moolenbroek     *str_pt = st_buff_allocate(info, strlen(buff) + 1);
4204*b2ed49a5SDavid van Moolenbroek     if (!*str_pt) {
4205*b2ed49a5SDavid van Moolenbroek         st_cbs_os.panic("md_transfer_str(): string buffer could not be allocated.\n");
4206*b2ed49a5SDavid van Moolenbroek         return EGENERIC;
4207*b2ed49a5SDavid van Moolenbroek     }
4208*b2ed49a5SDavid van Moolenbroek     strcpy(*str_pt, buff);
4209*b2ed49a5SDavid van Moolenbroek     return OK;
4210*b2ed49a5SDavid van Moolenbroek }
4211*b2ed49a5SDavid van Moolenbroek 
md_transfer(st_init_info_t * info,void * from,void ** to,int len)4212*b2ed49a5SDavid van Moolenbroek PRIVATE int md_transfer(st_init_info_t *info, void *from, void **to, int len)
4213*b2ed49a5SDavid van Moolenbroek {
4214*b2ed49a5SDavid van Moolenbroek     /* backup from value, in case &from == to */
4215*b2ed49a5SDavid van Moolenbroek     void *from_backup = from;
4216*b2ed49a5SDavid van Moolenbroek     *to = st_buff_allocate(info, len);
4217*b2ed49a5SDavid van Moolenbroek     if (!*to) {
4218*b2ed49a5SDavid van Moolenbroek         st_cbs_os.panic("md_transfer(): buffer could not be allocated.\n");
4219*b2ed49a5SDavid van Moolenbroek         return EGENERIC;
4220*b2ed49a5SDavid van Moolenbroek     }
4221*b2ed49a5SDavid van Moolenbroek     if (st_cbs_os.copy_state_region(info->info_opaque, (uint32_t) from_backup, len, (uint32_t) *to)) {
4222*b2ed49a5SDavid van Moolenbroek         st_cbs_os.panic("md_transfer(): ERROR transferring remote data to buffer.\n");
4223*b2ed49a5SDavid van Moolenbroek         return EGENERIC;
4224*b2ed49a5SDavid van Moolenbroek     }
4225*b2ed49a5SDavid van Moolenbroek     return OK;
4226*b2ed49a5SDavid van Moolenbroek }
4227*b2ed49a5SDavid van Moolenbroek 
4228*b2ed49a5SDavid van Moolenbroek 
4229*b2ed49a5SDavid van Moolenbroek /* Buffer allocation */
4230*b2ed49a5SDavid van Moolenbroek 
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)4231*b2ed49a5SDavid van Moolenbroek 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) {
4232*b2ed49a5SDavid van Moolenbroek     if (USE_PRE_ALLOCATED_BUFFER(info)) {
4233*b2ed49a5SDavid van Moolenbroek         size_t alloc_length = length + (length % magic_get_sys_pagesize() == 0 ? 0 : magic_get_sys_pagesize() - (length % magic_get_sys_pagesize()));
4234*b2ed49a5SDavid van Moolenbroek         char *ptr, *data_ptr;
4235*b2ed49a5SDavid van Moolenbroek 
4236*b2ed49a5SDavid van Moolenbroek         assert(((char *)info->init_buff_cleanup_start) + alloc_length + magic_get_sys_pagesize() <= st_pre_allocated_page_pt && "mmap region hits temporary buffer.");
4237*b2ed49a5SDavid van Moolenbroek         assert(((char *)info->init_buff_cleanup_start) + alloc_length + magic_get_sys_pagesize() <= ((char *) info->init_buff_start) + info->init_buff_len && "mmap region hits end of pre-allocated buffer");
4238*b2ed49a5SDavid van Moolenbroek 
4239*b2ed49a5SDavid van Moolenbroek         ptr = ((char *)info->init_buff_cleanup_start) + magic_get_sys_pagesize() - MAGIC_SIZE_TO_REAL(0);
4240*b2ed49a5SDavid van Moolenbroek         data_ptr = magic_alloc(__MA_VALUES__ ptr, alloc_length, (int) MAGIC_STATE_MAP);
4241*b2ed49a5SDavid van Moolenbroek         MAGIC_PTR_TO_DSENTRY(MAGIC_PTR_FROM_DATA(data_ptr))->alloc_mmap_flags = flags;
4242*b2ed49a5SDavid van Moolenbroek         MAGIC_PTR_TO_DSENTRY(MAGIC_PTR_FROM_DATA(data_ptr))->alloc_mmap_prot = prot;
4243*b2ed49a5SDavid van Moolenbroek         info->init_buff_cleanup_start = &data_ptr[alloc_length];
4244*b2ed49a5SDavid van Moolenbroek         return data_ptr;
4245*b2ed49a5SDavid van Moolenbroek     } else {
4246*b2ed49a5SDavid van Moolenbroek         /* no pre-allocated mmap buffer. Call magic_mmap to allocate region. */
4247*b2ed49a5SDavid van Moolenbroek         return magic_mmap_positioned(type, name, parent_name
4248*b2ed49a5SDavid van Moolenbroek             , NULL, length, prot, flags, -1, 0, dsentry);
4249*b2ed49a5SDavid van Moolenbroek     }
4250*b2ed49a5SDavid van Moolenbroek }
4251*b2ed49a5SDavid van Moolenbroek 
st_cb_pages_allocate(st_init_info_t * info,uint32_t * phys,int num_pages)4252*b2ed49a5SDavid van Moolenbroek PUBLIC void *st_cb_pages_allocate(st_init_info_t *info, uint32_t *phys, int num_pages)
4253*b2ed49a5SDavid van Moolenbroek {
4254*b2ed49a5SDavid van Moolenbroek     void *result;
4255*b2ed49a5SDavid van Moolenbroek     int len = num_pages * magic_get_sys_pagesize();
4256*b2ed49a5SDavid van Moolenbroek 
4257*b2ed49a5SDavid van Moolenbroek     if (USE_PRE_ALLOCATED_BUFFER(info)) {
4258*b2ed49a5SDavid van Moolenbroek         if (!st_pre_allocated_page_pt) {
4259*b2ed49a5SDavid van Moolenbroek #if ST_DEBUG_LEVEL > 0
4260*b2ed49a5SDavid van Moolenbroek             printf("st_pages_allocate: initializing pre-allocated page buffer.\n");
4261*b2ed49a5SDavid van Moolenbroek #endif
4262*b2ed49a5SDavid van Moolenbroek             st_pre_allocated_page_pt = &((char *)info->init_buff_start)[info->init_buff_len];
4263*b2ed49a5SDavid van Moolenbroek         }
4264*b2ed49a5SDavid van Moolenbroek         st_pre_allocated_page_pt -= len;
4265*b2ed49a5SDavid van Moolenbroek         assert(st_pre_allocated_page_pt >= (char *)info->init_buff_cleanup_start
4266*b2ed49a5SDavid van Moolenbroek             && "Temporary buffer ran into perminently pre-allocated mmapped pages.");
4267*b2ed49a5SDavid van Moolenbroek         return st_pre_allocated_page_pt;
4268*b2ed49a5SDavid van Moolenbroek     }
4269*b2ed49a5SDavid van Moolenbroek 
4270*b2ed49a5SDavid van Moolenbroek     result = st_cbs_os.alloc_contig(len, 0, NULL);
4271*b2ed49a5SDavid van Moolenbroek     if (result == NULL) {
4272*b2ed49a5SDavid van Moolenbroek         printf("st_pages_allocate: alloc_contig(%d) failed.\n", len);
4273*b2ed49a5SDavid van Moolenbroek         return NULL;
4274*b2ed49a5SDavid van Moolenbroek     }
4275*b2ed49a5SDavid van Moolenbroek 
4276*b2ed49a5SDavid van Moolenbroek     *phys = (uint32_t) NULL; /* we don't know or need the physical address in order to free */
4277*b2ed49a5SDavid van Moolenbroek 
4278*b2ed49a5SDavid van Moolenbroek     return result;
4279*b2ed49a5SDavid van Moolenbroek }
4280*b2ed49a5SDavid van Moolenbroek 
st_cb_pages_free(st_init_info_t * info,st_alloc_pages * current_page)4281*b2ed49a5SDavid van Moolenbroek PUBLIC void st_cb_pages_free(st_init_info_t *info, st_alloc_pages *current_page)
4282*b2ed49a5SDavid van Moolenbroek {
4283*b2ed49a5SDavid van Moolenbroek     st_alloc_pages *to_be_freed;
4284*b2ed49a5SDavid van Moolenbroek     int result;
4285*b2ed49a5SDavid van Moolenbroek 
4286*b2ed49a5SDavid van Moolenbroek     if (USE_PRE_ALLOCATED_BUFFER(info)) {
4287*b2ed49a5SDavid van Moolenbroek         /* nothing to do */
4288*b2ed49a5SDavid van Moolenbroek         return;
4289*b2ed49a5SDavid van Moolenbroek     }
4290*b2ed49a5SDavid van Moolenbroek 
4291*b2ed49a5SDavid van Moolenbroek     while (current_page != NULL) {
4292*b2ed49a5SDavid van Moolenbroek         to_be_freed = current_page;
4293*b2ed49a5SDavid van Moolenbroek         current_page = current_page->previous;
4294*b2ed49a5SDavid van Moolenbroek 
4295*b2ed49a5SDavid van Moolenbroek         result = st_cbs_os.free_contig(to_be_freed->virt_addr, to_be_freed->num_pages * magic_get_sys_pagesize());
4296*b2ed49a5SDavid van Moolenbroek 
4297*b2ed49a5SDavid van Moolenbroek         if (result != OK) {
4298*b2ed49a5SDavid van Moolenbroek             printf("munmap result != ok, using free()\n");
4299*b2ed49a5SDavid van Moolenbroek             /*
4300*b2ed49a5SDavid van Moolenbroek              * NOTE: in case this is moved out of a magic_* module it needs to be
4301*b2ed49a5SDavid van Moolenbroek              * manually annotated so it doesn't get instrumented.
4302*b2ed49a5SDavid van Moolenbroek              */
4303*b2ed49a5SDavid van Moolenbroek             free(to_be_freed->virt_addr);
4304*b2ed49a5SDavid van Moolenbroek         }
4305*b2ed49a5SDavid van Moolenbroek 
4306*b2ed49a5SDavid van Moolenbroek     }
4307*b2ed49a5SDavid van Moolenbroek 
4308*b2ed49a5SDavid van Moolenbroek }
4309*b2ed49a5SDavid van Moolenbroek 
st_buff_allocate(st_init_info_t * info,size_t size)4310*b2ed49a5SDavid van Moolenbroek PUBLIC void *st_buff_allocate(st_init_info_t *info, size_t size)
4311*b2ed49a5SDavid van Moolenbroek {
4312*b2ed49a5SDavid van Moolenbroek     void *result;
4313*b2ed49a5SDavid van Moolenbroek 
4314*b2ed49a5SDavid van Moolenbroek     if (size > st_alloc_buff_available) {
4315*b2ed49a5SDavid van Moolenbroek 
4316*b2ed49a5SDavid van Moolenbroek         int pagesize = magic_get_sys_pagesize();
4317*b2ed49a5SDavid van Moolenbroek         uint32_t phys;
4318*b2ed49a5SDavid van Moolenbroek         st_alloc_pages *buff_previous_page = st_alloc_pages_current;
4319*b2ed49a5SDavid van Moolenbroek 
4320*b2ed49a5SDavid van Moolenbroek         /* calculate number of pages needed */
4321*b2ed49a5SDavid van Moolenbroek         int pages_needed = (size + sizeof(st_alloc_pages)) / pagesize;
4322*b2ed49a5SDavid van Moolenbroek         if ((size + sizeof(st_alloc_pages)) % pagesize)
4323*b2ed49a5SDavid van Moolenbroek             pages_needed++;
4324*b2ed49a5SDavid van Moolenbroek 
4325*b2ed49a5SDavid van Moolenbroek         /* allocate pages */
4326*b2ed49a5SDavid van Moolenbroek         st_alloc_pages_current
4327*b2ed49a5SDavid van Moolenbroek             = st_cbs.st_cb_pages_allocate(info, &phys, pages_needed);
4328*b2ed49a5SDavid van Moolenbroek 
4329*b2ed49a5SDavid van Moolenbroek         if (!st_alloc_pages_current) {
4330*b2ed49a5SDavid van Moolenbroek             printf("Could not allocate buffer.\n");
4331*b2ed49a5SDavid van Moolenbroek             return NULL;
4332*b2ed49a5SDavid van Moolenbroek         }
4333*b2ed49a5SDavid van Moolenbroek 
4334*b2ed49a5SDavid van Moolenbroek         /* set allocation struct */
4335*b2ed49a5SDavid van Moolenbroek         st_alloc_pages_current->virt_addr = st_alloc_pages_current;
4336*b2ed49a5SDavid van Moolenbroek         st_alloc_pages_current->phys_addr = phys;
4337*b2ed49a5SDavid van Moolenbroek         st_alloc_pages_current->num_pages = pages_needed;
4338*b2ed49a5SDavid van Moolenbroek         st_alloc_pages_current->previous = buff_previous_page;
4339*b2ed49a5SDavid van Moolenbroek 
4340*b2ed49a5SDavid van Moolenbroek         /* requested space is right after the struct */
4341*b2ed49a5SDavid van Moolenbroek         st_alloc_buff_pt = (char *) st_alloc_pages_current;
4342*b2ed49a5SDavid van Moolenbroek         st_alloc_buff_pt += sizeof(st_alloc_pages);
4343*b2ed49a5SDavid van Moolenbroek         /* subtract the struct size from the available buffer */
4344*b2ed49a5SDavid van Moolenbroek         st_alloc_buff_available = pages_needed * pagesize - sizeof(st_alloc_pages);
4345*b2ed49a5SDavid van Moolenbroek 
4346*b2ed49a5SDavid van Moolenbroek     }
4347*b2ed49a5SDavid van Moolenbroek 
4348*b2ed49a5SDavid van Moolenbroek     /* return current buffer pointer */
4349*b2ed49a5SDavid van Moolenbroek     result = st_alloc_buff_pt;
4350*b2ed49a5SDavid van Moolenbroek     /* set buffer pointer after space that is requested, ready for next allocation */
4351*b2ed49a5SDavid van Moolenbroek     st_alloc_buff_pt += size;
4352*b2ed49a5SDavid van Moolenbroek     /* adjust available space */
4353*b2ed49a5SDavid van Moolenbroek     st_alloc_buff_available -= size;
4354*b2ed49a5SDavid van Moolenbroek 
4355*b2ed49a5SDavid van Moolenbroek     return result;
4356*b2ed49a5SDavid van Moolenbroek 
4357*b2ed49a5SDavid van Moolenbroek }
4358*b2ed49a5SDavid van Moolenbroek 
st_buff_cleanup(st_init_info_t * info)4359*b2ed49a5SDavid van Moolenbroek PUBLIC void st_buff_cleanup(st_init_info_t *info)
4360*b2ed49a5SDavid van Moolenbroek {
4361*b2ed49a5SDavid van Moolenbroek     st_cbs.st_cb_pages_free(info, st_alloc_pages_current);
4362*b2ed49a5SDavid van Moolenbroek     st_alloc_pages_current = NULL;
4363*b2ed49a5SDavid van Moolenbroek     st_alloc_buff_available = 0;
4364*b2ed49a5SDavid van Moolenbroek     st_alloc_buff_pt = NULL;
4365*b2ed49a5SDavid van Moolenbroek }
4366*b2ed49a5SDavid van Moolenbroek 
st_cleanup(st_init_info_t * info)4367*b2ed49a5SDavid van Moolenbroek PUBLIC void st_cleanup(st_init_info_t *info)
4368*b2ed49a5SDavid van Moolenbroek {
4369*b2ed49a5SDavid van Moolenbroek 
4370*b2ed49a5SDavid van Moolenbroek #if MAGIC_LOOKUP_SENTRY_ALLOW_RANGE_INDEX
4371*b2ed49a5SDavid van Moolenbroek     st_cleanup_rl_index(info, &st_cached_magic_vars);
4372*b2ed49a5SDavid van Moolenbroek     st_cleanup_rl_index(info, _magic_vars);
4373*b2ed49a5SDavid van Moolenbroek #endif
4374*b2ed49a5SDavid van Moolenbroek 
4375*b2ed49a5SDavid van Moolenbroek #if MAGIC_LOOKUP_SENTRY_ALLOW_NAME_HASH
4376*b2ed49a5SDavid van Moolenbroek     st_cleanup_sentry_hash(info, &st_cached_magic_vars);
4377*b2ed49a5SDavid van Moolenbroek     st_cleanup_sentry_hash(info, _magic_vars);
4378*b2ed49a5SDavid van Moolenbroek #endif
4379*b2ed49a5SDavid van Moolenbroek 
4380*b2ed49a5SDavid van Moolenbroek #if MAGIC_LOOKUP_FUNCTION_ALLOW_ADDR_HASH
4381*b2ed49a5SDavid van Moolenbroek     st_cleanup_function_hash(info, &st_cached_magic_vars);
4382*b2ed49a5SDavid van Moolenbroek     st_cleanup_function_hash(info, _magic_vars);
4383*b2ed49a5SDavid van Moolenbroek #endif
4384*b2ed49a5SDavid van Moolenbroek 
4385*b2ed49a5SDavid van Moolenbroek #if !ST_ASSUME_RAW_COPY_BEFORE_TRANSFER
4386*b2ed49a5SDavid van Moolenbroek     assert(
4387*b2ed49a5SDavid van Moolenbroek         deallocate_nonxferred_dsentries(st_cached_magic_vars.first_dsentry,
4388*b2ed49a5SDavid van Moolenbroek             &st_counterparts) == OK &&
4389*b2ed49a5SDavid van Moolenbroek             "ERROR occurred during call to deallocate_nonxferred_dsentries().");
4390*b2ed49a5SDavid van Moolenbroek #endif
4391*b2ed49a5SDavid van Moolenbroek 
4392*b2ed49a5SDavid van Moolenbroek     /*
4393*b2ed49a5SDavid van Moolenbroek      * Free all temporary allocated memory.
4394*b2ed49a5SDavid van Moolenbroek      */
4395*b2ed49a5SDavid van Moolenbroek     st_buff_cleanup(info);
4396*b2ed49a5SDavid van Moolenbroek 
4397*b2ed49a5SDavid van Moolenbroek     /*
4398*b2ed49a5SDavid van Moolenbroek      * Reset all values in case of successive state transfers.
4399*b2ed49a5SDavid van Moolenbroek      */
4400*b2ed49a5SDavid van Moolenbroek     st_init_done = FALSE;
4401*b2ed49a5SDavid van Moolenbroek     st_pre_allocated_page_pt = NULL;
4402*b2ed49a5SDavid van Moolenbroek     st_dsentry_buff = NULL;
4403*b2ed49a5SDavid van Moolenbroek     st_data_buff = NULL;
4404*b2ed49a5SDavid van Moolenbroek     st_num_type_transformations = 0;
4405*b2ed49a5SDavid van Moolenbroek     st_local_magic_vars_ptr = &_magic_vars_buff;
4406*b2ed49a5SDavid van Moolenbroek     st_policies = ST_POLICIES_DEFAULT;
4407*b2ed49a5SDavid van Moolenbroek     st_unpaired_types_ratio = ST_UNPAIRED_TYPES_RATIO_DEFAULT;
4408*b2ed49a5SDavid van Moolenbroek     st_unpaired_struct_types_ratio = ST_UNPAIRED_STRUCT_TYPES_RATIO_DEFAULT;
4409*b2ed49a5SDavid van Moolenbroek 
4410*b2ed49a5SDavid van Moolenbroek     /* Reallow mempool dsentries lookups. */
4411*b2ed49a5SDavid van Moolenbroek     magic_lookup_nested_dsentries = 1;
4412*b2ed49a5SDavid van Moolenbroek }
4413*b2ed49a5SDavid van Moolenbroek 
4414*b2ed49a5SDavid van Moolenbroek /* State cleanup/checking functions. */
4415*b2ed49a5SDavid van Moolenbroek 
4416*b2ed49a5SDavid van Moolenbroek /*===========================================================================*
4417*b2ed49a5SDavid van Moolenbroek  *                         do_st_before_receive                              *
4418*b2ed49a5SDavid van Moolenbroek  *===========================================================================*/
do_st_before_receive()4419*b2ed49a5SDavid van Moolenbroek PUBLIC void do_st_before_receive()
4420*b2ed49a5SDavid van Moolenbroek {
4421*b2ed49a5SDavid van Moolenbroek /* Handle State transfer before receive events. */
4422*b2ed49a5SDavid van Moolenbroek   int num_violations;
4423*b2ed49a5SDavid van Moolenbroek 
4424*b2ed49a5SDavid van Moolenbroek   assert(st_state_checking_before_receive_is_enabled());
4425*b2ed49a5SDavid van Moolenbroek 
4426*b2ed49a5SDavid van Moolenbroek   num_violations = st_do_state_checking();
4427*b2ed49a5SDavid van Moolenbroek   if (__st_before_receive_sc_max_cycles < LONG_MAX) {
4428*b2ed49a5SDavid van Moolenbroek       __st_before_receive_sc_max_cycles--;
4429*b2ed49a5SDavid van Moolenbroek   }
4430*b2ed49a5SDavid van Moolenbroek   if (__st_before_receive_sc_max_violations < LONG_MAX) {
4431*b2ed49a5SDavid van Moolenbroek       __st_before_receive_sc_max_violations -= num_violations;
4432*b2ed49a5SDavid van Moolenbroek   }
4433*b2ed49a5SDavid van Moolenbroek   if (__st_before_receive_sc_max_cycles <= 0) {
4434*b2ed49a5SDavid van Moolenbroek       st_state_checking_before_receive_set_enabled(0, 0, 0);
4435*b2ed49a5SDavid van Moolenbroek       printf("Maximum number of cycles reached\n");
4436*b2ed49a5SDavid van Moolenbroek   }
4437*b2ed49a5SDavid van Moolenbroek   if (__st_before_receive_sc_max_violations <= 0) {
4438*b2ed49a5SDavid van Moolenbroek       st_state_checking_before_receive_set_enabled(0, 0, 0);
4439*b2ed49a5SDavid van Moolenbroek       printf("Maximum number of violations reached\n");
4440*b2ed49a5SDavid van Moolenbroek   }
4441*b2ed49a5SDavid van Moolenbroek }
4442*b2ed49a5SDavid van Moolenbroek 
4443*b2ed49a5SDavid van Moolenbroek /*===========================================================================*
4444*b2ed49a5SDavid van Moolenbroek  *                st_state_checking_before_receive_is_enabled                *
4445*b2ed49a5SDavid van Moolenbroek  *===========================================================================*/
st_state_checking_before_receive_is_enabled()4446*b2ed49a5SDavid van Moolenbroek PUBLIC int st_state_checking_before_receive_is_enabled()
4447*b2ed49a5SDavid van Moolenbroek {
4448*b2ed49a5SDavid van Moolenbroek     return __st_before_receive_enabled;
4449*b2ed49a5SDavid van Moolenbroek }
4450*b2ed49a5SDavid van Moolenbroek 
4451*b2ed49a5SDavid van Moolenbroek /*===========================================================================*
4452*b2ed49a5SDavid van Moolenbroek  *               st_state_checking_before_receive_set_enabled                *
4453*b2ed49a5SDavid van Moolenbroek  *===========================================================================*/
st_state_checking_before_receive_set_enabled(int enabled,int max_cycles,int max_violations)4454*b2ed49a5SDavid van Moolenbroek PUBLIC int st_state_checking_before_receive_set_enabled(int enabled,
4455*b2ed49a5SDavid van Moolenbroek     int max_cycles, int max_violations)
4456*b2ed49a5SDavid van Moolenbroek {
4457*b2ed49a5SDavid van Moolenbroek     int was_enabled = __st_before_receive_enabled;
4458*b2ed49a5SDavid van Moolenbroek     __st_before_receive_enabled = enabled;
4459*b2ed49a5SDavid van Moolenbroek     if (enabled) {
4460*b2ed49a5SDavid van Moolenbroek         if (max_cycles <= 0) {
4461*b2ed49a5SDavid van Moolenbroek             max_cycles = ST_STATE_CHECKING_DEFAULT_MAX_CYCLES;
4462*b2ed49a5SDavid van Moolenbroek         }
4463*b2ed49a5SDavid van Moolenbroek         if (max_violations <= 0) {
4464*b2ed49a5SDavid van Moolenbroek             max_violations = ST_STATE_CHECKING_DEFAULT_MAX_VIOLATIONS;
4465*b2ed49a5SDavid van Moolenbroek         }
4466*b2ed49a5SDavid van Moolenbroek         __st_before_receive_sc_max_cycles = max_cycles;
4467*b2ed49a5SDavid van Moolenbroek         __st_before_receive_sc_max_violations = max_violations;
4468*b2ed49a5SDavid van Moolenbroek         printf("Continuous state checking enabled, max cycles=%d, max violations=%d\n",
4469*b2ed49a5SDavid van Moolenbroek             max_cycles == LONG_MAX ? 0 : max_cycles,
4470*b2ed49a5SDavid van Moolenbroek             max_violations == LONG_MAX ? 0 : max_violations);
4471*b2ed49a5SDavid van Moolenbroek     }
4472*b2ed49a5SDavid van Moolenbroek     else {
4473*b2ed49a5SDavid van Moolenbroek         printf("Continuous state checking disabled\n");
4474*b2ed49a5SDavid van Moolenbroek     }
4475*b2ed49a5SDavid van Moolenbroek     return was_enabled;
4476*b2ed49a5SDavid van Moolenbroek }
4477*b2ed49a5SDavid van Moolenbroek 
4478*b2ed49a5SDavid van Moolenbroek /*===========================================================================*
4479*b2ed49a5SDavid van Moolenbroek  *                         st_cb_state_checking_wrapper                      *
4480*b2ed49a5SDavid van Moolenbroek  *===========================================================================*/
st_cb_state_checking_wrapper(_magic_selement_t * selement,_magic_sel_analyzed_t * sel_analyzed,_magic_sel_stats_t * sel_stats,void * cb_args)4481*b2ed49a5SDavid van Moolenbroek PRIVATE int st_cb_state_checking_wrapper(_magic_selement_t* selement,
4482*b2ed49a5SDavid van Moolenbroek     _magic_sel_analyzed_t *sel_analyzed, _magic_sel_stats_t *sel_stats,
4483*b2ed49a5SDavid van Moolenbroek     void* cb_args)
4484*b2ed49a5SDavid van Moolenbroek {
4485*b2ed49a5SDavid van Moolenbroek     struct st_cb_info cb_info_buff;
4486*b2ed49a5SDavid van Moolenbroek     struct st_cb_info *cb_info = &cb_info_buff;
4487*b2ed49a5SDavid van Moolenbroek     int *num_violations = (int*) cb_args;
4488*b2ed49a5SDavid van Moolenbroek     int ret;
4489*b2ed49a5SDavid van Moolenbroek 
4490*b2ed49a5SDavid van Moolenbroek     cb_info->local_selements = NULL;
4491*b2ed49a5SDavid van Moolenbroek     cb_info->local_selement = NULL;
4492*b2ed49a5SDavid van Moolenbroek     cb_info->walk_flags = MAGIC_TYPE_WALK_DEFAULT_FLAGS;
4493*b2ed49a5SDavid van Moolenbroek     cb_info->st_cb_flags = ST_CB_CHECK_ONLY;
4494*b2ed49a5SDavid van Moolenbroek     cb_info->st_cb_saved_flags = NULL;
4495*b2ed49a5SDavid van Moolenbroek     cb_info->init_info = NULL;
4496*b2ed49a5SDavid van Moolenbroek 
4497*b2ed49a5SDavid van Moolenbroek     ret = transfer_data_selement(selement, sel_analyzed, sel_stats, cb_info);
4498*b2ed49a5SDavid van Moolenbroek     if (ret < 0) {
4499*b2ed49a5SDavid van Moolenbroek         ret = st_cbs.st_cb_state_checking(selement, sel_analyzed, sel_stats, cb_args);
4500*b2ed49a5SDavid van Moolenbroek         (*num_violations)++;
4501*b2ed49a5SDavid van Moolenbroek     }
4502*b2ed49a5SDavid van Moolenbroek     return ret;
4503*b2ed49a5SDavid van Moolenbroek }
4504*b2ed49a5SDavid van Moolenbroek 
4505*b2ed49a5SDavid van Moolenbroek /*===========================================================================*
4506*b2ed49a5SDavid van Moolenbroek  *                         st_do_state_checking                              *
4507*b2ed49a5SDavid van Moolenbroek  *===========================================================================*/
st_do_state_checking()4508*b2ed49a5SDavid van Moolenbroek PUBLIC int st_do_state_checking()
4509*b2ed49a5SDavid van Moolenbroek {
4510*b2ed49a5SDavid van Moolenbroek     int num_violations = 0;
4511*b2ed49a5SDavid van Moolenbroek     magic_sentries_analyze(ST_SEL_ANALYZE_FLAGS,
4512*b2ed49a5SDavid van Moolenbroek         st_cb_state_checking_wrapper, &num_violations, NULL);
4513*b2ed49a5SDavid van Moolenbroek     return num_violations;
4514*b2ed49a5SDavid van Moolenbroek }
4515*b2ed49a5SDavid van Moolenbroek 
4516*b2ed49a5SDavid van Moolenbroek /*===========================================================================*
4517*b2ed49a5SDavid van Moolenbroek  *                         st_cb_state_checking_null                         *
4518*b2ed49a5SDavid van Moolenbroek  *===========================================================================*/
st_cb_state_checking_null(_magic_selement_t * selement,_magic_sel_analyzed_t * sel_analyzed,_magic_sel_stats_t * sel_stats,void * cb_args)4519*b2ed49a5SDavid van Moolenbroek PUBLIC int st_cb_state_checking_null(_magic_selement_t* selement,
4520*b2ed49a5SDavid van Moolenbroek     _magic_sel_analyzed_t *sel_analyzed, _magic_sel_stats_t *sel_stats,
4521*b2ed49a5SDavid van Moolenbroek     void* cb_args)
4522*b2ed49a5SDavid van Moolenbroek {
4523*b2ed49a5SDavid van Moolenbroek     return EINTR;
4524*b2ed49a5SDavid van Moolenbroek }
4525*b2ed49a5SDavid van Moolenbroek 
4526*b2ed49a5SDavid van Moolenbroek /*===========================================================================*
4527*b2ed49a5SDavid van Moolenbroek  *                         st_cb_state_checking_print                        *
4528*b2ed49a5SDavid van Moolenbroek  *===========================================================================*/
st_cb_state_checking_print(_magic_selement_t * selement,_magic_sel_analyzed_t * sel_analyzed,_magic_sel_stats_t * sel_stats,void * cb_args)4529*b2ed49a5SDavid van Moolenbroek PUBLIC int st_cb_state_checking_print(_magic_selement_t* selement,
4530*b2ed49a5SDavid van Moolenbroek     _magic_sel_analyzed_t *sel_analyzed, _magic_sel_stats_t *sel_stats,
4531*b2ed49a5SDavid van Moolenbroek     void* cb_args)
4532*b2ed49a5SDavid van Moolenbroek {
4533*b2ed49a5SDavid van Moolenbroek     printf("%s. Found state violation:\n", st_cbs_os.debug_header());
4534*b2ed49a5SDavid van Moolenbroek     magic_sentry_print_el_cb(selement, sel_analyzed, sel_stats, cb_args);
4535*b2ed49a5SDavid van Moolenbroek     return MAGIC_SENTRY_ANALYZE_SKIP_PATH;
4536*b2ed49a5SDavid van Moolenbroek }
4537*b2ed49a5SDavid van Moolenbroek 
4538*b2ed49a5SDavid van Moolenbroek /*===========================================================================*
4539*b2ed49a5SDavid van Moolenbroek  *                         st_cb_state_checking_panic                        *
4540*b2ed49a5SDavid van Moolenbroek  *===========================================================================*/
st_cb_state_checking_panic(_magic_selement_t * selement,_magic_sel_analyzed_t * sel_analyzed,_magic_sel_stats_t * sel_stats,void * cb_args)4541*b2ed49a5SDavid van Moolenbroek PUBLIC int st_cb_state_checking_panic(_magic_selement_t* selement,
4542*b2ed49a5SDavid van Moolenbroek     _magic_sel_analyzed_t *sel_analyzed, _magic_sel_stats_t *sel_stats,
4543*b2ed49a5SDavid van Moolenbroek     void* cb_args)
4544*b2ed49a5SDavid van Moolenbroek {
4545*b2ed49a5SDavid van Moolenbroek     st_cb_state_checking_print(selement, sel_analyzed, sel_stats, cb_args);
4546*b2ed49a5SDavid van Moolenbroek     st_cbs_os.panic("Time to panic...");
4547*b2ed49a5SDavid van Moolenbroek     return MAGIC_SENTRY_ANALYZE_STOP;
4548*b2ed49a5SDavid van Moolenbroek }
4549*b2ed49a5SDavid van Moolenbroek 
4550*b2ed49a5SDavid van Moolenbroek /*===========================================================================*
4551*b2ed49a5SDavid van Moolenbroek  *                         st_do_state_cleanup                               *
4552*b2ed49a5SDavid van Moolenbroek  *===========================================================================*/
st_do_state_cleanup()4553*b2ed49a5SDavid van Moolenbroek PUBLIC int st_do_state_cleanup()
4554*b2ed49a5SDavid van Moolenbroek {
4555*b2ed49a5SDavid van Moolenbroek     return st_cbs.st_cb_state_cleanup();
4556*b2ed49a5SDavid van Moolenbroek }
4557*b2ed49a5SDavid van Moolenbroek 
4558*b2ed49a5SDavid van Moolenbroek /*===========================================================================*
4559*b2ed49a5SDavid van Moolenbroek  *                         st_cb_state_cleanup_null                          *
4560*b2ed49a5SDavid van Moolenbroek  *===========================================================================*/
st_cb_state_cleanup_null()4561*b2ed49a5SDavid van Moolenbroek PUBLIC int st_cb_state_cleanup_null() {
4562*b2ed49a5SDavid van Moolenbroek     return OK;
4563*b2ed49a5SDavid van Moolenbroek }
4564*b2ed49a5SDavid van Moolenbroek 
4565*b2ed49a5SDavid van Moolenbroek #ifndef __MINIX
4566*b2ed49a5SDavid van Moolenbroek /*===========================================================================*
4567*b2ed49a5SDavid van Moolenbroek  *                        st_msync_all_shm_dsentries                         *
4568*b2ed49a5SDavid van Moolenbroek  *===========================================================================*/
st_msync_all_shm_dsentries(void)4569*b2ed49a5SDavid van Moolenbroek PUBLIC void st_msync_all_shm_dsentries(void) {
4570*b2ed49a5SDavid van Moolenbroek     struct _magic_dsentry *prev_dsentry, *dsentry;
4571*b2ed49a5SDavid van Moolenbroek     struct _magic_sentry *sentry;
4572*b2ed49a5SDavid van Moolenbroek     MAGIC_DSENTRY_ALIVE_ITER(_magic_first_dsentry, prev_dsentry,
4573*b2ed49a5SDavid van Moolenbroek         dsentry, sentry,
4574*b2ed49a5SDavid van Moolenbroek 
4575*b2ed49a5SDavid van Moolenbroek         /*
4576*b2ed49a5SDavid van Moolenbroek          * TODO:
4577*b2ed49a5SDavid van Moolenbroek          * - Don't msync mmaps of /dev/zero
4578*b2ed49a5SDavid van Moolenbroek          */
4579*b2ed49a5SDavid van Moolenbroek         if (MAGIC_STATE_FLAGS(sentry, MAGIC_STATE_SHM | MAGIC_STATE_MAP) &&
4580*b2ed49a5SDavid van Moolenbroek             !(dsentry->alloc_mmap_flags & MAP_ANONYMOUS))
4581*b2ed49a5SDavid van Moolenbroek             msync(MAGIC_PTR_TO_DATA(dsentry), sentry->type->size,
4582*b2ed49a5SDavid van Moolenbroek                 MS_SYNC | MS_INVALIDATE);
4583*b2ed49a5SDavid van Moolenbroek 
4584*b2ed49a5SDavid van Moolenbroek     );
4585*b2ed49a5SDavid van Moolenbroek }
4586*b2ed49a5SDavid van Moolenbroek #endif
4587*b2ed49a5SDavid van Moolenbroek 
4588