sync with OpenBSD -current

This commit is contained in:
purplerain 2024-01-26 22:08:02 +00:00
parent 25f7188861
commit 8ff00f10fc
Signed by: purplerain
GPG key ID: F42C07F07E2E35B7
2137 changed files with 177389 additions and 104447 deletions

View file

@ -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>

View file

@ -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

View file

@ -1,2 +1,2 @@
major=9
major=10
minor=0

View file

@ -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}

View file

@ -1,3 +1,3 @@
# Don't forget to give libc++ the same type of bump!
major=6
major=7
minor=0

View file

@ -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 \

View file

@ -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)

View file

@ -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

View file

@ -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
)

View file

@ -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()

View file

@ -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}")

View 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()

View file

@ -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()

View file

@ -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

View file

@ -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)

View file

@ -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()

View file

@ -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()

View file

@ -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)

View file

@ -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()

View file

@ -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")

View file

@ -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")

View file

@ -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)

View file

@ -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()

View 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()

View file

@ -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

View file

@ -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

View file

@ -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;
}

View file

@ -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

View 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)

View 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

View file

@ -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

View file

@ -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.
///

View file

@ -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

View file

@ -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. */

View file

@ -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

View file

@ -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()

View file

@ -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

View file

@ -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;

View file

@ -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

View file

@ -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.

View file

@ -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;
}

View file

@ -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,

View file

@ -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(),

View file

@ -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

View file

@ -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"

View file

@ -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) {

View file

@ -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,

View file

@ -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.

View file

@ -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];

View file

@ -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

View file

@ -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

View file

@ -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()) { \

View file

@ -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

View file

@ -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)

View file

@ -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);

View file

@ -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;

View file

@ -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

View file

@ -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

View file

@ -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);
}

View file

@ -12,7 +12,7 @@
//===----------------------------------------------------------------------===//
#include "sanitizer_common/sanitizer_platform.h"
#if SANITIZER_MAC
#if SANITIZER_APPLE
#include "asan_interceptors.h"
#include "asan_report.h"

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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);

View file

@ -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;

View file

@ -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

View file

@ -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

View file

@ -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;
}

View file

@ -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);

View file

@ -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() {

View 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

View 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

View file

@ -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();

View file

@ -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();
}

View file

@ -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

View file

@ -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; }

View file

@ -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

View file

@ -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.

View file

@ -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.

View file

@ -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}>

View file

@ -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);
}

View file

@ -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);

View file

@ -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),

View file

@ -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

View file

@ -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;
}

View file

@ -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));
}

View file

@ -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);

View file

@ -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);

View file

@ -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

View file

@ -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()

View file

@ -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

View file

@ -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));

View file

@ -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)

View file

@ -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));

View file

@ -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) \

View file

@ -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

View file

@ -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

View file

@ -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

View 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