sync with OpenBSD -current
This commit is contained in:
parent
25f7188861
commit
8ff00f10fc
2137 changed files with 177389 additions and 104447 deletions
|
@ -1,4 +1,4 @@
|
|||
# $OpenBSD: Makefile,v 1.6 2023/07/05 15:34:52 robert Exp $
|
||||
# $OpenBSD: Makefile,v 1.7 2024/01/26 11:51:45 robert Exp $
|
||||
|
||||
.include <bsd.own.mk>
|
||||
|
||||
|
@ -18,11 +18,10 @@ CXXINCLUDEDIR= /usr/include/c++/v1
|
|||
LOCALHDRDIR= ${.CURDIR}/include/c++/v1
|
||||
CONFIG_SITE= ${LOCALHDRDIR}/__config_site
|
||||
|
||||
.PATH: ${SRCDIR} ${SRCDIR}/filesystem
|
||||
.PATH: ${SRCDIR} ${SRCDIR}/filesystem ${SRCDIR}/ryu
|
||||
|
||||
LIB= c++
|
||||
|
||||
|
||||
SRCS+= algorithm.cpp \
|
||||
any.cpp \
|
||||
atomic.cpp \
|
||||
|
@ -33,7 +32,6 @@ SRCS+= algorithm.cpp \
|
|||
condition_variable.cpp \
|
||||
condition_variable_destructor.cpp \
|
||||
debug.cpp \
|
||||
directory_iterator.cpp \
|
||||
exception.cpp \
|
||||
functional.cpp \
|
||||
future.cpp \
|
||||
|
@ -41,12 +39,14 @@ SRCS+= algorithm.cpp \
|
|||
ios.cpp \
|
||||
ios.instantiations.cpp \
|
||||
iostream.cpp \
|
||||
legacy_debug_handler.cpp \
|
||||
legacy_pointer_safety.cpp \
|
||||
locale.cpp \
|
||||
memory.cpp \
|
||||
memory_resource.cpp \
|
||||
mutex.cpp \
|
||||
mutex_destructor.cpp \
|
||||
new.cpp \
|
||||
operations.cpp \
|
||||
optional.cpp \
|
||||
random.cpp \
|
||||
random_shuffle.cpp \
|
||||
|
@ -61,14 +61,27 @@ SRCS+= algorithm.cpp \
|
|||
utility.cpp \
|
||||
valarray.cpp \
|
||||
variant.cpp \
|
||||
vector.cpp
|
||||
vector.cpp \
|
||||
verbose_abort.cpp
|
||||
|
||||
CPPFLAGS+= -Wall -DLIBCXXABI -I${HDRDIR} -D_LIBCPP_BUILDING_LIBRARY \
|
||||
# filesystem
|
||||
SRCS+= directory_iterator.cpp \
|
||||
operations.cpp
|
||||
# ryu
|
||||
SRCS+= d2fixed.cpp \
|
||||
d2s.cpp \
|
||||
f2s.cpp
|
||||
|
||||
CPPFLAGS+= -Wall -DLIBCXXABI -I${HDRDIR} -I${SRCDIR} -D_LIBCPP_BUILDING_LIBRARY \
|
||||
-DLIBCXX_BUILDING_LIBCXXABI -I${AHDRDIR} -I${UHDRDIR} -I${LOCALHDRDIR} \
|
||||
-DNDEBUG
|
||||
|
||||
# This is required because our __string directory has been moved
|
||||
CPPFLAGS+= -I${HDRDIR}/__string.d/
|
||||
|
||||
CXXFLAGS+= -nostdlib -nostdinc++
|
||||
.if empty(CXXFLAGS:M-std=*)
|
||||
CXXFLAGS+= -std=c++14
|
||||
CXXFLAGS+= -std=c++20
|
||||
.endif
|
||||
|
||||
LDADD+= -L${BSDOBJDIR}/gnu/lib/libcxxabi -lc++abi
|
||||
|
@ -80,79 +93,172 @@ STD_HEADERS= \
|
|||
__algorithm/any_of.h \
|
||||
__algorithm/binary_search.h \
|
||||
__algorithm/clamp.h \
|
||||
__algorithm/comp_ref_type.h \
|
||||
__algorithm/comp.h \
|
||||
__algorithm/comp_ref_type.h \
|
||||
__algorithm/copy.h \
|
||||
__algorithm/copy_backward.h \
|
||||
__algorithm/copy_if.h \
|
||||
__algorithm/copy_move_common.h \
|
||||
__algorithm/copy_n.h \
|
||||
__algorithm/copy.h \
|
||||
__algorithm/count_if.h \
|
||||
__algorithm/count.h \
|
||||
__algorithm/equal_range.h \
|
||||
__algorithm/count_if.h \
|
||||
__algorithm/equal.h \
|
||||
__algorithm/fill_n.h \
|
||||
__algorithm/equal_range.h \
|
||||
__algorithm/fill.h \
|
||||
__algorithm/fill_n.h \
|
||||
__algorithm/find.h \
|
||||
__algorithm/find_end.h \
|
||||
__algorithm/find_first_of.h \
|
||||
__algorithm/find_if_not.h \
|
||||
__algorithm/find_if.h \
|
||||
__algorithm/find.h \
|
||||
__algorithm/for_each_n.h \
|
||||
__algorithm/find_if_not.h \
|
||||
__algorithm/for_each.h \
|
||||
__algorithm/generate_n.h \
|
||||
__algorithm/for_each_n.h \
|
||||
__algorithm/generate.h \
|
||||
__algorithm/generate_n.h \
|
||||
__algorithm/half_positive.h \
|
||||
__algorithm/in_found_result.h \
|
||||
__algorithm/in_fun_result.h \
|
||||
__algorithm/in_in_out_result.h \
|
||||
__algorithm/in_in_result.h \
|
||||
__algorithm/in_out_out_result.h \
|
||||
__algorithm/in_out_result.h \
|
||||
__algorithm/includes.h \
|
||||
__algorithm/inplace_merge.h \
|
||||
__algorithm/is_heap_until.h \
|
||||
__algorithm/is_heap.h \
|
||||
__algorithm/is_heap_until.h \
|
||||
__algorithm/is_partitioned.h \
|
||||
__algorithm/is_permutation.h \
|
||||
__algorithm/is_sorted_until.h \
|
||||
__algorithm/is_sorted.h \
|
||||
__algorithm/is_sorted_until.h \
|
||||
__algorithm/iter_swap.h \
|
||||
__algorithm/iterator_operations.h \
|
||||
__algorithm/lexicographical_compare.h \
|
||||
__algorithm/lower_bound.h \
|
||||
__algorithm/make_heap.h \
|
||||
__algorithm/max_element.h \
|
||||
__algorithm/make_projected.h \
|
||||
__algorithm/max.h \
|
||||
__algorithm/max_element.h \
|
||||
__algorithm/merge.h \
|
||||
__algorithm/min_element.h \
|
||||
__algorithm/min.h \
|
||||
__algorithm/minmax_element.h \
|
||||
__algorithm/min_element.h \
|
||||
__algorithm/min_max_result.h \
|
||||
__algorithm/minmax.h \
|
||||
__algorithm/minmax_element.h \
|
||||
__algorithm/mismatch.h \
|
||||
__algorithm/move_backward.h \
|
||||
__algorithm/move.h \
|
||||
__algorithm/move_backward.h \
|
||||
__algorithm/next_permutation.h \
|
||||
__algorithm/none_of.h \
|
||||
__algorithm/nth_element.h \
|
||||
__algorithm/partial_sort_copy.h \
|
||||
__algorithm/partial_sort.h \
|
||||
__algorithm/partial_sort_copy.h \
|
||||
__algorithm/partition.h \
|
||||
__algorithm/partition_copy.h \
|
||||
__algorithm/partition_point.h \
|
||||
__algorithm/partition.h \
|
||||
__algorithm/pop_heap.h \
|
||||
__algorithm/prev_permutation.h \
|
||||
__algorithm/push_heap.h \
|
||||
__algorithm/ranges_adjacent_find.h \
|
||||
__algorithm/ranges_all_of.h \
|
||||
__algorithm/ranges_any_of.h \
|
||||
__algorithm/ranges_binary_search.h \
|
||||
__algorithm/ranges_clamp.h \
|
||||
__algorithm/ranges_copy.h \
|
||||
__algorithm/ranges_copy_backward.h \
|
||||
__algorithm/ranges_copy_if.h \
|
||||
__algorithm/ranges_copy_n.h \
|
||||
__algorithm/ranges_count.h \
|
||||
__algorithm/ranges_count_if.h \
|
||||
__algorithm/ranges_equal.h \
|
||||
__algorithm/ranges_equal_range.h \
|
||||
__algorithm/ranges_fill.h \
|
||||
__algorithm/ranges_fill_n.h \
|
||||
__algorithm/ranges_find.h \
|
||||
__algorithm/ranges_find_end.h \
|
||||
__algorithm/ranges_find_first_of.h \
|
||||
__algorithm/ranges_find_if.h \
|
||||
__algorithm/ranges_find_if_not.h \
|
||||
__algorithm/remove_copy_if.h \
|
||||
__algorithm/remove_copy.h \
|
||||
__algorithm/remove_if.h \
|
||||
__algorithm/ranges_for_each.h \
|
||||
__algorithm/ranges_for_each_n.h \
|
||||
__algorithm/ranges_generate.h \
|
||||
__algorithm/ranges_generate_n.h \
|
||||
__algorithm/ranges_includes.h \
|
||||
__algorithm/ranges_inplace_merge.h \
|
||||
__algorithm/ranges_is_heap.h \
|
||||
__algorithm/ranges_is_heap_until.h \
|
||||
__algorithm/ranges_is_partitioned.h \
|
||||
__algorithm/ranges_is_permutation.h \
|
||||
__algorithm/ranges_is_sorted.h \
|
||||
__algorithm/ranges_is_sorted_until.h \
|
||||
__algorithm/ranges_iterator_concept.h \
|
||||
__algorithm/ranges_lexicographical_compare.h \
|
||||
__algorithm/ranges_lower_bound.h \
|
||||
__algorithm/ranges_make_heap.h \
|
||||
__algorithm/ranges_max.h \
|
||||
__algorithm/ranges_max_element.h \
|
||||
__algorithm/ranges_merge.h \
|
||||
__algorithm/ranges_min.h \
|
||||
__algorithm/ranges_min_element.h \
|
||||
__algorithm/ranges_minmax.h \
|
||||
__algorithm/ranges_minmax_element.h \
|
||||
__algorithm/ranges_mismatch.h \
|
||||
__algorithm/ranges_move.h \
|
||||
__algorithm/ranges_move_backward.h \
|
||||
__algorithm/ranges_next_permutation.h \
|
||||
__algorithm/ranges_none_of.h \
|
||||
__algorithm/ranges_nth_element.h \
|
||||
__algorithm/ranges_partial_sort.h \
|
||||
__algorithm/ranges_partial_sort_copy.h \
|
||||
__algorithm/ranges_partition.h \
|
||||
__algorithm/ranges_partition_copy.h \
|
||||
__algorithm/ranges_partition_point.h \
|
||||
__algorithm/ranges_pop_heap.h \
|
||||
__algorithm/ranges_prev_permutation.h \
|
||||
__algorithm/ranges_push_heap.h \
|
||||
__algorithm/ranges_remove.h \
|
||||
__algorithm/ranges_remove_copy.h \
|
||||
__algorithm/ranges_remove_copy_if.h \
|
||||
__algorithm/ranges_remove_if.h \
|
||||
__algorithm/ranges_replace.h \
|
||||
__algorithm/ranges_replace_copy.h \
|
||||
__algorithm/ranges_replace_copy_if.h \
|
||||
__algorithm/ranges_replace_if.h \
|
||||
__algorithm/ranges_reverse.h \
|
||||
__algorithm/ranges_reverse_copy.h \
|
||||
__algorithm/ranges_rotate.h \
|
||||
__algorithm/ranges_rotate_copy.h \
|
||||
__algorithm/ranges_sample.h \
|
||||
__algorithm/ranges_search.h \
|
||||
__algorithm/ranges_search_n.h \
|
||||
__algorithm/ranges_set_difference.h \
|
||||
__algorithm/ranges_set_intersection.h \
|
||||
__algorithm/ranges_set_symmetric_difference.h \
|
||||
__algorithm/ranges_set_union.h \
|
||||
__algorithm/ranges_shuffle.h \
|
||||
__algorithm/ranges_sort.h \
|
||||
__algorithm/ranges_sort_heap.h \
|
||||
__algorithm/ranges_stable_partition.h \
|
||||
__algorithm/ranges_stable_sort.h \
|
||||
__algorithm/ranges_swap_ranges.h \
|
||||
__algorithm/ranges_transform.h \
|
||||
__algorithm/ranges_unique.h \
|
||||
__algorithm/ranges_unique_copy.h \
|
||||
__algorithm/ranges_upper_bound.h \
|
||||
__algorithm/remove.h \
|
||||
__algorithm/replace_copy_if.h \
|
||||
__algorithm/replace_copy.h \
|
||||
__algorithm/replace_if.h \
|
||||
__algorithm/remove_copy.h \
|
||||
__algorithm/remove_copy_if.h \
|
||||
__algorithm/remove_if.h \
|
||||
__algorithm/replace.h \
|
||||
__algorithm/reverse_copy.h \
|
||||
__algorithm/replace_copy.h \
|
||||
__algorithm/replace_copy_if.h \
|
||||
__algorithm/replace_if.h \
|
||||
__algorithm/reverse.h \
|
||||
__algorithm/rotate_copy.h \
|
||||
__algorithm/reverse_copy.h \
|
||||
__algorithm/rotate.h \
|
||||
__algorithm/rotate_copy.h \
|
||||
__algorithm/sample.h \
|
||||
__algorithm/search_n.h \
|
||||
__algorithm/search.h \
|
||||
__algorithm/search_n.h \
|
||||
__algorithm/set_difference.h \
|
||||
__algorithm/set_intersection.h \
|
||||
__algorithm/set_symmetric_difference.h \
|
||||
|
@ -161,34 +267,167 @@ STD_HEADERS= \
|
|||
__algorithm/shift_right.h \
|
||||
__algorithm/shuffle.h \
|
||||
__algorithm/sift_down.h \
|
||||
__algorithm/sort_heap.h \
|
||||
__algorithm/sort.h \
|
||||
__algorithm/sort_heap.h \
|
||||
__algorithm/stable_partition.h \
|
||||
__algorithm/stable_sort.h \
|
||||
__algorithm/swap_ranges.h \
|
||||
__algorithm/transform.h \
|
||||
__algorithm/unique_copy.h \
|
||||
__algorithm/uniform_random_bit_generator_adaptor.h \
|
||||
__algorithm/unique.h \
|
||||
__algorithm/unique_copy.h \
|
||||
__algorithm/unwrap_iter.h \
|
||||
__algorithm/unwrap_range.h \
|
||||
__algorithm/upper_bound.h \
|
||||
__assert \
|
||||
__availability \
|
||||
__bit/bit_cast.h \
|
||||
__bit/bit_ceil.h \
|
||||
__bit/bit_floor.h \
|
||||
__bit/bit_log2.h \
|
||||
__bit/bit_width.h \
|
||||
__bit/blsr.h \
|
||||
__bit/byteswap.h \
|
||||
__bit/countl.h \
|
||||
__bit/countr.h \
|
||||
__bit/endian.h \
|
||||
__bit/has_single_bit.h \
|
||||
__bit/popcount.h \
|
||||
__bit/rotate.h \
|
||||
__bit_reference \
|
||||
__bits \
|
||||
__bsd_locale_defaults.h \
|
||||
__bsd_locale_fallbacks.h \
|
||||
__charconv/chars_format.h \
|
||||
__charconv/from_chars_result.h \
|
||||
__charconv/tables.h \
|
||||
__charconv/to_chars_base_10.h \
|
||||
__charconv/to_chars_result.h \
|
||||
__chrono/calendar.h \
|
||||
__chrono/convert_to_timespec.h \
|
||||
__chrono/convert_to_tm.h \
|
||||
__chrono/day.h \
|
||||
__chrono/duration.h \
|
||||
__chrono/file_clock.h \
|
||||
__chrono/formatter.h \
|
||||
__chrono/hh_mm_ss.h \
|
||||
__chrono/high_resolution_clock.h \
|
||||
__chrono/literals.h \
|
||||
__chrono/month.h \
|
||||
__chrono/month_weekday.h \
|
||||
__chrono/monthday.h \
|
||||
__chrono/ostream.h \
|
||||
__chrono/parser_std_format_spec.h \
|
||||
__chrono/statically_widen.h \
|
||||
__chrono/steady_clock.h \
|
||||
__chrono/system_clock.h \
|
||||
__chrono/time_point.h \
|
||||
__chrono/weekday.h \
|
||||
__chrono/year.h \
|
||||
__chrono/year_month.h \
|
||||
__chrono/year_month_day.h \
|
||||
__chrono/year_month_weekday.h \
|
||||
__compare/common_comparison_category.h \
|
||||
__compare/compare_partial_order_fallback.h \
|
||||
__compare/compare_strong_order_fallback.h \
|
||||
__compare/compare_three_way.h \
|
||||
__compare/compare_three_way_result.h \
|
||||
__compare/compare_weak_order_fallback.h \
|
||||
__compare/is_eq.h \
|
||||
__compare/ordering.h \
|
||||
__compare/partial_order.h \
|
||||
__compare/strong_order.h \
|
||||
__compare/synth_three_way.h \
|
||||
__compare/three_way_comparable.h \
|
||||
__compare/weak_order.h \
|
||||
__concepts/arithmetic.h \
|
||||
__concepts/assignable.h \
|
||||
__concepts/boolean_testable.h \
|
||||
__concepts/class_or_enum.h \
|
||||
__concepts/common_reference_with.h \
|
||||
__concepts/common_with.h \
|
||||
__concepts/constructible.h \
|
||||
__concepts/convertible_to.h \
|
||||
__concepts/copyable.h \
|
||||
__concepts/derived_from.h \
|
||||
__concepts/destructible.h \
|
||||
__concepts/different_from.h \
|
||||
__concepts/equality_comparable.h \
|
||||
__concepts/invocable.h \
|
||||
__concepts/movable.h \
|
||||
__concepts/predicate.h \
|
||||
__concepts/regular.h \
|
||||
__concepts/relation.h \
|
||||
__concepts/same_as.h \
|
||||
__concepts/semiregular.h \
|
||||
__concepts/swappable.h \
|
||||
__concepts/totally_ordered.h \
|
||||
__config \
|
||||
__coroutine/coroutine_handle.h \
|
||||
__coroutine/coroutine_traits.h \
|
||||
__coroutine/noop_coroutine_handle.h \
|
||||
__coroutine/trivial_awaitables.h \
|
||||
__debug \
|
||||
__debug_utils/randomize_range.h \
|
||||
__errc \
|
||||
__expected/bad_expected_access.h \
|
||||
__expected/expected.h \
|
||||
__expected/unexpect.h \
|
||||
__expected/unexpected.h \
|
||||
__filesystem/copy_options.h \
|
||||
__filesystem/directory_entry.h \
|
||||
__filesystem/directory_iterator.h \
|
||||
__filesystem/directory_options.h \
|
||||
__filesystem/file_status.h \
|
||||
__filesystem/file_time_type.h \
|
||||
__filesystem/file_type.h \
|
||||
__filesystem/filesystem_error.h \
|
||||
__filesystem/operations.h \
|
||||
__filesystem/path.h \
|
||||
__filesystem/path_iterator.h \
|
||||
__filesystem/perm_options.h \
|
||||
__filesystem/perms.h \
|
||||
__filesystem/recursive_directory_iterator.h \
|
||||
__filesystem/space_info.h \
|
||||
__filesystem/u8path.h \
|
||||
__format/buffer.h \
|
||||
__format/concepts.h \
|
||||
__format/container_adaptor.h \
|
||||
__format/enable_insertable.h \
|
||||
__format/escaped_output_table.h \
|
||||
__format/extended_grapheme_cluster_table.h \
|
||||
__format/format_arg.h \
|
||||
__format/format_arg_store.h \
|
||||
__format/format_args.h \
|
||||
__format/format_context.h \
|
||||
__format/format_error.h \
|
||||
__format/format_functions.h \
|
||||
__format/format_fwd.h \
|
||||
__format/format_parse_context.h \
|
||||
__function_like.h \
|
||||
__functional_base \
|
||||
__format/format_string.h \
|
||||
__format/format_to_n_result.h \
|
||||
__format/formatter.h \
|
||||
__format/formatter_bool.h \
|
||||
__format/formatter_char.h \
|
||||
__format/formatter_floating_point.h \
|
||||
__format/formatter_integer.h \
|
||||
__format/formatter_integral.h \
|
||||
__format/formatter_output.h \
|
||||
__format/formatter_pointer.h \
|
||||
__format/formatter_string.h \
|
||||
__format/formatter_tuple.h \
|
||||
__format/parser_std_format_spec.h \
|
||||
__format/range_default_formatter.h \
|
||||
__format/range_formatter.h \
|
||||
__format/unicode.h \
|
||||
__functional/binary_function.h \
|
||||
__functional/binary_negate.h \
|
||||
__functional/bind_front.h \
|
||||
__functional/bind.h \
|
||||
__functional/bind_back.h \
|
||||
__functional/bind_front.h \
|
||||
__functional/binder1st.h \
|
||||
__functional/binder2nd.h \
|
||||
__functional/boyer_moore_searcher.h \
|
||||
__functional/compose.h \
|
||||
__functional/default_searcher.h \
|
||||
__functional/function.h \
|
||||
__functional/hash.h \
|
||||
|
@ -208,10 +447,22 @@ STD_HEADERS= \
|
|||
__functional/unary_negate.h \
|
||||
__functional/unwrap_ref.h \
|
||||
__functional/weak_result_type.h \
|
||||
__fwd/array.h \
|
||||
__fwd/get.h \
|
||||
__fwd/hash.h \
|
||||
__fwd/memory_resource.h \
|
||||
__fwd/pair.h \
|
||||
__fwd/span.h \
|
||||
__fwd/string.h \
|
||||
__fwd/string_view.h \
|
||||
__fwd/subrange.h \
|
||||
__fwd/tuple.h \
|
||||
__hash_table \
|
||||
__ios/fpos.h \
|
||||
__iterator/access.h \
|
||||
__iterator/advance.h \
|
||||
__iterator/back_insert_iterator.h \
|
||||
__iterator/bounded_iter.h \
|
||||
__iterator/common_iterator.h \
|
||||
__iterator/concepts.h \
|
||||
__iterator/counted_iterator.h \
|
||||
|
@ -222,107 +473,342 @@ STD_HEADERS= \
|
|||
__iterator/erase_if_container.h \
|
||||
__iterator/front_insert_iterator.h \
|
||||
__iterator/incrementable_traits.h \
|
||||
__iterator/indirectly_comparable.h \
|
||||
__iterator/insert_iterator.h \
|
||||
__iterator/istream_iterator.h \
|
||||
__iterator/istreambuf_iterator.h \
|
||||
__iterator/iter_move.h \
|
||||
__iterator/iter_swap.h \
|
||||
__iterator/iterator_traits.h \
|
||||
__iterator/iterator.h \
|
||||
__iterator/iterator_traits.h \
|
||||
__iterator/iterator_with_data.h \
|
||||
__iterator/mergeable.h \
|
||||
__iterator/move_iterator.h \
|
||||
__iterator/move_sentinel.h \
|
||||
__iterator/next.h \
|
||||
__iterator/ostream_iterator.h \
|
||||
__iterator/ostreambuf_iterator.h \
|
||||
__iterator/permutable.h \
|
||||
__iterator/prev.h \
|
||||
__iterator/projected.h \
|
||||
__iterator/readable_traits.h \
|
||||
__iterator/reverse_access.h \
|
||||
__iterator/reverse_iterator.h \
|
||||
__iterator/segmented_iterator.h \
|
||||
__iterator/size.h \
|
||||
__iterator/sortable.h \
|
||||
__iterator/unreachable_sentinel.h \
|
||||
__iterator/wrap_iter.h \
|
||||
__libcpp_version \
|
||||
__locale \
|
||||
__mbstate_t.h \
|
||||
__memory/addressof.h \
|
||||
__memory/align.h \
|
||||
__memory/allocate_at_least.h \
|
||||
__memory/allocation_guard.h \
|
||||
__memory/allocator_arg_t.h \
|
||||
__memory/allocator_traits.h \
|
||||
__memory/allocator.h \
|
||||
__memory/allocator_arg_t.h \
|
||||
__memory/allocator_destructor.h \
|
||||
__memory/allocator_traits.h \
|
||||
__memory/assume_aligned.h \
|
||||
__memory/auto_ptr.h \
|
||||
__memory/builtin_new_allocator.h \
|
||||
__memory/compressed_pair.h \
|
||||
__memory/concepts.h \
|
||||
__memory/construct_at.h \
|
||||
__memory/pointer_safety.h \
|
||||
__memory/destruct_n.h \
|
||||
__memory/pointer_traits.h \
|
||||
__memory/ranges_construct_at.h \
|
||||
__memory/ranges_uninitialized_algorithms.h \
|
||||
__memory/raw_storage_iterator.h \
|
||||
__memory/shared_ptr.h \
|
||||
__memory/swap_allocator.h \
|
||||
__memory/temp_value.h \
|
||||
__memory/temporary_buffer.h \
|
||||
__memory/uninitialized_algorithms.h \
|
||||
__memory/unique_ptr.h \
|
||||
__memory/uses_allocator.h \
|
||||
__memory/uses_allocator_construction.h \
|
||||
__memory/voidify.h \
|
||||
__memory_resource/memory_resource.h \
|
||||
__memory_resource/monotonic_buffer_resource.h \
|
||||
__memory_resource/polymorphic_allocator.h \
|
||||
__memory_resource/pool_options.h \
|
||||
__memory_resource/synchronized_pool_resource.h \
|
||||
__memory_resource/unsynchronized_pool_resource.h \
|
||||
__mutex_base \
|
||||
__node_handle \
|
||||
__nullptr \
|
||||
__numeric/accumulate.h \
|
||||
__numeric/adjacent_difference.h \
|
||||
__numeric/exclusive_scan.h \
|
||||
__numeric/gcd_lcm.h \
|
||||
__numeric/inclusive_scan.h \
|
||||
__numeric/inner_product.h \
|
||||
__numeric/iota.h \
|
||||
__numeric/midpoint.h \
|
||||
__numeric/partial_sum.h \
|
||||
__numeric/reduce.h \
|
||||
__numeric/transform_exclusive_scan.h \
|
||||
__numeric/transform_inclusive_scan.h \
|
||||
__numeric/transform_reduce.h \
|
||||
__random/bernoulli_distribution.h \
|
||||
__random/binomial_distribution.h \
|
||||
__random/cauchy_distribution.h \
|
||||
__random/chi_squared_distribution.h \
|
||||
__random/clamp_to_integral.h \
|
||||
__random/default_random_engine.h \
|
||||
__random/discard_block_engine.h \
|
||||
__random/discrete_distribution.h \
|
||||
__random/exponential_distribution.h \
|
||||
__random/extreme_value_distribution.h \
|
||||
__random/fisher_f_distribution.h \
|
||||
__random/gamma_distribution.h \
|
||||
__random/generate_canonical.h \
|
||||
__random/geometric_distribution.h \
|
||||
__random/independent_bits_engine.h \
|
||||
__random/is_seed_sequence.h \
|
||||
__random/is_valid.h \
|
||||
__random/knuth_b.h \
|
||||
__random/linear_congruential_engine.h \
|
||||
__random/log2.h \
|
||||
__random/lognormal_distribution.h \
|
||||
__random/mersenne_twister_engine.h \
|
||||
__random/negative_binomial_distribution.h \
|
||||
__random/normal_distribution.h \
|
||||
__random/piecewise_constant_distribution.h \
|
||||
__random/piecewise_linear_distribution.h \
|
||||
__random/poisson_distribution.h \
|
||||
__random/random_device.h \
|
||||
__random/ranlux.h \
|
||||
__random/seed_seq.h \
|
||||
__random/shuffle_order_engine.h \
|
||||
__random/student_t_distribution.h \
|
||||
__random/subtract_with_carry_engine.h \
|
||||
__random/uniform_int_distribution.h \
|
||||
__random/uniform_random_bit_generator.h \
|
||||
__random/uniform_real_distribution.h \
|
||||
__random/weibull_distribution.h \
|
||||
__ranges/access.h \
|
||||
__ranges/all.h \
|
||||
__ranges/as_rvalue_view.h \
|
||||
__ranges/common_view.h \
|
||||
__ranges/concepts.h \
|
||||
__ranges/copyable_box.h \
|
||||
__ranges/counted.h \
|
||||
__ranges/dangling.h \
|
||||
__ranges/data.h \
|
||||
__ranges/drop_view.h \
|
||||
__ranges/empty_view.h \
|
||||
__ranges/drop_while_view.h \
|
||||
__ranges/elements_view.h \
|
||||
__ranges/empty.h \
|
||||
__ranges/empty_view.h \
|
||||
__ranges/enable_borrowed_range.h \
|
||||
__ranges/enable_view.h \
|
||||
__ranges/filter_view.h \
|
||||
__ranges/iota_view.h \
|
||||
__ranges/istream_view.h \
|
||||
__ranges/join_view.h \
|
||||
__ranges/lazy_split_view.h \
|
||||
__ranges/non_propagating_cache.h \
|
||||
__ranges/owning_view.h \
|
||||
__ranges/range_adaptor.h \
|
||||
__ranges/rbegin.h \
|
||||
__ranges/ref_view.h \
|
||||
__ranges/rend.h \
|
||||
__ranges/reverse_view.h \
|
||||
__ranges/single_view.h \
|
||||
__ranges/size.h \
|
||||
__ranges/split_view.h \
|
||||
__ranges/subrange.h \
|
||||
__ranges/take_view.h \
|
||||
__ranges/take_while_view.h \
|
||||
__ranges/transform_view.h \
|
||||
__ranges/view_interface.h \
|
||||
__ranges/views.h \
|
||||
__ranges/zip_view.h \
|
||||
__split_buffer \
|
||||
__std_stream \
|
||||
__string \
|
||||
__support/android/locale_bionic.h \
|
||||
__support/fuchsia/xlocale.h \
|
||||
__support/ibm/gettod_zos.h \
|
||||
__support/ibm/limits.h \
|
||||
__support/ibm/locale_mgmt_aix.h \
|
||||
__support/ibm/locale_mgmt_zos.h \
|
||||
__support/ibm/nanosleep.h \
|
||||
__support/ibm/support.h \
|
||||
__support/ibm/xlocale.h \
|
||||
__support/musl/xlocale.h \
|
||||
__support/newlib/xlocale.h \
|
||||
__support/nuttx/xlocale.h \
|
||||
__support/openbsd/xlocale.h \
|
||||
__support/solaris/floatingpoint.h \
|
||||
__support/solaris/wchar.h \
|
||||
__support/solaris/xlocale.h \
|
||||
__support/win32/limits_msvc_win32.h \
|
||||
__support/win32/locale_win32.h \
|
||||
__support/xlocale/__nop_locale_mgmt.h \
|
||||
__support/xlocale/__posix_l_fallback.h \
|
||||
__support/xlocale/__strtonum_fallback.h \
|
||||
__thread/poll_with_backoff.h \
|
||||
__thread/timed_backoff_policy.h \
|
||||
__threading_support \
|
||||
__tree \
|
||||
__tuple \
|
||||
__tuple_dir/apply_cv.h \
|
||||
__tuple_dir/make_tuple_types.h \
|
||||
__tuple_dir/pair_like.h \
|
||||
__tuple_dir/sfinae_helpers.h \
|
||||
__tuple_dir/tuple_element.h \
|
||||
__tuple_dir/tuple_indices.h \
|
||||
__tuple_dir/tuple_like.h \
|
||||
__tuple_dir/tuple_like_ext.h \
|
||||
__tuple_dir/tuple_size.h \
|
||||
__tuple_dir/tuple_types.h \
|
||||
__type_traits/add_const.h \
|
||||
__type_traits/add_cv.h \
|
||||
__type_traits/add_lvalue_reference.h \
|
||||
__type_traits/add_pointer.h \
|
||||
__type_traits/add_rvalue_reference.h \
|
||||
__type_traits/add_volatile.h \
|
||||
__type_traits/aligned_storage.h \
|
||||
__type_traits/aligned_union.h \
|
||||
__type_traits/alignment_of.h \
|
||||
__type_traits/apply_cv.h \
|
||||
__type_traits/can_extract_key.h \
|
||||
__type_traits/common_reference.h \
|
||||
__type_traits/common_type.h \
|
||||
__type_traits/conditional.h \
|
||||
__type_traits/conjunction.h \
|
||||
__type_traits/copy_cv.h \
|
||||
__type_traits/copy_cvref.h \
|
||||
__type_traits/decay.h \
|
||||
__type_traits/dependent_type.h \
|
||||
__type_traits/disjunction.h \
|
||||
__type_traits/enable_if.h \
|
||||
__type_traits/extent.h \
|
||||
__type_traits/has_unique_object_representation.h \
|
||||
__type_traits/has_virtual_destructor.h \
|
||||
__type_traits/integral_constant.h \
|
||||
__type_traits/is_abstract.h \
|
||||
__type_traits/is_aggregate.h \
|
||||
__type_traits/is_allocator.h \
|
||||
__type_traits/is_always_bitcastable.h \
|
||||
__type_traits/is_arithmetic.h \
|
||||
__type_traits/is_array.h \
|
||||
__type_traits/is_assignable.h \
|
||||
__type_traits/is_base_of.h \
|
||||
__type_traits/is_bounded_array.h \
|
||||
__type_traits/is_callable.h \
|
||||
__type_traits/is_char_like_type.h \
|
||||
__type_traits/is_class.h \
|
||||
__type_traits/is_compound.h \
|
||||
__type_traits/is_const.h \
|
||||
__type_traits/is_constant_evaluated.h \
|
||||
__type_traits/is_constructible.h \
|
||||
__type_traits/is_convertible.h \
|
||||
__type_traits/is_copy_assignable.h \
|
||||
__type_traits/is_copy_constructible.h \
|
||||
__type_traits/is_core_convertible.h \
|
||||
__type_traits/is_default_constructible.h \
|
||||
__type_traits/is_destructible.h \
|
||||
__type_traits/is_empty.h \
|
||||
__type_traits/is_enum.h \
|
||||
__type_traits/is_final.h \
|
||||
__type_traits/is_floating_point.h \
|
||||
__type_traits/is_function.h \
|
||||
__type_traits/is_fundamental.h \
|
||||
__type_traits/is_implicitly_default_constructible.h \
|
||||
__type_traits/is_integral.h \
|
||||
__type_traits/is_literal_type.h \
|
||||
__type_traits/is_member_function_pointer.h \
|
||||
__type_traits/is_member_object_pointer.h \
|
||||
__type_traits/is_member_pointer.h \
|
||||
__type_traits/is_move_assignable.h \
|
||||
__type_traits/is_move_constructible.h \
|
||||
__type_traits/is_nothrow_assignable.h \
|
||||
__type_traits/is_nothrow_constructible.h \
|
||||
__type_traits/is_nothrow_convertible.h \
|
||||
__type_traits/is_nothrow_copy_assignable.h \
|
||||
__type_traits/is_nothrow_copy_constructible.h \
|
||||
__type_traits/is_nothrow_default_constructible.h \
|
||||
__type_traits/is_nothrow_destructible.h \
|
||||
__type_traits/is_nothrow_move_assignable.h \
|
||||
__type_traits/is_nothrow_move_constructible.h \
|
||||
__type_traits/is_null_pointer.h \
|
||||
__type_traits/is_object.h \
|
||||
__type_traits/is_pod.h \
|
||||
__type_traits/is_pointer.h \
|
||||
__type_traits/is_polymorphic.h \
|
||||
__type_traits/is_primary_template.h \
|
||||
__type_traits/is_reference.h \
|
||||
__type_traits/is_reference_wrapper.h \
|
||||
__type_traits/is_referenceable.h \
|
||||
__type_traits/is_same.h \
|
||||
__type_traits/is_scalar.h \
|
||||
__type_traits/is_scoped_enum.h \
|
||||
__type_traits/is_signed.h \
|
||||
__type_traits/is_signed_integer.h \
|
||||
__type_traits/is_specialization.h \
|
||||
__type_traits/is_standard_layout.h \
|
||||
__type_traits/is_swappable.h \
|
||||
__type_traits/is_trivial.h \
|
||||
__type_traits/is_trivially_assignable.h \
|
||||
__type_traits/is_trivially_constructible.h \
|
||||
__type_traits/is_trivially_copy_assignable.h \
|
||||
__type_traits/is_trivially_copy_constructible.h \
|
||||
__type_traits/is_trivially_copyable.h \
|
||||
__type_traits/is_trivially_default_constructible.h \
|
||||
__type_traits/is_trivially_destructible.h \
|
||||
__type_traits/is_trivially_move_assignable.h \
|
||||
__type_traits/is_trivially_move_constructible.h \
|
||||
__type_traits/is_unbounded_array.h \
|
||||
__type_traits/is_union.h \
|
||||
__type_traits/is_unsigned.h \
|
||||
__type_traits/is_unsigned_integer.h \
|
||||
__type_traits/is_valid_expansion.h \
|
||||
__type_traits/is_void.h \
|
||||
__type_traits/is_volatile.h \
|
||||
__type_traits/lazy.h \
|
||||
__type_traits/make_32_64_or_128_bit.h \
|
||||
__type_traits/make_const_lvalue_ref.h \
|
||||
__type_traits/make_signed.h \
|
||||
__type_traits/make_unsigned.h \
|
||||
__type_traits/maybe_const.h \
|
||||
__type_traits/nat.h \
|
||||
__type_traits/negation.h \
|
||||
__type_traits/noexcept_move_assign_container.h \
|
||||
__type_traits/promote.h \
|
||||
__type_traits/rank.h \
|
||||
__type_traits/remove_all_extents.h \
|
||||
__type_traits/remove_const.h \
|
||||
__type_traits/remove_const_ref.h \
|
||||
__type_traits/remove_cv.h \
|
||||
__type_traits/remove_cvref.h \
|
||||
__type_traits/remove_extent.h \
|
||||
__type_traits/remove_pointer.h \
|
||||
__type_traits/remove_reference.h \
|
||||
__type_traits/remove_volatile.h \
|
||||
__type_traits/result_of.h \
|
||||
__type_traits/strip_signature.h \
|
||||
__type_traits/type_identity.h \
|
||||
__type_traits/type_list.h \
|
||||
__type_traits/underlying_type.h \
|
||||
__type_traits/void_t.h \
|
||||
__undef_macros \
|
||||
__utility/__decay_copy.h \
|
||||
__utility/as_const.h \
|
||||
__utility/auto_cast.h \
|
||||
__utility/cmp.h \
|
||||
__utility/convert_to_integral.h \
|
||||
__utility/declval.h \
|
||||
__utility/exception_guard.h \
|
||||
__utility/exchange.h \
|
||||
__utility/forward.h \
|
||||
__utility/forward_like.h \
|
||||
__utility/in_place.h \
|
||||
__utility/integer_sequence.h \
|
||||
__utility/move.h \
|
||||
__utility/pair.h \
|
||||
__utility/piecewise_construct.h \
|
||||
__utility/priority_tag.h \
|
||||
__utility/rel_ops.h \
|
||||
__utility/swap.h \
|
||||
__utility/to_underlying.h \
|
||||
__utility/unreachable.h \
|
||||
__variant/monostate.h \
|
||||
__verbose_abort \
|
||||
algorithm \
|
||||
any \
|
||||
array \
|
||||
|
@ -349,6 +835,7 @@ STD_HEADERS= \
|
|||
complex.h \
|
||||
concepts \
|
||||
condition_variable \
|
||||
coroutine \
|
||||
csetjmp \
|
||||
csignal \
|
||||
cstdarg \
|
||||
|
@ -361,18 +848,19 @@ STD_HEADERS= \
|
|||
ctgmath \
|
||||
ctime \
|
||||
ctype.h \
|
||||
cuchar \
|
||||
cwchar \
|
||||
cwctype \
|
||||
deque \
|
||||
errno.h \
|
||||
exception \
|
||||
execution \
|
||||
expected \
|
||||
experimental/__config \
|
||||
experimental/__memory \
|
||||
experimental/algorithm \
|
||||
experimental/coroutine \
|
||||
experimental/deque \
|
||||
experimental/filesystem \
|
||||
experimental/forward_list \
|
||||
experimental/functional \
|
||||
experimental/iterator \
|
||||
|
@ -409,6 +897,7 @@ STD_HEADERS= \
|
|||
istream \
|
||||
iterator \
|
||||
latch \
|
||||
libcxx.imp \
|
||||
limits \
|
||||
limits.h \
|
||||
list \
|
||||
|
@ -417,7 +906,7 @@ STD_HEADERS= \
|
|||
map \
|
||||
math.h \
|
||||
memory \
|
||||
module.modulemap \
|
||||
memory_resource \
|
||||
mutex \
|
||||
new \
|
||||
numbers \
|
||||
|
@ -427,7 +916,6 @@ STD_HEADERS= \
|
|||
queue \
|
||||
random \
|
||||
ranges \
|
||||
ranges \
|
||||
ratio \
|
||||
regex \
|
||||
scoped_allocator \
|
||||
|
@ -435,9 +923,11 @@ STD_HEADERS= \
|
|||
set \
|
||||
setjmp.h \
|
||||
shared_mutex \
|
||||
source_location \
|
||||
span \
|
||||
sstream \
|
||||
stack \
|
||||
stdatomic.h \
|
||||
stdbool.h \
|
||||
stddef.h \
|
||||
stdexcept \
|
||||
|
@ -446,8 +936,8 @@ STD_HEADERS= \
|
|||
stdlib.h \
|
||||
streambuf \
|
||||
string \
|
||||
string_view \
|
||||
string.h \
|
||||
string_view \
|
||||
strstream \
|
||||
system_error \
|
||||
tgmath.h \
|
||||
|
@ -456,6 +946,7 @@ STD_HEADERS= \
|
|||
type_traits \
|
||||
typeindex \
|
||||
typeinfo \
|
||||
uchar.h \
|
||||
unordered_map \
|
||||
unordered_set \
|
||||
utility \
|
||||
|
@ -466,6 +957,12 @@ STD_HEADERS= \
|
|||
wchar.h \
|
||||
wctype.h
|
||||
|
||||
# __string has moved from a file to a directory which CVS cannot
|
||||
# handle so we have to do some trickery with these
|
||||
STRING_HEADERS= \
|
||||
__string/char_traits.h \
|
||||
__string/extern_template_lists.h
|
||||
|
||||
includes:
|
||||
@echo installing ${STD_HEADERS}
|
||||
. for hdr in ${STD_HEADERS}
|
||||
|
@ -476,6 +973,12 @@ includes:
|
|||
cmp -s ${CONFIG_SITE} ${DESTDIR}/${CXXINCLUDEDIR}/${CONFIG_SITE:T} || \
|
||||
${INSTALL} ${INSTALL_COPY} -D -m 444 ${CONFIG_SITE} \
|
||||
${DESTDIR}/${CXXINCLUDEDIR}/${CONFIG_SITE:T}
|
||||
@echo installing ${STRING_HEADERS}
|
||||
. for hdr in ${STRING_HEADERS}
|
||||
cmp -s ${HDRDIR}/__string.d/${hdr} ${DESTDIR}/${CXXINCLUDEDIR}/${hdr} || \
|
||||
${INSTALL} ${INSTALL_COPY} -D -m 444 ${HDRDIR}/__string.d/${hdr} \
|
||||
${DESTDIR}/${CXXINCLUDEDIR}/${hdr};
|
||||
. endfor
|
||||
|
||||
.include <bsd.lib.mk>
|
||||
|
||||
|
|
|
@ -6,37 +6,49 @@
|
|||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef _LIBCPP_CONFIG_SITE
|
||||
#define _LIBCPP_CONFIG_SITE
|
||||
#ifndef _LIBCPP___CONFIG_SITE
|
||||
#define _LIBCPP___CONFIG_SITE
|
||||
|
||||
/* #undef _LIBCPP_ABI_VERSION */
|
||||
/* #undef _LIBCPP_ABI_UNSTABLE */
|
||||
#define _LIBCPP_ABI_VERSION 1
|
||||
#define _LIBCPP_ABI_NAMESPACE __1
|
||||
/* #undef _LIBCPP_ABI_FORCE_ITANIUM */
|
||||
/* #undef _LIBCPP_ABI_FORCE_MICROSOFT */
|
||||
/* #undef _LIBCPP_HIDE_FROM_ABI_PER_TU_BY_DEFAULT */
|
||||
/* #undef _LIBCPP_HAS_NO_GLOBAL_FILESYSTEM_NAMESPACE */
|
||||
/* #undef _LIBCPP_HAS_NO_STDIN */
|
||||
/* #undef _LIBCPP_HAS_NO_STDOUT */
|
||||
/* #undef _LIBCPP_HAS_NO_THREADS */
|
||||
/* #undef _LIBCPP_HAS_NO_MONOTONIC_CLOCK */
|
||||
/* #undef _LIBCPP_HAS_NO_THREAD_UNSAFE_C_FUNCTIONS */
|
||||
/* #undef _LIBCPP_HAS_MUSL_LIBC */
|
||||
/* #undef _LIBCPP_HAS_THREAD_API_PTHREAD */
|
||||
/* #undef _LIBCPP_HAS_THREAD_API_EXTERNAL */
|
||||
/* #undef _LIBCPP_HAS_THREAD_API_WIN32 */
|
||||
/* #undef _LIBCPP_HAS_THREAD_LIBRARY_EXTERNAL */
|
||||
/* #undef _LIBCPP_DISABLE_VISIBILITY_ANNOTATIONS */
|
||||
#define _LIBCPP_HAS_NO_VENDOR_AVAILABILITY_ANNOTATIONS
|
||||
/* #undef _LIBCPP_NO_VCRUNTIME */
|
||||
/* #undef _LIBCPP_TYPEINFO_COMPARISON_IMPLEMENTATION */
|
||||
/* #undef _LIBCPP_ABI_NAMESPACE */
|
||||
/* #undef _LIBCPP_HAS_NO_FILESYSTEM_LIBRARY */
|
||||
/* #undef _LIBCPP_HAS_PARALLEL_ALGORITHMS */
|
||||
/* #undef _LIBCPP_HAS_NO_FILESYSTEM */
|
||||
/* #undef _LIBCPP_HAS_NO_RANDOM_DEVICE */
|
||||
/* #undef _LIBCPP_HAS_NO_LOCALIZATION */
|
||||
/* #undef _LIBCPP_HAS_NO_INCOMPLETE_FORMAT */
|
||||
/* #undef _LIBCPP_HAS_NO_INCOMPLETE_RANGES */
|
||||
/* #undef _LIBCPP_HAS_NO_WIDE_CHARACTERS */
|
||||
#define _LIBCPP_ENABLE_ASSERTIONS_DEFAULT 0
|
||||
|
||||
// PSTL backends
|
||||
/* #undef _LIBCPP_PSTL_CPU_BACKEND_SERIAL */
|
||||
#define _LIBCPP_PSTL_CPU_BACKEND_THREAD
|
||||
/* #undef _LIBCPP_PSTL_CPU_BACKEND_LIBDISPATCH */
|
||||
|
||||
// Hardening.
|
||||
#define _LIBCPP_ENABLE_HARDENED_MODE_DEFAULT 0
|
||||
#define _LIBCPP_ENABLE_DEBUG_MODE_DEFAULT 0
|
||||
|
||||
// __USE_MINGW_ANSI_STDIO gets redefined on MinGW
|
||||
#ifdef __clang__
|
||||
# pragma clang diagnostic push
|
||||
# pragma clang diagnostic ignored "-Wmacro-redefined"
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
#endif // _LIBCPP_CONFIG_SITE
|
||||
|
||||
#ifdef __clang__
|
||||
# pragma clang diagnostic pop
|
||||
#endif
|
||||
|
||||
#endif // _LIBCPP___CONFIG_SITE
|
||||
|
|
|
@ -1,2 +1,2 @@
|
|||
major=9
|
||||
major=10
|
||||
minor=0
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
# $OpenBSD: Makefile,v 1.4 2021/12/17 14:55:44 patrick Exp $
|
||||
# $OpenBSD: Makefile,v 1.5 2024/01/26 11:51:45 robert Exp $
|
||||
|
||||
.include <bsd.own.mk>
|
||||
|
||||
|
@ -12,6 +12,7 @@ CXX= clang++
|
|||
HDRDIR= ${.CURDIR}/../../../gnu/llvm/libcxxabi/include
|
||||
SRCDIR= ${.CURDIR}/../../../gnu/llvm/libcxxabi/src
|
||||
SHDRDIR= ${.CURDIR}/../../../gnu/llvm/libcxx/include
|
||||
SSHDRDIR= ${.CURDIR}/../../../gnu/llvm/libcxx/src/include
|
||||
UHDRDIR= ${.CURDIR}/../../../gnu/llvm/libunwind/include
|
||||
CXXINCLUDEDIR= /usr/include/c++/v1
|
||||
|
||||
|
@ -49,14 +50,15 @@ SRCS+= abort_message.cpp \
|
|||
libunwind.cpp
|
||||
|
||||
CPPFLAGS+= -Wall -I${SHDRDIR} -I${HDRDIR} -I${UHDRDIR} \
|
||||
-I${LOCALHDRDIR} -I${SHDRDIR}/../
|
||||
-I${LOCALHDRDIR} -I${SHDRDIR}/../ -I${SSHDRDIR}/../
|
||||
CPPFLAGS+= -D_LIBUNWIND_IS_NATIVE_ONLY
|
||||
CPPFLAGS+= -D_LIBCXXABI_BUILDING_LIBRARY
|
||||
CPPFLAGS+= -D_LIBCPP_BUILDING_LIBRARY
|
||||
CPPFLAGS+= -DNDEBUG
|
||||
CFLAGS+= -nostdlib -funwind-tables
|
||||
CXXFLAGS+= -nostdlib -nostdinc++ -funwind-tables
|
||||
.if empty(CXXFLAGS:M-std=*)
|
||||
CXXFLAGS+= -std=c++11
|
||||
CXXFLAGS+= -std=c++20
|
||||
.endif
|
||||
|
||||
STD_HEADERS= cxxabi.h \
|
||||
|
@ -69,7 +71,9 @@ STDDIR= ${CXXINCLUDEDIR}
|
|||
|
||||
STD_UHEADERS= libunwind.h \
|
||||
__libunwind_config.h \
|
||||
unwind.h
|
||||
unwind.h \
|
||||
unwind_arm_ehabi.h \
|
||||
unwind_itanium.h
|
||||
|
||||
.for hdr in ${STD_UHEADERS}
|
||||
USTD+= ${hdr} ${UHDRDIR}/${hdr}
|
||||
|
|
|
@ -1,3 +1,3 @@
|
|||
# Don't forget to give libc++ the same type of bump!
|
||||
major=6
|
||||
major=7
|
||||
minor=0
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
# $OpenBSD: Makefile,v 1.2 2021/12/17 14:55:44 patrick Exp $
|
||||
# $OpenBSD: Makefile,v 1.3 2024/01/26 11:51:45 robert Exp $
|
||||
|
||||
.include <bsd.own.mk>
|
||||
|
||||
|
@ -29,7 +29,7 @@ CPPFLAGS+= -DNDEBUG
|
|||
CXXFLAGS+= -nostdlib -nostdinc++ -funwind-tables \
|
||||
-fno-exceptions -fno-rtti
|
||||
.if empty(CXXFLAGS:M-std=*)
|
||||
CXXFLAGS+= -std=c++11
|
||||
CXXFLAGS+= -std=c++20
|
||||
.endif
|
||||
|
||||
SRCS+=unwind.c \
|
||||
|
|
|
@ -10,12 +10,23 @@ if (CMAKE_SOURCE_DIR STREQUAL CMAKE_CURRENT_SOURCE_DIR OR COMPILER_RT_STANDALONE
|
|||
project(CompilerRT C CXX ASM)
|
||||
set(COMPILER_RT_STANDALONE_BUILD TRUE)
|
||||
set_property(GLOBAL PROPERTY USE_FOLDERS ON)
|
||||
if ("${CMAKE_VERSION}" VERSION_LESS "3.20.0")
|
||||
message(WARNING
|
||||
"Your CMake version is ${CMAKE_VERSION}. Starting with LLVM 17.0.0, the "
|
||||
"minimum version of CMake required to build LLVM will become 3.20.0, and "
|
||||
"using an older CMake will become an error. Please upgrade your CMake to "
|
||||
"at least 3.20.0 now to avoid issues in the future!")
|
||||
endif()
|
||||
endif()
|
||||
|
||||
set(LLVM_COMMON_CMAKE_UTILS "${CMAKE_CURRENT_SOURCE_DIR}/../cmake")
|
||||
|
||||
# Add path for custom compiler-rt modules.
|
||||
list(INSERT CMAKE_MODULE_PATH 0
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/cmake"
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/cmake/Modules"
|
||||
"${LLVM_COMMON_CMAKE_UTILS}"
|
||||
"${LLVM_COMMON_CMAKE_UTILS}/Modules"
|
||||
)
|
||||
|
||||
if(CMAKE_CONFIGURATION_TYPES)
|
||||
|
@ -24,11 +35,15 @@ else()
|
|||
set(CMAKE_CFG_RESOLVED_INTDIR "")
|
||||
endif()
|
||||
|
||||
include(SetPlatformToolchainTools)
|
||||
include(base-config-ix)
|
||||
include(CompilerRTUtils)
|
||||
include(CMakeDependentOption)
|
||||
|
||||
option(COMPILER_RT_BUILD_BUILTINS "Build builtins" ON)
|
||||
mark_as_advanced(COMPILER_RT_BUILD_BUILTINS)
|
||||
option(COMPILER_RT_DISABLE_AARCH64_FMV "Disable AArch64 Function Multi Versioning support" OFF)
|
||||
mark_as_advanced(COMPILER_RT_DISABLE_AARCH64_FMV)
|
||||
option(COMPILER_RT_BUILD_CRT "Build crtbegin.o/crtend.o" ON)
|
||||
mark_as_advanced(COMPILER_RT_BUILD_CRT)
|
||||
option(COMPILER_RT_CRT_USE_EH_FRAME_REGISTRY "Use eh_frame in crtbegin.o/crtend.o" ON)
|
||||
|
@ -47,25 +62,16 @@ option(COMPILER_RT_BUILD_XRAY_NO_PREINIT "Build xray with no preinit patching" O
|
|||
mark_as_advanced(COMPILER_RT_BUILD_XRAY_NO_PREINIT)
|
||||
option(COMPILER_RT_BUILD_ORC "Build ORC runtime" ON)
|
||||
mark_as_advanced(COMPILER_RT_BUILD_ORC)
|
||||
option(COMPILER_RT_BUILD_GWP_ASAN "Build GWP-ASan, and link it into SCUDO" ON)
|
||||
mark_as_advanced(COMPILER_RT_BUILD_GWP_ASAN)
|
||||
option(COMPILER_RT_ENABLE_CET "Build Compiler RT with CET enabled" OFF)
|
||||
|
||||
set(COMPILER_RT_ASAN_SHADOW_SCALE ""
|
||||
CACHE STRING "Override the shadow scale to be used in ASan runtime")
|
||||
|
||||
if (NOT COMPILER_RT_ASAN_SHADOW_SCALE STREQUAL "")
|
||||
# Check that the shadow scale value is valid.
|
||||
if (NOT (COMPILER_RT_ASAN_SHADOW_SCALE GREATER -1 AND
|
||||
COMPILER_RT_ASAN_SHADOW_SCALE LESS 8))
|
||||
message(FATAL_ERROR "
|
||||
Invalid ASan Shadow Scale '${COMPILER_RT_ASAN_SHADOW_SCALE}'.")
|
||||
endif()
|
||||
|
||||
set(COMPILER_RT_ASAN_SHADOW_SCALE_LLVM_FLAG
|
||||
-mllvm -asan-mapping-scale=${COMPILER_RT_ASAN_SHADOW_SCALE})
|
||||
set(COMPILER_RT_ASAN_SHADOW_SCALE_DEFINITION
|
||||
ASAN_SHADOW_SCALE=${COMPILER_RT_ASAN_SHADOW_SCALE})
|
||||
set(COMPILER_RT_ASAN_SHADOW_SCALE_FLAG
|
||||
-D${COMPILER_RT_ASAN_SHADOW_SCALE_DEFINITION})
|
||||
endif()
|
||||
option(COMPILER_RT_SCUDO_STANDALONE_SYSROOT_PATH "Set custom sysroot for building SCUDO standalone" OFF)
|
||||
mark_as_advanced(COMPILER_RT_SCUDO_STANDALONE_SYSROOT_PATH)
|
||||
option(COMPILER_RT_SCUDO_STANDALONE_BUILD_SHARED "Build SCUDO standalone for shared libraries" ON)
|
||||
mark_as_advanced(COMPILER_RT_SCUDO_STANDALONE_BUILD_SHARED)
|
||||
option(COMPILER_RT_BUILD_SCUDO_STANDALONE_WITH_LLVM_LIBC "Build SCUDO standalone with LLVM's libc headers" OFF)
|
||||
mark_as_advanced(COMPILER_RT_BUILD_SCUDO_STANDALONE_WITH_LLVM_LIBC)
|
||||
|
||||
if(FUCHSIA)
|
||||
set(COMPILER_RT_HWASAN_WITH_INTERCEPTORS_DEFAULT OFF)
|
||||
|
@ -78,7 +84,13 @@ set(COMPILER_RT_BAREMETAL_BUILD OFF CACHE BOOL
|
|||
"Build for a bare-metal target.")
|
||||
|
||||
if (COMPILER_RT_STANDALONE_BUILD)
|
||||
load_llvm_config()
|
||||
set(CMAKE_CXX_STANDARD 17 CACHE STRING "C++ standard to conform to")
|
||||
set(CMAKE_CXX_STANDARD_REQUIRED YES)
|
||||
set(CMAKE_CXX_EXTENSIONS NO)
|
||||
|
||||
if (NOT LLVM_RUNTIMES_BUILD)
|
||||
load_llvm_config()
|
||||
endif()
|
||||
if (TARGET intrinsics_gen)
|
||||
# Loading the llvm config causes this target to be imported so place it
|
||||
# under the appropriate folder in an IDE.
|
||||
|
@ -121,6 +133,20 @@ if ("${COMPILER_RT_DEFAULT_TARGET_TRIPLE}" MATCHES ".*hf$")
|
|||
CHECK_SYMBOL_EXISTS (__thumb__ "" COMPILER_RT_ARM_THUMB)
|
||||
endif()
|
||||
endif()
|
||||
if (${COMPILER_RT_DEFAULT_TARGET_ARCH} MATCHES "^mips")
|
||||
CHECK_SYMBOL_EXISTS (_MIPS_ARCH_MIPS32R6 "" COMPILER_RT_MIPS32R6)
|
||||
CHECK_SYMBOL_EXISTS (_MIPS_ARCH_MIPS64R6 "" COMPILER_RT_MIPS64R6)
|
||||
CHECK_SYMBOL_EXISTS (__mips64 "" COMPILER_RT_MIPS_64)
|
||||
CHECK_SYMBOL_EXISTS (__MIPSEL__ "" COMPILER_RT_MIPS_EL)
|
||||
if ("${COMPILER_RT_MIPS_64}")
|
||||
set(COMPILER_RT_DEFAULT_TARGET_ARCH "mips64")
|
||||
else()
|
||||
set(COMPILER_RT_DEFAULT_TARGET_ARCH "mips")
|
||||
endif()
|
||||
if ("${COMPILER_RT_MIPS_EL}")
|
||||
set(COMPILER_RT_DEFAULT_TARGET_ARCH "${COMPILER_RT_DEFAULT_TARGET_ARCH}el")
|
||||
endif()
|
||||
endif()
|
||||
if ("${COMPILER_RT_DEFAULT_TARGET_TRIPLE}" MATCHES ".*android.*")
|
||||
set(ANDROID 1)
|
||||
string(REGEX MATCH "-target(=| +)[^ ]+android[a-z]*([0-9]+)" ANDROID_API_LEVEL "${CMAKE_C_FLAGS}")
|
||||
|
@ -133,11 +159,11 @@ set(COMPILER_RT_BINARY_DIR ${CMAKE_CURRENT_BINARY_DIR})
|
|||
|
||||
pythonize_bool(LLVM_ENABLE_PER_TARGET_RUNTIME_DIR)
|
||||
|
||||
# We support running instrumented tests when we're not cross compiling
|
||||
# We support running instrumented tests when we're not cross-compiling
|
||||
# and target a UNIX-like system or Windows.
|
||||
# We can run tests on Android even when we are cross-compiling.
|
||||
if(("${CMAKE_HOST_SYSTEM}" STREQUAL "${CMAKE_SYSTEM}" AND (UNIX OR WIN32)) OR ANDROID
|
||||
OR COMPILER_RT_EMULATOR)
|
||||
if(("${CMAKE_HOST_SYSTEM_NAME}" STREQUAL "${CMAKE_SYSTEM_NAME}" AND (UNIX OR WIN32))
|
||||
OR ANDROID OR COMPILER_RT_EMULATOR)
|
||||
option(COMPILER_RT_CAN_EXECUTE_TESTS "Can we execute instrumented tests" ON)
|
||||
else()
|
||||
option(COMPILER_RT_CAN_EXECUTE_TESTS "Can we execute instrumented tests" OFF)
|
||||
|
@ -209,6 +235,7 @@ endmacro()
|
|||
|
||||
# This is either directly the C++ ABI library or the full C++ library
|
||||
# which pulls in the ABI transitively.
|
||||
# TODO: Mark this as internal flag, most users should use COMPILER_RT_CXX_LIBRARY.
|
||||
set(SANITIZER_CXX_ABI "default" CACHE STRING
|
||||
"Specify C++ ABI library to use.")
|
||||
set(CXXABIS none default libstdc++ libc++ libcxxabi)
|
||||
|
@ -216,12 +243,18 @@ set_property(CACHE SANITIZER_CXX_ABI PROPERTY STRINGS ;${CXXABIS})
|
|||
handle_default_cxx_lib(SANITIZER_CXX_ABI)
|
||||
|
||||
# This needs to be a full C++ library for linking gtest and unit tests.
|
||||
# TODO: Mark this as internal flag, most users should use COMPILER_RT_CXX_LIBRARY.
|
||||
set(SANITIZER_TEST_CXX "default" CACHE STRING
|
||||
"Specify C++ library to use for tests.")
|
||||
set(CXXLIBS none default libstdc++ libc++)
|
||||
set_property(CACHE SANITIZER_TEST_CXX PROPERTY STRINGS ;${CXXLIBS})
|
||||
handle_default_cxx_lib(SANITIZER_TEST_CXX)
|
||||
|
||||
option(COMPILER_RT_USE_LLVM_UNWINDER "Use the LLVM unwinder." OFF)
|
||||
cmake_dependent_option(COMPILER_RT_ENABLE_STATIC_UNWINDER
|
||||
"Statically link the LLVM unwinder." OFF
|
||||
"COMPILER_RT_USE_LLVM_UNWINDER" OFF)
|
||||
|
||||
set(DEFAULT_SANITIZER_USE_STATIC_LLVM_UNWINDER OFF)
|
||||
if (FUCHSIA)
|
||||
set(DEFAULT_SANITIZER_USE_STATIC_LLVM_UNWINDER ON)
|
||||
|
@ -231,6 +264,7 @@ endif()
|
|||
|
||||
option(SANITIZER_USE_STATIC_LLVM_UNWINDER
|
||||
"Use static LLVM unwinder." ${DEFAULT_SANITIZER_USE_STATIC_LLVM_UNWINDER})
|
||||
pythonize_bool(SANITIZER_USE_STATIC_LLVM_UNWINDER)
|
||||
|
||||
set(DEFAULT_SANITIZER_USE_STATIC_CXX_ABI OFF)
|
||||
if (DEFINED LIBCXXABI_ENABLE_SHARED AND NOT LIBCXXABI_ENABLE_SHARED)
|
||||
|
@ -239,6 +273,25 @@ endif()
|
|||
|
||||
option(SANITIZER_USE_STATIC_CXX_ABI
|
||||
"Use static libc++abi." ${DEFAULT_SANITIZER_USE_STATIC_CXX_ABI})
|
||||
pythonize_bool(SANITIZER_USE_STATIC_CXX_ABI)
|
||||
|
||||
set(DEFAULT_SANITIZER_USE_STATIC_TEST_CXX OFF)
|
||||
if (DEFINED LIBCXX_ENABLE_SHARED AND NOT LIBCXX_ENABLE_SHARED)
|
||||
set(DEFAULT_SANITIZER_USE_STATIC_TEST_CXX ON)
|
||||
endif()
|
||||
|
||||
option(SANITIZER_USE_STATIC_TEST_CXX
|
||||
"Use static libc++ for tests." ${DEFAULT_SANITIZER_USE_STATIC_TEST_CXX})
|
||||
pythonize_bool(SANITIZER_USE_STATIC_TEST_CXX)
|
||||
|
||||
set(COMPILER_RT_SUPPORTED_CXX_LIBRARIES none default libcxx)
|
||||
set(COMPILER_RT_CXX_LIBRARY "default" CACHE STRING "Specify C++ library to use. Supported values are ${COMPILER_RT_SUPPORTED_CXX_LIBRARIES}.")
|
||||
if (NOT "${COMPILER_RT_CXX_LIBRARY}" IN_LIST COMPILER_RT_SUPPORTED_CXX_LIBRARIES)
|
||||
message(FATAL_ERROR "Unsupported C++ library: '${COMPILER_RT_CXX_LIBRARY}'. Supported values are ${COMPILER_RT_SUPPORTED_CXX_LIBRARIES}.")
|
||||
endif()
|
||||
cmake_dependent_option(COMPILER_RT_STATIC_CXX_LIBRARY
|
||||
"Statically link the C++ library." OFF
|
||||
"COMPILER_RT_CXX_LIBRARY" OFF)
|
||||
|
||||
set(DEFAULT_COMPILER_RT_USE_BUILTINS_LIBRARY OFF)
|
||||
if (FUCHSIA)
|
||||
|
@ -254,6 +307,14 @@ include(config-ix)
|
|||
# Setup Compiler Flags
|
||||
#================================
|
||||
|
||||
# fcf-protection is a gcc/clang option for CET support on Linux platforms.
|
||||
# We need to handle MSVC CET option on Windows platforms.
|
||||
if (NOT MSVC)
|
||||
if (COMPILER_RT_ENABLE_CET AND NOT COMPILER_RT_HAS_FCF_PROTECTION_FLAG)
|
||||
message(FATAL_ERROR "Compiler used to build compiler-rt doesn't support CET!")
|
||||
endif()
|
||||
endif()
|
||||
|
||||
if(MSVC)
|
||||
# Override any existing /W flags with /W4. This is what LLVM does. Failing to
|
||||
# remove other /W[0-4] flags will result in a warning about overriding a
|
||||
|
@ -271,8 +332,6 @@ if(COMPILER_RT_ENABLE_WERROR)
|
|||
append_string_if(COMPILER_RT_HAS_WX_FLAG /WX CMAKE_C_FLAGS CMAKE_CXX_FLAGS)
|
||||
endif()
|
||||
|
||||
append_string_if(COMPILER_RT_HAS_STD_CXX14_FLAG -std=c++14 CMAKE_CXX_FLAGS)
|
||||
|
||||
# Emulate C99 and C++11's __func__ for MSVC prior to 2013 CTP.
|
||||
if(NOT COMPILER_RT_HAS_FUNC_SYMBOL)
|
||||
add_definitions(-D__func__=__FUNCTION__)
|
||||
|
@ -307,8 +366,11 @@ if(NOT COMPILER_RT_ENABLE_PGO)
|
|||
endif()
|
||||
if(LLVM_BUILD_INSTRUMENTED MATCHES IR AND COMPILER_RT_HAS_FNO_PROFILE_GENERATE_FLAG)
|
||||
list(APPEND SANITIZER_COMMON_CFLAGS "-fno-profile-generate")
|
||||
elseif(LLVM_BUILD_INSTRUMENTED AND COMPILER_RT_HAS_FNO_PROFILE_INSTR_GENERATE_FLAG)
|
||||
elseif((LLVM_BUILD_INSTRUMENTED OR LLVM_BUILD_INSTRUMENTED_COVERAGE) AND COMPILER_RT_HAS_FNO_PROFILE_INSTR_GENERATE_FLAG)
|
||||
list(APPEND SANITIZER_COMMON_CFLAGS "-fno-profile-instr-generate")
|
||||
if(LLVM_BUILD_INSTRUMENTED_COVERAGE AND COMPILER_RT_HAS_FNO_COVERAGE_MAPPING_FLAG)
|
||||
list(APPEND SANITIZER_COMMON_CFLAGS "-fno-coverage-mapping")
|
||||
endif()
|
||||
endif()
|
||||
endif()
|
||||
|
||||
|
@ -359,16 +421,12 @@ endif()
|
|||
|
||||
append_list_if(COMPILER_RT_DEBUG -DSANITIZER_DEBUG=1 SANITIZER_COMMON_CFLAGS)
|
||||
|
||||
if(CMAKE_CXX_COMPILER_ID MATCHES Clang)
|
||||
list(APPEND THREAD_SAFETY_FLAGS
|
||||
"-Werror=thread-safety"
|
||||
"-Werror=thread-safety-reference"
|
||||
"-Werror=thread-safety-beta"
|
||||
)
|
||||
list(APPEND SANITIZER_COMMON_CFLAGS ${THREAD_SAFETY_FLAGS})
|
||||
string(REPLACE ";" " " thread_safety_flags_space_sep "${THREAD_SAFETY_FLAGS}")
|
||||
string(APPEND COMPILER_RT_TEST_COMPILER_CFLAGS " ${thread_safety_flags_space_sep}")
|
||||
endif()
|
||||
append_list_if(COMPILER_RT_HAS_WTHREAD_SAFETY_FLAG -Wthread-safety THREAD_SAFETY_FLAGS)
|
||||
append_list_if(COMPILER_RT_HAS_WTHREAD_SAFETY_REFERENCE_FLAG -Wthread-safety-reference THREAD_SAFETY_FLAGS)
|
||||
append_list_if(COMPILER_RT_HAS_WTHREAD_SAFETY_BETA_FLAG -Wthread-safety-beta THREAD_SAFETY_FLAGS)
|
||||
list(APPEND SANITIZER_COMMON_CFLAGS ${THREAD_SAFETY_FLAGS})
|
||||
string(REPLACE ";" " " thread_safety_flags_space_sep "${THREAD_SAFETY_FLAGS}")
|
||||
string(APPEND COMPILER_RT_TEST_COMPILER_CFLAGS " ${thread_safety_flags_space_sep}")
|
||||
|
||||
# If we're using MSVC,
|
||||
# always respect the optimization flags set by CMAKE_BUILD_TYPE instead.
|
||||
|
@ -376,7 +434,7 @@ if (NOT MSVC)
|
|||
|
||||
# Build with optimization, unless we're in debug mode.
|
||||
if(COMPILER_RT_DEBUG)
|
||||
list(APPEND SANITIZER_COMMON_CFLAGS -O0)
|
||||
list(APPEND SANITIZER_COMMON_CFLAGS -O1)
|
||||
else()
|
||||
list(APPEND SANITIZER_COMMON_CFLAGS -O3)
|
||||
endif()
|
||||
|
@ -413,6 +471,13 @@ if(MSVC)
|
|||
string(REGEX REPLACE "(^| )/Z[i7I]($| )" " /Z7 "
|
||||
"${var_to_update}" "${${var_to_update}}")
|
||||
endforeach()
|
||||
elseif(APPLE)
|
||||
# On Apple platforms use full debug info (i.e. not `-gline-tables-only`)
|
||||
# for all build types so that the runtime can be debugged.
|
||||
if(NOT COMPILER_RT_HAS_G_FLAG)
|
||||
message(FATAL_ERROR "-g is not supported by host compiler")
|
||||
endif()
|
||||
list(APPEND SANITIZER_COMMON_CFLAGS -g)
|
||||
elseif(COMPILER_RT_HAS_GLINE_TABLES_ONLY_FLAG AND NOT COMPILER_RT_DEBUG)
|
||||
list(APPEND SANITIZER_COMMON_CFLAGS -gline-tables-only)
|
||||
elseif(COMPILER_RT_HAS_G_FLAG)
|
||||
|
@ -429,6 +494,7 @@ endif()
|
|||
append_list_if(COMPILER_RT_HAS_WGNU_FLAG -Wno-gnu SANITIZER_COMMON_CFLAGS)
|
||||
append_list_if(COMPILER_RT_HAS_WVARIADIC_MACROS_FLAG -Wno-variadic-macros SANITIZER_COMMON_CFLAGS)
|
||||
append_list_if(COMPILER_RT_HAS_WC99_EXTENSIONS_FLAG -Wno-c99-extensions SANITIZER_COMMON_CFLAGS)
|
||||
# format-pedantic warns about passing T* for %p, which is not useful.
|
||||
append_list_if(COMPILER_RT_HAS_WD4146_FLAG /wd4146 SANITIZER_COMMON_CFLAGS)
|
||||
append_list_if(COMPILER_RT_HAS_WD4291_FLAG /wd4291 SANITIZER_COMMON_CFLAGS)
|
||||
append_list_if(COMPILER_RT_HAS_WD4391_FLAG /wd4391 SANITIZER_COMMON_CFLAGS)
|
||||
|
@ -437,10 +503,33 @@ append_list_if(COMPILER_RT_HAS_WD4800_FLAG /wd4800 SANITIZER_COMMON_CFLAGS)
|
|||
|
||||
append_list_if(MINGW -fms-extensions SANITIZER_COMMON_CFLAGS)
|
||||
|
||||
# When lsan scans the stack for detecting reachable pointers, it's possible for
|
||||
# a leaked pointer, which was pushed to the stack on an earlier function call,
|
||||
# to still exist on the stack when doing a leak check if that part of the stack
|
||||
# was not overwritten. In particular, if there's any uninitialized data in the
|
||||
# lsan runtime, and the SP we start from is sufficiently deep into the runtime,
|
||||
# then a leaked pointer could be marked as reachable. Such instances could be
|
||||
# mitigated by clobbering any uninitialized data. Note that this won't cover
|
||||
# all possible uninitialized stack contents, such as those used for register
|
||||
# spill slots, unused portions for alignment, or even local variables not
|
||||
# yet in scope at a certain point in the function.
|
||||
#
|
||||
# Note that this type of issue was discovered with lsan, but can apply to other
|
||||
# sanitizers.
|
||||
append_list_if(COMPILER_RT_HAS_TRIVIAL_AUTO_INIT -ftrivial-auto-var-init=pattern SANITIZER_COMMON_CFLAGS)
|
||||
|
||||
# Set common link flags.
|
||||
append_list_if(COMPILER_RT_HAS_NODEFAULTLIBS_FLAG -nodefaultlibs SANITIZER_COMMON_LINK_FLAGS)
|
||||
# TODO: We should consider using the same model as libc++, that is use either
|
||||
# -nostdlib++ and --unwindlib=none if supported, or -nodefaultlibs otherwise.
|
||||
append_list_if(C_SUPPORTS_NODEFAULTLIBS_FLAG -nodefaultlibs SANITIZER_COMMON_LINK_FLAGS)
|
||||
append_list_if(COMPILER_RT_HAS_Z_TEXT -Wl,-z,text SANITIZER_COMMON_LINK_FLAGS)
|
||||
|
||||
# Only necessary for 32-bit SPARC. Solaris 11.2+ ld uses -z ignore/-z record
|
||||
# natively, but supports --as-needed/--no-as-needed for GNU ld compatibility.
|
||||
if("${COMPILER_RT_DEFAULT_TARGET_ARCH}" MATCHES "sparc")
|
||||
list(APPEND SANITIZER_COMMON_LINK_LIBS -Wl,--as-needed atomic -Wl,--no-as-needed)
|
||||
endif()
|
||||
|
||||
if (COMPILER_RT_USE_BUILTINS_LIBRARY)
|
||||
string(REPLACE "-Wl,-z,defs" "" CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS}")
|
||||
else()
|
||||
|
@ -485,38 +574,6 @@ string(REGEX REPLACE "-stdlib=[a-zA-Z+]*" "" CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS}
|
|||
list(APPEND COMPILER_RT_COMMON_CFLAGS ${stdlib_flag})
|
||||
list(APPEND COMPILER_RT_COMMON_LINK_FLAGS ${stdlib_flag})
|
||||
|
||||
macro(append_libcxx_libs var)
|
||||
if (${var}_INTREE)
|
||||
if (SANITIZER_USE_STATIC_LLVM_UNWINDER AND (TARGET unwind_static OR HAVE_LIBUNWIND))
|
||||
list(APPEND ${var}_LIBRARIES unwind_static)
|
||||
elseif (TARGET unwind_shared OR HAVE_LIBUNWIND)
|
||||
list(APPEND ${var}_LIBRARIES unwind_shared)
|
||||
endif()
|
||||
|
||||
if (SANITIZER_USE_STATIC_CXX_ABI AND (TARGET cxxabi_static OR HAVE_LIBCXXABI))
|
||||
list(APPEND ${var}_LIBRARIES cxxabi_static)
|
||||
elseif (TARGET cxxabi_shared OR HAVE_LIBCXXABI)
|
||||
list(APPEND ${var}_LIBRARIES cxxabi_shared)
|
||||
endif()
|
||||
else()
|
||||
append_list_if(COMPILER_RT_HAS_LIBCXX c++ ${var}_LIBRARIES)
|
||||
endif()
|
||||
endmacro()
|
||||
|
||||
if (SANITIZER_CXX_ABI_LIBNAME STREQUAL "libc++")
|
||||
append_libcxx_libs(SANITIZER_CXX_ABI)
|
||||
elseif (SANITIZER_CXX_ABI_LIBNAME STREQUAL "libcxxabi")
|
||||
list(APPEND SANITIZER_CXX_ABI_LIBRARIES "c++abi")
|
||||
elseif (SANITIZER_CXX_ABI_LIBNAME STREQUAL "libstdc++")
|
||||
append_list_if(COMPILER_RT_HAS_LIBSTDCXX stdc++ SANITIZER_CXX_ABI_LIBRARIES)
|
||||
endif()
|
||||
|
||||
if (SANITIZER_TEST_CXX_LIBNAME STREQUAL "libc++")
|
||||
append_libcxx_libs(SANITIZER_TEST_CXX)
|
||||
elseif (SANITIZER_TEST_CXX_LIBNAME STREQUAL "libstdc++")
|
||||
append_list_if(COMPILER_RT_HAS_LIBSTDCXX stdc++ SANITIZER_TEST_CXX_LIBRARIES)
|
||||
endif()
|
||||
|
||||
# TODO: There's a lot of duplication across lib/*/tests/CMakeLists.txt files,
|
||||
# move some of the common flags to COMPILER_RT_UNITTEST_CFLAGS.
|
||||
|
||||
|
@ -528,8 +585,89 @@ string(APPEND COMPILER_RT_TEST_COMPILER_CFLAGS " ${stdlib_flag}")
|
|||
string(REPLACE " " ";" COMPILER_RT_UNITTEST_CFLAGS "${COMPILER_RT_TEST_COMPILER_CFLAGS}")
|
||||
set(COMPILER_RT_UNITTEST_LINK_FLAGS ${COMPILER_RT_UNITTEST_CFLAGS})
|
||||
|
||||
if(COMPILER_RT_USE_LLVM_UNWINDER)
|
||||
# We're linking directly against the libunwind that we're building so don't
|
||||
# try to link in the toolchain's default libunwind which may be missing.
|
||||
append_list_if(CXX_SUPPORTS_UNWINDLIB_NONE_FLAG --unwindlib=none COMPILER_RT_COMMON_LINK_FLAGS)
|
||||
append_list_if(CXX_SUPPORTS_UNWINDLIB_NONE_FLAG --unwindlib=none COMPILER_RT_UNITTEST_LINK_FLAGS)
|
||||
if (COMPILER_RT_ENABLE_STATIC_UNWINDER)
|
||||
list(APPEND COMPILER_RT_UNWINDER_LINK_LIBS "$<TARGET_LINKER_FILE:unwind_static>")
|
||||
else()
|
||||
list(APPEND COMPILER_RT_UNWINDER_LINK_LIBS "$<TARGET_LINKER_FILE:$<IF:$<TARGET_EXISTS:unwind_shared>,unwind_shared,unwind_static>>")
|
||||
endif()
|
||||
endif()
|
||||
|
||||
if (COMPILER_RT_CXX_LIBRARY STREQUAL "libcxx")
|
||||
# We are using the in-tree libc++ so avoid including the default one.
|
||||
append_list_if(COMPILER_RT_HAS_NOSTDINCXX_FLAG -nostdinc++ COMPILER_RT_COMMON_CFLAGS)
|
||||
append_list_if(COMPILER_RT_HAS_NOSTDLIBXX_FLAG -nostdlib++ COMPILER_RT_COMMON_LINK_FLAGS)
|
||||
# Use the in-tree libc++ through explicit include and library paths.
|
||||
set(COMPILER_RT_CXX_CFLAGS "$<$<TARGET_EXISTS:cxx-headers>:$<IF:$<BOOL:${MSVC}>,/imsvc,-isystem>$<JOIN:$<TARGET_PROPERTY:cxx-headers,INTERFACE_INCLUDE_DIRECTORIES>,$<SEMICOLON>$<IF:$<BOOL:${MSVC}>,/imsvc,-isystem>>>")
|
||||
if (COMPILER_RT_STATIC_CXX_LIBRARY)
|
||||
set(COMPILER_RT_CXX_LINK_LIBS "$<TARGET_LINKER_FILE:cxx_static>")
|
||||
else()
|
||||
set(COMPILER_RT_CXX_LINK_LIBS "$<TARGET_LINKER_FILE:$<IF:$<TARGET_EXISTS:cxx_shared>,cxx_shared,cxx_static>>")
|
||||
endif()
|
||||
elseif (COMPILER_RT_CXX_LIBRARY STREQUAL "none")
|
||||
# We aren't using any C++ standard library so avoid including the default one.
|
||||
append_list_if(COMPILER_RT_HAS_NOSTDINCXX_FLAG -nostdinc++ COMPILER_RT_COMMON_CFLAGS)
|
||||
append_list_if(COMPILER_RT_HAS_NOSTDLIBXX_FLAG -nostdlib++ COMPILER_RT_COMMON_LINK_FLAGS)
|
||||
else()
|
||||
# Nothing to be done for `default`.
|
||||
endif()
|
||||
|
||||
if (SANITIZER_CXX_ABI_LIBNAME STREQUAL "libc++")
|
||||
if (SANITIZER_CXX_ABI_INTREE)
|
||||
# TODO: We don't need to add --unwindlib=none to SANITIZER_COMMON_LINK_FLAGS
|
||||
# because we added -nodefaultlibs there earlier, and adding would result in
|
||||
# a warning, but if we switch to -nostdlib++, we would need to add it here.
|
||||
# append_list_if(CXX_SUPPORTS_UNWINDLIB_NONE_FLAG --unwindlib=none SANITIZER_COMMON_LINK_FLAGS)
|
||||
if(SANITIZER_USE_STATIC_CXX_ABI)
|
||||
if(TARGET libcxx-abi-static)
|
||||
set(SANITIZER_CXX_ABI_LIBRARIES libcxx-abi-static)
|
||||
endif()
|
||||
else()
|
||||
if(TARGET libcxx-abi-shared)
|
||||
set(SANITIZER_CXX_ABI_LIBRARIES libcxx-abi-shared)
|
||||
elseif(TARGET libcxx-abi-static)
|
||||
set(SANITIZER_CXX_ABI_LIBRARIES libcxx-abi-static)
|
||||
endif()
|
||||
endif()
|
||||
else()
|
||||
append_list_if(COMPILER_RT_HAS_LIBCXX c++ SANITIZER_CXX_ABI_LIBRARIES)
|
||||
endif()
|
||||
elseif (SANITIZER_CXX_ABI_LIBNAME STREQUAL "libcxxabi")
|
||||
list(APPEND SANITIZER_CXX_ABI_LIBRARIES "c++abi")
|
||||
elseif (SANITIZER_CXX_ABI_LIBNAME STREQUAL "libstdc++")
|
||||
append_list_if(COMPILER_RT_HAS_LIBSTDCXX stdc++ SANITIZER_CXX_ABI_LIBRARIES)
|
||||
endif()
|
||||
|
||||
if (SANITIZER_TEST_CXX_LIBNAME STREQUAL "libc++")
|
||||
if (SANITIZER_TEST_CXX_INTREE)
|
||||
list(APPEND SANITIZER_TEST_CXX_CFLAGS "$<$<TARGET_EXISTS:cxx-headers>:$<IF:$<BOOL:${MSVC}>,/imsvc,-isystem>$<JOIN:$<TARGET_PROPERTY:cxx-headers,INTERFACE_INCLUDE_DIRECTORIES>,$<SEMICOLON>$<IF:$<BOOL:${MSVC}>,/imsvc,-isystem>>>")
|
||||
if (SANITIZER_USE_STATIC_TEST_CXX)
|
||||
list(APPEND SANITIZER_TEST_CXX_LIBRARIES "$<TARGET_LINKER_FILE:cxx_static>")
|
||||
else()
|
||||
list(APPEND SANITIZER_TEST_CXX_LIBRARIES "$<TARGET_LINKER_FILE:$<IF:$<TARGET_EXISTS:cxx_shared>,cxx_shared,cxx_static>>")
|
||||
endif()
|
||||
# We are using the in tree libc++ so avoid including the default one.
|
||||
append_list_if(COMPILER_RT_HAS_NOSTDINCXX_FLAG -nostdinc++ COMPILER_RT_UNITTEST_CFLAGS)
|
||||
append_list_if(COMPILER_RT_HAS_NOSTDLIBXX_FLAG -nostdlib++ COMPILER_RT_UNITTEST_LINK_FLAGS)
|
||||
else()
|
||||
append_list_if(COMPILER_RT_HAS_LIBCXX -lc++ SANITIZER_TEST_CXX_LIBRARIES)
|
||||
endif()
|
||||
elseif (SANITIZER_TEST_CXX_LIBNAME STREQUAL "libstdc++")
|
||||
append_list_if(COMPILER_RT_HAS_LIBSTDCXX -lstdc++ SANITIZER_TEST_CXX_LIBRARIES)
|
||||
endif()
|
||||
|
||||
# Unittests support.
|
||||
set(COMPILER_RT_GTEST_PATH ${LLVM_MAIN_SRC_DIR}/utils/unittest/googletest)
|
||||
# FIXME: When compiler-rt is build using -DLLVM_BUILD_EXTERNAL_COMPILER_RT=ON, then
|
||||
# The LLVM_THIRD_PARTY_DIR variable is not set.
|
||||
if (NOT LLVM_THIRD_PARTY_DIR)
|
||||
set(LLVM_THIRD_PARTY_DIR "${CMAKE_CURRENT_SOURCE_DIR}/../third-party")
|
||||
endif()
|
||||
|
||||
set(COMPILER_RT_GTEST_PATH ${LLVM_THIRD_PARTY_DIR}/unittest/googletest)
|
||||
set(COMPILER_RT_GTEST_SOURCE ${COMPILER_RT_GTEST_PATH}/src/gtest-all.cc)
|
||||
set(COMPILER_RT_GTEST_CFLAGS
|
||||
-DGTEST_NO_LLVM_SUPPORT=1
|
||||
|
@ -537,17 +675,9 @@ set(COMPILER_RT_GTEST_CFLAGS
|
|||
-I${COMPILER_RT_GTEST_PATH}/include
|
||||
-I${COMPILER_RT_GTEST_PATH}
|
||||
)
|
||||
if(CMAKE_SYSTEM_NAME MATCHES "FreeBSD")
|
||||
# FreeBSD has its pthread functions marked with thread safety annotations, but
|
||||
# googletest is not compatible with such annotations. Disable the thread
|
||||
# safety warnings-as-errors until googletest has been fixed.
|
||||
list(APPEND NO_THREAD_SAFETY_FLAGS ${THREAD_SAFETY_FLAGS})
|
||||
list(TRANSFORM NO_THREAD_SAFETY_FLAGS REPLACE "error=" "no-")
|
||||
list(APPEND COMPILER_RT_GTEST_CFLAGS ${NO_THREAD_SAFETY_FLAGS})
|
||||
endif()
|
||||
|
||||
# Mocking support.
|
||||
set(COMPILER_RT_GMOCK_PATH ${LLVM_MAIN_SRC_DIR}/utils/unittest/googlemock)
|
||||
set(COMPILER_RT_GMOCK_PATH ${LLVM_THIRD_PARTY_DIR}/unittest/googlemock)
|
||||
set(COMPILER_RT_GMOCK_SOURCE ${COMPILER_RT_GMOCK_PATH}/src/gmock-all.cc)
|
||||
set(COMPILER_RT_GMOCK_CFLAGS
|
||||
-DGTEST_NO_LLVM_SUPPORT=1
|
||||
|
@ -556,6 +686,9 @@ set(COMPILER_RT_GMOCK_CFLAGS
|
|||
-I${COMPILER_RT_GMOCK_PATH}
|
||||
)
|
||||
|
||||
if(COMPILER_RT_HAS_G_FLAG)
|
||||
list(APPEND COMPILER_RT_UNITTEST_CFLAGS -g)
|
||||
endif()
|
||||
append_list_if(COMPILER_RT_DEBUG -DSANITIZER_DEBUG=1 COMPILER_RT_UNITTEST_CFLAGS)
|
||||
append_list_if(COMPILER_RT_HAS_WCOVERED_SWITCH_DEFAULT_FLAG -Wno-covered-switch-default COMPILER_RT_UNITTEST_CFLAGS)
|
||||
append_list_if(COMPILER_RT_HAS_WSUGGEST_OVERRIDE_FLAG -Wno-suggest-override COMPILER_RT_UNITTEST_CFLAGS)
|
||||
|
@ -579,15 +712,6 @@ if (CMAKE_LINKER MATCHES "link.exe$")
|
|||
set(CMAKE_STATIC_LINKER_FLAGS "${CMAKE_STATIC_LINKER_FLAGS} /IGNORE:4221")
|
||||
endif()
|
||||
|
||||
if(${CMAKE_SYSTEM_NAME} MATCHES "AIX")
|
||||
set(CMAKE_C_ARCHIVE_CREATE "<CMAKE_AR> -X32_64 qc <TARGET> <LINK_FLAGS> <OBJECTS>")
|
||||
set(CMAKE_CXX_ARCHIVE_CREATE "<CMAKE_AR> -X32_64 qc <TARGET> <LINK_FLAGS> <OBJECTS>")
|
||||
set(CMAKE_C_ARCHIVE_APPEND "<CMAKE_AR> -X32_64 q <TARGET> <LINK_FLAGS> <OBJECTS>")
|
||||
set(CMAKE_CXX_ARCHIVE_APPEND "<CMAKE_AR> -X32_64 q <TARGET> <LINK_FLAGS> <OBJECTS>")
|
||||
set(CMAKE_C_ARCHIVE_FINISH "<CMAKE_RANLIB> -X32_64 <TARGET>")
|
||||
set(CMAKE_CXX_ARCHIVE_FINISH "<CMAKE_RANLIB> -X32_64 <TARGET>")
|
||||
endif()
|
||||
|
||||
add_subdirectory(include)
|
||||
|
||||
option(COMPILER_RT_USE_LIBCXX
|
||||
|
@ -634,9 +758,6 @@ if(ANDROID)
|
|||
set(COMPILER_RT_TEST_USE_LLD TRUE)
|
||||
append_list_if(COMPILER_RT_HAS_FUSE_LD_LLD_FLAG -fuse-ld=lld SANITIZER_COMMON_LINK_FLAGS)
|
||||
append_list_if(COMPILER_RT_HAS_LLD -fuse-ld=lld COMPILER_RT_UNITTEST_LINK_FLAGS)
|
||||
if(COMPILER_RT_HAS_FUSE_LD_LLD_FLAG)
|
||||
set(COMPILER_RT_HAS_GNU_VERSION_SCRIPT_COMPAT FALSE)
|
||||
endif()
|
||||
endif()
|
||||
pythonize_bool(COMPILER_RT_HAS_LLD)
|
||||
pythonize_bool(COMPILER_RT_TEST_USE_LLD)
|
||||
|
|
|
@ -8,33 +8,41 @@ beautification by scripts. The fields are: name (N), email (E), web-address
|
|||
(W), PGP key ID and fingerprint (P), description (D), and snail-mail address
|
||||
(S).
|
||||
|
||||
N: Saleem Abdulrasool
|
||||
E: compnerd@compnerd.org
|
||||
D: builtins library
|
||||
|
||||
N: Vitaly Buka
|
||||
E: vitalybuka@google.com
|
||||
D: Sanitizers
|
||||
|
||||
N: Peter Collingbourne
|
||||
E: peter@pcc.me.uk
|
||||
D: DataFlowSanitizer
|
||||
D: CFI, SafeStack
|
||||
|
||||
N: Daniel Dunbar
|
||||
E: daniel@zuster.org
|
||||
D: Makefile build
|
||||
N: Lang Hames
|
||||
E: lhames@gmail.com
|
||||
D: ORC
|
||||
|
||||
N: Timur Iskhodzhanov
|
||||
E: timurrrr@google.com
|
||||
D: AddressSanitizer for Windows
|
||||
N: Petr Hosek
|
||||
E: phosek@google.com
|
||||
D: CRT, CMake build
|
||||
|
||||
N: Howard Hinnant
|
||||
E: howard.hinnant@gmail.com
|
||||
D: builtins library
|
||||
N: Teresa Johnson
|
||||
E: tejohnson@google.com
|
||||
D: MemProf
|
||||
|
||||
N: Mitch Phillips
|
||||
E: mitchp@google.com
|
||||
D: GWP ASAN
|
||||
|
||||
N: Alexander Potapenko
|
||||
E: glider@google.com
|
||||
D: MacOS/iOS port of sanitizers
|
||||
|
||||
N: Alexey Samsonov
|
||||
E: samsonov@google.com
|
||||
D: CMake build, test suite
|
||||
D: Sanitizers
|
||||
|
||||
N: Kostya Serebryany
|
||||
E: kcc@google.com
|
||||
D: AddressSanitizer, sanitizer_common, porting sanitizers to another platforms, LeakSanitizer
|
||||
D: AddressSanitizer, sanitizer_common, LeakSanitizer, LibFuzzer
|
||||
|
||||
N: Richard Smith
|
||||
E: richard-llvm@metafoo.co.uk
|
||||
|
|
|
@ -2,6 +2,12 @@ include(ExternalProject)
|
|||
include(CompilerRTUtils)
|
||||
include(HandleCompilerRT)
|
||||
|
||||
# CMP0114: ExternalProject step targets fully adopt their steps.
|
||||
# New in CMake 3.19: https://cmake.org/cmake/help/latest/policy/CMP0114.html
|
||||
if(POLICY CMP0114)
|
||||
cmake_policy(SET CMP0114 OLD)
|
||||
endif()
|
||||
|
||||
function(set_target_output_directories target output_dir)
|
||||
# For RUNTIME_OUTPUT_DIRECTORY variable, Multi-configuration generators
|
||||
# append a per-configuration subdirectory to the specified directory.
|
||||
|
@ -77,6 +83,16 @@ function(add_compiler_rt_object_libraries name)
|
|||
list(REMOVE_ITEM target_flags "-msse3")
|
||||
endif()
|
||||
|
||||
# Build the macOS sanitizers with Mac Catalyst support.
|
||||
if (APPLE AND
|
||||
"${COMPILER_RT_ENABLE_MACCATALYST}" AND
|
||||
"${libname}" MATCHES ".*\.osx.*")
|
||||
foreach(arch ${LIB_ARCHS_${libname}})
|
||||
list(APPEND target_flags
|
||||
"SHELL:-target ${arch}-apple-macos${DARWIN_osx_MIN_VER} -darwin-target-variant ${arch}-apple-ios13.1-macabi")
|
||||
endforeach()
|
||||
endif()
|
||||
|
||||
set_target_compile_flags(${libname}
|
||||
${extra_cflags_${libname}} ${target_flags})
|
||||
set_property(TARGET ${libname} APPEND PROPERTY
|
||||
|
@ -128,13 +144,16 @@ macro(set_output_name output name arch)
|
|||
if(COMPILER_RT_DEFAULT_TARGET_ONLY)
|
||||
set(triple "${COMPILER_RT_DEFAULT_TARGET_TRIPLE}")
|
||||
else()
|
||||
set(triple "${TARGET_TRIPLE}")
|
||||
set(triple "${LLVM_TARGET_TRIPLE}")
|
||||
endif()
|
||||
# When using arch-suffixed runtime library names, clang only looks for
|
||||
# libraries named "arm" or "armhf", see getArchNameForCompilerRTLib in
|
||||
# clang. Therefore, try to inspect both the arch name and the triple
|
||||
# if it seems like we're building an armhf target.
|
||||
if ("${arch}" MATCHES "hf$" OR "${triple}" MATCHES "hf$")
|
||||
# Except for baremetal, when using arch-suffixed runtime library names,
|
||||
# clang only looks for libraries named "arm" or "armhf", see
|
||||
# getArchNameForCompilerRTLib in clang. Therefore, try to inspect both
|
||||
# the arch name and the triple if it seems like we're building an armhf
|
||||
# target.
|
||||
if (COMPILER_RT_BAREMETAL_BUILD)
|
||||
set(${output} "${name}-${arch}${COMPILER_RT_OS_SUFFIX}")
|
||||
elseif ("${arch}" MATCHES "hf$" OR "${triple}" MATCHES "hf$")
|
||||
set(${output} "${name}-armhf${COMPILER_RT_OS_SUFFIX}")
|
||||
else()
|
||||
set(${output} "${name}-arm${COMPILER_RT_OS_SUFFIX}")
|
||||
|
@ -188,8 +207,11 @@ function(add_compiler_rt_runtime name type)
|
|||
endif()
|
||||
if(LLVM_BUILD_INSTRUMENTED MATCHES IR AND COMPILER_RT_HAS_FNO_PROFILE_GENERATE_FLAG)
|
||||
list(APPEND NO_PGO_FLAGS "-fno-profile-generate")
|
||||
elseif(LLVM_BUILD_INSTRUMENTED AND COMPILER_RT_HAS_FNO_PROFILE_INSTR_GENERATE_FLAG)
|
||||
elseif((LLVM_BUILD_INSTRUMENTED OR LLVM_BUILD_INSTRUMENTED_COVERAGE) AND COMPILER_RT_HAS_FNO_PROFILE_INSTR_GENERATE_FLAG)
|
||||
list(APPEND NO_PGO_FLAGS "-fno-profile-instr-generate")
|
||||
if(LLVM_BUILD_INSTRUMENTED_COVERAGE AND COMPILER_RT_HAS_FNO_COVERAGE_MAPPING_FLAG)
|
||||
list(APPEND NO_PGO_FLAGS "-fno-coverage-mapping")
|
||||
endif()
|
||||
endif()
|
||||
endif()
|
||||
|
||||
|
@ -228,6 +250,17 @@ function(add_compiler_rt_runtime name type)
|
|||
get_compiler_rt_output_dir(${COMPILER_RT_DEFAULT_TARGET_ARCH} output_dir_${libname})
|
||||
get_compiler_rt_install_dir(${COMPILER_RT_DEFAULT_TARGET_ARCH} install_dir_${libname})
|
||||
endif()
|
||||
|
||||
# Build the macOS sanitizers with Mac Catalyst support.
|
||||
if ("${COMPILER_RT_ENABLE_MACCATALYST}" AND
|
||||
"${os}" MATCHES "^(osx)$")
|
||||
foreach(arch ${LIB_ARCHS_${libname}})
|
||||
list(APPEND extra_cflags_${libname}
|
||||
"SHELL:-target ${arch}-apple-macos${DARWIN_osx_MIN_VER} -darwin-target-variant ${arch}-apple-ios13.1-macabi")
|
||||
list(APPEND extra_link_flags_${libname}
|
||||
"SHELL:-target ${arch}-apple-macos${DARWIN_osx_MIN_VER} -darwin-target-variant ${arch}-apple-ios13.1-macabi")
|
||||
endforeach()
|
||||
endif()
|
||||
endforeach()
|
||||
else()
|
||||
foreach(arch ${LIB_ARCHS})
|
||||
|
@ -254,7 +287,7 @@ function(add_compiler_rt_runtime name type)
|
|||
if(COMPILER_RT_USE_BUILTINS_LIBRARY AND NOT type STREQUAL "OBJECT" AND
|
||||
NOT name STREQUAL "clang_rt.builtins")
|
||||
get_compiler_rt_target(${arch} target)
|
||||
find_compiler_rt_library(builtins ${target} builtins_${libname})
|
||||
find_compiler_rt_library(builtins builtins_${libname} TARGET ${target})
|
||||
if(builtins_${libname} STREQUAL "NOTFOUND")
|
||||
message(FATAL_ERROR "Cannot find builtins library for the target architecture")
|
||||
endif()
|
||||
|
@ -359,20 +392,40 @@ function(add_compiler_rt_runtime name type)
|
|||
target_link_libraries(${libname} PRIVATE ${builtins_${libname}})
|
||||
endif()
|
||||
if(${type} STREQUAL "SHARED")
|
||||
if(COMMAND llvm_setup_rpath)
|
||||
llvm_setup_rpath(${libname})
|
||||
if(APPLE OR WIN32)
|
||||
set_property(TARGET ${libname} PROPERTY BUILD_WITH_INSTALL_RPATH ON)
|
||||
endif()
|
||||
if(WIN32 AND NOT CYGWIN AND NOT MINGW)
|
||||
set_target_properties(${libname} PROPERTIES IMPORT_PREFIX "")
|
||||
set_target_properties(${libname} PROPERTIES IMPORT_SUFFIX ".lib")
|
||||
endif()
|
||||
if(APPLE)
|
||||
# Ad-hoc sign the dylibs
|
||||
add_custom_command(TARGET ${libname}
|
||||
POST_BUILD
|
||||
COMMAND codesign --sign - $<TARGET_FILE:${libname}>
|
||||
WORKING_DIRECTORY ${COMPILER_RT_OUTPUT_LIBRARY_DIR}
|
||||
if (APPLE AND NOT CMAKE_LINKER MATCHES ".*lld.*")
|
||||
# Ad-hoc sign the dylibs when using Xcode versions older than 12.
|
||||
# Xcode 12 shipped with ld64-609.
|
||||
# FIXME: Remove whole conditional block once everything uses Xcode 12+.
|
||||
set(LD_V_OUTPUT)
|
||||
execute_process(
|
||||
COMMAND sh -c "${CMAKE_LINKER} -v 2>&1 | head -1"
|
||||
RESULT_VARIABLE HAD_ERROR
|
||||
OUTPUT_VARIABLE LD_V_OUTPUT
|
||||
)
|
||||
if (HAD_ERROR)
|
||||
message(FATAL_ERROR "${CMAKE_LINKER} failed with status ${HAD_ERROR}")
|
||||
endif()
|
||||
set(NEED_EXPLICIT_ADHOC_CODESIGN 1)
|
||||
if ("${LD_V_OUTPUT}" MATCHES ".*ld64-([0-9.]+).*")
|
||||
string(REGEX REPLACE ".*ld64-([0-9.]+).*" "\\1" HOST_LINK_VERSION ${LD_V_OUTPUT})
|
||||
if (HOST_LINK_VERSION VERSION_GREATER_EQUAL 609)
|
||||
set(NEED_EXPLICIT_ADHOC_CODESIGN 0)
|
||||
endif()
|
||||
endif()
|
||||
if (NEED_EXPLICIT_ADHOC_CODESIGN)
|
||||
add_custom_command(TARGET ${libname}
|
||||
POST_BUILD
|
||||
COMMAND codesign --sign - $<TARGET_FILE:${libname}>
|
||||
WORKING_DIRECTORY ${COMPILER_RT_OUTPUT_LIBRARY_DIR}
|
||||
)
|
||||
endif()
|
||||
endif()
|
||||
endif()
|
||||
|
||||
|
@ -490,7 +543,7 @@ function(add_compiler_rt_test test_suite test_name arch)
|
|||
endif()
|
||||
add_custom_command(
|
||||
OUTPUT "${output_bin}"
|
||||
COMMAND ${COMPILER_RT_TEST_COMPILER} ${TEST_OBJECTS} -o "${output_bin}"
|
||||
COMMAND ${COMPILER_RT_TEST_CXX_COMPILER} ${TEST_OBJECTS} -o "${output_bin}"
|
||||
${TEST_LINK_FLAGS}
|
||||
DEPENDS ${TEST_DEPS}
|
||||
)
|
||||
|
@ -559,13 +612,9 @@ macro(add_custom_libcxx name prefix)
|
|||
-DCMAKE_CXX_COMPILER=${CMAKE_CXX_COMPILER})
|
||||
endif()
|
||||
|
||||
set(STAMP_DIR ${prefix}-stamps/)
|
||||
set(BINARY_DIR ${prefix}-bins/)
|
||||
|
||||
add_custom_target(${name}-clear
|
||||
COMMAND ${CMAKE_COMMAND} -E remove_directory ${BINARY_DIR}
|
||||
COMMAND ${CMAKE_COMMAND} -E remove_directory ${STAMP_DIR}
|
||||
COMMENT "Clobbering ${name} build and stamp directories"
|
||||
COMMAND ${CMAKE_COMMAND} -E remove_directory ${prefix}
|
||||
COMMENT "Clobbering ${name} build directories"
|
||||
USES_TERMINAL
|
||||
)
|
||||
set_target_properties(${name}-clear PROPERTIES FOLDER "Compiler-RT Misc")
|
||||
|
@ -573,10 +622,9 @@ macro(add_custom_libcxx name prefix)
|
|||
add_custom_command(
|
||||
OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/${name}-clobber-stamp
|
||||
DEPENDS ${LIBCXX_DEPS} ${toolchain_deps}
|
||||
COMMAND ${CMAKE_COMMAND} -E touch ${BINARY_DIR}/CMakeCache.txt
|
||||
COMMAND ${CMAKE_COMMAND} -E touch ${STAMP_DIR}/${name}-mkdir
|
||||
COMMAND ${CMAKE_COMMAND} -E touch ${prefix}/CMakeCache.txt
|
||||
COMMAND ${CMAKE_COMMAND} -E touch ${CMAKE_CURRENT_BINARY_DIR}/${name}-clobber-stamp
|
||||
COMMENT "Clobbering bootstrap build and stamp directories"
|
||||
COMMENT "Clobbering bootstrap build directories"
|
||||
)
|
||||
|
||||
add_custom_target(${name}-clobber
|
||||
|
@ -598,8 +646,14 @@ macro(add_custom_libcxx name prefix)
|
|||
CMAKE_OBJCOPY
|
||||
CMAKE_OBJDUMP
|
||||
CMAKE_STRIP
|
||||
CMAKE_READELF
|
||||
CMAKE_SYSROOT
|
||||
LIBCXX_HAS_MUSL_LIBC
|
||||
LIBCXX_HAS_GCC_S_LIB
|
||||
LIBCXX_HAS_PTHREAD_LIB
|
||||
LIBCXX_HAS_RT_LIB
|
||||
LIBCXX_USE_COMPILER_RT
|
||||
LIBCXXABI_HAS_PTHREAD_LIB
|
||||
PYTHON_EXECUTABLE
|
||||
Python3_EXECUTABLE
|
||||
Python2_EXECUTABLE
|
||||
|
@ -622,10 +676,9 @@ macro(add_custom_libcxx name prefix)
|
|||
|
||||
ExternalProject_Add(${name}
|
||||
DEPENDS ${name}-clobber ${LIBCXX_DEPS}
|
||||
PREFIX ${prefix}
|
||||
SOURCE_DIR ${COMPILER_RT_SOURCE_DIR}/cmake/Modules/CustomLibcxx
|
||||
STAMP_DIR ${STAMP_DIR}
|
||||
BINARY_DIR ${BINARY_DIR}
|
||||
PREFIX ${CMAKE_CURRENT_BINARY_DIR}/${name}
|
||||
SOURCE_DIR ${LLVM_MAIN_SRC_DIR}/../runtimes
|
||||
BINARY_DIR ${prefix}
|
||||
CMAKE_ARGS ${CMAKE_PASSTHROUGH_VARIABLES}
|
||||
${compiler_args}
|
||||
-DCMAKE_C_FLAGS=${LIBCXX_C_FLAGS}
|
||||
|
@ -633,10 +686,16 @@ macro(add_custom_libcxx name prefix)
|
|||
-DCMAKE_BUILD_TYPE=Release
|
||||
-DCMAKE_TRY_COMPILE_TARGET_TYPE=STATIC_LIBRARY
|
||||
-DLLVM_PATH=${LLVM_MAIN_SRC_DIR}
|
||||
-DLLVM_BINARY_DIR=${prefix}
|
||||
-DLLVM_LIBRARY_OUTPUT_INTDIR=${prefix}/lib
|
||||
-DCOMPILER_RT_LIBCXX_PATH=${COMPILER_RT_LIBCXX_PATH}
|
||||
-DCOMPILER_RT_LIBCXXABI_PATH=${COMPILER_RT_LIBCXXABI_PATH}
|
||||
-DLLVM_ENABLE_RUNTIMES=libcxx|libcxxabi
|
||||
-DLIBCXXABI_ENABLE_SHARED=OFF
|
||||
-DLIBCXXABI_HERMETIC_STATIC_LIBRARY=ON
|
||||
-DLIBCXXABI_INCLUDE_TESTS=OFF
|
||||
-DLIBCXX_CXX_ABI=libcxxabi
|
||||
-DLIBCXX_ENABLE_SHARED=OFF
|
||||
-DLIBCXX_HERMETIC_STATIC_LIBRARY=ON
|
||||
-DLIBCXX_INCLUDE_BENCHMARKS=OFF
|
||||
-DLIBCXX_INCLUDE_TESTS=OFF
|
||||
-DLIBCXX_ENABLE_STATIC_ABI_LIBRARY=ON
|
||||
${LIBCXX_CMAKE_ARGS}
|
||||
INSTALL_COMMAND ""
|
||||
STEP_TARGETS configure build
|
||||
|
@ -644,14 +703,15 @@ macro(add_custom_libcxx name prefix)
|
|||
USES_TERMINAL_CONFIGURE 1
|
||||
USES_TERMINAL_BUILD 1
|
||||
USES_TERMINAL_INSTALL 1
|
||||
LIST_SEPARATOR |
|
||||
EXCLUDE_FROM_ALL TRUE
|
||||
BUILD_BYPRODUCTS "${prefix}/lib/libc++.a" "${prefix}/lib/libc++abi.a"
|
||||
)
|
||||
|
||||
if (CMAKE_GENERATOR MATCHES "Make")
|
||||
set(run_clean "$(MAKE)" "-C" "${BINARY_DIR}" "clean")
|
||||
set(run_clean "$(MAKE)" "-C" "${prefix}" "clean")
|
||||
else()
|
||||
set(run_clean ${CMAKE_COMMAND} --build ${BINARY_DIR} --target clean
|
||||
set(run_clean ${CMAKE_COMMAND} --build ${prefix} --target clean
|
||||
--config "$<CONFIG>")
|
||||
endif()
|
||||
|
||||
|
@ -660,7 +720,7 @@ macro(add_custom_libcxx name prefix)
|
|||
COMMENT "Cleaning ${name}..."
|
||||
DEPENDEES configure
|
||||
${force_deps}
|
||||
WORKING_DIRECTORY ${BINARY_DIR}
|
||||
WORKING_DIRECTORY ${prefix}
|
||||
EXCLUDE_FROM_MAIN 1
|
||||
USES_TERMINAL 1
|
||||
)
|
||||
|
|
|
@ -0,0 +1,88 @@
|
|||
set(ARM64 aarch64)
|
||||
set(ARM32 arm armhf)
|
||||
set(HEXAGON hexagon)
|
||||
set(X86 i386)
|
||||
set(X86_64 x86_64)
|
||||
set(LOONGARCH64 loongarch64)
|
||||
set(MIPS32 mips mipsel)
|
||||
set(MIPS64 mips64 mips64el)
|
||||
set(PPC32 powerpc powerpcspe)
|
||||
set(PPC64 powerpc64 powerpc64le)
|
||||
set(RISCV32 riscv32)
|
||||
set(RISCV64 riscv64)
|
||||
set(S390X s390x)
|
||||
set(SPARC sparc)
|
||||
set(SPARCV9 sparcv9)
|
||||
set(WASM32 wasm32)
|
||||
set(WASM64 wasm64)
|
||||
set(VE ve)
|
||||
|
||||
if(APPLE)
|
||||
set(ARM64 arm64)
|
||||
set(ARM32 armv7 armv7s armv7k)
|
||||
set(X86_64 x86_64 x86_64h)
|
||||
endif()
|
||||
|
||||
set(ALL_SANITIZER_COMMON_SUPPORTED_ARCH ${X86} ${X86_64} ${PPC64} ${RISCV64}
|
||||
${ARM32} ${ARM64} ${MIPS32} ${MIPS64} ${S390X} ${SPARC} ${SPARCV9}
|
||||
${HEXAGON} ${LOONGARCH64})
|
||||
set(ALL_ASAN_SUPPORTED_ARCH ${X86} ${X86_64} ${ARM32} ${ARM64} ${RISCV64}
|
||||
${MIPS32} ${MIPS64} ${PPC64} ${S390X} ${SPARC} ${SPARCV9} ${HEXAGON}
|
||||
${LOONGARCH64})
|
||||
set(ALL_DFSAN_SUPPORTED_ARCH ${X86_64} ${MIPS64} ${ARM64})
|
||||
|
||||
if(ANDROID)
|
||||
set(OS_NAME "Android")
|
||||
else()
|
||||
set(OS_NAME "${CMAKE_SYSTEM_NAME}")
|
||||
endif()
|
||||
|
||||
if(OS_NAME MATCHES "Linux")
|
||||
set(ALL_FUZZER_SUPPORTED_ARCH ${X86} ${X86_64} ${ARM32} ${ARM64} ${S390X})
|
||||
elseif (OS_NAME MATCHES "Windows")
|
||||
set(ALL_FUZZER_SUPPORTED_ARCH ${X86} ${X86_64})
|
||||
elseif(OS_NAME MATCHES "Android")
|
||||
set(ALL_FUZZER_SUPPORTED_ARCH ${X86} ${X86_64} ${ARM32} ${ARM64})
|
||||
else()
|
||||
set(ALL_FUZZER_SUPPORTED_ARCH ${X86_64} ${ARM64})
|
||||
endif()
|
||||
|
||||
set(ALL_GWP_ASAN_SUPPORTED_ARCH ${X86} ${X86_64} ${ARM32} ${ARM64})
|
||||
if(APPLE)
|
||||
set(ALL_LSAN_SUPPORTED_ARCH ${X86} ${X86_64} ${MIPS64} ${ARM64})
|
||||
else()
|
||||
set(ALL_LSAN_SUPPORTED_ARCH ${X86} ${X86_64} ${MIPS64} ${ARM64} ${ARM32}
|
||||
${PPC64} ${S390X} ${RISCV64} ${HEXAGON} ${LOONGARCH64})
|
||||
endif()
|
||||
set(ALL_MSAN_SUPPORTED_ARCH ${X86_64} ${MIPS64} ${ARM64} ${PPC64} ${S390X})
|
||||
set(ALL_HWASAN_SUPPORTED_ARCH ${X86_64} ${ARM64} ${RISCV64})
|
||||
set(ALL_MEMPROF_SUPPORTED_ARCH ${X86_64})
|
||||
set(ALL_PROFILE_SUPPORTED_ARCH ${X86} ${X86_64} ${ARM32} ${ARM64} ${PPC32} ${PPC64}
|
||||
${MIPS32} ${MIPS64} ${S390X} ${SPARC} ${SPARCV9} ${HEXAGON}
|
||||
${RISCV32} ${RISCV64})
|
||||
set(ALL_TSAN_SUPPORTED_ARCH ${X86_64} ${MIPS64} ${ARM64} ${PPC64} ${S390X}
|
||||
${LOONGARCH64})
|
||||
set(ALL_UBSAN_SUPPORTED_ARCH ${X86} ${X86_64} ${ARM32} ${ARM64} ${RISCV64}
|
||||
${MIPS32} ${MIPS64} ${PPC64} ${S390X} ${SPARC} ${SPARCV9} ${HEXAGON}
|
||||
${LOONGARCH64})
|
||||
set(ALL_SAFESTACK_SUPPORTED_ARCH ${X86} ${X86_64} ${ARM64} ${MIPS32} ${MIPS64}
|
||||
${HEXAGON} ${LOONGARCH64})
|
||||
set(ALL_CFI_SUPPORTED_ARCH ${X86} ${X86_64} ${ARM32} ${ARM64} ${MIPS64}
|
||||
${HEXAGON})
|
||||
set(ALL_SCUDO_STANDALONE_SUPPORTED_ARCH ${X86} ${X86_64} ${ARM32} ${ARM64}
|
||||
${MIPS32} ${MIPS64} ${PPC64} ${HEXAGON} ${LOONGARCH64})
|
||||
if(APPLE)
|
||||
set(ALL_XRAY_SUPPORTED_ARCH ${X86_64})
|
||||
else()
|
||||
set(ALL_XRAY_SUPPORTED_ARCH ${X86_64} ${ARM32} ${ARM64} ${MIPS32} ${MIPS64}
|
||||
powerpc64le ${HEXAGON})
|
||||
endif()
|
||||
set(ALL_SHADOWCALLSTACK_SUPPORTED_ARCH ${ARM64})
|
||||
|
||||
if (UNIX)
|
||||
set(ALL_ORC_SUPPORTED_ARCH ${X86_64} ${ARM64} ${ARM32})
|
||||
endif()
|
||||
|
||||
if (WIN32)
|
||||
set(ALL_ORC_SUPPORTED_ARCH ${X86_64})
|
||||
endif()
|
|
@ -46,7 +46,7 @@ function(try_compile_only output)
|
|||
|
||||
set(TRY_COMPILE_FLAGS "${ARG_FLAGS}")
|
||||
if(CMAKE_C_COMPILER_ID MATCHES Clang AND CMAKE_C_COMPILER_TARGET)
|
||||
list(APPEND TRY_COMPILE_FLAGS "-target ${CMAKE_C_COMPILER_TARGET}")
|
||||
list(APPEND TRY_COMPILE_FLAGS "--target=${CMAKE_C_COMPILER_TARGET}")
|
||||
endif()
|
||||
|
||||
string(REPLACE ";" " " extra_flags "${TRY_COMPILE_FLAGS}")
|
||||
|
@ -74,7 +74,7 @@ function(try_compile_only output)
|
|||
|
||||
# Strip quotes from the compile command, as the compiler is not expecting
|
||||
# quoted arguments (see discussion on D62063 for when this can come up). If
|
||||
# the quotes were there for arugments with spaces in them, the quotes were
|
||||
# the quotes were there for arguments with spaces in them, the quotes were
|
||||
# not going to help since the string gets split on spaces below.
|
||||
string(REPLACE "\"" "" test_compile_command "${test_compile_command}")
|
||||
|
||||
|
|
91
gnu/llvm/compiler-rt/cmake/Modules/CheckSectionExists.cmake
Normal file
91
gnu/llvm/compiler-rt/cmake/Modules/CheckSectionExists.cmake
Normal file
|
@ -0,0 +1,91 @@
|
|||
function(check_section_exists section output)
|
||||
cmake_parse_arguments(ARG "" "" "SOURCE;FLAGS" ${ARGN})
|
||||
if(NOT ARG_SOURCE)
|
||||
set(ARG_SOURCE "int main(void) { return 0; }\n")
|
||||
endif()
|
||||
|
||||
string(RANDOM TARGET_NAME)
|
||||
set(TARGET_NAME "${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/cmTC_${TARGET_NAME}.dir")
|
||||
file(MAKE_DIRECTORY ${TARGET_NAME})
|
||||
|
||||
file(WRITE "${TARGET_NAME}/CheckSectionExists.c" "${ARG_SOURCE}\n")
|
||||
|
||||
string(REGEX MATCHALL "<[A-Za-z0-9_]*>" substitutions
|
||||
${CMAKE_C_COMPILE_OBJECT})
|
||||
|
||||
set(try_compile_flags "${ARG_FLAGS}")
|
||||
if(CMAKE_C_COMPILER_ID MATCHES Clang AND CMAKE_C_COMPILER_TARGET)
|
||||
list(APPEND try_compile_flags "-target ${CMAKE_C_COMPILER_TARGET}")
|
||||
endif()
|
||||
append_list_if(COMPILER_RT_HAS_FNO_LTO_FLAG -fno-lto try_compile_flags)
|
||||
if(NOT COMPILER_RT_ENABLE_PGO)
|
||||
if(LLVM_PROFDATA_FILE AND COMPILER_RT_HAS_FNO_PROFILE_INSTR_USE_FLAG)
|
||||
list(APPEND try_compile_flags "-fno-profile-instr-use")
|
||||
endif()
|
||||
if(LLVM_BUILD_INSTRUMENTED MATCHES IR AND COMPILER_RT_HAS_FNO_PROFILE_GENERATE_FLAG)
|
||||
list(APPEND try_compile_flags "-fno-profile-generate")
|
||||
elseif((LLVM_BUILD_INSTRUMENTED OR LLVM_BUILD_INSTRUMENTED_COVERAGE) AND COMPILER_RT_HAS_FNO_PROFILE_INSTR_GENERATE_FLAG)
|
||||
list(APPEND try_compile_flags "-fno-profile-instr-generate")
|
||||
if(LLVM_BUILD_INSTRUMENTED_COVERAGE AND COMPILER_RT_HAS_FNO_COVERAGE_MAPPING_FLAG)
|
||||
list(APPEND try_compile_flags "-fno-coverage-mapping")
|
||||
endif()
|
||||
endif()
|
||||
endif()
|
||||
|
||||
string(REPLACE ";" " " extra_flags "${try_compile_flags}")
|
||||
|
||||
set(test_compile_command "${CMAKE_C_COMPILE_OBJECT}")
|
||||
foreach(substitution ${substitutions})
|
||||
if(substitution STREQUAL "<CMAKE_C_COMPILER>")
|
||||
string(REPLACE "<CMAKE_C_COMPILER>" "${CMAKE_C_COMPILER} ${CMAKE_C_COMPILER_ARG1}"
|
||||
test_compile_command ${test_compile_command})
|
||||
elseif(substitution STREQUAL "<OBJECT>")
|
||||
string(REPLACE "<OBJECT>" "${TARGET_NAME}/CheckSectionExists.o"
|
||||
test_compile_command ${test_compile_command})
|
||||
elseif(substitution STREQUAL "<SOURCE>")
|
||||
string(REPLACE "<SOURCE>" "${TARGET_NAME}/CheckSectionExists.c"
|
||||
test_compile_command ${test_compile_command})
|
||||
elseif(substitution STREQUAL "<FLAGS>")
|
||||
string(REPLACE "<FLAGS>" "${CMAKE_C_FLAGS} ${extra_flags}"
|
||||
test_compile_command ${test_compile_command})
|
||||
else()
|
||||
string(REPLACE "${substitution}" "" test_compile_command
|
||||
${test_compile_command})
|
||||
endif()
|
||||
endforeach()
|
||||
|
||||
# Strip quotes from the compile command, as the compiler is not expecting
|
||||
# quoted arguments (potential quotes added from D62063).
|
||||
string(REPLACE "\"" "" test_compile_command "${test_compile_command}")
|
||||
|
||||
string(REPLACE " " ";" test_compile_command "${test_compile_command}")
|
||||
|
||||
execute_process(
|
||||
COMMAND ${test_compile_command}
|
||||
RESULT_VARIABLE TEST_RESULT
|
||||
OUTPUT_VARIABLE TEST_OUTPUT
|
||||
ERROR_VARIABLE TEST_ERROR
|
||||
)
|
||||
|
||||
# Explicitly throw a fatal error message if test_compile_command fails.
|
||||
if(TEST_RESULT)
|
||||
message(FATAL_ERROR "${TEST_ERROR}")
|
||||
return()
|
||||
endif()
|
||||
|
||||
execute_process(
|
||||
COMMAND ${CMAKE_OBJDUMP} -h "${TARGET_NAME}/CheckSectionExists.o"
|
||||
RESULT_VARIABLE CHECK_RESULT
|
||||
OUTPUT_VARIABLE CHECK_OUTPUT
|
||||
ERROR_VARIABLE CHECK_ERROR
|
||||
)
|
||||
string(FIND "${CHECK_OUTPUT}" "${section}" SECTION_FOUND)
|
||||
|
||||
if(NOT SECTION_FOUND EQUAL -1)
|
||||
set(${output} TRUE PARENT_SCOPE)
|
||||
else()
|
||||
set(${output} FALSE PARENT_SCOPE)
|
||||
endif()
|
||||
|
||||
file(REMOVE_RECURSE ${TARGET_NAME})
|
||||
endfunction()
|
|
@ -2,16 +2,16 @@ include(CMakeParseArguments)
|
|||
include(CompilerRTUtils)
|
||||
|
||||
function(get_aix_libatomic_default_link_flags link_flags export_list)
|
||||
set(linkopts
|
||||
"-Wl,-H512 -Wl,-D0 \
|
||||
-Wl,-T512 -Wl,-bhalt:4 -Wl,-bernotok \
|
||||
-Wl,-bnoentry -Wl,-bexport:${export_list} \
|
||||
-Wl,-bmodtype:SRE -Wl,-lc")
|
||||
set(linkopts
|
||||
-Wl,-H512 -Wl,-D0
|
||||
-Wl,-T512 -Wl,-bhalt:4 -Wl,-bernotok
|
||||
-Wl,-bnoentry -Wl,-bexport:${export_list}
|
||||
-Wl,-bmodtype:SRE -Wl,-lc)
|
||||
# Add `-Wl,-G`. Quoted from release notes of cmake-3.16.0
|
||||
# > On AIX, runtime linking is no longer enabled by default.
|
||||
# See https://cmake.org/cmake/help/latest/release/3.16.html
|
||||
if(${CMAKE_VERSION} VERSION_GREATER_EQUAL "3.16.0")
|
||||
set(linkopts "-Wl,-G" "${linkopts}")
|
||||
set(linkopts -Wl,-G ${linkopts})
|
||||
endif()
|
||||
set(${link_flags} ${linkopts} PARENT_SCOPE)
|
||||
endfunction()
|
||||
|
@ -24,16 +24,16 @@ function(get_aix_libatomic_type type)
|
|||
endif()
|
||||
endfunction()
|
||||
|
||||
macro(archive_aix_libatomic name)
|
||||
macro(archive_aix_libatomic name libname)
|
||||
cmake_parse_arguments(LIB
|
||||
""
|
||||
""
|
||||
"ARCHS;PARENT_TARGET"
|
||||
${ARGN})
|
||||
set(shared_libraries_to_archive "")
|
||||
set(objects_to_archive "")
|
||||
foreach (arch ${LIB_ARCHS})
|
||||
if(CAN_TARGET_${arch})
|
||||
set(output_dir "${CMAKE_CURRENT_BINARY_DIR}/libatomic-${arch}.dir")
|
||||
set(output_dir "${CMAKE_CURRENT_BINARY_DIR}/${libname}-${arch}.dir")
|
||||
# FIXME: Target name should be kept consistent with definition
|
||||
# in AddCompilerRT.cmake added by
|
||||
# add_compiler_rt_runtime(<name> SHARED ...)
|
||||
|
@ -50,11 +50,11 @@ macro(archive_aix_libatomic name)
|
|||
COMMAND ${CMAKE_STRIP} -X32_64 -E
|
||||
"${output_dir}/libatomic.so.1"
|
||||
DEPENDS ${target})
|
||||
list(APPEND shared_libraries_to_archive "${output_dir}/libatomic.so.1")
|
||||
list(APPEND objects_to_archive "${output_dir}/libatomic.so.1")
|
||||
endif()
|
||||
endif()
|
||||
endforeach()
|
||||
if(shared_libraries_to_archive)
|
||||
if(objects_to_archive)
|
||||
set(output_dir "")
|
||||
set(install_dir "")
|
||||
# If LLVM defines top level library directory, we want to deliver
|
||||
|
@ -67,14 +67,14 @@ macro(archive_aix_libatomic name)
|
|||
get_compiler_rt_output_dir(${COMPILER_RT_DEFAULT_TARGET_ARCH} output_dir)
|
||||
get_compiler_rt_install_dir(${COMPILER_RT_DEFAULT_TARGET_ARCH} install_dir)
|
||||
endif()
|
||||
add_custom_command(OUTPUT "${output_dir}/libatomic.a"
|
||||
COMMAND ${CMAKE_AR} -X32_64 r "${output_dir}/libatomic.a"
|
||||
${shared_libraries_to_archive}
|
||||
DEPENDS ${shared_libraries_to_archive})
|
||||
install(FILES "${output_dir}/libatomic.a"
|
||||
add_custom_command(OUTPUT "${output_dir}/${libname}.a"
|
||||
COMMAND ${CMAKE_AR} -X32_64 r "${output_dir}/${libname}.a"
|
||||
${objects_to_archive}
|
||||
DEPENDS ${objects_to_archive})
|
||||
install(FILES "${output_dir}/${libname}.a"
|
||||
DESTINATION ${install_dir})
|
||||
add_custom_target(aix-libatomic
|
||||
DEPENDS "${output_dir}/libatomic.a")
|
||||
add_custom_target(aix-${libname}
|
||||
DEPENDS "${output_dir}/${libname}.a")
|
||||
add_dependencies(${LIB_PARENT_TARGET} aix-${libname})
|
||||
endif()
|
||||
add_dependencies(${LIB_PARENT_TARGET} aix-libatomic)
|
||||
endmacro()
|
||||
|
|
|
@ -106,7 +106,8 @@ function(clang_compile object_file source)
|
|||
-o "${object_file}"
|
||||
${source_rpath}
|
||||
MAIN_DEPENDENCY ${source}
|
||||
DEPENDS ${SOURCE_DEPS})
|
||||
DEPENDS ${SOURCE_DEPS}
|
||||
COMMAND_EXPAND_LISTS)
|
||||
endfunction()
|
||||
|
||||
# On Darwin, there are no system-wide C++ headers and the just-built clang is
|
||||
|
|
|
@ -116,7 +116,7 @@ function(darwin_test_archs os valid_archs)
|
|||
if(NOT TEST_COMPILE_ONLY)
|
||||
message(STATUS "Finding valid architectures for ${os}...")
|
||||
set(SIMPLE_C ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/src.c)
|
||||
file(WRITE ${SIMPLE_C} "#include <stdio.h>\nint main() { printf(__FILE__); return 0; }\n")
|
||||
file(WRITE ${SIMPLE_C} "#include <stdio.h>\nint main(void) { printf(__FILE__); return 0; }\n")
|
||||
|
||||
set(os_linker_flags)
|
||||
foreach(flag ${DARWIN_${os}_LINK_FLAGS})
|
||||
|
@ -142,6 +142,11 @@ function(darwin_test_archs os valid_archs)
|
|||
list(REMOVE_ITEM archs "x86_64h")
|
||||
endif()
|
||||
|
||||
if(${os} MATCHES "iossim")
|
||||
message(STATUS "Disabling i386 slice for iossim")
|
||||
list(REMOVE_ITEM archs "i386")
|
||||
endif()
|
||||
|
||||
set(working_archs)
|
||||
foreach(arch ${archs})
|
||||
|
||||
|
@ -189,6 +194,8 @@ function(darwin_filter_host_archs input output)
|
|||
|
||||
if(ARM_HOST)
|
||||
list(REMOVE_ITEM tmp_var i386)
|
||||
list(REMOVE_ITEM tmp_var x86_64)
|
||||
list(REMOVE_ITEM tmp_var x86_64h)
|
||||
else()
|
||||
list(REMOVE_ITEM tmp_var arm64)
|
||||
list(REMOVE_ITEM tmp_var arm64e)
|
||||
|
@ -298,6 +305,13 @@ macro(darwin_add_builtin_library name suffix)
|
|||
-target "${LIB_ARCH}-apple-${base_os}${DARWIN_${LIBOS}_BUILTIN_MIN_VER}-simulator")
|
||||
endif()
|
||||
|
||||
if ("${COMPILER_RT_ENABLE_MACCATALYST}" AND
|
||||
"${LIB_OS}" MATCHES "^osx$")
|
||||
# Build the macOS builtins with Mac Catalyst support.
|
||||
list(APPEND builtin_cflags
|
||||
"SHELL:-target ${LIB_ARCH}-apple-macos${DARWIN_osx_BUILTIN_MIN_VER} -darwin-target-variant ${LIB_ARCH}-apple-ios13.1-macabi")
|
||||
endif()
|
||||
|
||||
set_target_compile_flags(${libname}
|
||||
${sysroot_flag}
|
||||
${DARWIN_${LIB_OS}_BUILTIN_MIN_VER_FLAG}
|
||||
|
@ -390,12 +404,12 @@ endfunction()
|
|||
macro(darwin_add_builtin_libraries)
|
||||
set(DARWIN_EXCLUDE_DIR ${CMAKE_CURRENT_SOURCE_DIR}/Darwin-excludes)
|
||||
|
||||
set(CFLAGS "-fPIC -O3 -fvisibility=hidden -DVISIBILITY_HIDDEN -Wall -fomit-frame-pointer")
|
||||
set(CFLAGS -fPIC -O3 -fvisibility=hidden -DVISIBILITY_HIDDEN -Wall -fomit-frame-pointer)
|
||||
set(CMAKE_C_FLAGS "")
|
||||
set(CMAKE_CXX_FLAGS "")
|
||||
set(CMAKE_ASM_FLAGS "")
|
||||
|
||||
append_string_if(COMPILER_RT_HAS_ASM_LSE " -DHAS_ASM_LSE" CFLAGS)
|
||||
append_list_if(COMPILER_RT_HAS_ASM_LSE -DHAS_ASM_LSE CFLAGS)
|
||||
|
||||
set(PROFILE_SOURCES ../profile/InstrProfiling.c
|
||||
../profile/InstrProfilingBuffer.c
|
||||
|
@ -404,6 +418,12 @@ macro(darwin_add_builtin_libraries)
|
|||
../profile/InstrProfilingInternal.c
|
||||
../profile/InstrProfilingVersionVar.c)
|
||||
foreach (os ${ARGN})
|
||||
set(macosx_sdk_version 99999)
|
||||
if ("${os}" STREQUAL "osx")
|
||||
find_darwin_sdk_version(macosx_sdk_version "macosx")
|
||||
endif()
|
||||
add_security_warnings(CFLAGS ${macosx_sdk_version})
|
||||
|
||||
list_intersect(DARWIN_BUILTIN_ARCHS DARWIN_${os}_BUILTIN_ARCHS BUILTIN_SUPPORTED_ARCH)
|
||||
|
||||
if((arm64 IN_LIST DARWIN_BUILTIN_ARCHS OR arm64e IN_LIST DARWIN_BUILTIN_ARCHS) AND NOT TARGET lse_builtin_symlinks)
|
||||
|
@ -505,7 +525,7 @@ macro(darwin_add_embedded_builtin_libraries)
|
|||
|
||||
set(MACHO_SYM_DIR ${CMAKE_CURRENT_SOURCE_DIR}/macho_embedded)
|
||||
|
||||
set(CFLAGS "-Oz -Wall -fomit-frame-pointer -ffreestanding")
|
||||
set(CFLAGS -Oz -Wall -fomit-frame-pointer -ffreestanding)
|
||||
set(CMAKE_C_FLAGS "")
|
||||
set(CMAKE_CXX_FLAGS "")
|
||||
set(CMAKE_ASM_FLAGS "")
|
||||
|
@ -524,8 +544,8 @@ macro(darwin_add_embedded_builtin_libraries)
|
|||
set(DARWIN_macho_embedded_LIBRARY_INSTALL_DIR
|
||||
${COMPILER_RT_INSTALL_LIBRARY_DIR}/macho_embedded)
|
||||
|
||||
set(CFLAGS_armv7 "-target thumbv7-apple-darwin-eabi")
|
||||
set(CFLAGS_i386 "-march=pentium")
|
||||
set(CFLAGS_armv7 -target thumbv7-apple-darwin-eabi)
|
||||
set(CFLAGS_i386 -march=pentium)
|
||||
|
||||
darwin_read_list_from_file(common_FUNCTIONS ${MACHO_SYM_DIR}/common.txt)
|
||||
darwin_read_list_from_file(thumb2_FUNCTIONS ${MACHO_SYM_DIR}/thumb2.txt)
|
||||
|
|
|
@ -13,20 +13,20 @@ macro(compiler_rt_mock_llvm_cmake_config)
|
|||
endmacro()
|
||||
|
||||
macro(compiler_rt_mock_llvm_cmake_config_set_cmake_path)
|
||||
# Point `LLVM_CMAKE_PATH` at the source tree in the monorepo.
|
||||
set(LLVM_CMAKE_PATH "${LLVM_MAIN_SRC_DIR}/cmake/modules")
|
||||
if (NOT EXISTS "${LLVM_CMAKE_PATH}")
|
||||
message(FATAL_ERROR "LLVM_CMAKE_PATH (${LLVM_CMAKE_PATH}) does not exist")
|
||||
# Point `LLVM_CMAKE_DIR` at the source tree in the monorepo.
|
||||
set(LLVM_CMAKE_DIR "${LLVM_MAIN_SRC_DIR}/cmake/modules")
|
||||
if (NOT EXISTS "${LLVM_CMAKE_DIR}")
|
||||
message(FATAL_ERROR "LLVM_CMAKE_DIR (${LLVM_CMAKE_DIR}) does not exist")
|
||||
endif()
|
||||
list(APPEND CMAKE_MODULE_PATH "${LLVM_CMAKE_PATH}")
|
||||
message(STATUS "LLVM_CMAKE_PATH: \"${LLVM_CMAKE_PATH}\"")
|
||||
list(APPEND CMAKE_MODULE_PATH "${LLVM_CMAKE_DIR}")
|
||||
message(STATUS "LLVM_CMAKE_DIR: \"${LLVM_CMAKE_DIR}\"")
|
||||
endmacro()
|
||||
|
||||
function(compiler_rt_mock_llvm_cmake_config_set_target_triple)
|
||||
# Various bits of compiler-rt depend on the `TARGET_TRIPLE`variable being
|
||||
# defined. This function tries to set a sensible value for the variable.
|
||||
# This is a function rather than a macro to avoid polluting the variable
|
||||
# namespace.
|
||||
# Various bits of compiler-rt depend on the `LLVM_TARGET_TRIPLE` variable
|
||||
# being defined. This function tries to set a sensible value for the
|
||||
# variable. This is a function rather than a macro to avoid polluting the
|
||||
# variable namespace.
|
||||
set(COMPILER_OUTPUT "")
|
||||
|
||||
# If the user provides `COMPILER_RT_DEFAULT_TARGET_ONLY` and `CMAKE_C_COMPILER_TARGET`
|
||||
|
@ -35,7 +35,7 @@ function(compiler_rt_mock_llvm_cmake_config_set_target_triple)
|
|||
if (COMPILER_RT_DEFAULT_TARGET_ONLY)
|
||||
if (NOT "${CMAKE_C_COMPILER_TARGET}" STREQUAL "")
|
||||
message(STATUS
|
||||
"Using CMAKE_C_COMPILER_TARGET (${CMAKE_C_COMPILER_TARGET}) as TARGET_TRIPLE")
|
||||
"Using CMAKE_C_COMPILER_TARGET (${CMAKE_C_COMPILER_TARGET}) as LLVM_TARGET_TRIPLE")
|
||||
endif()
|
||||
set(COMPILER_OUTPUT "${CMAKE_C_COMPILER_TARGET}")
|
||||
endif()
|
||||
|
@ -61,15 +61,15 @@ function(compiler_rt_mock_llvm_cmake_config_set_target_triple)
|
|||
if (HAD_ERROR)
|
||||
message(FATAL_ERROR "Fetching target triple from compiler failed")
|
||||
endif()
|
||||
set(TARGET_TRIPLE "${COMPILER_OUTPUT}")
|
||||
message(STATUS "TARGET_TRIPLE: \"${TARGET_TRIPLE}\"")
|
||||
if ("${TARGET_TRIPLE}" STREQUAL "")
|
||||
set(LLVM_TARGET_TRIPLE "${COMPILER_OUTPUT}")
|
||||
message(STATUS "TARGET_TRIPLE: \"${LLVM_TARGET_TRIPLE}\"")
|
||||
if ("${LLVM_TARGET_TRIPLE}" STREQUAL "")
|
||||
message(FATAL_ERROR "TARGET_TRIPLE cannot be empty")
|
||||
endif()
|
||||
set(TARGET_TRIPLE "${TARGET_TRIPLE}" PARENT_SCOPE)
|
||||
set(LLVM_TARGET_TRIPLE "${LLVM_TARGET_TRIPLE}" PARENT_SCOPE)
|
||||
endfunction()
|
||||
|
||||
macro(compiler_rt_mock_llvm_cmake_config_include_cmake_files)
|
||||
# Some compiler-rt CMake code needs to call code in this file.
|
||||
include("${LLVM_CMAKE_PATH}/AddLLVM.cmake")
|
||||
include("${LLVM_CMAKE_DIR}/AddLLVM.cmake")
|
||||
endmacro()
|
||||
|
|
|
@ -5,19 +5,11 @@ include(CheckSymbolExists)
|
|||
# define a handy helper function for it. The compile flags setting in CMake
|
||||
# has serious issues that make its syntax challenging at best.
|
||||
function(set_target_compile_flags target)
|
||||
set(argstring "")
|
||||
foreach(arg ${ARGN})
|
||||
set(argstring "${argstring} ${arg}")
|
||||
endforeach()
|
||||
set_property(TARGET ${target} PROPERTY COMPILE_FLAGS "${argstring}")
|
||||
set_property(TARGET ${target} PROPERTY COMPILE_OPTIONS ${ARGN})
|
||||
endfunction()
|
||||
|
||||
function(set_target_link_flags target)
|
||||
set(argstring "")
|
||||
foreach(arg ${ARGN})
|
||||
set(argstring "${argstring} ${arg}")
|
||||
endforeach()
|
||||
set_property(TARGET ${target} PROPERTY LINK_FLAGS "${argstring}")
|
||||
set_property(TARGET ${target} PROPERTY LINK_OPTIONS ${ARGN})
|
||||
endfunction()
|
||||
|
||||
# Set the variable var_PYBOOL to True if var holds a true-ish string,
|
||||
|
@ -128,7 +120,9 @@ macro(test_target_arch arch def)
|
|||
if(NOT HAS_${arch}_DEF)
|
||||
set(CAN_TARGET_${arch} FALSE)
|
||||
elseif(TEST_COMPILE_ONLY)
|
||||
try_compile_only(CAN_TARGET_${arch} FLAGS ${TARGET_${arch}_CFLAGS})
|
||||
try_compile_only(CAN_TARGET_${arch}
|
||||
SOURCE "#include <limits.h>\nint foo(int x, int y) { return x + y; }\n"
|
||||
FLAGS ${TARGET_${arch}_CFLAGS})
|
||||
else()
|
||||
set(FLAG_NO_EXCEPTIONS "")
|
||||
if(COMPILER_RT_HAS_FNO_EXCEPTIONS_FLAG)
|
||||
|
@ -153,9 +147,11 @@ endmacro()
|
|||
|
||||
macro(detect_target_arch)
|
||||
check_symbol_exists(__arm__ "" __ARM)
|
||||
check_symbol_exists(__AVR__ "" __AVR)
|
||||
check_symbol_exists(__aarch64__ "" __AARCH64)
|
||||
check_symbol_exists(__x86_64__ "" __X86_64)
|
||||
check_symbol_exists(__i386__ "" __I386)
|
||||
check_symbol_exists(__loongarch__ "" __LOONGARCH)
|
||||
check_symbol_exists(__mips__ "" __MIPS)
|
||||
check_symbol_exists(__mips64__ "" __MIPS64)
|
||||
check_symbol_exists(__powerpc__ "" __PPC)
|
||||
|
@ -170,6 +166,8 @@ macro(detect_target_arch)
|
|||
check_symbol_exists(__ve__ "" __VE)
|
||||
if(__ARM)
|
||||
add_default_target_arch(arm)
|
||||
elseif(__AVR)
|
||||
add_default_target_arch(avr)
|
||||
elseif(__AARCH64)
|
||||
add_default_target_arch(aarch64)
|
||||
elseif(__X86_64)
|
||||
|
@ -182,6 +180,14 @@ macro(detect_target_arch)
|
|||
endif()
|
||||
elseif(__I386)
|
||||
add_default_target_arch(i386)
|
||||
elseif(__LOONGARCH)
|
||||
if(CMAKE_SIZEOF_VOID_P EQUAL "4")
|
||||
add_default_target_arch(loongarch32)
|
||||
elseif(CMAKE_SIZEOF_VOID_P EQUAL "8")
|
||||
add_default_target_arch(loongarch64)
|
||||
else()
|
||||
message(FATAL_ERROR "Unsupported pointer size for LoongArch")
|
||||
endif()
|
||||
elseif(__MIPS64) # must be checked before __MIPS
|
||||
add_default_target_arch(mips64)
|
||||
elseif(__MIPS)
|
||||
|
@ -238,6 +244,10 @@ function(get_compiler_rt_root_source_dir ROOT_DIR_VAR)
|
|||
# Compiler-RT Builtins standalone build.
|
||||
# `llvm-project/compiler-rt/lib/builtins`
|
||||
set(PATH_TO_COMPILER_RT_SOURCE_ROOT "${CompilerRTBuiltins_SOURCE_DIR}/../../")
|
||||
elseif (DEFINED CompilerRTCRT_SOURCE_DIR)
|
||||
# Compiler-RT CRT standalone build.
|
||||
# `llvm-project/compiler-rt/lib/crt`
|
||||
set(PATH_TO_COMPILER_RT_SOURCE_ROOT "${CompilerRTCRT_SOURCE_DIR}/../../")
|
||||
elseif(DEFINED CompilerRT_SOURCE_DIR)
|
||||
# Compiler-RT standalone build.
|
||||
# `llvm-project/compiler-rt`
|
||||
|
@ -267,14 +277,15 @@ function(get_compiler_rt_root_source_dir ROOT_DIR_VAR)
|
|||
endfunction()
|
||||
|
||||
macro(load_llvm_config)
|
||||
if (NOT LLVM_CONFIG_PATH)
|
||||
find_program(LLVM_CONFIG_PATH "llvm-config"
|
||||
DOC "Path to llvm-config binary")
|
||||
if (NOT LLVM_CONFIG_PATH)
|
||||
message(WARNING "UNSUPPORTED COMPILER-RT CONFIGURATION DETECTED: "
|
||||
"llvm-config not found.\n"
|
||||
"Reconfigure with -DLLVM_CONFIG_PATH=path/to/llvm-config.")
|
||||
endif()
|
||||
if (LLVM_CONFIG_PATH AND NOT LLVM_CMAKE_DIR)
|
||||
message(WARNING
|
||||
"LLVM_CONFIG_PATH is deprecated, please use LLVM_CMAKE_DIR instead")
|
||||
# Compute the path to the LLVM install prefix and pass it as LLVM_CMAKE_DIR,
|
||||
# CMake will locate the appropriate lib*/cmake subdirectory from there.
|
||||
# For example. for -DLLVM_CONFIG_PATH=/usr/lib/llvm/16/bin/llvm-config
|
||||
# this will yield LLVM_CMAKE_DIR=/usr/lib/llvm/16.
|
||||
get_filename_component(LLVM_CMAKE_DIR "${LLVM_CONFIG_PATH}" DIRECTORY)
|
||||
get_filename_component(LLVM_CMAKE_DIR "${LLVM_CMAKE_DIR}" DIRECTORY)
|
||||
endif()
|
||||
|
||||
# Compute path to LLVM sources assuming the monorepo layout.
|
||||
|
@ -289,114 +300,37 @@ macro(load_llvm_config)
|
|||
"You are not using the monorepo layout. This configuration is DEPRECATED.")
|
||||
endif()
|
||||
|
||||
set(FOUND_LLVM_CMAKE_PATH FALSE)
|
||||
if (LLVM_CONFIG_PATH)
|
||||
execute_process(
|
||||
COMMAND ${LLVM_CONFIG_PATH} "--obj-root" "--bindir" "--libdir" "--src-root" "--includedir"
|
||||
RESULT_VARIABLE HAD_ERROR
|
||||
OUTPUT_VARIABLE CONFIG_OUTPUT)
|
||||
if (HAD_ERROR)
|
||||
message(FATAL_ERROR "llvm-config failed with status ${HAD_ERROR}")
|
||||
endif()
|
||||
string(REGEX REPLACE "[ \t]*[\r\n]+[ \t]*" ";" CONFIG_OUTPUT ${CONFIG_OUTPUT})
|
||||
list(GET CONFIG_OUTPUT 0 BINARY_DIR)
|
||||
list(GET CONFIG_OUTPUT 1 TOOLS_BINARY_DIR)
|
||||
list(GET CONFIG_OUTPUT 2 LIBRARY_DIR)
|
||||
list(GET CONFIG_OUTPUT 3 MAIN_SRC_DIR)
|
||||
list(GET CONFIG_OUTPUT 4 INCLUDE_DIR)
|
||||
find_package(LLVM HINTS "${LLVM_CMAKE_DIR}")
|
||||
if (NOT LLVM_FOUND)
|
||||
message(WARNING "UNSUPPORTED COMPILER-RT CONFIGURATION DETECTED: "
|
||||
"LLVM cmake package not found.\n"
|
||||
"Reconfigure with -DLLVM_CMAKE_DIR=/path/to/llvm.")
|
||||
else()
|
||||
list(APPEND CMAKE_MODULE_PATH "${LLVM_DIR}")
|
||||
# Turn into CACHE PATHs for overwritting
|
||||
set(LLVM_BINARY_DIR "${LLVM_BINARY_DIR}" CACHE PATH "Path to LLVM build tree")
|
||||
set(LLVM_LIBRARY_DIR "${LLVM_LIBRARY_DIR}" CACHE PATH "Path to llvm/lib")
|
||||
set(LLVM_TOOLS_BINARY_DIR "${LLVM_TOOLS_BINARY_DIR}" CACHE PATH "Path to llvm/bin")
|
||||
set(LLVM_INCLUDE_DIR ${LLVM_INCLUDE_DIRS} CACHE PATH "Path to llvm/include and any other header dirs needed")
|
||||
|
||||
set(LLVM_BINARY_DIR ${BINARY_DIR} CACHE PATH "Path to LLVM build tree")
|
||||
set(LLVM_LIBRARY_DIR ${LIBRARY_DIR} CACHE PATH "Path to llvm/lib")
|
||||
set(LLVM_TOOLS_BINARY_DIR ${TOOLS_BINARY_DIR} CACHE PATH "Path to llvm/bin")
|
||||
set(LLVM_INCLUDE_DIR ${INCLUDE_DIR} CACHE PATH "Paths to LLVM headers")
|
||||
|
||||
if (NOT EXISTS "${LLVM_MAIN_SRC_DIR_DEFAULT}")
|
||||
# TODO(dliew): Remove this legacy fallback path.
|
||||
message(WARNING
|
||||
"Consulting llvm-config for the LLVM source path "
|
||||
"as a fallback. This behavior will be removed in the future.")
|
||||
# We don't set `LLVM_MAIN_SRC_DIR` directly to avoid overriding a user
|
||||
# provided CMake cache value.
|
||||
set(LLVM_MAIN_SRC_DIR_DEFAULT "${MAIN_SRC_DIR}")
|
||||
message(STATUS "Using LLVM source path (${LLVM_MAIN_SRC_DIR_DEFAULT}) from llvm-config")
|
||||
endif()
|
||||
|
||||
# Detect if we have the LLVMXRay and TestingSupport library installed and
|
||||
# available from llvm-config.
|
||||
execute_process(
|
||||
COMMAND ${LLVM_CONFIG_PATH} "--ldflags" "--libs" "xray"
|
||||
RESULT_VARIABLE HAD_ERROR
|
||||
OUTPUT_VARIABLE CONFIG_OUTPUT
|
||||
ERROR_QUIET)
|
||||
if (HAD_ERROR)
|
||||
message(WARNING "llvm-config finding xray failed with status ${HAD_ERROR}")
|
||||
list(FIND LLVM_AVAILABLE_LIBS LLVMXRay XRAY_INDEX)
|
||||
set(COMPILER_RT_HAS_LLVMXRAY TRUE)
|
||||
if (XRAY_INDEX EQUAL -1)
|
||||
message(WARNING "LLVMXRay not found in LLVM_AVAILABLE_LIBS")
|
||||
set(COMPILER_RT_HAS_LLVMXRAY FALSE)
|
||||
else()
|
||||
string(REGEX REPLACE "[ \t]*[\r\n]+[ \t]*" ";" CONFIG_OUTPUT ${CONFIG_OUTPUT})
|
||||
list(GET CONFIG_OUTPUT 0 LDFLAGS)
|
||||
list(GET CONFIG_OUTPUT 1 LIBLIST)
|
||||
file(TO_CMAKE_PATH "${LDFLAGS}" LDFLAGS)
|
||||
file(TO_CMAKE_PATH "${LIBLIST}" LIBLIST)
|
||||
set(LLVM_XRAY_LDFLAGS ${LDFLAGS} CACHE STRING "Linker flags for LLVMXRay library")
|
||||
set(LLVM_XRAY_LIBLIST ${LIBLIST} CACHE STRING "Library list for LLVMXRay")
|
||||
set(COMPILER_RT_HAS_LLVMXRAY TRUE)
|
||||
endif()
|
||||
|
||||
set(COMPILER_RT_HAS_LLVMTESTINGSUPPORT FALSE)
|
||||
execute_process(
|
||||
COMMAND ${LLVM_CONFIG_PATH} "--ldflags" "--libs" "testingsupport"
|
||||
RESULT_VARIABLE HAD_ERROR
|
||||
OUTPUT_VARIABLE CONFIG_OUTPUT
|
||||
ERROR_QUIET)
|
||||
if (HAD_ERROR)
|
||||
message(WARNING "llvm-config finding testingsupport failed with status ${HAD_ERROR}")
|
||||
elseif(COMPILER_RT_INCLUDE_TESTS)
|
||||
string(REGEX REPLACE "[ \t]*[\r\n]+[ \t]*" ";" CONFIG_OUTPUT ${CONFIG_OUTPUT})
|
||||
list(GET CONFIG_OUTPUT 0 LDFLAGS)
|
||||
list(GET CONFIG_OUTPUT 1 LIBLIST)
|
||||
if (LIBLIST STREQUAL "")
|
||||
message(WARNING "testingsupport library not installed, some tests will be skipped")
|
||||
else()
|
||||
file(TO_CMAKE_PATH "${LDFLAGS}" LDFLAGS)
|
||||
file(TO_CMAKE_PATH "${LIBLIST}" LIBLIST)
|
||||
set(LLVM_TESTINGSUPPORT_LDFLAGS ${LDFLAGS} CACHE STRING "Linker flags for LLVMTestingSupport library")
|
||||
set(LLVM_TESTINGSUPPORT_LIBLIST ${LIBLIST} CACHE STRING "Library list for LLVMTestingSupport")
|
||||
set(COMPILER_RT_HAS_LLVMTESTINGSUPPORT TRUE)
|
||||
endif()
|
||||
list(FIND LLVM_AVAILABLE_LIBS LLVMTestingSupport TESTINGSUPPORT_INDEX)
|
||||
set(COMPILER_RT_HAS_LLVMTESTINGSUPPORT TRUE)
|
||||
if (TESTINGSUPPORT_INDEX EQUAL -1)
|
||||
message(WARNING "LLVMTestingSupport not found in LLVM_AVAILABLE_LIBS")
|
||||
set(COMPILER_RT_HAS_LLVMTESTINGSUPPORT FALSE)
|
||||
endif()
|
||||
|
||||
# Make use of LLVM CMake modules.
|
||||
# --cmakedir is supported since llvm r291218 (4.0 release)
|
||||
execute_process(
|
||||
COMMAND ${LLVM_CONFIG_PATH} --cmakedir
|
||||
RESULT_VARIABLE HAD_ERROR
|
||||
OUTPUT_VARIABLE CONFIG_OUTPUT)
|
||||
if(NOT HAD_ERROR)
|
||||
string(STRIP "${CONFIG_OUTPUT}" LLVM_CMAKE_PATH_FROM_LLVM_CONFIG)
|
||||
file(TO_CMAKE_PATH ${LLVM_CMAKE_PATH_FROM_LLVM_CONFIG} LLVM_CMAKE_PATH)
|
||||
else()
|
||||
file(TO_CMAKE_PATH ${LLVM_BINARY_DIR} LLVM_BINARY_DIR_CMAKE_STYLE)
|
||||
set(LLVM_CMAKE_PATH "${LLVM_BINARY_DIR_CMAKE_STYLE}/lib${LLVM_LIBDIR_SUFFIX}/cmake/llvm")
|
||||
endif()
|
||||
|
||||
set(LLVM_CMAKE_INCLUDE_FILE "${LLVM_CMAKE_PATH}/LLVMConfig.cmake")
|
||||
if (EXISTS "${LLVM_CMAKE_INCLUDE_FILE}")
|
||||
list(APPEND CMAKE_MODULE_PATH "${LLVM_CMAKE_PATH}")
|
||||
# Get some LLVM variables from LLVMConfig.
|
||||
include("${LLVM_CMAKE_INCLUDE_FILE}")
|
||||
set(FOUND_LLVM_CMAKE_PATH TRUE)
|
||||
else()
|
||||
set(FOUND_LLVM_CMAKE_PATH FALSE)
|
||||
message(WARNING "LLVM CMake path (${LLVM_CMAKE_INCLUDE_FILE}) reported by llvm-config does not exist")
|
||||
endif()
|
||||
unset(LLVM_CMAKE_INCLUDE_FILE)
|
||||
|
||||
set(LLVM_LIBRARY_OUTPUT_INTDIR
|
||||
${LLVM_BINARY_DIR}/${CMAKE_CFG_INTDIR}/lib${LLVM_LIBDIR_SUFFIX})
|
||||
endif()
|
||||
|
||||
# Finally set the cache variable now that `llvm-config` has also had a chance
|
||||
# to set `LLVM_MAIN_SRC_DIR_DEFAULT`.
|
||||
set(LLVM_LIBRARY_OUTPUT_INTDIR
|
||||
${LLVM_BINARY_DIR}/${CMAKE_CFG_INTDIR}/lib${LLVM_LIBDIR_SUFFIX})
|
||||
|
||||
set(LLVM_MAIN_SRC_DIR "${LLVM_MAIN_SRC_DIR_DEFAULT}" CACHE PATH "Path to LLVM source tree")
|
||||
message(STATUS "LLVM_MAIN_SRC_DIR: \"${LLVM_MAIN_SRC_DIR}\"")
|
||||
if (NOT EXISTS "${LLVM_MAIN_SRC_DIR}")
|
||||
|
@ -409,7 +343,7 @@ macro(load_llvm_config)
|
|||
"This will be treated as error in the future.")
|
||||
endif()
|
||||
|
||||
if (NOT FOUND_LLVM_CMAKE_PATH)
|
||||
if (NOT LLVM_FOUND)
|
||||
# This configuration tries to configure without the prescence of `LLVMConfig.cmake`. It is
|
||||
# intended for testing purposes (generating the lit test suites) and will likely not support
|
||||
# a build of the runtimes in compiler-rt.
|
||||
|
@ -426,18 +360,12 @@ macro(construct_compiler_rt_default_triple)
|
|||
endif()
|
||||
set(COMPILER_RT_DEFAULT_TARGET_TRIPLE ${CMAKE_C_COMPILER_TARGET})
|
||||
else()
|
||||
set(COMPILER_RT_DEFAULT_TARGET_TRIPLE ${TARGET_TRIPLE} CACHE STRING
|
||||
set(COMPILER_RT_DEFAULT_TARGET_TRIPLE ${LLVM_TARGET_TRIPLE} CACHE STRING
|
||||
"Default triple for which compiler-rt runtimes will be built.")
|
||||
endif()
|
||||
|
||||
if(DEFINED COMPILER_RT_TEST_TARGET_TRIPLE)
|
||||
# Backwards compatibility: this variable used to be called
|
||||
# COMPILER_RT_TEST_TARGET_TRIPLE.
|
||||
set(COMPILER_RT_DEFAULT_TARGET_TRIPLE ${COMPILER_RT_TEST_TARGET_TRIPLE})
|
||||
endif()
|
||||
|
||||
string(REPLACE "-" ";" TARGET_TRIPLE_LIST ${COMPILER_RT_DEFAULT_TARGET_TRIPLE})
|
||||
list(GET TARGET_TRIPLE_LIST 0 COMPILER_RT_DEFAULT_TARGET_ARCH)
|
||||
string(REPLACE "-" ";" LLVM_TARGET_TRIPLE_LIST ${COMPILER_RT_DEFAULT_TARGET_TRIPLE})
|
||||
list(GET LLVM_TARGET_TRIPLE_LIST 0 COMPILER_RT_DEFAULT_TARGET_ARCH)
|
||||
|
||||
# Map various forms of the architecture names to the canonical forms
|
||||
# (as they are used by clang, see getArchNameForCompilerRTLib).
|
||||
|
@ -448,7 +376,7 @@ macro(construct_compiler_rt_default_triple)
|
|||
|
||||
# Determine if test target triple is specified explicitly, and doesn't match the
|
||||
# default.
|
||||
if(NOT COMPILER_RT_DEFAULT_TARGET_TRIPLE STREQUAL TARGET_TRIPLE)
|
||||
if(NOT COMPILER_RT_DEFAULT_TARGET_TRIPLE STREQUAL LLVM_TARGET_TRIPLE)
|
||||
set(COMPILER_RT_HAS_EXPLICIT_DEFAULT_TARGET_TRIPLE TRUE)
|
||||
else()
|
||||
set(COMPILER_RT_HAS_EXPLICIT_DEFAULT_TARGET_TRIPLE FALSE)
|
||||
|
@ -484,11 +412,46 @@ endfunction()
|
|||
function(get_compiler_rt_target arch variable)
|
||||
string(FIND ${COMPILER_RT_DEFAULT_TARGET_TRIPLE} "-" dash_index)
|
||||
string(SUBSTRING ${COMPILER_RT_DEFAULT_TARGET_TRIPLE} ${dash_index} -1 triple_suffix)
|
||||
string(SUBSTRING ${COMPILER_RT_DEFAULT_TARGET_TRIPLE} 0 ${dash_index} triple_cpu)
|
||||
if(COMPILER_RT_DEFAULT_TARGET_ONLY)
|
||||
# Use exact spelling when building only for the target specified to CMake.
|
||||
set(target "${COMPILER_RT_DEFAULT_TARGET_TRIPLE}")
|
||||
elseif(ANDROID AND ${arch} STREQUAL "i386")
|
||||
set(target "i686${triple_suffix}")
|
||||
elseif(${arch} STREQUAL "amd64")
|
||||
set(target "x86_64${triple_suffix}")
|
||||
elseif(${arch} STREQUAL "sparc64")
|
||||
set(target "sparcv9${triple_suffix}")
|
||||
elseif("${arch}" MATCHES "mips64|mips64el")
|
||||
string(REGEX REPLACE "-gnu.*" "-gnuabi64" triple_suffix_gnu "${triple_suffix}")
|
||||
string(REGEX REPLACE "mipsisa32" "mipsisa64" triple_cpu_mips "${triple_cpu}")
|
||||
string(REGEX REPLACE "^mips$" "mips64" triple_cpu_mips "${triple_cpu_mips}")
|
||||
string(REGEX REPLACE "^mipsel$" "mips64el" triple_cpu_mips "${triple_cpu_mips}")
|
||||
set(target "${triple_cpu_mips}${triple_suffix_gnu}")
|
||||
elseif("${arch}" MATCHES "mips|mipsel")
|
||||
string(REGEX REPLACE "-gnuabi.*" "-gnu" triple_suffix_gnu "${triple_suffix}")
|
||||
string(REGEX REPLACE "mipsisa64" "mipsisa32" triple_cpu_mips "${triple_cpu}")
|
||||
string(REGEX REPLACE "mips64" "mips" triple_cpu_mips "${triple_cpu_mips}")
|
||||
set(target "${triple_cpu_mips}${triple_suffix_gnu}")
|
||||
elseif("${arch}" MATCHES "^arm")
|
||||
# Arch is arm, armhf, armv6m (anything else would come from using
|
||||
# COMPILER_RT_DEFAULT_TARGET_ONLY, which is checked above).
|
||||
if (${arch} STREQUAL "armhf")
|
||||
# If we are building for hard float but our ABI is soft float.
|
||||
if ("${triple_suffix}" MATCHES ".*eabi$")
|
||||
# Change "eabi" -> "eabihf"
|
||||
set(triple_suffix "${triple_suffix}hf")
|
||||
endif()
|
||||
# ABI is already set in the triple, don't repeat it in the architecture.
|
||||
set(arch "arm")
|
||||
else ()
|
||||
# If we are building for soft float, but the triple's ABI is hard float.
|
||||
if ("${triple_suffix}" MATCHES ".*eabihf$")
|
||||
# Change "eabihf" -> "eabi"
|
||||
string(REGEX REPLACE "hf$" "" triple_suffix "${triple_suffix}")
|
||||
endif()
|
||||
endif()
|
||||
set(target "${arch}${triple_suffix}")
|
||||
else()
|
||||
set(target "${arch}${triple_suffix}")
|
||||
endif()
|
||||
|
@ -598,3 +561,34 @@ function(add_compiler_rt_install_targets name)
|
|||
endif()
|
||||
endif()
|
||||
endfunction()
|
||||
|
||||
# Add warnings to catch potential errors that can lead to security
|
||||
# vulnerabilities.
|
||||
function(add_security_warnings out_flags macosx_sdk_version)
|
||||
set(flags "${${out_flags}}")
|
||||
|
||||
append_list_if(COMPILER_RT_HAS_ARRAY_BOUNDS_FLAG -Werror=array-bounds flags)
|
||||
append_list_if(COMPILER_RT_HAS_UNINITIALIZED_FLAG -Werror=uninitialized flags)
|
||||
append_list_if(COMPILER_RT_HAS_SHADOW_FLAG -Werror=shadow flags)
|
||||
append_list_if(COMPILER_RT_HAS_EMPTY_BODY_FLAG -Werror=empty-body flags)
|
||||
append_list_if(COMPILER_RT_HAS_SIZEOF_POINTER_MEMACCESS_FLAG -Werror=sizeof-pointer-memaccess flags)
|
||||
append_list_if(COMPILER_RT_HAS_SIZEOF_ARRAY_ARGUMENT_FLAG -Werror=sizeof-array-argument flags)
|
||||
append_list_if(COMPILER_RT_HAS_SUSPICIOUS_MEMACCESS_FLAG -Werror=suspicious-memaccess flags)
|
||||
append_list_if(COMPILER_RT_HAS_BUILTIN_MEMCPY_CHK_SIZE_FLAG -Werror=builtin-memcpy-chk-size flags)
|
||||
append_list_if(COMPILER_RT_HAS_ARRAY_BOUNDS_POINTER_ARITHMETIC_FLAG -Werror=array-bounds-pointer-arithmetic flags)
|
||||
append_list_if(COMPILER_RT_HAS_RETURN_STACK_ADDRESS_FLAG -Werror=return-stack-address flags)
|
||||
append_list_if(COMPILER_RT_HAS_SIZEOF_ARRAY_DECAY_FLAG -Werror=sizeof-array-decay flags)
|
||||
append_list_if(COMPILER_RT_HAS_FORMAT_INSUFFICIENT_ARGS_FLAG -Werror=format-insufficient-args flags)
|
||||
append_list_if(COMPILER_RT_HAS_BUILTIN_FORMAL_SECURITY_FLAG -Werror=format-security flags)
|
||||
append_list_if(COMPILER_RT_HAS_SIZEOF_ARRAY_DIV_FLAG -Werror=sizeof-array-div)
|
||||
append_list_if(COMPILER_RT_HAS_SIZEOF_POINTER_DIV_FLAG -Werror=sizeof-pointer-div)
|
||||
|
||||
# Add -Wformat-nonliteral only if we can avoid adding the definition of
|
||||
# eprintf. On Apple platforms, eprintf is needed only on macosx and only if
|
||||
# its version is older than 10.7.
|
||||
if ("${macosx_sdk_version}" VERSION_GREATER_EQUAL 10.7)
|
||||
list(APPEND flags -Werror=format-nonliteral -DDONT_DEFINE_EPRINTF)
|
||||
endif()
|
||||
|
||||
set(${out_flags} "${flags}" PARENT_SCOPE)
|
||||
endfunction()
|
||||
|
|
|
@ -1,29 +0,0 @@
|
|||
# TODO(phosek): We should use the runtimes build instead configured with
|
||||
# LLVM_ENABLE_RUNTIMES=libcxxabi;libcxx to avoid duplication of logic.
|
||||
|
||||
cmake_minimum_required(VERSION 3.13.4)
|
||||
project(custom-libcxx C CXX)
|
||||
|
||||
find_package(Python3 REQUIRED COMPONENTS Interpreter)
|
||||
|
||||
# Build static libcxxabi.
|
||||
set(LIBCXXABI_ENABLE_SHARED OFF CACHE BOOL "")
|
||||
set(LIBCXXABI_ENABLE_EXCEPTIONS ON CACHE BOOL "")
|
||||
set(LIBCXXABI_HERMETIC_STATIC_LIBRARY ON CACHE STRING "")
|
||||
set(LIBCXXABI_LIBCXX_PATH ${COMPILER_RT_LIBCXX_PATH} CACHE PATH "")
|
||||
set(LIBCXXABI_INCLUDE_TESTS OFF CACHE BOOL "")
|
||||
add_subdirectory(${COMPILER_RT_LIBCXXABI_PATH} ${CMAKE_CURRENT_BINARY_DIR}/cxxabi)
|
||||
|
||||
# Build static libcxx without exceptions.
|
||||
set(LIBCXX_ENABLE_EXPERIMENTAL_LIBRARY OFF CACHE BOOL "")
|
||||
set(LIBCXX_ENABLE_SHARED OFF CACHE BOOL "")
|
||||
set(LIBCXX_ENABLE_EXCEPTIONS OFF CACHE BOOL "")
|
||||
set(LIBCXX_HERMETIC_STATIC_LIBRARY ON CACHE BOOL "")
|
||||
|
||||
# Use above libcxxabi.
|
||||
set(LIBCXX_CXX_ABI "libcxxabi" CACHE STRING "")
|
||||
set(LIBCXX_CXX_ABI_INTREE 1)
|
||||
set(LIBCXX_ENABLE_STATIC_ABI_LIBRARY ON CACHE BOOL "")
|
||||
set(LIBCXX_CXX_ABI_INCLUDE_PATHS ${COMPILER_RT_LIBCXXABI_PATH}/include CACHE PATH "")
|
||||
|
||||
add_subdirectory(${COMPILER_RT_LIBCXX_PATH} ${CMAKE_CURRENT_BINARY_DIR}/cxx)
|
|
@ -1,65 +0,0 @@
|
|||
# Check if compile-rt library file path exists.
|
||||
# If found, cache the path in:
|
||||
# COMPILER_RT_LIBRARY-<name>-<target>
|
||||
# If err_flag is true OR path not found, emit a message and set:
|
||||
# COMPILER_RT_LIBRARY-<name>-<target> to NOTFOUND
|
||||
function(cache_compiler_rt_library err_flag name target library_file)
|
||||
if(err_flag OR NOT EXISTS "${library_file}")
|
||||
message(STATUS "Failed to find compiler-rt ${name} library for ${target}")
|
||||
set(COMPILER_RT_LIBRARY-${name}-${target} "NOTFOUND" CACHE INTERNAL
|
||||
"compiler-rt ${name} library for ${target}")
|
||||
else()
|
||||
message(STATUS "Found compiler-rt ${name} library: ${library_file}")
|
||||
set(COMPILER_RT_LIBRARY-${name}-${target} "${library_file}" CACHE INTERNAL
|
||||
"compiler-rt ${name} library for ${target}")
|
||||
endif()
|
||||
endfunction()
|
||||
|
||||
# Find the path to compiler-rt library `name` (e.g. "builtins") for
|
||||
# the specified `target` (e.g. "x86_64-linux") and return it in `variable`.
|
||||
# This calls cache_compiler_rt_library that caches the path to speed up
|
||||
# repeated invocations with the same `name` and `target`.
|
||||
function(find_compiler_rt_library name target variable)
|
||||
if(NOT CMAKE_CXX_COMPILER_ID MATCHES Clang)
|
||||
set(${variable} "NOTFOUND" PARENT_SCOPE)
|
||||
return()
|
||||
endif()
|
||||
if (NOT target AND CMAKE_CXX_COMPILER_TARGET)
|
||||
set(target "${CMAKE_CXX_COMPILER_TARGET}")
|
||||
endif()
|
||||
if(NOT DEFINED COMPILER_RT_LIBRARY-builtins-${target})
|
||||
# If the cache variable is not defined, invoke clang and then
|
||||
# set it with cache_compiler_rt_library.
|
||||
set(CLANG_COMMAND ${CMAKE_CXX_COMPILER} ${SANITIZER_COMMON_FLAGS}
|
||||
"--rtlib=compiler-rt" "-print-libgcc-file-name")
|
||||
if(target)
|
||||
list(APPEND CLANG_COMMAND "--target=${target}")
|
||||
endif()
|
||||
get_property(SANITIZER_CXX_FLAGS CACHE CMAKE_CXX_FLAGS PROPERTY VALUE)
|
||||
string(REPLACE " " ";" SANITIZER_CXX_FLAGS "${SANITIZER_CXX_FLAGS}")
|
||||
list(APPEND CLANG_COMMAND ${SANITIZER_CXX_FLAGS})
|
||||
execute_process(
|
||||
COMMAND ${CLANG_COMMAND}
|
||||
RESULT_VARIABLE HAD_ERROR
|
||||
OUTPUT_VARIABLE LIBRARY_FILE
|
||||
)
|
||||
string(STRIP "${LIBRARY_FILE}" LIBRARY_FILE)
|
||||
file(TO_CMAKE_PATH "${LIBRARY_FILE}" LIBRARY_FILE)
|
||||
cache_compiler_rt_library(${HAD_ERROR}
|
||||
builtins "${target}" "${LIBRARY_FILE}")
|
||||
endif()
|
||||
if(NOT COMPILER_RT_LIBRARY-builtins-${target})
|
||||
set(${variable} "NOTFOUND" PARENT_SCOPE)
|
||||
return()
|
||||
endif()
|
||||
if(NOT DEFINED COMPILER_RT_LIBRARY-${name}-${target})
|
||||
# clang gives only the builtins library path. Other library paths are
|
||||
# obtained by substituting "builtins" with ${name} in the builtins
|
||||
# path and then checking if the resultant path exists. The result of
|
||||
# this check is also cached by cache_compiler_rt_library.
|
||||
set(LIBRARY_FILE "${COMPILER_RT_LIBRARY-builtins-${target}}")
|
||||
string(REPLACE "builtins" "${name}" LIBRARY_FILE "${LIBRARY_FILE}")
|
||||
cache_compiler_rt_library(FALSE "${name}" "${target}" "${LIBRARY_FILE}")
|
||||
endif()
|
||||
set(${variable} "${COMPILER_RT_LIBRARY-${name}-${target}}" PARENT_SCOPE)
|
||||
endfunction()
|
|
@ -3,9 +3,6 @@ include(CompilerRTUtils)
|
|||
set(SANITIZER_GEN_DYNAMIC_LIST
|
||||
${COMPILER_RT_SOURCE_DIR}/lib/sanitizer_common/scripts/gen_dynamic_list.py)
|
||||
|
||||
set(SANITIZER_LINT_SCRIPT
|
||||
${COMPILER_RT_SOURCE_DIR}/lib/sanitizer_common/scripts/check_lint.sh)
|
||||
|
||||
if(CMAKE_NM)
|
||||
set(SANITIZER_NM "${CMAKE_NM}")
|
||||
else()
|
||||
|
@ -95,20 +92,3 @@ macro(add_sanitizer_rt_version_list name)
|
|||
add_custom_target(${name}-version-list ALL
|
||||
DEPENDS ${vers})
|
||||
endmacro()
|
||||
|
||||
# Add target to check code style for sanitizer runtimes.
|
||||
if(CMAKE_HOST_UNIX AND NOT OS_NAME MATCHES "OpenBSD")
|
||||
add_custom_target(SanitizerLintCheck
|
||||
COMMAND env LLVM_CHECKOUT=${LLVM_MAIN_SRC_DIR} SILENT=1 TMPDIR=
|
||||
PYTHON_EXECUTABLE=${Python3_EXECUTABLE}
|
||||
COMPILER_RT=${COMPILER_RT_SOURCE_DIR}
|
||||
${SANITIZER_LINT_SCRIPT}
|
||||
DEPENDS ${SANITIZER_LINT_SCRIPT}
|
||||
COMMENT "Running lint check for sanitizer sources..."
|
||||
VERBATIM)
|
||||
else()
|
||||
add_custom_target(SanitizerLintCheck
|
||||
COMMAND echo "No lint check")
|
||||
endif()
|
||||
set_target_properties(SanitizerLintCheck
|
||||
PROPERTIES FOLDER "Compiler-RT Misc")
|
||||
|
|
|
@ -3,8 +3,12 @@
|
|||
# .o files. This is particularly useful in producing larger, more complex
|
||||
# runtime libraries.
|
||||
|
||||
include(BuiltinTests)
|
||||
include(CheckIncludeFile)
|
||||
include(CheckCXXSourceCompiles)
|
||||
include(GNUInstallDirs)
|
||||
include(ExtendPath)
|
||||
include(CompilerRTDarwinUtils)
|
||||
|
||||
check_include_file(unwind.h HAVE_UNWIND_H)
|
||||
|
||||
|
@ -35,14 +39,14 @@ endif()
|
|||
|
||||
if (LLVM_TREE_AVAILABLE)
|
||||
# Compute the Clang version from the LLVM version.
|
||||
# FIXME: We should be able to reuse CLANG_VERSION variable calculated
|
||||
# FIXME: We should be able to reuse CLANG_VERSION_MAJOR variable calculated
|
||||
# in Clang cmake files, instead of copying the rules here.
|
||||
string(REGEX MATCH "[0-9]+\\.[0-9]+(\\.[0-9]+)?" CLANG_VERSION
|
||||
string(REGEX MATCH "^[0-9]+" CLANG_VERSION_MAJOR
|
||||
${PACKAGE_VERSION})
|
||||
# Setup the paths where compiler-rt runtimes and headers should be stored.
|
||||
set(COMPILER_RT_OUTPUT_DIR ${LLVM_LIBRARY_OUTPUT_INTDIR}/clang/${CLANG_VERSION})
|
||||
set(COMPILER_RT_OUTPUT_DIR ${LLVM_LIBRARY_OUTPUT_INTDIR}/clang/${CLANG_VERSION_MAJOR})
|
||||
set(COMPILER_RT_EXEC_OUTPUT_DIR ${LLVM_RUNTIME_OUTPUT_INTDIR})
|
||||
set(COMPILER_RT_INSTALL_PATH lib${LLVM_LIBDIR_SUFFIX}/clang/${CLANG_VERSION})
|
||||
set(COMPILER_RT_INSTALL_PATH lib${LLVM_LIBDIR_SUFFIX}/clang/${CLANG_VERSION_MAJOR})
|
||||
option(COMPILER_RT_INCLUDE_TESTS "Generate and build compiler-rt unit tests."
|
||||
${LLVM_INCLUDE_TESTS})
|
||||
option(COMPILER_RT_ENABLE_WERROR "Fail and stop if warning is triggered"
|
||||
|
@ -85,43 +89,35 @@ else()
|
|||
set(COMPILER_RT_TEST_COMPILER_ID GNU)
|
||||
endif()
|
||||
|
||||
function(extend_install_path joined_path current_segment)
|
||||
if("${current_segment}" STREQUAL "")
|
||||
set(temp_path "${COMPILER_RT_INSTALL_PATH}")
|
||||
elseif("${COMPILER_RT_INSTALL_PATH}" STREQUAL "")
|
||||
set(temp_path "${current_segment}")
|
||||
elseif(IS_ABSOLUTE "${current_segment}")
|
||||
message(WARNING "Since \"${current_segment}\" is absolute, it overrides COMPILER_RT_INSTALL_PATH: \"${COMPILER_RT_INSTALL_PATH}\".")
|
||||
set(temp_path "${current_segment}")
|
||||
else()
|
||||
set(temp_path "${COMPILER_RT_INSTALL_PATH}/${current_segment}")
|
||||
endif()
|
||||
set(${joined_path} "${temp_path}" PARENT_SCOPE)
|
||||
endfunction()
|
||||
|
||||
if(NOT DEFINED COMPILER_RT_OS_DIR)
|
||||
string(TOLOWER ${CMAKE_SYSTEM_NAME} COMPILER_RT_OS_DIR)
|
||||
if(ANDROID)
|
||||
# The CMAKE_SYSTEM_NAME for Android is Android, but the OS is Linux and the
|
||||
# driver will search for compiler-rt libraries in the "linux" directory.
|
||||
set(COMPILER_RT_OS_DIR linux)
|
||||
else()
|
||||
string(TOLOWER ${CMAKE_SYSTEM_NAME} COMPILER_RT_OS_DIR)
|
||||
endif()
|
||||
endif()
|
||||
if(LLVM_ENABLE_PER_TARGET_RUNTIME_DIR AND NOT APPLE)
|
||||
set(COMPILER_RT_OUTPUT_LIBRARY_DIR
|
||||
${COMPILER_RT_OUTPUT_DIR}/lib)
|
||||
extend_install_path(default_install_path lib)
|
||||
extend_path(default_install_path "${COMPILER_RT_INSTALL_PATH}" lib)
|
||||
set(COMPILER_RT_INSTALL_LIBRARY_DIR "${default_install_path}" CACHE PATH
|
||||
"Path where built compiler-rt libraries should be installed.")
|
||||
else(LLVM_ENABLE_PER_TARGET_RUNTIME_DIR AND NOT APPLE)
|
||||
set(COMPILER_RT_OUTPUT_LIBRARY_DIR
|
||||
${COMPILER_RT_OUTPUT_DIR}/lib/${COMPILER_RT_OS_DIR})
|
||||
extend_install_path(default_install_path "lib/${COMPILER_RT_OS_DIR}")
|
||||
extend_path(default_install_path "${COMPILER_RT_INSTALL_PATH}" "lib/${COMPILER_RT_OS_DIR}")
|
||||
set(COMPILER_RT_INSTALL_LIBRARY_DIR "${default_install_path}" CACHE PATH
|
||||
"Path where built compiler-rt libraries should be installed.")
|
||||
endif()
|
||||
extend_install_path(default_install_path bin)
|
||||
extend_path(default_install_path "${COMPILER_RT_INSTALL_PATH}" "${CMAKE_INSTALL_BINDIR}")
|
||||
set(COMPILER_RT_INSTALL_BINARY_DIR "${default_install_path}" CACHE PATH
|
||||
"Path where built compiler-rt executables should be installed.")
|
||||
extend_install_path(default_install_path include)
|
||||
extend_path(default_install_path "${COMPILER_RT_INSTALL_PATH}" "${CMAKE_INSTALL_INCLUDEDIR}")
|
||||
set(COMPILER_RT_INSTALL_INCLUDE_DIR "${default_install_path}" CACHE PATH
|
||||
"Path where compiler-rt headers should be installed.")
|
||||
extend_install_path(default_install_path share)
|
||||
extend_path(default_install_path "${COMPILER_RT_INSTALL_PATH}" "${CMAKE_INSTALL_DATADIR}")
|
||||
set(COMPILER_RT_INSTALL_DATA_DIR "${default_install_path}" CACHE PATH
|
||||
"Path where compiler-rt data files should be installed.")
|
||||
|
||||
|
@ -144,7 +140,24 @@ if(APPLE)
|
|||
set(OSX_SYSROOT_FLAG "")
|
||||
endif()
|
||||
|
||||
option(COMPILER_RT_ENABLE_IOS "Enable building for iOS" On)
|
||||
try_compile_only(COMPILER_RT_HAS_DARWIN_TARGET_VARIANT_FLAG
|
||||
FLAGS
|
||||
"-target" "x86_64-apple-macos10.15"
|
||||
"-darwin-target-variant" "x86_64-apple-ios13.1-macabi"
|
||||
"-Werror")
|
||||
option(COMPILER_RT_ENABLE_MACCATALYST "Enable building for Mac Catalyst" ${COMPILER_RT_HAS_DARWIN_TARGET_VARIANT_FLAG})
|
||||
|
||||
# Don't enable COMPILER_RT_ENABLE_IOS if we can't find the sdk dir.
|
||||
# This can happen when you only have the commandline tools installed
|
||||
# which doesn't come with the iOS SDK.
|
||||
find_darwin_sdk_dir(HAS_IOS_SDK "iphoneos")
|
||||
set(COMPILER_RT_ENABLE_IOS_DEFAULT On)
|
||||
if("${HAS_IOS_SDK}" STREQUAL "")
|
||||
message(WARNING "iOS SDK not found! Building compiler-rt without iOS support.")
|
||||
set(COMPILER_RT_ENABLE_IOS_DEFAULT Off)
|
||||
endif()
|
||||
option(COMPILER_RT_ENABLE_IOS "Enable building for iOS" ${COMPILER_RT_ENABLE_IOS_DEFAULT})
|
||||
|
||||
option(COMPILER_RT_ENABLE_WATCHOS "Enable building for watchOS - Experimental" Off)
|
||||
option(COMPILER_RT_ENABLE_TVOS "Enable building for tvOS - Experimental" Off)
|
||||
|
||||
|
@ -204,37 +217,44 @@ macro(test_targets)
|
|||
test_target_arch(x86_64 "" "")
|
||||
endif()
|
||||
endif()
|
||||
elseif("${COMPILER_RT_DEFAULT_TARGET_ARCH}" MATCHES "powerpc64le")
|
||||
elseif("${COMPILER_RT_DEFAULT_TARGET_ARCH}" MATCHES "loongarch64")
|
||||
test_target_arch(loongarch64 "" "")
|
||||
elseif("${COMPILER_RT_DEFAULT_TARGET_ARCH}" MATCHES "powerpc64le|ppc64le")
|
||||
test_target_arch(powerpc64le "" "-m64")
|
||||
elseif("${COMPILER_RT_DEFAULT_TARGET_ARCH}" MATCHES "powerpc")
|
||||
if(CMAKE_SYSTEM_NAME MATCHES "AIX")
|
||||
test_target_arch(powerpc "" "-m32")
|
||||
endif()
|
||||
test_target_arch(powerpc "" "-m32")
|
||||
test_target_arch(powerpc64 "" "-m64")
|
||||
elseif("${COMPILER_RT_DEFAULT_TARGET_ARCH}" MATCHES "s390x")
|
||||
test_target_arch(s390x "" "")
|
||||
elseif("${COMPILER_RT_DEFAULT_TARGET_ARCH}" MATCHES "sparc")
|
||||
test_target_arch(sparc "" "-m32")
|
||||
test_target_arch(sparcv9 "" "-m64")
|
||||
elseif("${COMPILER_RT_DEFAULT_TARGET_ARCH}" MATCHES "mipsel|mips64el")
|
||||
# Gcc doesn't accept -m32/-m64 so we do the next best thing and use
|
||||
# -mips32r2/-mips64r2. We don't use -mips1/-mips3 because we want to match
|
||||
# clang's default CPU's. In the 64-bit case, we must also specify the ABI
|
||||
# since the default ABI differs between gcc and clang.
|
||||
# FIXME: Ideally, we would build the N32 library too.
|
||||
test_target_arch(mipsel "" "-mips32r2" "-mabi=32" "-D_LARGEFILE_SOURCE" "-D_FILE_OFFSET_BITS=64")
|
||||
test_target_arch(mips64el "" "-mips64r2" "-mabi=64")
|
||||
elseif("${COMPILER_RT_DEFAULT_TARGET_ARCH}" MATCHES "mips")
|
||||
test_target_arch(mips "" "-mips32r2" "-mabi=32" "-D_LARGEFILE_SOURCE" "-D_FILE_OFFSET_BITS=64")
|
||||
test_target_arch(mips64 "" "-mips64r2" "-mabi=64")
|
||||
# FIXME: Ideally, we would build the N32 library too.
|
||||
if("${COMPILER_RT_MIPS_EL}" AND ("${COMPILER_RT_MIPS32R6}" OR "${COMPILER_RT_MIPS64R6}"))
|
||||
test_target_arch(mipsel "" "-mips32r6" "-mabi=32" "-D_LARGEFILE_SOURCE" "-D_FILE_OFFSET_BITS=64")
|
||||
test_target_arch(mips64el "" "-mips64r6" "-mabi=64")
|
||||
elseif("${COMPILER_RT_MIPS_EL}")
|
||||
test_target_arch(mipsel "" "-mips32r2" "-mabi=32" "-D_LARGEFILE_SOURCE" "-D_FILE_OFFSET_BITS=64")
|
||||
test_target_arch(mips64el "" "-mips64r2" "-mabi=64")
|
||||
elseif("${COMPILER_RT_MIPS32R6}" OR "${COMPILER_RT_MIPS64R6}")
|
||||
test_target_arch(mips "" "-mips32r6" "-mabi=32" "-D_LARGEFILE_SOURCE" "-D_FILE_OFFSET_BITS=64")
|
||||
test_target_arch(mips64 "" "-mips64r6" "-mabi=64")
|
||||
else()
|
||||
test_target_arch(mips "" "-mips32r2" "-mabi=32" "-D_LARGEFILE_SOURCE" "-D_FILE_OFFSET_BITS=64")
|
||||
test_target_arch(mips64 "" "-mips64r2" "-mabi=64")
|
||||
endif()
|
||||
elseif("${COMPILER_RT_DEFAULT_TARGET_ARCH}" MATCHES "arm")
|
||||
if(WIN32)
|
||||
test_target_arch(arm "" "" "")
|
||||
else()
|
||||
test_target_arch(armv4t "" "-march=armv4t" "-mfloat-abi=soft")
|
||||
test_target_arch(armv6m "" "-march=armv6m" "-mfloat-abi=soft")
|
||||
test_target_arch(arm "" "-march=armv7-a" "-mfloat-abi=soft")
|
||||
test_target_arch(armhf "" "-march=armv7-a" "-mfloat-abi=hard")
|
||||
test_target_arch(armv6m "" "-march=armv6m" "-mfloat-abi=soft")
|
||||
endif()
|
||||
elseif("${COMPILER_RT_DEFAULT_TARGET_ARCH}" MATCHES "avr")
|
||||
test_target_arch(avr "__AVR__" "--target=avr")
|
||||
elseif("${COMPILER_RT_DEFAULT_TARGET_ARCH}" MATCHES "aarch32")
|
||||
test_target_arch(aarch32 "" "-march=armv8-a")
|
||||
elseif("${COMPILER_RT_DEFAULT_TARGET_ARCH}" MATCHES "aarch64")
|
||||
|
|
|
@ -10,7 +10,8 @@ builtin_check_c_compiler_flag(-fPIE COMPILER_RT_HAS_FPIE_FLAG)
|
|||
builtin_check_c_compiler_flag(-fno-builtin COMPILER_RT_HAS_FNO_BUILTIN_FLAG)
|
||||
builtin_check_c_compiler_flag(-std=c11 COMPILER_RT_HAS_STD_C11_FLAG)
|
||||
builtin_check_c_compiler_flag(-fvisibility=hidden COMPILER_RT_HAS_VISIBILITY_HIDDEN_FLAG)
|
||||
builtin_check_c_compiler_flag(-ffreestanding COMPILER_RT_HAS_FREESTANDING_FLAG)
|
||||
builtin_check_c_compiler_flag(-fomit-frame-pointer COMPILER_RT_HAS_OMIT_FRAME_POINTER_FLAG)
|
||||
builtin_check_c_compiler_flag(-ffreestanding COMPILER_RT_HAS_FFREESTANDING_FLAG)
|
||||
builtin_check_c_compiler_flag(-fxray-instrument COMPILER_RT_HAS_XRAY_COMPILER_FLAG)
|
||||
|
||||
builtin_check_c_compiler_source(COMPILER_RT_HAS_ATOMIC_KEYWORD
|
||||
|
@ -21,14 +22,6 @@ int foo(int x, int y) {
|
|||
}
|
||||
")
|
||||
|
||||
builtin_check_c_compiler_source(COMPILER_RT_HAS_FLOAT16
|
||||
"
|
||||
_Float16 foo(_Float16 x) {
|
||||
return x;
|
||||
}
|
||||
"
|
||||
)
|
||||
|
||||
builtin_check_c_compiler_source(COMPILER_RT_HAS_ASM_LSE
|
||||
"
|
||||
asm(\".arch armv8-a+lse\");
|
||||
|
@ -36,13 +29,15 @@ asm(\"cas w0, w1, [x2]\");
|
|||
")
|
||||
|
||||
set(ARM64 aarch64)
|
||||
set(ARM32 arm armhf armv6m armv7m armv7em armv7 armv7s armv7k armv8m.main armv8.1m.main)
|
||||
set(ARM32 arm armhf armv4t armv5te armv6 armv6m armv7m armv7em armv7 armv7s armv7k armv8m.main armv8.1m.main)
|
||||
set(AVR avr)
|
||||
set(HEXAGON hexagon)
|
||||
set(X86 i386)
|
||||
set(X86_64 x86_64)
|
||||
set(LOONGARCH64 loongarch64)
|
||||
set(MIPS32 mips mipsel)
|
||||
set(MIPS64 mips64 mips64el)
|
||||
set(PPC32 powerpc)
|
||||
set(PPC32 powerpc powerpcspe)
|
||||
set(PPC64 powerpc64 powerpc64le)
|
||||
set(RISCV32 riscv32)
|
||||
set(RISCV64 riscv64)
|
||||
|
@ -59,10 +54,10 @@ if(APPLE)
|
|||
endif()
|
||||
|
||||
set(ALL_BUILTIN_SUPPORTED_ARCH
|
||||
${X86} ${X86_64} ${ARM32} ${ARM64}
|
||||
${X86} ${X86_64} ${ARM32} ${ARM64} ${AVR}
|
||||
${HEXAGON} ${MIPS32} ${MIPS64} ${PPC32} ${PPC64}
|
||||
${RISCV32} ${RISCV64} ${SPARC} ${SPARCV9}
|
||||
${WASM32} ${WASM64} ${VE})
|
||||
${WASM32} ${WASM64} ${VE} ${LOONGARCH64})
|
||||
|
||||
include(CompilerRTUtils)
|
||||
include(CompilerRTDarwinUtils)
|
||||
|
@ -82,7 +77,8 @@ if(APPLE)
|
|||
execute_process(COMMAND
|
||||
/usr/libexec/PlistBuddy -c "Print :SupportedTargets:${os}:Archs" ${sdk_path}/SDKSettings.plist
|
||||
OUTPUT_VARIABLE SDK_SUPPORTED_ARCHS
|
||||
RESULT_VARIABLE PLIST_ERROR)
|
||||
RESULT_VARIABLE PLIST_ERROR
|
||||
ERROR_QUIET)
|
||||
if (PLIST_ERROR EQUAL 0 AND
|
||||
SDK_SUPPORTED_ARCHS MATCHES " ${arch}\n")
|
||||
message(STATUS "Found ${arch} support in ${sdk_path}/SDKSettings.plist")
|
||||
|
@ -94,7 +90,7 @@ if(APPLE)
|
|||
endfunction()
|
||||
|
||||
set(DARWIN_EMBEDDED_PLATFORMS)
|
||||
set(DARWIN_osx_BUILTIN_MIN_VER 10.5)
|
||||
set(DARWIN_osx_BUILTIN_MIN_VER 10.7)
|
||||
set(DARWIN_osx_BUILTIN_MIN_VER_FLAG
|
||||
-mmacosx-version-min=${DARWIN_osx_BUILTIN_MIN_VER})
|
||||
set(DARWIN_osx_BUILTIN_ALL_POSSIBLE_ARCHS ${X86} ${X86_64})
|
||||
|
@ -114,6 +110,10 @@ if(APPLE)
|
|||
${DARWIN_ios_MIN_VER_FLAG}=${DARWIN_ios_BUILTIN_MIN_VER})
|
||||
set(DARWIN_ios_BUILTIN_ALL_POSSIBLE_ARCHS ${ARM64} ${ARM32})
|
||||
set(DARWIN_iossim_BUILTIN_ALL_POSSIBLE_ARCHS ${X86} ${X86_64})
|
||||
find_darwin_sdk_version(iossim_sdk_version "iphonesimulator")
|
||||
if ("${iossim_sdk_version}" VERSION_GREATER 14.0 OR "${iossim_sdk_version}" VERSION_EQUAL 14.0)
|
||||
list(APPEND DARWIN_iossim_BUILTIN_ALL_POSSIBLE_ARCHS arm64)
|
||||
endif()
|
||||
endif()
|
||||
if(COMPILER_RT_ENABLE_WATCHOS)
|
||||
list(APPEND DARWIN_EMBEDDED_PLATFORMS watchos)
|
||||
|
@ -123,6 +123,10 @@ if(APPLE)
|
|||
${DARWIN_watchos_MIN_VER_FLAG}=${DARWIN_watchos_BUILTIN_MIN_VER})
|
||||
set(DARWIN_watchos_BUILTIN_ALL_POSSIBLE_ARCHS armv7 armv7k arm64_32)
|
||||
set(DARWIN_watchossim_BUILTIN_ALL_POSSIBLE_ARCHS ${X86})
|
||||
find_darwin_sdk_version(watchossim_sdk_version "watchsimulator")
|
||||
if ("${watchossim_sdk_version}" VERSION_GREATER 7.0 OR "${watchossim_sdk_version}" VERSION_EQUAL 7.0)
|
||||
list(APPEND DARWIN_watchossim_BUILTIN_ALL_POSSIBLE_ARCHS arm64)
|
||||
endif()
|
||||
endif()
|
||||
if(COMPILER_RT_ENABLE_TVOS)
|
||||
list(APPEND DARWIN_EMBEDDED_PLATFORMS tvos)
|
||||
|
@ -132,6 +136,10 @@ if(APPLE)
|
|||
${DARWIN_tvos_MIN_VER_FLAG}=${DARWIN_tvos_BUILTIN_MIN_VER})
|
||||
set(DARWIN_tvos_BUILTIN_ALL_POSSIBLE_ARCHS armv7 arm64)
|
||||
set(DARWIN_tvossim_BUILTIN_ALL_POSSIBLE_ARCHS ${X86} ${X86_64})
|
||||
find_darwin_sdk_version(tvossim_sdk_version "appletvsimulator")
|
||||
if ("${tvossim_sdk_version}" VERSION_GREATER 14.0 OR "${tvossim_sdk_version}" VERSION_EQUAL 14.0)
|
||||
list(APPEND DARWIN_tvossim_BUILTIN_ALL_POSSIBLE_ARCHS arm64)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
set(BUILTIN_SUPPORTED_OS osx)
|
||||
|
|
|
@ -1,22 +1,30 @@
|
|||
include(CMakePushCheckState)
|
||||
include(LLVMCheckCompilerLinkerFlag)
|
||||
include(CheckCCompilerFlag)
|
||||
include(CheckCXXCompilerFlag)
|
||||
include(CheckIncludeFiles)
|
||||
include(CheckLibraryExists)
|
||||
include(LLVMCheckCompilerLinkerFlag)
|
||||
include(CheckSymbolExists)
|
||||
include(TestBigEndian)
|
||||
|
||||
function(compiler_rt_check_linker_flag flag out_var)
|
||||
cmake_push_check_state()
|
||||
set(CMAKE_REQUIRED_FLAGS "${CMAKE_REQUIRED_FLAGS} ${flag}")
|
||||
check_cxx_compiler_flag("" ${out_var})
|
||||
cmake_pop_check_state()
|
||||
endfunction()
|
||||
# The compiler driver may be implicitly trying to link against libunwind.
|
||||
# This is normally ok (libcxx relies on an unwinder), but if libunwind is
|
||||
# built in the same cmake invocation as compiler-rt and we're using the
|
||||
# in tree version of runtimes, we'd be linking against the just-built
|
||||
# libunwind (and the compiler implicit -lunwind wouldn't succeed as the newly
|
||||
# built libunwind isn't installed yet). For those cases, it'd be good to
|
||||
# link with --uwnindlib=none. Check if that option works.
|
||||
llvm_check_compiler_linker_flag(C "--unwindlib=none" CXX_SUPPORTS_UNWINDLIB_NONE_FLAG)
|
||||
|
||||
check_library_exists(c fopen "" COMPILER_RT_HAS_LIBC)
|
||||
if (COMPILER_RT_USE_BUILTINS_LIBRARY)
|
||||
include(HandleCompilerRT)
|
||||
find_compiler_rt_library(builtins "" COMPILER_RT_BUILTINS_LIBRARY)
|
||||
find_compiler_rt_library(builtins COMPILER_RT_BUILTINS_LIBRARY
|
||||
FLAGS ${SANITIZER_COMMON_FLAGS})
|
||||
# TODO(PR51389): We should check COMPILER_RT_BUILTINS_LIBRARY and report an
|
||||
# error if the value is NOTFOUND rather than silenty continuing but we first
|
||||
# need to fix find_compiler_rt_library on Darwin.
|
||||
else()
|
||||
if (ANDROID)
|
||||
check_library_exists(gcc __gcc_personality_v0 "" COMPILER_RT_HAS_GCC_LIB)
|
||||
|
@ -25,14 +33,17 @@ else()
|
|||
endif()
|
||||
endif()
|
||||
|
||||
check_c_compiler_flag(-nodefaultlibs COMPILER_RT_HAS_NODEFAULTLIBS_FLAG)
|
||||
if (COMPILER_RT_HAS_NODEFAULTLIBS_FLAG)
|
||||
check_c_compiler_flag(-nodefaultlibs C_SUPPORTS_NODEFAULTLIBS_FLAG)
|
||||
if (C_SUPPORTS_NODEFAULTLIBS_FLAG)
|
||||
set(CMAKE_REQUIRED_FLAGS "${CMAKE_REQUIRED_FLAGS} -nodefaultlibs")
|
||||
if (COMPILER_RT_HAS_LIBC)
|
||||
list(APPEND CMAKE_REQUIRED_LIBRARIES c)
|
||||
endif ()
|
||||
if (COMPILER_RT_USE_BUILTINS_LIBRARY)
|
||||
list(APPEND CMAKE_REQUIRED_LIBRARIES "${COMPILER_RT_BUILTINS_LIBRARY}")
|
||||
# TODO: remote this check once we address PR51389.
|
||||
if (${COMPILER_RT_BUILTINS_LIBRARY})
|
||||
list(APPEND CMAKE_REQUIRED_LIBRARIES "${COMPILER_RT_BUILTINS_LIBRARY}")
|
||||
endif()
|
||||
elseif (COMPILER_RT_HAS_GCC_S_LIB)
|
||||
list(APPEND CMAKE_REQUIRED_LIBRARIES gcc_s)
|
||||
elseif (COMPILER_RT_HAS_GCC_LIB)
|
||||
|
@ -57,6 +68,7 @@ endif ()
|
|||
check_c_compiler_flag(-ffreestanding COMPILER_RT_HAS_FFREESTANDING_FLAG)
|
||||
check_c_compiler_flag(-fomit-frame-pointer COMPILER_RT_HAS_OMIT_FRAME_POINTER_FLAG)
|
||||
check_c_compiler_flag(-std=c11 COMPILER_RT_HAS_STD_C11_FLAG)
|
||||
check_c_compiler_flag(-fcf-protection=full COMPILER_RT_HAS_FCF_PROTECTION_FLAG)
|
||||
check_cxx_compiler_flag(-fPIC COMPILER_RT_HAS_FPIC_FLAG)
|
||||
check_cxx_compiler_flag(-fPIE COMPILER_RT_HAS_FPIE_FLAG)
|
||||
check_cxx_compiler_flag(-fno-builtin COMPILER_RT_HAS_FNO_BUILTIN_FLAG)
|
||||
|
@ -69,17 +81,19 @@ check_cxx_compiler_flag(-fvisibility=hidden COMPILER_RT_HAS_FVISIBILITY_HIDDEN_
|
|||
check_cxx_compiler_flag(-frtti COMPILER_RT_HAS_FRTTI_FLAG)
|
||||
check_cxx_compiler_flag(-fno-rtti COMPILER_RT_HAS_FNO_RTTI_FLAG)
|
||||
check_cxx_compiler_flag("-Werror -fno-function-sections" COMPILER_RT_HAS_FNO_FUNCTION_SECTIONS_FLAG)
|
||||
check_cxx_compiler_flag(-std=c++14 COMPILER_RT_HAS_STD_CXX14_FLAG)
|
||||
check_cxx_compiler_flag(-ftls-model=initial-exec COMPILER_RT_HAS_FTLS_MODEL_INITIAL_EXEC)
|
||||
check_cxx_compiler_flag(-fno-lto COMPILER_RT_HAS_FNO_LTO_FLAG)
|
||||
check_cxx_compiler_flag(-fno-profile-generate COMPILER_RT_HAS_FNO_PROFILE_GENERATE_FLAG)
|
||||
check_cxx_compiler_flag(-fno-profile-instr-generate COMPILER_RT_HAS_FNO_PROFILE_INSTR_GENERATE_FLAG)
|
||||
check_cxx_compiler_flag(-fno-profile-instr-use COMPILER_RT_HAS_FNO_PROFILE_INSTR_USE_FLAG)
|
||||
check_cxx_compiler_flag(-fno-coverage-mapping COMPILER_RT_HAS_FNO_COVERAGE_MAPPING_FLAG)
|
||||
check_cxx_compiler_flag("-Werror -mcrc32" COMPILER_RT_HAS_MCRC32_FLAG)
|
||||
check_cxx_compiler_flag("-Werror -msse3" COMPILER_RT_HAS_MSSE3_FLAG)
|
||||
check_cxx_compiler_flag("-Werror -msse4.2" COMPILER_RT_HAS_MSSE4_2_FLAG)
|
||||
check_cxx_compiler_flag(--sysroot=. COMPILER_RT_HAS_SYSROOT_FLAG)
|
||||
check_cxx_compiler_flag("-Werror -mcrc" COMPILER_RT_HAS_MCRC_FLAG)
|
||||
check_cxx_compiler_flag(-fno-partial-inlining COMPILER_RT_HAS_FNO_PARTIAL_INLINING_FLAG)
|
||||
check_cxx_compiler_flag(-Werror -ftrivial-auto-var-init=pattern COMPILER_RT_HAS_TRIVIAL_AUTO_INIT)
|
||||
|
||||
if(NOT WIN32 AND NOT CYGWIN)
|
||||
# MinGW warns if -fvisibility-inlines-hidden is used.
|
||||
|
@ -108,17 +122,41 @@ check_cxx_compiler_flag("-Werror -Wvariadic-macros" COMPILER_RT_HAS_WVARIADIC
|
|||
check_cxx_compiler_flag("-Werror -Wunused-parameter" COMPILER_RT_HAS_WUNUSED_PARAMETER_FLAG)
|
||||
check_cxx_compiler_flag("-Werror -Wcovered-switch-default" COMPILER_RT_HAS_WCOVERED_SWITCH_DEFAULT_FLAG)
|
||||
check_cxx_compiler_flag("-Werror -Wsuggest-override" COMPILER_RT_HAS_WSUGGEST_OVERRIDE_FLAG)
|
||||
check_cxx_compiler_flag("-Werror -Wthread-safety" COMPILER_RT_HAS_WTHREAD_SAFETY_FLAG)
|
||||
check_cxx_compiler_flag("-Werror -Wthread-safety-reference" COMPILER_RT_HAS_WTHREAD_SAFETY_REFERENCE_FLAG)
|
||||
check_cxx_compiler_flag("-Werror -Wthread-safety-beta" COMPILER_RT_HAS_WTHREAD_SAFETY_BETA_FLAG)
|
||||
check_cxx_compiler_flag(-Wno-pedantic COMPILER_RT_HAS_WNO_PEDANTIC)
|
||||
check_cxx_compiler_flag(-Wno-format COMPILER_RT_HAS_WNO_FORMAT)
|
||||
check_cxx_compiler_flag(-Wno-format-pedantic COMPILER_RT_HAS_WNO_FORMAT_PEDANTIC)
|
||||
|
||||
check_cxx_compiler_flag("/experimental:external /external:W0" COMPILER_RT_HAS_EXTERNAL_FLAG)
|
||||
|
||||
check_cxx_compiler_flag(/W4 COMPILER_RT_HAS_W4_FLAG)
|
||||
check_cxx_compiler_flag(/WX COMPILER_RT_HAS_WX_FLAG)
|
||||
check_cxx_compiler_flag(/wd4146 COMPILER_RT_HAS_WD4146_FLAG)
|
||||
check_cxx_compiler_flag(/wd4206 COMPILER_RT_HAS_WD4206_FLAG)
|
||||
check_cxx_compiler_flag(/wd4291 COMPILER_RT_HAS_WD4291_FLAG)
|
||||
check_cxx_compiler_flag(/wd4221 COMPILER_RT_HAS_WD4221_FLAG)
|
||||
check_cxx_compiler_flag(/wd4391 COMPILER_RT_HAS_WD4391_FLAG)
|
||||
check_cxx_compiler_flag(/wd4722 COMPILER_RT_HAS_WD4722_FLAG)
|
||||
check_cxx_compiler_flag(/wd4800 COMPILER_RT_HAS_WD4800_FLAG)
|
||||
|
||||
check_cxx_compiler_flag(-Werror -Warray-bounds COMPILER_RT_HAS_ARRAY_BOUNDS_FLAG)
|
||||
check_cxx_compiler_flag(-Werror -Wuninitialized COMPILER_RT_HAS_UNINITIALIZED_FLAG)
|
||||
check_cxx_compiler_flag(-Werror -Wshadow COMPILER_RT_HAS_SHADOW_FLAG)
|
||||
check_cxx_compiler_flag(-Werror -Wempty-body COMPILER_RT_HAS_EMPTY_BODY_FLAG)
|
||||
check_cxx_compiler_flag(-Werror -Wsizeof-pointer-memaccess COMPILER_RT_HAS_SIZEOF_POINTER_MEMACCESS_FLAG)
|
||||
check_cxx_compiler_flag(-Werror -Wsizeof-array-argument COMPILER_RT_HAS_SIZEOF_ARRAY_ARGUMENT_FLAG)
|
||||
check_cxx_compiler_flag(-Werror -Wsuspicious-memaccess COMPILER_RT_HAS_SUSPICIOUS_MEMACCESS_FLAG)
|
||||
check_cxx_compiler_flag(-Werror -Wbuiltin-memcpy-chk-size COMPILER_RT_HAS_BUILTIN_MEMCPY_CHK_SIZE_FLAG)
|
||||
check_cxx_compiler_flag(-Werror -Warray-bounds-pointer-arithmetic COMPILER_RT_HAS_ARRAY_BOUNDS_POINTER_ARITHMETIC_FLAG)
|
||||
check_cxx_compiler_flag(-Werror -Wreturn-stack-address COMPILER_RT_HAS_RETURN_STACK_ADDRESS_FLAG)
|
||||
check_cxx_compiler_flag(-Werror -Wsizeof-array-decay COMPILER_RT_HAS_SIZEOF_ARRAY_DECAY_FLAG)
|
||||
check_cxx_compiler_flag(-Werror -Wformat-insufficient-args COMPILER_RT_HAS_FORMAT_INSUFFICIENT_ARGS_FLAG)
|
||||
check_cxx_compiler_flag(-Werror -Wformat-security COMPILER_RT_HAS_BUILTIN_FORMAL_SECURITY_FLAG)
|
||||
check_cxx_compiler_flag(-Werror -Wsizeof-array-div COMPILER_RT_HAS_SIZEOF_ARRAY_DIV_FLAG)
|
||||
check_cxx_compiler_flag(-Werror -Wsizeof-pointer-div COMPILER_RT_HAS_SIZEOF_POINTER_DIV_FLAG)
|
||||
|
||||
# Symbols.
|
||||
check_symbol_exists(__func__ "" COMPILER_RT_HAS_FUNC_SYMBOL)
|
||||
|
||||
|
@ -157,11 +195,13 @@ check_library_exists(c++ __cxa_throw "" COMPILER_RT_HAS_LIBCXX)
|
|||
check_library_exists(stdc++ __cxa_throw "" COMPILER_RT_HAS_LIBSTDCXX)
|
||||
|
||||
# Linker flags.
|
||||
compiler_rt_check_linker_flag("-Wl,-z,text" COMPILER_RT_HAS_Z_TEXT)
|
||||
compiler_rt_check_linker_flag("-fuse-ld=lld" COMPILER_RT_HAS_FUSE_LD_LLD_FLAG)
|
||||
llvm_check_compiler_linker_flag(C "-Wl,-z,text" COMPILER_RT_HAS_Z_TEXT)
|
||||
llvm_check_compiler_linker_flag(C "-fuse-ld=lld" COMPILER_RT_HAS_FUSE_LD_LLD_FLAG)
|
||||
|
||||
set(VERS_COMPAT_OPTION "-Wl,-z,gnu-version-script-compat")
|
||||
compiler_rt_check_linker_flag("${VERS_COMPAT_OPTION}" COMPILER_RT_HAS_GNU_VERSION_SCRIPT_COMPAT)
|
||||
if(${CMAKE_SYSTEM_NAME} MATCHES "SunOS")
|
||||
set(VERS_COMPAT_OPTION "-Wl,-z,gnu-version-script-compat")
|
||||
llvm_check_compiler_linker_flag(C "${VERS_COMPAT_OPTION}" COMPILER_RT_HAS_GNU_VERSION_SCRIPT_COMPAT)
|
||||
endif()
|
||||
|
||||
set(DUMMY_VERS ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeTmp/dummy.vers)
|
||||
file(WRITE ${DUMMY_VERS} "{};")
|
||||
|
@ -171,10 +211,10 @@ if(COMPILER_RT_HAS_GNU_VERSION_SCRIPT_COMPAT)
|
|||
# -z gnu-version-script-compat.
|
||||
string(APPEND VERS_OPTION " ${VERS_COMPAT_OPTION}")
|
||||
endif()
|
||||
compiler_rt_check_linker_flag("${VERS_OPTION}" COMPILER_RT_HAS_VERSION_SCRIPT)
|
||||
llvm_check_compiler_linker_flag(C "${VERS_OPTION}" COMPILER_RT_HAS_VERSION_SCRIPT)
|
||||
|
||||
if(ANDROID)
|
||||
compiler_rt_check_linker_flag("-Wl,-z,global" COMPILER_RT_HAS_Z_GLOBAL)
|
||||
llvm_check_compiler_linker_flag(C "-Wl,-z,global" COMPILER_RT_HAS_Z_GLOBAL)
|
||||
check_library_exists(log __android_log_write "" COMPILER_RT_HAS_LIBLOG)
|
||||
endif()
|
||||
|
||||
|
@ -188,12 +228,14 @@ set(COMPILER_RT_SUPPORTED_ARCH)
|
|||
# runtime libraries supported by our current compilers cross-compiling
|
||||
# abilities.
|
||||
set(SIMPLE_SOURCE ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/simple.cc)
|
||||
file(WRITE ${SIMPLE_SOURCE} "#include <stdlib.h>\n#include <stdio.h>\nint main() { printf(\"hello, world\"); }\n")
|
||||
file(WRITE ${SIMPLE_SOURCE} "#include <stdlib.h>\n#include <stdio.h>\nint main(void) { printf(\"hello, world\"); }\n")
|
||||
|
||||
# Detect whether the current target platform is 32-bit or 64-bit, and setup
|
||||
# the correct commandline flags needed to attempt to target 32-bit and 64-bit.
|
||||
# AVR and MSP430 are omitted since they have 16-bit pointers.
|
||||
if (NOT CMAKE_SIZEOF_VOID_P EQUAL 4 AND
|
||||
NOT CMAKE_SIZEOF_VOID_P EQUAL 8)
|
||||
NOT CMAKE_SIZEOF_VOID_P EQUAL 8 AND
|
||||
NOT ${arch} MATCHES "avr|msp430")
|
||||
message(FATAL_ERROR "Please use architecture with 4 or 8 byte pointers.")
|
||||
endif()
|
||||
|
||||
|
@ -216,11 +258,27 @@ function(get_target_flags_for_arch arch out_var)
|
|||
endif()
|
||||
endfunction()
|
||||
|
||||
# Returns a list of architecture specific target ldflags in @out_var list.
|
||||
function(get_target_link_flags_for_arch arch out_var)
|
||||
list(FIND COMPILER_RT_SUPPORTED_ARCH ${arch} ARCH_INDEX)
|
||||
if(ARCH_INDEX EQUAL -1)
|
||||
message(FATAL_ERROR "Unsupported architecture: ${arch}")
|
||||
else()
|
||||
# Workaround for direct calls to __tls_get_addr on Solaris/amd64.
|
||||
if(OS_NAME MATCHES "SunOS" AND ${arch} MATCHES x86_64)
|
||||
set(${out_var} "-Wl,-z,relax=transtls" PARENT_SCOPE)
|
||||
endif()
|
||||
endif()
|
||||
endfunction()
|
||||
|
||||
# Returns a compiler and CFLAGS that should be used to run tests for the
|
||||
# specific architecture. When cross-compiling, this is controled via
|
||||
# COMPILER_RT_TEST_COMPILER and COMPILER_RT_TEST_COMPILER_CFLAGS.
|
||||
macro(get_test_cc_for_arch arch cc_out cflags_out)
|
||||
if(ANDROID OR ${arch} MATCHES "arm|aarch64|riscv32|riscv64")
|
||||
if (NOT ${ARGC} EQUAL 3)
|
||||
message(FATAL_ERROR "got too many args. expected 3, got ${ARGC} (namely: ${ARGV})")
|
||||
endif()
|
||||
if(ANDROID OR (NOT APPLE AND ${arch} MATCHES "arm|aarch64|riscv32|riscv64"))
|
||||
# This is only true if we are cross-compiling.
|
||||
# Build all tests with host compiler and use host tools.
|
||||
set(${cc_out} ${COMPILER_RT_TEST_COMPILER})
|
||||
|
@ -243,7 +301,35 @@ function(get_test_cflags_for_apple_platform platform arch cflags_out)
|
|||
endif()
|
||||
set(test_cflags "")
|
||||
get_target_flags_for_arch(${arch} test_cflags)
|
||||
list(APPEND test_cflags ${DARWIN_${platform}_CFLAGS})
|
||||
|
||||
if (NOT "${arch}" STREQUAL "arm64e")
|
||||
list(APPEND test_cflags ${DARWIN_${platform}_CFLAGS})
|
||||
else()
|
||||
# arm64e is not currently ABI stable so we need to build for the
|
||||
# OS version being tested. Rather than querying the device under test
|
||||
# we use the SDK version which "should" be the same as the
|
||||
# device under test (it is a configuration error for these not to match).
|
||||
# FIXME(dliew): We can remove this if we build the runtimes with the appropriate
|
||||
# deployment target for arm64e.
|
||||
foreach (flag ${DARWIN_${platform}_CFLAGS})
|
||||
if ("${flag}" MATCHES "^${DARWIN_${platform}_MIN_VER_FLAG}=.+")
|
||||
# Find the SDK version
|
||||
get_xcrun_platform_from_apple_platform("${platform}" xcrun_platform_name)
|
||||
# TODO(dliew): Remove this check once get_xcrun_platform_from_apple_platform
|
||||
# emits a fatal error for unrecognised platforms.
|
||||
if (NOT "${xcrun_platform_name}" STREQUAL "")
|
||||
find_darwin_sdk_version(platform_sdk_version "${xcrun_platform_name}")
|
||||
# Patch flag with correct deployment target
|
||||
set(replacement_flag "${DARWIN_${platform}_MIN_VER_FLAG}=${platform_sdk_version}")
|
||||
list(APPEND test_cflags "${replacement_flag}")
|
||||
endif()
|
||||
else()
|
||||
# Copy through
|
||||
list(APPEND test_cflags "${flag}")
|
||||
endif()
|
||||
endforeach()
|
||||
endif()
|
||||
|
||||
string(REPLACE ";" " " test_cflags_str "${test_cflags}")
|
||||
string(APPEND test_cflags_str "${COMPILER_RT_TEST_COMPILER_CFLAGS}")
|
||||
set(${cflags_out} "${test_cflags_str}" PARENT_SCOPE)
|
||||
|
@ -272,81 +358,32 @@ function(is_valid_apple_platform platform is_valid_out)
|
|||
set(${is_valid_out} ${is_valid} PARENT_SCOPE)
|
||||
endfunction()
|
||||
|
||||
set(ARM64 aarch64)
|
||||
set(ARM32 arm armhf)
|
||||
set(HEXAGON hexagon)
|
||||
set(X86 i386)
|
||||
set(X86_64 x86_64)
|
||||
set(MIPS32 mips mipsel)
|
||||
set(MIPS64 mips64 mips64el)
|
||||
set(PPC32 powerpc)
|
||||
set(PPC64 powerpc64 powerpc64le)
|
||||
set(RISCV32 riscv32)
|
||||
set(RISCV64 riscv64)
|
||||
set(S390X s390x)
|
||||
set(SPARC sparc)
|
||||
set(SPARCV9 sparcv9)
|
||||
set(WASM32 wasm32)
|
||||
set(WASM64 wasm64)
|
||||
set(VE ve)
|
||||
# Maps the Apple platform name used in Compiler-rt's CMake code
|
||||
# to the name recognised by xcrun's `--sdk` argument
|
||||
function(get_xcrun_platform_from_apple_platform platform out_var)
|
||||
set(xcrun_platform "")
|
||||
if ("${platform}" STREQUAL "osx")
|
||||
set(xcrun_platform "macosx")
|
||||
elseif ("${platform}" STREQUAL "iossim")
|
||||
set(xcrun_platform "iphonesimulator")
|
||||
elseif ("${platform}" STREQUAL "ios")
|
||||
set(xcrun_platform "iphoneos")
|
||||
elseif ("${platform}" STREQUAL "watchossim")
|
||||
set(xcrun_platform "watchsimulator")
|
||||
elseif ("${platform}" STREQUAL "watchos")
|
||||
set(xcrun_platform "watchos")
|
||||
elseif ("${platform}" STREQUAL "tvossim")
|
||||
set(xcrun_platform "appletvsimulator")
|
||||
elseif ("${platform}" STREQUAL "tvos")
|
||||
set(xcrun_platform "appletvos")
|
||||
else()
|
||||
# TODO(dliew): Make this an error.
|
||||
message(WARNING "\"${platform}\" is not a handled apple platform")
|
||||
endif()
|
||||
set(${out_var} ${xcrun_platform} PARENT_SCOPE)
|
||||
endfunction()
|
||||
|
||||
if(APPLE)
|
||||
set(ARM64 arm64)
|
||||
set(ARM32 armv7 armv7s armv7k)
|
||||
set(X86_64 x86_64 x86_64h)
|
||||
endif()
|
||||
|
||||
set(ALL_SANITIZER_COMMON_SUPPORTED_ARCH ${X86} ${X86_64} ${PPC64} ${RISCV64}
|
||||
${ARM32} ${ARM64} ${MIPS32} ${MIPS64} ${S390X} ${SPARC} ${SPARCV9})
|
||||
set(ALL_ASAN_SUPPORTED_ARCH ${X86} ${X86_64} ${ARM32} ${ARM64} ${RISCV64}
|
||||
${MIPS32} ${MIPS64} ${PPC64} ${S390X} ${SPARC} ${SPARCV9})
|
||||
set(ALL_CRT_SUPPORTED_ARCH ${X86} ${X86_64} ${ARM32} ${ARM64} ${RISCV32} ${RISCV64} ${VE})
|
||||
set(ALL_DFSAN_SUPPORTED_ARCH ${X86_64} ${MIPS64} ${ARM64})
|
||||
|
||||
if(ANDROID)
|
||||
set(OS_NAME "Android")
|
||||
else()
|
||||
set(OS_NAME "${CMAKE_SYSTEM_NAME}")
|
||||
endif()
|
||||
|
||||
if(OS_NAME MATCHES "Linux")
|
||||
set(ALL_FUZZER_SUPPORTED_ARCH ${X86} ${X86_64} ${ARM64} ${S390X})
|
||||
elseif (OS_NAME MATCHES "Windows")
|
||||
set(ALL_FUZZER_SUPPORTED_ARCH ${X86} ${X86_64})
|
||||
elseif(OS_NAME MATCHES "Android")
|
||||
set(ALL_FUZZER_SUPPORTED_ARCH ${X86} ${X86_64} ${ARM32} ${ARM64})
|
||||
else()
|
||||
set(ALL_FUZZER_SUPPORTED_ARCH ${X86_64} ${ARM64})
|
||||
endif()
|
||||
|
||||
set(ALL_GWP_ASAN_SUPPORTED_ARCH ${X86} ${X86_64} ${ARM32} ${ARM64})
|
||||
if(APPLE)
|
||||
set(ALL_LSAN_SUPPORTED_ARCH ${X86} ${X86_64} ${MIPS64} ${ARM64})
|
||||
else()
|
||||
set(ALL_LSAN_SUPPORTED_ARCH ${X86} ${X86_64} ${MIPS64} ${ARM64} ${ARM32} ${PPC64} ${S390X} ${RISCV64})
|
||||
endif()
|
||||
set(ALL_MSAN_SUPPORTED_ARCH ${X86_64} ${MIPS64} ${ARM64} ${PPC64} ${S390X})
|
||||
set(ALL_HWASAN_SUPPORTED_ARCH ${X86_64} ${ARM64})
|
||||
set(ALL_MEMPROF_SUPPORTED_ARCH ${X86_64})
|
||||
set(ALL_PROFILE_SUPPORTED_ARCH ${X86} ${X86_64} ${ARM32} ${ARM64} ${PPC32} ${PPC64}
|
||||
${MIPS32} ${MIPS64} ${S390X} ${SPARC} ${SPARCV9})
|
||||
set(ALL_TSAN_SUPPORTED_ARCH ${X86_64} ${MIPS64} ${ARM64} ${PPC64} ${S390X})
|
||||
set(ALL_UBSAN_SUPPORTED_ARCH ${X86} ${X86_64} ${ARM32} ${ARM64} ${RISCV64}
|
||||
${MIPS32} ${MIPS64} ${PPC64} ${S390X} ${SPARC} ${SPARCV9})
|
||||
set(ALL_SAFESTACK_SUPPORTED_ARCH ${X86} ${X86_64} ${ARM64} ${MIPS32} ${MIPS64})
|
||||
set(ALL_CFI_SUPPORTED_ARCH ${X86} ${X86_64} ${ARM32} ${ARM64} ${MIPS64})
|
||||
set(ALL_SCUDO_SUPPORTED_ARCH ${X86} ${X86_64} ${ARM32} ${ARM64} ${MIPS32} ${MIPS64} ${PPC64})
|
||||
set(ALL_SCUDO_STANDALONE_SUPPORTED_ARCH ${X86} ${X86_64} ${ARM32} ${ARM64} ${MIPS32} ${MIPS64} ${PPC64})
|
||||
if(APPLE)
|
||||
set(ALL_XRAY_SUPPORTED_ARCH ${X86_64})
|
||||
else()
|
||||
set(ALL_XRAY_SUPPORTED_ARCH ${X86_64} ${ARM32} ${ARM64} ${MIPS32} ${MIPS64} powerpc64le)
|
||||
endif()
|
||||
set(ALL_SHADOWCALLSTACK_SUPPORTED_ARCH ${ARM64})
|
||||
|
||||
if (UNIX)
|
||||
set(ALL_ORC_SUPPORTED_ARCH ${X86_64})
|
||||
endif()
|
||||
include(AllSupportedArchDefs)
|
||||
|
||||
if(APPLE)
|
||||
include(CompilerRTDarwinUtils)
|
||||
|
@ -405,6 +442,9 @@ if(APPLE)
|
|||
set(XRAY_SUPPORTED_OS osx)
|
||||
set(FUZZER_SUPPORTED_OS osx)
|
||||
set(ORC_SUPPORTED_OS osx)
|
||||
set(UBSAN_SUPPORTED_OS osx)
|
||||
set(LSAN_SUPPORTED_OS osx)
|
||||
set(STATS_SUPPORTED_OS osx)
|
||||
|
||||
# Note: In order to target x86_64h on OS X the minimum deployment target must
|
||||
# be 10.8 or higher.
|
||||
|
@ -438,7 +478,7 @@ if(APPLE)
|
|||
-lc++
|
||||
-lc++abi)
|
||||
|
||||
compiler_rt_check_linker_flag("-fapplication-extension" COMPILER_RT_HAS_APP_EXTENSION)
|
||||
llvm_check_compiler_linker_flag(C "-fapplication-extension" COMPILER_RT_HAS_APP_EXTENSION)
|
||||
if(COMPILER_RT_HAS_APP_EXTENSION)
|
||||
list(APPEND DARWIN_COMMON_LINK_FLAGS "-fapplication-extension")
|
||||
endif()
|
||||
|
@ -490,6 +530,10 @@ if(APPLE)
|
|||
list(APPEND PROFILE_SUPPORTED_OS ${platform}sim)
|
||||
list(APPEND TSAN_SUPPORTED_OS ${platform}sim)
|
||||
list(APPEND FUZZER_SUPPORTED_OS ${platform}sim)
|
||||
list(APPEND ORC_SUPPORTED_OS ${platform}sim)
|
||||
list(APPEND UBSAN_SUPPORTED_OS ${platform}sim)
|
||||
list(APPEND LSAN_SUPPORTED_OS ${platform}sim)
|
||||
list(APPEND STATS_SUPPORTED_OS ${platform}sim)
|
||||
endif()
|
||||
foreach(arch ${DARWIN_${platform}sim_ARCHS})
|
||||
list(APPEND COMPILER_RT_SUPPORTED_ARCH ${arch})
|
||||
|
@ -520,6 +564,10 @@ if(APPLE)
|
|||
list(APPEND TSAN_SUPPORTED_OS ${platform})
|
||||
endif()
|
||||
list(APPEND FUZZER_SUPPORTED_OS ${platform})
|
||||
list(APPEND ORC_SUPPORTED_OS ${platform})
|
||||
list(APPEND UBSAN_SUPPORTED_OS ${platform})
|
||||
list(APPEND LSAN_SUPPORTED_OS ${platform})
|
||||
list(APPEND STATS_SUPPORTED_OS ${platform})
|
||||
endif()
|
||||
foreach(arch ${DARWIN_${platform}_ARCHS})
|
||||
list(APPEND COMPILER_RT_SUPPORTED_ARCH ${arch})
|
||||
|
@ -529,7 +577,7 @@ if(APPLE)
|
|||
endforeach()
|
||||
endif()
|
||||
|
||||
# Explictly disable unsupported Sanitizer configurations.
|
||||
# Explicitly disable unsupported Sanitizer configurations.
|
||||
list(REMOVE_ITEM FUZZER_SUPPORTED_OS "watchos")
|
||||
list(REMOVE_ITEM FUZZER_SUPPORTED_OS "watchossim")
|
||||
|
||||
|
@ -578,9 +626,6 @@ if(APPLE)
|
|||
list_intersect(CFI_SUPPORTED_ARCH
|
||||
ALL_CFI_SUPPORTED_ARCH
|
||||
SANITIZER_COMMON_SUPPORTED_ARCH)
|
||||
list_intersect(SCUDO_SUPPORTED_ARCH
|
||||
ALL_SCUDO_SUPPORTED_ARCH
|
||||
SANITIZER_COMMON_SUPPORTED_ARCH)
|
||||
list_intersect(SCUDO_STANDALONE_SUPPORTED_ARCH
|
||||
ALL_SCUDO_STANDALONE_SUPPORTED_ARCH
|
||||
SANITIZER_COMMON_SUPPORTED_ARCH)
|
||||
|
@ -598,7 +643,6 @@ if(APPLE)
|
|||
SANITIZER_COMMON_SUPPORTED_ARCH)
|
||||
|
||||
else()
|
||||
filter_available_targets(CRT_SUPPORTED_ARCH ${ALL_CRT_SUPPORTED_ARCH})
|
||||
# Architectures supported by compiler-rt libraries.
|
||||
filter_available_targets(SANITIZER_COMMON_SUPPORTED_ARCH
|
||||
${ALL_SANITIZER_COMMON_SUPPORTED_ARCH})
|
||||
|
@ -621,7 +665,6 @@ else()
|
|||
filter_available_targets(SAFESTACK_SUPPORTED_ARCH
|
||||
${ALL_SAFESTACK_SUPPORTED_ARCH})
|
||||
filter_available_targets(CFI_SUPPORTED_ARCH ${ALL_CFI_SUPPORTED_ARCH})
|
||||
filter_available_targets(SCUDO_SUPPORTED_ARCH ${ALL_SCUDO_SUPPORTED_ARCH})
|
||||
filter_available_targets(SCUDO_STANDALONE_SUPPORTED_ARCH ${ALL_SCUDO_STANDALONE_SUPPORTED_ARCH})
|
||||
filter_available_targets(XRAY_SUPPORTED_ARCH ${ALL_XRAY_SUPPORTED_ARCH})
|
||||
filter_available_targets(SHADOWCALLSTACK_SUPPORTED_ARCH
|
||||
|
@ -631,8 +674,19 @@ else()
|
|||
endif()
|
||||
|
||||
if (MSVC)
|
||||
# Allow setting clang-cl's /winsysroot flag.
|
||||
set(LLVM_WINSYSROOT "" CACHE STRING
|
||||
"If set, argument to clang-cl's /winsysroot")
|
||||
|
||||
if (LLVM_WINSYSROOT)
|
||||
set(MSVC_DIA_SDK_DIR "${LLVM_WINSYSROOT}/DIA SDK" CACHE PATH
|
||||
"Path to the DIA SDK")
|
||||
else()
|
||||
set(MSVC_DIA_SDK_DIR "$ENV{VSINSTALLDIR}DIA SDK" CACHE PATH
|
||||
"Path to the DIA SDK")
|
||||
endif()
|
||||
|
||||
# See if the DIA SDK is available and usable.
|
||||
set(MSVC_DIA_SDK_DIR "$ENV{VSINSTALLDIR}DIA SDK")
|
||||
if (IS_DIRECTORY ${MSVC_DIA_SDK_DIR})
|
||||
set(CAN_SYMBOLIZE 1)
|
||||
else()
|
||||
|
@ -650,7 +704,7 @@ if(COMPILER_RT_SUPPORTED_ARCH)
|
|||
endif()
|
||||
message(STATUS "Compiler-RT supported architectures: ${COMPILER_RT_SUPPORTED_ARCH}")
|
||||
|
||||
set(ALL_SANITIZERS asan;dfsan;msan;hwasan;tsan;safestack;cfi;scudo;ubsan_minimal;gwp_asan)
|
||||
set(ALL_SANITIZERS asan;dfsan;msan;hwasan;tsan;safestack;cfi;scudo_standalone;ubsan_minimal;gwp_asan)
|
||||
set(COMPILER_RT_SANITIZERS_TO_BUILD all CACHE STRING
|
||||
"sanitizers to build if supported on the target (all;${ALL_SANITIZERS})")
|
||||
list_replace(COMPILER_RT_SANITIZERS_TO_BUILD all "${ALL_SANITIZERS}")
|
||||
|
@ -684,12 +738,6 @@ endif()
|
|||
|
||||
# TODO: Add builtins support.
|
||||
|
||||
if (CRT_SUPPORTED_ARCH AND OS_NAME MATCHES "Linux" AND NOT LLVM_USE_SANITIZER)
|
||||
set(COMPILER_RT_HAS_CRT TRUE)
|
||||
else()
|
||||
set(COMPILER_RT_HAS_CRT FALSE)
|
||||
endif()
|
||||
|
||||
if (COMPILER_RT_HAS_SANITIZER_COMMON AND DFSAN_SUPPORTED_ARCH AND
|
||||
OS_NAME MATCHES "Linux")
|
||||
set(COMPILER_RT_HAS_DFSAN TRUE)
|
||||
|
@ -712,7 +760,7 @@ else()
|
|||
endif()
|
||||
|
||||
if (COMPILER_RT_HAS_SANITIZER_COMMON AND HWASAN_SUPPORTED_ARCH AND
|
||||
OS_NAME MATCHES "Linux|Android")
|
||||
OS_NAME MATCHES "Linux|Android|Fuchsia")
|
||||
set(COMPILER_RT_HAS_HWASAN TRUE)
|
||||
else()
|
||||
set(COMPILER_RT_HAS_HWASAN FALSE)
|
||||
|
@ -732,13 +780,24 @@ else()
|
|||
set(COMPILER_RT_HAS_PROFILE FALSE)
|
||||
endif()
|
||||
|
||||
if (COMPILER_RT_HAS_SANITIZER_COMMON AND TSAN_SUPPORTED_ARCH AND
|
||||
OS_NAME MATCHES "Darwin|Linux|FreeBSD|Android|NetBSD")
|
||||
set(COMPILER_RT_HAS_TSAN TRUE)
|
||||
if (COMPILER_RT_HAS_SANITIZER_COMMON AND TSAN_SUPPORTED_ARCH)
|
||||
if (OS_NAME MATCHES "Linux|Darwin|FreeBSD|NetBSD")
|
||||
set(COMPILER_RT_HAS_TSAN TRUE)
|
||||
elseif (OS_NAME MATCHES "Android" AND ANDROID_PLATFORM_LEVEL GREATER 23)
|
||||
set(COMPILER_RT_HAS_TSAN TRUE)
|
||||
else()
|
||||
set(COMPILER_RT_HAS_TSAN FALSE)
|
||||
endif()
|
||||
else()
|
||||
set(COMPILER_RT_HAS_TSAN FALSE)
|
||||
endif()
|
||||
|
||||
if (OS_NAME MATCHES "Linux|FreeBSD|Windows|NetBSD|SunOS")
|
||||
set(COMPILER_RT_TSAN_HAS_STATIC_RUNTIME TRUE)
|
||||
else()
|
||||
set(COMPILER_RT_TSAN_HAS_STATIC_RUNTIME FALSE)
|
||||
endif()
|
||||
|
||||
if (COMPILER_RT_HAS_SANITIZER_COMMON AND UBSAN_SUPPORTED_ARCH AND
|
||||
OS_NAME MATCHES "Darwin|Linux|FreeBSD|NetBSD|Windows|Android|Fuchsia|SunOS")
|
||||
set(COMPILER_RT_HAS_UBSAN TRUE)
|
||||
|
@ -767,20 +826,16 @@ else()
|
|||
endif()
|
||||
|
||||
#TODO(kostyak): add back Android & Fuchsia when the code settles a bit.
|
||||
if (SCUDO_STANDALONE_SUPPORTED_ARCH AND OS_NAME MATCHES "Linux" AND
|
||||
if (SCUDO_STANDALONE_SUPPORTED_ARCH AND
|
||||
COMPILER_RT_BUILD_SANITIZERS AND
|
||||
"scudo_standalone" IN_LIST COMPILER_RT_SANITIZERS_TO_BUILD AND
|
||||
OS_NAME MATCHES "Linux" AND
|
||||
COMPILER_RT_HAS_AUXV)
|
||||
set(COMPILER_RT_HAS_SCUDO_STANDALONE TRUE)
|
||||
else()
|
||||
set(COMPILER_RT_HAS_SCUDO_STANDALONE FALSE)
|
||||
endif()
|
||||
|
||||
if (COMPILER_RT_HAS_SANITIZER_COMMON AND SCUDO_SUPPORTED_ARCH AND
|
||||
OS_NAME MATCHES "Linux|Android|Fuchsia")
|
||||
set(COMPILER_RT_HAS_SCUDO TRUE)
|
||||
else()
|
||||
set(COMPILER_RT_HAS_SCUDO FALSE)
|
||||
endif()
|
||||
|
||||
if (COMPILER_RT_HAS_SANITIZER_COMMON AND XRAY_SUPPORTED_ARCH AND
|
||||
OS_NAME MATCHES "Darwin|Linux|FreeBSD|NetBSD|Fuchsia")
|
||||
set(COMPILER_RT_HAS_XRAY TRUE)
|
||||
|
@ -813,7 +868,10 @@ endif()
|
|||
# calling malloc on first use.
|
||||
# TODO(hctim): Enable this on Android again. Looks like it's causing a SIGSEGV
|
||||
# for Scudo and GWP-ASan, further testing needed.
|
||||
if (COMPILER_RT_HAS_SANITIZER_COMMON AND GWP_ASAN_SUPPORTED_ARCH AND
|
||||
if (GWP_ASAN_SUPPORTED_ARCH AND
|
||||
COMPILER_RT_BUILD_GWP_ASAN AND
|
||||
COMPILER_RT_BUILD_SANITIZERS AND
|
||||
"gwp_asan" IN_LIST COMPILER_RT_SANITIZERS_TO_BUILD AND
|
||||
OS_NAME MATCHES "Linux")
|
||||
set(COMPILER_RT_HAS_GWP_ASAN TRUE)
|
||||
else()
|
||||
|
|
51
gnu/llvm/compiler-rt/cmake/crt-config-ix.cmake
Normal file
51
gnu/llvm/compiler-rt/cmake/crt-config-ix.cmake
Normal file
|
@ -0,0 +1,51 @@
|
|||
include(BuiltinTests)
|
||||
include(CheckCSourceCompiles)
|
||||
|
||||
# Make all the tests only check the compiler
|
||||
set(TEST_COMPILE_ONLY On)
|
||||
|
||||
builtin_check_c_compiler_flag(-fPIC COMPILER_RT_HAS_FPIC_FLAG)
|
||||
builtin_check_c_compiler_flag(-std=c11 COMPILER_RT_HAS_STD_C11_FLAG)
|
||||
builtin_check_c_compiler_flag(-Wno-pedantic COMPILER_RT_HAS_WNO_PEDANTIC)
|
||||
builtin_check_c_compiler_flag(-fno-lto COMPILER_RT_HAS_FNO_LTO_FLAG)
|
||||
builtin_check_c_compiler_flag(-fno-profile-generate COMPILER_RT_HAS_FNO_PROFILE_GENERATE_FLAG)
|
||||
builtin_check_c_compiler_flag(-fno-profile-instr-generate COMPILER_RT_HAS_FNO_PROFILE_INSTR_GENERATE_FLAG)
|
||||
builtin_check_c_compiler_flag(-fno-profile-instr-use COMPILER_RT_HAS_FNO_PROFILE_INSTR_USE_FLAG)
|
||||
|
||||
if(ANDROID)
|
||||
set(OS_NAME "Android")
|
||||
else()
|
||||
set(OS_NAME "${CMAKE_SYSTEM_NAME}")
|
||||
endif()
|
||||
|
||||
set(ARM64 aarch64)
|
||||
set(ARM32 arm armhf)
|
||||
set(HEXAGON hexagon)
|
||||
set(X86 i386)
|
||||
set(X86_64 x86_64)
|
||||
set(LOONGARCH64 loongarch64)
|
||||
set(PPC32 powerpc powerpcspe)
|
||||
set(PPC64 powerpc64 powerpc64le)
|
||||
set(RISCV32 riscv32)
|
||||
set(RISCV64 riscv64)
|
||||
set(VE ve)
|
||||
|
||||
set(ALL_CRT_SUPPORTED_ARCH ${X86} ${X86_64} ${ARM32} ${ARM64} ${PPC32}
|
||||
${PPC64} ${RISCV32} ${RISCV64} ${VE} ${HEXAGON} ${LOONGARCH64})
|
||||
|
||||
include(CompilerRTUtils)
|
||||
|
||||
if(NOT APPLE)
|
||||
if(COMPILER_RT_CRT_STANDALONE_BUILD)
|
||||
test_targets()
|
||||
endif()
|
||||
# Architectures supported by compiler-rt crt library.
|
||||
filter_available_targets(CRT_SUPPORTED_ARCH ${ALL_CRT_SUPPORTED_ARCH})
|
||||
message(STATUS "Supported architectures for crt: ${CRT_SUPPORTED_ARCH}")
|
||||
endif()
|
||||
|
||||
if (CRT_SUPPORTED_ARCH AND OS_NAME MATCHES "Linux" AND NOT LLVM_USE_SANITIZER)
|
||||
set(COMPILER_RT_HAS_CRT TRUE)
|
||||
else()
|
||||
set(COMPILER_RT_HAS_CRT FALSE)
|
||||
endif()
|
|
@ -31,23 +31,24 @@ REQUIRES, XFAIL, etc.
|
|||
|
||||
Sometimes it is necessary to restrict a test to a specific target or mark it as
|
||||
an "expected fail" or XFAIL. This is normally achieved using ``REQUIRES:`` or
|
||||
``XFAIL:`` with a substring of LLVM's default target triple. Unfortunately, the
|
||||
``XFAIL:`` and the ``target=<target-triple>`` feature, typically with a regular
|
||||
expression matching an appropriate substring of the triple. Unfortunately, the
|
||||
behaviour of this is somewhat quirky in compiler-rt. There are two main
|
||||
pitfalls to avoid.
|
||||
|
||||
The first pitfall is that these directives perform a substring match on the
|
||||
triple and as such ``XFAIL: mips`` affects more triples than expected. For
|
||||
example, ``mips-linux-gnu``, ``mipsel-linux-gnu``, ``mips64-linux-gnu``, and
|
||||
``mips64el-linux-gnu`` will all match a ``XFAIL: mips`` directive. Including a
|
||||
trailing ``-`` such as in ``XFAIL: mips-`` can help to mitigate this quirk but
|
||||
even that has issues as described below.
|
||||
The first pitfall is that these regular expressions may inadvertently match
|
||||
more triples than expected. For example, ``XFAIL: target=mips{{.*}}`` matches
|
||||
``mips-linux-gnu``, ``mipsel-linux-gnu``, ``mips64-linux-gnu``, and
|
||||
``mips64el-linux-gnu``. Including a trailing ``-`` such as in
|
||||
``XFAIL: target=mips-{{.*}}`` can help to mitigate this quirk but even that has
|
||||
issues as described below.
|
||||
|
||||
The second pitfall is that the default target triple is often inappropriate for
|
||||
compiler-rt tests since compiler-rt tests may be compiled for multiple targets.
|
||||
For example, a typical build on an ``x86_64-linux-gnu`` host will often run the
|
||||
tests for both x86_64 and i386. In this situation ``XFAIL: x86_64`` will mark
|
||||
both the x86_64 and i386 tests as an expected failure while ``XFAIL: i386``
|
||||
will have no effect at all.
|
||||
tests for both x86_64 and i386. In this situation ``XFAIL: target=x86_64{{{.*}}``
|
||||
will mark both the x86_64 and i386 tests as an expected failure while
|
||||
``XFAIL: target=i386{{.*}}`` will have no effect at all.
|
||||
|
||||
To remedy both pitfalls, compiler-rt tests provide a feature string which can
|
||||
be used to specify a single target. This string is of the form
|
||||
|
|
|
@ -23,6 +23,7 @@ endif(COMPILER_RT_BUILD_SANITIZERS)
|
|||
if (COMPILER_RT_BUILD_MEMPROF)
|
||||
set(MEMPROF_HEADERS
|
||||
sanitizer/memprof_interface.h
|
||||
profile/MemProfData.inc
|
||||
)
|
||||
endif(COMPILER_RT_BUILD_MEMPROF)
|
||||
|
||||
|
@ -34,6 +35,12 @@ if (COMPILER_RT_BUILD_XRAY)
|
|||
)
|
||||
endif(COMPILER_RT_BUILD_XRAY)
|
||||
|
||||
if (COMPILER_RT_BUILD_ORC)
|
||||
set(ORC_HEADERS
|
||||
orc_rt/c_api.h
|
||||
)
|
||||
endif(COMPILER_RT_BUILD_ORC)
|
||||
|
||||
if (COMPILER_RT_BUILD_PROFILE)
|
||||
set(PROFILE_HEADERS
|
||||
profile/InstrProfData.inc
|
||||
|
@ -45,6 +52,7 @@ set(COMPILER_RT_HEADERS
|
|||
${FUZZER_HEADERS}
|
||||
${MEMPROF_HEADERS}
|
||||
${XRAY_HEADERS}
|
||||
${ORC_HEADERS}
|
||||
${PROFILE_HEADERS})
|
||||
|
||||
set(output_dir ${COMPILER_RT_OUTPUT_DIR}/include)
|
||||
|
@ -75,11 +83,23 @@ install(FILES ${FUZZER_HEADERS}
|
|||
COMPONENT compiler-rt-headers
|
||||
PERMISSIONS OWNER_READ OWNER_WRITE GROUP_READ WORLD_READ
|
||||
DESTINATION ${COMPILER_RT_INSTALL_INCLUDE_DIR}/fuzzer)
|
||||
# Install memprof headers.
|
||||
if (COMPILER_RT_BUILD_MEMPROF)
|
||||
install(FILES sanitizer/memprof_interface.h
|
||||
COMPONENT compiler-rt-headers
|
||||
PERMISSIONS OWNER_READ OWNER_WRITE GROUP_READ WORLD_READ
|
||||
DESTINATION ${COMPILER_RT_INSTALL_INCLUDE_DIR}/sanitizer)
|
||||
endif(COMPILER_RT_BUILD_MEMPROF)
|
||||
# Install xray headers.
|
||||
install(FILES ${XRAY_HEADERS}
|
||||
COMPONENT compiler-rt-headers
|
||||
PERMISSIONS OWNER_READ OWNER_WRITE GROUP_READ WORLD_READ
|
||||
DESTINATION ${COMPILER_RT_INSTALL_INCLUDE_DIR}/xray)
|
||||
# Install ORC headers.
|
||||
install(FILES ${ORC_HEADERS}
|
||||
COMPONENT compiler-rt-headers
|
||||
PERMISSIONS OWNER_READ OWNER_WRITE GROUP_READ WORLD_READ
|
||||
DESTINATION ${COMPILER_RT_INSTALL_INCLUDE_DIR}/orc)
|
||||
# Install profile headers.
|
||||
install(FILES ${PROFILE_HEADERS}
|
||||
COMPONENT compiler-rt-headers
|
||||
|
|
|
@ -9,9 +9,6 @@
|
|||
|* *|
|
||||
|* This file defines the C API for the ORC runtime *|
|
||||
|* *|
|
||||
|* NOTE: The OrtRTWrapperFunctionResult type must be kept in sync with the *|
|
||||
|* definition in llvm/include/llvm-c/OrcShared.h. *|
|
||||
|* *|
|
||||
\*===----------------------------------------------------------------------===*/
|
||||
|
||||
#ifndef ORC_RT_C_API_H
|
||||
|
@ -50,7 +47,7 @@ ORC_RT_C_EXTERN_C_BEGIN
|
|||
|
||||
typedef union {
|
||||
char *ValuePtr;
|
||||
char Value[sizeof(ValuePtr)];
|
||||
char Value[sizeof(char *)];
|
||||
} __orc_rt_CWrapperFunctionResultDataUnion;
|
||||
|
||||
/**
|
||||
|
@ -91,15 +88,15 @@ __orc_rt_CWrapperFunctionResultInit(__orc_rt_CWrapperFunctionResult *R) {
|
|||
* Create an __orc_rt_CWrapperFunctionResult with an uninitialized buffer of
|
||||
* size Size. The buffer is returned via the DataPtr argument.
|
||||
*/
|
||||
static inline char *
|
||||
__orc_rt_CWrapperFunctionResultAllocate(__orc_rt_CWrapperFunctionResult *R,
|
||||
size_t Size) {
|
||||
R->Size = Size;
|
||||
if (Size <= sizeof(R->Data.Value))
|
||||
return R->Data.Value;
|
||||
|
||||
R->Data.ValuePtr = (char *)malloc(Size);
|
||||
return R->Data.ValuePtr;
|
||||
static inline __orc_rt_CWrapperFunctionResult
|
||||
__orc_rt_CWrapperFunctionResultAllocate(size_t Size) {
|
||||
__orc_rt_CWrapperFunctionResult R;
|
||||
R.Size = Size;
|
||||
// If Size is 0 ValuePtr must be 0 or it is considered an out-of-band error.
|
||||
R.Data.ValuePtr = 0;
|
||||
if (Size > sizeof(R.Data.Value))
|
||||
R.Data.ValuePtr = (char *)malloc(Size);
|
||||
return R;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -135,8 +132,8 @@ __orc_rt_CreateCWrapperFunctionResultFromString(const char *Source) {
|
|||
* Create an __orc_rt_CWrapperFunctionResult representing an out-of-band
|
||||
* error.
|
||||
*
|
||||
* This function takes ownership of the string argument which must have been
|
||||
* allocated with malloc.
|
||||
* This function copies the input string. The client is responsible for freeing
|
||||
* the ErrMsg arg.
|
||||
*/
|
||||
static inline __orc_rt_CWrapperFunctionResult
|
||||
__orc_rt_CreateCWrapperFunctionResultFromOutOfBandError(const char *ErrMsg) {
|
||||
|
@ -163,9 +160,9 @@ __orc_rt_DisposeCWrapperFunctionResult(__orc_rt_CWrapperFunctionResult *R) {
|
|||
* Get a pointer to the data contained in the given
|
||||
* __orc_rt_CWrapperFunctionResult.
|
||||
*/
|
||||
static inline const char *
|
||||
__orc_rt_CWrapperFunctionResultData(const __orc_rt_CWrapperFunctionResult *R) {
|
||||
assert((R->Size != 0 || R->Data.ValuePtr == nullptr) &&
|
||||
static inline char *
|
||||
__orc_rt_CWrapperFunctionResultData(__orc_rt_CWrapperFunctionResult *R) {
|
||||
assert((R->Size != 0 || R->Data.ValuePtr == NULL) &&
|
||||
"Cannot get data for out-of-band error value");
|
||||
return R->Size > sizeof(R->Data.Value) ? R->Data.ValuePtr : R->Data.Value;
|
||||
}
|
||||
|
@ -177,7 +174,7 @@ __orc_rt_CWrapperFunctionResultData(const __orc_rt_CWrapperFunctionResult *R) {
|
|||
*/
|
||||
static inline size_t
|
||||
__orc_rt_CWrapperFunctionResultSize(const __orc_rt_CWrapperFunctionResult *R) {
|
||||
assert((R->Size != 0 || R->Data.ValuePtr == nullptr) &&
|
||||
assert((R->Size != 0 || R->Data.ValuePtr == NULL) &&
|
||||
"Cannot get size for out-of-band error value");
|
||||
return R->Size;
|
||||
}
|
|
@ -75,9 +75,7 @@ INSTR_PROF_DATA(const uint64_t, llvm::Type::getInt64Ty(Ctx), NameRef, \
|
|||
INSTR_PROF_DATA(const uint64_t, llvm::Type::getInt64Ty(Ctx), FuncHash, \
|
||||
ConstantInt::get(llvm::Type::getInt64Ty(Ctx), \
|
||||
Inc->getHash()->getZExtValue()))
|
||||
INSTR_PROF_DATA(const IntPtrT, llvm::Type::getInt64PtrTy(Ctx), CounterPtr, \
|
||||
ConstantExpr::getBitCast(CounterPtr, \
|
||||
llvm::Type::getInt64PtrTy(Ctx)))
|
||||
INSTR_PROF_DATA(const IntPtrT, IntPtrTy, CounterPtr, RelativeCounterPtr)
|
||||
/* This is used to map function pointers for the indirect call targets to
|
||||
* function name hashes during the conversion from raw to merged profile
|
||||
* data.
|
||||
|
@ -130,12 +128,15 @@ INSTR_PROF_VALUE_NODE(PtrToNodeT, llvm::Type::getInt8PtrTy(Ctx), Next, \
|
|||
INSTR_PROF_RAW_HEADER(uint64_t, Magic, __llvm_profile_get_magic())
|
||||
INSTR_PROF_RAW_HEADER(uint64_t, Version, __llvm_profile_get_version())
|
||||
INSTR_PROF_RAW_HEADER(uint64_t, BinaryIdsSize, __llvm_write_binary_ids(NULL))
|
||||
/* FIXME: A more accurate name is NumData */
|
||||
INSTR_PROF_RAW_HEADER(uint64_t, DataSize, DataSize)
|
||||
INSTR_PROF_RAW_HEADER(uint64_t, PaddingBytesBeforeCounters, PaddingBytesBeforeCounters)
|
||||
/* FIXME: A more accurate name is NumCounters */
|
||||
INSTR_PROF_RAW_HEADER(uint64_t, CountersSize, CountersSize)
|
||||
INSTR_PROF_RAW_HEADER(uint64_t, PaddingBytesAfterCounters, PaddingBytesAfterCounters)
|
||||
INSTR_PROF_RAW_HEADER(uint64_t, NamesSize, NamesSize)
|
||||
INSTR_PROF_RAW_HEADER(uint64_t, CountersDelta, (uintptr_t)CountersBegin)
|
||||
INSTR_PROF_RAW_HEADER(uint64_t, CountersDelta,
|
||||
(uintptr_t)CountersBegin - (uintptr_t)DataBegin)
|
||||
INSTR_PROF_RAW_HEADER(uint64_t, NamesDelta, (uintptr_t)NamesBegin)
|
||||
INSTR_PROF_RAW_HEADER(uint64_t, ValueKindLast, IPVK_Last)
|
||||
#undef INSTR_PROF_RAW_HEADER
|
||||
|
@ -645,24 +646,33 @@ serializeValueProfDataFrom(ValueProfRecordClosure *Closure,
|
|||
(uint64_t)'p' << 40 | (uint64_t)'r' << 32 | (uint64_t)'o' << 24 | \
|
||||
(uint64_t)'f' << 16 | (uint64_t)'R' << 8 | (uint64_t)129
|
||||
|
||||
/* FIXME: Please remedy the fixme in the header before bumping the version. */
|
||||
/* Raw profile format version (start from 1). */
|
||||
#define INSTR_PROF_RAW_VERSION 7
|
||||
#define INSTR_PROF_RAW_VERSION 8
|
||||
/* Indexed profile format version (start from 1). */
|
||||
#define INSTR_PROF_INDEX_VERSION 7
|
||||
#define INSTR_PROF_INDEX_VERSION 9
|
||||
/* Coverage mapping format version (start from 0). */
|
||||
#define INSTR_PROF_COVMAP_VERSION 5
|
||||
|
||||
/* Profile version is always of type uint64_t. Reserve the upper 8 bits in the
|
||||
* version for other variants of profile. We set the lowest bit of the upper 8
|
||||
* bits (i.e. bit 56) to 1 to indicate if this is an IR-level instrumentaiton
|
||||
* bits (i.e. bit 56) to 1 to indicate if this is an IR-level instrumentation
|
||||
* generated profile, and 0 if this is a Clang FE generated profile.
|
||||
* 1 in bit 57 indicates there are context-sensitive records in the profile.
|
||||
* The 59th bit indicates whether to use debug info to correlate profiles.
|
||||
* The 60th bit indicates single byte coverage instrumentation.
|
||||
* The 61st bit indicates function entry instrumentation only.
|
||||
* The 62nd bit indicates whether memory profile information is present.
|
||||
*/
|
||||
#define VARIANT_MASKS_ALL 0xff00000000000000ULL
|
||||
#define GET_VERSION(V) ((V) & ~VARIANT_MASKS_ALL)
|
||||
#define VARIANT_MASK_IR_PROF (0x1ULL << 56)
|
||||
#define VARIANT_MASK_CSIR_PROF (0x1ULL << 57)
|
||||
#define VARIANT_MASK_INSTR_ENTRY (0x1ULL << 58)
|
||||
#define VARIANT_MASK_DBG_CORRELATE (0x1ULL << 59)
|
||||
#define VARIANT_MASK_BYTE_COVERAGE (0x1ULL << 60)
|
||||
#define VARIANT_MASK_FUNCTION_ENTRY_ONLY (0x1ULL << 61)
|
||||
#define VARIANT_MASK_MEMPROF (0x1ULL << 62)
|
||||
#define INSTR_PROF_RAW_VERSION_VAR __llvm_profile_raw_version
|
||||
#define INSTR_PROF_PROFILE_RUNTIME_VAR __llvm_profile_runtime
|
||||
#define INSTR_PROF_PROFILE_COUNTER_BIAS_VAR __llvm_profile_counter_bias
|
||||
|
|
53
gnu/llvm/compiler-rt/include/profile/MIBEntryDef.inc
Normal file
53
gnu/llvm/compiler-rt/include/profile/MIBEntryDef.inc
Normal file
|
@ -0,0 +1,53 @@
|
|||
/*===-- MemEntryDef.inc - MemProf profiling runtime macros -*- C++ -*-======== *\
|
||||
|*
|
||||
|* Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
||||
|* See https://llvm.org/LICENSE.txt for license information.
|
||||
|* SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
|*
|
||||
\*===----------------------------------------------------------------------===*/
|
||||
/*
|
||||
* This file defines the macros for memprof profiling data structures.
|
||||
* Eg. usage to define the memprof meminfoblock struct:
|
||||
*
|
||||
* struct MemInfoBlock {
|
||||
* #define MIBEntryDef(NameTag, Name, Type) Type Name;
|
||||
* #include MIBEntryDef.inc
|
||||
* #undef MIBEntryDef
|
||||
* };
|
||||
*
|
||||
* This file has two identical copies. The primary copy lives in LLVM and
|
||||
* the other one sits in compiler-rt/include/profile directory. To make changes
|
||||
* in this file, first modify the primary copy and copy it over to compiler-rt.
|
||||
* Testing of any change in this file can start only after the two copies are
|
||||
* synced up.
|
||||
*
|
||||
\*===----------------------------------------------------------------------===*/
|
||||
#ifndef MIBEntryDef
|
||||
#define MIBEntryDef(NameTag, Name, Type)
|
||||
#endif
|
||||
|
||||
MIBEntryDef(AllocCount = 1, AllocCount, uint32_t)
|
||||
MIBEntryDef(TotalAccessCount = 2, TotalAccessCount, uint64_t)
|
||||
MIBEntryDef(MinAccessCount = 3, MinAccessCount, uint64_t)
|
||||
MIBEntryDef(MaxAccessCount = 4, MaxAccessCount, uint64_t)
|
||||
MIBEntryDef(TotalSize = 5, TotalSize, uint64_t)
|
||||
MIBEntryDef(MinSize = 6, MinSize, uint32_t)
|
||||
MIBEntryDef(MaxSize = 7, MaxSize, uint32_t)
|
||||
MIBEntryDef(AllocTimestamp = 8, AllocTimestamp, uint32_t)
|
||||
MIBEntryDef(DeallocTimestamp = 9, DeallocTimestamp, uint32_t)
|
||||
MIBEntryDef(TotalLifetime = 10, TotalLifetime, uint64_t)
|
||||
MIBEntryDef(MinLifetime = 11, MinLifetime, uint32_t)
|
||||
MIBEntryDef(MaxLifetime = 12, MaxLifetime, uint32_t)
|
||||
MIBEntryDef(AllocCpuId = 13, AllocCpuId, uint32_t)
|
||||
MIBEntryDef(DeallocCpuId = 14, DeallocCpuId, uint32_t)
|
||||
MIBEntryDef(NumMigratedCpu = 15, NumMigratedCpu, uint32_t)
|
||||
MIBEntryDef(NumLifetimeOverlaps = 16, NumLifetimeOverlaps, uint32_t)
|
||||
MIBEntryDef(NumSameAllocCpu = 17, NumSameAllocCpu, uint32_t)
|
||||
MIBEntryDef(NumSameDeallocCpu = 18, NumSameDeallocCpu, uint32_t)
|
||||
MIBEntryDef(DataTypeId = 19, DataTypeId, uint64_t)
|
||||
MIBEntryDef(TotalAccessDensity = 20, TotalAccessDensity, uint64_t)
|
||||
MIBEntryDef(MinAccessDensity = 21, MinAccessDensity, uint32_t)
|
||||
MIBEntryDef(MaxAccessDensity = 22, MaxAccessDensity, uint32_t)
|
||||
MIBEntryDef(TotalLifetimeAccessDensity = 23, TotalLifetimeAccessDensity, uint64_t)
|
||||
MIBEntryDef(MinLifetimeAccessDensity = 24, MinLifetimeAccessDensity, uint32_t)
|
||||
MIBEntryDef(MaxLifetimeAccessDensity = 25, MaxLifetimeAccessDensity, uint32_t)
|
202
gnu/llvm/compiler-rt/include/profile/MemProfData.inc
Normal file
202
gnu/llvm/compiler-rt/include/profile/MemProfData.inc
Normal file
|
@ -0,0 +1,202 @@
|
|||
#ifndef MEMPROF_DATA_INC
|
||||
#define MEMPROF_DATA_INC
|
||||
/*===-- MemProfData.inc - MemProf profiling runtime structures -*- C++ -*-=== *\
|
||||
|*
|
||||
|* Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
||||
|* See https://llvm.org/LICENSE.txt for license information.
|
||||
|* SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
|*
|
||||
\*===----------------------------------------------------------------------===*/
|
||||
/*
|
||||
* This is the main file that defines all the data structure, signature,
|
||||
* constant literals that are shared across profiling runtime library,
|
||||
* and host tools (reader/writer).
|
||||
*
|
||||
* This file has two identical copies. The primary copy lives in LLVM and
|
||||
* the other one sits in compiler-rt/include/profile directory. To make changes
|
||||
* in this file, first modify the primary copy and copy it over to compiler-rt.
|
||||
* Testing of any change in this file can start only after the two copies are
|
||||
* synced up.
|
||||
*
|
||||
\*===----------------------------------------------------------------------===*/
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#define PACKED(...) __pragma(pack(push,1)) __VA_ARGS__ __pragma(pack(pop))
|
||||
#else
|
||||
#define PACKED(...) __VA_ARGS__ __attribute__((__packed__))
|
||||
#endif
|
||||
|
||||
// A 64-bit magic number to uniquely identify the raw binary memprof profile file.
|
||||
#define MEMPROF_RAW_MAGIC_64 \
|
||||
((uint64_t)255 << 56 | (uint64_t)'m' << 48 | (uint64_t)'p' << 40 | (uint64_t)'r' << 32 | \
|
||||
(uint64_t)'o' << 24 | (uint64_t)'f' << 16 | (uint64_t)'r' << 8 | (uint64_t)129)
|
||||
|
||||
// The version number of the raw binary format.
|
||||
#define MEMPROF_RAW_VERSION 2ULL
|
||||
|
||||
namespace llvm {
|
||||
namespace memprof {
|
||||
// A struct describing the header used for the raw binary memprof profile format.
|
||||
PACKED(struct Header {
|
||||
uint64_t Magic;
|
||||
uint64_t Version;
|
||||
uint64_t TotalSize;
|
||||
uint64_t SegmentOffset;
|
||||
uint64_t MIBOffset;
|
||||
uint64_t StackOffset;
|
||||
});
|
||||
|
||||
|
||||
// A struct describing the information necessary to describe a /proc/maps
|
||||
// segment entry for a particular binary/library identified by its build id.
|
||||
PACKED(struct SegmentEntry {
|
||||
uint64_t Start;
|
||||
uint64_t End;
|
||||
uint64_t Offset;
|
||||
// This field is unused until sanitizer procmaps support for build ids for
|
||||
// Linux-Elf is implemented.
|
||||
uint8_t BuildId[32] = {0};
|
||||
|
||||
SegmentEntry(uint64_t S, uint64_t E, uint64_t O) :
|
||||
Start(S), End(E), Offset(O) {}
|
||||
|
||||
SegmentEntry(const SegmentEntry& S) {
|
||||
Start = S.Start;
|
||||
End = S.End;
|
||||
Offset = S.Offset;
|
||||
}
|
||||
|
||||
SegmentEntry& operator=(const SegmentEntry& S) {
|
||||
Start = S.Start;
|
||||
End = S.End;
|
||||
Offset = S.Offset;
|
||||
return *this;
|
||||
}
|
||||
|
||||
bool operator==(const SegmentEntry& S) const {
|
||||
return Start == S.Start &&
|
||||
End == S.End &&
|
||||
Offset == S.Offset;
|
||||
}
|
||||
});
|
||||
|
||||
// Packed struct definition for MSVC. We can't use the PACKED macro defined in
|
||||
// MemProfData.inc since it would mean we are embedding a directive (the
|
||||
// #include for MIBEntryDef) into the macros which is undefined behaviour.
|
||||
#ifdef _MSC_VER
|
||||
__pragma(pack(push,1))
|
||||
#endif
|
||||
|
||||
// A struct representing the heap allocation characteristics of a particular
|
||||
// runtime context. This struct is shared between the compiler-rt runtime and
|
||||
// the raw profile reader. The indexed format uses a separate, self-describing
|
||||
// backwards compatible format.
|
||||
struct MemInfoBlock{
|
||||
|
||||
#define MIBEntryDef(NameTag, Name, Type) Type Name;
|
||||
#include "MIBEntryDef.inc"
|
||||
#undef MIBEntryDef
|
||||
|
||||
bool operator==(const MemInfoBlock& Other) const {
|
||||
bool IsEqual = true;
|
||||
#define MIBEntryDef(NameTag, Name, Type) \
|
||||
IsEqual = (IsEqual && Name == Other.Name);
|
||||
#include "MIBEntryDef.inc"
|
||||
#undef MIBEntryDef
|
||||
return IsEqual;
|
||||
}
|
||||
|
||||
MemInfoBlock() {
|
||||
#define MIBEntryDef(NameTag, Name, Type) Name = Type();
|
||||
#include "MIBEntryDef.inc"
|
||||
#undef MIBEntryDef
|
||||
}
|
||||
|
||||
MemInfoBlock(uint32_t Size, uint64_t AccessCount, uint32_t AllocTs,
|
||||
uint32_t DeallocTs, uint32_t AllocCpu, uint32_t DeallocCpu)
|
||||
: MemInfoBlock() {
|
||||
AllocCount = 1U;
|
||||
TotalAccessCount = AccessCount;
|
||||
MinAccessCount = AccessCount;
|
||||
MaxAccessCount = AccessCount;
|
||||
TotalSize = Size;
|
||||
MinSize = Size;
|
||||
MaxSize = Size;
|
||||
AllocTimestamp = AllocTs;
|
||||
DeallocTimestamp = DeallocTs;
|
||||
TotalLifetime = DeallocTimestamp - AllocTimestamp;
|
||||
MinLifetime = TotalLifetime;
|
||||
MaxLifetime = TotalLifetime;
|
||||
// Access density is accesses per byte. Multiply by 100 to include the
|
||||
// fractional part.
|
||||
TotalAccessDensity = AccessCount * 100 / Size;
|
||||
MinAccessDensity = TotalAccessDensity;
|
||||
MaxAccessDensity = TotalAccessDensity;
|
||||
// Lifetime access density is the access density per second of lifetime.
|
||||
// Multiply by 1000 to convert denominator lifetime to seconds (using a
|
||||
// minimum lifetime of 1ms to avoid divide by 0. Do the multiplication first
|
||||
// to reduce truncations to 0.
|
||||
TotalLifetimeAccessDensity =
|
||||
TotalAccessDensity * 1000 / (TotalLifetime ? TotalLifetime : 1);
|
||||
MinLifetimeAccessDensity = TotalLifetimeAccessDensity;
|
||||
MaxLifetimeAccessDensity = TotalLifetimeAccessDensity;
|
||||
AllocCpuId = AllocCpu;
|
||||
DeallocCpuId = DeallocCpu;
|
||||
NumMigratedCpu = AllocCpuId != DeallocCpuId;
|
||||
}
|
||||
|
||||
void Merge(const MemInfoBlock &newMIB) {
|
||||
AllocCount += newMIB.AllocCount;
|
||||
|
||||
TotalAccessCount += newMIB.TotalAccessCount;
|
||||
MinAccessCount = newMIB.MinAccessCount < MinAccessCount ? newMIB.MinAccessCount : MinAccessCount;
|
||||
MaxAccessCount = newMIB.MaxAccessCount > MaxAccessCount ? newMIB.MaxAccessCount : MaxAccessCount;
|
||||
|
||||
TotalSize += newMIB.TotalSize;
|
||||
MinSize = newMIB.MinSize < MinSize ? newMIB.MinSize : MinSize;
|
||||
MaxSize = newMIB.MaxSize > MaxSize ? newMIB.MaxSize : MaxSize;
|
||||
|
||||
TotalLifetime += newMIB.TotalLifetime;
|
||||
MinLifetime = newMIB.MinLifetime < MinLifetime ? newMIB.MinLifetime : MinLifetime;
|
||||
MaxLifetime = newMIB.MaxLifetime > MaxLifetime ? newMIB.MaxLifetime : MaxLifetime;
|
||||
|
||||
TotalAccessDensity += newMIB.TotalAccessDensity;
|
||||
MinAccessDensity = newMIB.MinAccessDensity < MinAccessDensity
|
||||
? newMIB.MinAccessDensity
|
||||
: MinAccessDensity;
|
||||
MaxAccessDensity = newMIB.MaxAccessDensity > MaxAccessDensity
|
||||
? newMIB.MaxAccessDensity
|
||||
: MaxAccessDensity;
|
||||
|
||||
TotalLifetimeAccessDensity += newMIB.TotalLifetimeAccessDensity;
|
||||
MinLifetimeAccessDensity =
|
||||
newMIB.MinLifetimeAccessDensity < MinLifetimeAccessDensity
|
||||
? newMIB.MinLifetimeAccessDensity
|
||||
: MinLifetimeAccessDensity;
|
||||
MaxLifetimeAccessDensity =
|
||||
newMIB.MaxLifetimeAccessDensity > MaxLifetimeAccessDensity
|
||||
? newMIB.MaxLifetimeAccessDensity
|
||||
: MaxLifetimeAccessDensity;
|
||||
|
||||
// We know newMIB was deallocated later, so just need to check if it was
|
||||
// allocated before last one deallocated.
|
||||
NumLifetimeOverlaps += newMIB.AllocTimestamp < DeallocTimestamp;
|
||||
AllocTimestamp = newMIB.AllocTimestamp;
|
||||
DeallocTimestamp = newMIB.DeallocTimestamp;
|
||||
|
||||
NumSameAllocCpu += AllocCpuId == newMIB.AllocCpuId;
|
||||
NumSameDeallocCpu += DeallocCpuId == newMIB.DeallocCpuId;
|
||||
AllocCpuId = newMIB.AllocCpuId;
|
||||
DeallocCpuId = newMIB.DeallocCpuId;
|
||||
}
|
||||
|
||||
#ifdef _MSC_VER
|
||||
} __pragma(pack(pop));
|
||||
#else
|
||||
} __attribute__((__packed__));
|
||||
#endif
|
||||
|
||||
} // namespace memprof
|
||||
} // namespace llvm
|
||||
|
||||
#endif
|
|
@ -316,7 +316,7 @@ void *__asan_addr_is_in_fake_stack(void *fake_stack, void *addr, void **beg,
|
|||
void __asan_handle_no_return(void);
|
||||
|
||||
/// Update allocation stack trace for the given allocation to the current stack
|
||||
/// trace. Returns 1 if successfull, 0 if not.
|
||||
/// trace. Returns 1 if successful, 0 if not.
|
||||
int __asan_update_allocation_context(void* addr);
|
||||
|
||||
#ifdef __cplusplus
|
||||
|
|
|
@ -28,7 +28,7 @@ typedef struct {
|
|||
// Enable sandbox support in sanitizer coverage.
|
||||
int coverage_sandboxed;
|
||||
// File descriptor to write coverage data to. If -1 is passed, a file will
|
||||
// be pre-opened by __sanitizer_sandobx_on_notify(). This field has no
|
||||
// be pre-opened by __sanitizer_sandbox_on_notify(). This field has no
|
||||
// effect if coverage_sandboxed == 0.
|
||||
intptr_t coverage_fd;
|
||||
// If non-zero, split the coverage data into well-formed blocks. This is
|
||||
|
@ -159,6 +159,40 @@ void __sanitizer_annotate_contiguous_container(const void *beg,
|
|||
const void *old_mid,
|
||||
const void *new_mid);
|
||||
|
||||
/// Similar to <c>__sanitizer_annotate_contiguous_container</c>.
|
||||
///
|
||||
/// Annotates the current state of a contiguous container memory,
|
||||
/// such as <c>std::deque</c>'s single chunk, when the boundries are moved.
|
||||
///
|
||||
/// A contiguous chunk is a chunk that keeps all of its elements
|
||||
/// in a contiguous region of memory. The container owns the region of memory
|
||||
/// <c>[storage_beg, storage_end)</c>; the memory <c>[container_beg,
|
||||
/// container_end)</c> is used to store the current elements, and the memory
|
||||
/// <c>[storage_beg, container_beg), [container_end, storage_end)</c> is
|
||||
/// reserved for future elements (<c>storage_beg <= container_beg <=
|
||||
/// container_end <= storage_end</c>). For example, in <c> std::deque </c>:
|
||||
/// - chunk with a frist deques element will have container_beg equal to address
|
||||
/// of the first element.
|
||||
/// - in every next chunk with elements, true is <c> container_beg ==
|
||||
/// storage_beg </c>.
|
||||
///
|
||||
/// Argument requirements:
|
||||
/// During unpoisoning memory of empty container (before first element is
|
||||
/// added):
|
||||
/// - old_container_beg_p == old_container_end_p
|
||||
/// During poisoning after last element was removed:
|
||||
/// - new_container_beg_p == new_container_end_p
|
||||
/// \param storage_beg Beginning of memory region.
|
||||
/// \param storage_end End of memory region.
|
||||
/// \param old_container_beg Old beginning of used region.
|
||||
/// \param old_container_end End of used region.
|
||||
/// \param new_container_beg New beginning of used region.
|
||||
/// \param new_container_end New end of used region.
|
||||
void __sanitizer_annotate_double_ended_contiguous_container(
|
||||
const void *storage_beg, const void *storage_end,
|
||||
const void *old_container_beg, const void *old_container_end,
|
||||
const void *new_container_beg, const void *new_container_end);
|
||||
|
||||
/// Returns true if the contiguous container <c>[beg, end)</c> is properly
|
||||
/// poisoned.
|
||||
///
|
||||
|
@ -178,6 +212,31 @@ void __sanitizer_annotate_contiguous_container(const void *beg,
|
|||
int __sanitizer_verify_contiguous_container(const void *beg, const void *mid,
|
||||
const void *end);
|
||||
|
||||
/// Returns true if the double ended contiguous
|
||||
/// container <c>[storage_beg, storage_end)</c> is properly poisoned.
|
||||
///
|
||||
/// Proper poisoning could occur, for example, with
|
||||
/// <c>__sanitizer_annotate_double_ended_contiguous_container</c>), that is, if
|
||||
/// <c>[storage_beg, container_beg)</c> is not addressable, <c>[container_beg,
|
||||
/// container_end)</c> is addressable and <c>[container_end, end)</c> is
|
||||
/// unaddressable. Full verification requires O (<c>storage_end -
|
||||
/// storage_beg</c>) time; this function tries to avoid such complexity by
|
||||
/// touching only parts of the container around <c><i>storage_beg</i></c>,
|
||||
/// <c><i>container_beg</i></c>, <c><i>container_end</i></c>, and
|
||||
/// <c><i>storage_end</i></c>.
|
||||
///
|
||||
/// \param storage_beg Beginning of memory region.
|
||||
/// \param container_beg Beginning of used region.
|
||||
/// \param container_end End of used region.
|
||||
/// \param storage_end End of memory region.
|
||||
///
|
||||
/// \returns True if the double-ended contiguous container <c>[storage_beg,
|
||||
/// container_beg, container_end, end)</c> is properly poisoned - only
|
||||
/// [container_beg; container_end) is addressable.
|
||||
int __sanitizer_verify_double_ended_contiguous_container(
|
||||
const void *storage_beg, const void *container_beg,
|
||||
const void *container_end, const void *storage_end);
|
||||
|
||||
/// Similar to <c>__sanitizer_verify_contiguous_container()</c> but also
|
||||
/// returns the address of the first improperly poisoned byte.
|
||||
///
|
||||
|
@ -192,6 +251,20 @@ const void *__sanitizer_contiguous_container_find_bad_address(const void *beg,
|
|||
const void *mid,
|
||||
const void *end);
|
||||
|
||||
/// returns the address of the first improperly poisoned byte.
|
||||
///
|
||||
/// Returns NULL if the area is poisoned properly.
|
||||
///
|
||||
/// \param storage_beg Beginning of memory region.
|
||||
/// \param container_beg Beginning of used region.
|
||||
/// \param container_end End of used region.
|
||||
/// \param storage_end End of memory region.
|
||||
///
|
||||
/// \returns The bad address or NULL.
|
||||
const void *__sanitizer_double_ended_contiguous_container_find_bad_address(
|
||||
const void *storage_beg, const void *container_beg,
|
||||
const void *container_end, const void *storage_end);
|
||||
|
||||
/// Prints the stack trace leading to this call (useful for calling from the
|
||||
/// debugger).
|
||||
void __sanitizer_print_stack_trace(void);
|
||||
|
@ -211,6 +284,15 @@ void __sanitizer_symbolize_pc(void *pc, const char *fmt, char *out_buf,
|
|||
// Same as __sanitizer_symbolize_pc, but for data section (i.e. globals).
|
||||
void __sanitizer_symbolize_global(void *data_ptr, const char *fmt,
|
||||
char *out_buf, size_t out_buf_size);
|
||||
// Determine the return address.
|
||||
#if !defined(_MSC_VER) || defined(__clang__)
|
||||
#define __sanitizer_return_address() \
|
||||
__builtin_extract_return_addr(__builtin_return_address(0))
|
||||
#else
|
||||
extern "C" void *_ReturnAddress(void);
|
||||
#pragma intrinsic(_ReturnAddress)
|
||||
#define __sanitizer_return_address() _ReturnAddress()
|
||||
#endif
|
||||
|
||||
/// Sets the callback to be called immediately before death on error.
|
||||
///
|
||||
|
|
|
@ -27,6 +27,18 @@ typedef uint32_t dfsan_origin;
|
|||
/// Signature of the callback argument to dfsan_set_write_callback().
|
||||
typedef void (*dfsan_write_callback_t)(int fd, const void *buf, size_t count);
|
||||
|
||||
/// Signature of the callback argument to dfsan_set_conditional_callback().
|
||||
typedef void (*dfsan_conditional_callback_t)(dfsan_label label,
|
||||
dfsan_origin origin);
|
||||
|
||||
/// Signature of the callback argument to dfsan_set_reaches_function_callback().
|
||||
/// The description is intended to hold the name of the variable.
|
||||
typedef void (*dfsan_reaches_function_callback_t)(dfsan_label label,
|
||||
dfsan_origin origin,
|
||||
const char *file,
|
||||
unsigned int line,
|
||||
const char *function);
|
||||
|
||||
/// Computes the union of \c l1 and \c l2, resulting in a union label.
|
||||
dfsan_label dfsan_union(dfsan_label l1, dfsan_label l2);
|
||||
|
||||
|
@ -54,6 +66,10 @@ dfsan_origin dfsan_get_origin(long data);
|
|||
/// Retrieves the label associated with the data at the given address.
|
||||
dfsan_label dfsan_read_label(const void *addr, size_t size);
|
||||
|
||||
/// Return the origin associated with the first taint byte in the size bytes
|
||||
/// from the address addr.
|
||||
dfsan_origin dfsan_read_origin_of_first_taint(const void *addr, size_t size);
|
||||
|
||||
/// Returns whether the given label label contains the label elem.
|
||||
int dfsan_has_label(dfsan_label label, dfsan_label elem);
|
||||
|
||||
|
@ -70,6 +86,31 @@ void dfsan_flush(void);
|
|||
/// callback executes. Pass in NULL to remove any callback.
|
||||
void dfsan_set_write_callback(dfsan_write_callback_t labeled_write_callback);
|
||||
|
||||
/// Sets a callback to be invoked on any conditional expressions which have a
|
||||
/// taint label set. This can be used to find where tainted data influences
|
||||
/// the behavior of the program.
|
||||
/// These callbacks will only be added when -dfsan-conditional-callbacks=true.
|
||||
void dfsan_set_conditional_callback(dfsan_conditional_callback_t callback);
|
||||
|
||||
/// Conditional expressions occur during signal handlers.
|
||||
/// Making callbacks that handle signals well is tricky, so when
|
||||
/// -dfsan-conditional-callbacks=true, conditional expressions used in signal
|
||||
/// handlers will add the labels they see into a global (bitwise-or together).
|
||||
/// This function returns all label bits seen in signal handler conditions.
|
||||
dfsan_label dfsan_get_labels_in_signal_conditional();
|
||||
|
||||
/// Sets a callback to be invoked when tainted data reaches a function.
|
||||
/// This could occur at function entry, or at a load instruction.
|
||||
/// These callbacks will only be added if -dfsan-reaches-function-callbacks=1.
|
||||
void dfsan_set_reaches_function_callback(
|
||||
dfsan_reaches_function_callback_t callback);
|
||||
|
||||
/// Making callbacks that handle signals well is tricky, so when
|
||||
/// -dfsan-reaches-function-callbacks=true, functions reached in signal
|
||||
/// handlers will add the labels they see into a global (bitwise-or together).
|
||||
/// This function returns all label bits seen during signal handlers.
|
||||
dfsan_label dfsan_get_labels_in_signal_reaches_function();
|
||||
|
||||
/// Interceptor hooks.
|
||||
/// Whenever a dfsan's custom function is called the corresponding
|
||||
/// hook is called it non-zero. The hooks should be defined by the user.
|
||||
|
@ -87,6 +128,9 @@ void dfsan_weak_hook_strncmp(void *caller_pc, const char *s1, const char *s2,
|
|||
/// prints description at the beginning of the trace. If origin tracking is not
|
||||
/// on, or the address is not labeled, it prints nothing.
|
||||
void dfsan_print_origin_trace(const void *addr, const char *description);
|
||||
/// As above, but use an origin id from dfsan_get_origin() instead of address.
|
||||
/// Does not include header line with taint label and address information.
|
||||
void dfsan_print_origin_id_trace(dfsan_origin origin);
|
||||
|
||||
/// Prints the origin trace of the label at the address \p addr to a
|
||||
/// pre-allocated output buffer. If origin tracking is not on, or the address is
|
||||
|
@ -124,6 +168,10 @@ void dfsan_print_origin_trace(const void *addr, const char *description);
|
|||
/// return value is not less than \p out_buf_size.
|
||||
size_t dfsan_sprint_origin_trace(const void *addr, const char *description,
|
||||
char *out_buf, size_t out_buf_size);
|
||||
/// As above, but use an origin id from dfsan_get_origin() instead of address.
|
||||
/// Does not include header line with taint label and address information.
|
||||
size_t dfsan_sprint_origin_id_trace(dfsan_origin origin, char *out_buf,
|
||||
size_t out_buf_size);
|
||||
|
||||
/// Prints the stack trace leading to this call to a pre-allocated output
|
||||
/// buffer.
|
||||
|
@ -150,8 +198,7 @@ int dfsan_get_track_origins(void);
|
|||
#ifdef __cplusplus
|
||||
} // extern "C"
|
||||
|
||||
template <typename T>
|
||||
void dfsan_set_label(dfsan_label label, T &data) { // NOLINT
|
||||
template <typename T> void dfsan_set_label(dfsan_label label, T &data) {
|
||||
dfsan_set_label(label, (void *)&data, sizeof(T));
|
||||
}
|
||||
|
||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -92,6 +92,8 @@ extern "C" {
|
|||
|
||||
/* Tell MSan about newly destroyed memory. Mark memory as uninitialized. */
|
||||
void __sanitizer_dtor_callback(const volatile void* data, size_t size);
|
||||
void __sanitizer_dtor_callback_fields(const volatile void *data, size_t size);
|
||||
void __sanitizer_dtor_callback_vptr(const volatile void *data);
|
||||
|
||||
/* This function may be optionally provided by user and should return
|
||||
a string containing Msan runtime options. See msan_flags.h for details. */
|
||||
|
|
|
@ -169,6 +169,9 @@ void __tsan_on_initialize();
|
|||
// if TSan should exit as if issues were detected.
|
||||
int __tsan_on_finalize(int failed);
|
||||
|
||||
// Release TSan internal memory in a best-effort manner.
|
||||
void __tsan_flush_memory();
|
||||
|
||||
#ifdef __cplusplus
|
||||
} // extern "C"
|
||||
#endif
|
||||
|
|
|
@ -17,19 +17,20 @@ if(COMPILER_RT_BUILD_BUILTINS)
|
|||
add_subdirectory(builtins)
|
||||
endif()
|
||||
|
||||
if(COMPILER_RT_BUILD_CRT AND COMPILER_RT_HAS_CRT)
|
||||
if(COMPILER_RT_BUILD_CRT)
|
||||
add_subdirectory(crt)
|
||||
endif()
|
||||
|
||||
function(compiler_rt_build_runtime runtime)
|
||||
string(TOUPPER ${runtime} runtime_uppercase)
|
||||
if(COMPILER_RT_HAS_${runtime_uppercase})
|
||||
add_subdirectory(${runtime})
|
||||
if(${runtime} STREQUAL tsan)
|
||||
add_subdirectory(tsan/dd)
|
||||
endif()
|
||||
if(${runtime} STREQUAL scudo)
|
||||
if(${runtime} STREQUAL scudo_standalone)
|
||||
add_subdirectory(scudo/standalone)
|
||||
else()
|
||||
add_subdirectory(${runtime})
|
||||
endif()
|
||||
endif()
|
||||
endfunction()
|
||||
|
|
|
@ -42,6 +42,16 @@ set(ASAN_CXX_SOURCES
|
|||
asan_new_delete.cpp
|
||||
)
|
||||
|
||||
set(ASAN_STATIC_SOURCES
|
||||
asan_rtl_static.cpp
|
||||
)
|
||||
|
||||
if (NOT WIN32 AND NOT APPLE)
|
||||
list(APPEND ASAN_STATIC_SOURCES
|
||||
asan_rtl_x86_64.S
|
||||
)
|
||||
endif()
|
||||
|
||||
set(ASAN_PREINIT_SOURCES
|
||||
asan_preinit.cpp
|
||||
)
|
||||
|
@ -80,6 +90,14 @@ set(ASAN_COMMON_DEFINITIONS ${COMPILER_RT_ASAN_SHADOW_SCALE_DEFINITION})
|
|||
|
||||
append_rtti_flag(OFF ASAN_CFLAGS)
|
||||
|
||||
# Silence warnings in system headers with MSVC.
|
||||
if(NOT CLANG_CL)
|
||||
append_list_if(COMPILER_RT_HAS_EXTERNAL_FLAG "/experimental:external /external:W0 /external:anglebrackets" ASAN_CFLAGS)
|
||||
endif()
|
||||
|
||||
# Too many existing bugs, needs cleanup.
|
||||
append_list_if(COMPILER_RT_HAS_WNO_FORMAT -Wno-format ASAN_CFLAGS)
|
||||
|
||||
set(ASAN_DYNAMIC_LINK_FLAGS ${SANITIZER_COMMON_LINK_FLAGS})
|
||||
|
||||
if(ANDROID)
|
||||
|
@ -99,7 +117,10 @@ append_list_if(COMPILER_RT_HAS_FTLS_MODEL_INITIAL_EXEC
|
|||
-ftls-model=initial-exec ASAN_DYNAMIC_CFLAGS)
|
||||
append_list_if(MSVC /DEBUG ASAN_DYNAMIC_LINK_FLAGS)
|
||||
|
||||
set(ASAN_DYNAMIC_LIBS ${SANITIZER_CXX_ABI_LIBRARIES} ${SANITIZER_COMMON_LINK_LIBS})
|
||||
set(ASAN_DYNAMIC_LIBS
|
||||
${COMPILER_RT_UNWINDER_LINK_LIBS}
|
||||
${SANITIZER_CXX_ABI_LIBRARIES}
|
||||
${SANITIZER_COMMON_LINK_LIBS})
|
||||
|
||||
append_list_if(COMPILER_RT_HAS_LIBDL dl ASAN_DYNAMIC_LIBS)
|
||||
append_list_if(COMPILER_RT_HAS_LIBRT rt ASAN_DYNAMIC_LIBS)
|
||||
|
@ -131,6 +152,12 @@ if(NOT APPLE)
|
|||
ADDITIONAL_HEADERS ${ASAN_HEADERS}
|
||||
CFLAGS ${ASAN_CFLAGS}
|
||||
DEFS ${ASAN_COMMON_DEFINITIONS})
|
||||
add_compiler_rt_object_libraries(RTAsan_static
|
||||
ARCHS ${ASAN_SUPPORTED_ARCH}
|
||||
SOURCES ${ASAN_STATIC_SOURCES}
|
||||
ADDITIONAL_HEADERS ${ASAN_HEADERS}
|
||||
CFLAGS ${ASAN_CFLAGS}
|
||||
DEFS ${ASAN_COMMON_DEFINITIONS})
|
||||
add_compiler_rt_object_libraries(RTAsan_preinit
|
||||
ARCHS ${ASAN_SUPPORTED_ARCH}
|
||||
SOURCES ${ASAN_PREINIT_SOURCES}
|
||||
|
@ -172,6 +199,14 @@ if(APPLE)
|
|||
LINK_FLAGS ${WEAK_SYMBOL_LINK_FLAGS}
|
||||
DEFS ${ASAN_DYNAMIC_DEFINITIONS}
|
||||
PARENT_TARGET asan)
|
||||
|
||||
add_compiler_rt_runtime(clang_rt.asan_static
|
||||
STATIC
|
||||
ARCHS ${ASAN_SUPPORTED_ARCH}
|
||||
OBJECT_LIBS RTAsan_static
|
||||
CFLAGS ${ASAN_CFLAGS}
|
||||
DEFS ${ASAN_COMMON_DEFINITIONS}
|
||||
PARENT_TARGET asan)
|
||||
else()
|
||||
# Build separate libraries for each target.
|
||||
|
||||
|
@ -203,6 +238,14 @@ else()
|
|||
DEFS ${ASAN_COMMON_DEFINITIONS}
|
||||
PARENT_TARGET asan)
|
||||
|
||||
add_compiler_rt_runtime(clang_rt.asan_static
|
||||
STATIC
|
||||
ARCHS ${ASAN_SUPPORTED_ARCH}
|
||||
OBJECT_LIBS RTAsan_static
|
||||
CFLAGS ${ASAN_CFLAGS}
|
||||
DEFS ${ASAN_COMMON_DEFINITIONS}
|
||||
PARENT_TARGET asan)
|
||||
|
||||
add_compiler_rt_runtime(clang_rt.asan-preinit
|
||||
STATIC
|
||||
ARCHS ${ASAN_SUPPORTED_ARCH}
|
||||
|
@ -236,7 +279,8 @@ else()
|
|||
add_compiler_rt_object_libraries(AsanWeakInterception
|
||||
${SANITIZER_COMMON_SUPPORTED_OS}
|
||||
ARCHS ${arch}
|
||||
SOURCES asan_win_weak_interception.cpp
|
||||
SOURCES
|
||||
asan_win_weak_interception.cpp
|
||||
CFLAGS ${ASAN_CFLAGS} -DSANITIZER_DYNAMIC
|
||||
DEFS ${ASAN_COMMON_DEFINITIONS})
|
||||
set(ASAN_DYNAMIC_WEAK_INTERCEPTION
|
||||
|
|
|
@ -112,7 +112,7 @@ void AsanDeactivate() {
|
|||
disabled.quarantine_size_mb = 0;
|
||||
disabled.thread_local_quarantine_size_kb = 0;
|
||||
// Redzone must be at least Max(16, granularity) bytes long.
|
||||
disabled.min_redzone = Max(16, (int)SHADOW_GRANULARITY);
|
||||
disabled.min_redzone = Max(16, (int)ASAN_SHADOW_GRANULARITY);
|
||||
disabled.max_redzone = disabled.min_redzone;
|
||||
disabled.alloc_dealloc_mismatch = false;
|
||||
disabled.may_return_null = true;
|
||||
|
|
|
@ -102,19 +102,18 @@ class ChunkHeader {
|
|||
|
||||
public:
|
||||
uptr UsedSize() const {
|
||||
uptr R = user_requested_size_lo;
|
||||
if (sizeof(uptr) > sizeof(user_requested_size_lo))
|
||||
R += (uptr)user_requested_size_hi << (8 * sizeof(user_requested_size_lo));
|
||||
return R;
|
||||
static_assert(sizeof(user_requested_size_lo) == 4,
|
||||
"Expression below requires this");
|
||||
return FIRST_32_SECOND_64(0, ((uptr)user_requested_size_hi << 32)) +
|
||||
user_requested_size_lo;
|
||||
}
|
||||
|
||||
void SetUsedSize(uptr size) {
|
||||
user_requested_size_lo = size;
|
||||
if (sizeof(uptr) > sizeof(user_requested_size_lo)) {
|
||||
size >>= (8 * sizeof(user_requested_size_lo));
|
||||
user_requested_size_hi = size;
|
||||
CHECK_EQ(user_requested_size_hi, size);
|
||||
}
|
||||
static_assert(sizeof(user_requested_size_lo) == 4,
|
||||
"Expression below requires this");
|
||||
user_requested_size_hi = FIRST_32_SECOND_64(0, size >> 32);
|
||||
CHECK_EQ(UsedSize(), size);
|
||||
}
|
||||
|
||||
void SetAllocContext(u32 tid, u32 stack) {
|
||||
|
@ -211,8 +210,7 @@ struct QuarantineCallback {
|
|||
CHECK_EQ(old_chunk_state, CHUNK_QUARANTINE);
|
||||
}
|
||||
|
||||
PoisonShadow(m->Beg(),
|
||||
RoundUpTo(m->UsedSize(), SHADOW_GRANULARITY),
|
||||
PoisonShadow(m->Beg(), RoundUpTo(m->UsedSize(), ASAN_SHADOW_GRANULARITY),
|
||||
kAsanHeapLeftRedzoneMagic);
|
||||
|
||||
// Statistics.
|
||||
|
@ -306,7 +304,6 @@ struct Allocator {
|
|||
QuarantineCache fallback_quarantine_cache;
|
||||
|
||||
uptr max_user_defined_malloc_size;
|
||||
atomic_uint8_t rss_limit_exceeded;
|
||||
|
||||
// ------------------- Options --------------------------
|
||||
atomic_uint16_t min_redzone;
|
||||
|
@ -346,14 +343,6 @@ struct Allocator {
|
|||
: kMaxAllowedMallocSize;
|
||||
}
|
||||
|
||||
bool RssLimitExceeded() {
|
||||
return atomic_load(&rss_limit_exceeded, memory_order_relaxed);
|
||||
}
|
||||
|
||||
void SetRssLimitExceeded(bool limit_exceeded) {
|
||||
atomic_store(&rss_limit_exceeded, limit_exceeded, memory_order_relaxed);
|
||||
}
|
||||
|
||||
void RePoisonChunk(uptr chunk) {
|
||||
// This could be a user-facing chunk (with redzones), or some internal
|
||||
// housekeeping chunk, like TransferBatch. Start by assuming the former.
|
||||
|
@ -367,7 +356,7 @@ struct Allocator {
|
|||
if (chunk < beg && beg < end && end <= chunk_end) {
|
||||
// Looks like a valid AsanChunk in use, poison redzones only.
|
||||
PoisonShadow(chunk, beg - chunk, kAsanHeapLeftRedzoneMagic);
|
||||
uptr end_aligned_down = RoundDownTo(end, SHADOW_GRANULARITY);
|
||||
uptr end_aligned_down = RoundDownTo(end, ASAN_SHADOW_GRANULARITY);
|
||||
FastPoisonShadowPartialRightRedzone(
|
||||
end_aligned_down, end - end_aligned_down,
|
||||
chunk_end - end_aligned_down, kAsanHeapLeftRedzoneMagic);
|
||||
|
@ -485,14 +474,14 @@ struct Allocator {
|
|||
AllocType alloc_type, bool can_fill) {
|
||||
if (UNLIKELY(!asan_inited))
|
||||
AsanInitFromRtl();
|
||||
if (RssLimitExceeded()) {
|
||||
if (UNLIKELY(IsRssLimitExceeded())) {
|
||||
if (AllocatorMayReturnNull())
|
||||
return nullptr;
|
||||
ReportRssLimitExceeded(stack);
|
||||
}
|
||||
Flags &fl = *flags();
|
||||
CHECK(stack);
|
||||
const uptr min_alignment = SHADOW_GRANULARITY;
|
||||
const uptr min_alignment = ASAN_SHADOW_GRANULARITY;
|
||||
const uptr user_requested_alignment_log =
|
||||
ComputeUserRequestedAlignmentLog(alignment);
|
||||
if (alignment < min_alignment)
|
||||
|
@ -522,7 +511,7 @@ struct Allocator {
|
|||
size > max_user_defined_malloc_size) {
|
||||
if (AllocatorMayReturnNull()) {
|
||||
Report("WARNING: AddressSanitizer failed to allocate 0x%zx bytes\n",
|
||||
(void*)size);
|
||||
size);
|
||||
return nullptr;
|
||||
}
|
||||
uptr malloc_limit =
|
||||
|
@ -573,7 +562,7 @@ struct Allocator {
|
|||
m->SetAllocContext(t ? t->tid() : kMainTid, StackDepotPut(*stack));
|
||||
|
||||
uptr size_rounded_down_to_granularity =
|
||||
RoundDownTo(size, SHADOW_GRANULARITY);
|
||||
RoundDownTo(size, ASAN_SHADOW_GRANULARITY);
|
||||
// Unpoison the bulk of the memory region.
|
||||
if (size_rounded_down_to_granularity)
|
||||
PoisonShadow(user_beg, size_rounded_down_to_granularity, 0);
|
||||
|
@ -581,7 +570,7 @@ struct Allocator {
|
|||
if (size != size_rounded_down_to_granularity && CanPoisonMemory()) {
|
||||
u8 *shadow =
|
||||
(u8 *)MemToShadow(user_beg + size_rounded_down_to_granularity);
|
||||
*shadow = fl.poison_partial ? (size & (SHADOW_GRANULARITY - 1)) : 0;
|
||||
*shadow = fl.poison_partial ? (size & (ASAN_SHADOW_GRANULARITY - 1)) : 0;
|
||||
}
|
||||
|
||||
AsanStats &thread_stats = GetCurrentThreadStats();
|
||||
|
@ -608,7 +597,7 @@ struct Allocator {
|
|||
CHECK_LE(alloc_beg + sizeof(LargeChunkHeader), chunk_beg);
|
||||
reinterpret_cast<LargeChunkHeader *>(alloc_beg)->Set(m);
|
||||
}
|
||||
ASAN_MALLOC_HOOK(res, size);
|
||||
RunMallocHooks(res, size);
|
||||
return res;
|
||||
}
|
||||
|
||||
|
@ -651,8 +640,7 @@ struct Allocator {
|
|||
}
|
||||
|
||||
// Poison the region.
|
||||
PoisonShadow(m->Beg(),
|
||||
RoundUpTo(m->UsedSize(), SHADOW_GRANULARITY),
|
||||
PoisonShadow(m->Beg(), RoundUpTo(m->UsedSize(), ASAN_SHADOW_GRANULARITY),
|
||||
kAsanHeapFreeMagic);
|
||||
|
||||
AsanStats &thread_stats = GetCurrentThreadStats();
|
||||
|
@ -690,7 +678,7 @@ struct Allocator {
|
|||
return;
|
||||
}
|
||||
|
||||
ASAN_FREE_HOOK(ptr);
|
||||
RunFreeHooks(ptr);
|
||||
|
||||
// Must mark the chunk as quarantined before any changes to its metadata.
|
||||
// Do not quarantine given chunk if we failed to set CHUNK_QUARANTINE flag.
|
||||
|
@ -815,8 +803,8 @@ struct Allocator {
|
|||
sptr offset = 0;
|
||||
if (!m1 || AsanChunkView(m1).AddrIsAtLeft(addr, 1, &offset)) {
|
||||
// The address is in the chunk's left redzone, so maybe it is actually
|
||||
// a right buffer overflow from the other chunk to the left.
|
||||
// Search a bit to the left to see if there is another chunk.
|
||||
// a right buffer overflow from the other chunk before.
|
||||
// Search a bit before to see if there is another chunk.
|
||||
AsanChunk *m2 = nullptr;
|
||||
for (uptr l = 1; l < GetPageSizeCached(); l++) {
|
||||
m2 = GetAsanChunkByAddr(addr - l);
|
||||
|
@ -852,12 +840,12 @@ struct Allocator {
|
|||
quarantine.PrintStats();
|
||||
}
|
||||
|
||||
void ForceLock() ACQUIRE(fallback_mutex) {
|
||||
void ForceLock() SANITIZER_ACQUIRE(fallback_mutex) {
|
||||
allocator.ForceLock();
|
||||
fallback_mutex.Lock();
|
||||
}
|
||||
|
||||
void ForceUnlock() RELEASE(fallback_mutex) {
|
||||
void ForceUnlock() SANITIZER_RELEASE(fallback_mutex) {
|
||||
fallback_mutex.Unlock();
|
||||
allocator.ForceUnlock();
|
||||
}
|
||||
|
@ -908,13 +896,6 @@ AllocType AsanChunkView::GetAllocType() const {
|
|||
return (AllocType)chunk_->alloc_type;
|
||||
}
|
||||
|
||||
static StackTrace GetStackTraceFromId(u32 id) {
|
||||
CHECK(id);
|
||||
StackTrace res = StackDepotGet(id);
|
||||
CHECK(res.trace);
|
||||
return res;
|
||||
}
|
||||
|
||||
u32 AsanChunkView::GetAllocStackId() const {
|
||||
u32 tid = 0;
|
||||
u32 stack = 0;
|
||||
|
@ -931,14 +912,6 @@ u32 AsanChunkView::GetFreeStackId() const {
|
|||
return stack;
|
||||
}
|
||||
|
||||
StackTrace AsanChunkView::GetAllocStack() const {
|
||||
return GetStackTraceFromId(GetAllocStackId());
|
||||
}
|
||||
|
||||
StackTrace AsanChunkView::GetFreeStack() const {
|
||||
return GetStackTraceFromId(GetFreeStackId());
|
||||
}
|
||||
|
||||
void InitializeAllocator(const AllocatorOptions &options) {
|
||||
instance.InitLinkerInitialized(options);
|
||||
}
|
||||
|
@ -1081,14 +1054,12 @@ uptr asan_mz_size(const void *ptr) {
|
|||
return instance.AllocationSize(reinterpret_cast<uptr>(ptr));
|
||||
}
|
||||
|
||||
void asan_mz_force_lock() NO_THREAD_SAFETY_ANALYSIS { instance.ForceLock(); }
|
||||
|
||||
void asan_mz_force_unlock() NO_THREAD_SAFETY_ANALYSIS {
|
||||
instance.ForceUnlock();
|
||||
void asan_mz_force_lock() SANITIZER_NO_THREAD_SAFETY_ANALYSIS {
|
||||
instance.ForceLock();
|
||||
}
|
||||
|
||||
void AsanSoftRssLimitExceededCallback(bool limit_exceeded) {
|
||||
instance.SetRssLimitExceeded(limit_exceeded);
|
||||
void asan_mz_force_unlock() SANITIZER_NO_THREAD_SAFETY_ANALYSIS {
|
||||
instance.ForceUnlock();
|
||||
}
|
||||
|
||||
} // namespace __asan
|
||||
|
@ -1123,6 +1094,8 @@ uptr PointsIntoChunk(void *p) {
|
|||
}
|
||||
|
||||
uptr GetUserBegin(uptr chunk) {
|
||||
// FIXME: All usecases provide chunk address, GetAsanChunkByAddrFastLocked is
|
||||
// not needed.
|
||||
__asan::AsanChunk *m = __asan::instance.GetAsanChunkByAddrFastLocked(chunk);
|
||||
return m ? m->Beg() : 0;
|
||||
}
|
||||
|
@ -1182,33 +1155,6 @@ IgnoreObjectResult IgnoreObjectLocked(const void *p) {
|
|||
return kIgnoreObjectSuccess;
|
||||
}
|
||||
|
||||
void GetAdditionalThreadContextPtrs(ThreadContextBase *tctx, void *ptrs) {
|
||||
// Look for the arg pointer of threads that have been created or are running.
|
||||
// This is necessary to prevent false positive leaks due to the AsanThread
|
||||
// holding the only live reference to a heap object. This can happen because
|
||||
// the `pthread_create()` interceptor doesn't wait for the child thread to
|
||||
// start before returning and thus loosing the the only live reference to the
|
||||
// heap object on the stack.
|
||||
|
||||
__asan::AsanThreadContext *atctx =
|
||||
reinterpret_cast<__asan::AsanThreadContext *>(tctx);
|
||||
__asan::AsanThread *asan_thread = atctx->thread;
|
||||
|
||||
// Note ThreadStatusRunning is required because there is a small window where
|
||||
// the thread status switches to `ThreadStatusRunning` but the `arg` pointer
|
||||
// still isn't on the stack yet.
|
||||
if (atctx->status != ThreadStatusCreated &&
|
||||
atctx->status != ThreadStatusRunning)
|
||||
return;
|
||||
|
||||
uptr thread_arg = reinterpret_cast<uptr>(asan_thread->get_arg());
|
||||
if (!thread_arg)
|
||||
return;
|
||||
|
||||
auto ptrsVec = reinterpret_cast<InternalMmapVector<uptr> *>(ptrs);
|
||||
ptrsVec->push_back(thread_arg);
|
||||
}
|
||||
|
||||
} // namespace __lsan
|
||||
|
||||
// ---------------------- Interface ---------------- {{{1
|
||||
|
@ -1246,16 +1192,3 @@ int __asan_update_allocation_context(void* addr) {
|
|||
GET_STACK_TRACE_MALLOC;
|
||||
return instance.UpdateAllocationStack((uptr)addr, &stack);
|
||||
}
|
||||
|
||||
#if !SANITIZER_SUPPORTS_WEAK_HOOKS
|
||||
// Provide default (no-op) implementation of malloc hooks.
|
||||
SANITIZER_INTERFACE_WEAK_DEF(void, __sanitizer_malloc_hook,
|
||||
void *ptr, uptr size) {
|
||||
(void)ptr;
|
||||
(void)size;
|
||||
}
|
||||
|
||||
SANITIZER_INTERFACE_WEAK_DEF(void, __sanitizer_free_hook, void *ptr) {
|
||||
(void)ptr;
|
||||
}
|
||||
#endif
|
||||
|
|
|
@ -64,8 +64,6 @@ class AsanChunkView {
|
|||
bool Eq(const AsanChunkView &c) const { return chunk_ == c.chunk_; }
|
||||
u32 GetAllocStackId() const;
|
||||
u32 GetFreeStackId() const;
|
||||
StackTrace GetAllocStack() const;
|
||||
StackTrace GetFreeStack() const;
|
||||
AllocType GetAllocType() const;
|
||||
bool AddrIsInside(uptr addr, uptr access_size, sptr *offset) const {
|
||||
if (addr >= Beg() && (addr + access_size) <= End()) {
|
||||
|
@ -137,12 +135,6 @@ typedef VeryCompactSizeClassMap SizeClassMap;
|
|||
const uptr kAllocatorSpace = ~(uptr)0;
|
||||
const uptr kAllocatorSize = 0x2000000000ULL; // 128G.
|
||||
typedef VeryDenseSizeClassMap SizeClassMap;
|
||||
# elif defined(__aarch64__)
|
||||
// AArch64/SANITIZER_CAN_USE_ALLOCATOR64 is only for 42-bit VMA
|
||||
// so no need to different values for different VMA.
|
||||
const uptr kAllocatorSpace = 0x10000000000ULL;
|
||||
const uptr kAllocatorSize = 0x10000000000ULL; // 3T.
|
||||
typedef DefaultSizeClassMap SizeClassMap;
|
||||
#elif defined(__sparc__)
|
||||
const uptr kAllocatorSpace = ~(uptr)0;
|
||||
const uptr kAllocatorSize = 0x20000000000ULL; // 2T.
|
||||
|
|
|
@ -19,6 +19,7 @@
|
|||
#include "asan_mapping.h"
|
||||
#include "asan_report.h"
|
||||
#include "asan_thread.h"
|
||||
#include "sanitizer_common/sanitizer_stackdepot.h"
|
||||
|
||||
namespace {
|
||||
using namespace __asan;
|
||||
|
@ -54,11 +55,11 @@ uptr AsanGetStack(uptr addr, uptr *trace, u32 size, u32 *thread_id,
|
|||
StackTrace stack(nullptr, 0);
|
||||
if (alloc_stack) {
|
||||
if (chunk.AllocTid() == kInvalidTid) return 0;
|
||||
stack = chunk.GetAllocStack();
|
||||
stack = StackDepotGet(chunk.GetAllocStackId());
|
||||
if (thread_id) *thread_id = chunk.AllocTid();
|
||||
} else {
|
||||
if (chunk.FreeTid() == kInvalidTid) return 0;
|
||||
stack = chunk.GetFreeStack();
|
||||
stack = StackDepotGet(chunk.GetFreeStackId());
|
||||
if (thread_id) *thread_id = chunk.FreeTid();
|
||||
}
|
||||
|
||||
|
@ -140,7 +141,7 @@ uptr __asan_get_free_stack(uptr addr, uptr *trace, uptr size, u32 *thread_id) {
|
|||
SANITIZER_INTERFACE_ATTRIBUTE
|
||||
void __asan_get_shadow_mapping(uptr *shadow_scale, uptr *shadow_offset) {
|
||||
if (shadow_scale)
|
||||
*shadow_scale = SHADOW_SCALE;
|
||||
*shadow_scale = ASAN_SHADOW_SCALE;
|
||||
if (shadow_offset)
|
||||
*shadow_offset = SHADOW_OFFSET;
|
||||
*shadow_offset = ASAN_SHADOW_OFFSET;
|
||||
}
|
||||
|
|
|
@ -129,11 +129,11 @@ static void PrintHeapChunkAccess(uptr addr, const ChunkAccess &descr) {
|
|||
str.append("%s", d.Location());
|
||||
switch (descr.access_type) {
|
||||
case kAccessTypeLeft:
|
||||
str.append("%p is located %zd bytes to the left of",
|
||||
str.append("%p is located %zd bytes before",
|
||||
(void *)descr.bad_addr, descr.offset);
|
||||
break;
|
||||
case kAccessTypeRight:
|
||||
str.append("%p is located %zd bytes to the right of",
|
||||
str.append("%p is located %zd bytes after",
|
||||
(void *)descr.bad_addr, descr.offset);
|
||||
break;
|
||||
case kAccessTypeInside:
|
||||
|
@ -251,7 +251,7 @@ static void PrintAccessAndVarIntersection(const StackVarDescr &var, uptr addr,
|
|||
}
|
||||
str.append("'");
|
||||
if (var.line > 0) {
|
||||
str.append(" (line %d)", var.line);
|
||||
str.append(" (line %zd)", var.line);
|
||||
}
|
||||
if (pos_descr) {
|
||||
Decorator d;
|
||||
|
@ -279,17 +279,17 @@ static void DescribeAddressRelativeToGlobal(uptr addr, uptr access_size,
|
|||
Decorator d;
|
||||
str.append("%s", d.Location());
|
||||
if (addr < g.beg) {
|
||||
str.append("%p is located %zd bytes to the left", (void *)addr,
|
||||
str.append("%p is located %zd bytes before", (void *)addr,
|
||||
g.beg - addr);
|
||||
} else if (addr + access_size > g.beg + g.size) {
|
||||
if (addr < g.beg + g.size) addr = g.beg + g.size;
|
||||
str.append("%p is located %zd bytes to the right", (void *)addr,
|
||||
str.append("%p is located %zd bytes after", (void *)addr,
|
||||
addr - (g.beg + g.size));
|
||||
} else {
|
||||
// Can it happen?
|
||||
str.append("%p is located %zd bytes inside", (void *)addr, addr - g.beg);
|
||||
str.append("%p is located %zd bytes inside of", (void *)addr, addr - g.beg);
|
||||
}
|
||||
str.append(" of global variable '%s' defined in '",
|
||||
str.append(" global variable '%s' defined in '",
|
||||
MaybeDemangleGlobalName(g.name));
|
||||
PrintGlobalLocation(&str, g);
|
||||
str.append("' (0x%zx) of size %zu\n", g.beg, g.size);
|
||||
|
@ -318,7 +318,8 @@ bool DescribeAddressIfGlobal(uptr addr, uptr access_size,
|
|||
}
|
||||
|
||||
void ShadowAddressDescription::Print() const {
|
||||
Printf("Address %p is located in the %s area.\n", addr, ShadowNames[kind]);
|
||||
Printf("Address %p is located in the %s area.\n", (void *)addr,
|
||||
ShadowNames[kind]);
|
||||
}
|
||||
|
||||
void GlobalAddressDescription::Print(const char *bug_type) const {
|
||||
|
@ -356,7 +357,7 @@ bool GlobalAddressDescription::PointsInsideTheSameVariable(
|
|||
void StackAddressDescription::Print() const {
|
||||
Decorator d;
|
||||
Printf("%s", d.Location());
|
||||
Printf("Address %p is located in stack of thread %s", addr,
|
||||
Printf("Address %p is located in stack of thread %s", (void *)addr,
|
||||
AsanThreadIdAndName(tid).c_str());
|
||||
|
||||
if (!frame_descr) {
|
||||
|
@ -469,7 +470,7 @@ AddressDescription::AddressDescription(uptr addr, uptr access_size,
|
|||
|
||||
void WildAddressDescription::Print() const {
|
||||
Printf("Address %p is a wild pointer inside of access range of size %p.\n",
|
||||
addr, access_size);
|
||||
(void *)addr, (void *)access_size);
|
||||
}
|
||||
|
||||
void PrintAddressDescription(uptr addr, uptr access_size,
|
||||
|
|
|
@ -46,10 +46,9 @@ void ErrorDeadlySignal::Print() {
|
|||
void ErrorDoubleFree::Print() {
|
||||
Decorator d;
|
||||
Printf("%s", d.Error());
|
||||
Report(
|
||||
"ERROR: AddressSanitizer: attempting %s on %p in thread %s:\n",
|
||||
scariness.GetDescription(), addr_description.addr,
|
||||
AsanThreadIdAndName(tid).c_str());
|
||||
Report("ERROR: AddressSanitizer: attempting %s on %p in thread %s:\n",
|
||||
scariness.GetDescription(), (void *)addr_description.addr,
|
||||
AsanThreadIdAndName(tid).c_str());
|
||||
Printf("%s", d.Default());
|
||||
scariness.Print();
|
||||
GET_STACK_TRACE_FATAL(second_free_stack->trace[0],
|
||||
|
@ -62,10 +61,9 @@ void ErrorDoubleFree::Print() {
|
|||
void ErrorNewDeleteTypeMismatch::Print() {
|
||||
Decorator d;
|
||||
Printf("%s", d.Error());
|
||||
Report(
|
||||
"ERROR: AddressSanitizer: %s on %p in thread %s:\n",
|
||||
scariness.GetDescription(), addr_description.addr,
|
||||
AsanThreadIdAndName(tid).c_str());
|
||||
Report("ERROR: AddressSanitizer: %s on %p in thread %s:\n",
|
||||
scariness.GetDescription(), (void *)addr_description.addr,
|
||||
AsanThreadIdAndName(tid).c_str());
|
||||
Printf("%s object passed to delete has wrong type:\n", d.Default());
|
||||
if (delete_size != 0) {
|
||||
Printf(
|
||||
|
@ -106,7 +104,7 @@ void ErrorFreeNotMalloced::Print() {
|
|||
Report(
|
||||
"ERROR: AddressSanitizer: attempting free on address "
|
||||
"which was not malloc()-ed: %p in thread %s\n",
|
||||
addr_description.Address(), AsanThreadIdAndName(tid).c_str());
|
||||
(void *)addr_description.Address(), AsanThreadIdAndName(tid).c_str());
|
||||
Printf("%s", d.Default());
|
||||
CHECK_GT(free_stack->size, 0);
|
||||
scariness.Print();
|
||||
|
@ -126,7 +124,7 @@ void ErrorAllocTypeMismatch::Print() {
|
|||
Printf("%s", d.Error());
|
||||
Report("ERROR: AddressSanitizer: %s (%s vs %s) on %p\n",
|
||||
scariness.GetDescription(), alloc_names[alloc_type],
|
||||
dealloc_names[dealloc_type], addr_description.Address());
|
||||
dealloc_names[dealloc_type], (void *)addr_description.Address());
|
||||
Printf("%s", d.Default());
|
||||
CHECK_GT(dealloc_stack->size, 0);
|
||||
scariness.Print();
|
||||
|
@ -145,7 +143,7 @@ void ErrorMallocUsableSizeNotOwned::Print() {
|
|||
Report(
|
||||
"ERROR: AddressSanitizer: attempting to call malloc_usable_size() for "
|
||||
"pointer which is not owned: %p\n",
|
||||
addr_description.Address());
|
||||
(void *)addr_description.Address());
|
||||
Printf("%s", d.Default());
|
||||
stack->Print();
|
||||
addr_description.Print();
|
||||
|
@ -158,7 +156,7 @@ void ErrorSanitizerGetAllocatedSizeNotOwned::Print() {
|
|||
Report(
|
||||
"ERROR: AddressSanitizer: attempting to call "
|
||||
"__sanitizer_get_allocated_size() for pointer which is not owned: %p\n",
|
||||
addr_description.Address());
|
||||
(void *)addr_description.Address());
|
||||
Printf("%s", d.Default());
|
||||
stack->Print();
|
||||
addr_description.Print();
|
||||
|
@ -281,9 +279,7 @@ void ErrorRssLimitExceeded::Print() {
|
|||
void ErrorOutOfMemory::Print() {
|
||||
Decorator d;
|
||||
Printf("%s", d.Error());
|
||||
Report(
|
||||
"ERROR: AddressSanitizer: allocator is out of memory trying to allocate "
|
||||
"0x%zx bytes\n", requested_size);
|
||||
ERROR_OOM("allocator is trying to allocate 0x%zx bytes\n", requested_size);
|
||||
Printf("%s", d.Default());
|
||||
stack->Print();
|
||||
PrintHintAllocatorCannotReturnNull();
|
||||
|
@ -298,9 +294,10 @@ void ErrorStringFunctionMemoryRangesOverlap::Print() {
|
|||
Report(
|
||||
"ERROR: AddressSanitizer: %s: memory ranges [%p,%p) and [%p, %p) "
|
||||
"overlap\n",
|
||||
bug_type, addr1_description.Address(),
|
||||
addr1_description.Address() + length1, addr2_description.Address(),
|
||||
addr2_description.Address() + length2);
|
||||
bug_type, (void *)addr1_description.Address(),
|
||||
(void *)(addr1_description.Address() + length1),
|
||||
(void *)addr2_description.Address(),
|
||||
(void *)(addr2_description.Address() + length2));
|
||||
Printf("%s", d.Default());
|
||||
scariness.Print();
|
||||
stack->Print();
|
||||
|
@ -329,10 +326,30 @@ void ErrorBadParamsToAnnotateContiguousContainer::Print() {
|
|||
" end : %p\n"
|
||||
" old_mid : %p\n"
|
||||
" new_mid : %p\n",
|
||||
beg, end, old_mid, new_mid);
|
||||
uptr granularity = SHADOW_GRANULARITY;
|
||||
(void *)beg, (void *)end, (void *)old_mid, (void *)new_mid);
|
||||
uptr granularity = ASAN_SHADOW_GRANULARITY;
|
||||
if (!IsAligned(beg, granularity))
|
||||
Report("ERROR: beg is not aligned by %d\n", granularity);
|
||||
Report("ERROR: beg is not aligned by %zu\n", granularity);
|
||||
stack->Print();
|
||||
ReportErrorSummary(scariness.GetDescription(), stack);
|
||||
}
|
||||
|
||||
void ErrorBadParamsToAnnotateDoubleEndedContiguousContainer::Print() {
|
||||
Report(
|
||||
"ERROR: AddressSanitizer: bad parameters to "
|
||||
"__sanitizer_annotate_double_ended_contiguous_container:\n"
|
||||
" storage_beg : %p\n"
|
||||
" storage_end : %p\n"
|
||||
" old_container_beg : %p\n"
|
||||
" old_container_end : %p\n"
|
||||
" new_container_beg : %p\n"
|
||||
" new_container_end : %p\n",
|
||||
(void *)storage_beg, (void *)storage_end, (void *)old_container_beg,
|
||||
(void *)old_container_end, (void *)new_container_beg,
|
||||
(void *)new_container_end);
|
||||
uptr granularity = ASAN_SHADOW_GRANULARITY;
|
||||
if (!IsAligned(storage_beg, granularity))
|
||||
Report("ERROR: storage_beg is not aligned by %zu\n", granularity);
|
||||
stack->Print();
|
||||
ReportErrorSummary(scariness.GetDescription(), stack);
|
||||
}
|
||||
|
@ -341,7 +358,7 @@ void ErrorODRViolation::Print() {
|
|||
Decorator d;
|
||||
Printf("%s", d.Error());
|
||||
Report("ERROR: AddressSanitizer: %s (%p):\n", scariness.GetDescription(),
|
||||
global1.beg);
|
||||
(void *)global1.beg);
|
||||
Printf("%s", d.Default());
|
||||
InternalScopedString g1_loc;
|
||||
InternalScopedString g2_loc;
|
||||
|
@ -371,7 +388,8 @@ void ErrorInvalidPointerPair::Print() {
|
|||
Decorator d;
|
||||
Printf("%s", d.Error());
|
||||
Report("ERROR: AddressSanitizer: %s: %p %p\n", scariness.GetDescription(),
|
||||
addr1_description.Address(), addr2_description.Address());
|
||||
(void *)addr1_description.Address(),
|
||||
(void *)addr2_description.Address());
|
||||
Printf("%s", d.Default());
|
||||
GET_STACK_TRACE_FATAL(pc, bp);
|
||||
stack.Print();
|
||||
|
@ -410,7 +428,8 @@ ErrorGeneric::ErrorGeneric(u32 tid, uptr pc_, uptr bp_, uptr sp_, uptr addr,
|
|||
if (AddrIsInMem(addr)) {
|
||||
u8 *shadow_addr = (u8 *)MemToShadow(addr);
|
||||
// If we are accessing 16 bytes, look at the second shadow byte.
|
||||
if (*shadow_addr == 0 && access_size > SHADOW_GRANULARITY) shadow_addr++;
|
||||
if (*shadow_addr == 0 && access_size > ASAN_SHADOW_GRANULARITY)
|
||||
shadow_addr++;
|
||||
// If we are in the partial right redzone, look at the next shadow byte.
|
||||
if (*shadow_addr > 0 && *shadow_addr < 128) shadow_addr++;
|
||||
bool far_from_bounds = false;
|
||||
|
@ -501,10 +520,11 @@ static void PrintLegend(InternalScopedString *str) {
|
|||
str->append(
|
||||
"Shadow byte legend (one shadow byte represents %d "
|
||||
"application bytes):\n",
|
||||
(int)SHADOW_GRANULARITY);
|
||||
(int)ASAN_SHADOW_GRANULARITY);
|
||||
PrintShadowByte(str, " Addressable: ", 0);
|
||||
str->append(" Partially addressable: ");
|
||||
for (u8 i = 1; i < SHADOW_GRANULARITY; i++) PrintShadowByte(str, "", i, " ");
|
||||
for (u8 i = 1; i < ASAN_SHADOW_GRANULARITY; i++)
|
||||
PrintShadowByte(str, "", i, " ");
|
||||
str->append("\n");
|
||||
PrintShadowByte(str, " Heap left redzone: ",
|
||||
kAsanHeapLeftRedzoneMagic);
|
||||
|
@ -538,7 +558,9 @@ static void PrintLegend(InternalScopedString *str) {
|
|||
static void PrintShadowBytes(InternalScopedString *str, const char *before,
|
||||
u8 *bytes, u8 *guilty, uptr n) {
|
||||
Decorator d;
|
||||
if (before) str->append("%s%p:", before, bytes);
|
||||
if (before)
|
||||
str->append("%s%p:", before,
|
||||
(void *)ShadowToMem(reinterpret_cast<uptr>(bytes)));
|
||||
for (uptr i = 0; i < n; i++) {
|
||||
u8 *p = bytes + i;
|
||||
const char *before =
|
||||
|
@ -575,7 +597,7 @@ void ErrorGeneric::Print() {
|
|||
Printf("%s", d.Error());
|
||||
uptr addr = addr_description.Address();
|
||||
Report("ERROR: AddressSanitizer: %s on address %p at pc %p bp %p sp %p\n",
|
||||
bug_descr, (void *)addr, pc, bp, sp);
|
||||
bug_descr, (void *)addr, (void *)pc, (void *)bp, (void *)sp);
|
||||
Printf("%s", d.Default());
|
||||
|
||||
Printf("%s%s of size %zu at %p thread %s%s\n", d.Access(),
|
||||
|
|
|
@ -53,9 +53,9 @@ struct ErrorDeadlySignal : ErrorBase {
|
|||
scariness.Scare(10, "null-deref");
|
||||
} else if (signal.addr == signal.pc) {
|
||||
scariness.Scare(60, "wild-jump");
|
||||
} else if (signal.write_flag == SignalContext::WRITE) {
|
||||
} else if (signal.write_flag == SignalContext::Write) {
|
||||
scariness.Scare(30, "wild-addr-write");
|
||||
} else if (signal.write_flag == SignalContext::READ) {
|
||||
} else if (signal.write_flag == SignalContext::Read) {
|
||||
scariness.Scare(20, "wild-addr-read");
|
||||
} else {
|
||||
scariness.Scare(25, "wild-addr");
|
||||
|
@ -331,6 +331,28 @@ struct ErrorBadParamsToAnnotateContiguousContainer : ErrorBase {
|
|||
void Print();
|
||||
};
|
||||
|
||||
struct ErrorBadParamsToAnnotateDoubleEndedContiguousContainer : ErrorBase {
|
||||
const BufferedStackTrace *stack;
|
||||
uptr storage_beg, storage_end, old_container_beg, old_container_end,
|
||||
new_container_beg, new_container_end;
|
||||
|
||||
ErrorBadParamsToAnnotateDoubleEndedContiguousContainer() = default; // (*)
|
||||
ErrorBadParamsToAnnotateDoubleEndedContiguousContainer(
|
||||
u32 tid, BufferedStackTrace *stack_, uptr storage_beg_, uptr storage_end_,
|
||||
uptr old_container_beg_, uptr old_container_end_, uptr new_container_beg_,
|
||||
uptr new_container_end_)
|
||||
: ErrorBase(tid, 10,
|
||||
"bad-__sanitizer_annotate_double_ended_contiguous_container"),
|
||||
stack(stack_),
|
||||
storage_beg(storage_beg_),
|
||||
storage_end(storage_end_),
|
||||
old_container_beg(old_container_beg_),
|
||||
old_container_end(old_container_end_),
|
||||
new_container_beg(new_container_beg_),
|
||||
new_container_end(new_container_end_) {}
|
||||
void Print();
|
||||
};
|
||||
|
||||
struct ErrorODRViolation : ErrorBase {
|
||||
__asan_global global1, global2;
|
||||
u32 stack_id1, stack_id2;
|
||||
|
@ -372,34 +394,35 @@ struct ErrorGeneric : ErrorBase {
|
|||
u8 shadow_val;
|
||||
|
||||
ErrorGeneric() = default; // (*)
|
||||
ErrorGeneric(u32 tid, uptr addr, uptr pc_, uptr bp_, uptr sp_, bool is_write_,
|
||||
ErrorGeneric(u32 tid, uptr pc_, uptr bp_, uptr sp_, uptr addr, bool is_write_,
|
||||
uptr access_size_);
|
||||
void Print();
|
||||
};
|
||||
|
||||
// clang-format off
|
||||
#define ASAN_FOR_EACH_ERROR_KIND(macro) \
|
||||
macro(DeadlySignal) \
|
||||
macro(DoubleFree) \
|
||||
macro(NewDeleteTypeMismatch) \
|
||||
macro(FreeNotMalloced) \
|
||||
macro(AllocTypeMismatch) \
|
||||
macro(MallocUsableSizeNotOwned) \
|
||||
macro(SanitizerGetAllocatedSizeNotOwned) \
|
||||
macro(CallocOverflow) \
|
||||
macro(ReallocArrayOverflow) \
|
||||
macro(PvallocOverflow) \
|
||||
macro(InvalidAllocationAlignment) \
|
||||
macro(InvalidAlignedAllocAlignment) \
|
||||
macro(InvalidPosixMemalignAlignment) \
|
||||
macro(AllocationSizeTooBig) \
|
||||
macro(RssLimitExceeded) \
|
||||
macro(OutOfMemory) \
|
||||
macro(StringFunctionMemoryRangesOverlap) \
|
||||
macro(StringFunctionSizeOverflow) \
|
||||
macro(BadParamsToAnnotateContiguousContainer) \
|
||||
macro(ODRViolation) \
|
||||
macro(InvalidPointerPair) \
|
||||
#define ASAN_FOR_EACH_ERROR_KIND(macro) \
|
||||
macro(DeadlySignal) \
|
||||
macro(DoubleFree) \
|
||||
macro(NewDeleteTypeMismatch) \
|
||||
macro(FreeNotMalloced) \
|
||||
macro(AllocTypeMismatch) \
|
||||
macro(MallocUsableSizeNotOwned) \
|
||||
macro(SanitizerGetAllocatedSizeNotOwned) \
|
||||
macro(CallocOverflow) \
|
||||
macro(ReallocArrayOverflow) \
|
||||
macro(PvallocOverflow) \
|
||||
macro(InvalidAllocationAlignment) \
|
||||
macro(InvalidAlignedAllocAlignment) \
|
||||
macro(InvalidPosixMemalignAlignment) \
|
||||
macro(AllocationSizeTooBig) \
|
||||
macro(RssLimitExceeded) \
|
||||
macro(OutOfMemory) \
|
||||
macro(StringFunctionMemoryRangesOverlap) \
|
||||
macro(StringFunctionSizeOverflow) \
|
||||
macro(BadParamsToAnnotateContiguousContainer) \
|
||||
macro(BadParamsToAnnotateDoubleEndedContiguousContainer) \
|
||||
macro(ODRViolation) \
|
||||
macro(InvalidPointerPair) \
|
||||
macro(Generic)
|
||||
// clang-format on
|
||||
|
||||
|
|
|
@ -28,8 +28,8 @@ static const u64 kAllocaRedzoneMask = 31UL;
|
|||
// For small size classes inline PoisonShadow for better performance.
|
||||
ALWAYS_INLINE void SetShadow(uptr ptr, uptr size, uptr class_id, u64 magic) {
|
||||
u64 *shadow = reinterpret_cast<u64*>(MemToShadow(ptr));
|
||||
if (SHADOW_SCALE == 3 && class_id <= 6) {
|
||||
// This code expects SHADOW_SCALE=3.
|
||||
if (ASAN_SHADOW_SCALE == 3 && class_id <= 6) {
|
||||
// This code expects ASAN_SHADOW_SCALE=3.
|
||||
for (uptr i = 0; i < (((uptr)1) << class_id); i++) {
|
||||
shadow[i] = magic;
|
||||
// Make sure this does not become memset.
|
||||
|
@ -54,10 +54,11 @@ FakeStack *FakeStack::Create(uptr stack_size_log) {
|
|||
: MmapOrDie(size, "FakeStack"));
|
||||
res->stack_size_log_ = stack_size_log;
|
||||
u8 *p = reinterpret_cast<u8 *>(res);
|
||||
VReport(1, "T%d: FakeStack created: %p -- %p stack_size_log: %zd; "
|
||||
VReport(1,
|
||||
"T%d: FakeStack created: %p -- %p stack_size_log: %zd; "
|
||||
"mmapped %zdK, noreserve=%d \n",
|
||||
GetCurrentTidOrInvalid(), p,
|
||||
p + FakeStack::RequiredSize(stack_size_log), stack_size_log,
|
||||
GetCurrentTidOrInvalid(), (void *)p,
|
||||
(void *)(p + FakeStack::RequiredSize(stack_size_log)), stack_size_log,
|
||||
size >> 10, flags()->uar_noreserve);
|
||||
return res;
|
||||
}
|
||||
|
@ -139,7 +140,6 @@ void FakeStack::HandleNoReturn() {
|
|||
// We do it based on their 'real_stack' values -- everything that is lower
|
||||
// than the current real_stack is garbage.
|
||||
NOINLINE void FakeStack::GC(uptr real_stack) {
|
||||
uptr collected = 0;
|
||||
for (uptr class_id = 0; class_id < kNumberOfSizeClasses; class_id++) {
|
||||
u8 *flags = GetFlags(stack_size_log(), class_id);
|
||||
for (uptr i = 0, n = NumberOfFrames(stack_size_log(), class_id); i < n;
|
||||
|
@ -149,7 +149,6 @@ NOINLINE void FakeStack::GC(uptr real_stack) {
|
|||
GetFrame(stack_size_log(), class_id, i));
|
||||
if (ff->real_stack < real_stack) {
|
||||
flags[i] = 0;
|
||||
collected++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -293,10 +292,10 @@ void __asan_alloca_poison(uptr addr, uptr size) {
|
|||
uptr LeftRedzoneAddr = addr - kAllocaRedzoneSize;
|
||||
uptr PartialRzAddr = addr + size;
|
||||
uptr RightRzAddr = (PartialRzAddr + kAllocaRedzoneMask) & ~kAllocaRedzoneMask;
|
||||
uptr PartialRzAligned = PartialRzAddr & ~(SHADOW_GRANULARITY - 1);
|
||||
uptr PartialRzAligned = PartialRzAddr & ~(ASAN_SHADOW_GRANULARITY - 1);
|
||||
FastPoisonShadow(LeftRedzoneAddr, kAllocaRedzoneSize, kAsanAllocaLeftMagic);
|
||||
FastPoisonShadowPartialRightRedzone(
|
||||
PartialRzAligned, PartialRzAddr % SHADOW_GRANULARITY,
|
||||
PartialRzAligned, PartialRzAddr % ASAN_SHADOW_GRANULARITY,
|
||||
RightRzAddr - PartialRzAligned, kAsanAllocaRightMagic);
|
||||
FastPoisonShadow(RightRzAddr, kAllocaRedzoneSize, kAsanAllocaRightMagic);
|
||||
}
|
||||
|
@ -304,7 +303,8 @@ void __asan_alloca_poison(uptr addr, uptr size) {
|
|||
SANITIZER_INTERFACE_ATTRIBUTE
|
||||
void __asan_allocas_unpoison(uptr top, uptr bottom) {
|
||||
if ((!top) || (top > bottom)) return;
|
||||
REAL(memset)(reinterpret_cast<void*>(MemToShadow(top)), 0,
|
||||
(bottom - top) / SHADOW_GRANULARITY);
|
||||
REAL(memset)
|
||||
(reinterpret_cast<void *>(MemToShadow(top)), 0,
|
||||
(bottom - top) / ASAN_SHADOW_GRANULARITY);
|
||||
}
|
||||
} // extern "C"
|
||||
|
|
|
@ -87,7 +87,7 @@ void InitializeFlags() {
|
|||
RegisterCommonFlags(&ubsan_parser);
|
||||
#endif
|
||||
|
||||
if (SANITIZER_MAC) {
|
||||
if (SANITIZER_APPLE) {
|
||||
// Support macOS MallocScribble and MallocPreScribble:
|
||||
// <https://developer.apple.com/library/content/documentation/Performance/
|
||||
// Conceptual/ManagingMemory/Articles/MallocDebug.html>
|
||||
|
@ -140,9 +140,9 @@ void InitializeFlags() {
|
|||
SanitizerToolName);
|
||||
Die();
|
||||
}
|
||||
// Ensure that redzone is at least SHADOW_GRANULARITY.
|
||||
if (f->redzone < (int)SHADOW_GRANULARITY)
|
||||
f->redzone = SHADOW_GRANULARITY;
|
||||
// Ensure that redzone is at least ASAN_SHADOW_GRANULARITY.
|
||||
if (f->redzone < (int)ASAN_SHADOW_GRANULARITY)
|
||||
f->redzone = ASAN_SHADOW_GRANULARITY;
|
||||
// Make "strict_init_order" imply "check_initialization_order".
|
||||
// TODO(samsonov): Use a single runtime flag for an init-order checker.
|
||||
if (f->strict_init_order) {
|
||||
|
|
|
@ -49,9 +49,10 @@ ASAN_FLAG(
|
|||
"to find more errors.")
|
||||
ASAN_FLAG(bool, replace_intrin, true,
|
||||
"If set, uses custom wrappers for memset/memcpy/memmove intrinsics.")
|
||||
ASAN_FLAG(bool, detect_stack_use_after_return, false,
|
||||
ASAN_FLAG(bool, detect_stack_use_after_return,
|
||||
SANITIZER_LINUX && !SANITIZER_ANDROID,
|
||||
"Enables stack-use-after-return checking at run-time.")
|
||||
ASAN_FLAG(int, min_uar_stack_size_log, 16, // We can't do smaller anyway.
|
||||
ASAN_FLAG(int, min_uar_stack_size_log, 16, // We can't do smaller anyway.
|
||||
"Minimum fake stack size log.")
|
||||
ASAN_FLAG(int, max_uar_stack_size_log,
|
||||
20, // 1Mb per size class, i.e. ~11Mb per thread
|
||||
|
@ -82,6 +83,10 @@ ASAN_FLAG(
|
|||
int, sleep_after_init, 0,
|
||||
"Number of seconds to sleep after AddressSanitizer is initialized. "
|
||||
"Useful for debugging purposes (e.g. when one needs to attach gdb).")
|
||||
ASAN_FLAG(
|
||||
int, sleep_before_init, 0,
|
||||
"Number of seconds to sleep before AddressSanitizer starts initializing. "
|
||||
"Useful for debugging purposes (e.g. when one needs to attach gdb).")
|
||||
ASAN_FLAG(bool, check_malloc_usable_size, true,
|
||||
"Allows the users to work around the bug in Nvidia drivers prior to "
|
||||
"295.*.")
|
||||
|
@ -117,7 +122,7 @@ ASAN_FLAG(bool, poison_array_cookie, true,
|
|||
// https://github.com/google/sanitizers/issues/309
|
||||
// TODO(glider,timurrrr): Fix known issues and enable this back.
|
||||
ASAN_FLAG(bool, alloc_dealloc_mismatch,
|
||||
!SANITIZER_MAC && !SANITIZER_WINDOWS && !SANITIZER_ANDROID,
|
||||
!SANITIZER_APPLE && !SANITIZER_WINDOWS && !SANITIZER_ANDROID,
|
||||
"Report errors on malloc/delete, new/free, new/delete[], etc.")
|
||||
|
||||
ASAN_FLAG(bool, new_delete_type_mismatch, true,
|
||||
|
|
|
@ -14,16 +14,17 @@
|
|||
#include "sanitizer_common/sanitizer_fuchsia.h"
|
||||
#if SANITIZER_FUCHSIA
|
||||
|
||||
#include "asan_interceptors.h"
|
||||
#include "asan_internal.h"
|
||||
#include "asan_stack.h"
|
||||
#include "asan_thread.h"
|
||||
|
||||
#include <limits.h>
|
||||
#include <zircon/sanitizer.h>
|
||||
#include <zircon/syscalls.h>
|
||||
#include <zircon/threads.h>
|
||||
|
||||
# include "asan_interceptors.h"
|
||||
# include "asan_internal.h"
|
||||
# include "asan_stack.h"
|
||||
# include "asan_thread.h"
|
||||
# include "lsan/lsan_common.h"
|
||||
|
||||
namespace __asan {
|
||||
|
||||
// The system already set up the shadow memory for us.
|
||||
|
@ -31,7 +32,8 @@ namespace __asan {
|
|||
// AsanInitInternal->InitializeHighMemEnd (asan_rtl.cpp).
|
||||
// Just do some additional sanity checks here.
|
||||
void InitializeShadowMemory() {
|
||||
if (Verbosity()) PrintAddressSpaceLayout();
|
||||
if (Verbosity())
|
||||
PrintAddressSpaceLayout();
|
||||
|
||||
// Make sure SHADOW_OFFSET doesn't use __asan_shadow_memory_dynamic_address.
|
||||
__asan_shadow_memory_dynamic_address = kDefaultShadowSentinel;
|
||||
|
@ -62,7 +64,34 @@ void AsanOnDeadlySignal(int signo, void *siginfo, void *context) {
|
|||
UNIMPLEMENTED();
|
||||
}
|
||||
|
||||
bool PlatformUnpoisonStacks() { return false; }
|
||||
bool PlatformUnpoisonStacks() {
|
||||
// The current sp might not point to the default stack. This
|
||||
// could be because we are in a crash stack from fuzzing for example.
|
||||
// Unpoison the default stack and the current stack page.
|
||||
AsanThread *curr_thread = GetCurrentThread();
|
||||
CHECK(curr_thread != nullptr);
|
||||
uptr top = curr_thread->stack_top();
|
||||
uptr bottom = curr_thread->stack_bottom();
|
||||
// The default stack grows from top to bottom. (bottom < top).
|
||||
|
||||
uptr local_stack = reinterpret_cast<uptr>(__builtin_frame_address(0));
|
||||
if (local_stack >= bottom && local_stack <= top) {
|
||||
// The current stack is the default stack.
|
||||
// We only need to unpoison from where we are using until the end.
|
||||
bottom = RoundDownTo(local_stack, GetPageSize());
|
||||
UnpoisonStack(bottom, top, "default");
|
||||
} else {
|
||||
// The current stack is not the default stack.
|
||||
// Unpoison the entire default stack and the current stack page.
|
||||
UnpoisonStack(bottom, top, "default");
|
||||
bottom = RoundDownTo(local_stack, GetPageSize());
|
||||
top = bottom + GetPageSize();
|
||||
UnpoisonStack(bottom, top, "unknown");
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
// We can use a plain thread_local variable for TSD.
|
||||
static thread_local void *per_thread;
|
||||
|
@ -90,14 +119,12 @@ struct AsanThread::InitOptions {
|
|||
|
||||
// Shared setup between thread creation and startup for the initial thread.
|
||||
static AsanThread *CreateAsanThread(StackTrace *stack, u32 parent_tid,
|
||||
uptr user_id, bool detached,
|
||||
const char *name) {
|
||||
bool detached, const char *name) {
|
||||
// In lieu of AsanThread::Create.
|
||||
AsanThread *thread = (AsanThread *)MmapOrDie(AsanThreadMmapSize(), __func__);
|
||||
|
||||
AsanThreadContext::CreateThreadContextArgs args = {thread, stack};
|
||||
u32 tid =
|
||||
asanThreadRegistry().CreateThread(user_id, detached, parent_tid, &args);
|
||||
u32 tid = asanThreadRegistry().CreateThread(0, detached, parent_tid, &args);
|
||||
asanThreadRegistry().SetThreadName(tid, name);
|
||||
|
||||
return thread;
|
||||
|
@ -124,7 +151,7 @@ AsanThread *CreateMainThread() {
|
|||
CHECK_NE(__sanitizer::MainThreadStackBase, 0);
|
||||
CHECK_GT(__sanitizer::MainThreadStackSize, 0);
|
||||
AsanThread *t = CreateAsanThread(
|
||||
nullptr, 0, reinterpret_cast<uptr>(self), true,
|
||||
nullptr, 0, true,
|
||||
_zx_object_get_property(thrd_get_zx_handle(self), ZX_PROP_NAME, name,
|
||||
sizeof(name)) == ZX_OK
|
||||
? name
|
||||
|
@ -148,13 +175,13 @@ static void *BeforeThreadCreateHook(uptr user_id, bool detached,
|
|||
uptr stack_size) {
|
||||
EnsureMainThreadIDIsCorrect();
|
||||
// Strict init-order checking is thread-hostile.
|
||||
if (flags()->strict_init_order) StopInitOrderChecking();
|
||||
if (flags()->strict_init_order)
|
||||
StopInitOrderChecking();
|
||||
|
||||
GET_STACK_TRACE_THREAD;
|
||||
u32 parent_tid = GetCurrentTidOrInvalid();
|
||||
|
||||
AsanThread *thread =
|
||||
CreateAsanThread(&stack, parent_tid, user_id, detached, name);
|
||||
AsanThread *thread = CreateAsanThread(&stack, parent_tid, detached, name);
|
||||
|
||||
// On other systems, AsanThread::Init() is called from the new
|
||||
// thread itself. But on Fuchsia we already know the stack address
|
||||
|
@ -209,8 +236,18 @@ void FlushUnneededASanShadowMemory(uptr p, uptr size) {
|
|||
__sanitizer_fill_shadow(p, size, 0, 0);
|
||||
}
|
||||
|
||||
// On Fuchsia, leak detection is done by a special hook after atexit hooks.
|
||||
// So this doesn't install any atexit hook like on other platforms.
|
||||
void InstallAtExitCheckLeaks() {}
|
||||
|
||||
} // namespace __asan
|
||||
|
||||
namespace __lsan {
|
||||
|
||||
bool UseExitcodeOnLeak() { return __asan::flags()->halt_on_error; }
|
||||
|
||||
} // namespace __lsan
|
||||
|
||||
// These are declared (in extern "C") by <zircon/sanitizer.h>.
|
||||
// The system runtime will call our definitions directly.
|
||||
|
||||
|
|
|
@ -35,7 +35,7 @@ struct ListOfGlobals {
|
|||
ListOfGlobals *next;
|
||||
};
|
||||
|
||||
static BlockingMutex mu_for_globals(LINKER_INITIALIZED);
|
||||
static Mutex mu_for_globals;
|
||||
static LowLevelAllocator allocator_for_globals;
|
||||
static ListOfGlobals *list_of_all_globals;
|
||||
|
||||
|
@ -61,14 +61,13 @@ ALWAYS_INLINE void PoisonShadowForGlobal(const Global *g, u8 value) {
|
|||
}
|
||||
|
||||
ALWAYS_INLINE void PoisonRedZones(const Global &g) {
|
||||
uptr aligned_size = RoundUpTo(g.size, SHADOW_GRANULARITY);
|
||||
uptr aligned_size = RoundUpTo(g.size, ASAN_SHADOW_GRANULARITY);
|
||||
FastPoisonShadow(g.beg + aligned_size, g.size_with_redzone - aligned_size,
|
||||
kAsanGlobalRedzoneMagic);
|
||||
if (g.size != aligned_size) {
|
||||
FastPoisonShadowPartialRightRedzone(
|
||||
g.beg + RoundDownTo(g.size, SHADOW_GRANULARITY),
|
||||
g.size % SHADOW_GRANULARITY,
|
||||
SHADOW_GRANULARITY,
|
||||
g.beg + RoundDownTo(g.size, ASAN_SHADOW_GRANULARITY),
|
||||
g.size % ASAN_SHADOW_GRANULARITY, ASAN_SHADOW_GRANULARITY,
|
||||
kAsanGlobalRedzoneMagic);
|
||||
}
|
||||
}
|
||||
|
@ -85,12 +84,13 @@ static void ReportGlobal(const Global &g, const char *prefix) {
|
|||
Report(
|
||||
"%s Global[%p]: beg=%p size=%zu/%zu name=%s module=%s dyn_init=%zu "
|
||||
"odr_indicator=%p\n",
|
||||
prefix, &g, (void *)g.beg, g.size, g.size_with_redzone, g.name,
|
||||
prefix, (void *)&g, (void *)g.beg, g.size, g.size_with_redzone, g.name,
|
||||
g.module_name, g.has_dynamic_init, (void *)g.odr_indicator);
|
||||
if (g.location) {
|
||||
Report(" location (%p): name=%s[%p], %d %d\n", g.location,
|
||||
g.location->filename, g.location->filename, g.location->line_no,
|
||||
g.location->column_no);
|
||||
|
||||
DataInfo info;
|
||||
Symbolizer::GetOrInit()->SymbolizeData(g.beg, &info);
|
||||
if (info.line != 0) {
|
||||
Report(" location: name=%s, %d\n", info.file, static_cast<int>(info.line));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -108,7 +108,7 @@ static u32 FindRegistrationSite(const Global *g) {
|
|||
int GetGlobalsForAddress(uptr addr, Global *globals, u32 *reg_sites,
|
||||
int max_globals) {
|
||||
if (!flags()->report_globals) return 0;
|
||||
BlockingMutexLock lock(&mu_for_globals);
|
||||
Lock lock(&mu_for_globals);
|
||||
int res = 0;
|
||||
for (ListOfGlobals *l = list_of_all_globals; l; l = l->next) {
|
||||
const Global &g = *l->g;
|
||||
|
@ -257,7 +257,7 @@ static void UnregisterGlobal(const Global *g) {
|
|||
}
|
||||
|
||||
void StopInitOrderChecking() {
|
||||
BlockingMutexLock lock(&mu_for_globals);
|
||||
Lock lock(&mu_for_globals);
|
||||
if (!flags()->check_initialization_order || !dynamic_init_globals)
|
||||
return;
|
||||
flags()->check_initialization_order = false;
|
||||
|
@ -296,19 +296,15 @@ void PrintGlobalNameIfASCII(InternalScopedString *str, const __asan_global &g) {
|
|||
(char *)g.beg);
|
||||
}
|
||||
|
||||
static const char *GlobalFilename(const __asan_global &g) {
|
||||
const char *res = g.module_name;
|
||||
// Prefer the filename from source location, if is available.
|
||||
if (g.location) res = g.location->filename;
|
||||
CHECK(res);
|
||||
return res;
|
||||
}
|
||||
|
||||
void PrintGlobalLocation(InternalScopedString *str, const __asan_global &g) {
|
||||
str->append("%s", GlobalFilename(g));
|
||||
if (!g.location) return;
|
||||
if (g.location->line_no) str->append(":%d", g.location->line_no);
|
||||
if (g.location->column_no) str->append(":%d", g.location->column_no);
|
||||
DataInfo info;
|
||||
Symbolizer::GetOrInit()->SymbolizeData(g.beg, &info);
|
||||
|
||||
if (info.line != 0) {
|
||||
str->append("%s:%d", info.file, static_cast<int>(info.line));
|
||||
} else {
|
||||
str->append("%s", g.module_name);
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace __asan
|
||||
|
@ -359,7 +355,7 @@ void __asan_register_globals(__asan_global *globals, uptr n) {
|
|||
if (!flags()->report_globals) return;
|
||||
GET_STACK_TRACE_MALLOC;
|
||||
u32 stack_id = StackDepotPut(stack);
|
||||
BlockingMutexLock lock(&mu_for_globals);
|
||||
Lock lock(&mu_for_globals);
|
||||
if (!global_registration_site_vector) {
|
||||
global_registration_site_vector =
|
||||
new (allocator_for_globals) GlobalRegistrationSiteVector;
|
||||
|
@ -369,7 +365,8 @@ void __asan_register_globals(__asan_global *globals, uptr n) {
|
|||
global_registration_site_vector->push_back(site);
|
||||
if (flags()->report_globals >= 2) {
|
||||
PRINT_CURRENT_STACK();
|
||||
Printf("=== ID %d; %p %p\n", stack_id, &globals[0], &globals[n - 1]);
|
||||
Printf("=== ID %d; %p %p\n", stack_id, (void *)&globals[0],
|
||||
(void *)&globals[n - 1]);
|
||||
}
|
||||
for (uptr i = 0; i < n; i++) {
|
||||
if (SANITIZER_WINDOWS && globals[i].beg == 0) {
|
||||
|
@ -398,7 +395,7 @@ void __asan_register_globals(__asan_global *globals, uptr n) {
|
|||
// We must do this when a shared objects gets dlclosed.
|
||||
void __asan_unregister_globals(__asan_global *globals, uptr n) {
|
||||
if (!flags()->report_globals) return;
|
||||
BlockingMutexLock lock(&mu_for_globals);
|
||||
Lock lock(&mu_for_globals);
|
||||
for (uptr i = 0; i < n; i++) {
|
||||
if (SANITIZER_WINDOWS && globals[i].beg == 0) {
|
||||
// Skip globals that look like padding from the MSVC incremental linker.
|
||||
|
@ -424,7 +421,7 @@ void __asan_before_dynamic_init(const char *module_name) {
|
|||
bool strict_init_order = flags()->strict_init_order;
|
||||
CHECK(module_name);
|
||||
CHECK(asan_inited);
|
||||
BlockingMutexLock lock(&mu_for_globals);
|
||||
Lock lock(&mu_for_globals);
|
||||
if (flags()->report_globals >= 3)
|
||||
Printf("DynInitPoison module: %s\n", module_name);
|
||||
for (uptr i = 0, n = dynamic_init_globals->size(); i < n; ++i) {
|
||||
|
@ -448,7 +445,7 @@ void __asan_after_dynamic_init() {
|
|||
!dynamic_init_globals)
|
||||
return;
|
||||
CHECK(asan_inited);
|
||||
BlockingMutexLock lock(&mu_for_globals);
|
||||
Lock lock(&mu_for_globals);
|
||||
// FIXME: Optionally report that we're unpoisoning globals from a module.
|
||||
for (uptr i = 0, n = dynamic_init_globals->size(); i < n; ++i) {
|
||||
DynInitGlobal &dyn_g = (*dynamic_init_globals)[i];
|
||||
|
|
|
@ -49,8 +49,8 @@ namespace __asan {
|
|||
ASAN_READ_RANGE((ctx), (s), \
|
||||
common_flags()->strict_string_checks ? (len) + 1 : (n))
|
||||
|
||||
#define ASAN_READ_STRING(ctx, s, n) \
|
||||
ASAN_READ_STRING_OF_LEN((ctx), (s), REAL(strlen)(s), (n))
|
||||
# define ASAN_READ_STRING(ctx, s, n) \
|
||||
ASAN_READ_STRING_OF_LEN((ctx), (s), internal_strlen(s), (n))
|
||||
|
||||
static inline uptr MaybeRealStrnlen(const char *s, uptr maxlen) {
|
||||
#if SANITIZER_INTERCEPT_STRNLEN
|
||||
|
@ -103,7 +103,7 @@ DECLARE_REAL_AND_INTERCEPTOR(void, free, void *)
|
|||
do { \
|
||||
if (asan_init_is_running) \
|
||||
return REAL(func)(__VA_ARGS__); \
|
||||
if (SANITIZER_MAC && UNLIKELY(!asan_inited)) \
|
||||
if (SANITIZER_APPLE && UNLIKELY(!asan_inited)) \
|
||||
return REAL(func)(__VA_ARGS__); \
|
||||
ENSURE_ASAN_INITED(); \
|
||||
} while (false)
|
||||
|
@ -130,23 +130,24 @@ DECLARE_REAL_AND_INTERCEPTOR(void, free, void *)
|
|||
#define COMMON_INTERCEPTOR_BLOCK_REAL(name) REAL(name)
|
||||
// Strict init-order checking is dlopen-hostile:
|
||||
// https://github.com/google/sanitizers/issues/178
|
||||
#define COMMON_INTERCEPTOR_ON_DLOPEN(filename, flag) \
|
||||
do { \
|
||||
if (flags()->strict_init_order) \
|
||||
StopInitOrderChecking(); \
|
||||
CheckNoDeepBind(filename, flag); \
|
||||
} while (false)
|
||||
#define COMMON_INTERCEPTOR_ON_EXIT(ctx) OnExit()
|
||||
#define COMMON_INTERCEPTOR_LIBRARY_LOADED(filename, handle)
|
||||
#define COMMON_INTERCEPTOR_LIBRARY_UNLOADED()
|
||||
#define COMMON_INTERCEPTOR_NOTHING_IS_INITIALIZED (!asan_inited)
|
||||
#define COMMON_INTERCEPTOR_GET_TLS_RANGE(begin, end) \
|
||||
if (AsanThread *t = GetCurrentThread()) { \
|
||||
*begin = t->tls_begin(); \
|
||||
*end = t->tls_end(); \
|
||||
} else { \
|
||||
*begin = *end = 0; \
|
||||
}
|
||||
# define COMMON_INTERCEPTOR_DLOPEN(filename, flag) \
|
||||
({ \
|
||||
if (flags()->strict_init_order) \
|
||||
StopInitOrderChecking(); \
|
||||
CheckNoDeepBind(filename, flag); \
|
||||
REAL(dlopen)(filename, flag); \
|
||||
})
|
||||
# define COMMON_INTERCEPTOR_ON_EXIT(ctx) OnExit()
|
||||
# define COMMON_INTERCEPTOR_LIBRARY_LOADED(filename, handle)
|
||||
# define COMMON_INTERCEPTOR_LIBRARY_UNLOADED()
|
||||
# define COMMON_INTERCEPTOR_NOTHING_IS_INITIALIZED (!asan_inited)
|
||||
# define COMMON_INTERCEPTOR_GET_TLS_RANGE(begin, end) \
|
||||
if (AsanThread *t = GetCurrentThread()) { \
|
||||
*begin = t->tls_begin(); \
|
||||
*end = t->tls_end(); \
|
||||
} else { \
|
||||
*begin = *end = 0; \
|
||||
}
|
||||
|
||||
#define COMMON_INTERCEPTOR_MEMMOVE_IMPL(ctx, to, from, size) \
|
||||
do { \
|
||||
|
@ -242,15 +243,50 @@ DEFINE_REAL_PTHREAD_FUNCTIONS
|
|||
|
||||
#if ASAN_INTERCEPT_SWAPCONTEXT
|
||||
static void ClearShadowMemoryForContextStack(uptr stack, uptr ssize) {
|
||||
// Only clear if we know the stack. This should be true only for contexts
|
||||
// created with makecontext().
|
||||
if (!ssize)
|
||||
return;
|
||||
// Align to page size.
|
||||
uptr PageSize = GetPageSizeCached();
|
||||
uptr bottom = stack & ~(PageSize - 1);
|
||||
uptr bottom = RoundDownTo(stack, PageSize);
|
||||
if (!AddrIsInMem(bottom))
|
||||
return;
|
||||
ssize += stack - bottom;
|
||||
ssize = RoundUpTo(ssize, PageSize);
|
||||
static const uptr kMaxSaneContextStackSize = 1 << 22; // 4 Mb
|
||||
if (AddrIsInMem(bottom) && ssize && ssize <= kMaxSaneContextStackSize) {
|
||||
PoisonShadow(bottom, ssize, 0);
|
||||
}
|
||||
PoisonShadow(bottom, ssize, 0);
|
||||
}
|
||||
|
||||
INTERCEPTOR(void, makecontext, struct ucontext_t *ucp, void (*func)(), int argc,
|
||||
...) {
|
||||
va_list ap;
|
||||
uptr args[64];
|
||||
// We don't know a better way to forward ... into REAL function. We can
|
||||
// increase args size if neccecary.
|
||||
CHECK_LE(argc, ARRAY_SIZE(args));
|
||||
internal_memset(args, 0, sizeof(args));
|
||||
va_start(ap, argc);
|
||||
for (int i = 0; i < argc; ++i) args[i] = va_arg(ap, uptr);
|
||||
va_end(ap);
|
||||
|
||||
# define ENUMERATE_ARRAY_4(start) \
|
||||
args[start], args[start + 1], args[start + 2], args[start + 3]
|
||||
# define ENUMERATE_ARRAY_16(start) \
|
||||
ENUMERATE_ARRAY_4(start), ENUMERATE_ARRAY_4(start + 4), \
|
||||
ENUMERATE_ARRAY_4(start + 8), ENUMERATE_ARRAY_4(start + 12)
|
||||
# define ENUMERATE_ARRAY_64() \
|
||||
ENUMERATE_ARRAY_16(0), ENUMERATE_ARRAY_16(16), ENUMERATE_ARRAY_16(32), \
|
||||
ENUMERATE_ARRAY_16(48)
|
||||
|
||||
REAL(makecontext)
|
||||
((struct ucontext_t *)ucp, func, argc, ENUMERATE_ARRAY_64());
|
||||
|
||||
# undef ENUMERATE_ARRAY_4
|
||||
# undef ENUMERATE_ARRAY_16
|
||||
# undef ENUMERATE_ARRAY_64
|
||||
|
||||
// Sign the stack so we can identify it for unpoisoning.
|
||||
SignContextStack(ucp);
|
||||
}
|
||||
|
||||
INTERCEPTOR(int, swapcontext, struct ucontext_t *oucp,
|
||||
|
@ -266,15 +302,15 @@ INTERCEPTOR(int, swapcontext, struct ucontext_t *oucp,
|
|||
uptr stack, ssize;
|
||||
ReadContextStack(ucp, &stack, &ssize);
|
||||
ClearShadowMemoryForContextStack(stack, ssize);
|
||||
#if __has_attribute(__indirect_return__) && \
|
||||
(defined(__x86_64__) || defined(__i386__))
|
||||
|
||||
# if __has_attribute(__indirect_return__) && \
|
||||
(defined(__x86_64__) || defined(__i386__))
|
||||
int (*real_swapcontext)(struct ucontext_t *, struct ucontext_t *)
|
||||
__attribute__((__indirect_return__))
|
||||
= REAL(swapcontext);
|
||||
__attribute__((__indirect_return__)) = REAL(swapcontext);
|
||||
int res = real_swapcontext(oucp, ucp);
|
||||
#else
|
||||
# else
|
||||
int res = REAL(swapcontext)(oucp, ucp);
|
||||
#endif
|
||||
# endif
|
||||
// swapcontext technically does not return, but program may swap context to
|
||||
// "oucp" later, that would look as if swapcontext() returned 0.
|
||||
// We need to clear shadow for ucp once again, as it may be in arbitrary
|
||||
|
@ -354,7 +390,7 @@ INTERCEPTOR(_Unwind_Reason_Code, _Unwind_SjLj_RaiseException,
|
|||
INTERCEPTOR(char*, index, const char *string, int c)
|
||||
ALIAS(WRAPPER_NAME(strchr));
|
||||
# else
|
||||
# if SANITIZER_MAC
|
||||
# if SANITIZER_APPLE
|
||||
DECLARE_REAL(char*, index, const char *string, int c)
|
||||
OVERRIDE_FUNCTION(index, strchr);
|
||||
# else
|
||||
|
@ -370,9 +406,9 @@ DEFINE_REAL(char*, index, const char *string, int c)
|
|||
ASAN_INTERCEPTOR_ENTER(ctx, strcat);
|
||||
ENSURE_ASAN_INITED();
|
||||
if (flags()->replace_str) {
|
||||
uptr from_length = REAL(strlen)(from);
|
||||
uptr from_length = internal_strlen(from);
|
||||
ASAN_READ_RANGE(ctx, from, from_length + 1);
|
||||
uptr to_length = REAL(strlen)(to);
|
||||
uptr to_length = internal_strlen(to);
|
||||
ASAN_READ_STRING_OF_LEN(ctx, to, to_length, to_length);
|
||||
ASAN_WRITE_RANGE(ctx, to + to_length, from_length + 1);
|
||||
// If the copying actually happens, the |from| string should not overlap
|
||||
|
@ -394,7 +430,7 @@ INTERCEPTOR(char*, strncat, char *to, const char *from, uptr size) {
|
|||
uptr from_length = MaybeRealStrnlen(from, size);
|
||||
uptr copy_length = Min(size, from_length + 1);
|
||||
ASAN_READ_RANGE(ctx, from, copy_length);
|
||||
uptr to_length = REAL(strlen)(to);
|
||||
uptr to_length = internal_strlen(to);
|
||||
ASAN_READ_STRING_OF_LEN(ctx, to, to_length, to_length);
|
||||
ASAN_WRITE_RANGE(ctx, to + to_length, from_length + 1);
|
||||
if (from_length > 0) {
|
||||
|
@ -408,7 +444,7 @@ INTERCEPTOR(char*, strncat, char *to, const char *from, uptr size) {
|
|||
INTERCEPTOR(char *, strcpy, char *to, const char *from) {
|
||||
void *ctx;
|
||||
ASAN_INTERCEPTOR_ENTER(ctx, strcpy);
|
||||
#if SANITIZER_MAC
|
||||
#if SANITIZER_APPLE
|
||||
if (UNLIKELY(!asan_inited))
|
||||
return REAL(strcpy)(to, from);
|
||||
#endif
|
||||
|
@ -419,7 +455,7 @@ INTERCEPTOR(char *, strcpy, char *to, const char *from) {
|
|||
}
|
||||
ENSURE_ASAN_INITED();
|
||||
if (flags()->replace_str) {
|
||||
uptr from_size = REAL(strlen)(from) + 1;
|
||||
uptr from_size = internal_strlen(from) + 1;
|
||||
CHECK_RANGES_OVERLAP("strcpy", to, from_size, from, from_size);
|
||||
ASAN_READ_RANGE(ctx, from, from_size);
|
||||
ASAN_WRITE_RANGE(ctx, to, from_size);
|
||||
|
@ -432,7 +468,7 @@ INTERCEPTOR(char*, strdup, const char *s) {
|
|||
ASAN_INTERCEPTOR_ENTER(ctx, strdup);
|
||||
if (UNLIKELY(!asan_inited)) return internal_strdup(s);
|
||||
ENSURE_ASAN_INITED();
|
||||
uptr length = REAL(strlen)(s);
|
||||
uptr length = internal_strlen(s);
|
||||
if (flags()->replace_str) {
|
||||
ASAN_READ_RANGE(ctx, s, length + 1);
|
||||
}
|
||||
|
@ -448,7 +484,7 @@ INTERCEPTOR(char*, __strdup, const char *s) {
|
|||
ASAN_INTERCEPTOR_ENTER(ctx, strdup);
|
||||
if (UNLIKELY(!asan_inited)) return internal_strdup(s);
|
||||
ENSURE_ASAN_INITED();
|
||||
uptr length = REAL(strlen)(s);
|
||||
uptr length = internal_strlen(s);
|
||||
if (flags()->replace_str) {
|
||||
ASAN_READ_RANGE(ctx, s, length + 1);
|
||||
}
|
||||
|
@ -488,7 +524,7 @@ INTERCEPTOR(long, strtol, const char *nptr, char **endptr, int base) {
|
|||
INTERCEPTOR(int, atoi, const char *nptr) {
|
||||
void *ctx;
|
||||
ASAN_INTERCEPTOR_ENTER(ctx, atoi);
|
||||
#if SANITIZER_MAC
|
||||
#if SANITIZER_APPLE
|
||||
if (UNLIKELY(!asan_inited)) return REAL(atoi)(nptr);
|
||||
#endif
|
||||
ENSURE_ASAN_INITED();
|
||||
|
@ -509,7 +545,7 @@ INTERCEPTOR(int, atoi, const char *nptr) {
|
|||
INTERCEPTOR(long, atol, const char *nptr) {
|
||||
void *ctx;
|
||||
ASAN_INTERCEPTOR_ENTER(ctx, atol);
|
||||
#if SANITIZER_MAC
|
||||
#if SANITIZER_APPLE
|
||||
if (UNLIKELY(!asan_inited)) return REAL(atol)(nptr);
|
||||
#endif
|
||||
ENSURE_ASAN_INITED();
|
||||
|
@ -562,7 +598,7 @@ static void AtCxaAtexit(void *unused) {
|
|||
#if ASAN_INTERCEPT___CXA_ATEXIT
|
||||
INTERCEPTOR(int, __cxa_atexit, void (*func)(void *), void *arg,
|
||||
void *dso_handle) {
|
||||
#if SANITIZER_MAC
|
||||
#if SANITIZER_APPLE
|
||||
if (UNLIKELY(!asan_inited)) return REAL(__cxa_atexit)(func, arg, dso_handle);
|
||||
#endif
|
||||
ENSURE_ASAN_INITED();
|
||||
|
@ -581,7 +617,7 @@ INTERCEPTOR(int, atexit, void (*func)()) {
|
|||
#if CAN_SANITIZE_LEAKS
|
||||
__lsan::ScopedInterceptorDisabler disabler;
|
||||
#endif
|
||||
// Avoid calling real atexit as it is unrechable on at least on Linux.
|
||||
// Avoid calling real atexit as it is unreachable on at least on Linux.
|
||||
int res = REAL(__cxa_atexit)((void (*)(void *a))func, nullptr, nullptr);
|
||||
REAL(__cxa_atexit)(AtCxaAtexit, nullptr, nullptr);
|
||||
return res;
|
||||
|
@ -643,10 +679,11 @@ void InitializeAsanInterceptors() {
|
|||
// Intecept jump-related functions.
|
||||
ASAN_INTERCEPT_FUNC(longjmp);
|
||||
|
||||
#if ASAN_INTERCEPT_SWAPCONTEXT
|
||||
# if ASAN_INTERCEPT_SWAPCONTEXT
|
||||
ASAN_INTERCEPT_FUNC(swapcontext);
|
||||
#endif
|
||||
#if ASAN_INTERCEPT__LONGJMP
|
||||
ASAN_INTERCEPT_FUNC(makecontext);
|
||||
# endif
|
||||
# if ASAN_INTERCEPT__LONGJMP
|
||||
ASAN_INTERCEPT_FUNC(_longjmp);
|
||||
#endif
|
||||
#if ASAN_INTERCEPT___LONGJMP_CHK
|
||||
|
|
|
@ -114,7 +114,7 @@ void InitializePlatformInterceptors();
|
|||
|
||||
#if SANITIZER_LINUX && \
|
||||
(defined(__arm__) || defined(__aarch64__) || defined(__i386__) || \
|
||||
defined(__x86_64__) || SANITIZER_RISCV64)
|
||||
defined(__x86_64__) || SANITIZER_RISCV64 || SANITIZER_LOONGARCH64)
|
||||
# define ASAN_INTERCEPT_VFORK 1
|
||||
#else
|
||||
# define ASAN_INTERCEPT_VFORK 0
|
||||
|
@ -133,29 +133,30 @@ DECLARE_REAL(char*, strncpy, char *to, const char *from, uptr size)
|
|||
DECLARE_REAL(uptr, strnlen, const char *s, uptr maxlen)
|
||||
DECLARE_REAL(char*, strstr, const char *s1, const char *s2)
|
||||
|
||||
#if !SANITIZER_MAC
|
||||
#define ASAN_INTERCEPT_FUNC(name) \
|
||||
do { \
|
||||
if (!INTERCEPT_FUNCTION(name)) \
|
||||
VReport(1, "AddressSanitizer: failed to intercept '%s'\n", #name); \
|
||||
} while (0)
|
||||
#define ASAN_INTERCEPT_FUNC_VER(name, ver) \
|
||||
do { \
|
||||
if (!INTERCEPT_FUNCTION_VER(name, ver)) \
|
||||
VReport(1, "AddressSanitizer: failed to intercept '%s@@%s'\n", #name, \
|
||||
#ver); \
|
||||
} while (0)
|
||||
#define ASAN_INTERCEPT_FUNC_VER_UNVERSIONED_FALLBACK(name, ver) \
|
||||
do { \
|
||||
if (!INTERCEPT_FUNCTION_VER(name, ver) && !INTERCEPT_FUNCTION(name)) \
|
||||
VReport(1, "AddressSanitizer: failed to intercept '%s@@%s' or '%s'\n", \
|
||||
#name, #ver, #name); \
|
||||
} while (0)
|
||||
# if !SANITIZER_APPLE
|
||||
# define ASAN_INTERCEPT_FUNC(name) \
|
||||
do { \
|
||||
if (!INTERCEPT_FUNCTION(name)) \
|
||||
VReport(1, "AddressSanitizer: failed to intercept '%s'\n", #name); \
|
||||
} while (0)
|
||||
# define ASAN_INTERCEPT_FUNC_VER(name, ver) \
|
||||
do { \
|
||||
if (!INTERCEPT_FUNCTION_VER(name, ver)) \
|
||||
VReport(1, "AddressSanitizer: failed to intercept '%s@@%s'\n", \
|
||||
#name, ver); \
|
||||
} while (0)
|
||||
# define ASAN_INTERCEPT_FUNC_VER_UNVERSIONED_FALLBACK(name, ver) \
|
||||
do { \
|
||||
if (!INTERCEPT_FUNCTION_VER(name, ver) && !INTERCEPT_FUNCTION(name)) \
|
||||
VReport(1, \
|
||||
"AddressSanitizer: failed to intercept '%s@@%s' or '%s'\n", \
|
||||
#name, ver, #name); \
|
||||
} while (0)
|
||||
|
||||
#else
|
||||
# else
|
||||
// OS X interceptors don't need to be initialized with INTERCEPT_FUNCTION.
|
||||
#define ASAN_INTERCEPT_FUNC(name)
|
||||
#endif // SANITIZER_MAC
|
||||
# define ASAN_INTERCEPT_FUNC(name)
|
||||
# endif // SANITIZER_APPLE
|
||||
|
||||
#endif // !SANITIZER_FUCHSIA
|
||||
|
||||
|
|
|
@ -18,26 +18,29 @@
|
|||
#include "asan_mapping.h"
|
||||
#include "interception/interception.h"
|
||||
|
||||
DECLARE_REAL(void*, memcpy, void *to, const void *from, uptr size)
|
||||
DECLARE_REAL(void*, memset, void *block, int c, uptr size)
|
||||
DECLARE_REAL(void *, memcpy, void *to, const void *from, uptr size)
|
||||
DECLARE_REAL(void *, memset, void *block, int c, uptr size)
|
||||
|
||||
namespace __asan {
|
||||
|
||||
// Return true if we can quickly decide that the region is unpoisoned.
|
||||
// We assume that a redzone is at least 16 bytes.
|
||||
static inline bool QuickCheckForUnpoisonedRegion(uptr beg, uptr size) {
|
||||
if (size == 0) return true;
|
||||
if (size <= 32)
|
||||
return !AddressIsPoisoned(beg) &&
|
||||
!AddressIsPoisoned(beg + size - 1) &&
|
||||
!AddressIsPoisoned(beg + size / 2);
|
||||
if (size <= 64)
|
||||
return !AddressIsPoisoned(beg) &&
|
||||
!AddressIsPoisoned(beg + size / 4) &&
|
||||
!AddressIsPoisoned(beg + size - 1) &&
|
||||
!AddressIsPoisoned(beg + 3 * size / 4) &&
|
||||
!AddressIsPoisoned(beg + size / 2);
|
||||
return false;
|
||||
if (UNLIKELY(size == 0 || size > sizeof(uptr) * ASAN_SHADOW_GRANULARITY))
|
||||
return !size;
|
||||
|
||||
uptr last = beg + size - 1;
|
||||
uptr shadow_first = MEM_TO_SHADOW(beg);
|
||||
uptr shadow_last = MEM_TO_SHADOW(last);
|
||||
uptr uptr_first = RoundDownTo(shadow_first, sizeof(uptr));
|
||||
uptr uptr_last = RoundDownTo(shadow_last, sizeof(uptr));
|
||||
if (LIKELY(((*reinterpret_cast<const uptr *>(uptr_first) |
|
||||
*reinterpret_cast<const uptr *>(uptr_last)) == 0)))
|
||||
return true;
|
||||
u8 shadow = AddressIsPoisoned(last);
|
||||
for (; shadow_first < shadow_last; ++shadow_first)
|
||||
shadow |= *((u8 *)shadow_first);
|
||||
return !shadow;
|
||||
}
|
||||
|
||||
struct AsanInterceptorContext {
|
||||
|
@ -49,75 +52,68 @@ struct AsanInterceptorContext {
|
|||
// that no extra frames are created, and stack trace contains
|
||||
// relevant information only.
|
||||
// We check all shadow bytes.
|
||||
#define ACCESS_MEMORY_RANGE(ctx, offset, size, isWrite) do { \
|
||||
uptr __offset = (uptr)(offset); \
|
||||
uptr __size = (uptr)(size); \
|
||||
uptr __bad = 0; \
|
||||
if (__offset > __offset + __size) { \
|
||||
GET_STACK_TRACE_FATAL_HERE; \
|
||||
ReportStringFunctionSizeOverflow(__offset, __size, &stack); \
|
||||
} \
|
||||
if (!QuickCheckForUnpoisonedRegion(__offset, __size) && \
|
||||
(__bad = __asan_region_is_poisoned(__offset, __size))) { \
|
||||
AsanInterceptorContext *_ctx = (AsanInterceptorContext *)ctx; \
|
||||
bool suppressed = false; \
|
||||
if (_ctx) { \
|
||||
suppressed = IsInterceptorSuppressed(_ctx->interceptor_name); \
|
||||
if (!suppressed && HaveStackTraceBasedSuppressions()) { \
|
||||
GET_STACK_TRACE_FATAL_HERE; \
|
||||
suppressed = IsStackTraceSuppressed(&stack); \
|
||||
} \
|
||||
} \
|
||||
if (!suppressed) { \
|
||||
GET_CURRENT_PC_BP_SP; \
|
||||
ReportGenericError(pc, bp, sp, __bad, isWrite, __size, 0, false);\
|
||||
} \
|
||||
} \
|
||||
#define ACCESS_MEMORY_RANGE(ctx, offset, size, isWrite) \
|
||||
do { \
|
||||
uptr __offset = (uptr)(offset); \
|
||||
uptr __size = (uptr)(size); \
|
||||
uptr __bad = 0; \
|
||||
if (UNLIKELY(__offset > __offset + __size)) { \
|
||||
GET_STACK_TRACE_FATAL_HERE; \
|
||||
ReportStringFunctionSizeOverflow(__offset, __size, &stack); \
|
||||
} \
|
||||
if (UNLIKELY(!QuickCheckForUnpoisonedRegion(__offset, __size)) && \
|
||||
(__bad = __asan_region_is_poisoned(__offset, __size))) { \
|
||||
AsanInterceptorContext *_ctx = (AsanInterceptorContext *)ctx; \
|
||||
bool suppressed = false; \
|
||||
if (_ctx) { \
|
||||
suppressed = IsInterceptorSuppressed(_ctx->interceptor_name); \
|
||||
if (!suppressed && HaveStackTraceBasedSuppressions()) { \
|
||||
GET_STACK_TRACE_FATAL_HERE; \
|
||||
suppressed = IsStackTraceSuppressed(&stack); \
|
||||
} \
|
||||
} \
|
||||
if (!suppressed) { \
|
||||
GET_CURRENT_PC_BP_SP; \
|
||||
ReportGenericError(pc, bp, sp, __bad, isWrite, __size, 0, false); \
|
||||
} \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
// memcpy is called during __asan_init() from the internals of printf(...).
|
||||
// We do not treat memcpy with to==from as a bug.
|
||||
// See http://llvm.org/bugs/show_bug.cgi?id=11763.
|
||||
#define ASAN_MEMCPY_IMPL(ctx, to, from, size) \
|
||||
do { \
|
||||
if (UNLIKELY(!asan_inited)) return internal_memcpy(to, from, size); \
|
||||
if (asan_init_is_running) { \
|
||||
return REAL(memcpy)(to, from, size); \
|
||||
} \
|
||||
ENSURE_ASAN_INITED(); \
|
||||
if (flags()->replace_intrin) { \
|
||||
if (to != from) { \
|
||||
CHECK_RANGES_OVERLAP("memcpy", to, size, from, size); \
|
||||
} \
|
||||
ASAN_READ_RANGE(ctx, from, size); \
|
||||
ASAN_WRITE_RANGE(ctx, to, size); \
|
||||
} \
|
||||
return REAL(memcpy)(to, from, size); \
|
||||
#define ASAN_MEMCPY_IMPL(ctx, to, from, size) \
|
||||
do { \
|
||||
if (LIKELY(replace_intrin_cached)) { \
|
||||
if (LIKELY(to != from)) { \
|
||||
CHECK_RANGES_OVERLAP("memcpy", to, size, from, size); \
|
||||
} \
|
||||
ASAN_READ_RANGE(ctx, from, size); \
|
||||
ASAN_WRITE_RANGE(ctx, to, size); \
|
||||
} else if (UNLIKELY(!asan_inited)) { \
|
||||
return internal_memcpy(to, from, size); \
|
||||
} \
|
||||
return REAL(memcpy)(to, from, size); \
|
||||
} while (0)
|
||||
|
||||
// memset is called inside Printf.
|
||||
#define ASAN_MEMSET_IMPL(ctx, block, c, size) \
|
||||
do { \
|
||||
if (UNLIKELY(!asan_inited)) return internal_memset(block, c, size); \
|
||||
if (asan_init_is_running) { \
|
||||
return REAL(memset)(block, c, size); \
|
||||
} \
|
||||
ENSURE_ASAN_INITED(); \
|
||||
if (flags()->replace_intrin) { \
|
||||
ASAN_WRITE_RANGE(ctx, block, size); \
|
||||
} \
|
||||
return REAL(memset)(block, c, size); \
|
||||
#define ASAN_MEMSET_IMPL(ctx, block, c, size) \
|
||||
do { \
|
||||
if (LIKELY(replace_intrin_cached)) { \
|
||||
ASAN_WRITE_RANGE(ctx, block, size); \
|
||||
} else if (UNLIKELY(!asan_inited)) { \
|
||||
return internal_memset(block, c, size); \
|
||||
} \
|
||||
return REAL(memset)(block, c, size); \
|
||||
} while (0)
|
||||
|
||||
#define ASAN_MEMMOVE_IMPL(ctx, to, from, size) \
|
||||
do { \
|
||||
if (UNLIKELY(!asan_inited)) return internal_memmove(to, from, size); \
|
||||
ENSURE_ASAN_INITED(); \
|
||||
if (flags()->replace_intrin) { \
|
||||
ASAN_READ_RANGE(ctx, from, size); \
|
||||
ASAN_WRITE_RANGE(ctx, to, size); \
|
||||
} \
|
||||
return internal_memmove(to, from, size); \
|
||||
#define ASAN_MEMMOVE_IMPL(ctx, to, from, size) \
|
||||
do { \
|
||||
if (LIKELY(replace_intrin_cached)) { \
|
||||
ASAN_READ_RANGE(ctx, from, size); \
|
||||
ASAN_WRITE_RANGE(ctx, to, size); \
|
||||
} \
|
||||
return internal_memmove(to, from, size); \
|
||||
} while (0)
|
||||
|
||||
#define ASAN_READ_RANGE(ctx, offset, size) \
|
||||
|
@ -136,7 +132,7 @@ static inline bool RangesOverlap(const char *offset1, uptr length1,
|
|||
do { \
|
||||
const char *offset1 = (const char *)_offset1; \
|
||||
const char *offset2 = (const char *)_offset2; \
|
||||
if (RangesOverlap(offset1, length1, offset2, length2)) { \
|
||||
if (UNLIKELY(RangesOverlap(offset1, length1, offset2, length2))) { \
|
||||
GET_STACK_TRACE_FATAL_HERE; \
|
||||
bool suppressed = IsInterceptorSuppressed(name); \
|
||||
if (!suppressed && HaveStackTraceBasedSuppressions()) { \
|
||||
|
|
|
@ -6,6 +6,7 @@
|
|||
#include "sanitizer_common/sanitizer_common_interceptors_vfork_aarch64.inc.S"
|
||||
#include "sanitizer_common/sanitizer_common_interceptors_vfork_arm.inc.S"
|
||||
#include "sanitizer_common/sanitizer_common_interceptors_vfork_i386.inc.S"
|
||||
#include "sanitizer_common/sanitizer_common_interceptors_vfork_loongarch64.inc.S"
|
||||
#include "sanitizer_common/sanitizer_common_interceptors_vfork_riscv64.inc.S"
|
||||
#include "sanitizer_common/sanitizer_common_interceptors_vfork_x86_64.inc.S"
|
||||
#endif
|
||||
|
|
|
@ -7,6 +7,7 @@
|
|||
//===----------------------------------------------------------------------===//
|
||||
// Asan interface list.
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
INTERFACE_FUNCTION(__asan_addr_is_in_fake_stack)
|
||||
INTERFACE_FUNCTION(__asan_address_is_poisoned)
|
||||
INTERFACE_FUNCTION(__asan_after_dynamic_init)
|
||||
|
@ -107,6 +108,13 @@ INTERFACE_FUNCTION(__asan_report_store_n_noabort)
|
|||
INTERFACE_FUNCTION(__asan_set_death_callback)
|
||||
INTERFACE_FUNCTION(__asan_set_error_report_callback)
|
||||
INTERFACE_FUNCTION(__asan_set_shadow_00)
|
||||
INTERFACE_FUNCTION(__asan_set_shadow_01)
|
||||
INTERFACE_FUNCTION(__asan_set_shadow_02)
|
||||
INTERFACE_FUNCTION(__asan_set_shadow_03)
|
||||
INTERFACE_FUNCTION(__asan_set_shadow_04)
|
||||
INTERFACE_FUNCTION(__asan_set_shadow_05)
|
||||
INTERFACE_FUNCTION(__asan_set_shadow_06)
|
||||
INTERFACE_FUNCTION(__asan_set_shadow_07)
|
||||
INTERFACE_FUNCTION(__asan_set_shadow_f1)
|
||||
INTERFACE_FUNCTION(__asan_set_shadow_f2)
|
||||
INTERFACE_FUNCTION(__asan_set_shadow_f3)
|
||||
|
|
|
@ -53,8 +53,9 @@ extern "C" {
|
|||
const char *module_name; // Module name as a C string. This pointer is a
|
||||
// unique identifier of a module.
|
||||
uptr has_dynamic_init; // Non-zero if the global has dynamic initializer.
|
||||
__asan_global_source_location *location; // Source location of a global,
|
||||
// or NULL if it is unknown.
|
||||
uptr windows_padding; // TODO: Figure out how to remove this padding
|
||||
// that's simply here to make the MSVC incremental
|
||||
// linker happy...
|
||||
uptr odr_indicator; // The address of the ODR indicator symbol.
|
||||
};
|
||||
|
||||
|
@ -89,6 +90,20 @@ extern "C" {
|
|||
SANITIZER_INTERFACE_ATTRIBUTE
|
||||
void __asan_set_shadow_00(uptr addr, uptr size);
|
||||
SANITIZER_INTERFACE_ATTRIBUTE
|
||||
void __asan_set_shadow_01(uptr addr, uptr size);
|
||||
SANITIZER_INTERFACE_ATTRIBUTE
|
||||
void __asan_set_shadow_02(uptr addr, uptr size);
|
||||
SANITIZER_INTERFACE_ATTRIBUTE
|
||||
void __asan_set_shadow_03(uptr addr, uptr size);
|
||||
SANITIZER_INTERFACE_ATTRIBUTE
|
||||
void __asan_set_shadow_04(uptr addr, uptr size);
|
||||
SANITIZER_INTERFACE_ATTRIBUTE
|
||||
void __asan_set_shadow_05(uptr addr, uptr size);
|
||||
SANITIZER_INTERFACE_ATTRIBUTE
|
||||
void __asan_set_shadow_06(uptr addr, uptr size);
|
||||
SANITIZER_INTERFACE_ATTRIBUTE
|
||||
void __asan_set_shadow_07(uptr addr, uptr size);
|
||||
SANITIZER_INTERFACE_ATTRIBUTE
|
||||
void __asan_set_shadow_f1(uptr addr, uptr size);
|
||||
SANITIZER_INTERFACE_ATTRIBUTE
|
||||
void __asan_set_shadow_f2(uptr addr, uptr size);
|
||||
|
|
|
@ -17,19 +17,19 @@
|
|||
#include "asan_interface_internal.h"
|
||||
#include "sanitizer_common/sanitizer_common.h"
|
||||
#include "sanitizer_common/sanitizer_internal_defs.h"
|
||||
#include "sanitizer_common/sanitizer_stacktrace.h"
|
||||
#include "sanitizer_common/sanitizer_libc.h"
|
||||
#include "sanitizer_common/sanitizer_stacktrace.h"
|
||||
|
||||
#if __has_feature(address_sanitizer) || defined(__SANITIZE_ADDRESS__)
|
||||
# error "The AddressSanitizer run-time should not be"
|
||||
" instrumented by AddressSanitizer"
|
||||
# error \
|
||||
"The AddressSanitizer run-time should not be instrumented by AddressSanitizer"
|
||||
#endif
|
||||
|
||||
// Build-time configuration options.
|
||||
|
||||
// If set, asan will intercept C++ exception api call(s).
|
||||
#ifndef ASAN_HAS_EXCEPTIONS
|
||||
# define ASAN_HAS_EXCEPTIONS 1
|
||||
# define ASAN_HAS_EXCEPTIONS 1
|
||||
#endif
|
||||
|
||||
// If set, values like allocator chunk size, as well as defaults for some flags
|
||||
|
@ -43,11 +43,11 @@
|
|||
#endif
|
||||
|
||||
#ifndef ASAN_DYNAMIC
|
||||
# ifdef PIC
|
||||
# define ASAN_DYNAMIC 1
|
||||
# else
|
||||
# define ASAN_DYNAMIC 0
|
||||
# endif
|
||||
# ifdef PIC
|
||||
# define ASAN_DYNAMIC 1
|
||||
# else
|
||||
# define ASAN_DYNAMIC 0
|
||||
# endif
|
||||
#endif
|
||||
|
||||
// All internal functions in asan reside inside the __asan namespace
|
||||
|
@ -105,6 +105,7 @@ void AsanApplyToGlobals(globals_op_fptr op, const void *needle);
|
|||
|
||||
void AsanOnDeadlySignal(int, void *siginfo, void *context);
|
||||
|
||||
void SignContextStack(void *context);
|
||||
void ReadContextStack(void *context, uptr *stack, uptr *ssize);
|
||||
void StopInitOrderChecking();
|
||||
|
||||
|
@ -123,26 +124,19 @@ void *AsanDlSymNext(const char *sym);
|
|||
// `dlopen()` specific initialization inside this function.
|
||||
bool HandleDlopenInit();
|
||||
|
||||
// Add convenient macro for interface functions that may be represented as
|
||||
// weak hooks.
|
||||
#define ASAN_MALLOC_HOOK(ptr, size) \
|
||||
do { \
|
||||
if (&__sanitizer_malloc_hook) __sanitizer_malloc_hook(ptr, size); \
|
||||
RunMallocHooks(ptr, size); \
|
||||
} while (false)
|
||||
#define ASAN_FREE_HOOK(ptr) \
|
||||
do { \
|
||||
if (&__sanitizer_free_hook) __sanitizer_free_hook(ptr); \
|
||||
RunFreeHooks(ptr); \
|
||||
} while (false)
|
||||
void InstallAtExitCheckLeaks();
|
||||
|
||||
#define ASAN_ON_ERROR() \
|
||||
if (&__asan_on_error) __asan_on_error()
|
||||
if (&__asan_on_error) \
|
||||
__asan_on_error()
|
||||
|
||||
extern int asan_inited;
|
||||
// Used to avoid infinite recursion in __asan_init().
|
||||
extern bool asan_init_is_running;
|
||||
extern bool replace_intrin_cached;
|
||||
extern void (*death_callback)(void);
|
||||
// These magic values are written to shadow for better error reporting.
|
||||
// These magic values are written to shadow for better error
|
||||
// reporting.
|
||||
const int kAsanHeapLeftRedzoneMagic = 0xfa;
|
||||
const int kAsanHeapFreeMagic = 0xfd;
|
||||
const int kAsanStackLeftRedzoneMagic = 0xf1;
|
||||
|
|
|
@ -15,55 +15,56 @@
|
|||
#if SANITIZER_FREEBSD || SANITIZER_LINUX || SANITIZER_NETBSD || \
|
||||
SANITIZER_SOLARIS
|
||||
|
||||
#include "asan_interceptors.h"
|
||||
#include "asan_internal.h"
|
||||
#include "asan_premap_shadow.h"
|
||||
#include "asan_thread.h"
|
||||
#include "sanitizer_common/sanitizer_flags.h"
|
||||
#include "sanitizer_common/sanitizer_freebsd.h"
|
||||
#include "sanitizer_common/sanitizer_libc.h"
|
||||
#include "sanitizer_common/sanitizer_procmaps.h"
|
||||
# include <dlfcn.h>
|
||||
# include <fcntl.h>
|
||||
# include <limits.h>
|
||||
# include <pthread.h>
|
||||
# include <stdio.h>
|
||||
# include <sys/mman.h>
|
||||
# include <sys/resource.h>
|
||||
# include <sys/syscall.h>
|
||||
# include <sys/time.h>
|
||||
# include <sys/types.h>
|
||||
# include <unistd.h>
|
||||
# include <unwind.h>
|
||||
|
||||
#include <sys/time.h>
|
||||
#include <sys/resource.h>
|
||||
#include <sys/mman.h>
|
||||
#include <sys/syscall.h>
|
||||
#include <sys/types.h>
|
||||
#include <dlfcn.h>
|
||||
#include <fcntl.h>
|
||||
#include <limits.h>
|
||||
#include <pthread.h>
|
||||
#include <stdio.h>
|
||||
#include <unistd.h>
|
||||
#include <unwind.h>
|
||||
# include "asan_interceptors.h"
|
||||
# include "asan_internal.h"
|
||||
# include "asan_premap_shadow.h"
|
||||
# include "asan_thread.h"
|
||||
# include "sanitizer_common/sanitizer_flags.h"
|
||||
# include "sanitizer_common/sanitizer_freebsd.h"
|
||||
# include "sanitizer_common/sanitizer_hash.h"
|
||||
# include "sanitizer_common/sanitizer_libc.h"
|
||||
# include "sanitizer_common/sanitizer_procmaps.h"
|
||||
|
||||
#if SANITIZER_FREEBSD
|
||||
#include <sys/link_elf.h>
|
||||
#endif
|
||||
# if SANITIZER_FREEBSD
|
||||
# include <sys/link_elf.h>
|
||||
# endif
|
||||
|
||||
#if SANITIZER_SOLARIS
|
||||
#include <link.h>
|
||||
#endif
|
||||
# if SANITIZER_SOLARIS
|
||||
# include <link.h>
|
||||
# endif
|
||||
|
||||
#if SANITIZER_ANDROID || SANITIZER_FREEBSD || SANITIZER_SOLARIS
|
||||
#include <ucontext.h>
|
||||
extern "C" void* _DYNAMIC;
|
||||
#elif SANITIZER_NETBSD
|
||||
#include <link_elf.h>
|
||||
#include <ucontext.h>
|
||||
# if SANITIZER_ANDROID || SANITIZER_FREEBSD || SANITIZER_SOLARIS
|
||||
# include <ucontext.h>
|
||||
extern "C" void *_DYNAMIC;
|
||||
# elif SANITIZER_NETBSD
|
||||
# include <link_elf.h>
|
||||
# include <ucontext.h>
|
||||
extern Elf_Dyn _DYNAMIC;
|
||||
#else
|
||||
#include <sys/ucontext.h>
|
||||
#include <link.h>
|
||||
# else
|
||||
# include <link.h>
|
||||
# include <sys/ucontext.h>
|
||||
extern ElfW(Dyn) _DYNAMIC[];
|
||||
#endif
|
||||
# endif
|
||||
|
||||
// x86-64 FreeBSD 9.2 and older define 'ucontext_t' incorrectly in
|
||||
// 32-bit mode.
|
||||
#if SANITIZER_FREEBSD && (SANITIZER_WORDSIZE == 32) && \
|
||||
__FreeBSD_version <= 902001 // v9.2
|
||||
#define ucontext_t xucontext_t
|
||||
#endif
|
||||
# if SANITIZER_FREEBSD && (SANITIZER_WORDSIZE == 32) && \
|
||||
__FreeBSD_version <= 902001 // v9.2
|
||||
# define ucontext_t xucontext_t
|
||||
# endif
|
||||
|
||||
typedef enum {
|
||||
ASAN_RT_VERSION_UNDEFINED = 0,
|
||||
|
@ -74,21 +75,21 @@ typedef enum {
|
|||
// FIXME: perhaps also store abi version here?
|
||||
extern "C" {
|
||||
SANITIZER_INTERFACE_ATTRIBUTE
|
||||
asan_rt_version_t __asan_rt_version;
|
||||
asan_rt_version_t __asan_rt_version;
|
||||
}
|
||||
|
||||
namespace __asan {
|
||||
|
||||
void InitializePlatformInterceptors() {}
|
||||
void InitializePlatformExceptionHandlers() {}
|
||||
bool IsSystemHeapAddress (uptr addr) { return false; }
|
||||
bool IsSystemHeapAddress(uptr addr) { return false; }
|
||||
|
||||
void *AsanDoesNotSupportStaticLinkage() {
|
||||
// This will fail to link with -static.
|
||||
return &_DYNAMIC;
|
||||
}
|
||||
|
||||
#if ASAN_PREMAP_SHADOW
|
||||
# if ASAN_PREMAP_SHADOW
|
||||
uptr FindPremappedShadowStart(uptr shadow_size_bytes) {
|
||||
uptr granularity = GetMmapGranularity();
|
||||
uptr shadow_start = reinterpret_cast<uptr>(&__asan_shadow);
|
||||
|
@ -98,16 +99,16 @@ uptr FindPremappedShadowStart(uptr shadow_size_bytes) {
|
|||
UnmapFromTo(shadow_start + shadow_size, shadow_start + premap_shadow_size);
|
||||
return shadow_start;
|
||||
}
|
||||
#endif
|
||||
# endif
|
||||
|
||||
uptr FindDynamicShadowStart() {
|
||||
uptr shadow_size_bytes = MemToShadowSize(kHighMemEnd);
|
||||
#if ASAN_PREMAP_SHADOW
|
||||
# if ASAN_PREMAP_SHADOW
|
||||
if (!PremapShadowFailed())
|
||||
return FindPremappedShadowStart(shadow_size_bytes);
|
||||
#endif
|
||||
# endif
|
||||
|
||||
return MapDynamicShadow(shadow_size_bytes, SHADOW_SCALE,
|
||||
return MapDynamicShadow(shadow_size_bytes, ASAN_SHADOW_SCALE,
|
||||
/*min_shadow_base_alignment*/ 0, kHighMemEnd);
|
||||
}
|
||||
|
||||
|
@ -121,46 +122,40 @@ void FlushUnneededASanShadowMemory(uptr p, uptr size) {
|
|||
ReleaseMemoryPagesToOS(MemToShadow(p), MemToShadow(p + size));
|
||||
}
|
||||
|
||||
#if SANITIZER_ANDROID
|
||||
# if SANITIZER_ANDROID
|
||||
// FIXME: should we do anything for Android?
|
||||
void AsanCheckDynamicRTPrereqs() {}
|
||||
void AsanCheckIncompatibleRT() {}
|
||||
#else
|
||||
# else
|
||||
static int FindFirstDSOCallback(struct dl_phdr_info *info, size_t size,
|
||||
void *data) {
|
||||
VReport(2, "info->dlpi_name = %s\tinfo->dlpi_addr = %p\n",
|
||||
info->dlpi_name, info->dlpi_addr);
|
||||
VReport(2, "info->dlpi_name = %s\tinfo->dlpi_addr = %p\n", info->dlpi_name,
|
||||
(void *)info->dlpi_addr);
|
||||
|
||||
// Continue until the first dynamic library is found
|
||||
if (!info->dlpi_name || info->dlpi_name[0] == 0)
|
||||
return 0;
|
||||
const char **name = (const char **)data;
|
||||
|
||||
// Ignore vDSO
|
||||
if (internal_strncmp(info->dlpi_name, "linux-", sizeof("linux-") - 1) == 0)
|
||||
return 0;
|
||||
|
||||
#if SANITIZER_FREEBSD || SANITIZER_NETBSD
|
||||
// Ignore first entry (the main program)
|
||||
char **p = (char **)data;
|
||||
if (!(*p)) {
|
||||
*p = (char *)-1;
|
||||
if (!*name) {
|
||||
*name = "";
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
#if SANITIZER_SOLARIS
|
||||
// Ignore executable on Solaris
|
||||
if (info->dlpi_addr == 0)
|
||||
# if SANITIZER_LINUX
|
||||
// Ignore vDSO. glibc versions earlier than 2.15 (and some patched
|
||||
// by distributors) return an empty name for the vDSO entry, so
|
||||
// detect this as well.
|
||||
if (!info->dlpi_name[0] ||
|
||||
internal_strncmp(info->dlpi_name, "linux-", sizeof("linux-") - 1) == 0)
|
||||
return 0;
|
||||
#endif
|
||||
# endif
|
||||
|
||||
*(const char **)data = info->dlpi_name;
|
||||
*name = info->dlpi_name;
|
||||
return 1;
|
||||
}
|
||||
|
||||
static bool IsDynamicRTName(const char *libname) {
|
||||
return internal_strstr(libname, "libclang_rt.asan") ||
|
||||
internal_strstr(libname, "libasan.so");
|
||||
internal_strstr(libname, "libasan.so");
|
||||
}
|
||||
|
||||
static void ReportIncompatibleRT() {
|
||||
|
@ -175,10 +170,11 @@ void AsanCheckDynamicRTPrereqs() {
|
|||
// Ensure that dynamic RT is the first DSO in the list
|
||||
const char *first_dso_name = nullptr;
|
||||
dl_iterate_phdr(FindFirstDSOCallback, &first_dso_name);
|
||||
if (first_dso_name && !IsDynamicRTName(first_dso_name)) {
|
||||
Report("ASan runtime does not come first in initial library list; "
|
||||
"you should either link runtime to your application or "
|
||||
"manually preload it with LD_PRELOAD.\n");
|
||||
if (first_dso_name && first_dso_name[0] && !IsDynamicRTName(first_dso_name)) {
|
||||
Report(
|
||||
"ASan runtime does not come first in initial library list; "
|
||||
"you should either link runtime to your application or "
|
||||
"manually preload it with LD_PRELOAD.\n");
|
||||
Die();
|
||||
}
|
||||
}
|
||||
|
@ -196,13 +192,14 @@ void AsanCheckIncompatibleRT() {
|
|||
// as early as possible, otherwise ASan interceptors could bind to
|
||||
// the functions in dynamic ASan runtime instead of the functions in
|
||||
// system libraries, causing crashes later in ASan initialization.
|
||||
MemoryMappingLayout proc_maps(/*cache_enabled*/true);
|
||||
MemoryMappingLayout proc_maps(/*cache_enabled*/ true);
|
||||
char filename[PATH_MAX];
|
||||
MemoryMappedSegment segment(filename, sizeof(filename));
|
||||
while (proc_maps.Next(&segment)) {
|
||||
if (IsDynamicRTName(segment.filename)) {
|
||||
Report("Your application is linked against "
|
||||
"incompatible ASan runtimes.\n");
|
||||
Report(
|
||||
"Your application is linked against "
|
||||
"incompatible ASan runtimes.\n");
|
||||
Die();
|
||||
}
|
||||
}
|
||||
|
@ -212,24 +209,37 @@ void AsanCheckIncompatibleRT() {
|
|||
}
|
||||
}
|
||||
}
|
||||
#endif // SANITIZER_ANDROID
|
||||
# endif // SANITIZER_ANDROID
|
||||
|
||||
#if !SANITIZER_ANDROID
|
||||
void ReadContextStack(void *context, uptr *stack, uptr *ssize) {
|
||||
ucontext_t *ucp = (ucontext_t*)context;
|
||||
*stack = (uptr)ucp->uc_stack.ss_sp;
|
||||
*ssize = ucp->uc_stack.ss_size;
|
||||
}
|
||||
#else
|
||||
void ReadContextStack(void *context, uptr *stack, uptr *ssize) {
|
||||
UNIMPLEMENTED();
|
||||
}
|
||||
#endif
|
||||
# if ASAN_INTERCEPT_SWAPCONTEXT
|
||||
constexpr u32 kAsanContextStackFlagsMagic = 0x51260eea;
|
||||
|
||||
void *AsanDlSymNext(const char *sym) {
|
||||
return dlsym(RTLD_NEXT, sym);
|
||||
static int HashContextStack(const ucontext_t &ucp) {
|
||||
MurMur2Hash64Builder hash(kAsanContextStackFlagsMagic);
|
||||
hash.add(reinterpret_cast<uptr>(ucp.uc_stack.ss_sp));
|
||||
hash.add(ucp.uc_stack.ss_size);
|
||||
return static_cast<int>(hash.get());
|
||||
}
|
||||
|
||||
void SignContextStack(void *context) {
|
||||
ucontext_t *ucp = reinterpret_cast<ucontext_t *>(context);
|
||||
ucp->uc_stack.ss_flags = HashContextStack(*ucp);
|
||||
}
|
||||
|
||||
void ReadContextStack(void *context, uptr *stack, uptr *ssize) {
|
||||
const ucontext_t *ucp = reinterpret_cast<const ucontext_t *>(context);
|
||||
if (HashContextStack(*ucp) == ucp->uc_stack.ss_flags) {
|
||||
*stack = reinterpret_cast<uptr>(ucp->uc_stack.ss_sp);
|
||||
*ssize = ucp->uc_stack.ss_size;
|
||||
return;
|
||||
}
|
||||
*stack = 0;
|
||||
*ssize = 0;
|
||||
}
|
||||
# endif // ASAN_INTERCEPT_SWAPCONTEXT
|
||||
|
||||
void *AsanDlSymNext(const char *sym) { return dlsym(RTLD_NEXT, sym); }
|
||||
|
||||
bool HandleDlopenInit() {
|
||||
// Not supported on this platform.
|
||||
static_assert(!SANITIZER_SUPPORTS_INIT_FOR_DLOPEN,
|
||||
|
@ -237,7 +247,7 @@ bool HandleDlopenInit() {
|
|||
return false;
|
||||
}
|
||||
|
||||
} // namespace __asan
|
||||
} // namespace __asan
|
||||
|
||||
#endif // SANITIZER_FREEBSD || SANITIZER_LINUX || SANITIZER_NETBSD ||
|
||||
// SANITIZER_SOLARIS
|
||||
|
|
|
@ -12,7 +12,7 @@
|
|||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "sanitizer_common/sanitizer_platform.h"
|
||||
#if SANITIZER_MAC
|
||||
#if SANITIZER_APPLE
|
||||
|
||||
#include "asan_interceptors.h"
|
||||
#include "asan_internal.h"
|
||||
|
@ -55,7 +55,7 @@ void *AsanDoesNotSupportStaticLinkage() {
|
|||
}
|
||||
|
||||
uptr FindDynamicShadowStart() {
|
||||
return MapDynamicShadow(MemToShadowSize(kHighMemEnd), SHADOW_SCALE,
|
||||
return MapDynamicShadow(MemToShadowSize(kHighMemEnd), ASAN_SHADOW_SCALE,
|
||||
/*min_shadow_base_alignment*/ 0, kHighMemEnd);
|
||||
}
|
||||
|
||||
|
@ -95,10 +95,6 @@ void FlushUnneededASanShadowMemory(uptr p, uptr size) {
|
|||
ReleaseMemoryPagesToOS(MemToShadow(p), MemToShadow(p + size));
|
||||
}
|
||||
|
||||
void ReadContextStack(void *context, uptr *stack, uptr *ssize) {
|
||||
UNIMPLEMENTED();
|
||||
}
|
||||
|
||||
// Support for the following functions from libdispatch on Mac OS:
|
||||
// dispatch_async_f()
|
||||
// dispatch_async()
|
||||
|
@ -296,4 +292,4 @@ INTERCEPTOR(void, dispatch_source_set_event_handler,
|
|||
}
|
||||
#endif
|
||||
|
||||
#endif // SANITIZER_MAC
|
||||
#endif // SANITIZER_APPLE
|
||||
|
|
|
@ -21,129 +21,66 @@
|
|||
# include "asan_interceptors.h"
|
||||
# include "asan_internal.h"
|
||||
# include "asan_stack.h"
|
||||
# include "lsan/lsan_common.h"
|
||||
# include "sanitizer_common/sanitizer_allocator_checks.h"
|
||||
# include "sanitizer_common/sanitizer_allocator_dlsym.h"
|
||||
# include "sanitizer_common/sanitizer_errno.h"
|
||||
# include "sanitizer_common/sanitizer_tls_get_addr.h"
|
||||
|
||||
// ---------------------- Replacement functions ---------------- {{{1
|
||||
using namespace __asan;
|
||||
|
||||
static uptr allocated_for_dlsym;
|
||||
static uptr last_dlsym_alloc_size_in_words;
|
||||
static const uptr kDlsymAllocPoolSize = 1024;
|
||||
static uptr alloc_memory_for_dlsym[kDlsymAllocPoolSize];
|
||||
|
||||
static inline bool IsInDlsymAllocPool(const void *ptr) {
|
||||
uptr off = (uptr)ptr - (uptr)alloc_memory_for_dlsym;
|
||||
return off < allocated_for_dlsym * sizeof(alloc_memory_for_dlsym[0]);
|
||||
}
|
||||
|
||||
static void *AllocateFromLocalPool(uptr size_in_bytes) {
|
||||
uptr size_in_words = RoundUpTo(size_in_bytes, kWordSize) / kWordSize;
|
||||
void *mem = (void*)&alloc_memory_for_dlsym[allocated_for_dlsym];
|
||||
last_dlsym_alloc_size_in_words = size_in_words;
|
||||
allocated_for_dlsym += size_in_words;
|
||||
CHECK_LT(allocated_for_dlsym, kDlsymAllocPoolSize);
|
||||
return mem;
|
||||
}
|
||||
|
||||
static void DeallocateFromLocalPool(const void *ptr) {
|
||||
// Hack: since glibc 2.27 dlsym no longer uses stack-allocated memory to store
|
||||
// error messages and instead uses malloc followed by free. To avoid pool
|
||||
// exhaustion due to long object filenames, handle that special case here.
|
||||
uptr prev_offset = allocated_for_dlsym - last_dlsym_alloc_size_in_words;
|
||||
void *prev_mem = (void*)&alloc_memory_for_dlsym[prev_offset];
|
||||
if (prev_mem == ptr) {
|
||||
REAL(memset)(prev_mem, 0, last_dlsym_alloc_size_in_words * kWordSize);
|
||||
allocated_for_dlsym = prev_offset;
|
||||
last_dlsym_alloc_size_in_words = 0;
|
||||
struct DlsymAlloc : public DlSymAllocator<DlsymAlloc> {
|
||||
static bool UseImpl() { return asan_init_is_running; }
|
||||
static void OnAllocate(const void *ptr, uptr size) {
|
||||
# if CAN_SANITIZE_LEAKS
|
||||
// Suppress leaks from dlerror(). Previously dlsym hack on global array was
|
||||
// used by leak sanitizer as a root region.
|
||||
__lsan_register_root_region(ptr, size);
|
||||
# endif
|
||||
}
|
||||
}
|
||||
|
||||
static int PosixMemalignFromLocalPool(void **memptr, uptr alignment,
|
||||
uptr size_in_bytes) {
|
||||
if (UNLIKELY(!CheckPosixMemalignAlignment(alignment)))
|
||||
return errno_EINVAL;
|
||||
|
||||
CHECK(alignment >= kWordSize);
|
||||
|
||||
uptr addr = (uptr)&alloc_memory_for_dlsym[allocated_for_dlsym];
|
||||
uptr aligned_addr = RoundUpTo(addr, alignment);
|
||||
uptr aligned_size = RoundUpTo(size_in_bytes, kWordSize);
|
||||
|
||||
uptr *end_mem = (uptr*)(aligned_addr + aligned_size);
|
||||
uptr allocated = end_mem - alloc_memory_for_dlsym;
|
||||
if (allocated >= kDlsymAllocPoolSize)
|
||||
return errno_ENOMEM;
|
||||
|
||||
allocated_for_dlsym = allocated;
|
||||
*memptr = (void*)aligned_addr;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline bool MaybeInDlsym() {
|
||||
// Fuchsia doesn't use dlsym-based interceptors.
|
||||
return !SANITIZER_FUCHSIA && asan_init_is_running;
|
||||
}
|
||||
|
||||
static inline bool UseLocalPool() { return MaybeInDlsym(); }
|
||||
|
||||
static void *ReallocFromLocalPool(void *ptr, uptr size) {
|
||||
const uptr offset = (uptr)ptr - (uptr)alloc_memory_for_dlsym;
|
||||
const uptr copy_size = Min(size, kDlsymAllocPoolSize - offset);
|
||||
void *new_ptr;
|
||||
if (UNLIKELY(UseLocalPool())) {
|
||||
new_ptr = AllocateFromLocalPool(size);
|
||||
} else {
|
||||
ENSURE_ASAN_INITED();
|
||||
GET_STACK_TRACE_MALLOC;
|
||||
new_ptr = asan_malloc(size, &stack);
|
||||
static void OnFree(const void *ptr, uptr size) {
|
||||
# if CAN_SANITIZE_LEAKS
|
||||
__lsan_unregister_root_region(ptr, size);
|
||||
# endif
|
||||
}
|
||||
internal_memcpy(new_ptr, ptr, copy_size);
|
||||
return new_ptr;
|
||||
}
|
||||
};
|
||||
|
||||
INTERCEPTOR(void, free, void *ptr) {
|
||||
if (UNLIKELY(IsInDlsymAllocPool(ptr))) {
|
||||
DeallocateFromLocalPool(ptr);
|
||||
return;
|
||||
}
|
||||
if (DlsymAlloc::PointerIsMine(ptr))
|
||||
return DlsymAlloc::Free(ptr);
|
||||
GET_STACK_TRACE_FREE;
|
||||
asan_free(ptr, &stack, FROM_MALLOC);
|
||||
}
|
||||
|
||||
#if SANITIZER_INTERCEPT_CFREE
|
||||
INTERCEPTOR(void, cfree, void *ptr) {
|
||||
if (UNLIKELY(IsInDlsymAllocPool(ptr)))
|
||||
return;
|
||||
if (DlsymAlloc::PointerIsMine(ptr))
|
||||
return DlsymAlloc::Free(ptr);
|
||||
GET_STACK_TRACE_FREE;
|
||||
asan_free(ptr, &stack, FROM_MALLOC);
|
||||
}
|
||||
#endif // SANITIZER_INTERCEPT_CFREE
|
||||
|
||||
INTERCEPTOR(void*, malloc, uptr size) {
|
||||
if (UNLIKELY(UseLocalPool()))
|
||||
// Hack: dlsym calls malloc before REAL(malloc) is retrieved from dlsym.
|
||||
return AllocateFromLocalPool(size);
|
||||
if (DlsymAlloc::Use())
|
||||
return DlsymAlloc::Allocate(size);
|
||||
ENSURE_ASAN_INITED();
|
||||
GET_STACK_TRACE_MALLOC;
|
||||
return asan_malloc(size, &stack);
|
||||
}
|
||||
|
||||
INTERCEPTOR(void*, calloc, uptr nmemb, uptr size) {
|
||||
if (UNLIKELY(UseLocalPool()))
|
||||
// Hack: dlsym calls calloc before REAL(calloc) is retrieved from dlsym.
|
||||
return AllocateFromLocalPool(nmemb * size);
|
||||
if (DlsymAlloc::Use())
|
||||
return DlsymAlloc::Callocate(nmemb, size);
|
||||
ENSURE_ASAN_INITED();
|
||||
GET_STACK_TRACE_MALLOC;
|
||||
return asan_calloc(nmemb, size, &stack);
|
||||
}
|
||||
|
||||
INTERCEPTOR(void*, realloc, void *ptr, uptr size) {
|
||||
if (UNLIKELY(IsInDlsymAllocPool(ptr)))
|
||||
return ReallocFromLocalPool(ptr, size);
|
||||
if (UNLIKELY(UseLocalPool()))
|
||||
return AllocateFromLocalPool(size);
|
||||
if (DlsymAlloc::Use() || DlsymAlloc::PointerIsMine(ptr))
|
||||
return DlsymAlloc::Realloc(ptr, size);
|
||||
ENSURE_ASAN_INITED();
|
||||
GET_STACK_TRACE_MALLOC;
|
||||
return asan_realloc(ptr, size, &stack);
|
||||
|
@ -205,8 +142,6 @@ INTERCEPTOR(int, mallopt, int cmd, int value) {
|
|||
#endif // SANITIZER_INTERCEPT_MALLOPT_AND_MALLINFO
|
||||
|
||||
INTERCEPTOR(int, posix_memalign, void **memptr, uptr alignment, uptr size) {
|
||||
if (UNLIKELY(UseLocalPool()))
|
||||
return PosixMemalignFromLocalPool(memptr, alignment, size);
|
||||
GET_STACK_TRACE_MALLOC;
|
||||
return asan_posix_memalign(memptr, alignment, size, &stack);
|
||||
}
|
||||
|
|
|
@ -12,7 +12,7 @@
|
|||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "sanitizer_common/sanitizer_platform.h"
|
||||
#if SANITIZER_MAC
|
||||
#if SANITIZER_APPLE
|
||||
|
||||
#include "asan_interceptors.h"
|
||||
#include "asan_report.h"
|
||||
|
|
|
@ -13,7 +13,7 @@
|
|||
#ifndef ASAN_MAPPING_H
|
||||
#define ASAN_MAPPING_H
|
||||
|
||||
#include "asan_internal.h"
|
||||
#include "sanitizer_common/sanitizer_platform.h"
|
||||
|
||||
// The full explanation of the memory mapping could be found here:
|
||||
// https://github.com/google/sanitizers/wiki/AddressSanitizerAlgorithm
|
||||
|
@ -114,6 +114,13 @@
|
|||
// || `[0x0080000000000, 0x008ffffffffff]` || LowShadow ||
|
||||
// || `[0x0000000000000, 0x007ffffffffff]` || LowMem ||
|
||||
//
|
||||
// Default Linux/LoongArch64 (47-bit VMA) mapping:
|
||||
// || `[0x500000000000, 0x7fffffffffff]` || HighMem ||
|
||||
// || `[0x4a0000000000, 0x4fffffffffff]` || HighShadow ||
|
||||
// || `[0x480000000000, 0x49ffffffffff]` || ShadowGap ||
|
||||
// || `[0x400000000000, 0x47ffffffffff]` || LowShadow ||
|
||||
// || `[0x000000000000, 0x3fffffffffff]` || LowMem ||
|
||||
//
|
||||
// Shadow mapping on FreeBSD/x86-64 with SHADOW_OFFSET == 0x400000000000:
|
||||
// || `[0x500000000000, 0x7fffffffffff]` || HighMem ||
|
||||
// || `[0x4a0000000000, 0x4fffffffffff]` || HighShadow ||
|
||||
|
@ -151,149 +158,151 @@
|
|||
// || `[0x30000000, 0x35ffffff]` || LowShadow ||
|
||||
// || `[0x00000000, 0x2fffffff]` || LowMem ||
|
||||
|
||||
#if defined(ASAN_SHADOW_SCALE)
|
||||
static const u64 kDefaultShadowScale = ASAN_SHADOW_SCALE;
|
||||
#else
|
||||
static const u64 kDefaultShadowScale = 3;
|
||||
#endif
|
||||
static const u64 kDefaultShadowSentinel = ~(uptr)0;
|
||||
static const u64 kDefaultShadowOffset32 = 1ULL << 29; // 0x20000000
|
||||
static const u64 kDefaultShadowOffset64 = 1ULL << 44;
|
||||
static const u64 kDefaultShort64bitShadowOffset =
|
||||
0x7FFFFFFF & (~0xFFFULL << kDefaultShadowScale); // < 2G.
|
||||
static const u64 kAArch64_ShadowOffset64 = 1ULL << 36;
|
||||
static const u64 kRiscv64_ShadowOffset64 = 0xd55550000;
|
||||
static const u64 kMIPS32_ShadowOffset32 = 0x0aaa0000;
|
||||
static const u64 kMIPS64_ShadowOffset64 = 1ULL << 37;
|
||||
static const u64 kPPC64_ShadowOffset64 = 1ULL << 44;
|
||||
static const u64 kSystemZ_ShadowOffset64 = 1ULL << 52;
|
||||
static const u64 kSPARC64_ShadowOffset64 = 1ULL << 43; // 0x80000000000
|
||||
static const u64 kFreeBSD_ShadowOffset32 = 1ULL << 30; // 0x40000000
|
||||
static const u64 kFreeBSD_ShadowOffset64 = 1ULL << 46; // 0x400000000000
|
||||
static const u64 kNetBSD_ShadowOffset32 = 1ULL << 30; // 0x40000000
|
||||
static const u64 kNetBSD_ShadowOffset64 = 1ULL << 46; // 0x400000000000
|
||||
static const u64 kWindowsShadowOffset32 = 3ULL << 28; // 0x30000000
|
||||
|
||||
#define SHADOW_SCALE kDefaultShadowScale
|
||||
#define ASAN_SHADOW_SCALE 3
|
||||
|
||||
#if SANITIZER_FUCHSIA
|
||||
# define SHADOW_OFFSET (0)
|
||||
# define ASAN_SHADOW_OFFSET_CONST (0)
|
||||
#elif SANITIZER_WORDSIZE == 32
|
||||
# if SANITIZER_ANDROID
|
||||
# define SHADOW_OFFSET __asan_shadow_memory_dynamic_address
|
||||
# define ASAN_SHADOW_OFFSET_DYNAMIC
|
||||
# elif defined(__mips__)
|
||||
# define SHADOW_OFFSET kMIPS32_ShadowOffset32
|
||||
# define ASAN_SHADOW_OFFSET_CONST 0x0aaa0000
|
||||
# elif SANITIZER_FREEBSD
|
||||
# define SHADOW_OFFSET kFreeBSD_ShadowOffset32
|
||||
# define ASAN_SHADOW_OFFSET_CONST 0x40000000
|
||||
# elif SANITIZER_NETBSD
|
||||
# define SHADOW_OFFSET kNetBSD_ShadowOffset32
|
||||
# define ASAN_SHADOW_OFFSET_CONST 0x40000000
|
||||
# elif SANITIZER_WINDOWS
|
||||
# define SHADOW_OFFSET kWindowsShadowOffset32
|
||||
# define ASAN_SHADOW_OFFSET_CONST 0x30000000
|
||||
# elif SANITIZER_IOS
|
||||
# define SHADOW_OFFSET __asan_shadow_memory_dynamic_address
|
||||
# define ASAN_SHADOW_OFFSET_DYNAMIC
|
||||
# else
|
||||
# define SHADOW_OFFSET kDefaultShadowOffset32
|
||||
# define ASAN_SHADOW_OFFSET_CONST 0x20000000
|
||||
# endif
|
||||
#else
|
||||
# if SANITIZER_IOS
|
||||
# define SHADOW_OFFSET __asan_shadow_memory_dynamic_address
|
||||
# elif SANITIZER_MAC && defined(__aarch64__)
|
||||
# define SHADOW_OFFSET __asan_shadow_memory_dynamic_address
|
||||
#elif SANITIZER_RISCV64
|
||||
#define SHADOW_OFFSET kRiscv64_ShadowOffset64
|
||||
# define ASAN_SHADOW_OFFSET_DYNAMIC
|
||||
# elif SANITIZER_APPLE && defined(__aarch64__)
|
||||
# define ASAN_SHADOW_OFFSET_DYNAMIC
|
||||
# elif SANITIZER_FREEBSD && defined(__aarch64__)
|
||||
# define ASAN_SHADOW_OFFSET_CONST 0x0000800000000000
|
||||
# elif SANITIZER_RISCV64
|
||||
# define ASAN_SHADOW_OFFSET_CONST 0x0000000d55550000
|
||||
# elif defined(__aarch64__)
|
||||
# define SHADOW_OFFSET kAArch64_ShadowOffset64
|
||||
# define ASAN_SHADOW_OFFSET_CONST 0x0000001000000000
|
||||
# elif defined(__powerpc64__)
|
||||
# define SHADOW_OFFSET kPPC64_ShadowOffset64
|
||||
# define ASAN_SHADOW_OFFSET_CONST 0x0000100000000000
|
||||
# elif defined(__s390x__)
|
||||
# define SHADOW_OFFSET kSystemZ_ShadowOffset64
|
||||
# define ASAN_SHADOW_OFFSET_CONST 0x0010000000000000
|
||||
# elif SANITIZER_FREEBSD
|
||||
# define SHADOW_OFFSET kFreeBSD_ShadowOffset64
|
||||
# define ASAN_SHADOW_OFFSET_CONST 0x0000400000000000
|
||||
# elif SANITIZER_NETBSD
|
||||
# define SHADOW_OFFSET kNetBSD_ShadowOffset64
|
||||
# elif SANITIZER_MAC
|
||||
# define SHADOW_OFFSET kDefaultShadowOffset64
|
||||
# define ASAN_SHADOW_OFFSET_CONST 0x0000400000000000
|
||||
# elif SANITIZER_APPLE
|
||||
# define ASAN_SHADOW_OFFSET_CONST 0x0000100000000000
|
||||
# elif defined(__mips64)
|
||||
# define SHADOW_OFFSET kMIPS64_ShadowOffset64
|
||||
#elif defined(__sparc__)
|
||||
#define SHADOW_OFFSET kSPARC64_ShadowOffset64
|
||||
# define ASAN_SHADOW_OFFSET_CONST 0x0000002000000000
|
||||
# elif defined(__sparc__)
|
||||
# define ASAN_SHADOW_OFFSET_CONST 0x0000080000000000
|
||||
# elif SANITIZER_LOONGARCH64
|
||||
# define ASAN_SHADOW_OFFSET_CONST 0x0000400000000000
|
||||
# elif SANITIZER_WINDOWS64
|
||||
# define SHADOW_OFFSET __asan_shadow_memory_dynamic_address
|
||||
# define ASAN_SHADOW_OFFSET_DYNAMIC
|
||||
# else
|
||||
# define SHADOW_OFFSET kDefaultShort64bitShadowOffset
|
||||
# if ASAN_SHADOW_SCALE != 3
|
||||
# error "Value below is based on shadow scale = 3."
|
||||
# error "Original formula was: 0x7FFFFFFF & (~0xFFFULL << SHADOW_SCALE)."
|
||||
# endif
|
||||
# define ASAN_SHADOW_OFFSET_CONST 0x000000007fff8000
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#if SANITIZER_ANDROID && defined(__arm__)
|
||||
# define ASAN_PREMAP_SHADOW 1
|
||||
#else
|
||||
# define ASAN_PREMAP_SHADOW 0
|
||||
#endif
|
||||
#if defined(__cplusplus)
|
||||
# include "asan_internal.h"
|
||||
|
||||
#define SHADOW_GRANULARITY (1ULL << SHADOW_SCALE)
|
||||
static const u64 kDefaultShadowSentinel = ~(uptr)0;
|
||||
|
||||
#define DO_ASAN_MAPPING_PROFILE 0 // Set to 1 to profile the functions below.
|
||||
# if defined(ASAN_SHADOW_OFFSET_CONST)
|
||||
static const u64 kConstShadowOffset = ASAN_SHADOW_OFFSET_CONST;
|
||||
# define ASAN_SHADOW_OFFSET kConstShadowOffset
|
||||
# elif defined(ASAN_SHADOW_OFFSET_DYNAMIC)
|
||||
# define ASAN_SHADOW_OFFSET __asan_shadow_memory_dynamic_address
|
||||
# else
|
||||
# error "ASAN_SHADOW_OFFSET can't be determined."
|
||||
# endif
|
||||
|
||||
#if DO_ASAN_MAPPING_PROFILE
|
||||
# define PROFILE_ASAN_MAPPING() AsanMappingProfile[__LINE__]++;
|
||||
#else
|
||||
# define PROFILE_ASAN_MAPPING()
|
||||
#endif
|
||||
# if SANITIZER_ANDROID && defined(__arm__)
|
||||
# define ASAN_PREMAP_SHADOW 1
|
||||
# else
|
||||
# define ASAN_PREMAP_SHADOW 0
|
||||
# endif
|
||||
|
||||
# define ASAN_SHADOW_GRANULARITY (1ULL << ASAN_SHADOW_SCALE)
|
||||
|
||||
# define DO_ASAN_MAPPING_PROFILE 0 // Set to 1 to profile the functions below.
|
||||
|
||||
# if DO_ASAN_MAPPING_PROFILE
|
||||
# define PROFILE_ASAN_MAPPING() AsanMappingProfile[__LINE__]++;
|
||||
# else
|
||||
# define PROFILE_ASAN_MAPPING()
|
||||
# endif
|
||||
|
||||
// If 1, all shadow boundaries are constants.
|
||||
// Don't set to 1 other than for testing.
|
||||
#define ASAN_FIXED_MAPPING 0
|
||||
# define ASAN_FIXED_MAPPING 0
|
||||
|
||||
namespace __asan {
|
||||
|
||||
extern uptr AsanMappingProfile[];
|
||||
|
||||
#if ASAN_FIXED_MAPPING
|
||||
# if ASAN_FIXED_MAPPING
|
||||
// Fixed mapping for 64-bit Linux. Mostly used for performance comparison
|
||||
// with non-fixed mapping. As of r175253 (Feb 2013) the performance
|
||||
// difference between fixed and non-fixed mapping is below the noise level.
|
||||
static uptr kHighMemEnd = 0x7fffffffffffULL;
|
||||
static uptr kMidMemBeg = 0x3000000000ULL;
|
||||
static uptr kMidMemEnd = 0x4fffffffffULL;
|
||||
#else
|
||||
static uptr kMidMemBeg = 0x3000000000ULL;
|
||||
static uptr kMidMemEnd = 0x4fffffffffULL;
|
||||
# else
|
||||
extern uptr kHighMemEnd, kMidMemBeg, kMidMemEnd; // Initialized in __asan_init.
|
||||
#endif
|
||||
# endif
|
||||
|
||||
} // namespace __asan
|
||||
|
||||
#if defined(__sparc__) && SANITIZER_WORDSIZE == 64
|
||||
# include "asan_mapping_sparc64.h"
|
||||
#else
|
||||
#define MEM_TO_SHADOW(mem) (((mem) >> SHADOW_SCALE) + (SHADOW_OFFSET))
|
||||
# if defined(__sparc__) && SANITIZER_WORDSIZE == 64
|
||||
# include "asan_mapping_sparc64.h"
|
||||
# else
|
||||
# define MEM_TO_SHADOW(mem) \
|
||||
(((mem) >> ASAN_SHADOW_SCALE) + (ASAN_SHADOW_OFFSET))
|
||||
# define SHADOW_TO_MEM(mem) \
|
||||
(((mem) - (ASAN_SHADOW_OFFSET)) << (ASAN_SHADOW_SCALE))
|
||||
|
||||
#define kLowMemBeg 0
|
||||
#define kLowMemEnd (SHADOW_OFFSET ? SHADOW_OFFSET - 1 : 0)
|
||||
# define kLowMemBeg 0
|
||||
# define kLowMemEnd (ASAN_SHADOW_OFFSET ? ASAN_SHADOW_OFFSET - 1 : 0)
|
||||
|
||||
#define kLowShadowBeg SHADOW_OFFSET
|
||||
#define kLowShadowEnd MEM_TO_SHADOW(kLowMemEnd)
|
||||
# define kLowShadowBeg ASAN_SHADOW_OFFSET
|
||||
# define kLowShadowEnd MEM_TO_SHADOW(kLowMemEnd)
|
||||
|
||||
#define kHighMemBeg (MEM_TO_SHADOW(kHighMemEnd) + 1)
|
||||
# define kHighMemBeg (MEM_TO_SHADOW(kHighMemEnd) + 1)
|
||||
|
||||
#define kHighShadowBeg MEM_TO_SHADOW(kHighMemBeg)
|
||||
#define kHighShadowEnd MEM_TO_SHADOW(kHighMemEnd)
|
||||
# define kHighShadowBeg MEM_TO_SHADOW(kHighMemBeg)
|
||||
# define kHighShadowEnd MEM_TO_SHADOW(kHighMemEnd)
|
||||
|
||||
# define kMidShadowBeg MEM_TO_SHADOW(kMidMemBeg)
|
||||
# define kMidShadowEnd MEM_TO_SHADOW(kMidMemEnd)
|
||||
# define kMidShadowBeg MEM_TO_SHADOW(kMidMemBeg)
|
||||
# define kMidShadowEnd MEM_TO_SHADOW(kMidMemEnd)
|
||||
|
||||
// With the zero shadow base we can not actually map pages starting from 0.
|
||||
// This constant is somewhat arbitrary.
|
||||
#define kZeroBaseShadowStart 0
|
||||
#define kZeroBaseMaxShadowStart (1 << 18)
|
||||
# define kZeroBaseShadowStart 0
|
||||
# define kZeroBaseMaxShadowStart (1 << 18)
|
||||
|
||||
#define kShadowGapBeg (kLowShadowEnd ? kLowShadowEnd + 1 \
|
||||
: kZeroBaseShadowStart)
|
||||
#define kShadowGapEnd ((kMidMemBeg ? kMidShadowBeg : kHighShadowBeg) - 1)
|
||||
# define kShadowGapBeg \
|
||||
(kLowShadowEnd ? kLowShadowEnd + 1 : kZeroBaseShadowStart)
|
||||
# define kShadowGapEnd ((kMidMemBeg ? kMidShadowBeg : kHighShadowBeg) - 1)
|
||||
|
||||
#define kShadowGap2Beg (kMidMemBeg ? kMidShadowEnd + 1 : 0)
|
||||
#define kShadowGap2End (kMidMemBeg ? kMidMemBeg - 1 : 0)
|
||||
# define kShadowGap2Beg (kMidMemBeg ? kMidShadowEnd + 1 : 0)
|
||||
# define kShadowGap2End (kMidMemBeg ? kMidMemBeg - 1 : 0)
|
||||
|
||||
#define kShadowGap3Beg (kMidMemBeg ? kMidMemEnd + 1 : 0)
|
||||
#define kShadowGap3End (kMidMemBeg ? kHighShadowBeg - 1 : 0)
|
||||
# define kShadowGap3Beg (kMidMemBeg ? kMidMemEnd + 1 : 0)
|
||||
# define kShadowGap3End (kMidMemBeg ? kHighShadowBeg - 1 : 0)
|
||||
|
||||
namespace __asan {
|
||||
|
||||
|
@ -331,29 +340,31 @@ static inline bool AddrIsInShadowGap(uptr a) {
|
|||
PROFILE_ASAN_MAPPING();
|
||||
if (kMidMemBeg) {
|
||||
if (a <= kShadowGapEnd)
|
||||
return SHADOW_OFFSET == 0 || a >= kShadowGapBeg;
|
||||
return ASAN_SHADOW_OFFSET == 0 || a >= kShadowGapBeg;
|
||||
return (a >= kShadowGap2Beg && a <= kShadowGap2End) ||
|
||||
(a >= kShadowGap3Beg && a <= kShadowGap3End);
|
||||
}
|
||||
// In zero-based shadow mode we treat addresses near zero as addresses
|
||||
// in shadow gap as well.
|
||||
if (SHADOW_OFFSET == 0)
|
||||
if (ASAN_SHADOW_OFFSET == 0)
|
||||
return a <= kShadowGapEnd;
|
||||
return a >= kShadowGapBeg && a <= kShadowGapEnd;
|
||||
}
|
||||
|
||||
} // namespace __asan
|
||||
|
||||
#endif
|
||||
# endif
|
||||
|
||||
namespace __asan {
|
||||
|
||||
static inline uptr MemToShadowSize(uptr size) { return size >> SHADOW_SCALE; }
|
||||
static inline uptr MemToShadowSize(uptr size) {
|
||||
return size >> ASAN_SHADOW_SCALE;
|
||||
}
|
||||
|
||||
static inline bool AddrIsInMem(uptr a) {
|
||||
PROFILE_ASAN_MAPPING();
|
||||
return AddrIsInLowMem(a) || AddrIsInMidMem(a) || AddrIsInHighMem(a) ||
|
||||
(flags()->protect_shadow_gap == 0 && AddrIsInShadowGap(a));
|
||||
(flags()->protect_shadow_gap == 0 && AddrIsInShadowGap(a));
|
||||
}
|
||||
|
||||
static inline uptr MemToShadow(uptr p) {
|
||||
|
@ -367,19 +378,25 @@ static inline bool AddrIsInShadow(uptr a) {
|
|||
return AddrIsInLowShadow(a) || AddrIsInMidShadow(a) || AddrIsInHighShadow(a);
|
||||
}
|
||||
|
||||
static inline uptr ShadowToMem(uptr p) {
|
||||
PROFILE_ASAN_MAPPING();
|
||||
CHECK(AddrIsInShadow(p));
|
||||
return SHADOW_TO_MEM(p);
|
||||
}
|
||||
|
||||
static inline bool AddrIsAlignedByGranularity(uptr a) {
|
||||
PROFILE_ASAN_MAPPING();
|
||||
return (a & (SHADOW_GRANULARITY - 1)) == 0;
|
||||
return (a & (ASAN_SHADOW_GRANULARITY - 1)) == 0;
|
||||
}
|
||||
|
||||
static inline bool AddressIsPoisoned(uptr a) {
|
||||
PROFILE_ASAN_MAPPING();
|
||||
const uptr kAccessSize = 1;
|
||||
u8 *shadow_address = (u8*)MEM_TO_SHADOW(a);
|
||||
u8 *shadow_address = (u8 *)MEM_TO_SHADOW(a);
|
||||
s8 shadow_value = *shadow_address;
|
||||
if (shadow_value) {
|
||||
u8 last_accessed_byte = (a & (SHADOW_GRANULARITY - 1))
|
||||
+ kAccessSize - 1;
|
||||
u8 last_accessed_byte =
|
||||
(a & (ASAN_SHADOW_GRANULARITY - 1)) + kAccessSize - 1;
|
||||
return (last_accessed_byte >= shadow_value);
|
||||
}
|
||||
return false;
|
||||
|
@ -390,4 +407,6 @@ static const uptr kAsanMappingProfileSize = __LINE__;
|
|||
|
||||
} // namespace __asan
|
||||
|
||||
#endif // __cplusplus
|
||||
|
||||
#endif // ASAN_MAPPING_H
|
||||
|
|
|
@ -25,13 +25,15 @@
|
|||
// The idea is to chop the high bits before doing the scaling, so the two
|
||||
// parts become contiguous again and the usual scheme can be applied.
|
||||
|
||||
#define MEM_TO_SHADOW(mem) \
|
||||
((((mem) << HIGH_BITS) >> (HIGH_BITS + (SHADOW_SCALE))) + (SHADOW_OFFSET))
|
||||
#define MEM_TO_SHADOW(mem) \
|
||||
((((mem) << HIGH_BITS) >> (HIGH_BITS + (ASAN_SHADOW_SCALE))) + \
|
||||
(ASAN_SHADOW_OFFSET))
|
||||
#define SHADOW_TO_MEM(ptr) (__asan::ShadowToMemSparc64(ptr))
|
||||
|
||||
#define kLowMemBeg 0
|
||||
#define kLowMemEnd (SHADOW_OFFSET - 1)
|
||||
#define kLowMemEnd (ASAN_SHADOW_OFFSET - 1)
|
||||
|
||||
#define kLowShadowBeg SHADOW_OFFSET
|
||||
#define kLowShadowBeg ASAN_SHADOW_OFFSET
|
||||
#define kLowShadowEnd MEM_TO_SHADOW(kLowMemEnd)
|
||||
|
||||
// But of course there is the huge hole between the high shadow memory,
|
||||
|
@ -96,6 +98,24 @@ static inline bool AddrIsInShadowGap(uptr a) {
|
|||
return a >= kShadowGapBeg && a <= kShadowGapEnd;
|
||||
}
|
||||
|
||||
static inline constexpr uptr ShadowToMemSparc64(uptr p) {
|
||||
PROFILE_ASAN_MAPPING();
|
||||
p -= ASAN_SHADOW_OFFSET;
|
||||
p <<= ASAN_SHADOW_SCALE;
|
||||
if (p >= 0x8000000000000) {
|
||||
p |= (~0ULL) << VMA_BITS;
|
||||
}
|
||||
return p;
|
||||
}
|
||||
|
||||
static_assert(ShadowToMemSparc64(MEM_TO_SHADOW(0x0000000000000000)) ==
|
||||
0x0000000000000000);
|
||||
static_assert(ShadowToMemSparc64(MEM_TO_SHADOW(0xfff8000000000000)) ==
|
||||
0xfff8000000000000);
|
||||
// Gets aligned down.
|
||||
static_assert(ShadowToMemSparc64(MEM_TO_SHADOW(0x0007ffffffffffff)) ==
|
||||
0x0007fffffffffff8);
|
||||
|
||||
} // namespace __asan
|
||||
|
||||
#endif // ASAN_MAPPING_SPARC64_H
|
||||
|
|
|
@ -89,7 +89,7 @@ enum class align_val_t: size_t {};
|
|||
// delete.
|
||||
// To make sure that C++ allocation/deallocation operators are overridden on
|
||||
// OS X we need to intercept them using their mangled names.
|
||||
#if !SANITIZER_MAC
|
||||
#if !SANITIZER_APPLE
|
||||
CXX_OPERATOR_ATTRIBUTE
|
||||
void *operator new(size_t size)
|
||||
{ OPERATOR_NEW_BODY(FROM_NEW, false /*nothrow*/); }
|
||||
|
@ -115,7 +115,7 @@ CXX_OPERATOR_ATTRIBUTE
|
|||
void *operator new[](size_t size, std::align_val_t align, std::nothrow_t const&)
|
||||
{ OPERATOR_NEW_BODY_ALIGN(FROM_NEW_BR, true /*nothrow*/); }
|
||||
|
||||
#else // SANITIZER_MAC
|
||||
#else // SANITIZER_APPLE
|
||||
INTERCEPTOR(void *, _Znwm, size_t size) {
|
||||
OPERATOR_NEW_BODY(FROM_NEW, false /*nothrow*/);
|
||||
}
|
||||
|
@ -128,7 +128,7 @@ INTERCEPTOR(void *, _ZnwmRKSt9nothrow_t, size_t size, std::nothrow_t const&) {
|
|||
INTERCEPTOR(void *, _ZnamRKSt9nothrow_t, size_t size, std::nothrow_t const&) {
|
||||
OPERATOR_NEW_BODY(FROM_NEW_BR, true /*nothrow*/);
|
||||
}
|
||||
#endif // !SANITIZER_MAC
|
||||
#endif // !SANITIZER_APPLE
|
||||
|
||||
#define OPERATOR_DELETE_BODY(type) \
|
||||
GET_STACK_TRACE_FREE; \
|
||||
|
@ -146,7 +146,7 @@ INTERCEPTOR(void *, _ZnamRKSt9nothrow_t, size_t size, std::nothrow_t const&) {
|
|||
GET_STACK_TRACE_FREE; \
|
||||
asan_delete(ptr, size, static_cast<uptr>(align), &stack, type);
|
||||
|
||||
#if !SANITIZER_MAC
|
||||
#if !SANITIZER_APPLE
|
||||
CXX_OPERATOR_ATTRIBUTE
|
||||
void operator delete(void *ptr) NOEXCEPT
|
||||
{ OPERATOR_DELETE_BODY(FROM_NEW); }
|
||||
|
@ -184,7 +184,7 @@ CXX_OPERATOR_ATTRIBUTE
|
|||
void operator delete[](void *ptr, size_t size, std::align_val_t align) NOEXCEPT
|
||||
{ OPERATOR_DELETE_BODY_SIZE_ALIGN(FROM_NEW_BR); }
|
||||
|
||||
#else // SANITIZER_MAC
|
||||
#else // SANITIZER_APPLE
|
||||
INTERCEPTOR(void, _ZdlPv, void *ptr)
|
||||
{ OPERATOR_DELETE_BODY(FROM_NEW); }
|
||||
INTERCEPTOR(void, _ZdaPv, void *ptr)
|
||||
|
@ -193,4 +193,4 @@ INTERCEPTOR(void, _ZdlPvRKSt9nothrow_t, void *ptr, std::nothrow_t const&)
|
|||
{ OPERATOR_DELETE_BODY(FROM_NEW); }
|
||||
INTERCEPTOR(void, _ZdaPvRKSt9nothrow_t, void *ptr, std::nothrow_t const&)
|
||||
{ OPERATOR_DELETE_BODY(FROM_NEW_BR); }
|
||||
#endif // !SANITIZER_MAC
|
||||
#endif // !SANITIZER_APPLE
|
||||
|
|
|
@ -12,11 +12,13 @@
|
|||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "asan_poisoning.h"
|
||||
|
||||
#include "asan_report.h"
|
||||
#include "asan_stack.h"
|
||||
#include "sanitizer_common/sanitizer_atomic.h"
|
||||
#include "sanitizer_common/sanitizer_libc.h"
|
||||
#include "sanitizer_common/sanitizer_flags.h"
|
||||
#include "sanitizer_common/sanitizer_interface_internal.h"
|
||||
#include "sanitizer_common/sanitizer_libc.h"
|
||||
|
||||
namespace __asan {
|
||||
|
||||
|
@ -35,7 +37,7 @@ void PoisonShadow(uptr addr, uptr size, u8 value) {
|
|||
CHECK(AddrIsAlignedByGranularity(addr));
|
||||
CHECK(AddrIsInMem(addr));
|
||||
CHECK(AddrIsAlignedByGranularity(addr + size));
|
||||
CHECK(AddrIsInMem(addr + size - SHADOW_GRANULARITY));
|
||||
CHECK(AddrIsInMem(addr + size - ASAN_SHADOW_GRANULARITY));
|
||||
CHECK(REAL(memset));
|
||||
FastPoisonShadow(addr, size, value);
|
||||
}
|
||||
|
@ -52,12 +54,12 @@ void PoisonShadowPartialRightRedzone(uptr addr,
|
|||
|
||||
struct ShadowSegmentEndpoint {
|
||||
u8 *chunk;
|
||||
s8 offset; // in [0, SHADOW_GRANULARITY)
|
||||
s8 offset; // in [0, ASAN_SHADOW_GRANULARITY)
|
||||
s8 value; // = *chunk;
|
||||
|
||||
explicit ShadowSegmentEndpoint(uptr address) {
|
||||
chunk = (u8*)MemToShadow(address);
|
||||
offset = address & (SHADOW_GRANULARITY - 1);
|
||||
offset = address & (ASAN_SHADOW_GRANULARITY - 1);
|
||||
value = *chunk;
|
||||
}
|
||||
};
|
||||
|
@ -66,20 +68,20 @@ void AsanPoisonOrUnpoisonIntraObjectRedzone(uptr ptr, uptr size, bool poison) {
|
|||
uptr end = ptr + size;
|
||||
if (Verbosity()) {
|
||||
Printf("__asan_%spoison_intra_object_redzone [%p,%p) %zd\n",
|
||||
poison ? "" : "un", ptr, end, size);
|
||||
poison ? "" : "un", (void *)ptr, (void *)end, size);
|
||||
if (Verbosity() >= 2)
|
||||
PRINT_CURRENT_STACK();
|
||||
}
|
||||
CHECK(size);
|
||||
CHECK_LE(size, 4096);
|
||||
CHECK(IsAligned(end, SHADOW_GRANULARITY));
|
||||
if (!IsAligned(ptr, SHADOW_GRANULARITY)) {
|
||||
CHECK(IsAligned(end, ASAN_SHADOW_GRANULARITY));
|
||||
if (!IsAligned(ptr, ASAN_SHADOW_GRANULARITY)) {
|
||||
*(u8 *)MemToShadow(ptr) =
|
||||
poison ? static_cast<u8>(ptr % SHADOW_GRANULARITY) : 0;
|
||||
ptr |= SHADOW_GRANULARITY - 1;
|
||||
poison ? static_cast<u8>(ptr % ASAN_SHADOW_GRANULARITY) : 0;
|
||||
ptr |= ASAN_SHADOW_GRANULARITY - 1;
|
||||
ptr++;
|
||||
}
|
||||
for (; ptr < end; ptr += SHADOW_GRANULARITY)
|
||||
for (; ptr < end; ptr += ASAN_SHADOW_GRANULARITY)
|
||||
*(u8*)MemToShadow(ptr) = poison ? kAsanIntraObjectRedzone : 0;
|
||||
}
|
||||
|
||||
|
@ -181,12 +183,12 @@ uptr __asan_region_is_poisoned(uptr beg, uptr size) {
|
|||
if (!AddrIsInMem(end))
|
||||
return end;
|
||||
CHECK_LT(beg, end);
|
||||
uptr aligned_b = RoundUpTo(beg, SHADOW_GRANULARITY);
|
||||
uptr aligned_e = RoundDownTo(end, SHADOW_GRANULARITY);
|
||||
uptr aligned_b = RoundUpTo(beg, ASAN_SHADOW_GRANULARITY);
|
||||
uptr aligned_e = RoundDownTo(end, ASAN_SHADOW_GRANULARITY);
|
||||
uptr shadow_beg = MemToShadow(aligned_b);
|
||||
uptr shadow_end = MemToShadow(aligned_e);
|
||||
// First check the first and the last application bytes,
|
||||
// then check the SHADOW_GRANULARITY-aligned region by calling
|
||||
// then check the ASAN_SHADOW_GRANULARITY-aligned region by calling
|
||||
// mem_is_zero on the corresponding shadow.
|
||||
if (!__asan::AddressIsPoisoned(beg) && !__asan::AddressIsPoisoned(end - 1) &&
|
||||
(shadow_end <= shadow_beg ||
|
||||
|
@ -285,7 +287,7 @@ uptr __asan_load_cxx_array_cookie(uptr *p) {
|
|||
// assumes that left border of region to be poisoned is properly aligned.
|
||||
static void PoisonAlignedStackMemory(uptr addr, uptr size, bool do_poison) {
|
||||
if (size == 0) return;
|
||||
uptr aligned_size = size & ~(SHADOW_GRANULARITY - 1);
|
||||
uptr aligned_size = size & ~(ASAN_SHADOW_GRANULARITY - 1);
|
||||
PoisonShadow(addr, aligned_size,
|
||||
do_poison ? kAsanStackUseAfterScopeMagic : 0);
|
||||
if (size == aligned_size)
|
||||
|
@ -310,6 +312,34 @@ void __asan_set_shadow_00(uptr addr, uptr size) {
|
|||
REAL(memset)((void *)addr, 0, size);
|
||||
}
|
||||
|
||||
void __asan_set_shadow_01(uptr addr, uptr size) {
|
||||
REAL(memset)((void *)addr, 0x01, size);
|
||||
}
|
||||
|
||||
void __asan_set_shadow_02(uptr addr, uptr size) {
|
||||
REAL(memset)((void *)addr, 0x02, size);
|
||||
}
|
||||
|
||||
void __asan_set_shadow_03(uptr addr, uptr size) {
|
||||
REAL(memset)((void *)addr, 0x03, size);
|
||||
}
|
||||
|
||||
void __asan_set_shadow_04(uptr addr, uptr size) {
|
||||
REAL(memset)((void *)addr, 0x04, size);
|
||||
}
|
||||
|
||||
void __asan_set_shadow_05(uptr addr, uptr size) {
|
||||
REAL(memset)((void *)addr, 0x05, size);
|
||||
}
|
||||
|
||||
void __asan_set_shadow_06(uptr addr, uptr size) {
|
||||
REAL(memset)((void *)addr, 0x06, size);
|
||||
}
|
||||
|
||||
void __asan_set_shadow_07(uptr addr, uptr size) {
|
||||
REAL(memset)((void *)addr, 0x07, size);
|
||||
}
|
||||
|
||||
void __asan_set_shadow_f1(uptr addr, uptr size) {
|
||||
REAL(memset)((void *)addr, 0xf1, size);
|
||||
}
|
||||
|
@ -340,30 +370,77 @@ void __asan_unpoison_stack_memory(uptr addr, uptr size) {
|
|||
PoisonAlignedStackMemory(addr, size, false);
|
||||
}
|
||||
|
||||
static void FixUnalignedStorage(uptr storage_beg, uptr storage_end,
|
||||
uptr &old_beg, uptr &old_end, uptr &new_beg,
|
||||
uptr &new_end) {
|
||||
constexpr uptr granularity = ASAN_SHADOW_GRANULARITY;
|
||||
if (UNLIKELY(!AddrIsAlignedByGranularity(storage_end))) {
|
||||
uptr end_down = RoundDownTo(storage_end, granularity);
|
||||
// Ignore the last unaligned granule if the storage is followed by
|
||||
// unpoisoned byte, because we can't poison the prefix anyway. Don't call
|
||||
// AddressIsPoisoned at all if container changes does not affect the last
|
||||
// granule at all.
|
||||
if ((((old_end != new_end) && Max(old_end, new_end) > end_down) ||
|
||||
((old_beg != new_beg) && Max(old_beg, new_beg) > end_down)) &&
|
||||
!AddressIsPoisoned(storage_end)) {
|
||||
old_beg = Min(end_down, old_beg);
|
||||
old_end = Min(end_down, old_end);
|
||||
new_beg = Min(end_down, new_beg);
|
||||
new_end = Min(end_down, new_end);
|
||||
}
|
||||
}
|
||||
|
||||
// Handle misaligned begin and cut it off.
|
||||
if (UNLIKELY(!AddrIsAlignedByGranularity(storage_beg))) {
|
||||
uptr beg_up = RoundUpTo(storage_beg, granularity);
|
||||
// The first unaligned granule needs special handling only if we had bytes
|
||||
// there before and will have none after.
|
||||
if ((new_beg == new_end || new_beg >= beg_up) && old_beg != old_end &&
|
||||
old_beg < beg_up) {
|
||||
// Keep granule prefix outside of the storage unpoisoned.
|
||||
uptr beg_down = RoundDownTo(storage_beg, granularity);
|
||||
*(u8 *)MemToShadow(beg_down) = storage_beg - beg_down;
|
||||
old_beg = Max(beg_up, old_beg);
|
||||
old_end = Max(beg_up, old_end);
|
||||
new_beg = Max(beg_up, new_beg);
|
||||
new_end = Max(beg_up, new_end);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void __sanitizer_annotate_contiguous_container(const void *beg_p,
|
||||
const void *end_p,
|
||||
const void *old_mid_p,
|
||||
const void *new_mid_p) {
|
||||
if (!flags()->detect_container_overflow) return;
|
||||
if (!flags()->detect_container_overflow)
|
||||
return;
|
||||
VPrintf(2, "contiguous_container: %p %p %p %p\n", beg_p, end_p, old_mid_p,
|
||||
new_mid_p);
|
||||
uptr beg = reinterpret_cast<uptr>(beg_p);
|
||||
uptr end = reinterpret_cast<uptr>(end_p);
|
||||
uptr old_mid = reinterpret_cast<uptr>(old_mid_p);
|
||||
uptr new_mid = reinterpret_cast<uptr>(new_mid_p);
|
||||
uptr granularity = SHADOW_GRANULARITY;
|
||||
if (!(beg <= old_mid && beg <= new_mid && old_mid <= end && new_mid <= end &&
|
||||
IsAligned(beg, granularity))) {
|
||||
uptr storage_beg = reinterpret_cast<uptr>(beg_p);
|
||||
uptr storage_end = reinterpret_cast<uptr>(end_p);
|
||||
uptr old_end = reinterpret_cast<uptr>(old_mid_p);
|
||||
uptr new_end = reinterpret_cast<uptr>(new_mid_p);
|
||||
uptr old_beg = storage_beg;
|
||||
uptr new_beg = storage_beg;
|
||||
uptr granularity = ASAN_SHADOW_GRANULARITY;
|
||||
if (!(storage_beg <= old_end && storage_beg <= new_end &&
|
||||
old_end <= storage_end && new_end <= storage_end)) {
|
||||
GET_STACK_TRACE_FATAL_HERE;
|
||||
ReportBadParamsToAnnotateContiguousContainer(beg, end, old_mid, new_mid,
|
||||
&stack);
|
||||
ReportBadParamsToAnnotateContiguousContainer(storage_beg, storage_end,
|
||||
old_end, new_end, &stack);
|
||||
}
|
||||
CHECK_LE(end - beg,
|
||||
FIRST_32_SECOND_64(1UL << 30, 1ULL << 40)); // Sanity check.
|
||||
CHECK_LE(storage_end - storage_beg,
|
||||
FIRST_32_SECOND_64(1UL << 30, 1ULL << 40)); // Sanity check.
|
||||
|
||||
uptr a = RoundDownTo(Min(old_mid, new_mid), granularity);
|
||||
uptr c = RoundUpTo(Max(old_mid, new_mid), granularity);
|
||||
uptr d1 = RoundDownTo(old_mid, granularity);
|
||||
if (old_end == new_end)
|
||||
return; // Nothing to do here.
|
||||
|
||||
FixUnalignedStorage(storage_beg, storage_end, old_beg, old_end, new_beg,
|
||||
new_end);
|
||||
|
||||
uptr a = RoundDownTo(Min(old_end, new_end), granularity);
|
||||
uptr c = RoundUpTo(Max(old_end, new_end), granularity);
|
||||
uptr d1 = RoundDownTo(old_end, granularity);
|
||||
// uptr d2 = RoundUpTo(old_mid, granularity);
|
||||
// Currently we should be in this state:
|
||||
// [a, d1) is good, [d2, c) is bad, [d1, d2) is partially good.
|
||||
|
@ -374,54 +451,171 @@ void __sanitizer_annotate_contiguous_container(const void *beg_p,
|
|||
// if (d1 != d2)
|
||||
// CHECK_EQ(*(u8*)MemToShadow(d1), old_mid - d1);
|
||||
if (a + granularity <= d1)
|
||||
CHECK_EQ(*(u8*)MemToShadow(a), 0);
|
||||
CHECK_EQ(*(u8 *)MemToShadow(a), 0);
|
||||
// if (d2 + granularity <= c && c <= end)
|
||||
// CHECK_EQ(*(u8 *)MemToShadow(c - granularity),
|
||||
// kAsanContiguousContainerOOBMagic);
|
||||
|
||||
uptr b1 = RoundDownTo(new_mid, granularity);
|
||||
uptr b2 = RoundUpTo(new_mid, granularity);
|
||||
uptr b1 = RoundDownTo(new_end, granularity);
|
||||
uptr b2 = RoundUpTo(new_end, granularity);
|
||||
// New state:
|
||||
// [a, b1) is good, [b2, c) is bad, [b1, b2) is partially good.
|
||||
PoisonShadow(a, b1 - a, 0);
|
||||
PoisonShadow(b2, c - b2, kAsanContiguousContainerOOBMagic);
|
||||
if (b1 > a)
|
||||
PoisonShadow(a, b1 - a, 0);
|
||||
else if (c > b2)
|
||||
PoisonShadow(b2, c - b2, kAsanContiguousContainerOOBMagic);
|
||||
if (b1 != b2) {
|
||||
CHECK_EQ(b2 - b1, granularity);
|
||||
*(u8*)MemToShadow(b1) = static_cast<u8>(new_mid - b1);
|
||||
*(u8 *)MemToShadow(b1) = static_cast<u8>(new_end - b1);
|
||||
}
|
||||
}
|
||||
|
||||
// Annotates a double ended contiguous memory area like std::deque's chunk.
|
||||
// It allows detecting buggy accesses to allocated but not used begining
|
||||
// or end items of such a container.
|
||||
void __sanitizer_annotate_double_ended_contiguous_container(
|
||||
const void *storage_beg_p, const void *storage_end_p,
|
||||
const void *old_container_beg_p, const void *old_container_end_p,
|
||||
const void *new_container_beg_p, const void *new_container_end_p) {
|
||||
if (!flags()->detect_container_overflow)
|
||||
return;
|
||||
|
||||
VPrintf(2, "contiguous_container: %p %p %p %p %p %p\n", storage_beg_p,
|
||||
storage_end_p, old_container_beg_p, old_container_end_p,
|
||||
new_container_beg_p, new_container_end_p);
|
||||
|
||||
uptr storage_beg = reinterpret_cast<uptr>(storage_beg_p);
|
||||
uptr storage_end = reinterpret_cast<uptr>(storage_end_p);
|
||||
uptr old_beg = reinterpret_cast<uptr>(old_container_beg_p);
|
||||
uptr old_end = reinterpret_cast<uptr>(old_container_end_p);
|
||||
uptr new_beg = reinterpret_cast<uptr>(new_container_beg_p);
|
||||
uptr new_end = reinterpret_cast<uptr>(new_container_end_p);
|
||||
|
||||
constexpr uptr granularity = ASAN_SHADOW_GRANULARITY;
|
||||
|
||||
if (!(old_beg <= old_end && new_beg <= new_end) ||
|
||||
!(storage_beg <= new_beg && new_end <= storage_end) ||
|
||||
!(storage_beg <= old_beg && old_end <= storage_end)) {
|
||||
GET_STACK_TRACE_FATAL_HERE;
|
||||
ReportBadParamsToAnnotateDoubleEndedContiguousContainer(
|
||||
storage_beg, storage_end, old_beg, old_end, new_beg, new_end, &stack);
|
||||
}
|
||||
CHECK_LE(storage_end - storage_beg,
|
||||
FIRST_32_SECOND_64(1UL << 30, 1ULL << 40)); // Sanity check.
|
||||
|
||||
if ((old_beg == old_end && new_beg == new_end) ||
|
||||
(old_beg == new_beg && old_end == new_end))
|
||||
return; // Nothing to do here.
|
||||
|
||||
FixUnalignedStorage(storage_beg, storage_end, old_beg, old_end, new_beg,
|
||||
new_end);
|
||||
|
||||
// Handle non-intersecting new/old containers separately have simpler
|
||||
// intersecting case.
|
||||
if (old_beg == old_end || new_beg == new_end || new_end <= old_beg ||
|
||||
old_end <= new_beg) {
|
||||
if (old_beg != old_end) {
|
||||
// Poisoning the old container.
|
||||
uptr a = RoundDownTo(old_beg, granularity);
|
||||
uptr b = RoundUpTo(old_end, granularity);
|
||||
PoisonShadow(a, b - a, kAsanContiguousContainerOOBMagic);
|
||||
}
|
||||
|
||||
if (new_beg != new_end) {
|
||||
// Unpoisoning the new container.
|
||||
uptr a = RoundDownTo(new_beg, granularity);
|
||||
uptr b = RoundDownTo(new_end, granularity);
|
||||
PoisonShadow(a, b - a, 0);
|
||||
if (!AddrIsAlignedByGranularity(new_end))
|
||||
*(u8 *)MemToShadow(b) = static_cast<u8>(new_end - b);
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
// Intersection of old and new containers is not empty.
|
||||
CHECK_LT(new_beg, old_end);
|
||||
CHECK_GT(new_end, old_beg);
|
||||
|
||||
if (new_beg < old_beg) {
|
||||
// Round down because we can't poison prefixes.
|
||||
uptr a = RoundDownTo(new_beg, granularity);
|
||||
// Round down and ignore the [c, old_beg) as its state defined by unchanged
|
||||
// [old_beg, old_end).
|
||||
uptr c = RoundDownTo(old_beg, granularity);
|
||||
PoisonShadow(a, c - a, 0);
|
||||
} else if (new_beg > old_beg) {
|
||||
// Round down and poison [a, old_beg) because it was unpoisoned only as a
|
||||
// prefix.
|
||||
uptr a = RoundDownTo(old_beg, granularity);
|
||||
// Round down and ignore the [c, new_beg) as its state defined by unchanged
|
||||
// [new_beg, old_end).
|
||||
uptr c = RoundDownTo(new_beg, granularity);
|
||||
|
||||
PoisonShadow(a, c - a, kAsanContiguousContainerOOBMagic);
|
||||
}
|
||||
|
||||
if (new_end > old_end) {
|
||||
// Round down to poison the prefix.
|
||||
uptr a = RoundDownTo(old_end, granularity);
|
||||
// Round down and handle remainder below.
|
||||
uptr c = RoundDownTo(new_end, granularity);
|
||||
PoisonShadow(a, c - a, 0);
|
||||
if (!AddrIsAlignedByGranularity(new_end))
|
||||
*(u8 *)MemToShadow(c) = static_cast<u8>(new_end - c);
|
||||
} else if (new_end < old_end) {
|
||||
// Round up and handle remained below.
|
||||
uptr a2 = RoundUpTo(new_end, granularity);
|
||||
// Round up to poison entire granule as we had nothing in [old_end, c2).
|
||||
uptr c2 = RoundUpTo(old_end, granularity);
|
||||
PoisonShadow(a2, c2 - a2, kAsanContiguousContainerOOBMagic);
|
||||
|
||||
if (!AddrIsAlignedByGranularity(new_end)) {
|
||||
uptr a = RoundDownTo(new_end, granularity);
|
||||
*(u8 *)MemToShadow(a) = static_cast<u8>(new_end - a);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static const void *FindBadAddress(uptr begin, uptr end, bool poisoned) {
|
||||
CHECK_LE(begin, end);
|
||||
constexpr uptr kMaxRangeToCheck = 32;
|
||||
if (end - begin > kMaxRangeToCheck * 2) {
|
||||
if (auto *bad = FindBadAddress(begin, begin + kMaxRangeToCheck, poisoned))
|
||||
return bad;
|
||||
if (auto *bad = FindBadAddress(end - kMaxRangeToCheck, end, poisoned))
|
||||
return bad;
|
||||
}
|
||||
|
||||
for (uptr i = begin; i < end; ++i)
|
||||
if (AddressIsPoisoned(i) != poisoned)
|
||||
return reinterpret_cast<const void *>(i);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
const void *__sanitizer_contiguous_container_find_bad_address(
|
||||
const void *beg_p, const void *mid_p, const void *end_p) {
|
||||
if (!flags()->detect_container_overflow)
|
||||
return nullptr;
|
||||
uptr granularity = ASAN_SHADOW_GRANULARITY;
|
||||
uptr beg = reinterpret_cast<uptr>(beg_p);
|
||||
uptr end = reinterpret_cast<uptr>(end_p);
|
||||
uptr mid = reinterpret_cast<uptr>(mid_p);
|
||||
CHECK_LE(beg, mid);
|
||||
CHECK_LE(mid, end);
|
||||
// Check some bytes starting from beg, some bytes around mid, and some bytes
|
||||
// ending with end.
|
||||
uptr kMaxRangeToCheck = 32;
|
||||
uptr r1_beg = beg;
|
||||
uptr r1_end = Min(beg + kMaxRangeToCheck, mid);
|
||||
uptr r2_beg = Max(beg, mid - kMaxRangeToCheck);
|
||||
uptr r2_end = Min(end, mid + kMaxRangeToCheck);
|
||||
uptr r3_beg = Max(end - kMaxRangeToCheck, mid);
|
||||
uptr r3_end = end;
|
||||
for (uptr i = r1_beg; i < r1_end; i++)
|
||||
if (AddressIsPoisoned(i))
|
||||
return reinterpret_cast<const void *>(i);
|
||||
for (uptr i = r2_beg; i < mid; i++)
|
||||
if (AddressIsPoisoned(i))
|
||||
return reinterpret_cast<const void *>(i);
|
||||
for (uptr i = mid; i < r2_end; i++)
|
||||
if (!AddressIsPoisoned(i))
|
||||
return reinterpret_cast<const void *>(i);
|
||||
for (uptr i = r3_beg; i < r3_end; i++)
|
||||
if (!AddressIsPoisoned(i))
|
||||
return reinterpret_cast<const void *>(i);
|
||||
return nullptr;
|
||||
// If the byte after the storage is unpoisoned, everything in the granule
|
||||
// before must stay unpoisoned.
|
||||
uptr annotations_end =
|
||||
(!AddrIsAlignedByGranularity(end) && !AddressIsPoisoned(end))
|
||||
? RoundDownTo(end, granularity)
|
||||
: end;
|
||||
beg = Min(beg, annotations_end);
|
||||
mid = Min(mid, annotations_end);
|
||||
if (auto *bad = FindBadAddress(beg, mid, false))
|
||||
return bad;
|
||||
if (auto *bad = FindBadAddress(mid, annotations_end, true))
|
||||
return bad;
|
||||
return FindBadAddress(annotations_end, end, false);
|
||||
}
|
||||
|
||||
int __sanitizer_verify_contiguous_container(const void *beg_p,
|
||||
|
@ -431,6 +625,48 @@ int __sanitizer_verify_contiguous_container(const void *beg_p,
|
|||
end_p) == nullptr;
|
||||
}
|
||||
|
||||
const void *__sanitizer_double_ended_contiguous_container_find_bad_address(
|
||||
const void *storage_beg_p, const void *container_beg_p,
|
||||
const void *container_end_p, const void *storage_end_p) {
|
||||
if (!flags()->detect_container_overflow)
|
||||
return nullptr;
|
||||
uptr granularity = ASAN_SHADOW_GRANULARITY;
|
||||
uptr storage_beg = reinterpret_cast<uptr>(storage_beg_p);
|
||||
uptr storage_end = reinterpret_cast<uptr>(storage_end_p);
|
||||
uptr beg = reinterpret_cast<uptr>(container_beg_p);
|
||||
uptr end = reinterpret_cast<uptr>(container_end_p);
|
||||
|
||||
// The prefix of the firs granule of the container is unpoisoned.
|
||||
if (beg != end)
|
||||
beg = Max(storage_beg, RoundDownTo(beg, granularity));
|
||||
|
||||
// If the byte after the storage is unpoisoned, the prefix of the last granule
|
||||
// is unpoisoned.
|
||||
uptr annotations_end = (!AddrIsAlignedByGranularity(storage_end) &&
|
||||
!AddressIsPoisoned(storage_end))
|
||||
? RoundDownTo(storage_end, granularity)
|
||||
: storage_end;
|
||||
storage_beg = Min(storage_beg, annotations_end);
|
||||
beg = Min(beg, annotations_end);
|
||||
end = Min(end, annotations_end);
|
||||
|
||||
if (auto *bad = FindBadAddress(storage_beg, beg, true))
|
||||
return bad;
|
||||
if (auto *bad = FindBadAddress(beg, end, false))
|
||||
return bad;
|
||||
if (auto *bad = FindBadAddress(end, annotations_end, true))
|
||||
return bad;
|
||||
return FindBadAddress(annotations_end, storage_end, false);
|
||||
}
|
||||
|
||||
int __sanitizer_verify_double_ended_contiguous_container(
|
||||
const void *storage_beg_p, const void *container_beg_p,
|
||||
const void *container_end_p, const void *storage_end_p) {
|
||||
return __sanitizer_double_ended_contiguous_container_find_bad_address(
|
||||
storage_beg_p, container_beg_p, container_end_p, storage_end_p) ==
|
||||
nullptr;
|
||||
}
|
||||
|
||||
extern "C" SANITIZER_INTERFACE_ATTRIBUTE
|
||||
void __asan_poison_intra_object_redzone(uptr ptr, uptr size) {
|
||||
AsanPoisonOrUnpoisonIntraObjectRedzone(ptr, size, true);
|
||||
|
|
|
@ -44,8 +44,8 @@ ALWAYS_INLINE void FastPoisonShadow(uptr aligned_beg, uptr aligned_size,
|
|||
common_flags()->clear_shadow_mmap_threshold);
|
||||
#else
|
||||
uptr shadow_beg = MEM_TO_SHADOW(aligned_beg);
|
||||
uptr shadow_end = MEM_TO_SHADOW(
|
||||
aligned_beg + aligned_size - SHADOW_GRANULARITY) + 1;
|
||||
uptr shadow_end =
|
||||
MEM_TO_SHADOW(aligned_beg + aligned_size - ASAN_SHADOW_GRANULARITY) + 1;
|
||||
// FIXME: Page states are different on Windows, so using the same interface
|
||||
// for mapping shadow and zeroing out pages doesn't "just work", so we should
|
||||
// probably provide higher-level interface for these operations.
|
||||
|
@ -78,11 +78,12 @@ ALWAYS_INLINE void FastPoisonShadowPartialRightRedzone(
|
|||
DCHECK(CanPoisonMemory());
|
||||
bool poison_partial = flags()->poison_partial;
|
||||
u8 *shadow = (u8*)MEM_TO_SHADOW(aligned_addr);
|
||||
for (uptr i = 0; i < redzone_size; i += SHADOW_GRANULARITY, shadow++) {
|
||||
if (i + SHADOW_GRANULARITY <= size) {
|
||||
for (uptr i = 0; i < redzone_size; i += ASAN_SHADOW_GRANULARITY, shadow++) {
|
||||
if (i + ASAN_SHADOW_GRANULARITY <= size) {
|
||||
*shadow = 0; // fully addressable
|
||||
} else if (i >= size) {
|
||||
*shadow = (SHADOW_GRANULARITY == 128) ? 0xff : value; // unaddressable
|
||||
*shadow =
|
||||
(ASAN_SHADOW_GRANULARITY == 128) ? 0xff : value; // unaddressable
|
||||
} else {
|
||||
// first size-i bytes are addressable
|
||||
*shadow = poison_partial ? static_cast<u8>(size - i) : 0;
|
||||
|
|
|
@ -14,22 +14,23 @@
|
|||
#include "sanitizer_common/sanitizer_platform.h"
|
||||
#if SANITIZER_POSIX
|
||||
|
||||
#include "asan_internal.h"
|
||||
#include "asan_interceptors.h"
|
||||
#include "asan_mapping.h"
|
||||
#include "asan_poisoning.h"
|
||||
#include "asan_report.h"
|
||||
#include "asan_stack.h"
|
||||
#include "sanitizer_common/sanitizer_libc.h"
|
||||
#include "sanitizer_common/sanitizer_posix.h"
|
||||
#include "sanitizer_common/sanitizer_procmaps.h"
|
||||
# include <pthread.h>
|
||||
# include <signal.h>
|
||||
# include <stdlib.h>
|
||||
# include <sys/resource.h>
|
||||
# include <sys/time.h>
|
||||
# include <unistd.h>
|
||||
|
||||
#include <pthread.h>
|
||||
#include <signal.h>
|
||||
#include <stdlib.h>
|
||||
#include <sys/time.h>
|
||||
#include <sys/resource.h>
|
||||
#include <unistd.h>
|
||||
# include "asan_interceptors.h"
|
||||
# include "asan_internal.h"
|
||||
# include "asan_mapping.h"
|
||||
# include "asan_poisoning.h"
|
||||
# include "asan_report.h"
|
||||
# include "asan_stack.h"
|
||||
# include "lsan/lsan_common.h"
|
||||
# include "sanitizer_common/sanitizer_libc.h"
|
||||
# include "sanitizer_common/sanitizer_posix.h"
|
||||
# include "sanitizer_common/sanitizer_procmaps.h"
|
||||
|
||||
namespace __asan {
|
||||
|
||||
|
@ -131,7 +132,7 @@ void AsanTSDSet(void *tsd) {
|
|||
}
|
||||
|
||||
void PlatformTSDDtor(void *tsd) {
|
||||
AsanThreadContext *context = (AsanThreadContext*)tsd;
|
||||
AsanThreadContext *context = (AsanThreadContext *)tsd;
|
||||
if (context->destructor_iterations > 1) {
|
||||
context->destructor_iterations--;
|
||||
CHECK_EQ(0, pthread_setspecific(tsd_key, tsd));
|
||||
|
@ -140,6 +141,18 @@ void PlatformTSDDtor(void *tsd) {
|
|||
AsanThread::TSDDtor(tsd);
|
||||
}
|
||||
#endif
|
||||
|
||||
void InstallAtExitCheckLeaks() {
|
||||
if (CAN_SANITIZE_LEAKS) {
|
||||
if (common_flags()->detect_leaks && common_flags()->leak_check_at_exit) {
|
||||
if (flags()->halt_on_error)
|
||||
Atexit(__lsan::DoLeakCheck);
|
||||
else
|
||||
Atexit(__lsan::DoRecoverableLeakCheckVoid);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace __asan
|
||||
|
||||
#endif // SANITIZER_POSIX
|
||||
|
|
|
@ -26,7 +26,7 @@ namespace __asan {
|
|||
// Conservative upper limit.
|
||||
uptr PremapShadowSize() {
|
||||
uptr granularity = GetMmapGranularity();
|
||||
return RoundUpTo(GetMaxVirtualAddress() >> SHADOW_SCALE, granularity);
|
||||
return RoundUpTo(GetMaxVirtualAddress() >> ASAN_SHADOW_SCALE, granularity);
|
||||
}
|
||||
|
||||
// Returns an address aligned to 8 pages, such that one page on the left and
|
||||
|
|
|
@ -11,17 +11,19 @@
|
|||
// This file contains error reporting code.
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "asan_report.h"
|
||||
|
||||
#include "asan_descriptions.h"
|
||||
#include "asan_errors.h"
|
||||
#include "asan_flags.h"
|
||||
#include "asan_descriptions.h"
|
||||
#include "asan_internal.h"
|
||||
#include "asan_mapping.h"
|
||||
#include "asan_report.h"
|
||||
#include "asan_scariness_score.h"
|
||||
#include "asan_stack.h"
|
||||
#include "asan_thread.h"
|
||||
#include "sanitizer_common/sanitizer_common.h"
|
||||
#include "sanitizer_common/sanitizer_flags.h"
|
||||
#include "sanitizer_common/sanitizer_interface_internal.h"
|
||||
#include "sanitizer_common/sanitizer_report_decorator.h"
|
||||
#include "sanitizer_common/sanitizer_stackdepot.h"
|
||||
#include "sanitizer_common/sanitizer_symbolizer.h"
|
||||
|
@ -32,12 +34,12 @@ namespace __asan {
|
|||
static void (*error_report_callback)(const char*);
|
||||
static char *error_message_buffer = nullptr;
|
||||
static uptr error_message_buffer_pos = 0;
|
||||
static BlockingMutex error_message_buf_mutex(LINKER_INITIALIZED);
|
||||
static Mutex error_message_buf_mutex;
|
||||
static const unsigned kAsanBuggyPcPoolSize = 25;
|
||||
static __sanitizer::atomic_uintptr_t AsanBuggyPcPool[kAsanBuggyPcPoolSize];
|
||||
|
||||
void AppendToErrorMessageBuffer(const char *buffer) {
|
||||
BlockingMutexLock l(&error_message_buf_mutex);
|
||||
Lock l(&error_message_buf_mutex);
|
||||
if (!error_message_buffer) {
|
||||
error_message_buffer =
|
||||
(char*)MmapOrDieQuietly(kErrorMessageBufferSize, __func__);
|
||||
|
@ -67,14 +69,14 @@ static void PrintZoneForPointer(uptr ptr, uptr zone_ptr,
|
|||
const char *zone_name) {
|
||||
if (zone_ptr) {
|
||||
if (zone_name) {
|
||||
Printf("malloc_zone_from_ptr(%p) = %p, which is %s\n",
|
||||
ptr, zone_ptr, zone_name);
|
||||
Printf("malloc_zone_from_ptr(%p) = %p, which is %s\n", (void *)ptr,
|
||||
(void *)zone_ptr, zone_name);
|
||||
} else {
|
||||
Printf("malloc_zone_from_ptr(%p) = %p, which doesn't have a name\n",
|
||||
ptr, zone_ptr);
|
||||
(void *)ptr, (void *)zone_ptr);
|
||||
}
|
||||
} else {
|
||||
Printf("malloc_zone_from_ptr(%p) = 0\n", ptr);
|
||||
Printf("malloc_zone_from_ptr(%p) = 0\n", (void *)ptr);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -155,10 +157,10 @@ class ScopedInErrorReport {
|
|||
DumpProcessMap();
|
||||
|
||||
// Copy the message buffer so that we could start logging without holding a
|
||||
// lock that gets aquired during printing.
|
||||
// lock that gets acquired during printing.
|
||||
InternalMmapVector<char> buffer_copy(kErrorMessageBufferSize);
|
||||
{
|
||||
BlockingMutexLock l(&error_message_buf_mutex);
|
||||
Lock l(&error_message_buf_mutex);
|
||||
internal_memcpy(buffer_copy.data(),
|
||||
error_message_buffer, kErrorMessageBufferSize);
|
||||
// Clear error_message_buffer so that if we find other errors
|
||||
|
@ -352,6 +354,18 @@ void ReportBadParamsToAnnotateContiguousContainer(uptr beg, uptr end,
|
|||
in_report.ReportError(error);
|
||||
}
|
||||
|
||||
void ReportBadParamsToAnnotateDoubleEndedContiguousContainer(
|
||||
uptr storage_beg, uptr storage_end, uptr old_container_beg,
|
||||
uptr old_container_end, uptr new_container_beg, uptr new_container_end,
|
||||
BufferedStackTrace *stack) {
|
||||
ScopedInErrorReport in_report;
|
||||
ErrorBadParamsToAnnotateDoubleEndedContiguousContainer error(
|
||||
GetCurrentTidOrInvalid(), stack, storage_beg, storage_end,
|
||||
old_container_beg, old_container_end, new_container_beg,
|
||||
new_container_end);
|
||||
in_report.ReportError(error);
|
||||
}
|
||||
|
||||
void ReportODRViolation(const __asan_global *g1, u32 stack_id1,
|
||||
const __asan_global *g2, u32 stack_id2) {
|
||||
ScopedInErrorReport in_report;
|
||||
|
@ -435,9 +449,10 @@ static inline void CheckForInvalidPointerPair(void *p1, void *p2) {
|
|||
void ReportMacMzReallocUnknown(uptr addr, uptr zone_ptr, const char *zone_name,
|
||||
BufferedStackTrace *stack) {
|
||||
ScopedInErrorReport in_report;
|
||||
Printf("mz_realloc(%p) -- attempting to realloc unallocated memory.\n"
|
||||
"This is an unrecoverable problem, exiting now.\n",
|
||||
addr);
|
||||
Printf(
|
||||
"mz_realloc(%p) -- attempting to realloc unallocated memory.\n"
|
||||
"This is an unrecoverable problem, exiting now.\n",
|
||||
(void *)addr);
|
||||
PrintZoneForPointer(addr, zone_ptr, zone_name);
|
||||
stack->Print();
|
||||
DescribeAddressIfHeap(addr);
|
||||
|
@ -459,6 +474,10 @@ static bool SuppressErrorReport(uptr pc) {
|
|||
|
||||
void ReportGenericError(uptr pc, uptr bp, uptr sp, uptr addr, bool is_write,
|
||||
uptr access_size, u32 exp, bool fatal) {
|
||||
if (__asan_test_only_reported_buggy_pointer) {
|
||||
*__asan_test_only_reported_buggy_pointer = addr;
|
||||
return;
|
||||
}
|
||||
if (!fatal && SuppressErrorReport(pc)) return;
|
||||
ENABLE_FRAME_POINTER;
|
||||
|
||||
|
@ -490,7 +509,7 @@ void __asan_report_error(uptr pc, uptr bp, uptr sp, uptr addr, int is_write,
|
|||
}
|
||||
|
||||
void NOINLINE __asan_set_error_report_callback(void (*callback)(const char*)) {
|
||||
BlockingMutexLock l(&error_message_buf_mutex);
|
||||
Lock l(&error_message_buf_mutex);
|
||||
error_report_callback = callback;
|
||||
}
|
||||
|
||||
|
|
|
@ -83,6 +83,10 @@ void ReportStringFunctionSizeOverflow(uptr offset, uptr size,
|
|||
void ReportBadParamsToAnnotateContiguousContainer(uptr beg, uptr end,
|
||||
uptr old_mid, uptr new_mid,
|
||||
BufferedStackTrace *stack);
|
||||
void ReportBadParamsToAnnotateDoubleEndedContiguousContainer(
|
||||
uptr storage_beg, uptr storage_end, uptr old_container_beg,
|
||||
uptr old_container_end, uptr new_container_beg, uptr new_container_end,
|
||||
BufferedStackTrace *stack);
|
||||
|
||||
void ReportODRViolation(const __asan_global *g1, u32 stack_id1,
|
||||
const __asan_global *g2, u32 stack_id2);
|
||||
|
|
|
@ -27,6 +27,7 @@
|
|||
#include "lsan/lsan_common.h"
|
||||
#include "sanitizer_common/sanitizer_atomic.h"
|
||||
#include "sanitizer_common/sanitizer_flags.h"
|
||||
#include "sanitizer_common/sanitizer_interface_internal.h"
|
||||
#include "sanitizer_common/sanitizer_libc.h"
|
||||
#include "sanitizer_common/sanitizer_symbolizer.h"
|
||||
#include "ubsan/ubsan_init.h"
|
||||
|
@ -44,14 +45,15 @@ static void AsanDie() {
|
|||
static atomic_uint32_t num_calls;
|
||||
if (atomic_fetch_add(&num_calls, 1, memory_order_relaxed) != 0) {
|
||||
// Don't die twice - run a busy loop.
|
||||
while (1) { }
|
||||
while (1) {
|
||||
internal_sched_yield();
|
||||
}
|
||||
}
|
||||
if (common_flags()->print_module_map >= 1)
|
||||
DumpProcessMap();
|
||||
if (flags()->sleep_before_dying) {
|
||||
Report("Sleeping for %d second(s)\n", flags()->sleep_before_dying);
|
||||
SleepForSeconds(flags()->sleep_before_dying);
|
||||
}
|
||||
|
||||
WaitForDebugger(flags()->sleep_before_dying, "before dying");
|
||||
|
||||
if (flags()->unmap_shadow_on_exit) {
|
||||
if (kMidMemBeg) {
|
||||
UnmapOrDie((void*)kLowShadowBeg, kMidMemBeg - kLowShadowBeg);
|
||||
|
@ -71,6 +73,7 @@ static void CheckUnwind() {
|
|||
// -------------------------- Globals --------------------- {{{1
|
||||
int asan_inited;
|
||||
bool asan_init_is_running;
|
||||
bool replace_intrin_cached;
|
||||
|
||||
#if !ASAN_FIXED_MAPPING
|
||||
uptr kHighMemEnd, kMidMemBeg, kMidMemEnd;
|
||||
|
@ -85,12 +88,8 @@ void ShowStatsAndAbort() {
|
|||
NOINLINE
|
||||
static void ReportGenericErrorWrapper(uptr addr, bool is_write, int size,
|
||||
int exp_arg, bool fatal) {
|
||||
if (__asan_test_only_reported_buggy_pointer) {
|
||||
*__asan_test_only_reported_buggy_pointer = addr;
|
||||
} else {
|
||||
GET_CALLER_PC_BP_SP;
|
||||
ReportGenericError(pc, bp, sp, addr, is_write, size, exp_arg, fatal);
|
||||
}
|
||||
GET_CALLER_PC_BP_SP;
|
||||
ReportGenericError(pc, bp, sp, addr, is_write, size, exp_arg, fatal);
|
||||
}
|
||||
|
||||
// --------------- LowLevelAllocateCallbac ---------- {{{1
|
||||
|
@ -150,11 +149,11 @@ ASAN_REPORT_ERROR_N(store, true)
|
|||
|
||||
#define ASAN_MEMORY_ACCESS_CALLBACK_BODY(type, is_write, size, exp_arg, fatal) \
|
||||
uptr sp = MEM_TO_SHADOW(addr); \
|
||||
uptr s = size <= SHADOW_GRANULARITY ? *reinterpret_cast<u8 *>(sp) \
|
||||
: *reinterpret_cast<u16 *>(sp); \
|
||||
uptr s = size <= ASAN_SHADOW_GRANULARITY ? *reinterpret_cast<u8 *>(sp) \
|
||||
: *reinterpret_cast<u16 *>(sp); \
|
||||
if (UNLIKELY(s)) { \
|
||||
if (UNLIKELY(size >= SHADOW_GRANULARITY || \
|
||||
((s8)((addr & (SHADOW_GRANULARITY - 1)) + size - 1)) >= \
|
||||
if (UNLIKELY(size >= ASAN_SHADOW_GRANULARITY || \
|
||||
((s8)((addr & (ASAN_SHADOW_GRANULARITY - 1)) + size - 1)) >= \
|
||||
(s8)s)) { \
|
||||
ReportGenericErrorWrapper(addr, is_write, size, exp_arg, fatal); \
|
||||
} \
|
||||
|
@ -188,7 +187,7 @@ ASAN_MEMORY_ACCESS_CALLBACK(store, true, 16)
|
|||
extern "C"
|
||||
NOINLINE INTERFACE_ATTRIBUTE
|
||||
void __asan_loadN(uptr addr, uptr size) {
|
||||
if (__asan_region_is_poisoned(addr, size)) {
|
||||
if ((addr = __asan_region_is_poisoned(addr, size))) {
|
||||
GET_CALLER_PC_BP_SP;
|
||||
ReportGenericError(pc, bp, sp, addr, false, size, 0, true);
|
||||
}
|
||||
|
@ -197,7 +196,7 @@ void __asan_loadN(uptr addr, uptr size) {
|
|||
extern "C"
|
||||
NOINLINE INTERFACE_ATTRIBUTE
|
||||
void __asan_exp_loadN(uptr addr, uptr size, u32 exp) {
|
||||
if (__asan_region_is_poisoned(addr, size)) {
|
||||
if ((addr = __asan_region_is_poisoned(addr, size))) {
|
||||
GET_CALLER_PC_BP_SP;
|
||||
ReportGenericError(pc, bp, sp, addr, false, size, exp, true);
|
||||
}
|
||||
|
@ -206,7 +205,7 @@ void __asan_exp_loadN(uptr addr, uptr size, u32 exp) {
|
|||
extern "C"
|
||||
NOINLINE INTERFACE_ATTRIBUTE
|
||||
void __asan_loadN_noabort(uptr addr, uptr size) {
|
||||
if (__asan_region_is_poisoned(addr, size)) {
|
||||
if ((addr = __asan_region_is_poisoned(addr, size))) {
|
||||
GET_CALLER_PC_BP_SP;
|
||||
ReportGenericError(pc, bp, sp, addr, false, size, 0, false);
|
||||
}
|
||||
|
@ -215,7 +214,7 @@ void __asan_loadN_noabort(uptr addr, uptr size) {
|
|||
extern "C"
|
||||
NOINLINE INTERFACE_ATTRIBUTE
|
||||
void __asan_storeN(uptr addr, uptr size) {
|
||||
if (__asan_region_is_poisoned(addr, size)) {
|
||||
if ((addr = __asan_region_is_poisoned(addr, size))) {
|
||||
GET_CALLER_PC_BP_SP;
|
||||
ReportGenericError(pc, bp, sp, addr, true, size, 0, true);
|
||||
}
|
||||
|
@ -224,7 +223,7 @@ void __asan_storeN(uptr addr, uptr size) {
|
|||
extern "C"
|
||||
NOINLINE INTERFACE_ATTRIBUTE
|
||||
void __asan_exp_storeN(uptr addr, uptr size, u32 exp) {
|
||||
if (__asan_region_is_poisoned(addr, size)) {
|
||||
if ((addr = __asan_region_is_poisoned(addr, size))) {
|
||||
GET_CALLER_PC_BP_SP;
|
||||
ReportGenericError(pc, bp, sp, addr, true, size, exp, true);
|
||||
}
|
||||
|
@ -233,7 +232,7 @@ void __asan_exp_storeN(uptr addr, uptr size, u32 exp) {
|
|||
extern "C"
|
||||
NOINLINE INTERFACE_ATTRIBUTE
|
||||
void __asan_storeN_noabort(uptr addr, uptr size) {
|
||||
if (__asan_region_is_poisoned(addr, size)) {
|
||||
if ((addr = __asan_region_is_poisoned(addr, size))) {
|
||||
GET_CALLER_PC_BP_SP;
|
||||
ReportGenericError(pc, bp, sp, addr, true, size, 0, false);
|
||||
}
|
||||
|
@ -289,11 +288,18 @@ static NOINLINE void force_interface_symbols() {
|
|||
case 38: __asan_region_is_poisoned(0, 0); break;
|
||||
case 39: __asan_describe_address(0); break;
|
||||
case 40: __asan_set_shadow_00(0, 0); break;
|
||||
case 41: __asan_set_shadow_f1(0, 0); break;
|
||||
case 42: __asan_set_shadow_f2(0, 0); break;
|
||||
case 43: __asan_set_shadow_f3(0, 0); break;
|
||||
case 44: __asan_set_shadow_f5(0, 0); break;
|
||||
case 45: __asan_set_shadow_f8(0, 0); break;
|
||||
case 41: __asan_set_shadow_01(0, 0); break;
|
||||
case 42: __asan_set_shadow_02(0, 0); break;
|
||||
case 43: __asan_set_shadow_03(0, 0); break;
|
||||
case 44: __asan_set_shadow_04(0, 0); break;
|
||||
case 45: __asan_set_shadow_05(0, 0); break;
|
||||
case 46: __asan_set_shadow_06(0, 0); break;
|
||||
case 47: __asan_set_shadow_07(0, 0); break;
|
||||
case 48: __asan_set_shadow_f1(0, 0); break;
|
||||
case 49: __asan_set_shadow_f2(0, 0); break;
|
||||
case 50: __asan_set_shadow_f3(0, 0); break;
|
||||
case 51: __asan_set_shadow_f5(0, 0); break;
|
||||
case 52: __asan_set_shadow_f8(0, 0); break;
|
||||
}
|
||||
// clang-format on
|
||||
}
|
||||
|
@ -313,7 +319,7 @@ static void InitializeHighMemEnd() {
|
|||
kHighMemEnd = GetMaxUserVirtualAddress();
|
||||
// Increase kHighMemEnd to make sure it's properly
|
||||
// aligned together with kHighMemBeg:
|
||||
kHighMemEnd |= (GetMmapGranularity() << SHADOW_SCALE) - 1;
|
||||
kHighMemEnd |= (GetMmapGranularity() << ASAN_SHADOW_SCALE) - 1;
|
||||
#endif // !ASAN_FIXED_MAPPING
|
||||
CHECK_EQ((kHighMemBeg % GetMmapGranularity()), 0);
|
||||
}
|
||||
|
@ -365,29 +371,16 @@ void PrintAddressSpaceLayout() {
|
|||
Printf("malloc_context_size=%zu\n",
|
||||
(uptr)common_flags()->malloc_context_size);
|
||||
|
||||
Printf("SHADOW_SCALE: %d\n", (int)SHADOW_SCALE);
|
||||
Printf("SHADOW_GRANULARITY: %d\n", (int)SHADOW_GRANULARITY);
|
||||
Printf("SHADOW_OFFSET: 0x%zx\n", (uptr)SHADOW_OFFSET);
|
||||
CHECK(SHADOW_SCALE >= 3 && SHADOW_SCALE <= 7);
|
||||
Printf("SHADOW_SCALE: %d\n", (int)ASAN_SHADOW_SCALE);
|
||||
Printf("SHADOW_GRANULARITY: %d\n", (int)ASAN_SHADOW_GRANULARITY);
|
||||
Printf("SHADOW_OFFSET: 0x%zx\n", (uptr)ASAN_SHADOW_OFFSET);
|
||||
CHECK(ASAN_SHADOW_SCALE >= 3 && ASAN_SHADOW_SCALE <= 7);
|
||||
if (kMidMemBeg)
|
||||
CHECK(kMidShadowBeg > kLowShadowEnd &&
|
||||
kMidMemBeg > kMidShadowEnd &&
|
||||
kHighShadowBeg > kMidMemEnd);
|
||||
}
|
||||
|
||||
#if defined(__thumb__) && defined(__linux__)
|
||||
#define START_BACKGROUND_THREAD_IN_ASAN_INTERNAL
|
||||
#endif
|
||||
|
||||
#ifndef START_BACKGROUND_THREAD_IN_ASAN_INTERNAL
|
||||
static bool UNUSED __local_asan_dyninit = [] {
|
||||
MaybeStartBackgroudThread();
|
||||
SetSoftRssLimitExceededCallback(AsanSoftRssLimitExceededCallback);
|
||||
|
||||
return false;
|
||||
}();
|
||||
#endif
|
||||
|
||||
static void AsanInitInternal() {
|
||||
if (LIKELY(asan_inited)) return;
|
||||
SanitizerToolName = "AddressSanitizer";
|
||||
|
@ -400,6 +393,8 @@ static void AsanInitInternal() {
|
|||
// initialization steps look at flags().
|
||||
InitializeFlags();
|
||||
|
||||
WaitForDebugger(flags()->sleep_before_init, "before init");
|
||||
|
||||
// Stop performing init at this point if we are being loaded via
|
||||
// dlopen() and the platform supports it.
|
||||
if (SANITIZER_SUPPORTS_INIT_FOR_DLOPEN && UNLIKELY(HandleDlopenInit())) {
|
||||
|
@ -434,11 +429,8 @@ static void AsanInitInternal() {
|
|||
|
||||
__sanitizer::InitializePlatformEarly();
|
||||
|
||||
// Re-exec ourselves if we need to set additional env or command line args.
|
||||
MaybeReexec();
|
||||
|
||||
// Setup internal allocator callback.
|
||||
SetLowLevelAllocateMinAlignment(SHADOW_GRANULARITY);
|
||||
SetLowLevelAllocateMinAlignment(ASAN_SHADOW_GRANULARITY);
|
||||
SetLowLevelAllocateCallback(OnLowLevelAllocate);
|
||||
|
||||
InitializeAsanInterceptors();
|
||||
|
@ -462,13 +454,12 @@ static void AsanInitInternal() {
|
|||
allocator_options.SetFrom(flags(), common_flags());
|
||||
InitializeAllocator(allocator_options);
|
||||
|
||||
#ifdef START_BACKGROUND_THREAD_IN_ASAN_INTERNAL
|
||||
MaybeStartBackgroudThread();
|
||||
SetSoftRssLimitExceededCallback(AsanSoftRssLimitExceededCallback);
|
||||
#endif
|
||||
if (SANITIZER_START_BACKGROUND_THREAD_IN_ASAN_INTERNAL)
|
||||
MaybeStartBackgroudThread();
|
||||
|
||||
// On Linux AsanThread::ThreadStart() calls malloc() that's why asan_inited
|
||||
// should be set to 1 prior to initializing the threads.
|
||||
replace_intrin_cached = flags()->replace_intrin;
|
||||
asan_inited = 1;
|
||||
asan_init_is_running = false;
|
||||
|
||||
|
@ -493,12 +484,7 @@ static void AsanInitInternal() {
|
|||
|
||||
if (CAN_SANITIZE_LEAKS) {
|
||||
__lsan::InitCommonLsan();
|
||||
if (common_flags()->detect_leaks && common_flags()->leak_check_at_exit) {
|
||||
if (flags()->halt_on_error)
|
||||
Atexit(__lsan::DoLeakCheck);
|
||||
else
|
||||
Atexit(__lsan::DoRecoverableLeakCheckVoid);
|
||||
}
|
||||
InstallAtExitCheckLeaks();
|
||||
}
|
||||
|
||||
#if CAN_SANITIZE_UB
|
||||
|
@ -518,10 +504,7 @@ static void AsanInitInternal() {
|
|||
|
||||
VReport(1, "AddressSanitizer Init done\n");
|
||||
|
||||
if (flags()->sleep_after_init) {
|
||||
Report("Sleeping for %d second(s)\n", flags()->sleep_after_init);
|
||||
SleepForSeconds(flags()->sleep_after_init);
|
||||
}
|
||||
WaitForDebugger(flags()->sleep_after_init, "after init");
|
||||
}
|
||||
|
||||
// Initialize as requested from some part of ASan runtime library (interceptors,
|
||||
|
@ -557,10 +540,11 @@ void UnpoisonStack(uptr bottom, uptr top, const char *type) {
|
|||
"False positive error reports may follow\n"
|
||||
"For details see "
|
||||
"https://github.com/google/sanitizers/issues/189\n",
|
||||
type, top, bottom, top - bottom, top - bottom);
|
||||
type, (void *)top, (void *)bottom, (void *)(top - bottom),
|
||||
top - bottom);
|
||||
return;
|
||||
}
|
||||
PoisonShadow(bottom, RoundUpTo(top - bottom, SHADOW_GRANULARITY), 0);
|
||||
PoisonShadow(bottom, RoundUpTo(top - bottom, ASAN_SHADOW_GRANULARITY), 0);
|
||||
}
|
||||
|
||||
static void UnpoisonDefaultStack() {
|
||||
|
|
36
gnu/llvm/compiler-rt/lib/asan/asan_rtl_static.cpp
Normal file
36
gnu/llvm/compiler-rt/lib/asan/asan_rtl_static.cpp
Normal file
|
@ -0,0 +1,36 @@
|
|||
//===-- asan_static_rtl.cpp -----------------------------------------------===//
|
||||
//
|
||||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
||||
// See https://llvm.org/LICENSE.txt for license information.
|
||||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// This file is a part of AddressSanitizer, an address sanity checker.
|
||||
//
|
||||
// Main file of the ASan run-time library.
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
// This file is empty for now. Main reason to have it is workaround for Windows
|
||||
// build, which complains because no files are part of the asan_static lib.
|
||||
|
||||
#include "sanitizer_common/sanitizer_common.h"
|
||||
|
||||
#define REPORT_FUNCTION(Name) \
|
||||
extern "C" SANITIZER_WEAK_ATTRIBUTE void Name(__asan::uptr addr); \
|
||||
extern "C" void Name##_asm(uptr addr) { Name(addr); }
|
||||
|
||||
namespace __asan {
|
||||
|
||||
REPORT_FUNCTION(__asan_report_load1)
|
||||
REPORT_FUNCTION(__asan_report_load2)
|
||||
REPORT_FUNCTION(__asan_report_load4)
|
||||
REPORT_FUNCTION(__asan_report_load8)
|
||||
REPORT_FUNCTION(__asan_report_load16)
|
||||
REPORT_FUNCTION(__asan_report_store1)
|
||||
REPORT_FUNCTION(__asan_report_store2)
|
||||
REPORT_FUNCTION(__asan_report_store4)
|
||||
REPORT_FUNCTION(__asan_report_store8)
|
||||
REPORT_FUNCTION(__asan_report_store16)
|
||||
|
||||
} // namespace __asan
|
146
gnu/llvm/compiler-rt/lib/asan/asan_rtl_x86_64.S
Normal file
146
gnu/llvm/compiler-rt/lib/asan/asan_rtl_x86_64.S
Normal file
|
@ -0,0 +1,146 @@
|
|||
#include "asan_mapping.h"
|
||||
#include "sanitizer_common/sanitizer_asm.h"
|
||||
|
||||
#if defined(__x86_64__)
|
||||
#include "sanitizer_common/sanitizer_platform.h"
|
||||
|
||||
.file "asan_rtl_x86_64.S"
|
||||
|
||||
#define NAME(n, reg, op, s, i) n##_##op##_##i##_##s##_##reg
|
||||
|
||||
#define FNAME(reg, op, s, i) NAME(__asan_check, reg, op, s, i)
|
||||
#define RLABEL(reg, op, s, i) NAME(.return, reg, op, s, i)
|
||||
#define CLABEL(reg, op, s, i) NAME(.check, reg, op, s, i)
|
||||
#define FLABEL(reg, op, s, i) NAME(.fail, reg, op, s, i)
|
||||
|
||||
#define BEGINF(reg, op, s, i) \
|
||||
.section .text.FNAME(reg, op, s, i),"ax",@progbits ;\
|
||||
.globl FNAME(reg, op, s, i) ;\
|
||||
.hidden FNAME(reg, op, s, i) ;\
|
||||
ASM_TYPE_FUNCTION(FNAME(reg, op, s, i)) ;\
|
||||
.cfi_startproc ;\
|
||||
FNAME(reg, op, s, i): ;\
|
||||
|
||||
#define ENDF .cfi_endproc ;\
|
||||
|
||||
// Access check functions for 1,2 and 4 byte types, which require extra checks.
|
||||
#define ASAN_MEMORY_ACCESS_INITIAL_CHECK_ADD(reg, op, s) \
|
||||
mov %##reg,%r10 ;\
|
||||
shr $0x3,%r10 ;\
|
||||
movsbl ASAN_SHADOW_OFFSET_CONST(%r10),%r10d ;\
|
||||
test %r10d,%r10d ;\
|
||||
jne CLABEL(reg, op, s, add) ;\
|
||||
RLABEL(reg, op, s, add): ;\
|
||||
retq ;\
|
||||
|
||||
#define ASAN_MEMORY_ACCESS_EXTRA_CHECK_1(reg, op, i) \
|
||||
CLABEL(reg, op, 1, i): ;\
|
||||
push %rcx ;\
|
||||
mov %##reg,%rcx ;\
|
||||
and $0x7,%ecx ;\
|
||||
cmp %r10d,%ecx ;\
|
||||
pop %rcx ;\
|
||||
jl RLABEL(reg, op, 1, i);\
|
||||
mov %##reg,%rdi ;\
|
||||
jmp __asan_report_##op##1_asm ;\
|
||||
|
||||
#define ASAN_MEMORY_ACCESS_EXTRA_CHECK_2(reg, op, i) \
|
||||
CLABEL(reg, op, 2, i): ;\
|
||||
push %rcx ;\
|
||||
mov %##reg,%rcx ;\
|
||||
and $0x7,%ecx ;\
|
||||
add $0x1,%ecx ;\
|
||||
cmp %r10d,%ecx ;\
|
||||
pop %rcx ;\
|
||||
jl RLABEL(reg, op, 2, i);\
|
||||
mov %##reg,%rdi ;\
|
||||
jmp __asan_report_##op##2_asm ;\
|
||||
|
||||
#define ASAN_MEMORY_ACCESS_EXTRA_CHECK_4(reg, op, i) \
|
||||
CLABEL(reg, op, 4, i): ;\
|
||||
push %rcx ;\
|
||||
mov %##reg,%rcx ;\
|
||||
and $0x7,%ecx ;\
|
||||
add $0x3,%ecx ;\
|
||||
cmp %r10d,%ecx ;\
|
||||
pop %rcx ;\
|
||||
jl RLABEL(reg, op, 4, i);\
|
||||
mov %##reg,%rdi ;\
|
||||
jmp __asan_report_##op##4_asm ;\
|
||||
|
||||
#define ASAN_MEMORY_ACCESS_CALLBACK_ADD_1(reg, op) \
|
||||
BEGINF(reg, op, 1, add) ;\
|
||||
ASAN_MEMORY_ACCESS_INITIAL_CHECK_ADD(reg, op, 1) ;\
|
||||
ASAN_MEMORY_ACCESS_EXTRA_CHECK_1(reg, op, add) ;\
|
||||
ENDF
|
||||
|
||||
#define ASAN_MEMORY_ACCESS_CALLBACK_ADD_2(reg, op) \
|
||||
BEGINF(reg, op, 2, add) ;\
|
||||
ASAN_MEMORY_ACCESS_INITIAL_CHECK_ADD(reg, op, 2) ;\
|
||||
ASAN_MEMORY_ACCESS_EXTRA_CHECK_2(reg, op, add) ;\
|
||||
ENDF
|
||||
|
||||
#define ASAN_MEMORY_ACCESS_CALLBACK_ADD_4(reg, op) \
|
||||
BEGINF(reg, op, 4, add) ;\
|
||||
ASAN_MEMORY_ACCESS_INITIAL_CHECK_ADD(reg, op, 4) ;\
|
||||
ASAN_MEMORY_ACCESS_EXTRA_CHECK_4(reg, op, add) ;\
|
||||
ENDF
|
||||
|
||||
// Access check functions for 8 and 16 byte types: no extra checks required.
|
||||
#define ASAN_MEMORY_ACCESS_CHECK_ADD(reg, op, s, c) \
|
||||
mov %##reg,%r10 ;\
|
||||
shr $0x3,%r10 ;\
|
||||
##c $0x0,ASAN_SHADOW_OFFSET_CONST(%r10) ;\
|
||||
jne FLABEL(reg, op, s, add) ;\
|
||||
retq ;\
|
||||
|
||||
#define ASAN_MEMORY_ACCESS_FAIL(reg, op, s, i) \
|
||||
FLABEL(reg, op, s, i): ;\
|
||||
mov %##reg,%rdi ;\
|
||||
jmp __asan_report_##op##s##_asm;\
|
||||
|
||||
#define ASAN_MEMORY_ACCESS_CALLBACK_ADD_8(reg, op) \
|
||||
BEGINF(reg, op, 8, add) ;\
|
||||
ASAN_MEMORY_ACCESS_CHECK_ADD(reg, op, 8, cmpb) ;\
|
||||
ASAN_MEMORY_ACCESS_FAIL(reg, op, 8, add) ;\
|
||||
ENDF
|
||||
|
||||
#define ASAN_MEMORY_ACCESS_CALLBACK_ADD_16(reg, op) \
|
||||
BEGINF(reg, op, 16, add) ;\
|
||||
ASAN_MEMORY_ACCESS_CHECK_ADD(reg, op, 16, cmpw) ;\
|
||||
ASAN_MEMORY_ACCESS_FAIL(reg, op, 16, add) ;\
|
||||
ENDF
|
||||
|
||||
#define ASAN_MEMORY_ACCESS_CALLBACKS_ADD(reg) \
|
||||
ASAN_MEMORY_ACCESS_CALLBACK_ADD_1(reg, load) \
|
||||
ASAN_MEMORY_ACCESS_CALLBACK_ADD_1(reg, store) \
|
||||
ASAN_MEMORY_ACCESS_CALLBACK_ADD_2(reg, load) \
|
||||
ASAN_MEMORY_ACCESS_CALLBACK_ADD_2(reg, store) \
|
||||
ASAN_MEMORY_ACCESS_CALLBACK_ADD_4(reg, load) \
|
||||
ASAN_MEMORY_ACCESS_CALLBACK_ADD_4(reg, store) \
|
||||
ASAN_MEMORY_ACCESS_CALLBACK_ADD_8(reg, load) \
|
||||
ASAN_MEMORY_ACCESS_CALLBACK_ADD_8(reg, store) \
|
||||
ASAN_MEMORY_ACCESS_CALLBACK_ADD_16(reg, load) \
|
||||
ASAN_MEMORY_ACCESS_CALLBACK_ADD_16(reg, store) \
|
||||
|
||||
|
||||
// Instantiate all but R10 and R11 callbacks. We are using PLTSafe class with
|
||||
// the intrinsic, which guarantees that the code generation will never emit
|
||||
// R10 or R11 callback.
|
||||
ASAN_MEMORY_ACCESS_CALLBACKS_ADD(RAX)
|
||||
ASAN_MEMORY_ACCESS_CALLBACKS_ADD(RBX)
|
||||
ASAN_MEMORY_ACCESS_CALLBACKS_ADD(RCX)
|
||||
ASAN_MEMORY_ACCESS_CALLBACKS_ADD(RDX)
|
||||
ASAN_MEMORY_ACCESS_CALLBACKS_ADD(RSI)
|
||||
ASAN_MEMORY_ACCESS_CALLBACKS_ADD(RDI)
|
||||
ASAN_MEMORY_ACCESS_CALLBACKS_ADD(RBP)
|
||||
ASAN_MEMORY_ACCESS_CALLBACKS_ADD(R8)
|
||||
ASAN_MEMORY_ACCESS_CALLBACKS_ADD(R9)
|
||||
ASAN_MEMORY_ACCESS_CALLBACKS_ADD(R12)
|
||||
ASAN_MEMORY_ACCESS_CALLBACKS_ADD(R13)
|
||||
ASAN_MEMORY_ACCESS_CALLBACKS_ADD(R14)
|
||||
ASAN_MEMORY_ACCESS_CALLBACKS_ADD(R15)
|
||||
|
||||
#endif
|
||||
|
||||
NO_EXEC_STACK_DIRECTIVE
|
|
@ -33,7 +33,7 @@ static void ProtectGap(uptr addr, uptr size) {
|
|||
"protect_shadow_gap=0:"
|
||||
" not protecting shadow gap, allocating gap's shadow\n"
|
||||
"|| `[%p, %p]` || ShadowGap's shadow ||\n",
|
||||
GapShadowBeg, GapShadowEnd);
|
||||
(void*)GapShadowBeg, (void*)GapShadowEnd);
|
||||
ReserveShadowMemoryRange(GapShadowBeg, GapShadowEnd,
|
||||
"unprotected gap shadow");
|
||||
return;
|
||||
|
@ -113,7 +113,7 @@ void InitializeShadowMemory() {
|
|||
"Shadow memory range interleaves with an existing memory mapping. "
|
||||
"ASan cannot proceed correctly. ABORTING.\n");
|
||||
Report("ASan shadow was supposed to be located in the [%p-%p] range.\n",
|
||||
shadow_start, kHighShadowEnd);
|
||||
(void*)shadow_start, (void*)kHighShadowEnd);
|
||||
MaybeReportLinuxPIEBug();
|
||||
DumpProcessMap();
|
||||
Die();
|
||||
|
|
|
@ -62,11 +62,11 @@ void AsanStats::MergeFrom(const AsanStats *stats) {
|
|||
dst_ptr[i] += src_ptr[i];
|
||||
}
|
||||
|
||||
static BlockingMutex print_lock(LINKER_INITIALIZED);
|
||||
static Mutex print_lock;
|
||||
|
||||
static AsanStats unknown_thread_stats(LINKER_INITIALIZED);
|
||||
static AsanStats dead_threads_stats(LINKER_INITIALIZED);
|
||||
static BlockingMutex dead_threads_stats_lock(LINKER_INITIALIZED);
|
||||
static Mutex dead_threads_stats_lock;
|
||||
// Required for malloc_zone_statistics() on OS X. This can't be stored in
|
||||
// per-thread AsanStats.
|
||||
static uptr max_malloced_memory;
|
||||
|
@ -87,7 +87,7 @@ static void GetAccumulatedStats(AsanStats *stats) {
|
|||
}
|
||||
stats->MergeFrom(&unknown_thread_stats);
|
||||
{
|
||||
BlockingMutexLock lock(&dead_threads_stats_lock);
|
||||
Lock lock(&dead_threads_stats_lock);
|
||||
stats->MergeFrom(&dead_threads_stats);
|
||||
}
|
||||
// This is not very accurate: we may miss allocation peaks that happen
|
||||
|
@ -99,7 +99,7 @@ static void GetAccumulatedStats(AsanStats *stats) {
|
|||
}
|
||||
|
||||
void FlushToDeadThreadStats(AsanStats *stats) {
|
||||
BlockingMutexLock lock(&dead_threads_stats_lock);
|
||||
Lock lock(&dead_threads_stats_lock);
|
||||
dead_threads_stats.MergeFrom(stats);
|
||||
stats->Clear();
|
||||
}
|
||||
|
@ -122,11 +122,11 @@ static void PrintAccumulatedStats() {
|
|||
AsanStats stats;
|
||||
GetAccumulatedStats(&stats);
|
||||
// Use lock to keep reports from mixing up.
|
||||
BlockingMutexLock lock(&print_lock);
|
||||
Lock lock(&print_lock);
|
||||
stats.Print();
|
||||
StackDepotStats *stack_depot_stats = StackDepotGetStats();
|
||||
StackDepotStats stack_depot_stats = StackDepotGetStats();
|
||||
Printf("Stats: StackDepot: %zd ids; %zdM allocated\n",
|
||||
stack_depot_stats->n_uniq_ids, stack_depot_stats->allocated >> 20);
|
||||
stack_depot_stats.n_uniq_ids, stack_depot_stats.allocated >> 20);
|
||||
PrintInternalAllocatorStats();
|
||||
}
|
||||
|
||||
|
|
|
@ -43,11 +43,11 @@ void AsanThreadContext::OnFinished() {
|
|||
static ALIGNED(16) char thread_registry_placeholder[sizeof(ThreadRegistry)];
|
||||
static ThreadRegistry *asan_thread_registry;
|
||||
|
||||
static BlockingMutex mu_for_thread_context(LINKER_INITIALIZED);
|
||||
static Mutex mu_for_thread_context;
|
||||
static LowLevelAllocator allocator_for_thread_context;
|
||||
|
||||
static ThreadContextBase *GetAsanThreadContext(u32 tid) {
|
||||
BlockingMutexLock lock(&mu_for_thread_context);
|
||||
Lock lock(&mu_for_thread_context);
|
||||
return new(allocator_for_thread_context) AsanThreadContext(tid);
|
||||
}
|
||||
|
||||
|
@ -83,8 +83,7 @@ AsanThread *AsanThread::Create(thread_callback_t start_routine, void *arg,
|
|||
thread->start_routine_ = start_routine;
|
||||
thread->arg_ = arg;
|
||||
AsanThreadContext::CreateThreadContextArgs args = {thread, stack};
|
||||
asanThreadRegistry().CreateThread(*reinterpret_cast<uptr *>(thread), detached,
|
||||
parent_tid, &args);
|
||||
asanThreadRegistry().CreateThread(0, detached, parent_tid, &args);
|
||||
|
||||
return thread;
|
||||
}
|
||||
|
@ -254,7 +253,7 @@ void AsanThread::Init(const InitOptions *options) {
|
|||
int local = 0;
|
||||
VReport(1, "T%d: stack [%p,%p) size 0x%zx; local=%p\n", tid(),
|
||||
(void *)stack_bottom_, (void *)stack_top_, stack_top_ - stack_bottom_,
|
||||
&local);
|
||||
(void *)&local);
|
||||
}
|
||||
|
||||
// Fuchsia doesn't use ThreadStart.
|
||||
|
@ -306,7 +305,7 @@ void AsanThread::SetThreadStackAndTls(const InitOptions *options) {
|
|||
uptr stack_size = 0;
|
||||
GetThreadStackAndTls(tid() == kMainTid, &stack_bottom_, &stack_size,
|
||||
&tls_begin_, &tls_size);
|
||||
stack_top_ = RoundDownTo(stack_bottom_ + stack_size, SHADOW_GRANULARITY);
|
||||
stack_top_ = RoundDownTo(stack_bottom_ + stack_size, ASAN_SHADOW_GRANULARITY);
|
||||
tls_end_ = tls_begin_ + tls_size;
|
||||
dtls_ = DTLS_Get();
|
||||
|
||||
|
@ -322,11 +321,9 @@ void AsanThread::ClearShadowForThreadStackAndTLS() {
|
|||
if (stack_top_ != stack_bottom_)
|
||||
PoisonShadow(stack_bottom_, stack_top_ - stack_bottom_, 0);
|
||||
if (tls_begin_ != tls_end_) {
|
||||
uptr tls_begin_aligned = RoundDownTo(tls_begin_, SHADOW_GRANULARITY);
|
||||
uptr tls_end_aligned = RoundUpTo(tls_end_, SHADOW_GRANULARITY);
|
||||
FastPoisonShadowPartialRightRedzone(tls_begin_aligned,
|
||||
tls_end_ - tls_begin_aligned,
|
||||
tls_end_aligned - tls_end_, 0);
|
||||
uptr tls_begin_aligned = RoundDownTo(tls_begin_, ASAN_SHADOW_GRANULARITY);
|
||||
uptr tls_end_aligned = RoundUpTo(tls_end_, ASAN_SHADOW_GRANULARITY);
|
||||
FastPoisonShadow(tls_begin_aligned, tls_end_aligned - tls_begin_aligned, 0);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -347,27 +344,27 @@ bool AsanThread::GetStackFrameAccessByAddr(uptr addr,
|
|||
return true;
|
||||
}
|
||||
uptr aligned_addr = RoundDownTo(addr, SANITIZER_WORDSIZE / 8); // align addr.
|
||||
uptr mem_ptr = RoundDownTo(aligned_addr, SHADOW_GRANULARITY);
|
||||
uptr mem_ptr = RoundDownTo(aligned_addr, ASAN_SHADOW_GRANULARITY);
|
||||
u8 *shadow_ptr = (u8*)MemToShadow(aligned_addr);
|
||||
u8 *shadow_bottom = (u8*)MemToShadow(bottom);
|
||||
|
||||
while (shadow_ptr >= shadow_bottom &&
|
||||
*shadow_ptr != kAsanStackLeftRedzoneMagic) {
|
||||
shadow_ptr--;
|
||||
mem_ptr -= SHADOW_GRANULARITY;
|
||||
mem_ptr -= ASAN_SHADOW_GRANULARITY;
|
||||
}
|
||||
|
||||
while (shadow_ptr >= shadow_bottom &&
|
||||
*shadow_ptr == kAsanStackLeftRedzoneMagic) {
|
||||
shadow_ptr--;
|
||||
mem_ptr -= SHADOW_GRANULARITY;
|
||||
mem_ptr -= ASAN_SHADOW_GRANULARITY;
|
||||
}
|
||||
|
||||
if (shadow_ptr < shadow_bottom) {
|
||||
return false;
|
||||
}
|
||||
|
||||
uptr* ptr = (uptr*)(mem_ptr + SHADOW_GRANULARITY);
|
||||
uptr *ptr = (uptr *)(mem_ptr + ASAN_SHADOW_GRANULARITY);
|
||||
CHECK(ptr[0] == kCurrentStackFrameMagic);
|
||||
access->offset = addr - (uptr)ptr;
|
||||
access->frame_pc = ptr[2];
|
||||
|
@ -443,7 +440,7 @@ AsanThread *GetCurrentThread() {
|
|||
|
||||
void SetCurrentThread(AsanThread *t) {
|
||||
CHECK(t->context());
|
||||
VReport(2, "SetCurrentThread: %p for thread %p\n", t->context(),
|
||||
VReport(2, "SetCurrentThread: %p for thread %p\n", (void *)t->context(),
|
||||
(void *)GetThreadSelf());
|
||||
// Make sure we do not reset the current AsanThread.
|
||||
CHECK_EQ(0, AsanTSDGet());
|
||||
|
@ -481,6 +478,17 @@ __asan::AsanThread *GetAsanThreadByOsIDLocked(tid_t os_id) {
|
|||
|
||||
// --- Implementation of LSan-specific functions --- {{{1
|
||||
namespace __lsan {
|
||||
void LockThreadRegistry() { __asan::asanThreadRegistry().Lock(); }
|
||||
|
||||
void UnlockThreadRegistry() { __asan::asanThreadRegistry().Unlock(); }
|
||||
|
||||
static ThreadRegistry *GetAsanThreadRegistryLocked() {
|
||||
__asan::asanThreadRegistry().CheckLocked();
|
||||
return &__asan::asanThreadRegistry();
|
||||
}
|
||||
|
||||
void EnsureMainThreadIDIsCorrect() { __asan::EnsureMainThreadIDIsCorrect(); }
|
||||
|
||||
bool GetThreadRangesLocked(tid_t os_id, uptr *stack_begin, uptr *stack_end,
|
||||
uptr *tls_begin, uptr *tls_end, uptr *cache_begin,
|
||||
uptr *cache_end, DTLS **dtls) {
|
||||
|
@ -499,33 +507,76 @@ bool GetThreadRangesLocked(tid_t os_id, uptr *stack_begin, uptr *stack_end,
|
|||
|
||||
void GetAllThreadAllocatorCachesLocked(InternalMmapVector<uptr> *caches) {}
|
||||
|
||||
void ForEachExtraStackRange(tid_t os_id, RangeIteratorCallback callback,
|
||||
void *arg) {
|
||||
void GetThreadExtraStackRangesLocked(tid_t os_id,
|
||||
InternalMmapVector<Range> *ranges) {
|
||||
__asan::AsanThread *t = __asan::GetAsanThreadByOsIDLocked(os_id);
|
||||
if (!t)
|
||||
return;
|
||||
__asan::FakeStack *fake_stack = t->get_fake_stack();
|
||||
if (!fake_stack)
|
||||
return;
|
||||
fake_stack->ForEachFakeFrame(callback, arg);
|
||||
|
||||
fake_stack->ForEachFakeFrame(
|
||||
[](uptr begin, uptr end, void *arg) {
|
||||
reinterpret_cast<InternalMmapVector<Range> *>(arg)->push_back(
|
||||
{begin, end});
|
||||
},
|
||||
ranges);
|
||||
}
|
||||
|
||||
void LockThreadRegistry() {
|
||||
__asan::asanThreadRegistry().Lock();
|
||||
void GetThreadExtraStackRangesLocked(InternalMmapVector<Range> *ranges) {
|
||||
GetAsanThreadRegistryLocked()->RunCallbackForEachThreadLocked(
|
||||
[](ThreadContextBase *tctx, void *arg) {
|
||||
GetThreadExtraStackRangesLocked(
|
||||
tctx->os_id, reinterpret_cast<InternalMmapVector<Range> *>(arg));
|
||||
},
|
||||
ranges);
|
||||
}
|
||||
|
||||
void UnlockThreadRegistry() {
|
||||
__asan::asanThreadRegistry().Unlock();
|
||||
void GetAdditionalThreadContextPtrsLocked(InternalMmapVector<uptr> *ptrs) {
|
||||
GetAsanThreadRegistryLocked()->RunCallbackForEachThreadLocked(
|
||||
[](ThreadContextBase *tctx, void *ptrs) {
|
||||
// Look for the arg pointer of threads that have been created or are
|
||||
// running. This is necessary to prevent false positive leaks due to the
|
||||
// AsanThread holding the only live reference to a heap object. This
|
||||
// can happen because the `pthread_create()` interceptor doesn't wait
|
||||
// for the child thread to start before returning and thus loosing the
|
||||
// the only live reference to the heap object on the stack.
|
||||
|
||||
__asan::AsanThreadContext *atctx =
|
||||
static_cast<__asan::AsanThreadContext *>(tctx);
|
||||
|
||||
// Note ThreadStatusRunning is required because there is a small window
|
||||
// where the thread status switches to `ThreadStatusRunning` but the
|
||||
// `arg` pointer still isn't on the stack yet.
|
||||
if (atctx->status != ThreadStatusCreated &&
|
||||
atctx->status != ThreadStatusRunning)
|
||||
return;
|
||||
|
||||
uptr thread_arg = reinterpret_cast<uptr>(atctx->thread->get_arg());
|
||||
if (!thread_arg)
|
||||
return;
|
||||
|
||||
auto ptrsVec = reinterpret_cast<InternalMmapVector<uptr> *>(ptrs);
|
||||
ptrsVec->push_back(thread_arg);
|
||||
},
|
||||
ptrs);
|
||||
}
|
||||
|
||||
ThreadRegistry *GetThreadRegistryLocked() {
|
||||
__asan::asanThreadRegistry().CheckLocked();
|
||||
return &__asan::asanThreadRegistry();
|
||||
void GetRunningThreadsLocked(InternalMmapVector<tid_t> *threads) {
|
||||
GetAsanThreadRegistryLocked()->RunCallbackForEachThreadLocked(
|
||||
[](ThreadContextBase *tctx, void *threads) {
|
||||
if (tctx->status == ThreadStatusRunning)
|
||||
reinterpret_cast<InternalMmapVector<tid_t> *>(threads)->push_back(
|
||||
tctx->os_id);
|
||||
},
|
||||
threads);
|
||||
}
|
||||
|
||||
void EnsureMainThreadIDIsCorrect() {
|
||||
__asan::EnsureMainThreadIDIsCorrect();
|
||||
void FinishThreadLocked(u32 tid) {
|
||||
GetAsanThreadRegistryLocked()->FinishThread(tid);
|
||||
}
|
||||
|
||||
} // namespace __lsan
|
||||
|
||||
// ---------------------- Interface ---------------- {{{1
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
//===-- asan_win.cpp ------------------------------------------------------===//
|
||||
//===-- asan_win.cpp
|
||||
//------------------------------------------------------===//>
|
||||
//
|
||||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
||||
// See https://llvm.org/LICENSE.txt for license information.
|
||||
|
@ -13,21 +14,20 @@
|
|||
|
||||
#include "sanitizer_common/sanitizer_platform.h"
|
||||
#if SANITIZER_WINDOWS
|
||||
#define WIN32_LEAN_AND_MEAN
|
||||
#include <windows.h>
|
||||
# define WIN32_LEAN_AND_MEAN
|
||||
# include <stdlib.h>
|
||||
# include <windows.h>
|
||||
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "asan_interceptors.h"
|
||||
#include "asan_internal.h"
|
||||
#include "asan_mapping.h"
|
||||
#include "asan_report.h"
|
||||
#include "asan_stack.h"
|
||||
#include "asan_thread.h"
|
||||
#include "sanitizer_common/sanitizer_libc.h"
|
||||
#include "sanitizer_common/sanitizer_mutex.h"
|
||||
#include "sanitizer_common/sanitizer_win.h"
|
||||
#include "sanitizer_common/sanitizer_win_defs.h"
|
||||
# include "asan_interceptors.h"
|
||||
# include "asan_internal.h"
|
||||
# include "asan_mapping.h"
|
||||
# include "asan_report.h"
|
||||
# include "asan_stack.h"
|
||||
# include "asan_thread.h"
|
||||
# include "sanitizer_common/sanitizer_libc.h"
|
||||
# include "sanitizer_common/sanitizer_mutex.h"
|
||||
# include "sanitizer_common/sanitizer_win.h"
|
||||
# include "sanitizer_common/sanitizer_win_defs.h"
|
||||
|
||||
using namespace __asan;
|
||||
|
||||
|
@ -49,8 +49,8 @@ uptr __asan_get_shadow_memory_dynamic_address() {
|
|||
static LPTOP_LEVEL_EXCEPTION_FILTER default_seh_handler;
|
||||
static LPTOP_LEVEL_EXCEPTION_FILTER user_seh_handler;
|
||||
|
||||
extern "C" SANITIZER_INTERFACE_ATTRIBUTE
|
||||
long __asan_unhandled_exception_filter(EXCEPTION_POINTERS *info) {
|
||||
extern "C" SANITIZER_INTERFACE_ATTRIBUTE long __asan_unhandled_exception_filter(
|
||||
EXCEPTION_POINTERS *info) {
|
||||
EXCEPTION_RECORD *exception_record = info->ExceptionRecord;
|
||||
CONTEXT *context = info->ContextRecord;
|
||||
|
||||
|
@ -187,6 +187,8 @@ void InitializePlatformInterceptors() {
|
|||
}
|
||||
}
|
||||
|
||||
void InstallAtExitCheckLeaks() {}
|
||||
|
||||
void AsanApplyToGlobals(globals_op_fptr op, const void *needle) {
|
||||
UNIMPLEMENTED();
|
||||
}
|
||||
|
@ -253,7 +255,7 @@ void *AsanDoesNotSupportStaticLinkage() {
|
|||
}
|
||||
|
||||
uptr FindDynamicShadowStart() {
|
||||
return MapDynamicShadow(MemToShadowSize(kHighMemEnd), SHADOW_SCALE,
|
||||
return MapDynamicShadow(MemToShadowSize(kHighMemEnd), ASAN_SHADOW_SCALE,
|
||||
/*min_shadow_base_alignment*/ 0, kHighMemEnd);
|
||||
}
|
||||
|
||||
|
@ -261,10 +263,6 @@ void AsanCheckDynamicRTPrereqs() {}
|
|||
|
||||
void AsanCheckIncompatibleRT() {}
|
||||
|
||||
void ReadContextStack(void *context, uptr *stack, uptr *ssize) {
|
||||
UNIMPLEMENTED();
|
||||
}
|
||||
|
||||
void AsanOnDeadlySignal(int, void *siginfo, void *context) { UNIMPLEMENTED(); }
|
||||
|
||||
bool PlatformUnpoisonStacks() { return false; }
|
||||
|
|
|
@ -56,6 +56,13 @@ INTERCEPT_WRAP_W_W(_expand_dbg)
|
|||
|
||||
// TODO(timurrrr): Do we need to add _Crt* stuff here? (see asan_malloc_win.cpp)
|
||||
|
||||
# if defined(_MSC_VER) && !defined(__clang__)
|
||||
// Disable warnings such as: 'void memchr(void)': incorrect number of arguments
|
||||
// for intrinsic function, expected '3' arguments.
|
||||
# pragma warning(push)
|
||||
# pragma warning(disable : 4392)
|
||||
# endif
|
||||
|
||||
INTERCEPT_LIBRARY_FUNCTION(atoi);
|
||||
INTERCEPT_LIBRARY_FUNCTION(atol);
|
||||
INTERCEPT_LIBRARY_FUNCTION(frexp);
|
||||
|
@ -87,6 +94,10 @@ INTERCEPT_LIBRARY_FUNCTION(strtol);
|
|||
INTERCEPT_LIBRARY_FUNCTION(wcslen);
|
||||
INTERCEPT_LIBRARY_FUNCTION(wcsnlen);
|
||||
|
||||
# if defined(_MSC_VER) && !defined(__clang__)
|
||||
# pragma warning(pop)
|
||||
# endif
|
||||
|
||||
#ifdef _WIN64
|
||||
INTERCEPT_LIBRARY_FUNCTION(__C_specific_handler);
|
||||
#else
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
#!/bin/bash
|
||||
#!/usr/bin/env bash
|
||||
#===- lib/asan/scripts/asan_device_setup -----------------------------------===#
|
||||
#
|
||||
# Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
||||
|
|
|
@ -50,7 +50,7 @@ def fix_filename(file_name):
|
|||
def is_valid_arch(s):
|
||||
return s in ["i386", "x86_64", "x86_64h", "arm", "armv6", "armv7", "armv7s",
|
||||
"armv7k", "arm64", "powerpc64", "powerpc64le", "s390x", "s390",
|
||||
"riscv64"]
|
||||
"riscv64", "loongarch64"]
|
||||
|
||||
def guess_arch(addr):
|
||||
# Guess which arch we're running. 10 = len('0x') + 8 hex digits.
|
||||
|
|
|
@ -23,7 +23,7 @@ set(ASAN_UNITTEST_HEADERS
|
|||
set(ASAN_UNITTEST_COMMON_CFLAGS
|
||||
${COMPILER_RT_UNITTEST_CFLAGS}
|
||||
${COMPILER_RT_GTEST_CFLAGS}
|
||||
${COMPILER_RT_ASAN_SHADOW_SCALE_LLVM_FLAG}
|
||||
${SANITIZER_TEST_CXX_CFLAGS}
|
||||
-I${COMPILER_RT_SOURCE_DIR}/include
|
||||
-I${COMPILER_RT_SOURCE_DIR}/lib
|
||||
-I${COMPILER_RT_SOURCE_DIR}/lib/asan
|
||||
|
@ -37,7 +37,9 @@ append_list_if(COMPILER_RT_HAS_WVARIADIC_MACROS_FLAG -Wno-variadic-macros ASAN_U
|
|||
# This will ensure the target linker is used
|
||||
# during cross compilation
|
||||
set(ASAN_UNITTEST_COMMON_LINK_FLAGS
|
||||
${COMPILER_RT_UNITTEST_LINK_FLAGS})
|
||||
${COMPILER_RT_UNITTEST_LINK_FLAGS}
|
||||
${COMPILER_RT_UNWINDER_LINK_LIBS}
|
||||
${SANITIZER_TEST_CXX_LIBRARIES})
|
||||
|
||||
# -gline-tables-only must be enough for ASan, so use it if possible.
|
||||
if(COMPILER_RT_TEST_COMPILER_ID MATCHES "Clang")
|
||||
|
@ -52,7 +54,6 @@ list(APPEND ASAN_UNITTEST_COMMON_LINK_FLAGS -g)
|
|||
|
||||
# Use -D instead of definitions to please custom compile command.
|
||||
list(APPEND ASAN_UNITTEST_COMMON_CFLAGS
|
||||
${COMPILER_RT_ASAN_SHADOW_SCALE_FLAG}
|
||||
-DASAN_HAS_IGNORELIST=1
|
||||
-DASAN_HAS_EXCEPTIONS=1
|
||||
-DASAN_UAR=0
|
||||
|
@ -163,22 +164,32 @@ set(ASAN_BENCHMARKS_SOURCES
|
|||
function(add_asan_tests arch test_runtime)
|
||||
cmake_parse_arguments(TEST "" "KIND" "CFLAGS" ${ARGN})
|
||||
|
||||
# The Lit files are configured once per architecture and static/dynamic
|
||||
# selection. Each configuration expects the test binaries in a corresponding
|
||||
# subdirectory. Generate subdirectory names based on the architecture name.
|
||||
string(TOUPPER ${arch} ARCH_UPPER_CASE)
|
||||
set(CONFIG_NAME ${ARCH_UPPER_CASE}${OS_NAME}Config)
|
||||
set(CONFIG_NAME_DYNAMIC ${ARCH_UPPER_CASE}${OS_NAME}DynamicConfig)
|
||||
|
||||
# Closure to keep the values.
|
||||
function(generate_asan_tests test_objects test_suite testname)
|
||||
generate_compiler_rt_tests(${test_objects} ${test_suite} ${testname} ${arch}
|
||||
COMPILE_DEPS ${ASAN_UNITTEST_HEADERS} ${ASAN_IGNORELIST_FILE}
|
||||
DEPS gtest asan
|
||||
DEPS llvm_gtest asan
|
||||
KIND ${TEST_KIND}
|
||||
${ARGN}
|
||||
)
|
||||
set("${test_objects}" "${${test_objects}}" PARENT_SCOPE)
|
||||
endfunction()
|
||||
|
||||
set(TARGET_LINK_FLAGS)
|
||||
get_target_link_flags_for_arch(${arch} TARGET_LINK_FLAGS)
|
||||
|
||||
set(ASAN_INST_TEST_OBJECTS)
|
||||
generate_asan_tests(ASAN_INST_TEST_OBJECTS AsanUnitTests
|
||||
"Asan-${arch}${TEST_KIND}-Test"
|
||||
SUBDIR "default"
|
||||
LINK_FLAGS ${ASAN_UNITTEST_INSTRUMENTED_LINK_FLAGS}
|
||||
SUBDIR "${CONFIG_NAME}"
|
||||
LINK_FLAGS ${ASAN_UNITTEST_INSTRUMENTED_LINK_FLAGS} ${TARGET_LINK_FLAGS}
|
||||
SOURCES ${ASAN_INST_TEST_SOURCES}
|
||||
CFLAGS ${ASAN_UNITTEST_INSTRUMENTED_CFLAGS} ${TEST_CFLAGS})
|
||||
|
||||
|
@ -191,7 +202,7 @@ function(add_asan_tests arch test_runtime)
|
|||
set(ASAN_DYNAMIC_TEST_OBJECTS)
|
||||
generate_asan_tests(ASAN_DYNAMIC_TEST_OBJECTS
|
||||
AsanDynamicUnitTests "${dynamic_test_name}"
|
||||
SUBDIR "dynamic"
|
||||
SUBDIR "${CONFIG_NAME_DYNAMIC}"
|
||||
CFLAGS ${ASAN_UNITTEST_INSTRUMENTED_CFLAGS} -D_MT -D_DLL
|
||||
SOURCES ${ASAN_INST_TEST_SOURCES}
|
||||
LINK_FLAGS ${ASAN_DYNAMIC_UNITTEST_INSTRUMENTED_LINK_FLAGS}
|
||||
|
@ -201,10 +212,10 @@ function(add_asan_tests arch test_runtime)
|
|||
|
||||
# Otherwise, reuse ASAN_INST_TEST_OBJECTS.
|
||||
add_compiler_rt_test(AsanDynamicUnitTests "${dynamic_test_name}" "${arch}"
|
||||
SUBDIR "dynamic"
|
||||
SUBDIR "${CONFIG_NAME_DYNAMIC}"
|
||||
OBJECTS ${ASAN_INST_TEST_OBJECTS}
|
||||
DEPS asan ${ASAN_INST_TEST_OBJECTS}
|
||||
LINK_FLAGS ${ASAN_DYNAMIC_UNITTEST_INSTRUMENTED_LINK_FLAGS}
|
||||
LINK_FLAGS ${ASAN_DYNAMIC_UNITTEST_INSTRUMENTED_LINK_FLAGS} ${TARGET_LINK_FLAGS}
|
||||
)
|
||||
endif()
|
||||
endif()
|
||||
|
@ -213,19 +224,19 @@ function(add_asan_tests arch test_runtime)
|
|||
set(ASAN_NOINST_TEST_OBJECTS)
|
||||
generate_asan_tests(ASAN_NOINST_TEST_OBJECTS
|
||||
AsanUnitTests "Asan-${arch}${TEST_KIND}-Noinst-Test"
|
||||
SUBDIR "default"
|
||||
SUBDIR "${CONFIG_NAME}"
|
||||
CFLAGS ${ASAN_UNITTEST_COMMON_CFLAGS}
|
||||
LINK_FLAGS ${ASAN_UNITTEST_NOINST_LINK_FLAGS}
|
||||
LINK_FLAGS ${ASAN_UNITTEST_NOINST_LINK_FLAGS} ${TARGET_LINK_FLAGS}
|
||||
SOURCES ${ASAN_NOINST_TEST_SOURCES}
|
||||
RUNTIME ${test_runtime})
|
||||
|
||||
set(ASAN_BENCHMARK_OBJECTS)
|
||||
generate_asan_tests(ASAN_BENCHMARK_OBJECTS
|
||||
AsanBenchmarks "Asan-${arch}${TEST_KIND}-Benchmark"
|
||||
SUBDIR "default"
|
||||
SUBDIR "${CONFIG_NAME}"
|
||||
CFLAGS ${ASAN_UNITTEST_INSTRUMENTED_CFLAGS}
|
||||
SOURCES ${ASAN_BENCHMARKS_SOURCES}
|
||||
LINK_FLAGS ${ASAN_UNITTEST_INSTRUMENTED_LINK_FLAGS})
|
||||
LINK_FLAGS ${ASAN_UNITTEST_INSTRUMENTED_LINK_FLAGS} ${TARGET_LINK_FLAGS})
|
||||
endfunction()
|
||||
|
||||
if(COMPILER_RT_CAN_EXECUTE_TESTS AND NOT ANDROID)
|
||||
|
@ -256,6 +267,7 @@ if(COMPILER_RT_CAN_EXECUTE_TESTS AND NOT ANDROID)
|
|||
set(ASAN_TEST_RUNTIME_OBJECTS
|
||||
$<TARGET_OBJECTS:RTAsan.${arch}>
|
||||
$<TARGET_OBJECTS:RTAsan_cxx.${arch}>
|
||||
$<TARGET_OBJECTS:RTAsan_static.${arch}>
|
||||
$<TARGET_OBJECTS:RTInterception.${arch}>
|
||||
$<TARGET_OBJECTS:RTSanitizerCommon.${arch}>
|
||||
$<TARGET_OBJECTS:RTSanitizerCommonLibc.${arch}>
|
||||
|
@ -281,6 +293,7 @@ if(ANDROID)
|
|||
# Test w/o ASan instrumentation. Link it with ASan statically.
|
||||
add_executable(AsanNoinstTest # FIXME: .arch?
|
||||
$<TARGET_OBJECTS:RTAsan.${arch}>
|
||||
$<TARGET_OBJECTS:RTAsan_static.${arch}>
|
||||
$<TARGET_OBJECTS:RTInterception.${arch}>
|
||||
$<TARGET_OBJECTS:RTSanitizerCommon.${arch}>
|
||||
$<TARGET_OBJECTS:RTSanitizerCommonLibc.${arch}>
|
||||
|
|
|
@ -90,7 +90,7 @@ TEST(AddressSanitizerInterface, GetCurrentAllocatedBytesTest) {
|
|||
TEST(AddressSanitizerInterface, GetHeapSizeTest) {
|
||||
// ASan allocator does not keep huge chunks in free list, but unmaps them.
|
||||
// The chunk should be greater than the quarantine size,
|
||||
// otherwise it will be stuck in quarantine instead of being unmaped.
|
||||
// otherwise it will be stuck in quarantine instead of being unmapped.
|
||||
static const size_t kLargeMallocSize = (1 << 28) + 1; // 256M
|
||||
free(Ident(malloc(kLargeMallocSize))); // Drain quarantine.
|
||||
size_t old_heap_size = __sanitizer_get_heap_size();
|
||||
|
@ -160,7 +160,6 @@ TEST(AddressSanitizerInterface, DeathCallbackTest) {
|
|||
#define BAD_ACCESS(ptr, offset) \
|
||||
EXPECT_TRUE(__asan_address_is_poisoned(ptr + offset))
|
||||
|
||||
#if !defined(ASAN_SHADOW_SCALE) || ASAN_SHADOW_SCALE == 3
|
||||
static const char* kUseAfterPoisonErrorMessage = "use-after-poison";
|
||||
|
||||
TEST(AddressSanitizerInterface, SimplePoisonMemoryRegionTest) {
|
||||
|
@ -200,7 +199,6 @@ TEST(AddressSanitizerInterface, OverlappingPoisonMemoryRegionTest) {
|
|||
BAD_ACCESS(array, 96);
|
||||
free(array);
|
||||
}
|
||||
#endif // !defined(ASAN_SHADOW_SCALE) || ASAN_SHADOW_SCALE == 3
|
||||
|
||||
TEST(AddressSanitizerInterface, PushAndPopWithPoisoningTest) {
|
||||
// Vector of capacity 20
|
||||
|
@ -415,6 +413,9 @@ TEST(AddressSanitizerInterface, HandleNoReturnTest) {
|
|||
__asan_poison_memory_region(array, sizeof(array));
|
||||
BAD_ACCESS(array, 20);
|
||||
__asan_handle_no_return();
|
||||
// Fake stack does not need to be unpoisoned.
|
||||
if (__asan_get_current_fake_stack())
|
||||
return;
|
||||
// It unpoisons the whole thread stack.
|
||||
GOOD_ACCESS(array, 20);
|
||||
}
|
||||
|
|
|
@ -19,6 +19,27 @@ TEST(AddressSanitizerInternalInterface, SetShadow) {
|
|||
__asan_set_shadow_00((uptr)buffer.data(), buffer.size());
|
||||
EXPECT_EQ(std::vector<char>(buffer.size(), 0x00), buffer);
|
||||
|
||||
__asan_set_shadow_01((uptr)buffer.data(), buffer.size());
|
||||
EXPECT_EQ(std::vector<char>(buffer.size(), 0x01), buffer);
|
||||
|
||||
__asan_set_shadow_02((uptr)buffer.data(), buffer.size());
|
||||
EXPECT_EQ(std::vector<char>(buffer.size(), 0x02), buffer);
|
||||
|
||||
__asan_set_shadow_03((uptr)buffer.data(), buffer.size());
|
||||
EXPECT_EQ(std::vector<char>(buffer.size(), 0x03), buffer);
|
||||
|
||||
__asan_set_shadow_04((uptr)buffer.data(), buffer.size());
|
||||
EXPECT_EQ(std::vector<char>(buffer.size(), 0x04), buffer);
|
||||
|
||||
__asan_set_shadow_05((uptr)buffer.data(), buffer.size());
|
||||
EXPECT_EQ(std::vector<char>(buffer.size(), 0x05), buffer);
|
||||
|
||||
__asan_set_shadow_06((uptr)buffer.data(), buffer.size());
|
||||
EXPECT_EQ(std::vector<char>(buffer.size(), 0x06), buffer);
|
||||
|
||||
__asan_set_shadow_07((uptr)buffer.data(), buffer.size());
|
||||
EXPECT_EQ(std::vector<char>(buffer.size(), 0x07), buffer);
|
||||
|
||||
__asan_set_shadow_f1((uptr)buffer.data(), buffer.size());
|
||||
EXPECT_EQ(std::vector<char>(buffer.size(), 0xf1), buffer);
|
||||
|
||||
|
|
|
@ -37,18 +37,18 @@ void MemSetOOBTestTemplate(size_t length) {
|
|||
MEMSET(array + length, 0, zero);
|
||||
MEMSET(array + length + 1, 0, zero);
|
||||
|
||||
// try to memset bytes to the right of array
|
||||
// try to memset bytes after array
|
||||
EXPECT_DEATH(MEMSET(array, 0, size + 1),
|
||||
RightOOBWriteMessage(0));
|
||||
EXPECT_DEATH(MEMSET((char*)(array + length) - 1, element, 6),
|
||||
RightOOBWriteMessage(0));
|
||||
EXPECT_DEATH(MEMSET(array + 1, element, size + sizeof(T)),
|
||||
RightOOBWriteMessage(0));
|
||||
// whole interval is to the right
|
||||
// whole interval is after
|
||||
EXPECT_DEATH(MEMSET(array + length + 1, 0, 10),
|
||||
RightOOBWriteMessage(sizeof(T)));
|
||||
|
||||
// try to memset bytes to the left of array
|
||||
// try to memset bytes before array
|
||||
EXPECT_DEATH(MEMSET((char*)array - 1, element, size),
|
||||
LeftOOBWriteMessage(1));
|
||||
EXPECT_DEATH(MEMSET((char*)array - 5, 0, 6),
|
||||
|
@ -58,11 +58,11 @@ void MemSetOOBTestTemplate(size_t length) {
|
|||
EXPECT_DEATH(memset(array - 5, element, size + 5 * sizeof(T)),
|
||||
LeftOOBWriteMessage(5 * sizeof(T)));
|
||||
}
|
||||
// whole interval is to the left
|
||||
// whole interval is before
|
||||
EXPECT_DEATH(MEMSET(array - 2, 0, sizeof(T)),
|
||||
LeftOOBWriteMessage(2 * sizeof(T)));
|
||||
|
||||
// try to memset bytes both to the left & to the right
|
||||
// try to memset bytes both before & after
|
||||
EXPECT_DEATH(MEMSET((char*)array - 2, element, size + 4),
|
||||
LeftOOBWriteMessage(2));
|
||||
|
||||
|
@ -114,7 +114,7 @@ TEST(AddressSanitizer, LargeOOBInMemset) {
|
|||
// fprintf(stderr, " large oob memset: %p %p %zd\n", x1, x2, size);
|
||||
// Do a memset on x1 with huge out-of-bound access that will end up in x2.
|
||||
EXPECT_DEATH(Ident(memset)(x1, 0, size * 2),
|
||||
"is located 0 bytes to the right");
|
||||
"is located 0 bytes after");
|
||||
delete [] x1;
|
||||
delete [] x2;
|
||||
return;
|
||||
|
@ -143,25 +143,25 @@ void MemTransferOOBTestTemplate(size_t length) {
|
|||
M::transfer(dest, src - 1, zero);
|
||||
M::transfer(dest, src, zero);
|
||||
|
||||
// try to change mem to the right of dest
|
||||
// try to change mem after dest
|
||||
EXPECT_DEATH(M::transfer(dest + 1, src, size),
|
||||
RightOOBWriteMessage(0));
|
||||
EXPECT_DEATH(M::transfer((char*)(dest + length) - 1, src, 5),
|
||||
RightOOBWriteMessage(0));
|
||||
|
||||
// try to change mem to the left of dest
|
||||
// try to change mem before dest
|
||||
EXPECT_DEATH(M::transfer(dest - 2, src, size),
|
||||
LeftOOBWriteMessage(2 * sizeof(T)));
|
||||
EXPECT_DEATH(M::transfer((char*)dest - 3, src, 4),
|
||||
LeftOOBWriteMessage(3));
|
||||
|
||||
// try to access mem to the right of src
|
||||
// try to access mem after src
|
||||
EXPECT_DEATH(M::transfer(dest, src + 2, size),
|
||||
RightOOBReadMessage(0));
|
||||
EXPECT_DEATH(M::transfer(dest, (char*)(src + length) - 3, 6),
|
||||
RightOOBReadMessage(0));
|
||||
|
||||
// try to access mem to the left of src
|
||||
// try to access mem before src
|
||||
EXPECT_DEATH(M::transfer(dest, src - 1, size),
|
||||
LeftOOBReadMessage(sizeof(T)));
|
||||
EXPECT_DEATH(M::transfer(dest, (char*)src - 6, 7),
|
||||
|
|
|
@ -11,19 +11,20 @@
|
|||
// This test file should be compiled w/o asan instrumentation.
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include <assert.h>
|
||||
#include <sanitizer/allocator_interface.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h> // for memset()
|
||||
|
||||
#include <algorithm>
|
||||
#include <limits>
|
||||
#include <vector>
|
||||
|
||||
#include "asan_allocator.h"
|
||||
#include "asan_internal.h"
|
||||
#include "asan_mapping.h"
|
||||
#include "asan_test_utils.h"
|
||||
#include <sanitizer/allocator_interface.h>
|
||||
|
||||
#include <assert.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h> // for memset()
|
||||
#include <algorithm>
|
||||
#include <vector>
|
||||
#include <limits>
|
||||
|
||||
using namespace __sanitizer;
|
||||
|
||||
|
@ -230,17 +231,8 @@ TEST(AddressSanitizer, ShadowRegionIsPoisonedTest) {
|
|||
}
|
||||
|
||||
// Test __asan_load1 & friends.
|
||||
TEST(AddressSanitizer, LoadStoreCallbacks) {
|
||||
typedef void (*CB)(uptr p);
|
||||
CB cb[2][5] = {
|
||||
{
|
||||
__asan_load1, __asan_load2, __asan_load4, __asan_load8, __asan_load16,
|
||||
}, {
|
||||
__asan_store1, __asan_store2, __asan_store4, __asan_store8,
|
||||
__asan_store16,
|
||||
}
|
||||
};
|
||||
|
||||
typedef void (*CB)(uptr p);
|
||||
static void TestLoadStoreCallbacks(CB cb[2][5]) {
|
||||
uptr buggy_ptr;
|
||||
|
||||
__asan_test_only_reported_buggy_pointer = &buggy_ptr;
|
||||
|
@ -270,3 +262,86 @@ TEST(AddressSanitizer, LoadStoreCallbacks) {
|
|||
}
|
||||
__asan_test_only_reported_buggy_pointer = 0;
|
||||
}
|
||||
|
||||
TEST(AddressSanitizer, LoadStoreCallbacks) {
|
||||
CB cb[2][5] = {{
|
||||
__asan_load1,
|
||||
__asan_load2,
|
||||
__asan_load4,
|
||||
__asan_load8,
|
||||
__asan_load16,
|
||||
},
|
||||
{
|
||||
__asan_store1,
|
||||
__asan_store2,
|
||||
__asan_store4,
|
||||
__asan_store8,
|
||||
__asan_store16,
|
||||
}};
|
||||
TestLoadStoreCallbacks(cb);
|
||||
}
|
||||
|
||||
#if defined(__x86_64__) && \
|
||||
!(defined(SANITIZER_APPLE) || defined(SANITIZER_WINDOWS))
|
||||
// clang-format off
|
||||
|
||||
#define CALL_ASAN_MEMORY_ACCESS_CALLBACK_ADD(s, reg, op) \
|
||||
void CallAsanMemoryAccessAdd##reg##op##s(uptr address) { \
|
||||
asm("push %%" #reg " \n" \
|
||||
"mov %[x], %%" #reg " \n" \
|
||||
"call __asan_check_" #op "_add_" #s "_" #reg "\n" \
|
||||
"pop %%" #reg " \n" \
|
||||
: \
|
||||
: [x] "r"(address) \
|
||||
: "r8", "rdi"); \
|
||||
}
|
||||
|
||||
#define TEST_ASAN_MEMORY_ACCESS_CALLBACKS_ADD(reg) \
|
||||
CALL_ASAN_MEMORY_ACCESS_CALLBACK_ADD(1, reg, load) \
|
||||
CALL_ASAN_MEMORY_ACCESS_CALLBACK_ADD(1, reg, store) \
|
||||
CALL_ASAN_MEMORY_ACCESS_CALLBACK_ADD(2, reg, load) \
|
||||
CALL_ASAN_MEMORY_ACCESS_CALLBACK_ADD(2, reg, store) \
|
||||
CALL_ASAN_MEMORY_ACCESS_CALLBACK_ADD(4, reg, load) \
|
||||
CALL_ASAN_MEMORY_ACCESS_CALLBACK_ADD(4, reg, store) \
|
||||
CALL_ASAN_MEMORY_ACCESS_CALLBACK_ADD(8, reg, load) \
|
||||
CALL_ASAN_MEMORY_ACCESS_CALLBACK_ADD(8, reg, store) \
|
||||
CALL_ASAN_MEMORY_ACCESS_CALLBACK_ADD(16, reg, load) \
|
||||
CALL_ASAN_MEMORY_ACCESS_CALLBACK_ADD(16, reg, store) \
|
||||
\
|
||||
TEST(AddressSanitizer, LoadStoreCallbacksAddX86##reg) { \
|
||||
CB cb[2][5] = {{ \
|
||||
CallAsanMemoryAccessAdd##reg##load1, \
|
||||
CallAsanMemoryAccessAdd##reg##load2, \
|
||||
CallAsanMemoryAccessAdd##reg##load4, \
|
||||
CallAsanMemoryAccessAdd##reg##load8, \
|
||||
CallAsanMemoryAccessAdd##reg##load16, \
|
||||
}, \
|
||||
{ \
|
||||
CallAsanMemoryAccessAdd##reg##store1, \
|
||||
CallAsanMemoryAccessAdd##reg##store2, \
|
||||
CallAsanMemoryAccessAdd##reg##store4, \
|
||||
CallAsanMemoryAccessAdd##reg##store8, \
|
||||
CallAsanMemoryAccessAdd##reg##store16, \
|
||||
}}; \
|
||||
TestLoadStoreCallbacks(cb); \
|
||||
}
|
||||
|
||||
// Instantiate all but R10 and R11 callbacks. We are using PLTSafe class with
|
||||
// the intrinsic, which guarantees that the code generation will never emit
|
||||
// R10 or R11 callbacks.
|
||||
TEST_ASAN_MEMORY_ACCESS_CALLBACKS_ADD(RAX)
|
||||
TEST_ASAN_MEMORY_ACCESS_CALLBACKS_ADD(RBX)
|
||||
TEST_ASAN_MEMORY_ACCESS_CALLBACKS_ADD(RCX)
|
||||
TEST_ASAN_MEMORY_ACCESS_CALLBACKS_ADD(RDX)
|
||||
TEST_ASAN_MEMORY_ACCESS_CALLBACKS_ADD(RSI)
|
||||
TEST_ASAN_MEMORY_ACCESS_CALLBACKS_ADD(RDI)
|
||||
TEST_ASAN_MEMORY_ACCESS_CALLBACKS_ADD(RBP)
|
||||
TEST_ASAN_MEMORY_ACCESS_CALLBACKS_ADD(R8)
|
||||
TEST_ASAN_MEMORY_ACCESS_CALLBACKS_ADD(R9)
|
||||
TEST_ASAN_MEMORY_ACCESS_CALLBACKS_ADD(R12)
|
||||
TEST_ASAN_MEMORY_ACCESS_CALLBACKS_ADD(R13)
|
||||
TEST_ASAN_MEMORY_ACCESS_CALLBACKS_ADD(R14)
|
||||
TEST_ASAN_MEMORY_ACCESS_CALLBACKS_ADD(R15)
|
||||
|
||||
// clang-format on
|
||||
#endif
|
||||
|
|
|
@ -30,7 +30,7 @@ NOINLINE void oob_test(int size, int off) {
|
|||
|
||||
static std::string GetLeftOOBMessage(int off) {
|
||||
char str[100];
|
||||
sprintf(str, "is located.*%d byte.*to the left", off);
|
||||
sprintf(str, "is located.*%d byte.*before", off);
|
||||
return str;
|
||||
}
|
||||
|
||||
|
@ -38,12 +38,12 @@ static std::string GetRightOOBMessage(int off) {
|
|||
char str[100];
|
||||
#if !defined(_WIN32)
|
||||
// FIXME: Fix PR42868 and remove SEGV match.
|
||||
sprintf(str, "is located.*%d byte.*to the right|SEGV", off);
|
||||
sprintf(str, "is located.*%d byte.*after|SEGV", off);
|
||||
#else
|
||||
// `|` doesn't work in googletest's regexes on Windows,
|
||||
// see googletest/docs/advanced.md#regular-expression-syntax
|
||||
// But it's not needed on Windows anyways.
|
||||
sprintf(str, "is located.*%d byte.*to the right", off);
|
||||
sprintf(str, "is located.*%d byte.*after", off);
|
||||
#endif
|
||||
return str;
|
||||
}
|
||||
|
|
|
@ -51,7 +51,7 @@ std::string RightOOBReadMessage(OOBKind oob_kind, int oob_distance) {
|
|||
} // namespace
|
||||
|
||||
// Input to a test is a zero-terminated string str with given length
|
||||
// Accesses to the bytes to the left and to the right of str
|
||||
// Accesses to the bytes before and after str
|
||||
// are presumed to produce OOB errors
|
||||
void StrLenOOBTestTemplate(char *str, size_t length, OOBKind oob_kind) {
|
||||
// Normal strlen calls
|
||||
|
@ -62,7 +62,7 @@ void StrLenOOBTestTemplate(char *str, size_t length, OOBKind oob_kind) {
|
|||
}
|
||||
// Arg of strlen is not malloced, OOB access
|
||||
if (oob_kind != OOBKind::Global) {
|
||||
// We don't insert RedZones to the left of global variables
|
||||
// We don't insert RedZones before global variables
|
||||
EXPECT_DEATH(Ident(strlen(str - 1)), LeftOOBReadMessage(oob_kind, 1));
|
||||
EXPECT_DEATH(Ident(strlen(str - 5)), LeftOOBReadMessage(oob_kind, 5));
|
||||
}
|
||||
|
|
|
@ -313,7 +313,7 @@ TEST(AddressSanitizer, SignalTest) {
|
|||
|
||||
static void TestLargeMalloc(size_t size) {
|
||||
char buff[1024];
|
||||
sprintf(buff, "is located 1 bytes to the left of %lu-byte", (long)size);
|
||||
sprintf(buff, "is located 1 bytes before %lu-byte", (long)size);
|
||||
EXPECT_DEATH(Ident((char*)malloc(size))[-1] = 0, buff);
|
||||
}
|
||||
|
||||
|
@ -329,7 +329,7 @@ TEST(AddressSanitizer, HugeMallocTest) {
|
|||
if (SANITIZER_WORDSIZE != 64 || ASAN_AVOID_EXPENSIVE_TESTS) return;
|
||||
size_t n_megs = 4100;
|
||||
EXPECT_DEATH(Ident((char*)malloc(n_megs << 20))[-1] = 0,
|
||||
"is located 1 bytes to the left|"
|
||||
"is located 1 bytes before|"
|
||||
"AddressSanitizer failed to allocate");
|
||||
}
|
||||
#endif
|
||||
|
@ -345,9 +345,9 @@ TEST(AddressSanitizer, memalign) {
|
|||
for (int align = 16; align <= (1 << 23); align *= 2) {
|
||||
size_t size = align * 5;
|
||||
EXPECT_DEATH(MemalignRun(align, size, -1),
|
||||
"is located 1 bytes to the left");
|
||||
"is located 1 bytes before");
|
||||
EXPECT_DEATH(MemalignRun(align, size, size + 1),
|
||||
"is located 1 bytes to the right");
|
||||
"is located 1 bytes after");
|
||||
}
|
||||
}
|
||||
#endif // SANITIZER_TEST_HAS_MEMALIGN
|
||||
|
@ -623,7 +623,7 @@ NOINLINE void SigLongJmpFunc1(sigjmp_buf buf) {
|
|||
|
||||
#if !defined(__ANDROID__) && !defined(__arm__) && !defined(__aarch64__) && \
|
||||
!defined(__mips__) && !defined(__mips64) && !defined(__s390__) && \
|
||||
!defined(__riscv)
|
||||
!defined(__riscv) && !defined(__loongarch__)
|
||||
NOINLINE void BuiltinLongJmpFunc1(jmp_buf buf) {
|
||||
// create three red zones for these two stack objects.
|
||||
int a;
|
||||
|
@ -646,9 +646,9 @@ TEST(AddressSanitizer, BuiltinLongJmpTest) {
|
|||
}
|
||||
}
|
||||
#endif // !defined(__ANDROID__) && !defined(__arm__) &&
|
||||
// !defined(__aarch64__) && !defined(__mips__)
|
||||
// !defined(__mips64) && !defined(__s390__)
|
||||
// !defined(__riscv)
|
||||
// !defined(__aarch64__) && !defined(__mips__) &&
|
||||
// !defined(__mips64) && !defined(__s390__) &&
|
||||
// !defined(__riscv) && !defined(__loongarch__)
|
||||
|
||||
TEST(AddressSanitizer, UnderscopeLongJmpTest) {
|
||||
static jmp_buf buf;
|
||||
|
@ -734,7 +734,7 @@ TEST(AddressSanitizer, Store128Test) {
|
|||
EXPECT_DEATH(_mm_store_si128((__m128i*)p, value_wide),
|
||||
"WRITE of size 16");
|
||||
EXPECT_DEATH(_mm_store_si128((__m128i*)p, value_wide),
|
||||
"located 0 bytes to the right of 12-byte");
|
||||
"located 0 bytes after 12-byte");
|
||||
free(a);
|
||||
}
|
||||
#endif
|
||||
|
@ -747,7 +747,7 @@ std::string RightOOBErrorMessage(int oob_distance, bool is_write) {
|
|||
#if !GTEST_USES_SIMPLE_RE
|
||||
"buffer-overflow.*%s.*"
|
||||
#endif
|
||||
"located %d bytes to the right",
|
||||
"located %d bytes after",
|
||||
#if !GTEST_USES_SIMPLE_RE
|
||||
is_write ? "WRITE" : "READ",
|
||||
#endif
|
||||
|
@ -771,7 +771,7 @@ std::string LeftOOBErrorMessage(int oob_distance, bool is_write) {
|
|||
#if !GTEST_USES_SIMPLE_RE
|
||||
ASAN_PCRE_DOTALL "%s.*"
|
||||
#endif
|
||||
"located %d bytes to the left",
|
||||
"located %d bytes before",
|
||||
#if !GTEST_USES_SIMPLE_RE
|
||||
is_write ? "WRITE" : "READ",
|
||||
#endif
|
||||
|
@ -790,7 +790,7 @@ std::string LeftOOBReadMessage(int oob_distance) {
|
|||
std::string LeftOOBAccessMessage(int oob_distance) {
|
||||
assert(oob_distance > 0);
|
||||
char expected_str[100];
|
||||
sprintf(expected_str, "located %d bytes to the left", oob_distance);
|
||||
sprintf(expected_str, "located %d bytes before", oob_distance);
|
||||
return std::string(expected_str);
|
||||
}
|
||||
|
||||
|
@ -812,7 +812,7 @@ char* MallocAndMemsetString(size_t size) {
|
|||
EXPECT_DEATH(READ_N_BYTES, \
|
||||
ASAN_PCRE_DOTALL \
|
||||
"AddressSanitizer: heap-buffer-overflow" \
|
||||
".* is located 0 bytes to the right of 10-byte region"); \
|
||||
".* is located 0 bytes after 10-byte region"); \
|
||||
close(fd); \
|
||||
delete [] x; \
|
||||
|
||||
|
@ -1013,23 +1013,23 @@ TEST(AddressSanitizer, GlobalTest) {
|
|||
glob5[Ident(4)] = 0;
|
||||
|
||||
EXPECT_DEATH(glob5[Ident(5)] = 0,
|
||||
"0 bytes to the right of global variable.*glob5.* size 5");
|
||||
"0 bytes after global variable.*glob5.* size 5");
|
||||
EXPECT_DEATH(glob5[Ident(5+6)] = 0,
|
||||
"6 bytes to the right of global variable.*glob5.* size 5");
|
||||
"6 bytes after global variable.*glob5.* size 5");
|
||||
Ident(static110); // avoid optimizations
|
||||
static110[Ident(0)] = 0;
|
||||
static110[Ident(109)] = 0;
|
||||
EXPECT_DEATH(static110[Ident(110)] = 0,
|
||||
"0 bytes to the right of global variable");
|
||||
"0 bytes after global variable");
|
||||
EXPECT_DEATH(static110[Ident(110+7)] = 0,
|
||||
"7 bytes to the right of global variable");
|
||||
"7 bytes after global variable");
|
||||
|
||||
Ident(func_static15); // avoid optimizations
|
||||
func_static15[Ident(0)] = 0;
|
||||
EXPECT_DEATH(func_static15[Ident(15)] = 0,
|
||||
"0 bytes to the right of global variable");
|
||||
"0 bytes after global variable");
|
||||
EXPECT_DEATH(func_static15[Ident(15 + 9)] = 0,
|
||||
"9 bytes to the right of global variable");
|
||||
"9 bytes after global variable");
|
||||
|
||||
Ident(fs1);
|
||||
Ident(fs2);
|
||||
|
@ -1037,12 +1037,12 @@ TEST(AddressSanitizer, GlobalTest) {
|
|||
|
||||
// We don't create left redzones, so this is not 100% guaranteed to fail.
|
||||
// But most likely will.
|
||||
EXPECT_DEATH(fs2[Ident(-1)] = 0, "is located.*of global variable");
|
||||
EXPECT_DEATH(fs2[Ident(-1)] = 0, "is located.* global variable");
|
||||
|
||||
EXPECT_DEATH(Ident(Ident(ConstGlob)[8]),
|
||||
"is located 1 bytes to the right of .*ConstGlob");
|
||||
"is located 1 bytes after .*ConstGlob");
|
||||
EXPECT_DEATH(Ident(Ident(StaticConstGlob)[5]),
|
||||
"is located 2 bytes to the right of .*StaticConstGlob");
|
||||
"is located 2 bytes after .*StaticConstGlob");
|
||||
|
||||
// call stuff from another file.
|
||||
GlobalsTest(0);
|
||||
|
|
|
@ -14,7 +14,7 @@
|
|||
|
||||
// Default ASAN_OPTIONS for the unit tests.
|
||||
extern "C" const char* __asan_default_options() {
|
||||
#if SANITIZER_MAC
|
||||
#if SANITIZER_APPLE
|
||||
// On Darwin, we default to `abort_on_error=1`, which would make tests run
|
||||
// much slower. Let's override this and run lit tests with 'abort_on_error=0'
|
||||
// and make sure we do not overwhelm the syslog while testing. Also, let's
|
||||
|
@ -33,21 +33,6 @@ extern "C" const char* __asan_default_options() {
|
|||
#endif
|
||||
}
|
||||
|
||||
namespace __sanitizer {
|
||||
bool ReexecDisabled() {
|
||||
#if __has_feature(address_sanitizer) && SANITIZER_MAC
|
||||
// Allow re-exec in instrumented unit tests on Darwin. Technically, we only
|
||||
// need this for 10.10 and below, where re-exec is required for the
|
||||
// interceptors to work, but to avoid duplicating the version detection logic,
|
||||
// let's just allow re-exec for all Darwin versions. On newer OS versions,
|
||||
// returning 'false' doesn't do anything anyway, because we don't re-exec.
|
||||
return false;
|
||||
#else
|
||||
return true;
|
||||
#endif
|
||||
}
|
||||
} // namespace __sanitizer
|
||||
|
||||
int main(int argc, char **argv) {
|
||||
testing::GTEST_FLAG(death_test_style) = "threadsafe";
|
||||
testing::InitGoogleTest(&argc, argv);
|
||||
|
|
|
@ -2,6 +2,13 @@ ___asan_default_options
|
|||
___asan_default_suppressions
|
||||
___asan_on_error
|
||||
___asan_set_shadow_00
|
||||
___asan_set_shadow_01
|
||||
___asan_set_shadow_02
|
||||
___asan_set_shadow_03
|
||||
___asan_set_shadow_04
|
||||
___asan_set_shadow_05
|
||||
___asan_set_shadow_06
|
||||
___asan_set_shadow_07
|
||||
___asan_set_shadow_f1
|
||||
___asan_set_shadow_f2
|
||||
___asan_set_shadow_f3
|
||||
|
|
|
@ -4,20 +4,40 @@
|
|||
|
||||
if (CMAKE_SOURCE_DIR STREQUAL CMAKE_CURRENT_SOURCE_DIR)
|
||||
cmake_minimum_required(VERSION 3.13.4)
|
||||
if ("${CMAKE_VERSION}" VERSION_LESS "3.20.0")
|
||||
message(WARNING
|
||||
"Your CMake version is ${CMAKE_VERSION}. Starting with LLVM 17.0.0, the "
|
||||
"minimum version of CMake required to build LLVM will become 3.20.0, and "
|
||||
"using an older CMake will become an error. Please upgrade your CMake to "
|
||||
"at least 3.20.0 now to avoid issues in the future!")
|
||||
endif()
|
||||
|
||||
set(CMAKE_TRY_COMPILE_TARGET_TYPE STATIC_LIBRARY)
|
||||
project(CompilerRTBuiltins C ASM)
|
||||
set(COMPILER_RT_STANDALONE_BUILD TRUE)
|
||||
set(COMPILER_RT_BUILTINS_STANDALONE_BUILD TRUE)
|
||||
|
||||
set(COMPILER_RT_SOURCE_DIR "${CMAKE_CURRENT_SOURCE_DIR}/../..")
|
||||
|
||||
set(LLVM_COMMON_CMAKE_UTILS "${COMPILER_RT_SOURCE_DIR}/../cmake")
|
||||
|
||||
# Add path for custom modules
|
||||
list(INSERT CMAKE_MODULE_PATH 0
|
||||
"${CMAKE_SOURCE_DIR}/../../cmake"
|
||||
"${CMAKE_SOURCE_DIR}/../../cmake/Modules")
|
||||
"${COMPILER_RT_SOURCE_DIR}/cmake"
|
||||
"${COMPILER_RT_SOURCE_DIR}/cmake/Modules"
|
||||
"${LLVM_COMMON_CMAKE_UTILS}"
|
||||
"${LLVM_COMMON_CMAKE_UTILS}/Modules"
|
||||
)
|
||||
|
||||
include(base-config-ix)
|
||||
include(CompilerRTUtils)
|
||||
|
||||
load_llvm_config()
|
||||
if (NOT LLVM_RUNTIMES_BUILD)
|
||||
load_llvm_config()
|
||||
endif()
|
||||
construct_compiler_rt_default_triple()
|
||||
|
||||
include(SetPlatformToolchainTools)
|
||||
if(APPLE)
|
||||
include(CompilerRTDarwinUtils)
|
||||
endif()
|
||||
|
@ -25,15 +45,6 @@ if (CMAKE_SOURCE_DIR STREQUAL CMAKE_CURRENT_SOURCE_DIR)
|
|||
include(UseLibtool)
|
||||
endif()
|
||||
include(AddCompilerRT)
|
||||
|
||||
if(${CMAKE_SYSTEM_NAME} MATCHES "AIX")
|
||||
set(CMAKE_C_ARCHIVE_CREATE "<CMAKE_AR> -X32_64 qc <TARGET> <LINK_FLAGS> <OBJECTS>")
|
||||
set(CMAKE_CXX_ARCHIVE_CREATE "<CMAKE_AR> -X32_64 qc <TARGET> <LINK_FLAGS> <OBJECTS>")
|
||||
set(CMAKE_C_ARCHIVE_APPEND "<CMAKE_AR> -X32_64 q <TARGET> <LINK_FLAGS> <OBJECTS>")
|
||||
set(CMAKE_CXX_ARCHIVE_APPEND "<CMAKE_AR> -X32_64 q <TARGET> <LINK_FLAGS> <OBJECTS>")
|
||||
set(CMAKE_C_ARCHIVE_FINISH "<CMAKE_RANLIB> -X32_64 <TARGET>")
|
||||
set(CMAKE_CXX_ARCHIVE_FINISH "<CMAKE_RANLIB> -X32_64 <TARGET>")
|
||||
endif()
|
||||
endif()
|
||||
|
||||
if (COMPILER_RT_STANDALONE_BUILD)
|
||||
|
@ -47,6 +58,7 @@ if (COMPILER_RT_STANDALONE_BUILD)
|
|||
endif()
|
||||
|
||||
include(builtin-config-ix)
|
||||
include(CMakePushCheckState)
|
||||
|
||||
if(${CMAKE_SYSTEM_NAME} MATCHES "AIX")
|
||||
include(CompilerRTAIXUtils)
|
||||
|
@ -179,6 +191,12 @@ set(GENERIC_SOURCES
|
|||
umodti3.c
|
||||
)
|
||||
|
||||
# We only build BF16 files when "__bf16" is available.
|
||||
set(BF16_SOURCES
|
||||
truncdfbf2.c
|
||||
truncsfbf2.c
|
||||
)
|
||||
|
||||
# TODO: Several "tf" files (and divtc3.c, but not multc3.c) are in
|
||||
# GENERIC_SOURCES instead of here.
|
||||
set(GENERIC_TF_SOURCES
|
||||
|
@ -362,7 +380,9 @@ else () # MSVC
|
|||
set(i386_SOURCES ${GENERIC_SOURCES} ${x86_ARCH_SOURCES})
|
||||
endif () # if (NOT MSVC)
|
||||
|
||||
set(arm_SOURCES
|
||||
|
||||
# builtin support for Targets that have Arm state or have Thumb2
|
||||
set(arm_or_thumb2_base_SOURCES
|
||||
arm/fp_mode.c
|
||||
arm/bswapdi2.S
|
||||
arm/bswapsi2.S
|
||||
|
@ -372,6 +392,13 @@ set(arm_SOURCES
|
|||
arm/divmodsi4.S
|
||||
arm/divsi3.S
|
||||
arm/modsi3.S
|
||||
arm/udivmodsi4.S
|
||||
arm/udivsi3.S
|
||||
arm/umodsi3.S
|
||||
${GENERIC_SOURCES}
|
||||
)
|
||||
|
||||
set(arm_sync_SOURCES
|
||||
arm/sync_fetch_and_add_4.S
|
||||
arm/sync_fetch_and_add_8.S
|
||||
arm/sync_fetch_and_and_4.S
|
||||
|
@ -392,13 +419,11 @@ set(arm_SOURCES
|
|||
arm/sync_fetch_and_umin_8.S
|
||||
arm/sync_fetch_and_xor_4.S
|
||||
arm/sync_fetch_and_xor_8.S
|
||||
arm/udivmodsi4.S
|
||||
arm/udivsi3.S
|
||||
arm/umodsi3.S
|
||||
${GENERIC_SOURCES}
|
||||
)
|
||||
|
||||
set(thumb1_SOURCES
|
||||
# builtin support for Thumb-only targets with very limited Thumb2 technology,
|
||||
# such as v6-m and v8-m.baseline
|
||||
set(thumb1_base_SOURCES
|
||||
arm/divsi3.S
|
||||
arm/udivsi3.S
|
||||
arm/comparesf2.S
|
||||
|
@ -477,6 +502,8 @@ set(arm_Thumb1_VFPv2_SP_SOURCES
|
|||
set(arm_Thumb1_icache_SOURCES
|
||||
arm/sync_synchronize.S
|
||||
)
|
||||
|
||||
# thumb1 calling into Arm to cover support
|
||||
set(arm_Thumb1_SOURCES
|
||||
${arm_Thumb1_JT_SOURCES}
|
||||
${arm_Thumb1_SjLj_EH_SOURCES}
|
||||
|
@ -485,6 +512,13 @@ set(arm_Thumb1_SOURCES
|
|||
${arm_Thumb1_icache_SOURCES}
|
||||
)
|
||||
|
||||
# base functionality for Arm Targets prior to Arm v7-a and Armv6-m such as v6,
|
||||
# v5t, v4t
|
||||
set(arm_min_SOURCES
|
||||
${arm_or_thumb2_base_SOURCES}
|
||||
${arm_EABI_SOURCES}
|
||||
)
|
||||
|
||||
if(MINGW)
|
||||
set(arm_SOURCES
|
||||
arm/aeabi_idivmod.S
|
||||
|
@ -492,19 +526,24 @@ if(MINGW)
|
|||
arm/aeabi_uidivmod.S
|
||||
arm/aeabi_uldivmod.S
|
||||
arm/chkstk.S
|
||||
mingw_fixfloat.c
|
||||
${arm_SOURCES}
|
||||
${arm_or_thumb2_base_SOURCES}
|
||||
${arm_sync_SOURCES}
|
||||
)
|
||||
|
||||
set(thumb1_SOURCES
|
||||
${thumb1_base_SOURCES}
|
||||
)
|
||||
elseif(NOT WIN32)
|
||||
# TODO the EABI sources should only be added to EABI targets
|
||||
set(arm_SOURCES
|
||||
${arm_SOURCES}
|
||||
${arm_or_thumb2_base_SOURCES}
|
||||
${arm_sync_SOURCES}
|
||||
${arm_EABI_SOURCES}
|
||||
${arm_Thumb1_SOURCES}
|
||||
)
|
||||
|
||||
set(thumb1_SOURCES
|
||||
${thumb1_SOURCES}
|
||||
${thumb1_base_SOURCES}
|
||||
${arm_EABI_SOURCES}
|
||||
)
|
||||
endif()
|
||||
|
@ -551,6 +590,9 @@ if (MINGW)
|
|||
)
|
||||
endif()
|
||||
|
||||
set(armv4t_SOURCES ${arm_min_SOURCES})
|
||||
set(armv5te_SOURCES ${arm_min_SOURCES})
|
||||
set(armv6_SOURCES ${arm_min_SOURCES})
|
||||
set(armhf_SOURCES ${arm_SOURCES})
|
||||
set(armv7_SOURCES ${arm_SOURCES})
|
||||
set(armv7s_SOURCES ${arm_SOURCES})
|
||||
|
@ -566,6 +608,18 @@ set(armv7em_SOURCES ${arm_SOURCES})
|
|||
set(armv8m.main_SOURCES ${arm_SOURCES})
|
||||
set(armv8.1m.main_SOURCES ${arm_SOURCES})
|
||||
|
||||
# 8-bit AVR MCU
|
||||
set(avr_SOURCES
|
||||
avr/mulqi3.S
|
||||
avr/mulhi3.S
|
||||
avr/exit.S
|
||||
avr/divmodhi4.S
|
||||
avr/udivmodhi4.S
|
||||
avr/divmodqi4.S
|
||||
avr/udivmodqi4.S
|
||||
${GENERIC_SOURCES}
|
||||
)
|
||||
|
||||
# hexagon arch
|
||||
set(hexagon_SOURCES
|
||||
hexagon/common_entry_exit_abi1.S
|
||||
|
@ -598,6 +652,14 @@ set(hexagon_SOURCES
|
|||
${GENERIC_TF_SOURCES}
|
||||
)
|
||||
|
||||
set(loongarch_SOURCES
|
||||
loongarch/fp_mode.c
|
||||
${GENERIC_SOURCES}
|
||||
${GENERIC_TF_SOURCES}
|
||||
)
|
||||
set(loongarch64_SOURCES
|
||||
${loongarch_SOURCES}
|
||||
)
|
||||
|
||||
set(mips_SOURCES ${GENERIC_SOURCES})
|
||||
set(mipsel_SOURCES ${mips_SOURCES})
|
||||
|
@ -608,6 +670,8 @@ set(mips64el_SOURCES ${GENERIC_TF_SOURCES}
|
|||
|
||||
set(powerpc_SOURCES ${GENERIC_SOURCES})
|
||||
|
||||
set(powerpcspe_SOURCES ${GENERIC_SOURCES})
|
||||
|
||||
set(powerpc64_SOURCES
|
||||
ppc/divtc3.c
|
||||
ppc/fixtfdi.c
|
||||
|
@ -633,6 +697,7 @@ endif()
|
|||
set(powerpc64le_SOURCES ${powerpc64_SOURCES})
|
||||
|
||||
set(riscv_SOURCES
|
||||
riscv/fp_mode.c
|
||||
riscv/save.S
|
||||
riscv/restore.S
|
||||
${GENERIC_SOURCES}
|
||||
|
@ -674,8 +739,11 @@ if (APPLE)
|
|||
darwin_add_builtin_libraries(${BUILTIN_SUPPORTED_OS})
|
||||
else ()
|
||||
set(BUILTIN_CFLAGS "")
|
||||
add_security_warnings(BUILTIN_CFLAGS 0)
|
||||
|
||||
append_list_if(COMPILER_RT_HAS_FLOAT16 -DCOMPILER_RT_HAS_FLOAT16 BUILTIN_CFLAGS)
|
||||
if (COMPILER_RT_HAS_FCF_PROTECTION_FLAG)
|
||||
append_list_if(COMPILER_RT_ENABLE_CET -fcf-protection=full BUILTIN_CFLAGS)
|
||||
endif()
|
||||
|
||||
append_list_if(COMPILER_RT_HAS_STD_C11_FLAG -std=c11 BUILTIN_CFLAGS)
|
||||
|
||||
|
@ -700,11 +768,19 @@ else ()
|
|||
append_list_if(COMPILER_RT_HAS_VISIBILITY_HIDDEN_FLAG VISIBILITY_HIDDEN BUILTIN_DEFS)
|
||||
endif()
|
||||
|
||||
if(COMPILER_RT_DISABLE_AARCH64_FMV)
|
||||
list(APPEND BUILTIN_DEFS DISABLE_AARCH64_FMV)
|
||||
endif()
|
||||
|
||||
append_list_if(COMPILER_RT_HAS_ASM_LSE HAS_ASM_LSE BUILTIN_DEFS)
|
||||
|
||||
foreach (arch ${BUILTIN_SUPPORTED_ARCH})
|
||||
if (CAN_TARGET_${arch})
|
||||
cmake_push_check_state()
|
||||
# TODO: we should probably make most of the checks in builtin-config depend on the target flags.
|
||||
message(STATUS "Performing additional configure checks with target flags: ${TARGET_${arch}_CFLAGS}")
|
||||
set(BUILTIN_CFLAGS_${arch} ${BUILTIN_CFLAGS})
|
||||
list(APPEND CMAKE_REQUIRED_FLAGS ${TARGET_${arch}_CFLAGS} ${BUILTIN_CFLAGS_${arch}})
|
||||
# For ARM archs, exclude any VFP builtins if VFP is not supported
|
||||
if (${arch} MATCHES "^(arm|armhf|armv7|armv7s|armv7k|armv7m|armv7em|armv8m.main|armv8.1m.main)$")
|
||||
string(REPLACE ";" " " _TARGET_${arch}_CFLAGS "${TARGET_${arch}_CFLAGS}")
|
||||
|
@ -717,12 +793,21 @@ else ()
|
|||
SOURCE "#if !(__ARM_FP & 0x8)
|
||||
#error No double-precision support!
|
||||
#endif
|
||||
int main() { return 0; }")
|
||||
int main(void) { return 0; }")
|
||||
if(NOT COMPILER_RT_HAS_${arch}_VFP_DP)
|
||||
list(REMOVE_ITEM ${arch}_SOURCES ${arm_Thumb1_VFPv2_DP_SOURCES})
|
||||
endif()
|
||||
endif()
|
||||
endif()
|
||||
check_c_source_compiles("_Float16 foo(_Float16 x) { return x; }"
|
||||
COMPILER_RT_HAS_${arch}_FLOAT16)
|
||||
append_list_if(COMPILER_RT_HAS_${arch}_FLOAT16 -DCOMPILER_RT_HAS_FLOAT16 BUILTIN_CFLAGS_${arch})
|
||||
check_c_source_compiles("__bf16 foo(__bf16 x) { return x; }"
|
||||
COMPILER_RT_HAS_${arch}_BFLOAT16)
|
||||
# Build BF16 files only when "__bf16" is available.
|
||||
if(COMPILER_RT_HAS_${arch}_BFLOAT16)
|
||||
list(APPEND ${arch}_SOURCES ${BF16_SOURCES})
|
||||
endif()
|
||||
|
||||
# Remove a generic C builtin when an arch-specific builtin is specified.
|
||||
filter_builtin_sources(${arch}_SOURCES ${arch})
|
||||
|
@ -757,6 +842,7 @@ else ()
|
|||
DEFS ${BUILTIN_DEFS}
|
||||
CFLAGS ${BUILTIN_CFLAGS_${arch}}
|
||||
PARENT_TARGET builtins)
|
||||
cmake_pop_check_state()
|
||||
endif ()
|
||||
endforeach ()
|
||||
endif ()
|
||||
|
@ -796,7 +882,7 @@ if(COMPILER_RT_BUILD_STANDALONE_LIBATOMIC)
|
|||
# archive, i.e., libatomic.a. Once cmake adds support of such usage for AIX,
|
||||
# this ad-hoc part can be removed.
|
||||
if(${CMAKE_SYSTEM_NAME} MATCHES "AIX")
|
||||
archive_aix_libatomic(clang_rt.atomic
|
||||
archive_aix_libatomic(clang_rt.atomic libatomic
|
||||
ARCHS ${BUILTIN_SUPPORTED_ARCH}
|
||||
PARENT_TARGET builtins-standalone-atomic)
|
||||
endif()
|
||||
|
|
|
@ -271,8 +271,8 @@ switchu8
|
|||
|
||||
// There is no C interface to the *_vfp_d8_d15_regs functions. There are
|
||||
// called in the prolog and epilog of Thumb1 functions. When the C++ ABI use
|
||||
// SJLJ for exceptions, each function with a catch clause or destuctors needs
|
||||
// to save and restore all registers in it prolog and epliog. But there is
|
||||
// SJLJ for exceptions, each function with a catch clause or destructors needs
|
||||
// to save and restore all registers in it prolog and epilog. But there is
|
||||
// no way to access vector and high float registers from thumb1 code, so the
|
||||
// compiler must add call outs to these helper functions in the prolog and
|
||||
// epilog.
|
||||
|
@ -311,9 +311,9 @@ double __floatsidfvfp(int a); // Appears to convert from
|
|||
float __floatsisfvfp(int a); // Appears to convert from
|
||||
// int to float.
|
||||
double __floatunssidfvfp(unsigned int a); // Appears to convert from
|
||||
// unisgned int to double.
|
||||
// unsigned int to double.
|
||||
float __floatunssisfvfp(unsigned int a); // Appears to convert from
|
||||
// unisgned int to float.
|
||||
// unsigned int to float.
|
||||
int __gedf2vfp(double a, double b); // Appears to return __gedf2
|
||||
// (a >= b)
|
||||
int __gesf2vfp(float a, float b); // Appears to return __gesf2
|
||||
|
|
|
@ -27,7 +27,7 @@ CRT_FE_ROUND_MODE __attribute__((weak)) __aarch64_fe_default_rmode =
|
|||
CRT_FE_TONEAREST;
|
||||
#endif
|
||||
|
||||
CRT_FE_ROUND_MODE __fe_getround() {
|
||||
CRT_FE_ROUND_MODE __fe_getround(void) {
|
||||
#ifdef __ARM_FP
|
||||
uint64_t fpcr;
|
||||
__asm__ __volatile__("mrs %0, fpcr" : "=r" (fpcr));
|
||||
|
@ -48,7 +48,7 @@ CRT_FE_ROUND_MODE __fe_getround() {
|
|||
#endif
|
||||
}
|
||||
|
||||
int __fe_raise_inexact() {
|
||||
int __fe_raise_inexact(void) {
|
||||
#ifdef __ARM_FP
|
||||
uint64_t fpsr;
|
||||
__asm__ __volatile__("mrs %0, fpsr" : "=r" (fpsr));
|
||||
|
|
|
@ -138,13 +138,13 @@ NOT_HERE_BEFORE_10_6(__udivti3)
|
|||
NOT_HERE_BEFORE_10_6(__umoddi3)
|
||||
NOT_HERE_BEFORE_10_6(__umodti3)
|
||||
|
||||
#if __ppc__
|
||||
#if __powerpc__
|
||||
NOT_HERE_BEFORE_10_6(__gcc_qadd)
|
||||
NOT_HERE_BEFORE_10_6(__gcc_qdiv)
|
||||
NOT_HERE_BEFORE_10_6(__gcc_qmul)
|
||||
NOT_HERE_BEFORE_10_6(__gcc_qsub)
|
||||
NOT_HERE_BEFORE_10_6(__trampoline_setup)
|
||||
#endif // __ppc__
|
||||
#endif // __powerpc__
|
||||
|
||||
NOT_HERE_IN_10_8_AND_EARLIER(__atomic_compare_exchange)
|
||||
NOT_HERE_IN_10_8_AND_EARLIER(__atomic_compare_exchange_1)
|
||||
|
|
|
@ -27,7 +27,7 @@ CRT_FE_ROUND_MODE __attribute__((weak)) __arm_fe_default_rmode =
|
|||
CRT_FE_TONEAREST;
|
||||
#endif
|
||||
|
||||
CRT_FE_ROUND_MODE __fe_getround() {
|
||||
CRT_FE_ROUND_MODE __fe_getround(void) {
|
||||
#ifdef __ARM_FP
|
||||
uint32_t fpscr;
|
||||
__asm__ __volatile__("vmrs %0, fpscr" : "=r" (fpscr));
|
||||
|
@ -48,7 +48,7 @@ CRT_FE_ROUND_MODE __fe_getround() {
|
|||
#endif
|
||||
}
|
||||
|
||||
int __fe_raise_inexact() {
|
||||
int __fe_raise_inexact(void) {
|
||||
#ifdef __ARM_FP
|
||||
uint32_t fpscr;
|
||||
__asm__ __volatile__("vmrs %0, fpscr" : "=r" (fpscr));
|
||||
|
|
|
@ -14,35 +14,41 @@
|
|||
|
||||
#include "../assembly.h"
|
||||
|
||||
#if __ARM_ARCH >= 7
|
||||
#define DMB dmb
|
||||
#elif __ARM_ARCH >= 6
|
||||
#define DMB mcr p15, #0, r0, c7, c10, #5
|
||||
#else
|
||||
#error DMB is only supported on ARMv6+
|
||||
#endif
|
||||
|
||||
#define SYNC_OP_4(op) \
|
||||
.p2align 2; \
|
||||
.thumb; \
|
||||
.syntax unified; \
|
||||
DEFINE_COMPILERRT_THUMB_FUNCTION(__sync_fetch_and_##op) \
|
||||
dmb; \
|
||||
DEFINE_COMPILERRT_FUNCTION(__sync_fetch_and_##op) \
|
||||
DMB; \
|
||||
mov r12, r0; \
|
||||
LOCAL_LABEL(tryatomic_##op) : ldrex r0, [r12]; \
|
||||
op(r2, r0, r1); \
|
||||
strex r3, r2, [r12]; \
|
||||
cmp r3, #0; \
|
||||
bne LOCAL_LABEL(tryatomic_##op); \
|
||||
dmb; \
|
||||
DMB; \
|
||||
bx lr
|
||||
|
||||
#define SYNC_OP_8(op) \
|
||||
.p2align 2; \
|
||||
.thumb; \
|
||||
.syntax unified; \
|
||||
DEFINE_COMPILERRT_THUMB_FUNCTION(__sync_fetch_and_##op) \
|
||||
DEFINE_COMPILERRT_FUNCTION(__sync_fetch_and_##op) \
|
||||
push {r4, r5, r6, lr}; \
|
||||
dmb; \
|
||||
DMB; \
|
||||
mov r12, r0; \
|
||||
LOCAL_LABEL(tryatomic_##op) : ldrexd r0, r1, [r12]; \
|
||||
op(r4, r5, r0, r1, r2, r3); \
|
||||
strexd r6, r4, r5, [r12]; \
|
||||
cmp r6, #0; \
|
||||
bne LOCAL_LABEL(tryatomic_##op); \
|
||||
dmb; \
|
||||
DMB; \
|
||||
pop { r4, r5, r6, pc }
|
||||
|
||||
#define MINMAX_4(rD, rN, rM, cmp_kind) \
|
||||
|
|
|
@ -11,9 +11,9 @@
|
|||
//
|
||||
// extern float __truncdfsf2vfp(double a);
|
||||
//
|
||||
// Converts double precision float to signle precision result.
|
||||
// Converts double precision float to single precision result.
|
||||
// Uses Darwin calling convention where a double precision parameter is
|
||||
// passed in a R0/R1 pair and a signle precision result is returned in R0.
|
||||
// passed in a R0/R1 pair and a single precision result is returned in R0.
|
||||
//
|
||||
.syntax unified
|
||||
.p2align 2
|
||||
|
|
|
@ -14,6 +14,12 @@
|
|||
#ifndef COMPILERRT_ASSEMBLY_H
|
||||
#define COMPILERRT_ASSEMBLY_H
|
||||
|
||||
#if defined(__linux__) && defined(__CET__)
|
||||
#if __has_include(<cet.h>)
|
||||
#include <cet.h>
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#if defined(__APPLE__) && defined(__aarch64__)
|
||||
#define SEPARATOR %%
|
||||
#else
|
||||
|
|
|
@ -92,6 +92,8 @@ __inline static void lock(Lock *l) { OSSpinLockLock(l); }
|
|||
static Lock locks[SPINLOCK_COUNT]; // initialized to OS_SPINLOCK_INIT which is 0
|
||||
|
||||
#else
|
||||
_Static_assert(__atomic_always_lock_free(sizeof(uintptr_t), 0),
|
||||
"Implementation assumes lock-free pointer-size cmpxchg");
|
||||
typedef _Atomic(uintptr_t) Lock;
|
||||
/// Unlock a lock. This is a release operation.
|
||||
__inline static void unlock(Lock *l) {
|
||||
|
@ -336,6 +338,18 @@ OPTIMISED_CASES
|
|||
return tmp; \
|
||||
}
|
||||
|
||||
#define ATOMIC_RMW_NAND(n, lockfree, type) \
|
||||
type __atomic_fetch_nand_##n(type *ptr, type val, int model) { \
|
||||
if (lockfree(ptr)) \
|
||||
return __c11_atomic_fetch_nand((_Atomic(type) *)ptr, val, model); \
|
||||
Lock *l = lock_for_pointer(ptr); \
|
||||
lock(l); \
|
||||
type tmp = *ptr; \
|
||||
*ptr = ~(tmp & val); \
|
||||
unlock(l); \
|
||||
return tmp; \
|
||||
}
|
||||
|
||||
#define OPTIMISED_CASE(n, lockfree, type) ATOMIC_RMW(n, lockfree, type, add, +)
|
||||
OPTIMISED_CASES
|
||||
#undef OPTIMISED_CASE
|
||||
|
@ -351,3 +365,9 @@ OPTIMISED_CASES
|
|||
#define OPTIMISED_CASE(n, lockfree, type) ATOMIC_RMW(n, lockfree, type, xor, ^)
|
||||
OPTIMISED_CASES
|
||||
#undef OPTIMISED_CASE
|
||||
// Allow build with clang without __c11_atomic_fetch_nand builtin (pre-14)
|
||||
#if __has_builtin(__c11_atomic_fetch_nand)
|
||||
#define OPTIMISED_CASE(n, lockfree, type) ATOMIC_RMW_NAND(n, lockfree, type)
|
||||
OPTIMISED_CASES
|
||||
#undef OPTIMISED_CASE
|
||||
#endif
|
||||
|
|
57
gnu/llvm/compiler-rt/lib/builtins/avr/divmodhi4.S
Normal file
57
gnu/llvm/compiler-rt/lib/builtins/avr/divmodhi4.S
Normal file
|
@ -0,0 +1,57 @@
|
|||
//===------------- divmodhi4.S - sint16 div & mod -------------------------===//
|
||||
//
|
||||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
||||
// See https://llvm.org/LICENSE.txt for license information.
|
||||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// As described at
|
||||
// https://gcc.gnu.org/wiki/avr-gcc#Exceptions_to_the_Calling_Convention, the
|
||||
// prototype is `struct {sint16, sint16} __divmodhi4(sint16, sint16)`.
|
||||
// The sint16 quotient is returned via R23:R22, and the sint16 remainder is
|
||||
// returned via R25:R24, while registers R21/R26/27/Rtmp and bit T in SREG
|
||||
// are clobbered.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
.text
|
||||
.align 2
|
||||
|
||||
#ifdef __AVR_TINY__
|
||||
.set __tmp_reg__, 16
|
||||
#else
|
||||
.set __tmp_reg__, 0
|
||||
#endif
|
||||
|
||||
.globl __divmodhi4
|
||||
.type __divmodhi4, @function
|
||||
|
||||
__divmodhi4:
|
||||
bst r25, 7
|
||||
mov __tmp_reg__, r23
|
||||
brtc __divmodhi4_a
|
||||
com __tmp_reg__
|
||||
rcall __divmodhi4_b
|
||||
|
||||
__divmodhi4_a:
|
||||
sbrc r23, 7
|
||||
rcall __divmodhi4_c
|
||||
rcall __udivmodhi4 ; Call __udivmodhi4 to do real calculation.
|
||||
sbrc __tmp_reg__, 7
|
||||
rcall __divmodhi4_c
|
||||
brtc __divmodhi4_exit
|
||||
|
||||
__divmodhi4_b:
|
||||
com r25
|
||||
neg r24
|
||||
sbci r25, 255
|
||||
ret ; Return quotient via R23:R22 and remainder via R25:R24.
|
||||
|
||||
__divmodhi4_c:
|
||||
com r23
|
||||
neg r22
|
||||
sbci r23, 255
|
||||
|
||||
__divmodhi4_exit:
|
||||
ret ; Return quotient via R23:R22 and remainder via R25:r24.
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Add a link
Reference in a new issue