3 #include <magic_analysis.h>
6 #include <st/state_transfer.h>
7 #include <st/metadata_transfer.h>
8 #include <st/typedefs.h>
9 #include <st/private.h>
11 #define printf _magic_printf
14 EXTERN endpoint_t sef_self_endpoint
;
16 #define DO_SKIP_ENVIRON_HACK 1
17 #define TODO_DSENTRY_PARENT_NAME_BUG 1
18 #define DO_SKIP_UNPAIRED_PTR_TARGETS 1
21 #define DO_SKIP_INVARIANTS_VIOLATIONS 0
23 PRIVATE st_alloc_pages
*st_alloc_pages_current
= NULL
;
24 PRIVATE
size_t st_alloc_buff_available
= 0;
25 PRIVATE
char *st_alloc_buff_pt
= NULL
;
26 PRIVATE
char *st_pre_allocated_page_pt
= NULL
;
27 PRIVATE
struct _magic_dsentry
*st_dsentry_buff
= NULL
;
28 PRIVATE
void *st_data_buff
= NULL
;
29 PRIVATE
unsigned st_num_type_transformations
= 0;
31 /* Magic variables and counterparts. */
32 struct _magic_vars_t st_remote_magic_vars
, st_cached_magic_vars
;
33 struct _magic_vars_t
*st_local_magic_vars_ptr
= &_magic_vars_buff
;
34 st_counterparts_t st_counterparts
;
36 /* Private variables. */
37 PRIVATE
int st_init_done
= FALSE
;
38 PRIVATE
int st_policies
= ST_POLICIES_DEFAULT
;
39 PRIVATE
double st_unpaired_types_ratio
= ST_UNPAIRED_TYPES_RATIO_DEFAULT
;
40 PRIVATE
double st_unpaired_struct_types_ratio
= ST_UNPAIRED_STRUCT_TYPES_RATIO_DEFAULT
;
42 /* Forward declarations. */
43 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
);
45 /* State transfer callbacks. */
47 PRIVATE
struct st_cbs_t st_cbs
= {
48 ST_CB_PAGES_ALLOCATE_DEFAULT
,
49 ST_CB_PAGES_FREE_DEFAULT
,
50 ST_CB_STATE_CLEANUP_DEFAULT
,
51 ST_CB_STATE_CHECKING_DEFAULT
,
52 ST_CB_SELEMENT_MAP_DEFAULT
,
53 ST_CB_SELEMENT_TRANSFER_EMPTY
56 /* OS dependent callbacks. */
57 PRIVATE
struct st_cbs_os_t st_cbs_os
= {
59 ST_CB_OS_OLD_STATE_TABLE_LOOKUP_EMPTY
,
60 ST_CB_OS_COPY_STATE_REGION_EMPTY
,
61 ST_CB_OS_ALLOC_CONTIG_EMPTY
,
62 ST_CB_OS_FREE_CONTIG_EMPTY
,
63 ST_CB_OS_DEBUG_HEADER_EMPTY
66 /* State transfer prototypes for st_receive(). */
67 PUBLIC
void do_st_before_receive(void);
69 /* Callback setters */
71 PUBLIC
void st_setcb_pages_allocate (st_cb_pages_allocate_t cb
)
74 st_cbs
.st_cb_pages_allocate
= cb
;
77 PUBLIC
void st_setcb_pages_free (st_cb_pages_free_t cb
)
80 st_cbs
.st_cb_pages_free
= cb
;
83 PUBLIC
void st_setcb_state_cleanup (st_cb_state_cleanup_t cb
)
86 st_cbs
.st_cb_state_cleanup
= cb
;
87 magic_setcb_sentries_analyze_pre(cb
);
90 PUBLIC
void st_setcb_state_checking (st_cb_state_checking_t cb
)
93 st_cbs
.st_cb_state_checking
= cb
;
96 PUBLIC
void st_setcb_selement_map(st_cb_selement_map_t cb
)
99 st_cbs
.st_cb_selement_map
= cb
;
102 PUBLIC
void st_setcb_selement_transfer(st_cb_selement_transfer_t cb
, int flags
)
105 for (i
= 0 ; i
< NUM_CB_ARRAYS
; i
++) {
107 int is_registered
= FALSE
;
108 for (j
= 0; j
< MAX_NUM_CBS
; j
++) {
109 if (st_cbs
.st_cb_selement_transfer
[i
][j
] == NULL
) {
110 st_cbs
.st_cb_selement_transfer
[i
][j
] = cb
;
111 is_registered
= TRUE
;
115 assert(is_registered
&& "Number of registered callbacks exceeds MAX_NUM_CBS");
120 /* OS Callback setters. */
122 PUBLIC
void st_setcb_os_panic(st_cb_os_panic_t cb
)
124 assert(cb
!= NULL
&& "No callback defined for panic().");
125 st_cbs_os
.panic
= cb
;
128 PUBLIC
void st_setcb_os_old_state_table_lookup(st_cb_os_old_state_table_lookup_t cb
)
130 assert(cb
!= NULL
&& "No callback defined for old_state_table_lookup().");
131 st_cbs_os
.old_state_table_lookup
= cb
;
134 PUBLIC
void st_setcb_os_copy_state_region(st_cb_os_copy_state_region_t cb
)
136 assert(cb
!= NULL
&& "No callback defined for copy_state_region().");
137 st_cbs_os
.copy_state_region
= cb
;
140 PUBLIC
void st_setcb_os_alloc_contig(st_cb_os_alloc_contig_t cb
)
142 assert(cb
!= NULL
&& "No callback defined for alloc_contig().");
143 st_cbs_os
.alloc_contig
= cb
;
146 PUBLIC
void st_setcb_os_free_contig(st_cb_os_free_contig_t cb
)
148 assert(cb
!= NULL
&& "No callback defined for free_contig().");
149 st_cbs_os
.free_contig
= cb
;
152 PUBLIC
void st_setcb_os_debug_header(st_cb_os_debug_header_t cb
)
154 assert(cb
!= NULL
&& "No callback defined for debug_header().");
155 st_cbs_os
.debug_header
= cb
;
159 PUBLIC
void st_setcb_os_all(struct st_cbs_os_t
*cbs
)
161 st_setcb_os_panic(cbs
->panic
);
162 st_setcb_os_old_state_table_lookup(cbs
->old_state_table_lookup
);
163 st_setcb_os_copy_state_region(cbs
->copy_state_region
);
164 st_setcb_os_alloc_contig(cbs
->alloc_contig
);
165 st_setcb_os_free_contig(cbs
->free_contig
);
166 st_setcb_os_debug_header(cbs
->debug_header
);
169 /* Status variables to be transfered at state transfer time. */
170 PUBLIC
int __st_before_receive_enabled
= 0;
171 PRIVATE
int __st_before_receive_sc_max_cycles
;
172 PRIVATE
int __st_before_receive_sc_max_violations
;
174 /* Typedef registration and lookup */
176 int st_strcmp_wildcard(const char *with_wildcard
, const char *without_wildcard
)
178 /* Note: this implementation only supports basic regexes with a '*'
179 * at the beginning or the end of the string.
181 const char *star
= strchr(with_wildcard
, '*');
183 if (star
== with_wildcard
) {
184 size_t len
= strlen(with_wildcard
+1);
185 size_t len_without_wildcard
= strlen(without_wildcard
);
186 const char *match_without_wildcard
= without_wildcard
+
187 len_without_wildcard
-len
;
188 if (match_without_wildcard
< without_wildcard
) {
191 return strncmp(with_wildcard
+1, match_without_wildcard
, len
);
193 return strncmp(with_wildcard
, without_wildcard
, star
- with_wildcard
);
195 return strcmp(with_wildcard
, without_wildcard
);
198 const char *st_typename_noxfers
[] = { ST_TYPENAME_NO_TRANSFER_NAMES
, NULL
};
199 const char *st_typename_ixfers
[] = { ST_TYPENAME_IDENTITY_TRANSFER_NAMES
, NULL
};
200 const char *st_typename_cixfers
[] = { ST_TYPENAME_CIDENTITY_TRANSFER_NAMES
, NULL
};
201 const char *st_typename_pxfers
[] = { ST_TYPENAME_PTR_TRANSFER_NAMES
, NULL
};
202 const char *st_typename_sxfers
[] = { ST_TYPENAME_STRUCT_TRANSFER_NAMES
, NULL
};
203 const char *st_sentryname_ixfers
[] = { ST_SENTRYNAME_IDENTITY_TRANSFER_NAMES
, NULL
};
204 const char *st_sentryname_cixfers
[] = { ST_SENTRYNAME_CIDENTITY_TRANSFER_NAMES
, NULL
};
205 const char *st_sentryname_pxfers
[] = { ST_SENTRYNAME_PTR_TRANSFER_NAMES
, NULL
};
207 /* Exclude stack references in addition to the default sentry names from state transfer. */
208 const char *st_sentryname_noxfers
[] = {
209 ST_SENTRYNAME_NO_TRANSFER_NAMES
,
210 #define __X(R) #R /* Stringify the symbol names. */
211 ST_STACK_REFS_INT_LIST
,
212 #if ST_STACK_REFS_CUSTOM_NUM > 0
213 ST_STACK_REFS_CUSTOM_LIST
,
217 const char *st_sentryname_noxfers_mem
[] = { ST_SENTRYNAME_NO_TRANSFER_MEM_NAMES
, NULL
};
219 /* Exclude the data segments of certain libs from state transfer. */
220 const char *st_dsentry_lib_noxfer
[] = {
221 #ifdef ST_DSENTRYLIB_NO_TRANSFER_NAMES
222 ST_DSENTRYLIB_NO_TRANSFER_NAMES
,
226 const char *st_typename_key_registrations
[MAX_NUM_TYPENAMES
];
228 static int is_typename(const char *search_key
, struct _magic_type
*type
)
231 /* We can't use a cached lookup result */
232 if (!st_strcmp_wildcard(search_key
, type
->name
)) {
233 /* The name matches */
236 for (i
= 0 ; i
< type
->num_names
; i
++) {
237 if(!st_strcmp_wildcard(search_key
, type
->names
[i
])) {
238 /* One of the typename names matches */
242 /* No match is found */
246 PUBLIC
void st_register_typename_key(const char *key
)
248 int i
, is_registered
= FALSE
;
249 for(i
= 0 ; i
< MAX_NUM_TYPENAMES
; i
++) {
250 if (st_typename_key_registrations
[i
] == NULL
) {
251 st_typename_key_registrations
[i
] = key
;
252 is_registered
= TRUE
;
256 assert(is_registered
&& "Error, number of typename registrations > MAX_NUM_TYPENAMES.\n");
259 PUBLIC
void st_register_typename_keys(const char **keys
)
262 while (keys
[i
] != NULL
) {
263 st_register_typename_key(keys
[i
]);
268 PRIVATE
void set_typename_key(struct _magic_type
*type
)
270 const char **registration
= st_typename_key_registrations
;
272 while (*registration
!= NULL
) {
273 if (is_typename(*registration
, type
)) {
274 type
->ext
= *registration
;
281 PRIVATE
void register_typenames(void)
286 /* Register typenames */
287 st_register_typename_keys(st_typename_noxfers
);
288 st_register_typename_keys(st_typename_ixfers
);
289 st_register_typename_keys(st_typename_cixfers
);
290 st_register_typename_keys(st_typename_pxfers
);
291 st_register_typename_keys(st_typename_sxfers
);
293 for(i
= 0 ; i
< _magic_types_num
; i
++) {
294 set_typename_key(&_magic_types
[i
]);
299 PRIVATE INLINE
void register_typenames_and_callbacks(void)
302 static int st_is_registered
= FALSE
;
303 if(st_is_registered
) {
307 register_typenames();
309 st_setcb_selement_transfer(st_cb_transfer_sentry_default
, ST_CB_TYPE_SENTRY
);
310 st_setcb_selement_transfer(st_cb_transfer_typename_default
, ST_CB_TYPE_TYPENAME
);
312 st_is_registered
= TRUE
;
316 PRIVATE
int st_type_name_match_any(const char **registered_type_name_keys
,
320 while (registered_type_name_keys
[i
] != NULL
) {
321 if (ST_TYPE_NAME_MATCH(registered_type_name_keys
[i
], key
)) {
329 PRIVATE
int st_sentry_name_match_any(const char **sentry_wildcard_names
,
333 while (sentry_wildcard_names
[i
] != NULL
) {
334 if (ST_SENTRY_NAME_MATCH(sentry_wildcard_names
[i
], name
)) {
342 PRIVATE
int st_dsentry_parent_name_match_any(const char **wildcard_names
,
346 while (wildcard_names
[i
] != NULL
) {
347 if (ST_DSENTRY_PARENT_NAME_MATCH(wildcard_names
[i
], name
)) {
356 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
)
358 if (ST_CB_PRINT_LEVEL(level
)) {
359 _magic_printf("[%s] %s. Current state element:\n",
360 ST_CB_LEVEL_TO_STR(level
), msg
);
361 MAGIC_SELEMENT_PRINT(selement
, MAGIC_EXPAND_TYPE_STR
);
363 MAGIC_SEL_ANALYZED_PRINT(sel_analyzed
, MAGIC_EXPAND_TYPE_STR
);
365 MAGIC_SEL_STATS_PRINT(sel_stats
);
366 _magic_printf("\n\n");
370 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
)
372 magic_selement_type_cast(selement
, ST_SEL_ANALYZE_FLAGS
,
373 new_selement_type
, sel_analyzed
, sel_stats
);
374 if (!ST_CB_FLAG(ST_CB_CHECK_ONLY
)) {
375 cb_info
->local_selement
->type
= new_local_selement_type
;
379 /* Stack management. */
381 PUBLIC
void st_stack_refs_save_restore(char* stack_buff
, int is_save
)
383 struct _magic_dsentry
*prev_dsentry
, *dsentry
;
384 struct _magic_sentry
* sentry
;
385 struct st_stack_refs_buff
*buff_ptr
;
389 extern int ST_STACK_REFS_INT_LIST
;
391 #define __X(P) ((int *)&(P))
392 int* int_ptrs
[] = { ST_STACK_REFS_INT_LIST
, ST_STACK_REFS_CUSTOM_LIST
};
395 assert((ST_STACK_REFS_NUM
) == sizeof(int_ptrs
)/sizeof(int_ptrs
[0]));
396 assert(sizeof(int) == sizeof(void*));
397 buff_ptr
= (struct st_stack_refs_buff
*) stack_buff
;
401 buff_ptr
->first_stack_dsentry
= _magic_first_stack_dsentry
;
402 buff_ptr
->last_stack_dsentry
= _magic_last_stack_dsentry
;
403 if (_magic_first_stack_dsentry
) {
404 buff_ptr
->first_stack_obdsentry_buff
= *MAGIC_OBDSENTRY_FROM_DSENTRY(_magic_first_stack_dsentry
);
406 memcpy(buff_ptr
->stack_range
, magic_stack_range
, 2*sizeof(void*));
407 for (i
= 0 ; i
< ST_STACK_REFS_NUM
; i
++) {
408 memcpy(&buff_ptr
->stack_int_refs
[i
], int_ptrs
[i
], sizeof(int));
414 if (_magic_first_dsentry
== _magic_last_stack_dsentry
) {
415 _magic_first_dsentry
= buff_ptr
->last_stack_dsentry
;
418 MAGIC_DSENTRY_ITER(_magic_first_dsentry
, prev_dsentry
, dsentry
, sentry
,
419 if (MAGIC_DSENTRY_HAS_NEXT(dsentry
)
420 && MAGIC_DSENTRY_NEXT(dsentry
) == _magic_last_stack_dsentry
) {
421 MAGIC_DSENTRY_NEXT(dsentry
) = buff_ptr
->last_stack_dsentry
;
427 _magic_first_stack_dsentry
= buff_ptr
->first_stack_dsentry
;
428 _magic_last_stack_dsentry
= buff_ptr
->last_stack_dsentry
;
429 if (_magic_first_stack_dsentry
) {
430 *MAGIC_OBDSENTRY_FROM_DSENTRY(_magic_first_stack_dsentry
) = buff_ptr
->first_stack_obdsentry_buff
;
432 memcpy(magic_stack_range
, buff_ptr
->stack_range
, 2*sizeof(void*));
433 for (i
= 0 ; i
< ST_STACK_REFS_NUM
; i
++) {
434 memcpy(int_ptrs
[i
], &buff_ptr
->stack_int_refs
[i
], sizeof(int));
438 /* Metadata management. */
439 PUBLIC
int st_add_special_mmapped_region(void *address
, size_t size
,
442 struct _magic_obdsentry
* obdsentry
;
445 if (!_magic_enabled
) return OK
;
448 snprintf(addr_name
, sizeof(addr_name
), "%%MMAP_0x%08x",
449 (unsigned int) address
);
452 obdsentry
= magic_create_obdsentry(address
, MAGIC_VOID_TYPE
,
453 size
, MAGIC_STATE_MAP
, name
, NULL
);
454 return obdsentry
? OK
: EINVAL
;
457 PUBLIC
int st_del_special_mmapped_region_by_addr(void *address
)
461 if (!_magic_enabled
) return OK
;
463 ret
= magic_destroy_obdsentry_by_addr(address
);
470 /* Selement transfer callbacks. */
472 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
)
474 /* Do nothing for complex type. process only its members, not the complex type itself */
475 return MAGIC_SENTRY_ANALYZE_CONTINUE
;
478 PRIVATE INLINE
int transfer_try_raw_copy_sel_cb(_magic_selement_t
*selement
, struct st_cb_info
*cb_info
)
480 /* Only do raw copying if there are no type transformations. */
481 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 memcpy(cb_info
->local_selement
->address
, selement
->address
, cb_info
->local_selement
->type
->size
);
483 return MAGIC_SENTRY_ANALYZE_SKIP_PATH
;
486 return MAGIC_SENTRY_ANALYZE_CONTINUE
;
489 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
)
491 if (!ST_CB_FLAG(ST_CB_CHECK_ONLY
)) {
492 /* First try to do raw copying, assuming there are no type transformations. */
493 if (transfer_try_raw_copy_sel_cb(selement
, cb_info
) == MAGIC_SENTRY_ANALYZE_SKIP_PATH
)
494 return MAGIC_SENTRY_ANALYZE_SKIP_PATH
;
496 #if CHECK_ASR && !FORCE_SOME_UNPAIRED_TYPES
497 if (cb_info
->init_info
->flags
& ST_LU_ASR
) {
498 st_cbs_os
.panic("ASR should never get here!");
501 if (selement
->type
->type_id
== MAGIC_TYPE_UNION
) {
502 ST_CB_PRINT(ST_CB_ERR
, "uncaught ixfer union with type changes", selement
, sel_analyzed
, sel_stats
, cb_info
);
505 cb_info
->st_cb_flags
|= ST_CB_FORCE_IXFER
;
506 return MAGIC_SENTRY_ANALYZE_CONTINUE
;
508 return MAGIC_SENTRY_ANALYZE_SKIP_PATH
;
511 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
)
514 int saved_flags
= cb_info
->st_cb_flags
;
515 cb_info
->st_cb_flags
&= ~ST_CB_PRINT_ERR
;
516 r
= default_transfer_selement_sel_cb(selement
, sel_analyzed
, sel_stats
, cb_info
);
517 cb_info
->st_cb_flags
= saved_flags
;
519 ST_CB_PRINT(ST_CB_DBG
, "conditional ixfer resorting to ixfer", selement
, sel_analyzed
, sel_stats
, cb_info
);
520 return transfer_identity_sel_cb(selement
, sel_analyzed
, sel_stats
, cb_info
);
525 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
)
527 if (sel_analyzed
->flags
& MAGIC_SEL_FOUND_VIOLATIONS
) {
528 ST_CB_PRINT(ST_CB_ERR
, "uncaught non-ptr with violations", selement
, sel_analyzed
, sel_stats
, cb_info
);
531 return transfer_identity_sel_cb(selement
, sel_analyzed
, sel_stats
, cb_info
);
534 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
)
536 int trg_flags
, trg_extf_flags
, trg_transferred
, trg_paired
;
537 _magic_selement_t cached_trg_selement
, local_trg_selement
;
538 void **local_selement_address
= cb_info
->local_selement
->address
;
541 r
= lookup_trg_info(selement
, sel_analyzed
, sel_stats
, cb_info
, &cached_trg_selement
, &local_trg_selement
);
546 trg_flags
= sel_analyzed
->u
.ptr
.trg_flags
;
547 trg_extf_flags
= MAGIC_STATE_FLAGS_TO_EXTF(trg_flags
);
548 trg_transferred
= (trg_extf_flags
& (ST_NEEDS_TRANSFER
| ST_TRANSFER_DONE
));
549 trg_paired
= (local_trg_selement
.type
!= NULL
);
551 if (!trg_transferred
&& trg_paired
&& (trg_extf_flags
& ST_ON_PTRXFER_CASCADE
)) {
552 /* Propagate transfer on the target. */
553 if (cached_trg_selement
.sentry
&& !(trg_extf_flags
& ST_NEEDS_TRANSFER
)) {
554 ST_CB_PRINT(ST_CB_DBG
, "ptr lookup results in cascade transfer for the target", selement
, sel_analyzed
, sel_stats
, cb_info
);
555 st_set_status_by_sentry_id(ST_NEEDS_TRANSFER
, ST_OP_ADD
, MAGIC_SENTRY_ID(cached_trg_selement
.sentry
));
557 /* Force code below to transfer the pointer normally. */
558 trg_transferred
= TRUE
;
561 if (trg_transferred
&& trg_paired
) {
562 *local_selement_address
= local_trg_selement
.address
;
564 else if (trg_extf_flags
& ST_ON_PTRXFER_SET_NULL
) {
565 ST_CB_PRINT(ST_CB_DBG
, "ptr lookup results in forcefully setting ptr to NULL", selement
, sel_analyzed
, sel_stats
, cb_info
);
566 *local_selement_address
= NULL
;
568 else if(trg_extf_flags
& ST_ON_PTRXFER_SET_DEFAULT
) {
569 ST_CB_PRINT(ST_CB_DBG
, "ptr lookup results in forcefully setting ptr to default value", selement
, sel_analyzed
, sel_stats
, cb_info
);
570 if (trg_flags
& MAGIC_STATE_STRING
) {
571 *((char**)local_selement_address
) = __UNCONST("");
574 *local_selement_address
= NULL
;
577 else if (trg_extf_flags
& ST_ON_PTRXFER_SKIP
) {
578 ST_CB_PRINT(ST_CB_DBG
, "ptr lookup results in skipping ptr transfer", selement
, sel_analyzed
, sel_stats
, cb_info
);
582 ST_CB_PRINT(ST_CB_ERR
, "uncaught ptr lookup for non-transferred target", selement
, sel_analyzed
, sel_stats
, cb_info
);
585 ST_CB_PRINT(ST_CB_ERR
, "uncaught ptr lookup for unpaired target", selement
, sel_analyzed
, sel_stats
, cb_info
);
587 #if DO_SKIP_UNPAIRED_PTR_TARGETS
588 return MAGIC_SENTRY_ANALYZE_SKIP_PATH
;
594 return MAGIC_SENTRY_ANALYZE_SKIP_PATH
;
597 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
)
599 const struct _magic_type
*first_trg_type
;
600 if (selement
->type
->type_id
!= MAGIC_TYPE_POINTER
) {
601 if (selement
->type
->size
!= sizeof(void*)) {
602 ST_CB_PRINT(ST_CB_ERR
, "wrong pointer size", selement
, sel_analyzed
, sel_stats
, cb_info
);
605 ST_CB_PRINT(ST_CB_DBG
, "casting non-ptr to ptr element", selement
, sel_analyzed
, sel_stats
, cb_info
);
606 st_cb_selement_type_cast(MAGIC_VOID_PTR_INT_CAST_TYPE
, MAGIC_VOID_PTR_INT_CAST_TYPE
, selement
, sel_analyzed
, sel_stats
, cb_info
);
608 first_trg_type
= MAGIC_SEL_ANALYZED_PTR_FIRST_TRG_TYPE(sel_analyzed
);
609 if (first_trg_type
== MAGIC_TYPE_NULL_ENTRY
610 || first_trg_type
== MAGIC_TYPE_VALUE_FOUND
) {
612 /* NULL pointer or special value. Don't adjust value */
613 return transfer_identity_sel_cb(selement
, sel_analyzed
, sel_stats
, cb_info
);
615 } else if (!(sel_analyzed
->flags
& MAGIC_SEL_FOUND_VIOLATIONS
)) {
616 /* Valid pointer found */
617 if (!ST_CB_FLAG(ST_CB_CHECK_ONLY
)) {
618 return transfer_ptr_sel_with_trg_cb(selement
, sel_analyzed
, sel_stats
, cb_info
);
621 return MAGIC_SENTRY_ANALYZE_SKIP_PATH
;
623 } else if(MAGIC_STATE_FLAG(selement
->sentry
, MAGIC_STATE_STACK
)) {
624 struct _magic_sentry
*trg_sentry
= magic_sentry_lookup_by_range(sel_analyzed
->u
.ptr
.value
, NULL
);
625 if (trg_sentry
&& !strcmp(trg_sentry
->name
, MAGIC_ALLOC_INITIAL_STACK_NAME
)) {
626 /* Stack pointer to initial stack area. This is common (e.g., argv).
627 * We can safely assume the pointer will be already correctly
628 * initialized in the new version and simply skip transfer.
630 ST_CB_PRINT(ST_CB_DBG
, "skipping stack ptr element pointing to initial stack area", selement
, sel_analyzed
, sel_stats
, cb_info
);
631 return MAGIC_SENTRY_ANALYZE_SKIP_PATH
;
635 #define IS_KERNEL_PTR(p) (((intptr_t)(p) & 0xf0000000) == 0xf0000000) /* TODO: make this more dynamic */
636 else if (IS_KERNEL_PTR(sel_analyzed
->u
.ptr
.value
))
637 return MAGIC_SENTRY_ANALYZE_SKIP_PATH
; /* Kernel-mapped pointer */
640 /* Pointer with violations found */
641 ST_CB_PRINT(ST_CB_ERR
, "uncaught ptr with violations", selement
, sel_analyzed
, sel_stats
, cb_info
);
642 #if DO_SKIP_INVARIANTS_VIOLATIONS
643 return MAGIC_SENTRY_ANALYZE_SKIP_PATH
;
649 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
)
651 static int st_counter
= 0;
652 unsigned parent_offset
, offset
;
655 if (selement
->type
->type_id
!= MAGIC_TYPE_UNION
&& selement
->type
->type_id
!= MAGIC_TYPE_STRUCT
) {
656 ST_CB_PRINT(ST_CB_ERR
, "struct transfer is only for structs and unions!", selement
, sel_analyzed
, sel_stats
, cb_info
);
659 if (selement
->type
->type_id
== MAGIC_TYPE_STRUCT
|| st_counter
> 0) {
660 return MAGIC_SENTRY_ANALYZE_CONTINUE
;
663 /* Walk the union as a struct. */
664 walk_flags
= cb_info
->walk_flags
;
665 cb_info
->walk_flags
= (MAGIC_TYPE_WALK_DEFAULT_FLAGS
& (~MAGIC_TYPE_WALK_UNIONS_AS_VOID
));
667 parent_offset
= (unsigned)selement
->parent_address
- (unsigned)selement
->sentry
->address
;
668 offset
= (unsigned)selement
->address
- (unsigned)selement
->sentry
->address
;
669 ret
= magic_type_walk_flags(selement
->parent_type
, parent_offset
,
670 selement
->child_num
, selement
->type
, offset
,
671 0, ULONG_MAX
, magic_type_analyzer_cb
, selement
->cb_args
, cb_info
->walk_flags
);
673 cb_info
->walk_flags
= walk_flags
;
675 return ret
== MAGIC_TYPE_WALK_STOP
? MAGIC_SENTRY_ANALYZE_STOP
: ret
;
678 return MAGIC_SENTRY_ANALYZE_SKIP_PATH
;
681 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
)
683 /* Default handler for walkable, ptr and nonptr types. */
684 #if ST_TRANSFER_IDENTITY_FOR_NO_INNER_PTRS
685 if (MAGIC_TYPE_FLAG(selement
->type
, MAGIC_TYPE_NO_INNER_PTRS
)) {
686 /* If the type has no inner pointers, try to do raw copying. */
687 if (transfer_try_raw_copy_sel_cb(selement
, cb_info
) == MAGIC_SENTRY_ANALYZE_SKIP_PATH
)
688 return MAGIC_SENTRY_ANALYZE_SKIP_PATH
;
691 if (selement
->type
->type_id
== MAGIC_TYPE_UNION
) {
692 if (!(st_policies
& ST_IXFER_UNCAUGHT_UNIONS
) && !MAGIC_TYPE_FLAG(selement
->type
, MAGIC_TYPE_NO_INNER_PTRS
)) {
693 ST_CB_PRINT(ST_CB_ERR
, "uncaught union", selement
, sel_analyzed
, sel_stats
, cb_info
);
697 int level
= (st_policies
& ST_REPORT_UNCAUGHT_UNIONS
) ? ST_CB_ERR
: ST_CB_DBG
;
698 ST_CB_PRINT(level
, "uncaught union", selement
, sel_analyzed
, sel_stats
, cb_info
);
699 return transfer_identity_sel_cb(selement
, sel_analyzed
, sel_stats
, cb_info
);
701 } else if (MAGIC_TYPE_IS_WALKABLE(selement
->type
)) {
702 return transfer_walkable_sel_cb(selement
, sel_analyzed
, sel_stats
, cb_info
);
703 } else if (selement
->type
->type_id
== MAGIC_TYPE_POINTER
) {
704 return transfer_ptr_sel_cb(selement
, sel_analyzed
, sel_stats
, cb_info
);
706 return transfer_nonptr_sel_cb(selement
, sel_analyzed
, sel_stats
, cb_info
);
710 ST_CB_PRINT(ST_CB_ERR
, "Bug!", selement
, sel_analyzed
, sel_stats
, cb_info
);
714 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
)
716 const char *sentry_name
= selement
->sentry
->name
;
718 #if ST_ASSUME_RAW_COPY_BEFORE_TRANSFER
719 if (MAGIC_STATE_FLAGS(selement
->sentry
, MAGIC_STATE_DYNAMIC
)) {
720 if (MAGIC_STATE_FLAG(selement
->sentry
, MAGIC_STATE_LIB
) || MAGIC_SENTRY_IS_EXT_ALLOC(selement
->sentry
))
721 return MAGIC_SENTRY_ANALYZE_SKIP_PATH
;
725 if (ST_SENTRY_NAME_MATCH_ANY(st_sentryname_ixfers
, sentry_name
)) {
726 ST_CB_PRINT(ST_CB_DBG
, "sentry name matches ixfer", selement
, sel_analyzed
, sel_stats
, cb_info
);
727 return transfer_identity_sel_cb(selement
, sel_analyzed
, sel_stats
, cb_info
);
730 if (ST_SENTRY_NAME_MATCH_ANY(st_sentryname_cixfers
, sentry_name
)) {
731 ST_CB_PRINT(ST_CB_DBG
, "sentry name matches cixfer", selement
, sel_analyzed
, sel_stats
, cb_info
);
732 return transfer_cond_identity_sel_cb(selement
, sel_analyzed
, sel_stats
, cb_info
);
735 if (ST_SENTRY_NAME_MATCH_ANY(st_sentryname_noxfers
, sentry_name
)) {
736 ST_CB_PRINT(ST_CB_DBG
, "sentry name matches noxfer", selement
, sel_analyzed
, sel_stats
, cb_info
);
737 return MAGIC_SENTRY_ANALYZE_SKIP_PATH
;
740 /* Skip memory management related sentries only when memory functions have
741 * been instrumented (which is *not* the case for the MINIX3 VM service).
743 if (_magic_no_mem_inst
== 0 && ST_SENTRY_NAME_MATCH_ANY(st_sentryname_noxfers_mem
, sentry_name
)) {
744 ST_CB_PRINT(ST_CB_DBG
, "sentry name matches noxfer", selement
, sel_analyzed
, sel_stats
, cb_info
);
745 return MAGIC_SENTRY_ANALYZE_SKIP_PATH
;
748 if (ST_SENTRY_NAME_MATCH_ANY(st_sentryname_pxfers
, sentry_name
)) {
749 ST_CB_PRINT(ST_CB_DBG
, "sentry name matches pxfer", selement
, sel_analyzed
, sel_stats
, cb_info
);
750 return transfer_ptr_sel_cb(selement
, sel_analyzed
, sel_stats
, cb_info
);
753 if (MAGIC_STATE_FLAGS(selement
->sentry
, MAGIC_STATE_DYNAMIC
| MAGIC_STATE_MAP
| MAGIC_STATE_LIB
)) {
754 struct _magic_dsentry
*dsentry
= MAGIC_DSENTRY_FROM_SENTRY(selement
->sentry
);
755 if (ST_DSENTRY_PARENT_NAME_MATCH_ANY(st_dsentry_lib_noxfer
, dsentry
->parent_name
)) {
756 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 return MAGIC_SENTRY_ANALYZE_SKIP_PATH
;
761 return ST_CB_NOT_PROCESSED
;
764 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
)
766 const char *typename_key
= ST_TYPE_NAME_KEY(selement
->type
);
767 if (ST_TYPE_NAME_MATCH_ANY(st_typename_ixfers
, typename_key
)) {
768 return transfer_identity_sel_cb(selement
, sel_analyzed
, sel_stats
, cb_info
);
771 if (ST_TYPE_NAME_MATCH_ANY(st_typename_cixfers
, typename_key
)) {
772 return transfer_cond_identity_sel_cb(selement
, sel_analyzed
, sel_stats
, cb_info
);
775 if (ST_TYPE_NAME_MATCH_ANY(st_typename_noxfers
, typename_key
)) {
776 return MAGIC_SENTRY_ANALYZE_SKIP_PATH
;
779 if (ST_TYPE_NAME_MATCH_ANY(st_typename_pxfers
, typename_key
)) {
780 return transfer_ptr_sel_cb(selement
, sel_analyzed
, sel_stats
, cb_info
);
783 if (ST_TYPE_NAME_MATCH_ANY(st_typename_sxfers
, typename_key
)) {
784 return transfer_struct_sel_cb(selement
, sel_analyzed
, sel_stats
, cb_info
);
787 return ST_CB_NOT_PROCESSED
;
790 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
)
792 return transfer_walkable_sel_cb(selement
, sel_analyzed
, sel_stats
, cb_info
);
795 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
)
797 return transfer_ptr_sel_cb(selement
, sel_analyzed
, sel_stats
, cb_info
);
800 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
)
802 return transfer_identity_sel_cb(selement
, sel_analyzed
, sel_stats
, cb_info
);
805 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
)
807 return transfer_cond_identity_sel_cb(selement
, sel_analyzed
, sel_stats
, cb_info
);
810 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
)
812 return transfer_nonptr_sel_cb(selement
, sel_analyzed
, sel_stats
, cb_info
);
815 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
)
817 return transfer_struct_sel_cb(selement
, sel_analyzed
, sel_stats
, cb_info
);
820 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
)
822 return default_transfer_selement_sel_cb(selement
, sel_analyzed
, sel_stats
, cb_info
);
825 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
)
827 return transfer_data_selement(selement
, sel_analyzed
, sel_stats
, cb_info
);
830 /* Selement mapping functions and callbacks. */
832 PRIVATE
int st_map_selement_from_sentry_cb(const struct _magic_type
* parent_type
,
833 const unsigned parent_offset
, int child_num
,
834 const struct _magic_type
* type
, const unsigned offset
, int depth
, void* cb_args
)
836 void **args_array
= (void**) cb_args
;
837 _magic_selement_t cached_selement
;
838 _magic_selement_t
*local_selement
= (_magic_selement_t
*) args_array
[1];
839 _magic_selement_t
*selement
= (_magic_selement_t
*) args_array
[0];
840 struct _magic_sentry
*sentry
= selement
->sentry
;
841 void *address
= (char*)sentry
->address
+ offset
;
842 void *selement_address
= selement
->address
;
844 struct st_cb_info
*cb_info
;
845 if ((char*) selement_address
>= ((char*) address
+ type
->size
)) {
846 return MAGIC_TYPE_WALK_SKIP_PATH
;
848 cb_info
= (struct st_cb_info
*) args_array
[2];
849 is_trg_mapping
= (int) args_array
[3];
850 cached_selement
.sentry
= sentry
;
851 cached_selement
.parent_type
= parent_type
;
852 cached_selement
.parent_address
= (char*)sentry
->address
+ parent_offset
;
853 cached_selement
.child_num
= child_num
;
854 cached_selement
.type
= type
;
855 cached_selement
.address
= address
;
856 cached_selement
.depth
= depth
;
857 st_map_selement(&cached_selement
, local_selement
, cb_info
, is_trg_mapping
);
858 if (local_selement
->type
== NULL
) {
861 if (address
== selement_address
&& type
== selement
->type
) {
862 return MAGIC_TYPE_WALK_STOP
;
864 if (type
->num_child_types
== 0) {
867 local_selement
->parent_type
= local_selement
->type
;
868 local_selement
->parent_address
= local_selement
->address
;
869 return MAGIC_TYPE_WALK_CONTINUE
;
872 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
)
877 max_offset
= (unsigned) ( (char *)cached_selement
->address
- (char *)cached_selement
->sentry
->address
);
878 args_array
[0] = cached_selement
;
879 args_array
[1] = magic_selement_from_sentry(local_sentry
, local_selement
);
880 args_array
[2] = cb_info
;
881 args_array
[3] = (void*) is_trg_mapping
;
882 r
= magic_type_walk_root(cached_selement
->sentry
->type
, 0, max_offset
, st_map_selement_from_sentry_cb
, (void*) args_array
);
885 local_selement
->type
= NULL
;
889 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
)
891 _magic_selement_t
*csel
, *lsel
;
892 assert(local_trg_sentry
|| local_trg_function
);
893 assert(cached_sel_analyzed
->type_id
== MAGIC_TYPE_POINTER
);
894 assert(cached_sel_analyzed
->u
.ptr
.first_legal_trg_type
>=0);
895 local_sel_analyzed
->type_id
= cached_sel_analyzed
->type_id
;
896 local_sel_analyzed
->num
= cached_sel_analyzed
->num
;
897 local_sel_analyzed
->flags
= cached_sel_analyzed
->flags
;
898 local_sel_analyzed
->u
.ptr
.trg_flags
= local_trg_sentry
? local_trg_sentry
->flags
: local_trg_function
->flags
;
899 local_sel_analyzed
->u
.ptr
.first_legal_trg_type
= -1;
900 local_sel_analyzed
->u
.ptr
.num_legal_trg_types
= 0;
901 if (local_trg_function
) {
902 assert(cached_sel_analyzed
->u
.ptr
.num_legal_trg_types
== 1);
903 lsel
= &local_sel_analyzed
->u
.ptr
.trg_selements
[0];
904 memset(lsel
, 0, sizeof(_magic_selement_t
));
906 lsel
->type
= local_trg_function
->type
;
907 lsel
->address
= local_trg_function
->address
;
908 local_sel_analyzed
->u
.ptr
.num_trg_types
= 1;
912 void *address
= NULL
;
913 local_sel_analyzed
->u
.ptr
.num_trg_types
= 0;
914 for (i
= cached_sel_analyzed
->u
.ptr
.first_legal_trg_type
; i
< cached_sel_analyzed
->u
.ptr
.num_trg_types
; i
++) {
915 _magic_trg_stats_t trg_stats
= cached_sel_analyzed
->u
.ptr
.trg_stats
[i
];
916 if (MAGIC_SEL_ANALYZED_TRG_STATS_HAS_VIOLATIONS(trg_stats
)) {
919 csel
= &cached_sel_analyzed
->u
.ptr
.trg_selements
[i
];
920 lsel
= &local_sel_analyzed
->u
.ptr
.trg_selements
[local_sel_analyzed
->u
.ptr
.num_trg_types
++];
921 st_map_selement_from_sentry(csel
, lsel
, local_trg_sentry
, cb_info
, TRUE
);
922 if (lsel
->type
== NULL
|| (address
&& lsel
->address
!= address
)) {
923 /* Unpaired selement or ambiguous local address. */
924 local_sel_analyzed
->u
.ptr
.num_trg_types
= 0;
927 address
= lsel
->address
;
929 assert(local_sel_analyzed
->u
.ptr
.num_trg_types
> 0);
933 PUBLIC
void st_map_local_selement_from_child_num(_magic_selement_t
*local_selement
, struct st_cb_info
*cb_info
, int child_num
)
935 local_selement
->child_num
= child_num
;
936 magic_selement_fill_from_parent_info(local_selement
, cb_info
->walk_flags
);
939 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
)
941 int cached_num_elements
, local_num_elements
, is_trg_at_array_end
, is_trg_at_str_end
;
942 /* Match arrays/vectors with arrays/vectors. */
943 assert(cached_selement
->parent_type
->type_id
== MAGIC_TYPE_ARRAY
|| cached_selement
->parent_type
->type_id
== MAGIC_TYPE_VECTOR
);
944 if (local_selement
->parent_type
->type_id
!= MAGIC_TYPE_ARRAY
&& local_selement
->parent_type
->type_id
!= MAGIC_TYPE_VECTOR
) {
945 local_selement
->type
= NULL
;
948 cached_num_elements
= cached_selement
->parent_type
->num_child_types
;
949 local_num_elements
= local_selement
->parent_type
->num_child_types
;
950 /* Same size or first child? We are done. */
951 if (cached_num_elements
== local_num_elements
|| local_selement
->child_num
== 0) {
952 st_map_local_selement_from_child_num(local_selement
, cb_info
, cached_selement
->child_num
);
955 assert(local_num_elements
> 0);
956 is_trg_at_str_end
= FALSE
;
957 is_trg_at_array_end
= FALSE
;
958 if (is_trg_mapping
&& cached_selement
->child_num
== cached_num_elements
-1) {
959 is_trg_at_str_end
= MAGIC_SENTRY_IS_STRING(cached_selement
->sentry
) || MAGIC_SENTRY_IS_STRING(local_selement
->sentry
);
960 is_trg_at_array_end
= !is_trg_at_str_end
;
962 if (is_trg_at_array_end
&& (st_policies
& ST_DEFAULT_MAP_GUARD_PTRS_TO_ARRAY_END
)) {
963 /* 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 st_map_local_selement_from_child_num(local_selement
, cb_info
, local_num_elements
-1);
966 else if (is_trg_at_str_end
&& (st_policies
& ST_DEFAULT_MAP_GUARD_PTRS_TO_STR_END
)) {
967 /* 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 st_map_local_selement_from_child_num(local_selement
, cb_info
, local_num_elements
-1);
970 else if (cached_selement
->child_num
>= local_num_elements
) {
971 /* New array got truncated and this element is gone. */
972 local_selement
->type
= NULL
;
975 /* New array is bigger, just keep the original position in the array. */
976 st_map_local_selement_from_child_num(local_selement
, cb_info
, cached_selement
->child_num
);
980 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
)
982 size_t cached_size
= cached_selement
->type
->num_child_types
, local_size
= local_selement
->type
->num_child_types
;
984 /* Match arrays/vectors with arrays/vectors. */
985 assert(cached_selement
->type
->type_id
== MAGIC_TYPE_ARRAY
|| cached_selement
->type
->type_id
== MAGIC_TYPE_VECTOR
);
986 if (local_selement
->type
->type_id
!= MAGIC_TYPE_ARRAY
&& local_selement
->type
->type_id
!= MAGIC_TYPE_VECTOR
) {
987 local_selement
->type
= NULL
;
991 /* Varsized arrays have to be consistent across versions. */
992 if (MAGIC_TYPE_FLAG(cached_selement
->type
, MAGIC_TYPE_VARSIZE
) != MAGIC_TYPE_FLAG(local_selement
->type
, MAGIC_TYPE_VARSIZE
)) {
993 local_selement
->type
= NULL
;
998 if (cached_size
!= local_size
) {
1000 int is_string
= MAGIC_SENTRY_IS_STRING(cached_selement
->sentry
) || MAGIC_SENTRY_IS_STRING(local_selement
->sentry
);
1001 if (local_size
< cached_size
) {
1002 report
= is_string
? (st_policies
& ST_REPORT_SMALLER_STRINGS
) : (st_policies
& ST_REPORT_SMALLER_ARRAYS
);
1005 report
= is_string
? (st_policies
& ST_REPORT_LARGER_STRINGS
) : (st_policies
& ST_REPORT_LARGER_ARRAYS
);
1009 printf("st_cb_map_child_array_selement_generic: %s size found while mapping array selements:\n", local_size
< cached_size
? "Smaller" : "Larger");
1010 MAGIC_SELEMENT_PRINT(cached_selement
, MAGIC_EXPAND_TYPE_STR
); printf("\n");
1011 MAGIC_SELEMENT_PRINT(local_selement
, MAGIC_EXPAND_TYPE_STR
); printf("\n");
1016 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
)
1018 /* This should only be called in case of unions transferred as structs. */
1019 st_cb_map_from_parent_struct_selement_generic(cached_selement
, local_selement
, cb_info
, is_trg_mapping
);
1022 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
)
1024 /* Match unions just like structs. */
1025 st_cb_map_child_struct_selement_generic(cached_selement
, local_selement
, cb_info
, is_trg_mapping
);
1028 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
)
1031 const char *cached_member_name
;
1032 /* Match struct/unions with struct/unions. */
1033 assert(cached_selement
->parent_type
->type_id
== MAGIC_TYPE_STRUCT
|| cached_selement
->parent_type
->type_id
== MAGIC_TYPE_UNION
);
1034 if (local_selement
->parent_type
->type_id
!= MAGIC_TYPE_STRUCT
&& local_selement
->parent_type
->type_id
!= MAGIC_TYPE_UNION
) {
1035 local_selement
->type
= NULL
;
1038 /* Match struct/unions members by name. */
1039 cached_member_name
= cached_selement
->parent_type
->member_names
[cached_selement
->child_num
];
1040 for (i
= 0 ; i
< local_selement
->parent_type
->num_child_types
; i
++) {
1041 if (!strcmp(local_selement
->parent_type
->member_names
[i
], cached_member_name
)) {
1042 st_map_local_selement_from_child_num(local_selement
, cb_info
, i
);
1046 local_selement
->type
= NULL
;
1049 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
)
1052 const struct _magic_type
*cached_type
= cached_selement
->type
;
1053 const struct _magic_type
*local_type
= local_selement
->type
;
1054 assert(cached_type
->type_id
== MAGIC_TYPE_STRUCT
|| cached_type
->type_id
== MAGIC_TYPE_UNION
);
1055 if (local_type
->type_id
!= MAGIC_TYPE_STRUCT
&& local_type
->type_id
!= MAGIC_TYPE_UNION
) {
1056 local_selement
->type
= NULL
;
1059 /* Match struct/unions by name(s). */
1060 if (!strcmp(cached_type
->name
, local_type
->name
)) {
1063 if (cached_type
->num_names
> 1 || local_type
->num_names
> 1 ) {
1064 for (i
= 0 ; i
< cached_type
->num_names
; i
++) {
1065 for (j
= 0 ; j
< local_type
->num_names
; j
++) {
1066 if (!strcmp(cached_type
->names
[i
], local_type
->names
[j
])) {
1073 local_selement
->type
= NULL
;
1076 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
)
1079 static char magic_value_buffer
[32];
1081 r
= magic_selement_value_cast(cached_selement
, local_selement
, magic_value_buffer
);
1085 if (r
< 0 && r
!= MAGIC_ERANGE
&& r
!= MAGIC_ESIGN
) {
1086 local_selement
->type
= NULL
;
1089 if ((r
== MAGIC_ERANGE
&& (st_policies
& ST_REPORT_PRECISION_LOSS
))
1090 || (r
== MAGIC_ESIGN
&& (st_policies
& ST_REPORT_SIGN_CHANGE
))) {
1091 _magic_selement_t converted_selement
= *cached_selement
;
1092 converted_selement
.address
= magic_value_buffer
;
1093 converted_selement
.type
= local_selement
->type
;
1094 printf("st_cb_map_child_nonaggr_selement_generic: %s while mapping non-aggregate selements:\n", r
== MAGIC_ERANGE
? "Precision loss" : "Sign change");
1095 MAGIC_SELEMENT_PRINT(cached_selement
, MAGIC_EXPAND_TYPE_STR
); printf("\n");
1096 MAGIC_SELEMENT_PRINT(local_selement
, MAGIC_EXPAND_TYPE_STR
); printf("\n");
1097 printf(" - ORIGINAL VALUE: "); magic_selement_print_value(cached_selement
); printf("\n");
1098 printf(" - MAPPED VALUE: "); magic_selement_print_value(&converted_selement
); printf("\n");
1100 cached_selement
->address
= magic_value_buffer
;
1103 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
)
1105 assert(cached_selement
->parent_type
&& local_selement
->parent_type
);
1106 switch(cached_selement
->parent_type
->type_id
) {
1107 case MAGIC_TYPE_ARRAY
:
1108 case MAGIC_TYPE_VECTOR
:
1109 st_cb_map_from_parent_array_selement_generic(cached_selement
, local_selement
, cb_info
, is_trg_mapping
);
1112 case MAGIC_TYPE_UNION
:
1113 st_cb_map_from_parent_union_selement_generic(cached_selement
, local_selement
, cb_info
, is_trg_mapping
);
1116 case MAGIC_TYPE_STRUCT
:
1117 st_cb_map_from_parent_struct_selement_generic(cached_selement
, local_selement
, cb_info
, is_trg_mapping
);
1121 st_cbs_os
.panic("Invalid parent type!");
1126 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
)
1128 assert(cached_selement
->type
);
1129 if (local_selement
->type
== NULL
) {
1132 if (cached_selement
->type
->num_child_types
== 0 || cached_selement
->type
->type_id
== MAGIC_TYPE_POINTER
) {
1133 st_cb_map_child_nonaggr_selement_generic(cached_selement
, local_selement
, cb_info
, is_trg_mapping
);
1136 switch (cached_selement
->type
->type_id
) {
1137 case MAGIC_TYPE_ARRAY
:
1138 case MAGIC_TYPE_VECTOR
:
1139 st_cb_map_child_array_selement_generic(cached_selement
, local_selement
, cb_info
, is_trg_mapping
);
1142 case MAGIC_TYPE_UNION
:
1143 st_cb_map_child_union_selement_generic(cached_selement
, local_selement
, cb_info
, is_trg_mapping
);
1146 case MAGIC_TYPE_STRUCT
:
1147 st_cb_map_child_struct_selement_generic(cached_selement
, local_selement
, cb_info
, is_trg_mapping
);
1151 st_cbs_os
.panic("Invalid parent type!");
1157 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
)
1160 assert(cached_selement
->type
->type_id
!= MAGIC_TYPE_FUNCTION
);
1161 for (i
= 0 ; i
< MAGIC_ST_TYPE_TRANS_ITERATIONS
; i
++) {
1162 if (cached_selement
->parent_type
) {
1163 st_cb_map_from_parent_selement_generic(cached_selement
, local_selement
, cb_info
, is_trg_mapping
);
1165 st_cb_map_child_selement_generic(cached_selement
, local_selement
, cb_info
, is_trg_mapping
);
1169 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
)
1171 const struct _magic_type
*cached_parent_type
= cached_selement
->parent_type
;
1172 const struct _magic_type
*local_parent_type
= local_selement
->parent_type
;
1173 const struct _magic_type
*cached_type
= cached_selement
->type
;
1175 if (cached_parent_type
) {
1176 if (cached_parent_type
== local_parent_type
) {
1177 /* Quickly propagate perfect type pairs from parents. */
1178 local_selement
->address
= (char *)local_selement
->parent_address
+ ((char *)cached_selement
->address
- (char *)cached_selement
->parent_address
);
1179 local_selement
->type
= cached_type
;
1182 else if (ST_TYPE_IS_CACHED_COUNTERPART(cached_parent_type
, local_parent_type
)) {
1183 /* Quickly propagate type pairs from parents. */
1184 st_map_local_selement_from_child_num(local_selement
, cb_info
, cached_selement
->child_num
);
1188 local_selement
->type
= NULL
;
1192 /* 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 if (ST_TYPE_IS_CACHED_COUNTERPART(cached_type
, local_selement
->type
)) {
1194 if (is_trg_mapping
) local_selement
->type
= cached_type
;
1198 #if CHECK_ASR && !FORCE_SOME_UNPAIRED_TYPES
1199 if (cb_info
->init_info
->flags
& ST_LU_ASR
) {
1200 st_cbs_os
.panic("ASR should never get here!");
1204 st_num_type_transformations
++;
1205 st_cbs
.st_cb_selement_map(cached_selement
, local_selement
, cb_info
, is_trg_mapping
);
1207 /* Check again for paired types and add a perfect type pair to speed up subsequent lookups in case of target mapping. */
1208 if (is_trg_mapping
&& local_selement
->type
!= NULL
&& local_selement
->type
!= cached_selement
->type
) {
1209 if (ST_TYPE_IS_CACHED_COUNTERPART(cached_selement
->type
, local_selement
->type
)) {
1210 local_selement
->type
= cached_selement
->type
;
1215 /* main functions */
1217 PUBLIC
int st_state_transfer(st_init_info_t
*info
)
1222 * Set all OS dependent callbacks first.
1224 st_setcb_os_all(&info
->st_cbs_os
);
1226 #if ST_ASSUME_RAW_COPY_BEFORE_TRANSFER
1227 _magic_vars
->fake_malloc
= 1;
1232 #if ST_ASSUME_RAW_COPY_BEFORE_TRANSFER
1233 _magic_vars
->fake_malloc
= 0;
1240 r
= st_data_transfer(info
);
1245 #if ST_DEBUG_LEVEL > 0
1246 printf("st_state_transfer: state transfer is done, num type transformations: %u.\n", st_num_type_transformations
);
1254 #if APPARENTLY_UNUSED
1255 PUBLIC
void st_set_policies(int policies
)
1257 st_policies
= policies
;
1261 #if MAGIC_LOOKUP_SENTRY_ALLOW_RANGE_INDEX
1262 PRIVATE
void st_init_rl_index(st_init_info_t
*info
,
1263 struct _magic_vars_t
*magic_vars
)
1268 EXEC_WITH_MAGIC_VARS(
1269 buff_size
= magic_sentry_rl_estimate_index_buff_size(0);
1272 buff
= st_buff_allocate(info
, buff_size
);
1274 EXEC_WITH_MAGIC_VARS(
1275 magic_sentry_rl_build_index(buff
, buff_size
);
1280 PRIVATE
void st_cleanup_rl_index(st_init_info_t
*info
,
1281 struct _magic_vars_t
*magic_vars
)
1283 EXEC_WITH_MAGIC_VARS(
1284 magic_sentry_rl_destroy_index();
1290 #if MAGIC_LOOKUP_SENTRY_ALLOW_NAME_HASH
1291 PRIVATE
void st_init_sentry_hash(st_init_info_t
*info
,
1292 struct _magic_vars_t
*magic_vars
)
1297 EXEC_WITH_MAGIC_VARS(
1298 buff_size
= magic_sentry_hash_estimate_buff_size(0);
1301 buff
= st_buff_allocate(info
, buff_size
);
1303 EXEC_WITH_MAGIC_VARS(
1304 magic_sentry_hash_build(buff
, buff_size
);
1309 PRIVATE
void st_cleanup_sentry_hash(st_init_info_t
*info
,
1310 struct _magic_vars_t
*magic_vars
)
1312 EXEC_WITH_MAGIC_VARS(
1313 magic_sentry_hash_destroy();
1319 #if MAGIC_LOOKUP_FUNCTION_ALLOW_ADDR_HASH
1320 PRIVATE
void st_init_function_hash(st_init_info_t
*info
,
1321 struct _magic_vars_t
*magic_vars
)
1326 EXEC_WITH_MAGIC_VARS(
1327 buff_size
= magic_function_hash_estimate_buff_size(0);
1330 buff
= st_buff_allocate(info
, buff_size
);
1332 EXEC_WITH_MAGIC_VARS(
1333 magic_function_hash_build(buff
, buff_size
);
1338 PRIVATE
void st_cleanup_function_hash(st_init_info_t
*info
,
1339 struct _magic_vars_t
*magic_vars
)
1341 EXEC_WITH_MAGIC_VARS(
1342 magic_function_hash_destroy();
1348 PRIVATE
void st_vars_clear_ptrs(struct _magic_vars_t
*magic_vars
)
1351 #define __X(x) offsetof(struct _magic_vars_t, x)
1352 size_t offset_list
[] = { ST_MAGIC_VARS_PTR_CLEAR_LIST
};
1356 for (i
= 0 ; i
< sizeof(offset_list
) / sizeof(size_t) ; i
++)
1357 *((void **)(((char *)magic_vars
) + offset_list
[i
])) = NULL
;
1362 PRIVATE
void st_unmap_mem(struct _magic_vars_t
*magic_vars
)
1366 for (i
= 0; i
< MAGIC_UNMAP_MEM_ENTRIES
; i
++) {
1367 if (magic_vars
->unmap_mem
[i
].length
!= 0) {
1368 #if ST_DEBUG_LEVEL > 0
1369 printf("st_unmap_mem: unmapping (%p, %zu)\n",
1370 magic_vars
->unmap_mem
[i
].start
,
1371 magic_vars
->unmap_mem
[i
].length
);
1373 r
= munmap(magic_vars
->unmap_mem
[i
].start
,
1374 magic_vars
->unmap_mem
[i
].length
);
1381 PUBLIC
int st_init(st_init_info_t
*info
)
1383 size_t max_buff_sz
= 0;
1384 int r
, dsentries_num
;
1385 int allow_unpaired_types
= TRUE
;
1389 if (!_magic_enabled
) return ENOSYS
;
1390 st_init_done
= TRUE
;
1392 /* Ignore nested mempool dsentries for now. */
1393 magic_lookup_nested_dsentries
= 0;
1395 /* Override default state transfer policies for ASR. */
1396 if ((info
->flags
& ST_LU_ASR
) && st_policies
== ST_POLICIES_DEFAULT
) {
1397 st_policies
= ST_POLICIES_DEFAULT_TRANSFER_ASR
;
1400 /* Fixup state transfer policies based on current configuration. */
1401 #if ST_ASSUME_RAW_COPY_BEFORE_TRANSFER
1402 st_policies
&= (~ST_DEFAULT_ALLOC_CASCADE_XFER
);
1403 #elif !defined(__MINIX)
1404 st_policies
|= ST_TRANSFER_DIRTY_ONLY
;
1407 assert((!info
->init_buff_start
|| (info
->flags
& ST_LU_NOMMAP
)) && "st_init: no mmapping allowed, and no buffer is available");
1408 register_typenames_and_callbacks();
1410 /* Transfer _magic_vars, which contain addresses of the magic variables */
1411 r
= st_cbs_os
.old_state_table_lookup(info
->info_opaque
, &st_remote_magic_vars
);
1412 assert( r
== OK
&& "ERROR occurred during transfer of _magic_vars.");
1414 * Clear all pointers not explictly transferred, as they are not valid in
1415 * the new address space.
1417 st_vars_clear_ptrs(&st_remote_magic_vars
);
1420 * Some magic_vars members do not need transfer or adjustment
1421 * (e.g. the memory ranges). They are copied to st_cached_magic_vars
1424 st_cached_magic_vars
= st_remote_magic_vars
;
1426 /* Transfer and adjust metadata */
1427 r
= st_transfer_metadata_types(info
, &st_cached_magic_vars
, &st_remote_magic_vars
, &st_counterparts
);
1428 assert( r
== OK
&& "ERROR occurred during transfer of type metadata.");
1429 r
= transfer_metadata_functions(info
, &st_cached_magic_vars
, &st_remote_magic_vars
, &st_counterparts
);
1430 assert( r
== OK
&& "ERROR occurred during transfer of function metadata.");
1431 r
= transfer_metadata_dfunctions(info
, &st_cached_magic_vars
, &st_remote_magic_vars
, &st_counterparts
);
1432 assert( r
== OK
&& "ERROR occurred during transfer of dfunction metadata.");
1433 r
= transfer_metadata_sentries(info
, &st_cached_magic_vars
, &st_remote_magic_vars
, &st_counterparts
, &max_buff_sz
);
1434 assert( r
== OK
&& "ERROR occurred during transfer of sentry metadata.");
1435 r
= st_transfer_metadata_dsentries(info
, &st_cached_magic_vars
, &st_remote_magic_vars
, &st_counterparts
, &max_buff_sz
, &dsentries_num
);
1436 assert( r
== OK
&& "ERROR occurred during transfer of dsentry metadata.");
1438 /* Allocate buffer for data transfer */
1439 st_dsentry_buff
= st_buff_allocate(info
, max_buff_sz
+ sizeof(struct _magic_dsentry
));
1440 if (!st_dsentry_buff
) {
1441 printf("st_dsentry_buff could not be allocated.\n");
1444 st_data_buff
= &st_dsentry_buff
[1];
1446 /* Allocate and initialize counterparts buffers. */
1447 st_counterparts
.functions_size
= st_cached_magic_vars
.functions_num
;
1448 st_counterparts
.functions
= st_buff_allocate(info
, st_counterparts
.functions_size
* sizeof(st_ptr_mapping
));
1449 assert(st_counterparts
.functions
&& "st_counterparts.functions could not be allocated.");
1451 st_counterparts
.types_size
= st_cached_magic_vars
.types_num
;
1452 st_counterparts
.types
= st_buff_allocate(info
, st_counterparts
.types_size
* sizeof(st_ptr_mapping
));
1453 assert(st_counterparts
.types
&& "st_counterparts.types could not be allocated.");
1454 st_counterparts
.ptr_types
= st_buff_allocate(info
, st_counterparts
.types_size
* sizeof(st_ptr_mapping
));
1455 assert(st_counterparts
.ptr_types
&& "st_counterparts.ptr_types could not be allocated.");
1457 st_counterparts
.sentries_size
= st_cached_magic_vars
.sentries_num
+ dsentries_num
;
1458 st_counterparts
.sentries
= st_buff_allocate(info
, st_counterparts
.sentries_size
* sizeof(st_ptr_mapping
));
1459 assert(st_counterparts
.sentries
&& "st_counterparts.sentries could not be allocated.");
1460 st_counterparts
.sentries_data
= st_buff_allocate(info
, st_counterparts
.sentries_size
* sizeof(st_ptr_mapping
));
1461 assert(st_counterparts
.sentries_data
&& "st_counterparts.sentries_data could not be allocated.");
1463 #if MAGIC_LOOKUP_SENTRY_ALLOW_RANGE_INDEX
1464 st_init_rl_index(info
, &st_cached_magic_vars
);
1467 #if MAGIC_LOOKUP_SENTRY_ALLOW_NAME_HASH
1468 st_init_sentry_hash(info
, &st_cached_magic_vars
);
1469 st_init_sentry_hash(info
, _magic_vars
);
1472 #if MAGIC_LOOKUP_FUNCTION_ALLOW_ADDR_HASH
1473 st_init_function_hash(info
, &st_cached_magic_vars
);
1474 st_init_function_hash(info
, _magic_vars
);
1478 /* Unmap any memory ranges that are not needed in the new process. */
1479 st_unmap_mem(&st_cached_magic_vars
);
1482 /* Pair metadata entities */
1483 r
= pair_metadata_types(info
, &st_cached_magic_vars
, &st_counterparts
, allow_unpaired_types
);
1484 assert( r
== OK
&& "ERROR occurred during call to pair_metadata_types().");
1485 r
= pair_metadata_functions(info
, &st_cached_magic_vars
, &st_counterparts
);
1486 assert( r
== OK
&& "ERROR occurred during call to pair_metadata_functions().");
1487 r
= pair_metadata_sentries(info
, &st_cached_magic_vars
, &st_counterparts
);
1488 assert( r
== OK
&& "ERROR occurred during call to pair_metadata_sentries().");
1489 #if ST_ASSUME_RAW_COPY_BEFORE_TRANSFER
1490 r
= allocate_pair_metadata_dsentries_from_raw_copy(info
, &st_cached_magic_vars
, &st_counterparts
);
1491 assert( r
== OK
&& "ERROR occurred during call to allocate_pair_metadata_dsentries().");
1493 r
= allocate_pair_metadata_dsentries(info
, &st_cached_magic_vars
, &st_counterparts
);
1494 assert( r
== OK
&& "ERROR occurred during call to allocate_pair_metadata_dsentries().");
1497 /* Set state transfer status defaults from the predefined policies. */
1498 st_set_status_defaults(info
);
1500 #if MAGIC_LOOKUP_SENTRY_ALLOW_RANGE_INDEX
1501 st_init_rl_index(info
, _magic_vars
);
1507 PRIVATE INLINE
char* st_lookup_str_local_data(struct _magic_sentry
*cached_sentry
)
1509 void *local_data_addr
;
1510 assert(cached_sentry
&& MAGIC_SENTRY_IS_STRING(cached_sentry
));
1511 ST_GET_CACHED_COUNTERPART(cached_sentry
, sentries
, sentries_data
, local_data_addr
);
1512 assert(local_data_addr
&& "String data not in cache!");
1513 return (char*) local_data_addr
;
1516 #if ST_DEBUG_DATA_TRANSFER
1517 PRIVATE
void st_print_sentities(struct _magic_vars_t
*magic_vars
)
1519 struct _magic_dsentry
*dsentry
= magic_vars
->first_dsentry
;
1522 for (i
= 0 ; i
< magic_vars
->sentries_num
; i
++) {
1523 struct _magic_sentry
*sentry
= &magic_vars
->sentries
[i
];
1524 ST_SENTRY_PRINT(sentry
, 0);
1528 while (dsentry
!= NULL
) {
1529 ST_DSENTRY_PRINT(dsentry
, 0);
1531 dsentry
= dsentry
->next
;
1534 for (i
= 0 ; i
< magic_vars
->functions_num
; i
++) {
1535 struct _magic_function
*function
= &magic_vars
->functions
[i
];
1536 ST_FUNCTION_PRINT(function
, 0);
1542 PUBLIC
void st_map_str_sentries(struct _magic_sentry
**cached_sentry_ptr
, struct _magic_sentry
**local_sentry_ptr
)
1544 struct _magic_sentry
*cached_sentry
= *cached_sentry_ptr
;
1545 struct _magic_sentry
*local_sentry
= *local_sentry_ptr
;
1546 struct _magic_sentry
*sentry
= cached_sentry
? cached_sentry
: local_sentry
;
1547 int string_flags
, match_by_name
, match_by_content
;
1549 assert((cached_sentry
== NULL
) ^ (local_sentry
== NULL
));
1551 string_flags
= sentry
->flags
& (MAGIC_STATE_STRING
|MAGIC_STATE_NAMED_STRING
);
1552 assert(string_flags
& MAGIC_STATE_STRING
);
1553 match_by_name
= (string_flags
& MAGIC_STATE_NAMED_STRING
) && (st_policies
& ST_MAP_NAMED_STRINGS_BY_NAME
);
1554 match_by_content
= ((string_flags
& MAGIC_STATE_NAMED_STRING
) && (st_policies
& ST_MAP_NAMED_STRINGS_BY_CONTENT
))
1555 || (!(string_flags
& MAGIC_STATE_NAMED_STRING
) && (st_policies
& ST_MAP_STRINGS_BY_CONTENT
));
1556 if (match_by_name
) {
1557 /* Pretend it's a regular sentry and match by name */
1558 sentry
->flags
&= ~string_flags
;
1559 st_map_sentries(cached_sentry_ptr
, local_sentry_ptr
);
1560 sentry
->flags
|= string_flags
;
1561 if (*cached_sentry_ptr
&& *local_sentry_ptr
) {
1562 /* Found by name. */
1566 if (!match_by_content
) {
1570 if (cached_sentry
) {
1571 EXEC_WITH_MAGIC_VARS(
1572 local_sentry
= magic_sentry_lookup_by_string(st_lookup_str_local_data(cached_sentry
));
1573 , st_local_magic_vars_ptr
1578 for(i
= 0 ; i
< st_cached_magic_vars
.sentries_num
; i
++) {
1579 sentry
= &st_cached_magic_vars
.sentries
[i
];
1580 if (MAGIC_SENTRY_IS_STRING(sentry
) && !strcmp(st_lookup_str_local_data(sentry
), (char*)local_sentry
->address
)) {
1581 cached_sentry
= sentry
;
1586 *cached_sentry_ptr
= cached_sentry
;
1587 *local_sentry_ptr
= local_sentry
;
1590 PUBLIC
void st_map_sentries(struct _magic_sentry
**cached_sentry_ptr
, struct _magic_sentry
**local_sentry_ptr
)
1592 struct _magic_sentry
*cached_sentry
= *cached_sentry_ptr
;
1593 struct _magic_sentry
*local_sentry
= *local_sentry_ptr
;
1594 struct _magic_dsentry
*cached_dsentry
= cached_sentry
? (MAGIC_STATE_FLAG(cached_sentry
, MAGIC_STATE_DYNAMIC
) ? MAGIC_DSENTRY_FROM_SENTRY(cached_sentry
) : NULL
) : NULL
;
1595 struct _magic_dsentry
*local_dsentry
= local_sentry
? (MAGIC_STATE_FLAG(local_sentry
, MAGIC_STATE_DYNAMIC
) ? MAGIC_DSENTRY_FROM_SENTRY(local_sentry
) : NULL
) : NULL
;
1597 assert((cached_sentry
== NULL
) ^ (local_sentry
== NULL
));
1599 if ((cached_sentry
&& MAGIC_STATE_FLAG(cached_sentry
, MAGIC_STATE_STRING
))
1600 || (local_sentry
&& MAGIC_STATE_FLAG(local_sentry
, MAGIC_STATE_STRING
))) {
1601 st_map_str_sentries(cached_sentry_ptr
, local_sentry_ptr
);
1604 else if (cached_sentry
) {
1605 EXEC_WITH_MAGIC_VARS(
1606 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 , st_local_magic_vars_ptr
1609 assert(!local_sentry
|| MAGIC_STATE_FLAG(cached_sentry
, MAGIC_STATE_DYNAMIC
) == MAGIC_STATE_FLAG(local_sentry
, MAGIC_STATE_DYNAMIC
));
1612 EXEC_WITH_MAGIC_VARS(
1613 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 , &st_cached_magic_vars
1616 assert(!cached_sentry
|| MAGIC_STATE_FLAG(local_sentry
, MAGIC_STATE_DYNAMIC
) == MAGIC_STATE_FLAG(cached_sentry
, MAGIC_STATE_DYNAMIC
));
1618 *cached_sentry_ptr
= cached_sentry
;
1619 *local_sentry_ptr
= local_sentry
;
1622 PRIVATE
struct _magic_sentry
*st_lookup_cached_sentry(struct _magic_sentry
*local_sentry
)
1625 struct _magic_dsentry
*cached_dsentry
;
1626 assert(local_sentry
);
1628 for (i
= 0 ; i
< st_counterparts
.sentries_size
; i
++) {
1629 if (st_counterparts
.sentries
[i
].counterpart
== local_sentry
) {
1633 if (i
>= st_counterparts
.sentries_size
) {
1636 if (i
< st_cached_magic_vars
.sentries_num
) {
1637 return &st_cached_magic_vars
.sentries
[i
];
1639 i
-= st_cached_magic_vars
.sentries_num
;
1640 cached_dsentry
= st_cached_magic_vars
.first_dsentry
;
1642 assert(cached_dsentry
);
1644 cached_dsentry
= cached_dsentry
->next
;
1645 assert(cached_dsentry
);
1648 return MAGIC_DSENTRY_TO_SENTRY(cached_dsentry
);
1651 PUBLIC
void st_lookup_sentry_pair(struct _magic_sentry
**cached_sentry_ptr
, struct _magic_sentry
**local_sentry_ptr
)
1653 struct _magic_sentry
*cached_sentry
= *cached_sentry_ptr
;
1654 struct _magic_sentry
*local_sentry
= *local_sentry_ptr
;
1656 assert((cached_sentry
== NULL
) ^ (local_sentry
== NULL
));
1658 if (cached_sentry
) {
1659 ST_GET_CACHED_COUNTERPART(cached_sentry
, sentries
, sentries
, local_sentry
);
1661 else if (MAGIC_SENTRY_IS_STRING(local_sentry
)) {
1662 /* strings are special, they may have multiple local duplicates */
1663 struct _magic_sentry
*csentry
= NULL
, *lsentry
= NULL
;
1664 st_map_str_sentries(&csentry
, &local_sentry
);
1666 st_lookup_sentry_pair(&csentry
, &lsentry
);
1668 cached_sentry
= csentry
;
1673 cached_sentry
= st_lookup_cached_sentry(local_sentry
);
1675 *cached_sentry_ptr
= cached_sentry
;
1676 *local_sentry_ptr
= local_sentry
;
1679 PRIVATE INLINE
void st_unpair_local_alloc_sentry(struct _magic_sentry
*local_sentry
)
1681 if (st_policies
& ST_ON_ALLOC_UNPAIR_ERROR
) {
1682 st_cbs_os
.panic("st_unpair_local_alloc_sentry: Error: attempting to unpair a local alloc sentry!");
1684 else if (st_policies
& ST_ON_ALLOC_UNPAIR_DEALLOCATE
) {
1685 deallocate_local_dsentry(MAGIC_DSENTRY_FROM_SENTRY(local_sentry
));
1689 PUBLIC
void st_add_sentry_pair(struct _magic_sentry
*cached_sentry
, struct _magic_sentry
*local_sentry
)
1692 assert(cached_sentry
|| local_sentry
);
1695 struct _magic_sentry
*csentry
= NULL
;
1696 st_lookup_sentry_pair(&csentry
, &local_sentry
);
1698 ST_SET_CACHED_COUNTERPART(csentry
, sentries
, sentries
, NULL
);
1700 if (!cached_sentry
&& MAGIC_SENTRY_IS_ALLOC(local_sentry
)) {
1701 st_unpair_local_alloc_sentry(local_sentry
);
1704 if (cached_sentry
) {
1705 struct _magic_sentry
*lsentry
= NULL
;
1706 st_lookup_sentry_pair(&cached_sentry
, &lsentry
);
1707 if (lsentry
&& MAGIC_SENTRY_IS_ALLOC(lsentry
)) {
1708 st_unpair_local_alloc_sentry(lsentry
);
1710 ST_SET_CACHED_COUNTERPART(cached_sentry
, sentries
, sentries
, local_sentry
);
1714 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
)
1717 struct _magic_dsentry
*local_dsentry
;
1719 assert(cached_sentry
);
1721 if (!local_dsindex
) {
1722 st_add_sentry_pair(cached_sentry
, NULL
);
1726 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
));
1730 st_add_sentry_pair(cached_sentry
, MAGIC_DSENTRY_TO_SENTRY(local_dsentry
));
1734 PUBLIC
void st_map_functions(struct _magic_function
**cached_function_ptr
, struct _magic_function
**local_function_ptr
)
1736 struct _magic_function
*cached_function
= *cached_function_ptr
;
1737 struct _magic_function
*local_function
= *local_function_ptr
;
1739 assert((cached_function
== NULL
) ^ (local_function
== NULL
));
1741 if (cached_function
) {
1742 EXEC_WITH_MAGIC_VARS(
1743 local_function
= magic_function_lookup_by_name(NULL
, cached_function
->name
);
1744 , st_local_magic_vars_ptr
1748 EXEC_WITH_MAGIC_VARS(
1749 cached_function
= magic_function_lookup_by_name(NULL
, local_function
->name
);
1750 , &st_cached_magic_vars
1753 *cached_function_ptr
= cached_function
;
1754 *local_function_ptr
= local_function
;
1757 PUBLIC
void st_lookup_function_pair(struct _magic_function
**cached_function_ptr
, struct _magic_function
**local_function_ptr
)
1759 struct _magic_function
*cached_function
= *cached_function_ptr
;
1760 struct _magic_function
*local_function
= *local_function_ptr
;
1763 assert((cached_function
== NULL
) ^ (local_function
== NULL
));
1765 if (cached_function
) {
1766 if ((int)cached_function
->id
- 1 >= st_counterparts
.functions_size
) {
1768 * Try to check if this is a function
1769 * from an external shared object.
1770 * XXX: The number of dfunctions can be quite large,
1771 * so this needs to be done more efficiently.
1773 struct _magic_dfunction
*dfunc
;
1774 struct _magic_function
*func
;
1775 MAGIC_DFUNCTION_FUNC_ITER(_magic_vars
->first_dfunction
, dfunc
, func
,
1776 if (func
->address
== cached_function
->address
) {
1777 local_function
= func
;
1781 assert(local_function
!= NULL
&& "No counterpart found for function.");
1783 ST_GET_CACHED_COUNTERPART(cached_function
, functions
, functions
, local_function
);
1787 assert(st_counterparts
.functions_size
== st_cached_magic_vars
.functions_num
);
1788 for(i
= 0 ; i
< st_counterparts
.functions_size
; i
++) {
1789 if(st_counterparts
.functions
[i
].counterpart
== local_function
) {
1790 cached_function
= &st_cached_magic_vars
.functions
[i
];
1795 *cached_function_ptr
= cached_function
;
1796 *local_function_ptr
= local_function
;
1799 PUBLIC
void st_add_function_pair(struct _magic_function
*cached_function
, struct _magic_function
*local_function
)
1802 assert(cached_function
|| local_function
);
1804 if (local_function
) {
1805 struct _magic_function
*cfunction
= NULL
;
1806 st_lookup_function_pair(&cfunction
, &local_function
);
1808 ST_SET_CACHED_COUNTERPART(cfunction
, functions
, functions
, NULL
);
1811 if (cached_function
) {
1812 ST_SET_CACHED_COUNTERPART(cached_function
, functions
, functions
, local_function
);
1816 PUBLIC
int st_sentry_equals(struct _magic_sentry
*cached_sentry
, struct _magic_sentry
*local_sentry
)
1818 const char *cached_parent_name
= "", *local_parent_name
= "";
1819 int cached_flags
= MAGIC_STATE_FLAGS_TO_NONEXTF(cached_sentry
->flags
) & (~MAGIC_STATE_ADDR_NOT_TAKEN
);
1820 int local_flags
= MAGIC_STATE_FLAGS_TO_NONEXTF(local_sentry
->flags
) & (~MAGIC_STATE_ADDR_NOT_TAKEN
);
1821 if (cached_flags
!= local_flags
) {
1824 if (MAGIC_STATE_FLAG(cached_sentry
, MAGIC_STATE_STRING
)) {
1825 return !strcmp(st_lookup_str_local_data(cached_sentry
), (char*)local_sentry
->address
);
1827 if (MAGIC_STATE_FLAG(cached_sentry
, MAGIC_STATE_DYNAMIC
)) {
1828 cached_parent_name
= MAGIC_DSENTRY_FROM_SENTRY(cached_sentry
)->parent_name
;
1829 local_parent_name
= MAGIC_DSENTRY_FROM_SENTRY(local_sentry
)->parent_name
;
1831 if (strcmp(cached_sentry
->name
, local_sentry
->name
) || strcmp(cached_parent_name
, local_parent_name
)) {
1834 return magic_type_compatible(cached_sentry
->type
, local_sentry
->type
, MAGIC_TYPE_COMPARE_ALL
);
1837 PUBLIC
int st_function_equals(struct _magic_function
*cached_function
, struct _magic_function
*local_function
)
1839 if (MAGIC_STATE_FLAGS_TO_NONEXTF(local_function
->flags
) != MAGIC_STATE_FLAGS_TO_NONEXTF(cached_function
->flags
)) {
1842 return !strcmp(cached_function
->name
, local_function
->name
);
1845 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
)
1847 int is_paired_sentry
;
1850 if (!cached_sentry
|| !local_sentry
) {
1852 st_map_sentries(&cached_sentry
, &local_sentry
);
1855 st_lookup_sentry_pair(&cached_sentry
, &local_sentry
);
1858 is_paired_sentry
= (cached_sentry
!= NULL
&& local_sentry
!= NULL
);
1859 if (is_paired_sentry
&& st_sentry_equals(cached_sentry
, local_sentry
)) {
1862 if (is_paired_sentry
&& !print_changed
) {
1865 if (cached_sentry
) {
1866 printf("-"); ST_SENTRY_PRINT(cached_sentry
, MAGIC_EXPAND_TYPE_STR
); printf("\n");
1869 printf("+"); ST_SENTRY_PRINT(local_sentry
, MAGIC_EXPAND_TYPE_STR
); printf("\n");
1874 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
)
1876 int is_paired_function
;
1879 if (!cached_function
|| !local_function
) {
1881 st_map_functions(&cached_function
, &local_function
);
1884 st_lookup_function_pair(&cached_function
, &local_function
);
1887 is_paired_function
= (cached_function
!= NULL
&& local_function
!= NULL
);
1888 if (is_paired_function
&& st_function_equals(cached_function
, local_function
)) {
1891 if (is_paired_function
&& !print_changed
) {
1894 if (cached_function
) {
1895 printf("-"); ST_FUNCTION_PRINT(cached_function
, MAGIC_EXPAND_TYPE_STR
); printf("\n");
1897 if (local_function
) {
1898 printf("+"); ST_FUNCTION_PRINT(local_function
, MAGIC_EXPAND_TYPE_STR
); printf("\n");
1903 PUBLIC
void st_print_sentries_diff(st_init_info_t
*info
, int raw_diff
, int print_changed
)
1908 for (i
= 0 ; i
< st_cached_magic_vars
.sentries_num
; i
++) {
1909 struct _magic_sentry
*cached_sentry
= &st_cached_magic_vars
.sentries
[i
];
1910 st_print_sentry_diff(info
, cached_sentry
, NULL
, raw_diff
, print_changed
);
1913 print_changed
= FALSE
;
1914 for (i
= 0 ; i
< st_local_magic_vars_ptr
->sentries_num
; i
++) {
1915 struct _magic_sentry
*local_sentry
= &st_local_magic_vars_ptr
->sentries
[i
];
1916 st_print_sentry_diff(info
, NULL
, local_sentry
, raw_diff
, print_changed
);
1920 PUBLIC
void st_print_dsentries_diff(st_init_info_t
*info
, int raw_diff
, int print_changed
)
1922 struct _magic_dsentry
*dsentry
;
1925 dsentry
= st_cached_magic_vars
.first_dsentry
;
1926 while (dsentry
!= NULL
) {
1927 struct _magic_sentry
*cached_sentry
= MAGIC_DSENTRY_TO_SENTRY(dsentry
);
1928 st_print_sentry_diff(info
, cached_sentry
, NULL
, raw_diff
, print_changed
);
1929 dsentry
= dsentry
->next
;
1932 dsentry
= st_local_magic_vars_ptr
->first_dsentry
;
1933 print_changed
= FALSE
;
1934 while (dsentry
!= NULL
) {
1935 struct _magic_sentry
*local_sentry
= MAGIC_DSENTRY_TO_SENTRY(dsentry
);
1936 st_print_sentry_diff(info
, NULL
, local_sentry
, raw_diff
, print_changed
);
1937 dsentry
= dsentry
->next
;
1941 PUBLIC
void st_print_functions_diff(st_init_info_t
*info
, int raw_diff
, int print_changed
)
1946 for(i
= 0 ; i
< st_cached_magic_vars
.functions_num
; i
++) {
1947 struct _magic_function
*cached_function
= &st_cached_magic_vars
.functions
[i
];
1948 st_print_function_diff(info
, cached_function
, NULL
, raw_diff
, print_changed
);
1951 print_changed
= FALSE
;
1952 for (i
= 0 ; i
< st_local_magic_vars_ptr
->functions_num
; i
++) {
1953 struct _magic_function
*local_function
= &st_local_magic_vars_ptr
->functions
[i
];
1954 st_print_function_diff(info
, NULL
, local_function
, raw_diff
, print_changed
);
1958 PUBLIC
void st_print_state_diff(st_init_info_t
*info
, int raw_diff
, int print_changed
)
1962 printf("Index: sentries\n");
1963 printf("===================================================================\n");
1964 st_print_sentries_diff(info
, raw_diff
, print_changed
);
1966 printf("\nIndex: dsentries\n");
1967 printf("===================================================================\n");
1968 st_print_dsentries_diff(info
, raw_diff
, print_changed
);
1970 printf("\nIndex: functions\n");
1971 printf("===================================================================\n");
1972 st_print_functions_diff(info
, raw_diff
, print_changed
);
1976 PUBLIC
int st_data_transfer(st_init_info_t
*info
)
1978 struct _magic_dsentry
*dsentry
;
1980 int sentry_transferred
;
1981 #if ST_DEBUG_DATA_TRANSFER
1986 /* Check unpaired sentries. */
1987 for (i
= 0 ; i
< st_cached_magic_vars
.sentries_num
; i
++) {
1988 struct _magic_sentry
*sentry
= &st_cached_magic_vars
.sentries
[i
];
1989 int is_paired_sentry
= ST_HAS_CACHED_COUNTERPART(sentry
, sentries
);
1990 if (!is_paired_sentry
) {
1991 r
= check_unpaired_sentry(info
, sentry
);
1998 /* Check unpaired dsentries. */
1999 dsentry
= st_cached_magic_vars
.first_dsentry
;
2000 while (dsentry
!= NULL
) {
2001 struct _magic_sentry
*sentry
= MAGIC_DSENTRY_TO_SENTRY(dsentry
);
2002 int is_paired_sentry
= ST_HAS_CACHED_COUNTERPART(sentry
, sentries
);
2003 if (!is_paired_sentry
) {
2004 r
= check_unpaired_sentry(info
, sentry
);
2009 dsentry
= dsentry
->next
;
2012 /* Data transfer. */
2014 sentry_transferred
= 0;
2016 #if ST_DEBUG_DATA_TRANSFER
2017 printf("st_data_transfer: Round %d\n", counter
++);
2018 st_print_sentities(&st_cached_magic_vars
);
2021 /* process sentries */
2022 #if ST_DEBUG_LEVEL > 0
2023 printf("st_data_transfer: processing sentries\n");
2025 for(i
= 0 ; i
< st_cached_magic_vars
.sentries_num
; i
++) {
2026 struct _magic_sentry
*sentry
= &st_cached_magic_vars
.sentries
[i
];
2027 int is_paired_sentry
= ST_HAS_CACHED_COUNTERPART(sentry
, sentries
);
2028 int sentry_needs_transfer
= MAGIC_STATE_EXTF_GET(sentry
, ST_NEEDS_TRANSFER
| ST_TRANSFER_DONE
) == ST_NEEDS_TRANSFER
;
2029 if (sentry_needs_transfer
&& is_paired_sentry
) {
2030 r
= transfer_data_sentry(info
, sentry
);
2034 sentry_transferred
= 1;
2038 /* process dsentries */
2039 #if ST_DEBUG_LEVEL > 0
2040 printf("st_data_transfer: processing dsentries\n");
2042 dsentry
= st_cached_magic_vars
.first_dsentry
;
2043 while (dsentry
!= NULL
) {
2044 struct _magic_sentry
*sentry
= MAGIC_DSENTRY_TO_SENTRY(dsentry
);
2045 int is_paired_sentry
= ST_HAS_CACHED_COUNTERPART(sentry
, sentries
);
2046 int sentry_needs_transfer
= MAGIC_STATE_EXTF_GET(sentry
, ST_NEEDS_TRANSFER
| ST_TRANSFER_DONE
) == ST_NEEDS_TRANSFER
;
2047 if (sentry_needs_transfer
&& is_paired_sentry
) {
2048 r
= transfer_data_sentry(info
, sentry
);
2052 sentry_transferred
= 1;
2054 dsentry
= dsentry
->next
;
2057 } while(sentry_transferred
);
2062 PRIVATE INLINE
void st_set_transfer_status(int status_flags
, int status_op
,
2063 struct _magic_sentry
*cached_sentry
, struct _magic_function
*cached_function
)
2065 #define __st_set_transfer_status(X) \
2066 switch(status_op) { \
2071 MAGIC_STATE_EXTF_ADD(X, status_flags); \
2074 MAGIC_STATE_EXTF_DEL(X, status_flags); \
2077 MAGIC_STATE_EXTF_SET(X, status_flags); \
2080 MAGIC_STATE_EXTF_CLEAR(X); \
2083 st_cbs_os.panic("Invalid operation!"); \
2087 if (cached_sentry) {
2088 __st_set_transfer_status(cached_sentry
);
2091 assert(cached_function
);
2092 __st_set_transfer_status(cached_function
);
2096 PUBLIC
void st_set_unpaired_types_ratios(float unpaired_types_ratio
,
2097 float unpaired_struct_types_ratio
)
2099 st_unpaired_types_ratio
= unpaired_types_ratio
;
2100 st_unpaired_struct_types_ratio
= unpaired_struct_types_ratio
;
2103 PUBLIC
void st_set_status_defaults(st_init_info_t
*info
)
2105 int match_all
= ~0, skip_none
= 0;
2106 int skip_state_flags
= (st_policies
& ST_DEFAULT_SKIP_STACK
) ? MAGIC_STATE_STACK
: 0;
2108 if (!(st_policies
& ST_DEFAULT_TRANSFER_NONE
)) {
2110 * Transfer all the (d)sentries by default. Skip stack dsentries when
2111 * requested. In that case, stack dsentries won't be transferred and an
2112 * error will be raised on stack pointer transfer.
2114 st_set_status_by_state_flags(ST_NEEDS_TRANSFER
, ST_OP_SET
,
2115 match_all
, skip_state_flags
);
2116 if (st_policies
& ST_DEFAULT_ALLOC_CASCADE_XFER
) {
2118 * If requested, mark non-stack dsentries for cascade transfer
2119 * instead of regular transfer.
2121 st_set_status_by_state_flags(ST_ON_PTRXFER_CASCADE
, ST_OP_SET
,
2122 MAGIC_STATE_HEAP
| MAGIC_STATE_MAP
, skip_none
);
2127 * Don't transfer any (d)sentries by default. Mark all the (d)sentries
2128 * for cascade transfer (except for stack dsentries when requested).
2130 st_set_status_by_state_flags(ST_ON_PTRXFER_CASCADE
, ST_OP_SET
,
2131 match_all
, skip_state_flags
);
2135 * Always transfer all immutable objects.
2137 st_set_status_by_state_flags(ST_NEEDS_TRANSFER
, ST_OP_SET
,
2138 MAGIC_STATE_IMMUTABLE
, skip_none
);
2141 * If requested, mark library state dsentries as already transferred too.
2143 if (st_policies
& ST_DEFAULT_SKIP_LIB_STATE
) {
2144 st_set_status_by_state_flags(ST_NEEDS_TRANSFER
| ST_TRANSFER_DONE
,
2145 ST_OP_ADD
, MAGIC_STATE_LIB
, skip_none
);
2149 * In addition, mark functions, out-of-band/string sentries
2150 * and shared dsentries as already transferred.
2152 st_set_status_by_state_flags(ST_NEEDS_TRANSFER
| ST_TRANSFER_DONE
,
2153 ST_OP_ADD
, MAGIC_STATE_TEXT
| MAGIC_STATE_OUT_OF_BAND
|
2154 MAGIC_STATE_STRING
| MAGIC_STATE_CONSTANT
| MAGIC_STATE_SHM
, skip_none
);
2157 * Finally, if we only want to transfer dirty sentries, mark all the other ones
2158 * as already transferred.
2160 if (st_policies
& ST_TRANSFER_DIRTY_ONLY
) {
2161 st_set_status_by_state_flags(ST_TRANSFER_DONE
, ST_OP_ADD
, match_all
, MAGIC_STATE_DIRTY_PAGE
);
2164 #if DO_SKIP_ENVIRON_HACK
2165 st_set_status_by_name(ST_NEEDS_TRANSFER
| ST_TRANSFER_DONE
,
2166 ST_OP_ADD
, NULL
, "__environ", MAGIC_DSENTRY_SITE_ID_NULL
);
2167 st_set_status_by_name(ST_NEEDS_TRANSFER
| ST_TRANSFER_DONE
,
2168 ST_OP_ADD
, NULL
, "stderr", MAGIC_DSENTRY_SITE_ID_NULL
);
2172 PUBLIC
void st_set_status_by_state_flags(int status_flags
, int status_op
,
2173 int match_state_flags
, int skip_state_flags
)
2175 struct _magic_dsentry
*dsentry
= st_cached_magic_vars
.first_dsentry
;
2177 int candidate_sentry_flags
= MAGIC_STATE_DATA
| MAGIC_STATE_STRING
| MAGIC_STATE_CONSTANT
| MAGIC_STATE_ADDR_NOT_TAKEN
;
2178 int candidate_function_flags
= MAGIC_STATE_TEXT
;
2179 int candidate_dsentry_flags
= ~(candidate_sentry_flags
| candidate_function_flags
);
2182 /* process sentries */
2183 if (match_state_flags
& candidate_sentry_flags
) {
2184 for (i
= 0 ; i
< st_cached_magic_vars
.sentries_num
; i
++) {
2185 int state_flags
= st_cached_magic_vars
.sentries
[i
].flags
;
2186 if ((state_flags
& match_state_flags
) && !(state_flags
& skip_state_flags
)) {
2187 st_set_transfer_status(status_flags
, status_op
, &st_cached_magic_vars
.sentries
[i
], NULL
);
2192 /* process dsentries */
2193 if (match_state_flags
& candidate_dsentry_flags
) {
2194 while (dsentry
!= NULL
) {
2195 int state_flags
= dsentry
->sentry
.flags
;
2196 if ((state_flags
& match_state_flags
) && !(state_flags
& skip_state_flags
)) {
2197 st_set_transfer_status(status_flags
, status_op
, MAGIC_DSENTRY_TO_SENTRY(dsentry
), NULL
);
2199 dsentry
= dsentry
->next
;
2203 /* process functions */
2204 if (match_state_flags
& candidate_function_flags
) {
2205 for (i
= 0 ; i
< st_cached_magic_vars
.functions_num
; i
++) {
2206 int state_flags
= st_cached_magic_vars
.functions
[i
].flags
;
2207 if ((state_flags
& match_state_flags
) && !(state_flags
& skip_state_flags
)) {
2208 st_set_transfer_status(status_flags
, status_op
, NULL
, &st_cached_magic_vars
.functions
[i
]);
2214 PUBLIC
int st_set_status_by_function_ids(int status_flags
, int status_op
, _magic_id_t
*ids
)
2217 while (ids
[i
] != 0) {
2218 r
= st_set_status_by_function_id(status_flags
, status_op
, ids
[i
]);
2227 PUBLIC
int st_set_status_by_sentry_ids(int status_flags
, int status_op
, _magic_id_t
*ids
)
2230 while (ids
[i
] != 0) {
2231 r
= st_set_status_by_sentry_id(status_flags
, status_op
, ids
[i
]);
2240 PUBLIC
int st_set_status_by_names(int status_flags
, int status_op
,
2241 const char **parent_names
, const char **names
,
2242 _magic_id_t
*dsentry_site_ids
)
2245 while (names
[i
] != NULL
) {
2246 r
= st_set_status_by_name(status_flags
, status_op
,
2247 parent_names
? parent_names
[i
] : NULL
, names
[i
],
2248 dsentry_site_ids
? dsentry_site_ids
[i
] :
2249 MAGIC_DSENTRY_SITE_ID_NULL
);
2258 PUBLIC
int st_set_status_by_local_addrs(int status_flags
, int status_op
,
2262 while (addrs
[i
] != NULL
) {
2263 r
= st_set_status_by_local_addr(status_flags
, status_op
, addrs
[i
]);
2272 PUBLIC
void st_set_status_by_sentry(int status_flags
, int status_op
,
2273 void *cached_sentry
)
2277 st_set_transfer_status(status_flags
, status_op
,
2278 (struct _magic_sentry
*) cached_sentry
, NULL
);
2281 PUBLIC
void st_set_status_by_function(int status_flags
, int status_op
,
2282 void *cached_function
)
2286 st_set_transfer_status(status_flags
, status_op
,
2287 NULL
, (struct _magic_function
*) cached_function
);
2290 PUBLIC
int st_set_status_by_name(int status_flags
, int status_op
,
2291 const char *parent_name
, const char *name
, _magic_id_t dsentry_site_id
)
2293 struct _magic_sentry
*cached_sentry
= NULL
;
2294 struct _magic_function
*cached_function
= NULL
;
2297 EXEC_WITH_MAGIC_VARS(
2298 cached_sentry
= magic_sentry_lookup_by_name(parent_name
? parent_name
: "", name
, dsentry_site_id
, NULL
);
2299 if (!cached_sentry
) {
2300 cached_function
= magic_function_lookup_by_name(parent_name
, name
);
2302 , &st_cached_magic_vars
2304 if (!cached_sentry
&& !cached_function
) {
2307 st_set_transfer_status(status_flags
, status_op
, cached_sentry
, cached_function
);
2308 if (cached_sentry
&& MAGIC_SENTRY_IS_ALLOC(cached_sentry
)) {
2309 struct _magic_dsentry
*prev_dsentry
, *dsentry
, *next_dsentry
= MAGIC_DSENTRY_NEXT(MAGIC_DSENTRY_FROM_SENTRY(cached_sentry
));
2310 struct _magic_sentry
* sentry
;
2312 * Alloc sentries may have multiple instances with the same name.
2313 * Use the site_id to distinguish between them.
2315 assert(parent_name
&& name
);
2316 MAGIC_DSENTRY_ALIVE_NAME_ID_ITER(next_dsentry
, prev_dsentry
, dsentry
, sentry
,
2317 parent_name
, name
, dsentry_site_id
,
2318 st_set_transfer_status(status_flags
, status_op
, sentry
, NULL
);
2324 PUBLIC
int st_set_status_by_function_id(int status_flags
, int status_op
,
2327 struct _magic_function
*cached_function
= NULL
;
2330 EXEC_WITH_MAGIC_VARS(
2331 cached_function
= magic_function_lookup_by_id(id
, NULL
);
2332 , &st_cached_magic_vars
2335 if (!cached_function
) {
2339 st_set_transfer_status(status_flags
, status_op
, NULL
, cached_function
);
2343 PUBLIC
int st_set_status_by_sentry_id(int status_flags
, int status_op
,
2346 struct _magic_sentry
*cached_sentry
= NULL
;
2349 EXEC_WITH_MAGIC_VARS(
2350 cached_sentry
= magic_sentry_lookup_by_id(id
, NULL
);
2351 , &st_cached_magic_vars
2354 if (!cached_sentry
) {
2358 st_set_transfer_status(status_flags
, status_op
, cached_sentry
, NULL
);
2362 PUBLIC
int st_set_status_by_local_addr(int status_flags
, int status_op
,
2365 const char *parent_name
, *name
;
2366 _magic_id_t dsentry_site_id
= MAGIC_DSENTRY_SITE_ID_NULL
;
2367 struct _magic_sentry
*sentry
= NULL
;
2368 struct _magic_function
*function
= NULL
;
2371 sentry
= magic_sentry_lookup_by_addr(addr
, NULL
);
2373 function
= magic_function_lookup_by_addr(addr
, NULL
);
2375 if (sentry
&& !MAGIC_STATE_FLAG(sentry
, MAGIC_STATE_DYNAMIC
)) {
2376 name
= sentry
->name
;
2377 parent_name
= MAGIC_SENTRY_PARENT(sentry
);
2378 dsentry_site_id
= MAGIC_SENTRY_SITE_ID(sentry
);
2380 else if (function
&& !MAGIC_STATE_FLAG(function
, MAGIC_STATE_DYNAMIC
)) {
2381 name
= function
->name
;
2382 parent_name
= MAGIC_FUNCTION_PARENT(function
);
2387 st_set_status_by_name(status_flags
, status_op
, parent_name
, name
, dsentry_site_id
);
2391 PUBLIC
int st_pair_by_function_ids(unsigned long *cached_ids
, unsigned long *local_ids
, int status_flags
, int status_op
)
2396 while (cached_ids
[i
] != 0) {
2397 assert(local_ids
[i
] != 0);
2398 r
= st_pair_by_function_id(cached_ids
[i
], local_ids
[i
], status_flags
, status_op
);
2407 PUBLIC
int st_pair_by_sentry_ids(unsigned long *cached_ids
, unsigned long *local_ids
, int status_flags
, int status_op
)
2412 while (cached_ids
[i
] != 0) {
2413 assert(local_ids
[i
] != 0);
2414 r
= st_pair_by_sentry_id(cached_ids
[i
], local_ids
[i
], status_flags
, status_op
);
2423 PUBLIC
int st_pair_by_names(char **cached_parent_names
, char **cached_names
,
2424 char **local_parent_names
, char **local_names
, _magic_id_t
*dsentry_site_ids
,
2425 int status_flags
, int status_op
)
2428 while (cached_names
[i
] != NULL
) {
2429 assert(local_names
[i
]);
2430 r
= st_pair_by_name(cached_parent_names
? cached_parent_names
[i
] : NULL
, cached_names
[i
],
2431 local_parent_names
? local_parent_names
[i
] : NULL
, local_names
[i
],
2432 dsentry_site_ids
? dsentry_site_ids
[i
] : MAGIC_DSENTRY_SITE_ID_NULL
,
2433 status_flags
, status_op
);
2442 PUBLIC
void st_pair_by_sentry(void *cached_sentry
, void *local_sentry
, int status_flags
, int status_op
)
2446 st_add_sentry_pair(cached_sentry
, local_sentry
);
2447 if (cached_sentry
) {
2448 st_set_status_by_sentry(status_flags
, status_op
, cached_sentry
);
2452 PUBLIC
void st_pair_by_function(void *cached_function
, void* local_function
, int status_flags
, int status_op
)
2456 st_add_function_pair(cached_function
, local_function
);
2457 if (cached_function
) {
2458 st_set_status_by_function(status_flags
, status_op
, cached_function
);
2462 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
)
2467 r
= st_add_sentry_pair_alloc_by_dsindex(info
, cached_sentry
, local_dsindex
, num_elements
, p_alloc_flags
);
2471 if (cached_sentry
) {
2472 st_set_status_by_sentry(status_flags
, status_op
, cached_sentry
);
2477 PUBLIC
int st_pair_by_function_id(unsigned long cached_id
, unsigned long local_id
, int status_flags
, int status_op
)
2479 struct _magic_function
*cached_function
= NULL
, *local_function
= NULL
;
2481 assert(cached_id
|| local_id
);
2484 EXEC_WITH_MAGIC_VARS(
2485 cached_function
= magic_function_lookup_by_id(cached_id
, NULL
);
2486 , &st_cached_magic_vars
2488 if (!cached_function
) {
2493 EXEC_WITH_MAGIC_VARS(
2494 local_function
= magic_function_lookup_by_id(local_id
, NULL
);
2495 , st_local_magic_vars_ptr
2497 if (!local_function
) {
2502 st_pair_by_function(cached_function
, local_function
, status_flags
, status_op
);
2506 PUBLIC
int st_pair_by_sentry_id(unsigned long cached_id
, unsigned long local_id
, int status_flags
, int status_op
)
2508 struct _magic_sentry
*cached_sentry
= NULL
, *local_sentry
= NULL
;
2510 assert(cached_id
|| local_id
);
2513 EXEC_WITH_MAGIC_VARS(
2514 cached_sentry
= magic_sentry_lookup_by_id(cached_id
, NULL
);
2515 , &st_cached_magic_vars
2517 if (!cached_sentry
) {
2522 EXEC_WITH_MAGIC_VARS(
2523 local_sentry
= magic_sentry_lookup_by_id(local_id
, NULL
);
2524 , st_local_magic_vars_ptr
2526 if (!local_sentry
) {
2531 st_pair_by_sentry(cached_sentry
, local_sentry
, status_flags
, status_op
);
2535 PUBLIC
int st_pair_by_name(char *cached_parent_name
, char *cached_name
,
2536 char *local_parent_name
, char *local_name
, _magic_id_t dsentry_site_id
,
2537 int status_flags
, int status_op
)
2539 struct _magic_function
*cached_function
= NULL
, *local_function
= NULL
;
2540 struct _magic_sentry
*cached_sentry
= NULL
, *local_sentry
= NULL
;
2542 assert(cached_name
|| local_name
);
2545 EXEC_WITH_MAGIC_VARS(
2546 cached_sentry
= magic_sentry_lookup_by_name(cached_parent_name
? cached_parent_name
: "", cached_name
, dsentry_site_id
, NULL
);
2547 if (cached_sentry
&& MAGIC_SENTRY_IS_ALLOC(cached_sentry
)) {
2550 if (!cached_sentry
) {
2551 cached_function
= magic_function_lookup_by_name(NULL
, cached_name
);
2553 , &st_cached_magic_vars
2555 if (!cached_sentry
&& !cached_function
) {
2560 EXEC_WITH_MAGIC_VARS(
2561 if (!cached_function
) {
2562 local_sentry
= magic_sentry_lookup_by_name(local_parent_name
? local_parent_name
: "", local_name
, dsentry_site_id
, NULL
);
2563 if (local_sentry
&& MAGIC_SENTRY_IS_ALLOC(local_sentry
)) {
2567 if (!cached_sentry
&& !local_sentry
) {
2568 local_function
= magic_function_lookup_by_name(NULL
, local_name
);
2570 , st_local_magic_vars_ptr
2572 if (!local_sentry
&& !local_function
) {
2576 if (cached_function
|| local_function
) {
2577 assert(!cached_sentry
&& !local_sentry
);
2578 st_pair_by_function(cached_function
, local_function
, status_flags
, status_op
);
2581 assert(cached_sentry
|| local_sentry
);
2582 st_pair_by_sentry(cached_sentry
, local_sentry
, status_flags
, status_op
);
2586 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
)
2588 int r
, saved_policies
= st_policies
;
2589 st_policies
&= ~(ST_ON_ALLOC_UNPAIR_MASK
);
2590 st_policies
|= (alloc_policies
& ST_ON_ALLOC_UNPAIR_MASK
);
2591 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 st_policies
= saved_policies
;
2596 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
)
2598 struct _magic_sentry
*cached_sentry
= NULL
, *local_sentry
= NULL
;
2599 struct _magic_dsindex
*local_dsindex
= NULL
;
2600 struct _magic_dsentry
*prev_dsentry
, *dsentry
, *head_dsentry
;
2601 struct _magic_sentry
* sentry
;
2603 int is_cached_alloc
= FALSE
, is_local_alloc
= FALSE
;
2605 assert(cached_name
|| local_name
);
2606 assert(!((cached_name
== NULL
) ^ (cached_parent_name
== NULL
)));
2607 assert(!((local_name
== NULL
) ^ (local_parent_name
== NULL
)));
2610 EXEC_WITH_MAGIC_VARS(
2611 cached_sentry
= magic_sentry_lookup_by_name(cached_parent_name
,
2612 cached_name
, cached_dsentry_site_id
, NULL
);
2613 if (cached_sentry
&& MAGIC_SENTRY_IS_ALLOC(cached_sentry
)) {
2614 is_cached_alloc
= TRUE
;
2616 , &st_cached_magic_vars
2620 EXEC_WITH_MAGIC_VARS(
2621 local_sentry
= magic_sentry_lookup_by_name(local_parent_name
,
2622 local_name
, local_dsentry_site_id
, NULL
);
2623 if (local_sentry
&& MAGIC_SENTRY_IS_ALLOC(local_sentry
)) {
2624 is_local_alloc
= TRUE
;
2626 if (!local_sentry
|| is_local_alloc
) {
2627 local_dsindex
= magic_dsindex_lookup_by_name(local_parent_name
, local_name
);
2628 if (local_dsindex
&& !MAGIC_DSINDEX_IS_ALLOC(local_dsindex
)) {
2629 local_dsindex
= NULL
;
2631 if (local_sentry
) assert(local_dsindex
);
2632 is_local_alloc
= is_local_alloc
|| local_dsindex
!= NULL
;
2634 , st_local_magic_vars_ptr
2637 if (!is_cached_alloc
&& !is_local_alloc
) {
2638 if (cached_sentry
|| local_sentry
) {
2639 st_pair_by_sentry(cached_sentry
, local_sentry
, status_flags
, status_op
);
2645 if (!is_local_alloc
) {
2646 /* Alloc sentries may have multiple instances with the same name. */
2647 assert(cached_sentry
&& is_cached_alloc
);
2648 head_dsentry
= MAGIC_DSENTRY_NEXT(MAGIC_DSENTRY_FROM_SENTRY(cached_sentry
));
2649 assert(cached_parent_name
&& cached_name
);
2650 MAGIC_DSENTRY_ALIVE_NAME_ID_ITER(head_dsentry
, prev_dsentry
, dsentry
, sentry
, cached_parent_name
, cached_name
, cached_dsentry_site_id
,
2651 /* Cannot map multiple cached alloc sentries to a single local non-alloc sentry. */
2654 /* Map a single cached alloc sentry to a single local non-alloc sentry. */
2655 st_pair_by_sentry(cached_sentry
, local_sentry
, status_flags
, status_op
);
2659 /* Unpair all the local alloc sentries. */
2660 head_dsentry
= MAGIC_DSENTRY_FROM_SENTRY(local_sentry
);
2661 assert(local_parent_name
&& local_name
);
2662 MAGIC_DSENTRY_ALIVE_NAME_ID_ITER(head_dsentry
, prev_dsentry
, dsentry
, sentry
, local_parent_name
, local_name
, local_dsentry_site_id
,
2663 st_pair_by_sentry(NULL
, sentry
, status_flags
, status_op
);
2667 if (!cached_sentry
) {
2671 /* Map a single cached non-alloc sentry to a local to-be-alloc sentry. */
2672 if (!is_cached_alloc
) {
2673 assert(local_dsindex
);
2674 return st_pair_alloc_by_dsindex(info
, cached_sentry
, local_dsindex
, num_elements
, p_alloc_flags
, status_flags
, status_op
);
2677 /* Map all the cached alloc sentries to the corresponding local to-be-alloc sentries (or NULL). */
2678 head_dsentry
= MAGIC_DSENTRY_FROM_SENTRY(cached_sentry
);
2679 assert(cached_parent_name
&& cached_name
);
2680 MAGIC_DSENTRY_ALIVE_NAME_ID_ITER(head_dsentry
, prev_dsentry
, dsentry
,
2681 sentry
, cached_parent_name
, cached_name
, cached_dsentry_site_id
,
2682 r
= st_pair_alloc_by_dsindex(info
, sentry
, local_dsindex
, num_elements
, p_alloc_flags
, status_flags
, status_op
);
2691 /* Metadata transfer and adjustment functions */
2693 PRIVATE
int transfer_metadata_functions(st_init_info_t
*info
,
2694 struct _magic_vars_t
*cached_magic_vars
,
2695 struct _magic_vars_t
*remote_magic_vars
,
2696 st_counterparts_t
*counterparts
)
2700 struct _magic_function
*cached_function
;
2702 /* transfer magic_functions */
2703 MD_TRANSFER(info
, remote_magic_vars
->functions
, (void **)&cached_magic_vars
->functions
, remote_magic_vars
->functions_num
* sizeof(struct _magic_function
));
2705 /* adjust magic_functions */
2706 for (i
= 0 ; i
< cached_magic_vars
->functions_num
; i
++) {
2707 cached_function
= &cached_magic_vars
->functions
[i
];
2708 MD_TRANSFER_STR(info
, &cached_function
->name
);
2709 cached_function
->type
= &cached_magic_vars
->types
[cached_function
->type
- remote_magic_vars
->types
];
2715 PRIVATE
int transfer_metadata_dfunctions(st_init_info_t
*info
,
2716 struct _magic_vars_t
*cached_magic_vars
,
2717 struct _magic_vars_t
*remote_magic_vars
,
2718 st_counterparts_t
*counterparts
)
2721 struct _magic_dfunction
**dfunction_ptr
;
2722 struct _magic_dfunction
*cached_dfunction
, *prev_dfunction
= NULL
;
2723 struct _magic_function
*cached_function
;
2725 /* Transfer dfunctions. */
2726 cached_magic_vars
->first_dfunction
= remote_magic_vars
->first_dfunction
;
2727 dfunction_ptr
= &cached_magic_vars
->first_dfunction
;
2728 while (*dfunction_ptr
!= NULL
) {
2729 MD_TRANSFER(info
, *dfunction_ptr
, (void **)dfunction_ptr
, sizeof(struct _magic_dfunction
));
2730 cached_dfunction
= *dfunction_ptr
;
2732 /* Adjust dfunction parent_name and next/prev links. */
2733 if (cached_dfunction
->parent_name
!= NULL
) {
2734 MD_TRANSFER_STR(info
, &cached_dfunction
->parent_name
);
2735 if (strlen(cached_dfunction
->parent_name
) == 0) {
2736 printf("ERROR. strlen(dfunction->parent_name) == 0.\n");
2740 printf("ERROR. dfunction->parent_name == NULL.\n");
2744 /* Adjust function name and type. */
2745 cached_function
= &cached_dfunction
->function
;
2746 MD_TRANSFER_STR(info
, &cached_function
->name
);
2747 cached_function
->type
= &cached_magic_vars
->types
[cached_function
->type
- remote_magic_vars
->types
];
2749 if (cached_dfunction
->prev
!= NULL
)
2750 cached_dfunction
->prev
= prev_dfunction
;
2752 dfunction_ptr
= &cached_dfunction
->next
;
2753 prev_dfunction
= cached_dfunction
;
2756 cached_magic_vars
->last_dfunction
= prev_dfunction
;
2762 PUBLIC
int st_transfer_metadata_types(st_init_info_t
*info
, struct _magic_vars_t
*cached_magic_vars
2763 , struct _magic_vars_t
*remote_magic_vars
, st_counterparts_t
*counterparts
)
2768 /* transfer types */
2769 MD_TRANSFER(info
, remote_magic_vars
->types
, (void **)&cached_magic_vars
->types
, remote_magic_vars
->types_num
* sizeof(struct _magic_type
));
2771 /* type adjustments */
2772 for (i
= 0 ; i
< cached_magic_vars
->types_num
; i
++) {
2773 if (transfer_metadata_type_members(info
, &cached_magic_vars
->types
[i
], cached_magic_vars
, remote_magic_vars
)) {
2774 printf("ERROR transferring type members metadata.\n");
2777 set_typename_key(&cached_magic_vars
->types
[i
]);
2783 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
)
2786 /* MD_TRANSFER cannot be used, because it will allocate space for num_elements */
2787 if (st_cbs_os
.copy_state_region(info
->info_opaque
, (uint32_t) type
->value_set
, sizeof(int), (uint32_t) &num_elements
)) {
2788 printf("ERROR transferring type value set metadata.\n");
2792 MD_TRANSFER(info
, type
->value_set
, (void **)&type
->value_set
, num_elements
*sizeof(int));
2796 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
)
2799 int num_child
= MAGIC_TYPE_NUM_CONTAINED_TYPES(type
), i
;
2801 MD_TRANSFER_STR(info
, &type
->name
);
2802 MD_TRANSFER_STR(info
, &type
->type_str
);
2804 if (type
->names
!= NULL
&& type
->num_names
> 0) {
2805 /* transfer array of name pointers */
2806 MD_TRANSFER(info
, type
->names
, (void **)&type
->names
, type
->num_names
* sizeof(char *));
2807 for (i
= 0 ; (unsigned int)i
< type
->num_names
; i
++) {
2808 /* transfer individual name */
2809 MD_TRANSFER_STR(info
, &type
->names
[i
]);
2814 #define MD_TRANSFER_ADJUST_MEMBER_PTR(NUM_ELEMENTS, \
2815 ELEMENT_SIZE,PTR_ARRAY,INDEX) \
2816 if((NUM_ELEMENTS) > 0 && (PTR_ARRAY) != NULL) { \
2817 MD_TRANSFER(info, PTR_ARRAY, (void **)&PTR_ARRAY, \
2818 NUM_ELEMENTS * ELEMENT_SIZE); \
2819 for(INDEX = 0 ; (INDEX) < (NUM_ELEMENTS) ; INDEX++) { \
2820 PTR_ARRAY[INDEX] = ADJUST_POINTER(cached_magic_vars->types, \
2821 remote_magic_vars->types, PTR_ARRAY[INDEX]); \
2825 MD_TRANSFER_ADJUST_MEMBER_PTR(
2826 (type
->type_id
== MAGIC_TYPE_FUNCTION
? num_child
+ 1 : num_child
),
2827 sizeof(struct _magic_type
*), type
->contained_types
, i
2830 if (type
->compatible_types
) {
2831 struct _magic_type
*comp_types_element
;
2832 int comp_types_size
=0;
2833 /* determine size of array */
2835 if (st_cbs_os
.copy_state_region(info
->info_opaque
, (uint32_t) &type
->compatible_types
[comp_types_size
]
2836 , sizeof(struct _magic_type
*), (uint32_t) &comp_types_element
))
2838 printf("ERROR transferring compatible types array metadata.\n");
2842 } while(comp_types_element
!= NULL
);
2843 /* We know the size, now transfer the whole array */
2844 MD_TRANSFER(info
, type
->compatible_types
, (void **) &type
->compatible_types
, comp_types_size
* sizeof(struct _magic_type
*));
2845 for (i
= 0; i
< comp_types_size
; i
++) {
2846 if (type
->compatible_types
[i
] != NULL
) {
2847 /* Adjust the pointer to point to the local counterpart */
2848 type
->compatible_types
[i
] = ADJUST_POINTER(cached_magic_vars
->types
, remote_magic_vars
->types
, type
->compatible_types
[i
]);
2853 if (num_child
>0 && type
->member_names
!= NULL
) {
2854 MD_TRANSFER(info
, type
->member_names
, (void **)&type
->member_names
, num_child
* sizeof(char *));
2855 for (i
= 0 ; i
< num_child
; i
++) {
2856 MD_TRANSFER_STR(info
, &type
->member_names
[i
]);
2860 if (num_child
>0 && type
->member_offsets
!= NULL
) {
2861 MD_TRANSFER(info
, type
->member_offsets
, (void **)&type
->member_offsets
, num_child
* sizeof(unsigned));
2864 if (MAGIC_TYPE_HAS_VALUE_SET(type
)) {
2865 r
= transfer_metadata_type_value_set(info
, type
, cached_magic_vars
, remote_magic_vars
);
2873 PRIVATE
int transfer_metadata_sentries(st_init_info_t
*info
, struct _magic_vars_t
*cached_magic_vars
2874 , struct _magic_vars_t
*remote_magic_vars
, st_counterparts_t
*counterparts
2875 , size_t *max_buff_sz
)
2879 int skipped_sentries
= 0;
2880 struct _magic_sentry
*cached_sentry
;
2882 /* transfer sentries */
2883 MD_TRANSFER(info
, remote_magic_vars
->sentries
, (void **)&cached_magic_vars
->sentries
, remote_magic_vars
->sentries_num
* sizeof(struct _magic_sentry
));
2884 /* todo: try to use only remote_magic_vars or cached magic_vars */
2885 /* todo: if transfer is complete, and argument 2 and 3 are always the same, remove 2nd argument */
2887 /* adjust sentries */
2888 for (i
= 0 ; i
< cached_magic_vars
->sentries_num
; i
++) {
2889 cached_sentry
= &cached_magic_vars
->sentries
[i
];
2891 if ((st_policies
& ST_TRANSFER_DIRTY_ONLY
) &&
2892 !MAGIC_STATE_FLAG(cached_sentry
, MAGIC_STATE_DIRTY_PAGE
) &&
2893 !MAGIC_STATE_FLAG(cached_sentry
, MAGIC_STATE_IMMUTABLE
)) {
2897 if (skipped_sentries
> 0) {
2898 cached_magic_vars
->sentries
[i
- skipped_sentries
] =
2899 cached_magic_vars
->sentries
[i
];
2900 cached_magic_vars
->sentries
[i
- skipped_sentries
].id
-=
2902 cached_sentry
= &cached_magic_vars
->sentries
[i
- skipped_sentries
];
2906 if (transfer_metadata_sentry_members(info
, cached_sentry
)) {
2907 printf("ERROR transferring sentry members metadata.\n");
2912 * We have to change the type to its cached counterpart,
2913 * so that it may be compared to the local type of the local sentry counterpart.
2915 cached_sentry
->type
= &cached_magic_vars
->types
[cached_sentry
->type
- remote_magic_vars
->types
];
2917 if (cached_sentry
->type
->size
> *max_buff_sz
) {
2918 *max_buff_sz
= cached_sentry
->type
->size
;
2922 if (skipped_sentries
> 0)
2923 cached_magic_vars
->sentries_num
-= skipped_sentries
;
2928 PRIVATE
int transfer_metadata_sentry_members(st_init_info_t
*info
, struct _magic_sentry
*sentry
)
2930 if (sentry
->name
!= NULL
) {
2931 MD_TRANSFER_STR(info
, &sentry
->name
);
2933 printf("ERROR. sentry->name == NULL.\n");
2939 PUBLIC
int st_transfer_metadata_dsentries(st_init_info_t
*info
, struct _magic_vars_t
*cached_magic_vars
2940 , struct _magic_vars_t
*remote_magic_vars
, st_counterparts_t
*counterparts
, size_t *max_buff_sz
, int *dsentries_num
)
2943 struct _magic_dsentry
**dsentry_ptr
;
2944 #if MAGIC_DSENTRY_ALLOW_PREV
2945 struct _magic_dsentry
*prev_dsentry
= NULL
;
2951 cached_magic_vars
->first_dsentry
= remote_magic_vars
->first_dsentry
;
2952 dsentry_ptr
= &cached_magic_vars
->first_dsentry
;
2953 while (*dsentry_ptr
!= NULL
) {
2955 struct _magic_dsentry
*cached_dsentry
, *remote_dsentry
= *dsentry_ptr
;
2956 struct _magic_sentry
*sentry
;
2958 /* transfer dsentry */
2959 MD_TRANSFER(info
, *dsentry_ptr
, (void **) dsentry_ptr
, sizeof(struct _magic_dsentry
));
2960 cached_dsentry
= *dsentry_ptr
;
2962 if ((st_policies
& ST_TRANSFER_DIRTY_ONLY
) &&
2963 !MAGIC_STATE_FLAG((&cached_dsentry
->sentry
), MAGIC_STATE_DIRTY_PAGE
) &&
2964 !MAGIC_STATE_FLAG((&cached_dsentry
->sentry
), MAGIC_STATE_IMMUTABLE
)) {
2965 *dsentry_ptr
= cached_dsentry
->next
;
2969 if (cached_magic_vars
->first_stack_dsentry
== remote_dsentry
) {
2970 cached_magic_vars
->first_stack_dsentry
= cached_dsentry
;
2971 } else if(cached_magic_vars
->last_stack_dsentry
== remote_dsentry
) {
2972 cached_magic_vars
->last_stack_dsentry
= cached_dsentry
;
2975 /* adjust dsentry */
2976 if (cached_dsentry
->parent_name
!= NULL
) {
2977 MD_TRANSFER_STR(info
, &cached_dsentry
->parent_name
);
2978 if (strlen(cached_dsentry
->parent_name
) == 0) {
2979 printf("ERROR. strlen(dsentry->parent_name) == 0.\n");
2980 #if TODO_DSENTRY_PARENT_NAME_BUG
2981 if (cached_dsentry
->next
!= NULL
)
2986 printf("ERROR. dsentry->parent_name == NULL.\n");
2990 sentry
= &cached_dsentry
->sentry
;
2991 if (transfer_metadata_sentry_members(info
, sentry
)) {
2992 printf("ERROR transferring sentry members metadata.\n");
2996 /* Override original id to simplify pairing later. */
2997 sentry
->id
= cached_magic_vars
->sentries_num
+ *dsentries_num
+ 1;
3000 * Report violations for all the pointers pointing to the initial stack area.
3001 * This is to make sure no assumption is incorrectly made about this area.
3003 if (!strcmp(sentry
->name
, MAGIC_ALLOC_INITIAL_STACK_NAME
)) {
3004 sentry
->flags
|= MAGIC_STATE_ADDR_NOT_TAKEN
;
3008 * Adjust the type, so that the local and remote type can be compared
3009 * during a server version update
3011 if (sentry
->type
== &remote_dsentry
->type
) {
3014 * sentry->type is contained in dsentry.type. Therefore, this is an
3015 * array type. In order to allocate a new memory region, we only
3016 * need the size of the type, and the contained type as arguments
3017 * to the magic allocation function. Therefore, other members of
3018 * the type do need to be cached or adjusted.
3021 /* Adjust pointer to cached location */
3022 sentry
->type
= &cached_dsentry
->type
;
3024 /* Adjust contained_types to type_array located in dsentry struct. */
3025 sentry
->type
->contained_types
= cached_dsentry
->type_array
;
3028 * Adjust only pointer in type_array. It currently has the same
3029 * value as the remote copy, but it has to point to the cached
3030 * of the contained type.
3032 sentry
->type
->contained_types
[0] = &cached_magic_vars
->types
[sentry
->type
->contained_types
[0] - remote_magic_vars
->types
];
3034 /* Adjust empty strings. */
3035 sentry
->type
->name
= "";
3036 sentry
->type
->type_str
= "";
3038 /* Adjust value set if necessary. */
3039 if (MAGIC_TYPE_HAS_VALUE_SET(sentry
->type
)) {
3040 r
= transfer_metadata_type_value_set(info
, sentry
->type
, cached_magic_vars
, remote_magic_vars
);
3048 * sentry.type must be in the global type array. Adjust pointer accordingly.
3049 * The pointer is still pointing to the remote version.
3050 * We have to change it to the cached version.
3052 sentry
->type
= &cached_magic_vars
->types
[sentry
->type
- remote_magic_vars
->types
];
3056 /* see if the buffer needs to be bigger for the dsentry data region. */
3057 if (!MAGIC_STATE_FLAG(sentry
, MAGIC_STATE_OUT_OF_BAND
) && *max_buff_sz
< sentry
->type
->size
) {
3058 *max_buff_sz
= sentry
->type
->size
;
3061 dsentry_ptr
= &cached_dsentry
->next
;
3062 #if MAGIC_DSENTRY_ALLOW_PREV
3063 if (cached_dsentry
->prev
!= NULL
)
3064 cached_dsentry
->prev
= prev_dsentry
;
3065 prev_dsentry
= cached_dsentry
;
3067 *dsentries_num
= *dsentries_num
+ 1;
3073 PRIVATE
int pair_metadata_types(st_init_info_t
*info
,
3074 struct _magic_vars_t
*cached_magic_vars
, st_counterparts_t
*counterparts
, int allow_unpaired_types
)
3076 int i
, j
, num_unpaired_struct_types
= 0;
3077 int num_unpaired_types
= 0;
3078 int num_total_types
= 0;
3079 int num_struct_types
= 0;
3080 int num_unpaired_types_left
, num_unpaired_struct_types_left
;
3082 if (st_unpaired_types_ratio
> 0 || st_unpaired_struct_types_ratio
> 0) {
3083 for (i
= 0 ; i
< cached_magic_vars
->types_num
; i
++) {
3084 struct _magic_type
*type
= &cached_magic_vars
->types
[i
];
3085 if (ST_IS_UNPAIRABLE_STRUCT_TYPE(type
)) {
3088 if (ST_IS_UNPAIRABLE_TYPE(type
)) {
3092 num_unpaired_types
= (int) (st_unpaired_types_ratio
*num_total_types
);
3093 num_unpaired_struct_types
= (int) (st_unpaired_struct_types_ratio
*num_struct_types
);
3095 num_unpaired_types_left
= num_unpaired_types
;
3096 num_unpaired_struct_types_left
= num_unpaired_struct_types
;
3098 /* type pairing, remote->local */
3099 for(i
= 0 ; i
< cached_magic_vars
->types_num
; i
++) {
3100 struct _magic_type
*type
= &cached_magic_vars
->types
[i
];
3101 counterparts
->types
[i
].counterpart
= NULL
;
3103 if (num_unpaired_types_left
> 0 && ST_IS_UNPAIRABLE_TYPE(type
)) {
3104 num_unpaired_types_left
--;
3107 else if (num_unpaired_struct_types_left
> 0 && ST_IS_UNPAIRABLE_STRUCT_TYPE(type
)) {
3108 num_unpaired_struct_types_left
--;
3112 for (j
= 0 ; j
< _magic_types_num
; j
++) {
3113 /* A remote type may be paired to multiple local types.
3114 * It is safe to index only the first type since counterparts
3115 * are only used to speed up type matching.
3117 if (magic_type_compatible(type
, &_magic_types
[j
], MAGIC_TYPE_COMPARE_ALL
)) {
3118 counterparts
->types
[i
].counterpart
= &_magic_types
[j
];
3123 if (!allow_unpaired_types
&& counterparts
->types
[i
].counterpart
== NULL
) {
3124 printf("ERROR, remote type cannot be paired with a local type: ");
3125 MAGIC_TYPE_PRINT(type
, MAGIC_EXPAND_TYPE_STR
);
3130 if (st_unpaired_types_ratio
> 0 || st_unpaired_struct_types_ratio
> 0) {
3131 assert(num_unpaired_types_left
== 0 && (st_unpaired_types_ratio
> 0 || num_unpaired_struct_types
== 0));
3132 _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
);
3135 for (i
= 0 ; i
< cached_magic_vars
->types_num
; i
++) {
3136 struct _magic_type
*type
= &cached_magic_vars
->types
[i
];
3137 struct _magic_type
*local_type
= (struct _magic_type
*) counterparts
->types
[i
].counterpart
;
3138 counterparts
->ptr_types
[i
].counterpart
= NULL
;
3139 if (local_type
&& type
->type_id
== MAGIC_TYPE_POINTER
) {
3140 if (MAGIC_TYPE_HAS_COMP_TYPES(type
) != MAGIC_TYPE_HAS_COMP_TYPES(local_type
)) {
3143 if (MAGIC_TYPE_HAS_COMP_TYPES(type
)) {
3145 while (MAGIC_TYPE_HAS_COMP_TYPE(type
, j
) && MAGIC_TYPE_HAS_COMP_TYPE(local_type
, j
)) {
3146 struct _magic_type
*ctype
= MAGIC_TYPE_COMP_TYPE(type
, j
);
3147 struct _magic_type
*local_ctype
= MAGIC_TYPE_COMP_TYPE(local_type
, j
);
3148 if (!ST_TYPE_IS_CACHED_COUNTERPART(ctype
, local_ctype
)) {
3153 if (MAGIC_TYPE_HAS_COMP_TYPE(type
, j
) || MAGIC_TYPE_HAS_COMP_TYPE(local_type
, j
)) {
3157 counterparts
->ptr_types
[i
].counterpart
= local_type
;
3164 PRIVATE
int pair_metadata_functions(st_init_info_t
*info
,
3165 struct _magic_vars_t
*cached_magic_vars
, st_counterparts_t
*counterparts
)
3168 struct _magic_function
*cached_function
, *local_function
;
3169 #if ST_DEBUG_LEVEL > 0
3170 int num_relocated
= 0;
3173 /* map remote functions to local functions */
3174 for(i
= 0 ; i
< cached_magic_vars
->functions_num
; i
++) {
3175 cached_function
= &cached_magic_vars
->functions
[i
];
3176 local_function
= NULL
;
3177 st_map_functions(&cached_function
, &local_function
);
3178 ST_SET_CACHED_COUNTERPART(cached_function
, functions
, functions
, local_function
);
3180 #if CHECK_SENTITY_PAIRS
3181 if (local_function
) {
3182 /* debug: see if the function is paired more than once */
3183 struct _magic_function
*cfunction
= NULL
;
3184 st_map_functions(&cfunction
, &local_function
);
3185 if (cfunction
!= cached_function
) {
3186 printf("function pairing failed for (1) local function linked to multiple remote functions (2), (3)\n");
3187 printf("(1) "); MAGIC_FUNCTION_PRINT(local_function
, 0); printf("\n");
3188 printf("(2) "); MAGIC_FUNCTION_PRINT(cached_function
, 0); printf("\n");
3189 printf("(3) "); MAGIC_FUNCTION_PRINT(cfunction
, 0); printf("\n");
3195 #if ST_DEBUG_LEVEL > 0
3196 if (local_function
&& cached_function
->address
!= local_function
->address
) {
3198 if (ST_DEBUG_LEVEL
> 1) {
3199 printf("- relocated function: '%s'\n", cached_magic_vars
->functions
[i
].name
);
3205 #if ST_DEBUG_LEVEL > 0
3206 printf("total remote functions: %d. relocated: %d\n", cached_magic_vars
->functions_num
, num_relocated
);
3212 PRIVATE
int pair_metadata_sentries(st_init_info_t
*info
,
3213 struct _magic_vars_t
*cached_magic_vars
, st_counterparts_t
*counterparts
)
3216 struct _magic_sentry
*cached_sentry
, *local_sentry
;
3217 #if ST_DEBUG_LEVEL > 0
3218 int num_relocated_str
= 0, num_relocated_normal
= 0;
3221 /* pair sentries remote->local */
3222 for (i
= 0 ; i
< cached_magic_vars
->sentries_num
; i
++) {
3223 void *local_data_addr
= NULL
;
3224 cached_sentry
= &cached_magic_vars
->sentries
[i
];
3226 /* String data is transferred directly. */
3227 if (MAGIC_SENTRY_IS_STRING(cached_sentry
)) {
3228 char *string
= st_buff_allocate(info
, cached_sentry
->type
->size
);
3230 printf("ERROR allocating string.\n");
3233 r
= st_cbs_os
.copy_state_region(info
->info_opaque
, (uint32_t) cached_sentry
->address
,
3234 cached_sentry
->type
->size
, (uint32_t) string
);
3236 printf("ERROR transferring string.\n");
3239 local_data_addr
= string
;
3241 ST_SET_CACHED_COUNTERPART(cached_sentry
, sentries
, sentries_data
, local_data_addr
);
3243 local_sentry
= NULL
;
3244 st_map_sentries(&cached_sentry
, &local_sentry
);
3245 ST_SET_CACHED_COUNTERPART(cached_sentry
, sentries
, sentries
, local_sentry
);
3247 #if CHECK_SENTITY_PAIRS
3248 if (local_sentry
&& !MAGIC_SENTRY_IS_STRING(cached_sentry
)) {
3249 /* debug: see if the non-string sentry is paired more than once */
3250 struct _magic_sentry
*csentry
= NULL
;
3251 st_map_sentries(&csentry
, &local_sentry
);
3252 if (csentry
!= cached_sentry
) {
3253 printf("sentry pairing failed for (1) local sentry linked to multiple remote sentries (2), (3)\n");
3254 printf("(1) "); MAGIC_SENTRY_PRINT(local_sentry
, 0); printf("\n");
3255 printf("(2) "); MAGIC_SENTRY_PRINT(cached_sentry
, 0); printf("\n");
3256 printf("(3) "); MAGIC_SENTRY_PRINT(csentry
, 0); printf("\n");
3262 #if ST_DEBUG_LEVEL > 0
3263 if (local_sentry
&& cached_sentry
->address
!= local_sentry
->address
) {
3264 if (MAGIC_SENTRY_IS_STRING(cached_sentry
)) {
3265 num_relocated_str
++;
3268 num_relocated_normal
++;
3269 if (ST_DEBUG_LEVEL
> 1) {
3270 printf("- relocated non-string sentry: '%s'\n", cached_sentry
->name
);
3277 #if ST_DEBUG_LEVEL > 0
3278 printf("total remote sentries: %d. relocated normal: %d relocated string: %d\n", cached_magic_vars
->sentries_num
, num_relocated_normal
, num_relocated_str
);
3284 #if ST_ASSUME_RAW_COPY_BEFORE_TRANSFER
3285 PRIVATE
int allocate_pair_metadata_dsentries_from_raw_copy(st_init_info_t
*info
,
3286 struct _magic_vars_t
*cached_magic_vars
, st_counterparts_t
*counterparts
)
3288 struct _magic_dsentry
*dsentry
;
3289 int remote_dsentries
= 0, unpaired_dsentries
= 0;
3291 #if ST_DEBUG_LEVEL > 3
3292 EXEC_WITH_MAGIC_VARS(
3293 magic_print_dsentries();
3294 , &st_cached_magic_vars
3296 magic_print_dsentries();
3299 dsentry
= cached_magic_vars
->first_dsentry
;
3300 while (dsentry
!= NULL
) {
3301 struct _magic_sentry
*local_sentry
= NULL
, *sentry
= MAGIC_DSENTRY_TO_SENTRY(dsentry
);
3303 /* Initialize counterpart to NULL. */
3304 ST_SET_CACHED_COUNTERPART(sentry
, sentries
, sentries
, NULL
);
3308 if (!MAGIC_STATE_FLAG(sentry
, MAGIC_STATE_STACK
) && !MAGIC_STATE_FLAG(sentry
, MAGIC_STATE_LIB
)) {
3309 local_sentry
= MAGIC_DSENTRY_TO_SENTRY((struct _magic_dsentry
*)MAGIC_PTR_FROM_DATA(sentry
->address
));
3311 #if MAGIC_LOOKUP_SENTRY_ALLOW_RANGE_INDEX
3312 EXEC_WITH_MAGIC_VARS(
3313 local_sentry
= magic_sentry_lookup_by_range(sentry
->address
, NULL
);
3314 , &st_cached_magic_vars
3317 local_sentry
= magic_sentry_lookup_by_addr(sentry
->address
, NULL
);
3321 if (!local_sentry
) {
3322 unpaired_dsentries
++;
3323 #if ST_DEBUG_LEVEL > 2
3324 printf("allocate_pair_metadata_dsentries_from_raw_copy: found unpaired "); MAGIC_DSENTRY_PRINT(dsentry
, MAGIC_EXPAND_TYPE_STR
); _magic_printf("\n");
3327 ST_SET_CACHED_COUNTERPART(sentry
, sentries
, sentries
, local_sentry
);
3328 dsentry
= dsentry
->next
;
3331 #if ST_DEBUG_LEVEL > 0
3332 printf("total remote dsentries: %d (%d unpaired)\n", remote_dsentries
, unpaired_dsentries
);
3340 PRIVATE
int allocate_pair_metadata_dsentries(st_init_info_t
*info
,
3341 struct _magic_vars_t
*cached_magic_vars
, st_counterparts_t
*counterparts
)
3343 struct _magic_dsentry
*dsentry
= cached_magic_vars
->first_dsentry
, *local_dsentry
;
3344 int remote_dsentries
= 0;
3346 int *local_sentry_paired_by_id
= st_buff_allocate(info
, (_magic_sentries_next_id
+ 1) * sizeof(int));
3349 #if ST_DEBUG_LEVEL > 3
3350 EXEC_WITH_MAGIC_VARS(
3351 magic_print_dsentries();
3352 , &st_cached_magic_vars
3354 magic_print_dsentries();
3359 * Since on MINIX the mmaped regions are inherited in the new process,
3360 * we must first deallocate them. This is not the case on Linux.
3362 while (dsentry
!= NULL
) {
3364 struct _magic_sentry
*sentry
= MAGIC_DSENTRY_TO_SENTRY(dsentry
);
3365 int size
= sentry
->type
->size
;
3366 /* For mmap first unmap the old region that is already mapped into this new instance */
3367 if (!MAGIC_STATE_FLAG(sentry
, MAGIC_STATE_OUT_OF_BAND
)
3368 && MAGIC_STATE_REGION(sentry
) == MAGIC_STATE_MAP
3369 && !USE_PRE_ALLOCATED_BUFFER(info
)
3373 * The 'ext' field in the dsentry is used here to record
3374 * the padding for ASR.
3376 size_t padding
= (size_t) dsentry
->ext
;
3378 * call munmap(). ptr and size have to be altered,
3379 * in order to free the preceding page, containing the dsentry struct, too.
3381 MAGIC_MEM_WRAPPER_BLOCK(
3382 res
= munmap((char *)sentry
->address
- magic_get_sys_pagesize(), size
+ magic_get_sys_pagesize() + padding
);
3385 printf("ERROR, munmap returned NULL.\n");
3389 dsentry
= dsentry
->next
;
3393 /* Permute dsentries in case of ASR. */
3394 if (info
->flags
& ST_LU_ASR
) {
3395 magic_asr_permute_dsentries(&cached_magic_vars
->first_dsentry
);
3398 dsentry
= cached_magic_vars
->first_dsentry
;
3399 while (dsentry
!= NULL
) {
3400 struct _magic_sentry
*local_sentry
, *sentry
= MAGIC_DSENTRY_TO_SENTRY(dsentry
);
3401 int is_alloc_dsentry
= MAGIC_SENTRY_IS_ALLOC(sentry
);
3403 struct _magic_dsindex
*local_dsindex
;
3408 /* Cannot deal with dead dsentries. */
3409 assert(dsentry
->magic_state
== MAGIC_DSENTRY_MSTATE_ALIVE
);
3412 * If there are dead dsentries, we simply skip them.
3414 if (dsentry
->magic_state
!= MAGIC_DSENTRY_MSTATE_ALIVE
) {
3415 dsentry
= dsentry
->next
;
3420 /* Initialize counterpart to NULL. */
3421 ST_SET_CACHED_COUNTERPART(sentry
, sentries
, sentries
, NULL
);
3423 /* Handle non-alloc dsentries first. */
3424 if (!is_alloc_dsentry
) {
3425 local_sentry
= magic_sentry_lookup_by_name(dsentry
->parent_name
,
3426 sentry
->name
, dsentry
->site_id
, NULL
);
3428 assert(!MAGIC_SENTRY_IS_ALLOC(local_sentry
));
3429 ST_SET_CACHED_COUNTERPART(sentry
, sentries
, sentries
, local_sentry
);
3432 dsentry
= dsentry
->next
;
3436 /* Out-of-band alloc dsentries next. */
3437 if (MAGIC_STATE_FLAG(sentry
, MAGIC_STATE_OUT_OF_BAND
)) {
3438 struct _magic_type
*type
;
3439 /* We can only handle obdsentries with the magic void type, transferred as-is. */
3440 if (sentry
->type
!= &dsentry
->type
) {
3441 /* Not an array type */
3442 type
= sentry
->type
;
3444 /* This is an array type, use its contained type instead. */
3445 type
= sentry
->type
->contained_types
[0];
3447 /* We now have the cached version of the type. Compare it to magic void type */
3448 if (!magic_type_compatible(type
, MAGIC_VOID_TYPE
, MAGIC_TYPE_COMPARE_ALL
)) {
3449 printf("Can't handle obdsentry with non-void type\n");
3453 /* On MINIX we need to recreate all the obdsentries. */
3454 struct _magic_obdsentry
*obdsentry
;
3455 int size
= sentry
->type
->size
;
3456 obdsentry
= magic_create_obdsentry(sentry
->address
,
3457 MAGIC_VOID_TYPE
, size
, MAGIC_STATE_REGION(sentry
), sentry
->name
, dsentry
->parent_name
);
3458 if (obdsentry
== NULL
) {
3459 printf("ERROR, magic_create_obdsentry returned NULL.\n");
3462 local_dsentry
= MAGIC_OBDSENTRY_TO_DSENTRY(obdsentry
);
3464 /* On Linux we only need to pair them. */
3465 local_sentry
= magic_sentry_lookup_by_name(
3466 MAGIC_SENTRY_PARENT(sentry
), sentry
->name
,
3467 MAGIC_SENTRY_SITE_ID(sentry
), NULL
);
3468 if (local_sentry
== NULL
) {
3469 printf("Unable to pair obdsentry.\n");
3472 local_dsentry
= MAGIC_DSENTRY_FROM_SENTRY(local_sentry
);
3474 ST_SET_CACHED_COUNTERPART(sentry
, sentries
, sentries
, MAGIC_DSENTRY_TO_SENTRY(local_dsentry
));
3475 dsentry
= dsentry
->next
;
3479 /* Handle regular alloc dsentries last. */
3482 * For Linux, first pair INIT time remote
3483 * dsentries with local dsentries.
3486 if (MAGIC_STATE_FLAG(sentry
, MAGIC_STATE_INIT
)) {
3487 local_sentry
= NULL
;
3489 if (MAGIC_STATE_FLAG(sentry
, MAGIC_STATE_IMMUTABLE
)) {
3491 * Immutable init time dsentries should have already been
3492 * preallocated, so just pair them by address.
3494 local_sentry
= magic_sentry_lookup_by_addr(sentry
->address
, NULL
);
3496 #if MAGIC_LOOKUP_SENTRY_ALLOW_NAME_HASH
3497 struct _magic_sentry_list
*local_sentry_list
;
3498 local_sentry_list
= magic_sentry_list_lookup_by_name_hash(
3499 dsentry
->parent_name
, sentry
->name
, dsentry
->site_id
, NULL
);
3501 while (local_sentry_list
) {
3502 if (!local_sentry_paired_by_id
[local_sentry_list
->sentry
->id
]) {
3503 local_sentry
= local_sentry_list
->sentry
;
3506 local_sentry_list
= local_sentry_list
->next
;
3511 struct _magic_dsentry
*prev_dsentry
, *tmp_dsentry
;
3512 struct _magic_sentry
*tmp_sentry
;
3513 MAGIC_DSENTRY_LOCK();
3514 MAGIC_DSENTRY_ALIVE_ITER(_magic_first_dsentry
, prev_dsentry
,
3515 tmp_dsentry
, tmp_sentry
,
3516 if (!strcmp(tmp_sentry
->name
, sentry
->name
)) {
3517 if (!dsentry
->parent_name
||
3518 !strcmp(MAGIC_SENTRY_PARENT(tmp_sentry
), dsentry
->parent_name
)) {
3519 if (dsentry
->site_id
== MAGIC_DSENTRY_SITE_ID_NULL
||
3520 tmp_dsentry
->site_id
== dsentry
->site_id
) {
3521 if (!local_sentry_paired_by_id
[tmp_sentry
->id
]) {
3522 local_sentry
= tmp_sentry
;
3529 MAGIC_DSENTRY_UNLOCK();
3534 ST_SET_CACHED_COUNTERPART(sentry
, sentries
, sentries
, local_sentry
);
3535 local_sentry_paired_by_id
[local_sentry
->id
] = 1;
3536 dsentry
= dsentry
->next
;
3543 * Just recreate all the other dsentries. Immutable objects will
3544 * have already been inherited and allocate_local_dsentry() will
3545 * not reallocate them, but instead it will just create a new
3546 * local dsentry in the right place.
3548 local_dsindex
= magic_dsindex_lookup_by_name(dsentry
->parent_name
, sentry
->name
);
3549 if (local_dsindex
|| MAGIC_SENTRY_IS_LIB_ALLOC(sentry
)) {
3551 /* Allocate a new local dsentry and pair it with the remote. */
3552 res
= allocate_local_dsentry(info
, local_dsindex
, 0, 0, NULL
, &local_dsentry
, dsentry
, NULL
);
3553 if (res
!= ENOSYS
) {
3557 assert(local_dsentry
);
3558 ST_SET_CACHED_COUNTERPART(sentry
, sentries
, sentries
, MAGIC_DSENTRY_TO_SENTRY(local_dsentry
));
3561 dsentry
= dsentry
->next
;
3564 #if ST_DEBUG_LEVEL > 0
3565 printf("total remote dsentries: %d\n", remote_dsentries
);
3571 PRIVATE
int deallocate_nonxferred_dsentries(struct _magic_dsentry
*first_dsentry
, st_counterparts_t
*counterparts
)
3573 struct _magic_dsentry
*dsentry
= first_dsentry
;
3574 struct _magic_sentry
*local_sentry
;
3576 while (dsentry
!= NULL
) {
3577 struct _magic_sentry
*sentry
= MAGIC_DSENTRY_TO_SENTRY(dsentry
);
3578 int is_paired_dsentry
= ST_HAS_CACHED_COUNTERPART(sentry
, sentries
);
3579 int is_alloc_dsentry
= MAGIC_SENTRY_IS_ALLOC(sentry
);
3580 ST_GET_CACHED_COUNTERPART(sentry
, sentries
, sentries
, local_sentry
);
3582 if (MAGIC_STATE_EXTF_GET(sentry
, ST_TRANSFER_DONE
) || !is_alloc_dsentry
) {
3583 dsentry
= dsentry
->next
;
3587 /* Report non-transferred alloc dsentries when requested. */
3588 if (is_paired_dsentry
&& (st_policies
& ST_REPORT_NONXFERRED_ALLOCS
)) {
3589 printf("deallocate_nonxferred_dsentries: Non-transferred dsentry found: ");
3590 MAGIC_DSENTRY_PRINT(dsentry
, MAGIC_EXPAND_TYPE_STR
);
3593 if (!is_paired_dsentry
&& (st_policies
& ST_REPORT_NONXFERRED_UNPAIRED_ALLOCS
)) {
3594 printf("deallocate_nonxferred_dsentries: Non-transferred unpaired dsentry found: ");
3595 MAGIC_DSENTRY_PRINT(dsentry
, MAGIC_EXPAND_TYPE_STR
);
3599 if (!is_paired_dsentry
) {
3600 dsentry
= dsentry
->next
;
3603 assert(local_sentry
);
3604 if (MAGIC_SENTRY_IS_ALLOC(local_sentry
)) {
3605 deallocate_local_dsentry(MAGIC_DSENTRY_FROM_SENTRY(local_sentry
));
3607 dsentry
= dsentry
->next
;
3614 PRIVATE
void deallocate_local_dsentry(struct _magic_dsentry
*local_dsentry
)
3616 int r
, dsentry_type
;
3617 struct _magic_sentry
*local_sentry
= MAGIC_DSENTRY_TO_SENTRY(local_dsentry
);
3619 assert(MAGIC_SENTRY_IS_ALLOC(local_sentry
));
3620 dsentry_type
= MAGIC_STATE_FLAG(local_sentry
, MAGIC_STATE_OUT_OF_BAND
) ? MAGIC_STATE_OUT_OF_BAND
: MAGIC_STATE_REGION(local_sentry
);
3621 /* A MAP_SHARED region will have both MAGIC_STATE_MAP and MAGIC_STATE_SHM. */
3622 if (dsentry_type
== (MAGIC_STATE_MAP
| MAGIC_STATE_SHM
))
3623 dsentry_type
= MAGIC_STATE_MAP
;
3625 MAGIC_MEM_WRAPPER_BEGIN();
3626 switch (dsentry_type
) {
3627 case MAGIC_STATE_HEAP
:
3629 magic_free(local_sentry
->address
);
3632 case MAGIC_STATE_MAP
:
3634 r
= magic_munmap(local_sentry
->address
, local_sentry
->type
->size
);
3636 printf("Warning: magic_munmap failed for ");
3637 MAGIC_DSENTRY_PRINT(local_dsentry
, 0);
3643 case MAGIC_STATE_SHM
:
3645 r
= magic_shmdt(local_sentry
->address
);
3647 printf("Warning: magic_shmdt failed for ");
3648 MAGIC_DSENTRY_PRINT(local_dsentry
, 0);
3654 case MAGIC_STATE_OUT_OF_BAND
:
3655 /* out-of-band dsentry. */
3656 r
= magic_destroy_obdsentry_by_addr(local_sentry
->address
);
3658 printf("Warning: magic_destroy_obdsentry_by_addr failed for ");
3659 MAGIC_DSENTRY_PRINT(local_dsentry
, 0);
3665 st_cbs_os
.panic("ERROR. UNSUPPORTED DSENTRY TYPE: %d\n", dsentry_type
);
3667 MAGIC_MEM_WRAPPER_END();
3670 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
)
3672 struct _magic_dsentry
*local_dsentry
= NULL
;
3673 struct _magic_sentry
*cached_sentry
= NULL
;
3674 const char *name
, *parent_name
;
3675 struct _magic_type
*type
;
3678 union __alloc_flags alloc_flags
;
3680 /* Either a dsindex or a dsentry needs to be set. */
3681 assert(local_dsindex
|| cached_dsentry
);
3684 cached_sentry
= MAGIC_DSENTRY_TO_SENTRY(cached_dsentry
);
3686 /* name, parent_name: local_dsindex || cached_dsentry. */
3687 if (local_dsindex
) {
3688 assert(MAGIC_DSINDEX_IS_ALLOC(local_dsindex
));
3689 name
= local_dsindex
->name
;
3690 parent_name
= local_dsindex
->parent_name
;
3692 assert(MAGIC_SENTRY_IS_ALLOC(cached_sentry
));
3694 * The external allocation parent_name needs to be readjusted.
3695 * The external allocation name is adjusted after the new dsentry
3698 name
= cached_sentry
->name
;
3699 if (!strcmp(cached_dsentry
->parent_name
, MAGIC_ALLOC_EXT_PARENT_NAME
)) {
3700 parent_name
= MAGIC_ALLOC_EXT_PARENT_NAME
;
3702 int found_parent_name
= 0;
3703 struct _magic_sodesc
*sodesc
;
3704 struct _magic_dsodesc
*dsodesc
;
3705 MAGIC_DSODESC_LOCK();
3706 MAGIC_SODESC_ITER(_magic_first_sodesc
, sodesc
,
3707 if (!strcmp(cached_dsentry
->parent_name
, sodesc
->lib
.name
)) {
3708 parent_name
= (const char *)sodesc
->lib
.name
;
3709 found_parent_name
= 1;
3713 if (!found_parent_name
) {
3714 MAGIC_DSODESC_ITER(_magic_first_dsodesc
, dsodesc
,
3715 if (!strcmp(cached_dsentry
->parent_name
, dsodesc
->lib
.name
)) {
3716 parent_name
= (const char *)dsodesc
->lib
.name
;
3717 found_parent_name
= 1;
3722 MAGIC_DSODESC_UNLOCK();
3723 assert(found_parent_name
&& "Invalid parent name for cached dsentry!");
3727 /* num_elements: args || cached_sentry. */
3728 if (num_elements
<= 0 && cached_sentry
) {
3729 num_elements
= cached_sentry
->type
->type_id
== MAGIC_TYPE_ARRAY
?
3730 cached_sentry
->type
->num_child_types
: 1;
3732 assert(num_elements
> 0);
3734 /* alloc_flags: args || cached_dsentry. */
3735 if (!p_alloc_flags
) {
3736 if (cached_dsentry
&& MAGIC_SENTRY_IS_ALLOC(cached_sentry
)) {
3737 alloc_flags
= cached_dsentry
->alloc_flags
;
3740 alloc_flags
= *p_alloc_flags
;
3743 /* is_type_mismatch: args || cached_dsentry. */
3744 if (!is_type_mismatch
&& cached_dsentry
)
3745 is_type_mismatch
= MAGIC_STATE_FLAG(cached_sentry
, MAGIC_STATE_TYPE_SIZE_MISMATCH
);
3748 * Use old address for immutable objects.
3750 /* ptr: args || cached_sentry. */
3751 if (!ptr
&& cached_sentry
&&
3752 MAGIC_STATE_FLAG(cached_sentry
, MAGIC_STATE_IMMUTABLE
))
3753 ptr
= cached_sentry
->address
;
3755 /* region: local_dsindex || cached_sentry. */
3757 region
= MAGIC_STATE_REGION(local_dsindex
);
3759 region
= MAGIC_STATE_REGION(cached_sentry
);
3761 /* Check if the region is ambigous. This shouldn't happen. */
3762 assert(!((region
& (MAGIC_STATE_HEAP
| MAGIC_STATE_MAP
)) ==
3763 (MAGIC_STATE_HEAP
| MAGIC_STATE_MAP
)) &&
3764 "MAGIC_STATE_HEAP | MAGIC_STATE_MAP detected!");
3766 if ((region
& (MAGIC_STATE_HEAP
| MAGIC_STATE_MAP
)) ==
3767 (MAGIC_STATE_HEAP
| MAGIC_STATE_MAP
)) {
3768 /* Check call flags to determine what to do in the ambiguous cases. */
3769 region
= (alloc_flags
.mmap_flags
&& alloc_flags
.mmap_prot
) ?
3770 MAGIC_STATE_MAP
: MAGIC_STATE_HEAP
;
3774 /* type: local_dsindex || cached_sentry. */
3775 if (local_dsindex
) {
3776 type
= local_dsindex
->type
;
3778 if (num_elements
> 1 && MAGIC_TYPE_FLAG(local_dsindex
->type
, MAGIC_TYPE_VARSIZE
)) {
3779 size
= magic_type_alloc_get_varsized_array_size(local_dsindex
->type
, num_elements
);
3782 if (is_type_mismatch
) {
3783 type
= MAGIC_VOID_TYPE
;
3784 printf("WARNING: Type size mismatch dsentry detected! Ignoring dsindex type and reverting to MAGIC_TYPE_VOID.\n");
3785 printf("name=%s, parent_name=%s\n", local_dsindex
->name
, local_dsindex
->parent_name
);
3787 size
= num_elements
* type
->size
;
3791 * The type will need adjusting later.
3793 type
= cached_sentry
->type
;
3797 *local_dsentry_ptr
= NULL
;
3799 if (region
& MAGIC_STATE_HEAP
) {
3801 ptr
= magic_malloc_positioned(type
, name
, parent_name
, size
, (ptr
== NULL
? NULL
: MAGIC_PTR_FROM_DATA(ptr
)));
3803 printf("ERROR, magic_malloc_positioned returned NULL.\n");
3806 memset(ptr
, 0, size
);
3807 local_dsentry
= MAGIC_PTR_TO_DSENTRY(MAGIC_PTR_FROM_DATA(ptr
));
3809 else if (region
& MAGIC_STATE_MAP
) {
3811 if (!alloc_flags
.mmap_flags
|| !alloc_flags
.mmap_prot
) {
3812 /* We need call_flags to perform mmap. */
3815 ptr
= persistent_mmap(type
, name
, parent_name
, info
, NULL
, size
,
3816 alloc_flags
.mmap_prot
, alloc_flags
.mmap_flags
, -1, 0, ptr
);
3818 printf("ERROR, persistent_mmap returned NULL.\n");
3821 if (!(alloc_flags
.mmap_flags
& MAP_SHARED
))
3822 memset(ptr
, 0, size
);
3823 local_dsentry
= MAGIC_PTR_TO_DSENTRY(MAGIC_PTR_FROM_DATA(ptr
));
3826 else if (region
& MAGIC_STATE_SHM
) {
3828 if (!alloc_flags
.shmat_flags
|| !alloc_flags
.shmat_shmid
) {
3829 /* We need call_flags to perform shmat. */
3832 ptr
= magic_shmat(type
, name
, parent_name
, alloc_flags
.shmat_shmid
,
3833 ptr
, alloc_flags
.shmat_flags
);
3835 printf("ERROR, magic_shmat returned NULL.\n");
3838 local_dsentry
= MAGIC_PTR_TO_DSENTRY(MAGIC_PTR_FROM_DATA(ptr
));
3842 if (local_dsindex
) {
3843 printf("ERROR. UNSUPPORTED DSINDEX TYPE: ");
3844 MAGIC_DSINDEX_PRINT(local_dsindex
, MAGIC_EXPAND_TYPE_STR
);
3846 printf("ERROR. UNSUPPORTED DSENTRY: ");
3847 MAGIC_DSENTRY_PRINT(cached_dsentry
, MAGIC_EXPAND_TYPE_STR
);
3853 if (!local_dsindex
) {
3855 * This was an externally allocated type and, as such, needs adjusting.
3857 assert(cached_sentry
->type
== &cached_dsentry
->type
);
3858 local_dsentry
->type
= cached_dsentry
->type
;
3859 if (cached_dsentry
->type_array
[0]->type_id
== MAGIC_TYPE_POINTER
) {
3860 ST_GET_CACHED_COUNTERPART(cached_dsentry
->type_array
[0], types
, ptr_types
, local_dsentry
->type_array
[0]);
3862 ST_GET_CACHED_COUNTERPART(cached_dsentry
->type_array
[0], types
, types
, local_dsentry
->type_array
[0]);
3864 local_dsentry
->sentry
.type
= &local_dsentry
->type
;
3865 local_dsentry
->sentry
.type
->contained_types
= local_dsentry
->type_array
;
3868 assert(local_dsentry
);
3869 assert(local_dsentry
->parent_name
&& strcmp(local_dsentry
->parent_name
, ""));
3870 assert(local_dsentry
->sentry
.name
&& strcmp(local_dsentry
->sentry
.name
, ""));
3871 assert(magic_check_dsentry(local_dsentry
, 0));
3872 *local_dsentry_ptr
= local_dsentry
;
3874 if (is_type_mismatch
)
3875 local_dsentry
->sentry
.flags
|= MAGIC_STATE_TYPE_SIZE_MISMATCH
;
3878 * Dsentries allocated by shared libraries have the names stored in dsentry
3879 * buffers (for now).
3880 * Readjust the local_sentry to do this as well, since after state transfer
3881 * cleanup the existing names will become invalid.
3883 if (!local_dsindex
&& MAGIC_SENTRY_IS_LIB_ALLOC(cached_sentry
)) {
3884 strncpy(local_dsentry
->name_ext_buff
, local_dsentry
->sentry
.name
,
3885 MAGIC_DSENTRY_EXT_NAME_BUFF_SIZE
);
3886 local_dsentry
->sentry
.name
= local_dsentry
->name_ext_buff
;
3892 PRIVATE
int check_unpaired_sentry(st_init_info_t
*info
,
3893 struct _magic_sentry
* cached_sentry
)
3895 int sentry_needs_transfer
= MAGIC_STATE_EXTF_GET(cached_sentry
, ST_NEEDS_TRANSFER
| ST_TRANSFER_DONE
) == ST_NEEDS_TRANSFER
;
3898 if (!sentry_needs_transfer
&& !MAGIC_SENTRY_IS_STRING(cached_sentry
)) {
3902 if (MAGIC_STATE_FLAG(cached_sentry
, MAGIC_STATE_DYNAMIC
)) {
3903 report
= st_policies
& ST_REPORT_UNPAIRED_DSENTRIES
;
3905 else if(MAGIC_SENTRY_IS_STRING(cached_sentry
)) {
3906 report
= st_policies
& ST_REPORT_UNPAIRED_STRINGS
;
3909 report
= st_policies
& ST_REPORT_UNPAIRED_SENTRIES
;
3912 printf("check_unpaired_sentry: Unpaired sentry found: ");
3913 ST_SENTRY_PRINT(cached_sentry
,MAGIC_EXPAND_TYPE_STR
);
3920 PUBLIC
struct _magic_sentry
* st_cached_to_remote_sentry(st_init_info_t
*info
, struct _magic_sentry
*cached_sentry
)
3922 struct _magic_sentry
*remote_sentry
;
3923 void *local_data_addr
;
3926 /* Copy metadata into metadata buffer. */
3927 if (MAGIC_STATE_FLAG(cached_sentry
, MAGIC_STATE_DYNAMIC
)) {
3928 magic_copy_dsentry(MAGIC_DSENTRY_FROM_SENTRY(cached_sentry
), st_dsentry_buff
);
3929 remote_sentry
= MAGIC_DSENTRY_TO_SENTRY(st_dsentry_buff
);
3932 memcpy(&st_dsentry_buff
->sentry
, cached_sentry
, sizeof(struct _magic_sentry
));
3933 remote_sentry
= &st_dsentry_buff
->sentry
;
3936 /* Have the remote sentry point to local data. */
3937 local_data_addr
= NULL
;
3938 /* See if we have the data locally already first. */
3939 ST_GET_CACHED_COUNTERPART(cached_sentry
, sentries
, sentries_data
, local_data_addr
);
3940 if (!local_data_addr
) {
3941 /* Copy remote data into local data buffer. */
3942 if (st_cbs_os
.copy_state_region(info
->info_opaque
, (uint32_t) remote_sentry
->address
3943 , remote_sentry
->type
->size
, (uint32_t) st_data_buff
))
3945 printf("ERROR transferring sentry data to local buffer.\n");
3948 local_data_addr
= st_data_buff
;
3950 remote_sentry
->address
= local_data_addr
;
3952 return remote_sentry
;
3955 PRIVATE
int transfer_data_sentry(st_init_info_t
*info
,
3956 struct _magic_sentry
* cached_sentry
)
3960 int st_cb_flags
= ST_CB_DEFAULT_FLAGS
;
3961 struct _magic_sentry
*local_sentry
, *remote_sentry
;
3962 int flags
= ST_SEL_ANALYZE_FLAGS
;
3963 struct st_cb_info cb_info_buff
;
3964 struct st_cb_info
*cb_info
= &cb_info_buff
;
3965 static _magic_selement_t magic_local_selements
[MAGIC_MAX_RECURSIVE_TYPES
+1];
3966 static int magic_flags_by_depth
[MAGIC_MAX_RECURSIVE_TYPES
+1];
3968 /* Skip extern weak symbols. */
3969 if (!cached_sentry
->address
) {
3970 assert(MAGIC_STATE_FLAG(cached_sentry
, MAGIC_STATE_EXTERNAL
));
3971 st_set_transfer_status(ST_TRANSFER_DONE
, ST_OP_ADD
, cached_sentry
, NULL
);
3975 /* Determine local and remote sentries from the cached version. */
3976 local_sentry
= NULL
;
3977 st_lookup_sentry_pair(&cached_sentry
, &local_sentry
);
3978 assert(local_sentry
&& "Unexpected unpaired sentry!");
3979 remote_sentry
= st_cached_to_remote_sentry(info
, cached_sentry
);
3980 if (!remote_sentry
) {
3981 printf("No remote sentry found for cached sentry: ");
3982 MAGIC_SENTRY_PRINT(cached_sentry
, 0);
3987 cb_info
->local_selements
= magic_local_selements
;
3988 cb_info
->local_selement
= magic_selement_from_sentry(local_sentry
, &magic_local_selements
[0]);
3989 cb_info
->walk_flags
= MAGIC_TYPE_WALK_DEFAULT_FLAGS
;
3990 cb_info
->st_cb_flags
= st_cb_flags
;
3991 cb_info
->init_info
= info
;
3992 cb_info
->st_cb_saved_flags
= magic_flags_by_depth
;
3993 magic_flags_by_depth
[0] = st_cb_flags
;
3995 EXEC_WITH_MAGIC_VARS(
3996 r
= magic_sentry_analyze(remote_sentry
, flags
, transfer_data_selement
, cb_info
, NULL
);
3997 , &st_cached_magic_vars
4003 st_set_transfer_status(ST_TRANSFER_DONE
, ST_OP_ADD
, cached_sentry
, NULL
);
4007 PRIVATE
int transfer_data_selement(_magic_selement_t
*selement
, _magic_sel_analyzed_t
*sel_analyzed
, _magic_sel_stats_t
*sel_stats
, void *cb_args
)
4010 int r
= ST_CB_NOT_PROCESSED
;
4011 int depth
, cb_flags
;
4012 struct st_cb_info
*cb_info
= (struct st_cb_info
*) cb_args
;
4013 _magic_selement_t
*local_selement
, *local_parent_selement
;
4014 st_cb_selement_transfer_t
*cb
;
4016 register_typenames_and_callbacks();
4018 if (!ST_CB_FLAG(ST_CB_CHECK_ONLY
)) {
4019 depth
= selement
->depth
;
4020 local_selement
= &cb_info
->local_selements
[depth
];
4022 local_parent_selement
= &cb_info
->local_selements
[depth
-1];
4023 local_selement
->sentry
= local_parent_selement
->sentry
;
4024 local_selement
->parent_type
= local_parent_selement
->type
;
4025 local_selement
->parent_address
= local_parent_selement
->address
;
4026 cb_info
->st_cb_flags
= cb_info
->st_cb_saved_flags
[depth
-1];
4028 /* Map the cached and the local selement. */
4029 st_map_selement(selement
, local_selement
, cb_info
, FALSE
);
4030 if (local_selement
->type
== NULL
) {
4031 /* Unpaired selement. */
4032 if (st_policies
& ST_REPORT_UNPAIRED_SELEMENTS
) {
4033 printf("transfer_data_selement: Unpaired selement found: ");
4034 MAGIC_SELEMENT_PRINT(selement
, MAGIC_EXPAND_TYPE_STR
);
4037 return MAGIC_SENTRY_ANALYZE_SKIP_PATH
;
4039 cb_info
->local_selement
= local_selement
;
4041 /* See if identity transfer has been requested. */
4042 if (cb_info
->st_cb_flags
& ST_CB_FORCE_IXFER
) {
4043 r
= transfer_identity_sel_cb(selement
, sel_analyzed
, sel_stats
, cb_info
);
4044 assert(r
!= ST_CB_NOT_PROCESSED
);
4045 cb_info
->st_cb_saved_flags
[depth
] = cb_info
->st_cb_flags
;
4050 cb_flags
= ST_CB_TYPE_SELEMENT
;
4051 if (ST_TYPE_NAME_KEY(selement
->type
) != NULL
) {
4052 cb_flags
|= ST_CB_TYPE_TYPENAME
;
4054 if (selement
->num
== 1) {
4055 cb_flags
|= ST_CB_TYPE_SENTRY
;
4058 cb
= st_cbs
.st_cb_selement_transfer
[cb_flags
];
4062 r
= (*cb
)(selement
, sel_analyzed
, sel_stats
, cb_info
);
4064 r
= default_transfer_selement_sel_cb(selement
, sel_analyzed
, sel_stats
, cb_info
);
4065 assert(r
!= ST_CB_NOT_PROCESSED
4066 && "Default selement callback should always process the selement.");
4069 if (r
!= ST_CB_NOT_PROCESSED
) {
4070 assert((r
<0 || MAGIC_SENTRY_ANALYZE_IS_VALID_RET(r
)) && "Invalid callback return code!");
4071 if (!ST_CB_FLAG(ST_CB_CHECK_ONLY
)) {
4072 cb_info
->st_cb_saved_flags
[depth
] = cb_info
->st_cb_flags
;
4080 /* Not reachable. */
4084 PRIVATE
int lookup_trg_info(_magic_selement_t
*selement
,
4085 _magic_sel_analyzed_t
*sel_analyzed
, _magic_sel_stats_t
*sel_stats
, struct st_cb_info
*cb_info
,
4086 _magic_selement_t
*cached_trg_selement
, _magic_selement_t
*local_trg_selement
)
4088 _magic_selement_t
*local_selement
, *trg_selement
;
4089 struct _magic_sentry
*cached_trg_sentry
, *local_trg_sentry
= NULL
;
4090 struct _magic_function
*cached_trg_function
, *local_trg_function
= NULL
;
4091 _magic_sel_analyzed_t local_sel_analyzed
;
4092 _magic_sel_stats_t local_sel_stats
;
4093 void *local_trg_root_address
;
4094 struct _magic_type
*cached_trg_root_type
, *local_trg_root_type
;
4095 int first_legal_trg_type
, is_same_type
, is_same_trg_type
, local_trg_has_addr_not_taken
;
4097 local_selement
= cb_info
->local_selement
;
4098 first_legal_trg_type
= sel_analyzed
->u
.ptr
.first_legal_trg_type
;
4099 assert(first_legal_trg_type
>= 0);
4100 trg_selement
= &sel_analyzed
->u
.ptr
.trg_selements
[first_legal_trg_type
];
4101 local_trg_root_type
= NULL
;
4103 /* Lookup cached and local targets. */
4104 if (MAGIC_SEL_ANALYZED_PTR_HAS_TRG_SENTRY(sel_analyzed
)) {
4105 cached_trg_sentry
= trg_selement
->sentry
;
4106 local_trg_sentry
= NULL
;
4107 st_lookup_sentry_pair(&cached_trg_sentry
, &local_trg_sentry
);
4108 *cached_trg_selement
= *trg_selement
;
4109 cached_trg_root_type
= cached_trg_sentry
->type
;
4110 local_trg_has_addr_not_taken
= local_trg_sentry
&& MAGIC_STATE_FLAG(local_trg_sentry
, MAGIC_STATE_ADDR_NOT_TAKEN
);
4111 local_trg_selement
->sentry
= local_trg_sentry
;
4112 if (local_trg_sentry
) {
4113 local_trg_root_address
= local_trg_sentry
->address
;
4114 local_trg_root_type
= local_trg_sentry
->type
;
4117 else if(MAGIC_SEL_ANALYZED_PTR_HAS_TRG_FUNCTION(sel_analyzed
)) {
4118 cached_trg_function
= MAGIC_DFUNCTION_TO_FUNCTION(&sel_analyzed
->u
.ptr
.trg
.dfunction
);
4119 local_trg_function
= NULL
;
4120 st_lookup_function_pair(&cached_trg_function
, &local_trg_function
);
4121 *cached_trg_selement
= *trg_selement
;
4122 cached_trg_root_type
= cached_trg_function
->type
;
4123 local_trg_has_addr_not_taken
= local_trg_function
&& MAGIC_STATE_FLAG(local_trg_function
, MAGIC_STATE_ADDR_NOT_TAKEN
);
4124 local_trg_selement
->sentry
= NULL
;
4125 if (local_trg_function
) {
4126 local_trg_root_address
= local_trg_function
->address
;
4127 local_trg_root_type
= local_trg_function
->type
;
4131 /* Check unpaired targets. */
4132 if (!local_trg_root_type
) {
4133 local_trg_selement
->type
= NULL
;
4137 /* Check address not taken violations. */
4138 if (local_trg_has_addr_not_taken
) {
4139 ST_CB_PRINT(ST_CB_ERR
, "uncaught ptr with paired target whose address is not taken", selement
, sel_analyzed
, sel_stats
, cb_info
);
4143 /* Check types and return immediately in case of perfect pointer match. */
4144 is_same_type
= selement
->type
== local_selement
->type
|| ST_PTR_TYPE_IS_CACHED_COUNTERPART(selement
->type
, local_selement
->type
);
4145 is_same_trg_type
= ST_TYPE_IS_CACHED_COUNTERPART(cached_trg_root_type
, local_trg_root_type
);
4146 if (is_same_type
&& is_same_trg_type
) {
4147 local_trg_selement
->type
= cached_trg_selement
->type
;
4148 local_trg_selement
->address
= (char*) local_trg_root_address
+ sel_analyzed
->u
.ptr
.trg_offset
;
4151 #if CHECK_ASR && !FORCE_SOME_UNPAIRED_TYPES
4152 if (cb_info
->init_info
->flags
& ST_LU_ASR
) {
4153 st_cbs_os
.panic("ASR should never get here!");
4157 /* Map sel_analyzed to its local counterpart. */
4158 if (is_same_trg_type
) {
4159 local_sel_analyzed
= *sel_analyzed
;
4160 local_sel_analyzed
.u
.ptr
.trg_selements
[0].address
= (char*) local_trg_root_address
+ sel_analyzed
->u
.ptr
.trg_offset
;
4163 st_map_sel_analyzed_from_target(sel_analyzed
, &local_sel_analyzed
, local_trg_sentry
, local_trg_function
, cb_info
);
4164 if (local_sel_analyzed
.u
.ptr
.num_trg_types
== 0) {
4165 /* Unpaired target selements. */
4166 local_trg_selement
->type
= NULL
;
4171 /* Check violations on the local target. */
4172 memset(&local_sel_stats
, 0, sizeof(local_sel_stats
));
4173 magic_selement_analyze_ptr_type_invs(local_selement
, &local_sel_analyzed
, &local_sel_stats
);
4174 if (MAGIC_SEL_STATS_HAS_VIOLATIONS(&local_sel_stats
)) {
4175 /* Local pointer with violations found */
4176 ST_CB_PRINT(ST_CB_ERR
, "uncaught ptr with after-transfer violations", selement
, sel_analyzed
, sel_stats
, cb_info
);
4177 ST_CB_PRINT(ST_CB_ERR
, "transferred ptr with violations", local_selement
, &local_sel_analyzed
, &local_sel_stats
, cb_info
);
4181 /* All the targets mapped correctly. */
4182 local_trg_selement
->type
= local_sel_analyzed
.u
.ptr
.trg_selements
[0].type
;
4183 local_trg_selement
->address
= local_sel_analyzed
.u
.ptr
.trg_selements
[0].address
;
4187 /* transfer helper functions */
4189 PRIVATE
int md_transfer_str(st_init_info_t
*info
, char **str_pt
)
4191 char buff
[ST_STR_BUFF_SIZE
+ 2];
4193 if (st_cbs_os
.copy_state_region(info
->info_opaque
, (uint32_t) *str_pt
, ST_STR_BUFF_SIZE
+ 1, (uint32_t) buff
)) {
4194 st_cbs_os
.panic("md_transfer_str(): ERROR transferring string.\n");
4197 buff
[ST_STR_BUFF_SIZE
+ 1] = '\0';
4198 if (strlen(buff
) > ST_STR_BUFF_SIZE
) {
4199 st_cbs_os
.panic("md_transfer_str(): transferred string has a wrong size: %d\n", strlen(buff
));
4203 *str_pt
= st_buff_allocate(info
, strlen(buff
) + 1);
4205 st_cbs_os
.panic("md_transfer_str(): string buffer could not be allocated.\n");
4208 strcpy(*str_pt
, buff
);
4212 PRIVATE
int md_transfer(st_init_info_t
*info
, void *from
, void **to
, int len
)
4214 /* backup from value, in case &from == to */
4215 void *from_backup
= from
;
4216 *to
= st_buff_allocate(info
, len
);
4218 st_cbs_os
.panic("md_transfer(): buffer could not be allocated.\n");
4221 if (st_cbs_os
.copy_state_region(info
->info_opaque
, (uint32_t) from_backup
, len
, (uint32_t) *to
)) {
4222 st_cbs_os
.panic("md_transfer(): ERROR transferring remote data to buffer.\n");
4229 /* Buffer allocation */
4231 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 if (USE_PRE_ALLOCATED_BUFFER(info
)) {
4233 size_t alloc_length
= length
+ (length
% magic_get_sys_pagesize() == 0 ? 0 : magic_get_sys_pagesize() - (length
% magic_get_sys_pagesize()));
4234 char *ptr
, *data_ptr
;
4236 assert(((char *)info
->init_buff_cleanup_start
) + alloc_length
+ magic_get_sys_pagesize() <= st_pre_allocated_page_pt
&& "mmap region hits temporary buffer.");
4237 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");
4239 ptr
= ((char *)info
->init_buff_cleanup_start
) + magic_get_sys_pagesize() - MAGIC_SIZE_TO_REAL(0);
4240 data_ptr
= magic_alloc(__MA_VALUES__ ptr
, alloc_length
, (int) MAGIC_STATE_MAP
);
4241 MAGIC_PTR_TO_DSENTRY(MAGIC_PTR_FROM_DATA(data_ptr
))->alloc_mmap_flags
= flags
;
4242 MAGIC_PTR_TO_DSENTRY(MAGIC_PTR_FROM_DATA(data_ptr
))->alloc_mmap_prot
= prot
;
4243 info
->init_buff_cleanup_start
= &data_ptr
[alloc_length
];
4246 /* no pre-allocated mmap buffer. Call magic_mmap to allocate region. */
4247 return magic_mmap_positioned(type
, name
, parent_name
4248 , NULL
, length
, prot
, flags
, -1, 0, dsentry
);
4252 PUBLIC
void *st_cb_pages_allocate(st_init_info_t
*info
, uint32_t *phys
, int num_pages
)
4255 int len
= num_pages
* magic_get_sys_pagesize();
4257 if (USE_PRE_ALLOCATED_BUFFER(info
)) {
4258 if (!st_pre_allocated_page_pt
) {
4259 #if ST_DEBUG_LEVEL > 0
4260 printf("st_pages_allocate: initializing pre-allocated page buffer.\n");
4262 st_pre_allocated_page_pt
= &((char *)info
->init_buff_start
)[info
->init_buff_len
];
4264 st_pre_allocated_page_pt
-= len
;
4265 assert(st_pre_allocated_page_pt
>= (char *)info
->init_buff_cleanup_start
4266 && "Temporary buffer ran into perminently pre-allocated mmapped pages.");
4267 return st_pre_allocated_page_pt
;
4270 result
= st_cbs_os
.alloc_contig(len
, 0, NULL
);
4271 if (result
== NULL
) {
4272 printf("st_pages_allocate: alloc_contig(%d) failed.\n", len
);
4276 *phys
= (uint32_t) NULL
; /* we don't know or need the physical address in order to free */
4281 PUBLIC
void st_cb_pages_free(st_init_info_t
*info
, st_alloc_pages
*current_page
)
4283 st_alloc_pages
*to_be_freed
;
4286 if (USE_PRE_ALLOCATED_BUFFER(info
)) {
4291 while (current_page
!= NULL
) {
4292 to_be_freed
= current_page
;
4293 current_page
= current_page
->previous
;
4295 result
= st_cbs_os
.free_contig(to_be_freed
->virt_addr
, to_be_freed
->num_pages
* magic_get_sys_pagesize());
4298 printf("munmap result != ok, using free()\n");
4300 * NOTE: in case this is moved out of a magic_* module it needs to be
4301 * manually annotated so it doesn't get instrumented.
4303 free(to_be_freed
->virt_addr
);
4310 PUBLIC
void *st_buff_allocate(st_init_info_t
*info
, size_t size
)
4314 if (size
> st_alloc_buff_available
) {
4316 int pagesize
= magic_get_sys_pagesize();
4318 st_alloc_pages
*buff_previous_page
= st_alloc_pages_current
;
4320 /* calculate number of pages needed */
4321 int pages_needed
= (size
+ sizeof(st_alloc_pages
)) / pagesize
;
4322 if ((size
+ sizeof(st_alloc_pages
)) % pagesize
)
4325 /* allocate pages */
4326 st_alloc_pages_current
4327 = st_cbs
.st_cb_pages_allocate(info
, &phys
, pages_needed
);
4329 if (!st_alloc_pages_current
) {
4330 printf("Could not allocate buffer.\n");
4334 /* set allocation struct */
4335 st_alloc_pages_current
->virt_addr
= st_alloc_pages_current
;
4336 st_alloc_pages_current
->phys_addr
= phys
;
4337 st_alloc_pages_current
->num_pages
= pages_needed
;
4338 st_alloc_pages_current
->previous
= buff_previous_page
;
4340 /* requested space is right after the struct */
4341 st_alloc_buff_pt
= (char *) st_alloc_pages_current
;
4342 st_alloc_buff_pt
+= sizeof(st_alloc_pages
);
4343 /* subtract the struct size from the available buffer */
4344 st_alloc_buff_available
= pages_needed
* pagesize
- sizeof(st_alloc_pages
);
4348 /* return current buffer pointer */
4349 result
= st_alloc_buff_pt
;
4350 /* set buffer pointer after space that is requested, ready for next allocation */
4351 st_alloc_buff_pt
+= size
;
4352 /* adjust available space */
4353 st_alloc_buff_available
-= size
;
4359 PUBLIC
void st_buff_cleanup(st_init_info_t
*info
)
4361 st_cbs
.st_cb_pages_free(info
, st_alloc_pages_current
);
4362 st_alloc_pages_current
= NULL
;
4363 st_alloc_buff_available
= 0;
4364 st_alloc_buff_pt
= NULL
;
4367 PUBLIC
void st_cleanup(st_init_info_t
*info
)
4370 #if MAGIC_LOOKUP_SENTRY_ALLOW_RANGE_INDEX
4371 st_cleanup_rl_index(info
, &st_cached_magic_vars
);
4372 st_cleanup_rl_index(info
, _magic_vars
);
4375 #if MAGIC_LOOKUP_SENTRY_ALLOW_NAME_HASH
4376 st_cleanup_sentry_hash(info
, &st_cached_magic_vars
);
4377 st_cleanup_sentry_hash(info
, _magic_vars
);
4380 #if MAGIC_LOOKUP_FUNCTION_ALLOW_ADDR_HASH
4381 st_cleanup_function_hash(info
, &st_cached_magic_vars
);
4382 st_cleanup_function_hash(info
, _magic_vars
);
4385 #if !ST_ASSUME_RAW_COPY_BEFORE_TRANSFER
4387 deallocate_nonxferred_dsentries(st_cached_magic_vars
.first_dsentry
,
4388 &st_counterparts
) == OK
&&
4389 "ERROR occurred during call to deallocate_nonxferred_dsentries().");
4393 * Free all temporary allocated memory.
4395 st_buff_cleanup(info
);
4398 * Reset all values in case of successive state transfers.
4400 st_init_done
= FALSE
;
4401 st_pre_allocated_page_pt
= NULL
;
4402 st_dsentry_buff
= NULL
;
4403 st_data_buff
= NULL
;
4404 st_num_type_transformations
= 0;
4405 st_local_magic_vars_ptr
= &_magic_vars_buff
;
4406 st_policies
= ST_POLICIES_DEFAULT
;
4407 st_unpaired_types_ratio
= ST_UNPAIRED_TYPES_RATIO_DEFAULT
;
4408 st_unpaired_struct_types_ratio
= ST_UNPAIRED_STRUCT_TYPES_RATIO_DEFAULT
;
4410 /* Reallow mempool dsentries lookups. */
4411 magic_lookup_nested_dsentries
= 1;
4414 /* State cleanup/checking functions. */
4416 /*===========================================================================*
4417 * do_st_before_receive *
4418 *===========================================================================*/
4419 PUBLIC
void do_st_before_receive()
4421 /* Handle State transfer before receive events. */
4424 assert(st_state_checking_before_receive_is_enabled());
4426 num_violations
= st_do_state_checking();
4427 if (__st_before_receive_sc_max_cycles
< LONG_MAX
) {
4428 __st_before_receive_sc_max_cycles
--;
4430 if (__st_before_receive_sc_max_violations
< LONG_MAX
) {
4431 __st_before_receive_sc_max_violations
-= num_violations
;
4433 if (__st_before_receive_sc_max_cycles
<= 0) {
4434 st_state_checking_before_receive_set_enabled(0, 0, 0);
4435 printf("Maximum number of cycles reached\n");
4437 if (__st_before_receive_sc_max_violations
<= 0) {
4438 st_state_checking_before_receive_set_enabled(0, 0, 0);
4439 printf("Maximum number of violations reached\n");
4443 /*===========================================================================*
4444 * st_state_checking_before_receive_is_enabled *
4445 *===========================================================================*/
4446 PUBLIC
int st_state_checking_before_receive_is_enabled()
4448 return __st_before_receive_enabled
;
4451 /*===========================================================================*
4452 * st_state_checking_before_receive_set_enabled *
4453 *===========================================================================*/
4454 PUBLIC
int st_state_checking_before_receive_set_enabled(int enabled
,
4455 int max_cycles
, int max_violations
)
4457 int was_enabled
= __st_before_receive_enabled
;
4458 __st_before_receive_enabled
= enabled
;
4460 if (max_cycles
<= 0) {
4461 max_cycles
= ST_STATE_CHECKING_DEFAULT_MAX_CYCLES
;
4463 if (max_violations
<= 0) {
4464 max_violations
= ST_STATE_CHECKING_DEFAULT_MAX_VIOLATIONS
;
4466 __st_before_receive_sc_max_cycles
= max_cycles
;
4467 __st_before_receive_sc_max_violations
= max_violations
;
4468 printf("Continuous state checking enabled, max cycles=%d, max violations=%d\n",
4469 max_cycles
== LONG_MAX
? 0 : max_cycles
,
4470 max_violations
== LONG_MAX
? 0 : max_violations
);
4473 printf("Continuous state checking disabled\n");
4478 /*===========================================================================*
4479 * st_cb_state_checking_wrapper *
4480 *===========================================================================*/
4481 PRIVATE
int st_cb_state_checking_wrapper(_magic_selement_t
* selement
,
4482 _magic_sel_analyzed_t
*sel_analyzed
, _magic_sel_stats_t
*sel_stats
,
4485 struct st_cb_info cb_info_buff
;
4486 struct st_cb_info
*cb_info
= &cb_info_buff
;
4487 int *num_violations
= (int*) cb_args
;
4490 cb_info
->local_selements
= NULL
;
4491 cb_info
->local_selement
= NULL
;
4492 cb_info
->walk_flags
= MAGIC_TYPE_WALK_DEFAULT_FLAGS
;
4493 cb_info
->st_cb_flags
= ST_CB_CHECK_ONLY
;
4494 cb_info
->st_cb_saved_flags
= NULL
;
4495 cb_info
->init_info
= NULL
;
4497 ret
= transfer_data_selement(selement
, sel_analyzed
, sel_stats
, cb_info
);
4499 ret
= st_cbs
.st_cb_state_checking(selement
, sel_analyzed
, sel_stats
, cb_args
);
4500 (*num_violations
)++;
4505 /*===========================================================================*
4506 * st_do_state_checking *
4507 *===========================================================================*/
4508 PUBLIC
int st_do_state_checking()
4510 int num_violations
= 0;
4511 magic_sentries_analyze(ST_SEL_ANALYZE_FLAGS
,
4512 st_cb_state_checking_wrapper
, &num_violations
, NULL
);
4513 return num_violations
;
4516 /*===========================================================================*
4517 * st_cb_state_checking_null *
4518 *===========================================================================*/
4519 PUBLIC
int st_cb_state_checking_null(_magic_selement_t
* selement
,
4520 _magic_sel_analyzed_t
*sel_analyzed
, _magic_sel_stats_t
*sel_stats
,
4526 /*===========================================================================*
4527 * st_cb_state_checking_print *
4528 *===========================================================================*/
4529 PUBLIC
int st_cb_state_checking_print(_magic_selement_t
* selement
,
4530 _magic_sel_analyzed_t
*sel_analyzed
, _magic_sel_stats_t
*sel_stats
,
4533 printf("%s. Found state violation:\n", st_cbs_os
.debug_header());
4534 magic_sentry_print_el_cb(selement
, sel_analyzed
, sel_stats
, cb_args
);
4535 return MAGIC_SENTRY_ANALYZE_SKIP_PATH
;
4538 /*===========================================================================*
4539 * st_cb_state_checking_panic *
4540 *===========================================================================*/
4541 PUBLIC
int st_cb_state_checking_panic(_magic_selement_t
* selement
,
4542 _magic_sel_analyzed_t
*sel_analyzed
, _magic_sel_stats_t
*sel_stats
,
4545 st_cb_state_checking_print(selement
, sel_analyzed
, sel_stats
, cb_args
);
4546 st_cbs_os
.panic("Time to panic...");
4547 return MAGIC_SENTRY_ANALYZE_STOP
;
4550 /*===========================================================================*
4551 * st_do_state_cleanup *
4552 *===========================================================================*/
4553 PUBLIC
int st_do_state_cleanup()
4555 return st_cbs
.st_cb_state_cleanup();
4558 /*===========================================================================*
4559 * st_cb_state_cleanup_null *
4560 *===========================================================================*/
4561 PUBLIC
int st_cb_state_cleanup_null() {
4566 /*===========================================================================*
4567 * st_msync_all_shm_dsentries *
4568 *===========================================================================*/
4569 PUBLIC
void st_msync_all_shm_dsentries(void) {
4570 struct _magic_dsentry
*prev_dsentry
, *dsentry
;
4571 struct _magic_sentry
*sentry
;
4572 MAGIC_DSENTRY_ALIVE_ITER(_magic_first_dsentry
, prev_dsentry
,
4577 * - Don't msync mmaps of /dev/zero
4579 if (MAGIC_STATE_FLAGS(sentry
, MAGIC_STATE_SHM
| MAGIC_STATE_MAP
) &&
4580 !(dsentry
->alloc_mmap_flags
& MAP_ANONYMOUS
))
4581 msync(MAGIC_PTR_TO_DATA(dsentry
), sentry
->type
->size
,
4582 MS_SYNC
| MS_INVALIDATE
);