prefix ASAN related inline functions asan_

requested by Ko1.
This commit is contained in:
Urabe, Shyouhei 2019-05-23 17:02:07 +09:00
parent 8fce83339b
commit 763989c6c5
4 changed files with 94 additions and 97 deletions

138
gc.c
View File

@ -1149,14 +1149,14 @@ gc_object_moved_p(rb_objspace_t * objspace, VALUE obj)
return FALSE; return FALSE;
} }
else { else {
void *poisoned = poisoned_object_p(obj); void *poisoned = asan_poisoned_object_p(obj);
unpoison_object(obj, false); asan_unpoison_object(obj, false);
int ret = BUILTIN_TYPE(obj) == T_MOVED; int ret = BUILTIN_TYPE(obj) == T_MOVED;
/* Re-poison slot if it's not the one we want */ /* Re-poison slot if it's not the one we want */
if (poisoned) { if (poisoned) {
GC_ASSERT(BUILTIN_TYPE(obj) == T_NONE); GC_ASSERT(BUILTIN_TYPE(obj) == T_NONE);
poison_object(obj); asan_poison_object(obj);
} }
return ret; return ret;
} }
@ -1483,17 +1483,17 @@ static inline void
heap_page_add_freeobj(rb_objspace_t *objspace, struct heap_page *page, VALUE obj) heap_page_add_freeobj(rb_objspace_t *objspace, struct heap_page *page, VALUE obj)
{ {
RVALUE *p = (RVALUE *)obj; RVALUE *p = (RVALUE *)obj;
unpoison_memory_region(&page->freelist, sizeof(RVALUE*), false); asan_unpoison_memory_region(&page->freelist, sizeof(RVALUE*), false);
p->as.free.flags = 0; p->as.free.flags = 0;
p->as.free.next = page->freelist; p->as.free.next = page->freelist;
page->freelist = p; page->freelist = p;
__asan_poison_memory_region(&page->freelist, sizeof(RVALUE*)); asan_poison_memory_region(&page->freelist, sizeof(RVALUE*));
if (RGENGC_CHECK_MODE && !is_pointer_to_heap(objspace, p)) { if (RGENGC_CHECK_MODE && !is_pointer_to_heap(objspace, p)) {
rb_bug("heap_page_add_freeobj: %p is not rvalue.", (void *)p); rb_bug("heap_page_add_freeobj: %p is not rvalue.", (void *)p);
} }
poison_object(obj); asan_poison_object(obj);
gc_report(3, objspace, "heap_page_add_freeobj: add %p to freelist\n", (void *)obj); gc_report(3, objspace, "heap_page_add_freeobj: add %p to freelist\n", (void *)obj);
} }
@ -1501,29 +1501,29 @@ heap_page_add_freeobj(rb_objspace_t *objspace, struct heap_page *page, VALUE obj
static inline void static inline void
heap_add_freepage(rb_objspace_t *objspace, rb_heap_t *heap, struct heap_page *page) heap_add_freepage(rb_objspace_t *objspace, rb_heap_t *heap, struct heap_page *page)
{ {
unpoison_memory_region(&page->freelist, sizeof(RVALUE*), false); asan_unpoison_memory_region(&page->freelist, sizeof(RVALUE*), false);
if (page->freelist) { if (page->freelist) {
page->free_next = heap->free_pages; page->free_next = heap->free_pages;
heap->free_pages = page; heap->free_pages = page;
} }
poison_memory_region(&page->freelist, sizeof(RVALUE*)); asan_poison_memory_region(&page->freelist, sizeof(RVALUE*));
} }
#if GC_ENABLE_INCREMENTAL_MARK #if GC_ENABLE_INCREMENTAL_MARK
static inline int static inline int
heap_add_poolpage(rb_objspace_t *objspace, rb_heap_t *heap, struct heap_page *page) heap_add_poolpage(rb_objspace_t *objspace, rb_heap_t *heap, struct heap_page *page)
{ {
unpoison_memory_region(&page->freelist, sizeof(RVALUE*), false); asan_unpoison_memory_region(&page->freelist, sizeof(RVALUE*), false);
if (page->freelist) { if (page->freelist) {
page->free_next = heap->pooled_pages; page->free_next = heap->pooled_pages;
heap->pooled_pages = page; heap->pooled_pages = page;
objspace->rincgc.pooled_slots += page->free_slots; objspace->rincgc.pooled_slots += page->free_slots;
poison_memory_region(&page->freelist, sizeof(RVALUE*)); asan_poison_memory_region(&page->freelist, sizeof(RVALUE*));
return TRUE; return TRUE;
} }
else { else {
poison_memory_region(&page->freelist, sizeof(RVALUE*)); asan_poison_memory_region(&page->freelist, sizeof(RVALUE*));
return FALSE; return FALSE;
} }
@ -1653,7 +1653,7 @@ heap_page_allocate(rb_objspace_t *objspace)
} }
page->free_slots = limit; page->free_slots = limit;
poison_memory_region(&page->freelist, sizeof(RVALUE*)); asan_poison_memory_region(&page->freelist, sizeof(RVALUE*));
return page; return page;
} }
@ -1663,10 +1663,10 @@ heap_page_resurrect(rb_objspace_t *objspace)
struct heap_page *page = 0, *next; struct heap_page *page = 0, *next;
list_for_each_safe(&heap_tomb->pages, page, next, page_node) { list_for_each_safe(&heap_tomb->pages, page, next, page_node) {
unpoison_memory_region(&page->freelist, sizeof(RVALUE*), false); asan_unpoison_memory_region(&page->freelist, sizeof(RVALUE*), false);
if (page->freelist != NULL) { if (page->freelist != NULL) {
heap_unlink_page(objspace, heap_tomb, page); heap_unlink_page(objspace, heap_tomb, page);
poison_memory_region(&page->freelist, sizeof(RVALUE*)); asan_poison_memory_region(&page->freelist, sizeof(RVALUE*));
return page; return page;
} }
} }
@ -1825,12 +1825,12 @@ heap_get_freeobj_from_next_freepage(rb_objspace_t *objspace, rb_heap_t *heap)
heap->using_page = page; heap->using_page = page;
GC_ASSERT(page->free_slots != 0); GC_ASSERT(page->free_slots != 0);
unpoison_memory_region(&page->freelist, sizeof(RVALUE*), false); asan_unpoison_memory_region(&page->freelist, sizeof(RVALUE*), false);
p = page->freelist; p = page->freelist;
page->freelist = NULL; page->freelist = NULL;
poison_memory_region(&page->freelist, sizeof(RVALUE*)); asan_poison_memory_region(&page->freelist, sizeof(RVALUE*));
page->free_slots = 0; page->free_slots = 0;
unpoison_object((VALUE)p, true); asan_unpoison_object((VALUE)p, true);
return p; return p;
} }
@ -1841,7 +1841,7 @@ heap_get_freeobj_head(rb_objspace_t *objspace, rb_heap_t *heap)
if (LIKELY(p != NULL)) { if (LIKELY(p != NULL)) {
heap->freelist = p->as.free.next; heap->freelist = p->as.free.next;
} }
unpoison_object((VALUE)p, true); asan_unpoison_object((VALUE)p, true);
return (VALUE)p; return (VALUE)p;
} }
@ -1852,7 +1852,7 @@ heap_get_freeobj(rb_objspace_t *objspace, rb_heap_t *heap)
while (1) { while (1) {
if (LIKELY(p != NULL)) { if (LIKELY(p != NULL)) {
unpoison_object((VALUE)p, true); asan_unpoison_object((VALUE)p, true);
heap->freelist = p->as.free.next; heap->freelist = p->as.free.next;
return (VALUE)p; return (VALUE)p;
} }
@ -2730,7 +2730,7 @@ internal_object_p(VALUE obj)
{ {
RVALUE *p = (RVALUE *)obj; RVALUE *p = (RVALUE *)obj;
void *ptr = __asan_region_is_poisoned(p, SIZEOF_VALUE); void *ptr = __asan_region_is_poisoned(p, SIZEOF_VALUE);
unpoison_object(obj, false); asan_unpoison_object(obj, false);
bool used_p = p->as.basic.flags; bool used_p = p->as.basic.flags;
if (used_p) { if (used_p) {
@ -2756,7 +2756,7 @@ internal_object_p(VALUE obj)
} }
} }
if (ptr || ! used_p) { if (ptr || ! used_p) {
poison_object(obj); asan_poison_object(obj);
} }
return 1; return 1;
} }
@ -3045,7 +3045,7 @@ finalize_list(rb_objspace_t *objspace, VALUE zombie)
while (zombie) { while (zombie) {
VALUE next_zombie; VALUE next_zombie;
struct heap_page *page; struct heap_page *page;
unpoison_object(zombie, false); asan_unpoison_object(zombie, false);
next_zombie = RZOMBIE(zombie)->next; next_zombie = RZOMBIE(zombie)->next;
page = GET_HEAP_PAGE(zombie); page = GET_HEAP_PAGE(zombie);
@ -3166,8 +3166,8 @@ rb_objspace_call_finalizer(rb_objspace_t *objspace)
for (i = 0; i < heap_allocated_pages; i++) { for (i = 0; i < heap_allocated_pages; i++) {
p = heap_pages_sorted[i]->start; pend = p + heap_pages_sorted[i]->total_slots; p = heap_pages_sorted[i]->start; pend = p + heap_pages_sorted[i]->total_slots;
while (p < pend) { while (p < pend) {
void *poisoned = poisoned_object_p((VALUE)p); void *poisoned = asan_poisoned_object_p((VALUE)p);
unpoison_object((VALUE)p, false); asan_unpoison_object((VALUE)p, false);
switch (BUILTIN_TYPE(p)) { switch (BUILTIN_TYPE(p)) {
case T_DATA: case T_DATA:
if (!DATA_PTR(p) || !RANY(p)->as.data.dfree) break; if (!DATA_PTR(p) || !RANY(p)->as.data.dfree) break;
@ -3193,7 +3193,7 @@ rb_objspace_call_finalizer(rb_objspace_t *objspace)
} }
if (poisoned) { if (poisoned) {
GC_ASSERT(BUILTIN_TYPE(p) == T_NONE); GC_ASSERT(BUILTIN_TYPE(p) == T_NONE);
poison_object((VALUE)p); asan_poison_object((VALUE)p);
} }
p++; p++;
} }
@ -3719,8 +3719,8 @@ count_objects(int argc, VALUE *argv, VALUE os)
p = page->start; pend = p + page->total_slots; p = page->start; pend = p + page->total_slots;
for (;p < pend; p++) { for (;p < pend; p++) {
void *poisoned = poisoned_object_p((VALUE)p); void *poisoned = asan_poisoned_object_p((VALUE)p);
unpoison_object((VALUE)p, false); asan_unpoison_object((VALUE)p, false);
if (p->as.basic.flags) { if (p->as.basic.flags) {
counts[BUILTIN_TYPE(p)]++; counts[BUILTIN_TYPE(p)]++;
} }
@ -3729,7 +3729,7 @@ count_objects(int argc, VALUE *argv, VALUE os)
} }
if (poisoned) { if (poisoned) {
GC_ASSERT(BUILTIN_TYPE((VALUE)p) == T_NONE); GC_ASSERT(BUILTIN_TYPE((VALUE)p) == T_NONE);
poison_object((VALUE)p); asan_poison_object((VALUE)p);
} }
} }
total += page->total_slots; total += page->total_slots;
@ -3814,7 +3814,7 @@ gc_page_sweep(rb_objspace_t *objspace, rb_heap_t *heap, struct heap_page *sweep_
if (bitset) { if (bitset) {
p = offset + i * BITS_BITLENGTH; p = offset + i * BITS_BITLENGTH;
do { do {
unpoison_object((VALUE)p, false); asan_unpoison_object((VALUE)p, false);
if (bitset & 1) { if (bitset & 1) {
switch (BUILTIN_TYPE(p)) { switch (BUILTIN_TYPE(p)) {
default: { /* majority case */ default: { /* majority case */
@ -3833,7 +3833,7 @@ gc_page_sweep(rb_objspace_t *objspace, rb_heap_t *heap, struct heap_page *sweep_
heap_page_add_freeobj(objspace, sweep_page, (VALUE)p); heap_page_add_freeobj(objspace, sweep_page, (VALUE)p);
gc_report(3, objspace, "page_sweep: %s is added to freelist\n", obj_info((VALUE)p)); gc_report(3, objspace, "page_sweep: %s is added to freelist\n", obj_info((VALUE)p));
freed_slots++; freed_slots++;
poison_object((VALUE)p); asan_poison_object((VALUE)p);
} }
break; break;
} }
@ -3934,14 +3934,14 @@ gc_sweep_start_heap(rb_objspace_t *objspace, rb_heap_t *heap)
#endif #endif
if (heap->using_page) { if (heap->using_page) {
struct heap_page *page = heap->using_page; struct heap_page *page = heap->using_page;
unpoison_memory_region(&page->freelist, sizeof(RVALUE*), false); asan_unpoison_memory_region(&page->freelist, sizeof(RVALUE*), false);
RVALUE **p = &page->freelist; RVALUE **p = &page->freelist;
while (*p) { while (*p) {
p = &(*p)->as.free.next; p = &(*p)->as.free.next;
} }
*p = heap->freelist; *p = heap->freelist;
poison_memory_region(&page->freelist, sizeof(RVALUE*)); asan_poison_memory_region(&page->freelist, sizeof(RVALUE*));
heap->using_page = NULL; heap->using_page = NULL;
} }
heap->freelist = NULL; heap->freelist = NULL;
@ -4684,7 +4684,7 @@ gc_mark_maybe(rb_objspace_t *objspace, VALUE obj)
if (is_pointer_to_heap(objspace, (void *)obj)) { if (is_pointer_to_heap(objspace, (void *)obj)) {
void *ptr = __asan_region_is_poisoned((void *)obj, SIZEOF_VALUE); void *ptr = __asan_region_is_poisoned((void *)obj, SIZEOF_VALUE);
unpoison_object(obj, false); asan_unpoison_object(obj, false);
/* Garbage can live on the stack, so do not mark or pin */ /* Garbage can live on the stack, so do not mark or pin */
switch (BUILTIN_TYPE(obj)) { switch (BUILTIN_TYPE(obj)) {
@ -4699,7 +4699,7 @@ gc_mark_maybe(rb_objspace_t *objspace, VALUE obj)
if (ptr) { if (ptr) {
GC_ASSERT(BUILTIN_TYPE(obj) == T_NONE); GC_ASSERT(BUILTIN_TYPE(obj) == T_NONE);
poison_object(obj); asan_poison_object(obj);
} }
} }
} }
@ -5612,8 +5612,8 @@ verify_internal_consistency_i(void *page_start, void *page_end, size_t stride, v
rb_objspace_t *objspace = data->objspace; rb_objspace_t *objspace = data->objspace;
for (obj = (VALUE)page_start; obj != (VALUE)page_end; obj += stride) { for (obj = (VALUE)page_start; obj != (VALUE)page_end; obj += stride) {
void *poisoned = poisoned_object_p(obj); void *poisoned = asan_poisoned_object_p(obj);
unpoison_object(obj, false); asan_unpoison_object(obj, false);
if (is_live_object(objspace, obj)) { if (is_live_object(objspace, obj)) {
/* count objects */ /* count objects */
@ -5656,7 +5656,7 @@ verify_internal_consistency_i(void *page_start, void *page_end, size_t stride, v
} }
if (poisoned) { if (poisoned) {
GC_ASSERT(BUILTIN_TYPE(obj) == T_NONE); GC_ASSERT(BUILTIN_TYPE(obj) == T_NONE);
poison_object(obj); asan_poison_object(obj);
} }
} }
@ -5676,8 +5676,8 @@ gc_verify_heap_page(rb_objspace_t *objspace, struct heap_page *page, VALUE obj)
for (i=0; i<page->total_slots; i++) { for (i=0; i<page->total_slots; i++) {
VALUE val = (VALUE)&page->start[i]; VALUE val = (VALUE)&page->start[i];
void *poisoned = poisoned_object_p(val); void *poisoned = asan_poisoned_object_p(val);
unpoison_object(val, false); asan_unpoison_object(val, false);
if (RBASIC(val) == 0) free_objects++; if (RBASIC(val) == 0) free_objects++;
if (BUILTIN_TYPE(val) == T_ZOMBIE) zombie_objects++; if (BUILTIN_TYPE(val) == T_ZOMBIE) zombie_objects++;
@ -5691,7 +5691,7 @@ gc_verify_heap_page(rb_objspace_t *objspace, struct heap_page *page, VALUE obj)
if (poisoned) { if (poisoned) {
GC_ASSERT(BUILTIN_TYPE(val) == T_NONE); GC_ASSERT(BUILTIN_TYPE(val) == T_NONE);
poison_object(val); asan_poison_object(val);
} }
} }
@ -5736,18 +5736,18 @@ gc_verify_heap_pages_(rb_objspace_t *objspace, struct list_head *head)
struct heap_page *page = 0; struct heap_page *page = 0;
list_for_each(head, page, page_node) { list_for_each(head, page, page_node) {
unpoison_memory_region(&page->freelist, sizeof(RVALUE*), false); asan_unpoison_memory_region(&page->freelist, sizeof(RVALUE*), false);
RVALUE *p = page->freelist; RVALUE *p = page->freelist;
while (p) { while (p) {
RVALUE *prev = p; RVALUE *prev = p;
unpoison_object((VALUE)p, false); asan_unpoison_object((VALUE)p, false);
if (BUILTIN_TYPE(p) != T_NONE) { if (BUILTIN_TYPE(p) != T_NONE) {
fprintf(stderr, "freelist slot expected to be T_NONE but was: %s\n", obj_info((VALUE)p)); fprintf(stderr, "freelist slot expected to be T_NONE but was: %s\n", obj_info((VALUE)p));
} }
p = p->as.free.next; p = p->as.free.next;
poison_object((VALUE)prev); asan_poison_object((VALUE)prev);
} }
poison_memory_region(&page->freelist, sizeof(RVALUE*)); asan_poison_memory_region(&page->freelist, sizeof(RVALUE*));
if (page->flags.has_remembered_objects == FALSE) { if (page->flags.has_remembered_objects == FALSE) {
remembered_old_objects += gc_verify_heap_page(objspace, page, Qfalse); remembered_old_objects += gc_verify_heap_page(objspace, page, Qfalse);
@ -7455,8 +7455,8 @@ count_pinned(struct heap_page *page)
VALUE v = (VALUE)pstart; VALUE v = (VALUE)pstart;
for (; v != (VALUE)pend; v += sizeof(RVALUE)) { for (; v != (VALUE)pend; v += sizeof(RVALUE)) {
void *poisoned = poisoned_object_p(v); void *poisoned = asan_poisoned_object_p(v);
unpoison_object(v, false); asan_unpoison_object(v, false);
if (RBASIC(v)->flags && RVALUE_PINNED(v)) { if (RBASIC(v)->flags && RVALUE_PINNED(v)) {
pinned++; pinned++;
@ -7464,7 +7464,7 @@ count_pinned(struct heap_page *page)
if (poisoned) { if (poisoned) {
GC_ASSERT(BUILTIN_TYPE(v) == T_NONE); GC_ASSERT(BUILTIN_TYPE(v) == T_NONE);
poison_object(v); asan_poison_object(v);
} }
} }
@ -7516,26 +7516,26 @@ gc_compact_heap(rb_objspace_t *objspace, page_compare_func_t *comparator)
/* Free cursor movement */ /* Free cursor movement */
/* Unpoison free_cursor slot */ /* Unpoison free_cursor slot */
void *free_slot_poison = poisoned_object_p((VALUE)free_cursor.slot); void *free_slot_poison = asan_poisoned_object_p((VALUE)free_cursor.slot);
unpoison_object((VALUE)free_cursor.slot, false); asan_unpoison_object((VALUE)free_cursor.slot, false);
while (BUILTIN_TYPE(free_cursor.slot) != T_NONE && not_met(&free_cursor, &scan_cursor)) { while (BUILTIN_TYPE(free_cursor.slot) != T_NONE && not_met(&free_cursor, &scan_cursor)) {
/* Re-poison slot if it's not the one we want */ /* Re-poison slot if it's not the one we want */
if (free_slot_poison) { if (free_slot_poison) {
GC_ASSERT(BUILTIN_TYPE(free_cursor.slot) == T_NONE); GC_ASSERT(BUILTIN_TYPE(free_cursor.slot) == T_NONE);
poison_object((VALUE)free_cursor.slot); asan_poison_object((VALUE)free_cursor.slot);
} }
advance_cursor(&free_cursor, page_list); advance_cursor(&free_cursor, page_list);
/* Unpoison free_cursor slot */ /* Unpoison free_cursor slot */
free_slot_poison = poisoned_object_p((VALUE)free_cursor.slot); free_slot_poison = asan_poisoned_object_p((VALUE)free_cursor.slot);
unpoison_object((VALUE)free_cursor.slot, false); asan_unpoison_object((VALUE)free_cursor.slot, false);
} }
/* Unpoison scan_cursor slot */ /* Unpoison scan_cursor slot */
void *scan_slot_poison = poisoned_object_p((VALUE)scan_cursor.slot); void *scan_slot_poison = asan_poisoned_object_p((VALUE)scan_cursor.slot);
unpoison_object((VALUE)scan_cursor.slot, false); asan_unpoison_object((VALUE)scan_cursor.slot, false);
/* Scan cursor movement */ /* Scan cursor movement */
objspace->rcompactor.considered_count_table[BUILTIN_TYPE((VALUE)scan_cursor.slot)]++; objspace->rcompactor.considered_count_table[BUILTIN_TYPE((VALUE)scan_cursor.slot)]++;
@ -7545,14 +7545,14 @@ gc_compact_heap(rb_objspace_t *objspace, page_compare_func_t *comparator)
/* Re-poison slot if it's not the one we want */ /* Re-poison slot if it's not the one we want */
if (scan_slot_poison) { if (scan_slot_poison) {
GC_ASSERT(BUILTIN_TYPE(scan_cursor.slot) == T_NONE); GC_ASSERT(BUILTIN_TYPE(scan_cursor.slot) == T_NONE);
poison_object((VALUE)scan_cursor.slot); asan_poison_object((VALUE)scan_cursor.slot);
} }
retreat_cursor(&scan_cursor, page_list); retreat_cursor(&scan_cursor, page_list);
/* Unpoison scan_cursor slot */ /* Unpoison scan_cursor slot */
scan_slot_poison = poisoned_object_p((VALUE)scan_cursor.slot); scan_slot_poison = asan_poisoned_object_p((VALUE)scan_cursor.slot);
unpoison_object((VALUE)scan_cursor.slot, false); asan_unpoison_object((VALUE)scan_cursor.slot, false);
objspace->rcompactor.considered_count_table[BUILTIN_TYPE((VALUE)scan_cursor.slot)]++; objspace->rcompactor.considered_count_table[BUILTIN_TYPE((VALUE)scan_cursor.slot)]++;
} }
@ -7779,8 +7779,8 @@ rb_gc_location(VALUE value)
VALUE destination; VALUE destination;
if (!SPECIAL_CONST_P((void *)value)) { if (!SPECIAL_CONST_P((void *)value)) {
void *poisoned = poisoned_object_p(value); void *poisoned = asan_poisoned_object_p(value);
unpoison_object(value, false); asan_unpoison_object(value, false);
if (BUILTIN_TYPE(value) == T_MOVED) { if (BUILTIN_TYPE(value) == T_MOVED) {
destination = (VALUE)RMOVED(value)->destination; destination = (VALUE)RMOVED(value)->destination;
@ -7793,7 +7793,7 @@ rb_gc_location(VALUE value)
/* Re-poison slot if it's not the one we want */ /* Re-poison slot if it's not the one we want */
if (poisoned) { if (poisoned) {
GC_ASSERT(BUILTIN_TYPE(value) == T_NONE); GC_ASSERT(BUILTIN_TYPE(value) == T_NONE);
poison_object(value); asan_poison_object(value);
} }
} }
else { else {
@ -8028,17 +8028,17 @@ gc_ref_update(void *vstart, void *vend, size_t stride, void * data)
VALUE v = (VALUE)vstart; VALUE v = (VALUE)vstart;
objspace = (rb_objspace_t *)data; objspace = (rb_objspace_t *)data;
page = GET_HEAP_PAGE(v); page = GET_HEAP_PAGE(v);
unpoison_memory_region(&page->freelist, sizeof(RVALUE*), false); asan_unpoison_memory_region(&page->freelist, sizeof(RVALUE*), false);
page->freelist = NULL; page->freelist = NULL;
poison_memory_region(&page->freelist, sizeof(RVALUE*)); asan_poison_memory_region(&page->freelist, sizeof(RVALUE*));
page->flags.has_uncollectible_shady_objects = FALSE; page->flags.has_uncollectible_shady_objects = FALSE;
page->flags.has_remembered_objects = FALSE; page->flags.has_remembered_objects = FALSE;
/* For each object on the page */ /* For each object on the page */
for (; v != (VALUE)vend; v += stride) { for (; v != (VALUE)vend; v += stride) {
if (!SPECIAL_CONST_P(v)) { if (!SPECIAL_CONST_P(v)) {
void *poisoned = poisoned_object_p(v); void *poisoned = asan_poisoned_object_p(v);
unpoison_object(v, false); asan_unpoison_object(v, false);
switch(BUILTIN_TYPE(v)) { switch(BUILTIN_TYPE(v)) {
case T_NONE: case T_NONE:
@ -8061,7 +8061,7 @@ gc_ref_update(void *vstart, void *vend, size_t stride, void * data)
if (poisoned) { if (poisoned) {
GC_ASSERT(BUILTIN_TYPE(v) == T_NONE); GC_ASSERT(BUILTIN_TYPE(v) == T_NONE);
poison_object(v); asan_poison_object(v);
} }
} }
} }
@ -8154,8 +8154,8 @@ heap_check_moved_i(void *vstart, void *vend, size_t stride, void *data)
/* Moved object still on the heap, something may have a reference. */ /* Moved object still on the heap, something may have a reference. */
} }
else { else {
void *poisoned = poisoned_object_p(v); void *poisoned = asan_poisoned_object_p(v);
unpoison_object(v, false); asan_unpoison_object(v, false);
switch (BUILTIN_TYPE(v)) { switch (BUILTIN_TYPE(v)) {
case T_NONE: case T_NONE:
@ -8167,7 +8167,7 @@ heap_check_moved_i(void *vstart, void *vend, size_t stride, void *data)
if (poisoned) { if (poisoned) {
GC_ASSERT(BUILTIN_TYPE(v) == T_NONE); GC_ASSERT(BUILTIN_TYPE(v) == T_NONE);
poison_object(v); asan_poison_object(v);
} }
} }
} }
@ -8221,7 +8221,7 @@ gc_compact_after_gc(rb_objspace_t *objspace, int use_toward_empty, int use_doubl
while (moved_list) { while (moved_list) {
VALUE current = moved_list; VALUE current = moved_list;
moved_list = RANY(moved_list)->as.moved.next; moved_list = RANY(moved_list)->as.moved.next;
poison_object(current); asan_poison_object(current);
} }
#else #else
(void)moved_list; (void)moved_list;

View File

@ -108,7 +108,6 @@ extern "C" {
# define __asan_poison_memory_region(x, y) # define __asan_poison_memory_region(x, y)
# define __asan_unpoison_memory_region(x, y) # define __asan_unpoison_memory_region(x, y)
# define __asan_region_is_poisoned(x, y) 0 # define __asan_region_is_poisoned(x, y) 0
# define poisoned_object_p(x) 0
#endif #endif
#ifdef HAVE_SANITIZER_MSAN_INTERFACE_H #ifdef HAVE_SANITIZER_MSAN_INTERFACE_H
@ -125,30 +124,28 @@ extern "C" {
#endif #endif
static inline void static inline void
poison_memory_region(const volatile void *ptr, size_t size) asan_poison_memory_region(const volatile void *ptr, size_t size)
{ {
__msan_poison(ptr, size); __msan_poison(ptr, size);
__asan_poison_memory_region(ptr, size); __asan_poison_memory_region(ptr, size);
} }
static inline void static inline void
poison_object(VALUE obj) asan_poison_object(VALUE obj)
{ {
struct RVALUE *ptr = (void *)obj; MAYBE_UNUSED(struct RVALUE *) ptr = (void *)obj;
poison_memory_region(ptr, SIZEOF_VALUE); asan_poison_memory_region(ptr, SIZEOF_VALUE);
} }
#if __has_feature(address_sanitizer)
static inline void * static inline void *
poisoned_object_p(VALUE obj) asan_poisoned_object_p(VALUE obj)
{ {
struct RVALUE *ptr = (void *)obj; MAYBE_UNUSED(struct RVALUE *) ptr = (void *)obj;
return __asan_region_is_poisoned(ptr, SIZEOF_VALUE); return __asan_region_is_poisoned(ptr, SIZEOF_VALUE);
} }
#endif
static inline void static inline void
unpoison_memory_region(const volatile void *ptr, size_t size, bool malloc_p) asan_unpoison_memory_region(const volatile void *ptr, size_t size, bool malloc_p)
{ {
__asan_unpoison_memory_region(ptr, size); __asan_unpoison_memory_region(ptr, size);
if (malloc_p) { if (malloc_p) {
@ -160,10 +157,10 @@ unpoison_memory_region(const volatile void *ptr, size_t size, bool malloc_p)
} }
static inline void static inline void
unpoison_object(VALUE obj, bool newobj_p) asan_unpoison_object(VALUE obj, bool newobj_p)
{ {
struct RVALUE *ptr = (void *)obj; MAYBE_UNUSED(struct RVALUE *) ptr = (void *)obj;
unpoison_memory_region(ptr, SIZEOF_VALUE, newobj_p); asan_unpoison_memory_region(ptr, SIZEOF_VALUE, newobj_p);
} }
#endif #endif

12
iseq.c
View File

@ -1079,8 +1079,8 @@ remove_coverage_i(void *vstart, void *vend, size_t stride, void *data)
{ {
VALUE v = (VALUE)vstart; VALUE v = (VALUE)vstart;
for (; v != (VALUE)vend; v += stride) { for (; v != (VALUE)vend; v += stride) {
void *ptr = poisoned_object_p(v); void *ptr = asan_poisoned_object_p(v);
unpoison_object(v, false); asan_unpoison_object(v, false);
if (rb_obj_is_iseq(v)) { if (rb_obj_is_iseq(v)) {
rb_iseq_t *iseq = (rb_iseq_t *)v; rb_iseq_t *iseq = (rb_iseq_t *)v;
@ -1088,7 +1088,7 @@ remove_coverage_i(void *vstart, void *vend, size_t stride, void *data)
} }
if (ptr) { if (ptr) {
poison_object(v); asan_poison_object(v);
} }
} }
return 0; return 0;
@ -3232,15 +3232,15 @@ trace_set_i(void *vstart, void *vend, size_t stride, void *data)
VALUE v = (VALUE)vstart; VALUE v = (VALUE)vstart;
for (; v != (VALUE)vend; v += stride) { for (; v != (VALUE)vend; v += stride) {
void *ptr = poisoned_object_p(v); void *ptr = asan_poisoned_object_p(v);
unpoison_object(v, false); asan_unpoison_object(v, false);
if (rb_obj_is_iseq(v)) { if (rb_obj_is_iseq(v)) {
rb_iseq_trace_set(rb_iseq_check((rb_iseq_t *)v), turnon_events); rb_iseq_trace_set(rb_iseq_check((rb_iseq_t *)v), turnon_events);
} }
if (ptr) { if (ptr) {
poison_object(v); asan_poison_object(v);
} }
} }
return 0; return 0;

View File

@ -385,7 +385,7 @@ rb_transient_heap_alloc(VALUE obj, size_t req_size)
/* header is poisoned to prevent buffer overflow, should /* header is poisoned to prevent buffer overflow, should
* unpoison first... */ * unpoison first... */
unpoison_memory_region(header, sizeof *header, true); asan_unpoison_memory_region(header, sizeof *header, true);
header->size = size; header->size = size;
header->magic = TRANSIENT_HEAP_ALLOC_MAGIC; header->magic = TRANSIENT_HEAP_ALLOC_MAGIC;
@ -393,7 +393,7 @@ rb_transient_heap_alloc(VALUE obj, size_t req_size)
header->obj = obj; /* TODO: can we eliminate it? */ header->obj = obj; /* TODO: can we eliminate it? */
/* header is fixed; shall poison again */ /* header is fixed; shall poison again */
poison_memory_region(header, sizeof *header); asan_poison_memory_region(header, sizeof *header);
ptr = header + 1; ptr = header + 1;
theap->total_objects++; /* statistics */ theap->total_objects++; /* statistics */
@ -408,7 +408,7 @@ rb_transient_heap_alloc(VALUE obj, size_t req_size)
RB_DEBUG_COUNTER_INC(theap_alloc); RB_DEBUG_COUNTER_INC(theap_alloc);
/* ptr is set up; OK to unpoison. */ /* ptr is set up; OK to unpoison. */
unpoison_memory_region(ptr, size - sizeof *header, true); asan_unpoison_memory_region(ptr, size - sizeof *header, true);
return ptr; return ptr;
} }
else { else {
@ -523,7 +523,7 @@ void
rb_transient_heap_mark(VALUE obj, const void *ptr) rb_transient_heap_mark(VALUE obj, const void *ptr)
{ {
struct transient_alloc_header *header = ptr_to_alloc_header(ptr); struct transient_alloc_header *header = ptr_to_alloc_header(ptr);
unpoison_memory_region(header, sizeof *header, false); asan_unpoison_memory_region(header, sizeof *header, false);
if (header->magic != TRANSIENT_HEAP_ALLOC_MAGIC) rb_bug("rb_transient_heap_mark: wrong header, %s (%p)", rb_obj_info(obj), ptr); if (header->magic != TRANSIENT_HEAP_ALLOC_MAGIC) rb_bug("rb_transient_heap_mark: wrong header, %s (%p)", rb_obj_info(obj), ptr);
if (TRANSIENT_HEAP_DEBUG >= 3) fprintf(stderr, "rb_transient_heap_mark: %s (%p)\n", rb_obj_info(obj), ptr); if (TRANSIENT_HEAP_DEBUG >= 3) fprintf(stderr, "rb_transient_heap_mark: %s (%p)\n", rb_obj_info(obj), ptr);
@ -782,7 +782,7 @@ clear_marked_index(struct transient_heap_block* block)
struct transient_alloc_header *header = alloc_header(block, marked_index); struct transient_alloc_header *header = alloc_header(block, marked_index);
/* header is poisoned to prevent buffer overflow, should /* header is poisoned to prevent buffer overflow, should
* unpoison first... */ * unpoison first... */
unpoison_memory_region(header, sizeof *header, false); asan_unpoison_memory_region(header, sizeof *header, false);
TH_ASSERT(marked_index != TRANSIENT_HEAP_ALLOC_MARKING_FREE); TH_ASSERT(marked_index != TRANSIENT_HEAP_ALLOC_MARKING_FREE);
if (0) fprintf(stderr, "clear_marked_index - block:%p mark_index:%d\n", (void *)block, marked_index); if (0) fprintf(stderr, "clear_marked_index - block:%p mark_index:%d\n", (void *)block, marked_index);
@ -811,19 +811,19 @@ transient_heap_block_update_refs(struct transient_heap* theap, struct transient_
void *ptr = &block->buff[i]; void *ptr = &block->buff[i];
struct transient_alloc_header *header = ptr; struct transient_alloc_header *header = ptr;
unpoison_memory_region(header, sizeof *header, false); asan_unpoison_memory_region(header, sizeof *header, false);
void *poisoned = __asan_region_is_poisoned((void *)header->obj, SIZEOF_VALUE); void *poisoned = __asan_region_is_poisoned((void *)header->obj, SIZEOF_VALUE);
unpoison_object(header->obj, false); asan_unpoison_object(header->obj, false);
header->obj = rb_gc_location(header->obj); header->obj = rb_gc_location(header->obj);
if (poisoned) { if (poisoned) {
poison_object(header->obj); asan_poison_object(header->obj);
} }
i += header->size; i += header->size;
poison_memory_region(header, sizeof *header); asan_poison_memory_region(header, sizeof *header);
n++; n++;
} }
} }