mirror of
https://https.git.savannah.gnu.org/git/gnulib.git
synced 2026-05-13 15:13:36 +00:00
M = Move variable declaration to its initialization. R = Reduce scope. S = Split scope, create separate variables from one variable. B = Insert braces, creating a block scope. O = Change order of initializations. * lib/accept4.c (accept4): M. * lib/acl-internal.c (acl_ace_nontrivial): R. * lib/acosl.c (acosl): MS. * lib/af_alg.c (afalg_stream): B. * lib/alignalloc.h (alignalloc): R. * lib/alloca.c (find_stack_direction): M. (alloca): M. * lib/amemxfrm.c (amemxfrm): MR. * lib/arcfour.c (arcfour_stream): MB. (arcfour_setkey): MB. * lib/arctwo.c (arctwo_encrypt): M. (arctwo_decrypt): M. (arctwo_setkey_ekb): M. * lib/areadlink-with-size.c (areadlink_with_size): MR. * lib/areadlinkat-with-size.c (areadlinkat_with_size): MR. * lib/argmatch.c (argmatch): MO. (main): RBO. * lib/argp-fmtstream.c (__argp_make_fmtstream): M. (__argp_fmtstream_update): M. (__argp_fmtstream_ensure): R. (__argp_fmtstream_printf): R. * lib/argp-fmtstream.h (__argp_fmtstream_set_lmargin): M. (__argp_fmtstream_set_rmargin): M. (__argp_fmtstream_set_wmargin): M. * lib/argp-help.c (validate_uparams): M. (fill_in_uparams): MR. (make_hol): MRSO. (hol_entry_short_iterate): R. (hol_entry_long_iterate): R. (hol_entry_first_long): Rename 'num' to 'nopts'. (canon_doc_option): M. (hol_append): MR. (argp_hol): O. (hol_entry_help): RSBO. (hol_help): RB. (usage_argful_short_opt): R. (usage_long_opt): R. (hol_usage): SB. (argp_args_levels): R. (argp_args_usage): MRB. (argp_doc): RBO. (_help): MR. (__argp_error): R. * lib/argp-parse.c (group_parse): M. (parser_init): MRB. (parser_finalize): MS. (parser_parse_next): R. (__argp_parse): MR. (__argp_input): M. * lib/argz.c (argz_add_sep): M. (argz_create_sep): M. (argz_create): R. (argz_replace): RB. * lib/asinl.c (asinl): MRS. * lib/asnprintf.c (asnprintf): M. * lib/asnwprintf.c (asnwprintf): M. * lib/asprintf.c (asprintf): M. * lib/astrxfrm.c (astrxfrm): MR. * lib/aszprintf.c (aszprintf): M. * lib/at-func.c (AT_FUNC_NAME): MR. * lib/at-func2.c (at_func2): MRS. * lib/atanl.c (atanl): MRS. * lib/backupfile.c (numbered_backup): R. * lib/base32.c (decode_8): R. (base32_decode_ctx): R. * lib/base64.c (decode_4): R. (base64_decode_ctx): R. * lib/basename-lgpl.c (last_component): R. (base_len): RO. * lib/bitset.c (bitset_copy_): R. * lib/bitset/list.c (lbitset_prune): MR. (lbitset_weed): MR. (lbitset_list): SB. * lib/bitset/table.c (tbitset_list): SB. * lib/boot-time-aux.h (get_windows_boot_time_fallback): R. * lib/btoc32.c (btoc32): R. * lib/c-asprintf.c (c_asprintf): M. * lib/c-aszprintf.c (c_aszprintf): M. * lib/c-snprintf.c (c_snprintf): M. * lib/c-snzprintf.c (c_snzprintf): M. * lib/c-strcasecmp.c (c_strcasecmp): R. * lib/c-strcasestr.c (c_strcasestr): MRSB. * lib/c-strncasecmp.c (c_strncasecmp): R. * lib/c-strtod.c (C_STRTOD): R. * lib/c-vsnzprintf.c (c_vsnzprintf): M. * lib/c-xasprintf.c (c_xasprintf): M. * lib/c32tob.c (c32tob): R. * lib/canon-host.c (canon_host_r): MR. * lib/canonicalize.c (canonicalize_filename_mode_stk): R. * lib/canonicalize-lgpl.c (realpath_stk): R. * lib/cbrt.c (cbrt): M. * lib/cbrtf.c (cbrtf): M. * lib/cbrtl.c (cbrtl): MR. * lib/chdir-long.c (chdir_long): M. (main): MR. * lib/classpath.c (new_classpath): MB. * lib/clean-temp.c (create_temp_dir): M. (unregister_temp_file): M. (unregister_temp_subdir): M. (cleanup_temp_file): M. (cleanup_temp_subdir): M. (cleanup_temp_dir_contents): MSB. (open_temp): R. (fopen_temp): R. (close_temp): RB. (fclose_variant_temp): RB. * lib/clean-temp-simple.c (cleanup_action): MSB. (cleanup_temporary_file): M. * lib/copy-file.c (copy_file_internal): MRB. * lib/cosl.c (cosl): MR. * lib/crc-generate-table.c (make_crc_table): M. * lib/crc-x86_64-pclmul.c (crc32_update_no_xor_pclmul): MRSB. * lib/crc.c (crc32_update_no_xor_slice_by_8): S. (crc32_update_no_xor_slice_by_n): M. (crc32_update_no_xor): MR. * lib/csharpcomp.c (compile_csharp_using_mono): MRB. (compile_csharp_using_dotnet): MRSB. (compile_csharp_using_sscli): MRB. * lib/csharpexec.c (execute_csharp_using_mono): MO. (execute_csharp_using_dotnet): MO. (execute_csharp_using_sscli): MO. (execute_csharp_program): R. * lib/cygpath.c (execute_and_read_line): M. * lib/des.c (gl_des_is_weak_key): M. (gl_3des_ecb_crypt): MO. * lib/dfa.c (closure): B. (dfamust): MRB. * lib/di-set.c (map_device): M. (di_set_insert): M. (di_set_lookup): M. * lib/dirname-lgpl.c (dir_len): R. * lib/dprintf.c (dprintf): M. * lib/dup.c (dup_nothrow): R. * lib/dup2.c (ms_windows_dup2): M. (klibc_dup2dirfd): M. (klibc_dup2): MR. (rpl_dup2): M. * lib/dup3.c (dup3): M. * lib/duplocale.c (duplocale): MRSB. * lib/dzprintf.c (dzprintf): M. * lib/euidaccess.c (euidaccess): MR. (main): M. * lib/exclude.c (add_exclude): R. * lib/execl.c (execl): SB. * lib/execle.c (execle): SB. * lib/execlp.c (execlp): SB. * lib/execute.c (execute): R. * lib/fchdir.c (ensure_dirs_slot): M. (get_name): M. (_gl_register_fd): R. * lib/fclose.c (rpl_fclose): MR. * lib/fcntl.c (dupfd): RO. (fcntl): R. (klibc_dupdirfd): M. (klibc_fcntl): MRSB. * lib/fdopen.c (rpl_fdopen): M. * lib/file-has-acl.c (get_aclinfo): R. (fdfile_has_aclinfo): MR. * lib/file-remote.c (main): M. * lib/file-set.c (record_file): M. (seen_file): R. * lib/findprog.c (find_in_path): MR. * lib/findprog-in.c (find_in_given_path): MR. * lib/flock.c (do_lock): MR. (do_unlock): M. (flock): MR. * lib/fma.c (decode): M. * lib/fopen.c (rpl_fopen): MR. * lib/forkpty.c (forkpty): M. * lib/fprintf.c (fprintf): M. * lib/freadseek.c (freadseek): MR. * lib/freopen.c (rpl_freopen): M. * lib/freopen-safer.c (freopen_safer): M. * lib/frexp.c (FUNC): MR. * lib/fseterr.c (fseterr): M. * lib/fstatat.c (rpl_fstatat): M. * lib/fstrcmp.c (fstrcmp_free_resources): M. (fstrcmp_bounded): MR. * lib/fsusage.c (statvfs_works): R. * lib/fsync.c (fsync): M. * lib/ftello.c (ftello): M. * lib/ftruncate.c (SetFileSize): M. * lib/fts.c (fts_open): MR. (fts_load): M. (fts_close): MR. (filesystem_type): MRO. (fts_read): MB. (fts_children): M. (fts_build): MR. (fts_cross_check): RO. (fd_ring_print): RO. (fts_stat): RO. (fts_sort): R. (fts_alloc): M. (fts_lfree): R. (fts_palloc): M. (fts_padjust): MS. (fts_maxarglen): M. (fts_safe_changedir): MR. * lib/fts-cycle.c (enter_dir): MRO. (leave_dir): M. * lib/fzprintf.c (fzprintf): M. * lib/gc-gnulib.c (gc_cipher_open): MR. (gc_cipher_setkey): MSB. (gc_cipher_setiv): M. (gc_cipher_encrypt_inline): M. (gc_cipher_decrypt_inline): M. (gc_hash_open): MR. (gc_hash_clone): M. * lib/gc-libgcrypt.c (gc_init): Remove local variable 'err'. (gc_cipher_open): MR. (gc_cipher_setkey): M. (gc_cipher_setiv): M. (gc_hash_open): MR. (gc_hash_clone): M. (gc_md4): MR. (gc_md5): MR. (gc_sha1): MR. (gc_sha256): MR. (gc_sha512): MR. (gc_sm3): MR. (gc_hmac_md5): MR. Remove local variable 'err'. (gc_hmac_sha1): MR. Remove local variable 'err'. (gc_hmac_sha256): MR. Remove local variable 'err'. (gc_hmac_sha512): MR. Remove local variable 'err'. * lib/gc-pbkdf2.c (gc_pbkdf2_prf): MR. * lib/gen-uni-tables.c (fill_attributes): M. (debug_output_predicate): M. (output_predicate_test): M. (output_predicate): MR. (output_category): MR. (output_combclass): MR. (output_bidi_category): MR. (output_decimal_digit_test): M. (output_decimal_digit): MR. (output_digit_test): M. (output_digit): MR. (output_numeric_test): M. (output_numeric): MR. (fill_mirror): MR. (get_mirror_value): M. (output_mirror): MR. (fill_properties): MR. (fill_property30): MR. (output_indic_conjunct_break_test): M. (output_indic_conjunct_break): MR. (fill_arabicshaping): MR. (output_joining_type_test): M. (output_joining_type): MR. (output_joining_group_test): M. (output_joining_group): MR. (fill_scripts): MR. (output_scripts): MR. (output_scripts_byname): M. (fill_blocks): MR. (output_blocks): M. (output_ident_category): MR. (output_charclass): MR. (output_charmap): MR. (output_tables): M. (fill_width): MR. (output_nonspacing_property): MR. (output_width_property_test): M. (debug_output_lbrk_tables): M. (fill_org_lbp): MR. (debug_output_org_lbrk_tables): M. (output_lbpea): M. (output_lbrk_tables): R. (output_lbrk_rules_as_tables): M. (debug_output_wbrk_tables): M. (fill_org_wbp): MR. (debug_output_org_wbrk_tables): M. (output_wbp): M. (output_wbrk_tables): M. (output_gbp_test): MR. (output_gbp_table): MR. (fill_org_gbp): MR. (get_decomposition): MR. (output_decomposition): M. (output_decomposition_tables): R. (fill_composition_exclusions): MR. (debug_output_composition_tables): M. (output_composition_tables): MSB. (output_simple_mapping_test): M. (output_simple_mapping): MR. (fill_casing_rules): MR. (fill_casefolding_rules): MR. (output_casing_rules): M. (output_version): MR. * lib/get-rusage-as.c (get_rusage_as_via_setrlimit): R. (get_rusage_as): M. * lib/get-rusage-data.c (get_rusage_data_via_setrlimit): R. (get_rusage_data): M. * lib/get_ppid_of.c (get_ppid_of): M. * lib/get_progname_of.c (get_progname_of): MR. * lib/getaddrinfo.c (use_win32_p): M. (getaddrinfo): MR. (freeaddrinfo): M. * lib/getcwd.c (__getcwd_generic): MRSBO. * lib/getcwd-lgpl.c (rpl_getcwd): MS. * lib/getdelim.c (getdelim): MR. * lib/getdomainname.c (getdomainname): M. * lib/getentropy.c (getentropy): R. * lib/getgroups.c (rpl_getgroups): MR. * lib/gethostname.c (rpl_gethostname): M. * lib/getloadavg.c (getloadavg): MRB. * lib/getlocalename_l-unsafe.c (newlocale): MR. (duplocale): MR. (freelocale): M. * lib/getlogin_r.c (getlogin_r): M. * lib/getndelim2.c (getndelim2): MR. * lib/getopt.c (exchange): MS. (process_long_option): MRB. (_getopt_internal_r): MR. (_getopt_internal): M. (main): M. * lib/getopt1.c (main): M. * lib/getpass.c (getpass): MRB. * lib/getprogname.c (getprogname): M. * lib/getrusage.c (getrusage): M. * lib/getsockopt.c (rpl_getsockopt): M. * lib/getsubopt.c (getsubopt): M. * lib/gettext.h (dcpgettext_expr): M. (dcnpgettext_expr): M. * lib/gettimeofday.c (gettimeofday): R. * lib/getugroups.c (getugroups): MR. * lib/getumask.c (getumask): R. * lib/gl_anyavltree_list2.h (rebalance): MR. (gl_tree_remove_node_from_tree): MR. (gl_tree_nx_add_before): R. (gl_tree_nx_add_after): R. * lib/gl_anyhash2.h (hash_resize): M. * lib/gl_anylinked_list2.h (gl_linked_get_at): R. (gl_linked_nx_set_at): R. (gl_linked_search_from_to): R. (gl_linked_indexof_from_to): MR. (gl_linked_nx_add_at): M. (gl_linked_remove_node): M. (gl_linked_remove_at): MR. (gl_linked_iterator_from_to): M. (gl_linked_sortedlist_search_from_to): R. (gl_linked_sortedlist_indexof_from_to): R. * lib/gl_anyrbtree_list2.h (rebalance_after_add): MR. (gl_tree_remove_node_from_tree): M. * lib/gl_anytree_list2.h (gl_tree_iterator): MB. (gl_tree_sortedlist_indexof_from_to): R. * lib/gl_anytree_omap.h (gl_tree_nx_getput): M. (gl_tree_iterator): MB. * lib/gl_anytree_oset.h (gl_tree_nx_add): M. (gl_tree_update): M. (gl_tree_iterator): MB. * lib/gl_anytreehash_list1.h (add_to_bucket): M. * lib/gl_array_list.c (grow): M. (gl_array_nx_add_first): M. (gl_array_nx_add_before): M. (gl_array_nx_add_after): M. (gl_array_nx_add_at): M. (gl_array_remove_node): M. (gl_array_remove_at): M. * lib/gl_array_map.c (grow): M. (gl_array_nx_getput): M. (gl_array_remove_at): M. * lib/gl_array_omap.c (grow): M. (gl_array_nx_add_at): M. (gl_array_remove_at): M. * lib/gl_array_oset.c (grow): M. (gl_array_nx_add_at): M. (gl_array_remove_at): M. * lib/gl_array_set.c (grow): M. * lib/gl_avltree_ordered.h (rebalance): M. (gl_tree_add_node_before): R. (gl_tree_add_node_after): R. (gl_tree_remove_node_no_free): M. * lib/gl_carray_list.c (gl_carray_node_value): M. (gl_carray_node_nx_set_value): M. (gl_carray_get_at): M. (gl_carray_nx_set_at): M. (gl_carray_indexof_from_to): M. (grow): M. (gl_carray_nx_add_last): M. (gl_carray_nx_add_at): M. (gl_carray_remove_at): M. (gl_carray_iterator_from_to): R. (gl_carray_sortedlist_indexof_from_to): M. (gl_carray_sortedlist_nx_add): M. * lib/gl_rbtree_ordered.h (rebalance_after_add): M. (gl_tree_remove_node_no_free): M. * lib/gl_sublist.c (gl_sublist_sortedlist_search_from_to): M. (gl_sublist_sortedlist_indexof_from_to): M. * lib/glob.c (__glob): MR. * lib/globfree.c (globfree): M. * lib/glthread/lock.c (glthread_rwlock_init_for_glibc): M. (glthread_rwlock_init_multithreaded): M. (glthread_rwlock_rdlock_multithreaded): M. (glthread_rwlock_wrlock_multithreaded): M. (glthread_rwlock_destroy_multithreaded): M. (glthread_rwlock_init_multithreaded): M. (glthread_rwlock_rdlock_multithreaded): M. (glthread_rwlock_wrlock_multithreaded): M. (glthread_rwlock_unlock_multithreaded): M. (glthread_rwlock_destroy_multithreaded): M. (glthread_recursive_lock_init_multithreaded): M. (glthread_recursive_lock_lock_multithreaded): M. (glthread_recursive_lock_destroy_multithreaded): M. (glthread_recursive_lock_init_multithreaded): M. (glthread_recursive_lock_lock_multithreaded): M. * lib/glthread/thread.c (gl_thread_create): M. * lib/group-member.c (group_member): M. (main): M. * lib/hash.c (hash_get_next): MB. (check_tuning): M. (hash_initialize): M. (hash_clear): M. (hash_free): MS. (transfer_entries): M. (hash_rehash): MR. (hash_insert_if_absent): MR. (hash_remove): MR. (hash_print): M. * lib/hasmntopt.c (hasmntopt): M. * lib/hmac.c (hmac_hash): R. (GL_HMAC_FN): R. * lib/human.c (group_number): MRO. (human_readable): MR. (humblock): M. * lib/hypot.c (hypot): M. * lib/hypotl.c (hypotl): M. * lib/i-ring.c (i_ring_pop): M. * lib/iconv_open.c (rpl_iconv_open): R. * lib/idcache.c (getuidbyname): M. (getgidbyname): M. * lib/inet_ntop.c (inet_ntop4): M. (inet_ntop6): R. * lib/inet_pton.c (inet_pton4): MRBO. (inet_pton6): MRBO. * lib/ino-map.c (ino_map_insert): M. * lib/integer_length.c (integer_length): M. * lib/ioctl.c (rpl_ioctl): M. (ioctl): M. * lib/is_l-impl.h (FUNC): M. * lib/isatty.c (IsCygwinConsoleHandle): R. * lib/isnan.c (FUNC): MR. * lib/javacomp.c (compile_using_envjavac): MRB. (compile_using_javac): MB. (execute_and_read_line): M. (write_temp_file): M. (get_classfile_version): MR. (is_envjavac_usable): MR. (is_javac_present): M. (is_javac_usable): MR. (compile_java_class): MR. * lib/javaexec.c (execute_java_class): MRBO. * lib/javaversion.c (execute_and_read_line): M. (javaexec_version): R. * lib/kwset.c (treefails): M. (kwsprep): MRSB. (bmexec_trans): MRSO. (acexec_trans): MRS. * lib/lchown.c (rpl_lchown): R. * lib/linebuffer.c (readlinebuffer_delim): RO. * lib/link.c (link): MRBO. (rpl_link): M. * lib/linkat.c (link_immediate): R. (link_follow): M. (linkat_follow): M. * lib/localcharset.c (locale_charset): MR. * lib/localeinfo.c (is_using_utf8): R. Rename 'mbs' to 'state'. (init_localeinfo): Rename 's' to 'state'. * lib/localename.c (gl_locale_name): MSB. * lib/localename-environ.c (gl_locale_name_environ): MSB. * lib/localename-unsafe.c (gl_locale_name_canonicalize): MSB. (gl_locale_name_from_win32_LANGID): M. (gl_locale_name_from_win32_LCID): M. (enum_locales_fn): R. (gl_locale_name_unsafe): MSB. * lib/log2.c (log2): M. * lib/log2f.c (log2f): M. * lib/log2l.c (log2l): M. * lib/login_tty.c (login_tty): M. * lib/logl.c (logl): MR. * lib/long-options.c (parse_long_options): MR. (parse_gnu_standard_options_only): M. * lib/mbfile.h (mbfile_multi_getc): MR. * lib/mbmemcasecoll.c (apply_c32tolower): M. (mbmemcasecoll): MR. * lib/mbrtoc32.c (mbrtoc32): R. * lib/mbrtowc.c (rpl_mbrtowc): MRS. * lib/mbrtowc-impl.h: MRB. * lib/mbscasestr.c (knuth_morris_pratt_multibyte): MR. (mbscasestr): R. * lib/mbscspn.c (mbscspn): MR. * lib/mbsnrtowcs-impl.h (FUNC): M. * lib/mbspbrk.c (mbspbrk): MR. * lib/mbsrtowcs-impl.h (FUNC): M. * lib/mbsspn.c (mbsspn): MR. * lib/mbsstr.c (knuth_morris_pratt_multibyte): MR. (mbsstr): MR. * lib/mbswidth.c (mbsnwidth): M. * lib/mbtowc-impl.h (mbtowc): MR. * lib/mbtowc-lock.h (mbtowc_with_lock): M. * lib/mcel.h: MR in comments. * lib/md2.c (md2_finish_ctx): M. (md2_process_bytes): M. (md2_update_chksum): M. (md2_compress): M. * lib/md2-stream.c (md2_stream): MR. * lib/md4.c (md4_finish_ctx): M. (md4_process_block): MR. * lib/md4-stream.c (md4_stream): MR. * lib/md5-stream.c (md5_stream): MR. * lib/mem-hash-map.c (compute_hashval): M. (lookup): M. * lib/memchr.c (__memchr): MRB. * lib/memchr2.c (memchr2): MRB. * lib/memrchr.c (__memrchr): MRB. * lib/mgetgroups.c (mgetgroups): MRS. * lib/mkancesdirs.c (mkancesdirs): M. * lib/mkdir.c (rpl_mkdir): MR. * lib/mkdir-p.c (make_dir_parents): R. * lib/modechange.c (mode_compile): R. * lib/mountlist.c (fstype_to_string): M. (dev_from_mount_options): MR. (read_file_system_list): MR. * lib/mpsort.c (mpsort_into_tmp): M. (mpsort_with_tmp): M. * lib/msvc-inval.h (TRY_MSVC_INVAL): M. * lib/mtx.c (mtx_init): MSB. * lib/nanosleep.c (nanosleep): M. * lib/nl_langinfo.c (ctype_codeset): MR. (nl_langinfo_with_lock): M. * lib/nonblocking.c (get_nonblocking_flag): M. (set_nonblocking_flag): M. * lib/nproc.c (num_processors_via_affinity_mask): M. (cgroup2_mount): MR. (get_cgroup2_cpu_quota): M. (parse_omp_threads): Remove variable 'ret'. (num_processors): M. * lib/obstack.c (_obstack_newchunk): M. (_obstack_allocated_p): M. (__obstack_free): M. * lib/obstack_printf.c (OBSTACK_PRINTF): M. (OBSTACK_VPRINTF): M. * lib/omp-init.c (parse_omp_threads): Remove variable 'ret'. * lib/openat-proc.c (openat_proc_name): R. * lib/openat2.c (do_openat2): R. (openat2): MSB. * lib/opendir.c (opendir): MR. * lib/openpty.c (openpty): M. * lib/os2-spawn.c (prepare_spawn): M. (spawnpvech): R. * lib/pagealign_alloc.c (pagealign_alloc): MR. (pagealign_xalloc): M. (pagealign_free): M. * lib/parse-duration.c (parse_scaled_value): M. (parse_year_month_day): M. (parse_yearmonthday): MR. (parse_YMWD): SB. (parse_hour_minute_second): M. (parse_hourminutesecond): MR. (parse_HMS): SB. (parse_time): M. (parse_period): MR. (parse_non_iso8601): M. * lib/passfd.c (sendfd): MRO. (recvfd): MRO. * lib/perror.c (perror): M. * lib/physmem.c (physmem_total): M. (physmem_claimable): M. * lib/pipe-filter-gi.c (filter_loop): MRB. (pipe_filter_gi_create): M. (pipe_filter_gi_close): M. * lib/pipe-filter-ii.c (_beginthreadex): M. (WaitForMultipleObjects): MR. (pipe_filter_ii_execute): MRB. * lib/poll.c (IsSocketHandle): R. (windows_compute_revents): MRB. (windows_compute_revents_socket): M. (poll): MRB. Remove variable 'bRet'. * lib/popen.c (rpl_popen): MB. * lib/posix_openpt.c (posix_openpt): M. * lib/posixtm.c (posix_time_parse): R. (posixtime): R. * lib/pread.c (pread): M. * lib/printf.c (printf): M. * lib/printf-frexp.c (FUNC): R. * lib/printf-parse.c (PRINTF_PARSE): MR. * lib/progreloc.c (maybe_executable): R. (find_executable): MRSB. (prepare_relocate): M. * lib/propername.c (mbsstr_trimmed_wordbounded): RSB. (proper_name_utf8): M. * lib/pselect.c (pselect): MR. * lib/pt_chown.c (do_pt_chown): MR. * lib/pthread-cond.c (pthread_cond_timedwait): R. * lib/pthread-rwlock.c (pthread_rwlockattr_init): MSB. (pthread_rwlock_init): MSB. (pthread_rwlock_rdlock): MSB. (pthread_rwlock_wrlock): MSB. (pthread_rwlock_tryrdlock): MB. (pthread_rwlock_trywrlock): MB. (pthread_rwlock_timedrdlock): MSB. (pthread_rwlock_timedwrlock): MSB. (pthread_rwlock_unlock): MSB. (pthread_rwlock_destroy): MSB. (pthread_rwlock_init): MSB. (pthread_rwlock_timedrdlock): MRB. (pthread_rwlock_timedwrlock): MRB. * lib/pthread_mutex_timedlock.c (pthread_mutex_timedlock): MRB. * lib/pthread_sigmask.c (pthread_sigmask): MR. * lib/ptsname_r.c (ptsname_r): MR. * lib/putenv.c (putenv): M. * lib/pwrite.c (pwrite): M. * lib/qcopy-acl.c (qcopy_acl): Remove a use of variable 'ret'. * lib/qset-acl.c (qset_acl): M. * lib/qsort.c (_quicksort): MR. * lib/quotearg.c (set_quoting_flags): M. (quotearg_buffer_restyled): MRSB. * lib/random.c (__initstate): M. (__setstate): M. (__random): R. * lib/random_r.c (__srandom_r): M. (__setstate_r): MO. (__random_r): M. * lib/rawmemchr.c (rawmemchr): RB. * lib/read-file.c (fread_file): M. (read_file): M. * lib/readdir.c (readdir): MR. * lib/readline.c (readline): R. * lib/readtokens.c (readtoken): R. (readtokens): M. * lib/regex-quote.c (regex_quote_spec_gnu): MB. (regex_quote_spec_pcre): MB. (regex_quote_length): MR. (regex_quote): MB. * lib/relocatable.c (set_this_relocation_prefix): M. (compute_curr_prefix): MR. (find_shared_library_fullname): MRS. (relocate): M. * lib/relocwrapper.c (activate_libdirs): MB. (main): M. * lib/rename.c (rpl_rename): MRBO. * lib/renameatu.c (renameatu): MRB. * lib/rijndael-alg-fst.c (rijndaelKeySetupEnc): MSB. (rijndaelKeySetupDec): MRSB. (rijndaelEncrypt): MSB. (rijndaelDecrypt): MSB. * lib/rijndael-api-fst.c (rijndaelMakeKey): MRSB. (rijndaelCipherInit): MSB. (rijndaelBlockEncrypt): MRSB. (rijndaelPadEncrypt): MRSB. (rijndaelBlockDecrypt): MRSB. (rijndaelPadDecrypt): MRSB. * lib/rmdir.c (rpl_rmdir): M. * lib/rpmatch.c (localized_pattern): MS. (try): M. (rpmatch): MSB. * lib/same.c (same_nameat): R. Remove variable 'flags'. * lib/savedir.c (streamsavedir): MRB. * lib/scandir.c (SCANDIR): MR. * lib/select.c (IsSocketHandle): R. (windows_poll_handle): MRSB. Remove variable 'bRet'. (rpl_select): MR. Remove variable 'bRet'. * lib/set-permissions.c (set_acls_from_mode): R. (context_acl_from_mode): R. (context_aclv_from_mode): M. (set_acls_from_mode): MR. (context_acl_from_mode): M. (set_acls): R. (set_permissions): MS. * lib/setenv.c (__add_to_environ): M. (rpl_setenv): M. * lib/sethostname.c (sethostname): MR. * lib/setlocale.c (setlocale_unixlike): MR. (langcmp): R. (setlocale_improved): MR. * lib/setlocale_null.c (setlocale_null_r_with_lock): M. (setlocale_null): M. * lib/setsockopt.c (rpl_setsockopt): R. * lib/sh-quote.c (shell_quote_argv): MB. * lib/sha1.c (sha1_process_block): R. * lib/sha1-stream.c (sha1_stream): M. * lib/sha256.c (sha256_process_block): MR. * lib/sha256-stream.c (shaxxx_stream): M. * lib/sha3.c (sha3_read_ctx): R. (sha3_process_block): R. * lib/sha3-stream.c (sha3_xxx_stream): M. * lib/sha512-stream.c (shaxxx_stream): M. * lib/sig2str.c (str2signum): RS. (sig2str): MR. * lib/sigaction.c (sigaction_handler): MR. (sigaction): MRB. * lib/sigprocmask.c (sigprocmask): M. * lib/sigsegv.c (sigsegv_handler): MR. * lib/sincosl.c (kernel_sinl): MRS. (kernel_cosl): MRS. * lib/sinl.c (sinl): MR. * lib/sleep.c (rpl_sleep): M. * lib/sm3.c (sm3_process_block): MR. * lib/sm3-stream.c (sm3_stream): MR. * lib/snprintf.c (snprintf): M. * lib/snzprintf.c (snzprintf): M. * lib/socket.c (rpl_socket): M. * lib/sockets.c (close_fd_maybe_socket): MR. (ioctl_fd_maybe_socket): MR. (gl_sockets_startup): M. (gl_sockets_cleanup): M. * lib/spawn-pipe.c (create_pipe): MR. * lib/spawni.c (__spawni): Split variable declaration. * lib/sprintf.c (sprintf): M. * lib/sqrtl.c (sqrtl): MR. * lib/ssfmalloc.h (allocate_block_from_pool): MSB. * lib/stackvma.c (rof_open): M. (vma_iterate_proc): RSB. (vma_iterate_bsd): MB. (mapped_range_start): M. (mapped_range_end): M. (is_unmapped): MR. (mapped_range_start): M. (mapped_range_end): M. (vma_iterate): MR. * lib/stat-w32.c (_gl_convert_FILETIME_to_timespec): R. * lib/stdio-consolesafe.c (gl_consolesafe_fprintf): R. (gl_consolesafe_printf): R. * lib/stdio-read.c (CALL_WITH_ERRNO_FIX): M. (scanf): M. (fscanf): M. * lib/stdio-write.c (CALL_WITH_SIGPIPE_EMULATION): M. (printf): M. (fprintf): M. * lib/stpncpy.c (__stpncpy): MSB. * lib/str-kmp.h (knuth_morris_pratt): M. * lib/str-two-way.h (critical_factorization): MSB. (two_way_short_needle): MS. (two_way_long_needle): MRS. * lib/strcasecmp.c (strcasecmp): R. * lib/strcasecmp_l.c (strcasecmp_l): MR. * lib/strcasestr.c (strcasestr): MRSB. * lib/strchrnul.c (strchrnul): MRB. * lib/strerror.c (strerror): M. * lib/strerror_l.c (strerror_l_r): R. * lib/strerror_r.c (local_snprintf): M. (strerror_r): M. * lib/strfmon_l.c (rpl_strfmon_l): MR. * lib/strftime.c (__strftime_internal): MR. * lib/striconv.c (mem_cd_iconv): MR. (str_cd_iconv): MR. (str_iconv): M. * lib/striconveh.c (iconveh_open): MR. (utf8conv_carefully): M. (mem_cd_iconveh_internal): MR. (mem_iconveh): M. (str_iconveh): M. * lib/striconveha.c (uniconv_register_autodetect): MRSB. (mem_iconveha_notranslit): MS. (mem_iconveha): M. (str_iconveha_notranslit): MS. (str_iconveha): M. * lib/string-buffer-printf.c (sb_appendvf): R. (sb_appendf): R. * lib/string-buffer-reversed-printf.c (sbr_prependvf): R. (sbr_prependf): R. * lib/string-desc.c (sd_new): R. * lib/stripslash.c (strip_trailing_slashes): M. * lib/strncasecmp.c (strncasecmp): R. * lib/strncasecmp_l.c (strncasecmp_l): MR. * lib/strptime.c (__strptime_internal): RSB. * lib/strsep.c (strsep): R. * lib/strsignal.c (strsignal): R. * lib/strstr.c (strstr): MRSB. * lib/strtod.c (parse_number): MR. (STRTOD): MR. * lib/strtok_r.c (__strtok_r): M. * lib/strtol.c (strtol): MR. * lib/struniq.h (struniq): M. * lib/supersede.c (open_supersede): R. * lib/system-quote.c (system_quote_argv): MB. * lib/szprintf.c (szprintf): M. * lib/tanl.c (kernel_tanl): MRS. (tanl): MR. * lib/tempname.c (try_tempname_len): M. * lib/term-style-control.c (sprintf_integer): MR. * lib/textstyle.in.h (ostream_printf): MR. * lib/time.c (time): M. * lib/times.c (filetime2clock): M. * lib/timespec-add.c (timespec_add): R. * lib/timespec-sub.c (timespec_sub): R. * lib/tmpdir.c (path_search): MR. * lib/tmpfile.c (tmpfile): M. * lib/to_l-impl.h (FUNC): M. * lib/tparm.c (tparm): MRB. * lib/trigl.c (ieee754_rem_pio2l): MRS. (kernel_rem_pio2): MRS. * lib/trim.c (trim2): MR. * lib/tsearch.c (check_tree): R. (maybe_split_for_insert): M. (__tsearch): MR. (__tfind): M. (__tdelete): MRB. * lib/ttyname_r.c (ttyname_r): M. * lib/uname.c (uname): MR. * lib/unicase/locale-language.c (uc_locale_language): M. * lib/unicase/u-casecmp.h (FUNC): MR. * lib/unicase/u-casecoll.h (FUNC): MR. * lib/unicase/u-casemap.h (FUNC): MR. * lib/unicase/u-casexfrm.h (FUNC): MR. * lib/unicase/u-ct-casefold.h (FUNC): MR. * lib/unicase/u-ct-totitle.h (FUNC): MR. * lib/unicase/u-is-cased.h (FUNC): MR. * lib/unicase/u-is-invariant.h (FUNC): MR. * lib/unicase/u8-casefold.c (read_file): M. * lib/unicase/u8-tolower.c (read_file): M. * lib/unicase/u8-totitle.c (read_file): M. * lib/unicase/u8-toupper.c (read_file): M. * lib/unicase/ulc-casecmp.c (ulc_u8_casefold): MR. * lib/unicase/ulc-casexfrm.c (ulc_casexfrm): MR. * lib/unicodeio.c (unicode_to_mb): MR. * lib/uniconv/u-conv-from-enc.h (FUNC): M. * lib/uniconv/u-conv-to-enc.h (FUNC): MR. * lib/uniconv/u-strconv-from-enc.h (FUNC): M. * lib/uniconv/u-strconv-to-enc.h (FUNC): M. * lib/uniconv/u16-conv-to-enc.c (FUNC): MR. * lib/uniconv/u8-conv-from-enc.c (u8_conv_from_encoding): R. * lib/uniconv/u8-conv-to-enc.c (u8_conv_to_encoding): R. * lib/uniconv/u8-strconv-to-enc.c (u8_strconv_to_encoding): MS. * lib/unictype/3level.h (CONCAT(TABLE,_add)): M. (CONCAT(TABLE,_finalize)): MRB. * lib/unictype/3levelbit.h (CONCAT(TABLE,_add)): M. (CONCAT(TABLE,_finalize)): MRB. * lib/unictype/bidi_byname.c (uc_bidi_class_byname): M. * lib/unictype/categ_and.c (uc_general_category_and): MR. * lib/unictype/categ_and_not.c (uc_general_category_and_not): MR. * lib/unictype/categ_byname.c (uc_general_category_byname): M. * lib/unictype/categ_of.c (uc_general_category): R. * lib/unictype/categ_or.c (uc_general_category_or): MR. * lib/unictype/combiningclass_byname.c (uc_combining_class_byname): M. * lib/unictype/incb_byname.c (uc_indic_conjunct_break_byname): M. * lib/unictype/joininggroup_byname.c (uc_joining_group_byname): M. * lib/unictype/joiningtype_byname.c (uc_joining_type_byname): M. * lib/unictype/pr_byname.c (uc_property_byname): MRB. * lib/unictype/scripts.c (uc_script_byname): M. * lib/unigbrk/u-grapheme-prev.h (ends_with_incb_consonant_extended_linker_extended): M. (ends_with_emoji_modifier_sequence): M. (ends_with_ri_count): M. (FUNC): M. * lib/unigbrk/uc-is-grapheme-break.c (uc_is_grapheme_break): M. * lib/unigbrk/ulc-grapheme-breaks.c (ulc_grapheme_breaks): M. * lib/unilbrk/u16-width-linebreaks.c (u16_width_linebreaks_internal): M. * lib/unilbrk/u32-width-linebreaks.c (u32_width_linebreaks_internal): M. * lib/unilbrk/u8-possible-linebreaks.c (read_file): M. * lib/unilbrk/u8-width-linebreaks.c (u8_width_linebreaks_internal): M. (read_file): M. * lib/unilbrk/ulc-possible-linebreaks.c (ulc_possible_linebreaks_internal): M. (read_file): M. * lib/unilbrk/ulc-width-linebreaks.c (ulc_width_linebreaks_internal): M. (read_file): M. * lib/uniname/uniname.c (unicode_name_word): MR. (unicode_character_name): M. (unicode_name_character): MR. * lib/uninorm/canonical-decomposition.c (uc_canonical_decomposition): M. * lib/uninorm/composition.c (uc_composition): M. * lib/uninorm/decomposition.c (uc_decomposition): M. * lib/uninorm/u-normalize-internal.h (FUNC): MR. * lib/uninorm/u-normcmp.h (FUNC): MR. * lib/uninorm/u-normcoll.h (FUNC): MR. * lib/uninorm/u-normxfrm.h (FUNC): MR. * lib/uninorm/uninorm-filter.c (uninorm_filter_write): M. * lib/unistdio/u-asnprintf.h (ASNPRINTF): M. * lib/unistdio/u-asprintf.h (ASPRINTF): M. * lib/unistdio/u-snprintf.h (SNPRINTF): M. * lib/unistdio/u-sprintf.h (SPRINTF): M. * lib/unistdio/u-vsnprintf.h (VSNPRINTF): M. * lib/unistdio/u-vsprintf.h (VSPRINTF): M. * lib/unistdio/ulc-fprintf.c (ulc_fprintf): M. * lib/unistdio/ulc-vfprintf.c (ulc_vfprintf): M. * lib/unistr/u16-chr.c (u16_chr): R. * lib/unistr/u16-mbsnlen.c (u16_mbsnlen): M. * lib/unistr/u16-next.c (u16_next): M. * lib/unistr/u16-strchr.c (u16_strchr): R. * lib/unistr/u16-strrchr.c (u16_strrchr): R. * lib/unistr/u16-to-u32.c (FUNC): MR. * lib/unistr/u16-to-u8.c (FUNC): MR. * lib/unistr/u32-next.c (u32_next): M. * lib/unistr/u32-to-u16.c (FUNC): MR. * lib/unistr/u32-to-u8.c (FUNC): MR. * lib/unistr/u8-chr.c (u8_chr): M. * lib/unistr/u8-mbsnlen.c (u8_mbsnlen): M. * lib/unistr/u8-next.c (u8_next): M. * lib/unistr/u8-strchr.c (u8_strchr): R. * lib/unistr/u8-strrchr.c (u8_strrchr): R. * lib/unistr/u8-to-u16.c (FUNC): MR. * lib/unistr/u8-to-u32.c (FUNC): MR. * lib/uniwbrk/u8-wordbreaks.c (read_file): M. * lib/uniwbrk/ulc-wordbreaks.c (ulc_wordbreaks): M. (read_file): M. * lib/uniwidth/u16-width.c (u16_width): M. * lib/uniwidth/u32-width.c (u32_width): M. * lib/uniwidth/u8-width.c (u8_width): M. * lib/unlinkat.c (rpl_unlinkat): MR. * lib/unsetenv.c (unsetenv): M. (rpl_unsetenv): R. * lib/userspec.c (parse_with_separator): MRS. (main): MR. * lib/utime.c (_gl_utimens_windows): M. * lib/utimecmp.c (utimecmpat): R. * lib/utimens.c (validate_timespec): R. (fdutimens): MR. (lutimens): MR. * lib/utimensat.c (rpl_utimensat): M. * lib/vasnprintf.c (divide): M. (decode_long_double): MR. (decode_double): MR. (scale10_round_decimal_decoded): MR. (floorlog10l): MR. (floorlog10): MR. (VASNPRINTF): MR. * lib/vc-mtime.c (is_git_present): MR. (git_vc_controlled): MR. (git_unmodified): M. (git_mtime): MR. (abs_git_checkout): MR. (max_vc_mtime): MR. * lib/vdzprintf.c (vdzprintf): M. * lib/vfzprintf.c (vfzprintf): M. * lib/vma-iter.c (rof_open): M. (vma_iterate_proc): MRSB. (vma_iterate_bsd): MB. (vma_iterate): MR. * lib/vsnzprintf.c (vsnzprintf): M. * lib/vszprintf.c (vszprintf): M. * lib/wait-process.c (klibc_waitpid): M. (wait_subprocess): MR. * lib/wcs-two-way.h (critical_factorization): MSB. (two_way_short_needle): MS. * lib/wcsstr-impl.h (FUNC): MRSB. * lib/wcswidth-impl.h (FUNC): B. * lib/wcsxfrm-impl.h (wcsxfrm): MR. * lib/wctomb-impl.h (wctomb): M. * lib/wgetcwd-lgpl.c (wgetcwd): MRS. * lib/windows-cond.c (glwthread_waitqueue_add): M. (glwthread_waitqueue_notify_first): M. (glwthread_waitqueue_notify_all): M. (glwthread_cond_wait): M. (glwthread_cond_timedwait): MRS. * lib/windows-cygpath.c (execute_and_read_line): MR. * lib/windows-rwlock.c (glwthread_waitqueue_add): M. (glwthread_rwlock_rdlock): M. (glwthread_rwlock_wrlock): M. * lib/windows-spawn.c (quoted_arg_length): M. (quoted_arg_string): M. (prepare_spawn): MR. (compose_command): MRB. (compose_envblock): RSB. * lib/windows-thread.c (glwthread_thread_self): M. (glwthread_thread_create): M. * lib/windows-timedmutex.c (glwthread_timedmutex_timedlock): MR. * lib/windows-timedrecmutex.c (glwthread_timedrecmutex_timedlock): MR. * lib/windows-timedrwlock.c (glwthread_waitqueue_add): M. (glwthread_waitqueue_notify_first): M. (glwthread_waitqueue_notify_all): M. (glwthread_timedrwlock_rdlock): M. (glwthread_timedrwlock_wrlock): M. (glwthread_timedrwlock_timedrdlock): MR. (glwthread_timedrwlock_timedwrlock): MR. * lib/xasprintf.c (xasprintf): M. * lib/xconcat-filename.c (xconcatenated_filename): M. * lib/xmalloc.c (xpalloc): R. * lib/xmalloca.c (xmmalloca): M. * lib/xprintf.c (xprintf): M. (xfprintf): M. * lib/xstring-buffer-printf.c (sb_xappendf): M. * lib/xstring-buffer-reversed-printf.c (sbr_xprependf): M. * lib/xstrtod.c (XSTRTOD): MR. * lib/xstrtol.c (__xstrtol): R. * lib/xstrtol-error.c (xstrtol_error): R. * lib/xvasprintf.c (xstrcat): MB. (xvasprintf): R. * lib/zprintf.c (zprintf): M.
1463 lines
49 KiB
C
1463 lines
49 KiB
C
/* Page fault handling library.
|
|
Copyright (C) 1993-2025 Free Software Foundation, Inc.
|
|
Copyright (C) 2018 Nylon Chen <nylon7@andestech.com>
|
|
|
|
This program is free software: you can redistribute it and/or modify
|
|
it under the terms of the GNU General Public License as published by
|
|
the Free Software Foundation; either version 2 of the License, or
|
|
(at your option) any later version.
|
|
|
|
This program is distributed in the hope that it will be useful,
|
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
GNU General Public License for more details.
|
|
|
|
You should have received a copy of the GNU General Public License
|
|
along with this program. If not, see <https://www.gnu.org/licenses/>. */
|
|
|
|
/* Written by Bruno Haible and Nylon Chen. */
|
|
|
|
#include <config.h>
|
|
|
|
/* Specification. */
|
|
#include "sigsegv.h"
|
|
|
|
#include <errno.h>
|
|
#include <stdio.h> /* declares perror */
|
|
#include <stdint.h> /* defines uintptr_t */
|
|
#include <stdlib.h>
|
|
#include <signal.h>
|
|
#if HAVE_GETRLIMIT
|
|
# include <sys/resource.h> /* declares struct rlimit */
|
|
#endif
|
|
|
|
#ifdef __OpenBSD__
|
|
# include <sys/param.h> /* defines macro OpenBSD */
|
|
#endif
|
|
|
|
|
|
/* Version number. */
|
|
int libsigsegv_version = LIBSIGSEGV_VERSION;
|
|
|
|
|
|
/* ======================= Fault handler information ======================= */
|
|
|
|
/* Define:
|
|
|
|
SIGSEGV_FAULT_HANDLER_ARGLIST
|
|
is the argument list for the actual fault handler.
|
|
|
|
and if available (optional):
|
|
|
|
SIGSEGV_FAULT_ADDRESS
|
|
is a macro for fetching the fault address.
|
|
|
|
SIGSEGV_FAULT_CONTEXT
|
|
is a macro giving a pointer to the entire fault context (i.e.
|
|
the register set etc.).
|
|
|
|
SIGSEGV_FAULT_STACKPOINTER
|
|
is a macro for fetching the stackpointer at the moment the fault
|
|
occurred.
|
|
*/
|
|
|
|
#if defined __linux__ && !defined __ANDROID__ /* Linux */
|
|
|
|
# define SIGSEGV_FAULT_HANDLER_ARGLIST int sig, siginfo_t *sip, void *ucp
|
|
# define SIGSEGV_FAULT_ADDRESS sip->si_addr
|
|
# define SIGSEGV_FAULT_CONTEXT ((ucontext_t *) ucp)
|
|
# define SIGSEGV_FAULT_ADDRESS_FROM_SIGINFO
|
|
|
|
# if defined __alpha__
|
|
|
|
/* See glibc/sysdeps/unix/sysv/linux/alpha/sys/ucontext.h
|
|
and the definition of GET_STACK in
|
|
glibc/sysdeps/unix/sysv/linux/alpha/sigcontextinfo.h.
|
|
Note that the 'mcontext_t' defined in
|
|
glibc/sysdeps/unix/sysv/linux/alpha/sys/ucontext.h
|
|
and the 'struct sigcontext' defined in <asm/sigcontext.h>
|
|
are actually the same. */
|
|
|
|
# define SIGSEGV_FAULT_STACKPOINTER ((ucontext_t *) ucp)->uc_mcontext.sc_regs[30]
|
|
|
|
# elif defined __arm64__ /* 64-bit */
|
|
|
|
/* See glibc/sysdeps/unix/sysv/linux/aarch64/sys/ucontext.h.
|
|
Note that the 'mcontext_t' defined in
|
|
glibc/sysdeps/unix/sysv/linux/aarch64/sys/ucontext.h
|
|
and the 'struct sigcontext' defined in <asm/sigcontext.h>
|
|
are actually the same. */
|
|
|
|
# define SIGSEGV_FAULT_STACKPOINTER ((ucontext_t *) ucp)->uc_mcontext.sp
|
|
|
|
# elif defined __arm__ || defined __armhf__ /* 32-bit */
|
|
|
|
/* See glibc/sysdeps/unix/sysv/linux/arm/sys/ucontext.h
|
|
and the definition of GET_STACK in
|
|
glibc/sysdeps/unix/sysv/linux/arm/sigcontextinfo.h.
|
|
Note that the 'mcontext_t' defined in
|
|
glibc/sysdeps/unix/sysv/linux/arm/sys/ucontext.h
|
|
and the 'struct sigcontext' defined in <asm/sigcontext.h>
|
|
are actually the same. */
|
|
|
|
# define SIGSEGV_FAULT_STACKPOINTER ((ucontext_t *) ucp)->uc_mcontext.arm_sp
|
|
|
|
# elif defined __cris__
|
|
|
|
/* See glibc-ports/sysdeps/unix/sysv/linux/cris/sys/ucontext.h.
|
|
Note that the 'mcontext_t' defined in
|
|
glibc-ports/sysdeps/unix/sysv/linux/cris/sys/ucontext.h
|
|
and the 'struct sigcontext' defined in <asm/sigcontext.h>
|
|
are actually the same. */
|
|
|
|
# define SIGSEGV_FAULT_STACKPOINTER ((ucontext_t *) ucp)->uc_mcontext.usp
|
|
|
|
# elif defined __hppa__
|
|
|
|
/* See glibc/sysdeps/unix/sysv/linux/hppa/sys/ucontext.h.
|
|
Note that the 'mcontext_t' defined in
|
|
glibc/sysdeps/unix/sysv/linux/hppa/sys/ucontext.h
|
|
and the 'struct sigcontext' defined in <asm/sigcontext.h>
|
|
are actually the same. */
|
|
|
|
# define SIGSEGV_FAULT_STACKPOINTER ((ucontext_t *) ucp)->uc_mcontext.sc_gr[30]
|
|
|
|
# elif defined __x86_64__ /* 64 bit registers */
|
|
|
|
/* See glibc/sysdeps/unix/sysv/linux/x86/sys/ucontext.h
|
|
and the definition of GET_STACK in
|
|
glibc/sysdeps/unix/sysv/linux/x86_64/sigcontextinfo.h.
|
|
Note that the 'mcontext_t' defined in
|
|
glibc/sysdeps/unix/sysv/linux/x86/sys/ucontext.h
|
|
and the 'struct sigcontext' defined in
|
|
glibc/sysdeps/unix/sysv/linux/x86/bits/sigcontext.h
|
|
(see also <asm/sigcontext.h>)
|
|
are effectively the same. */
|
|
|
|
# define SIGSEGV_FAULT_STACKPOINTER ((ucontext_t *) ucp)->uc_mcontext.gregs[REG_RSP]
|
|
|
|
# elif defined __i386__ /* 32 bit registers */
|
|
|
|
/* See glibc/sysdeps/unix/sysv/linux/x86/sys/ucontext.h
|
|
and the definition of GET_STACK in
|
|
glibc/sysdeps/unix/sysv/linux/i386/sigcontextinfo.h.
|
|
Note that the 'mcontext_t' defined in
|
|
glibc/sysdeps/unix/sysv/linux/x86/sys/ucontext.h
|
|
and the 'struct sigcontext_ia32' defined in <asm/sigcontext32.h>
|
|
are effectively the same. */
|
|
|
|
# define SIGSEGV_FAULT_STACKPOINTER ((ucontext_t *) ucp)->uc_mcontext.gregs[REG_ESP]
|
|
/* same value as ((ucontext_t *) ucp)->uc_mcontext.gregs[REG_UESP] */
|
|
|
|
# elif defined __ia64__
|
|
|
|
/* See glibc/sysdeps/unix/sysv/linux/ia64/sys/ucontext.h.
|
|
Note that the 'mcontext_t' defined in
|
|
glibc/sysdeps/unix/sysv/linux/ia64/sys/ucontext.h
|
|
and the 'struct sigcontext' defined in
|
|
glibc/sysdeps/unix/sysv/linux/ia64/bits/sigcontext.h
|
|
(see also <asm/sigcontext.h>)
|
|
are actually the same. */
|
|
|
|
/* IA-64 has two stack pointers, one that grows down, called $r12, and one
|
|
that grows up, called $bsp/$bspstore. */
|
|
# define SIGSEGV_FAULT_STACKPOINTER ((ucontext_t *) ucp)->uc_mcontext.sc_gr[12]
|
|
|
|
/* It would be better to access $bspstore instead of $bsp but I don't know
|
|
where to find it in 'struct sigcontext'. Anyway, it doesn't matter
|
|
because $bsp and $bspstore never differ by more than ca. 1 KB. */
|
|
# define SIGSEGV_FAULT_BSP_POINTER ((ucontext_t *) ucp)->uc_mcontext.sc_ar_bsp
|
|
|
|
# elif defined __loongarch__
|
|
|
|
/* See <sys/ucontext.h>.
|
|
Note that the 'mcontext_t' defined in <sys/ucontext.h>
|
|
and the 'struct sigcontext' defined in <bits/sigcontext.h>
|
|
(see also <asm/sigcontext.h>) are effectively the same. */
|
|
|
|
# define SIGSEGV_FAULT_STACKPOINTER ((ucontext_t *) ucp)->uc_mcontext.__gregs[3]
|
|
|
|
# elif defined __m68k__
|
|
|
|
/* See glibc/sysdeps/unix/sysv/linux/m68k/sys/ucontext.h
|
|
and the definition of GET_STACK in
|
|
glibc/sysdeps/unix/sysv/linux/m68k/sigcontextinfo.h.
|
|
Note that the 'mcontext_t' defined in
|
|
glibc/sysdeps/unix/sysv/linux/m68k/sys/ucontext.h
|
|
and the 'struct sigcontext' defined in <asm/sigcontext.h>
|
|
are quite different types. */
|
|
|
|
# define SIGSEGV_FAULT_STACKPOINTER ((ucontext_t *) ucp)->uc_mcontext.gregs[R_SP]
|
|
|
|
# elif defined __mips__ || defined __mipsn32__ || defined __mips64__
|
|
|
|
/* See glibc/sysdeps/unix/sysv/linux/mips/sys/ucontext.h
|
|
and the definition of GET_STACK in
|
|
glibc/sysdeps/unix/sysv/linux/mips/sigcontextinfo.h.
|
|
Note that the 'mcontext_t' defined in
|
|
glibc/sysdeps/unix/sysv/linux/mips/sys/ucontext.h
|
|
and the 'struct sigcontext' defined in
|
|
glibc/sysdeps/unix/sysv/linux/mips/bits/sigcontext.h
|
|
(see also <asm/sigcontext.h>)
|
|
are effectively the same. */
|
|
|
|
# define SIGSEGV_FAULT_STACKPOINTER ((ucontext_t *) ucp)->uc_mcontext.gregs[29]
|
|
|
|
# elif defined __nds32__
|
|
|
|
/* See glibc/sysdeps/unix/sysv/linux/nds32/sys/ucontext.h
|
|
and the definition of GET_STACK in
|
|
glibc/sysdeps/unix/sysv/linux/nds32/sigcontextinfo.h.
|
|
Both are found in <https://patches-gcc.linaro.org/cover/4409/> part 08/11
|
|
<https://sourceware.org/ml/libc-alpha/2018-05/msg00125.html>. */
|
|
|
|
# define SIGSEGV_FAULT_STACKPOINTER ((ucontext_t *) ucp)->uc_mcontext.nds32_sp
|
|
|
|
# elif defined __powerpc__ || defined __powerpc64__ || defined __powerpc64_elfv2__
|
|
|
|
/* See glibc/sysdeps/unix/sysv/linux/powerpc/sys/ucontext.h
|
|
and the definition of GET_STACK in
|
|
glibc/sysdeps/unix/sysv/linux/powerpc/sigcontextinfo.h.
|
|
Note that the 'mcontext_t' defined in
|
|
glibc/sysdeps/unix/sysv/linux/powerpc/sys/ucontext.h,
|
|
the 'struct sigcontext' defined in <asm/sigcontext.h>,
|
|
and the 'struct pt_regs' defined in <asm/ptrace.h>
|
|
are quite different types. */
|
|
|
|
# if defined __powerpc64__ || defined __powerpc64_elfv2__ /* 64-bit */
|
|
# define SIGSEGV_FAULT_STACKPOINTER ((ucontext_t *) ucp)->uc_mcontext.gp_regs[1]
|
|
# else /* 32-bit */
|
|
# if MUSL_LIBC
|
|
/* musl libc has a different structure of ucontext_t in
|
|
musl/arch/powerpc/bits/signal.h. */
|
|
/* The glibc comments say:
|
|
"Different versions of the kernel have stored the registers on signal
|
|
delivery at different offsets from the ucontext struct. Programs should
|
|
thus use the uc_mcontext.uc_regs pointer to find where the registers are
|
|
actually stored." */
|
|
# if 0
|
|
# define SIGSEGV_FAULT_STACKPOINTER ((ucontext_t *) ucp)->uc_mcontext.gregs[1]
|
|
# else
|
|
# define SIGSEGV_FAULT_STACKPOINTER ((ucontext_t *) ucp)->uc_regs->gregs[1]
|
|
# endif
|
|
# else
|
|
/* Assume the structure of ucontext_t in
|
|
glibc/sysdeps/unix/sysv/linux/powerpc/sys/ucontext.h. */
|
|
/* Because of the union, both definitions should be equivalent. */
|
|
# if 0
|
|
# define SIGSEGV_FAULT_STACKPOINTER ((ucontext_t *) ucp)->uc_mcontext.regs->gpr[1]
|
|
# else
|
|
# define SIGSEGV_FAULT_STACKPOINTER ((ucontext_t *) ucp)->uc_mcontext.uc_regs->gregs[1]
|
|
# endif
|
|
# endif
|
|
# endif
|
|
|
|
# elif defined __riscv32__ || __riscv64__
|
|
|
|
/* See glibc/sysdeps/unix/sysv/linux/riscv/sys/ucontext.h
|
|
and the definition of GET_STACK in
|
|
glibc/sysdeps/unix/sysv/linux/riscv/sigcontextinfo.h.
|
|
Note that the 'mcontext_t' defined in
|
|
glibc/sysdeps/unix/sysv/linux/riscv/sys/ucontext.h
|
|
and the 'struct sigcontext' defined in
|
|
glibc/sysdeps/unix/sysv/linux/riscv/bits/sigcontext.h
|
|
start with the same block of 32 general-purpose registers. */
|
|
|
|
# define SIGSEGV_FAULT_STACKPOINTER ((ucontext_t *) ucp)->uc_mcontext.__gregs[REG_SP]
|
|
|
|
# elif defined __s390__ || defined __s390x__
|
|
|
|
/* See glibc/sysdeps/unix/sysv/linux/s390/sys/ucontext.h
|
|
and the definition of GET_STACK in
|
|
glibc/sysdeps/unix/sysv/linux/s390/sigcontextinfo.h.
|
|
Note that the 'mcontext_t' defined in
|
|
glibc/sysdeps/unix/sysv/linux/s390/sys/ucontext.h
|
|
and the '_sigregs' type, indirect part of 'struct sigcontext', defined
|
|
in <asm/sigcontext.h>, are effectively the same. */
|
|
|
|
# define SIGSEGV_FAULT_STACKPOINTER ((ucontext_t *) ucp)->uc_mcontext.gregs[15]
|
|
|
|
# elif defined __sh__
|
|
|
|
/* See glibc/sysdeps/unix/sysv/linux/sh/sys/ucontext.h
|
|
and the definition of GET_STACK in
|
|
glibc/sysdeps/unix/sysv/linux/sh/sigcontextinfo.h.
|
|
Note that the 'mcontext_t' defined in
|
|
glibc/sysdeps/unix/sysv/linux/sh/sys/ucontext.h
|
|
and the 'struct sigcontext' defined in <asm/sigcontext.h>
|
|
are effectively the same. */
|
|
|
|
# define SIGSEGV_FAULT_STACKPOINTER ((ucontext_t *) ucp)->uc_mcontext.gregs[15]
|
|
|
|
# elif defined __sparc__ || defined __sparc64__
|
|
|
|
/* See glibc/sysdeps/unix/sysv/linux/sparc/sys/ucontext.h
|
|
and the definition of GET_STACK in
|
|
glibc/sysdeps/unix/sysv/linux/sparc/{sparc32,sparc64}/sigcontextinfo.h.
|
|
Note that the 'mcontext_t' defined in
|
|
glibc/sysdeps/unix/sysv/linux/sparc/sys/ucontext.h
|
|
and the 'struct sigcontext' defined in
|
|
glibc/sysdeps/unix/sysv/linux/sparc/bits/sigcontext.h
|
|
(see also <asm/sigcontext.h>)
|
|
are quite different types. */
|
|
|
|
# if defined __sparc64__/* 64-bit */
|
|
/* From linux-4.8.1/arch/sparc/kernel/signal_64.c, function setup_rt_frame, we
|
|
see that ucp is not an 'ucontext_t *' but rather a 'struct sigcontext *'
|
|
that happens to have the same value as sip (which is possible because a
|
|
'struct sigcontext' starts with 128 bytes room for the siginfo_t). */
|
|
# define SIGSEGV_FAULT_STACKPOINTER (((struct sigcontext *) ucp)->sigc_regs.u_regs[14] + 2047)
|
|
# else /* 32-bit */
|
|
/* From linux-4.8.1/arch/sparc/kernel/signal_32.c, function setup_rt_frame,
|
|
and linux-4.8.1/arch/sparc/kernel/signal32.c, function setup_rt_frame32, we
|
|
see that ucp is a 'struct pt_regs *' or 'struct pt_regs32 *', respectively.
|
|
In userland, this is a 'struct sigcontext *'. */
|
|
# define SIGSEGV_FAULT_STACKPOINTER ((struct sigcontext *) ucp)->si_regs.u_regs[14]
|
|
# endif
|
|
|
|
/* The sip->si_addr field is correct for a normal fault, but unusable in case
|
|
of a stack overflow. What I observe (when running
|
|
tests/test-sigsegv-catch-stackoverflow1, with a printf right at the beginning
|
|
of sigsegv_handler) is that sip->si_addr is near 0:
|
|
- in 64-bit mode: sip->si_addr = 0x000000000000030F, and gdb shows me that
|
|
the fault occurs in an instruction 'stx %o3,[%fp+0x30f]' and %fp is 0.
|
|
In fact, all registers %l0..%l7 and %i0..%i7 are 0.
|
|
- in 32-bit mode: sip->si_addr = 0xFFFFFA64, and gdb shows me that
|
|
the fault occurs in an instruction 'st %g2,[%fp-1436]' and %fp is 0.
|
|
In fact, all registers %l0..%l7 and %i0..%i7 are 0.
|
|
Apparently when the stack overflow occurred, some trap has tried to move the
|
|
contents of the registers %l0..%l7 and %i0..%i7 (a "window" in SPARC
|
|
terminology) to the stack, did not succeed in doing this, replaced all these
|
|
register values with 0, and resumed execution at the fault location. This
|
|
time, due to %fp = 0, a different fault was triggered. Now it is impossible
|
|
to determine the real (previous) fault address because, even if know the
|
|
faulting instruction, the previous register values have been lost. */
|
|
# define BOGUS_FAULT_ADDRESS_UPON_STACK_OVERFLOW
|
|
|
|
# else
|
|
|
|
/* When adding support for other CPUs here: */
|
|
|
|
/* For SIGSEGV_FAULT_HANDLER_ARGLIST, see the definition of SIGCONTEXT in
|
|
glibc/sysdeps/unix/sysv/linux/<cpu>/sigcontextinfo.h. */
|
|
|
|
/* For SIGSEGV_FAULT_STACKPOINTER, see the definition of GET_STACK in
|
|
glibc/sysdeps/unix/sysv/linux/<cpu>/sigcontextinfo.h. */
|
|
|
|
# endif
|
|
|
|
#endif
|
|
|
|
#if defined __ANDROID__ /* Android */
|
|
/* A platform that supports the POSIX:2008 (XPG 7) way, without
|
|
'struct sigcontext' nor 'ucontext_t'. */
|
|
|
|
# define SIGSEGV_FAULT_HANDLER_ARGLIST int sig, siginfo_t *sip, void *context
|
|
# define SIGSEGV_FAULT_ADDRESS sip->si_addr
|
|
# define SIGSEGV_FAULT_CONTEXT context
|
|
# define SIGSEGV_FAULT_ADDRESS_FROM_SIGINFO
|
|
|
|
#endif
|
|
|
|
#if defined __gnu_hurd__ /* Hurd */
|
|
|
|
# define SIGSEGV_FAULT_HANDLER_ARGLIST int sig, long code, struct sigcontext *scp
|
|
# define SIGSEGV_FAULT_ADDRESS (unsigned long) code
|
|
# define SIGSEGV_FAULT_CONTEXT scp
|
|
|
|
# if defined __x86_64__
|
|
/* 64 bit registers */
|
|
|
|
/* scp points to a 'struct sigcontext' (defined in
|
|
glibc/sysdeps/mach/hurd/x86_64/bits/sigcontext.h).
|
|
The registers, at the moment the signal occurred, get pushed on the kernel
|
|
stack through gnumach/x86_64/locore.S:alltraps. They are denoted by a
|
|
'struct i386_saved_state' (defined in gnumach/i386/i386/thread.h).
|
|
Upon invocation of the Mach interface function thread_get_state
|
|
<https://www.gnu.org/software/hurd/gnumach-doc/Thread-Execution.html>
|
|
(= __thread_get_state in glibc), defined in gnumach/kern/thread.c,
|
|
the function thread_getstatus, defined in gnumach/i386/i386/pcb.c, copies the
|
|
register values in a different arrangement into a 'struct i386_thread_state',
|
|
defined in gnumach/i386/include/mach/i386/thread_status.h. (Different
|
|
arrangement: trapno, err get dropped; different order of r8...r15; also rsp
|
|
gets set to 0.)
|
|
This 'struct i386_thread_state' is actually the 'basic' part of a
|
|
'struct machine_thread_all_state', defined in
|
|
glibc/sysdeps/mach/x86/thread_state.h.
|
|
From there, the function _hurd_setup_sighandler, defined in
|
|
glibc/sysdeps/mach/hurd/x86/trampoline.c,
|
|
1. sets rsp to the same value as ursp,
|
|
2. copies the 'struct i386_thread_state' into the appropriate part of a
|
|
'struct sigcontext', defined in
|
|
glibc/sysdeps/mach/hurd/x86_64/bits/sigcontext.h. */
|
|
/* Both sc_rsp and sc_ursp have the same value.
|
|
It appears more reliable to use sc_ursp because sc_rsp is marked as
|
|
"not used". */
|
|
# define SIGSEGV_FAULT_STACKPOINTER scp->sc_ursp
|
|
|
|
# elif defined __i386__
|
|
/* 32 bit registers */
|
|
|
|
/* scp points to a 'struct sigcontext' (defined in
|
|
glibc/sysdeps/mach/hurd/i386/bits/sigcontext.h).
|
|
The registers, at the moment the signal occurred, get pushed on the kernel
|
|
stack through gnumach/i386/i386/locore.S:alltraps. They are denoted by a
|
|
'struct i386_saved_state' (defined in gnumach/i386/i386/thread.h).
|
|
Upon invocation of the Mach interface function thread_get_state
|
|
<https://www.gnu.org/software/hurd/gnumach-doc/Thread-Execution.html>
|
|
(= __thread_get_state in glibc), defined in gnumach/kern/thread.c,
|
|
the function thread_getstatus, defined in gnumach/i386/i386/pcb.c, copies the
|
|
register values in a different arrangement into a 'struct i386_thread_state',
|
|
defined in gnumach/i386/include/mach/i386/thread_status.h. (Different
|
|
arrangement: trapno, err get dropped; also esp gets set to 0.)
|
|
This 'struct i386_thread_state' is actually the 'basic' part of a
|
|
'struct machine_thread_all_state', defined in
|
|
glibc/sysdeps/mach/x86/thread_state.h.
|
|
From there, the function _hurd_setup_sighandler, defined in
|
|
glibc/sysdeps/mach/hurd/x86/trampoline.c,
|
|
1. sets esp to the same value as uesp,
|
|
2. copies the 'struct i386_thread_state' into the appropriate part of a
|
|
'struct sigcontext', defined in
|
|
glibc/sysdeps/mach/hurd/i386/bits/sigcontext.h. */
|
|
/* Both sc_esp and sc_uesp have the same value.
|
|
It appears more reliable to use sc_uesp because sc_esp is marked as
|
|
"not used". */
|
|
# define SIGSEGV_FAULT_STACKPOINTER scp->sc_uesp
|
|
|
|
# endif
|
|
|
|
#endif
|
|
|
|
#if defined __FreeBSD_kernel__ || defined __FreeBSD__ || defined __DragonFly__ /* GNU/kFreeBSD, FreeBSD */
|
|
|
|
# if defined __arm__ || defined __armhf__ || (defined __arm64__ || defined __aarch64__)
|
|
|
|
# define SIGSEGV_FAULT_HANDLER_ARGLIST int sig, siginfo_t *sip, void *ucp
|
|
# define SIGSEGV_FAULT_ADDRESS sip->si_addr
|
|
# define SIGSEGV_FAULT_CONTEXT ((ucontext_t *) ucp)
|
|
|
|
# if defined __arm64__ || defined __aarch64__ /* 64-bit */
|
|
|
|
/* See sys/arm64/include/ucontext.h. */
|
|
|
|
# if defined __CHERI_PURE_CAPABILITY__
|
|
# define SIGSEGV_FAULT_STACKPOINTER ((ucontext_t *) ucp)->uc_mcontext.mc_capregs.cap_sp
|
|
# else
|
|
# define SIGSEGV_FAULT_STACKPOINTER ((ucontext_t *) ucp)->uc_mcontext.mc_gpregs.gp_sp
|
|
# endif
|
|
|
|
# elif defined __arm__ || defined __armhf__ /* 32-bit */
|
|
|
|
/* See sys/arm/include/ucontext.h. */
|
|
|
|
# define SIGSEGV_FAULT_STACKPOINTER ((ucontext_t *) ucp)->uc_mcontext.__gregs[_REG_SP]
|
|
|
|
# endif
|
|
|
|
# else
|
|
|
|
/* On FreeBSD 12, both of these approaches work. On FreeBSD derivatives, the
|
|
first one has more chances to work. */
|
|
# if 1
|
|
/* Use signal handlers without SA_SIGINFO. */
|
|
|
|
# define SIGSEGV_FAULT_HANDLER_ARGLIST int sig, int code, struct sigcontext *scp, void *addr
|
|
# define SIGSEGV_FAULT_ADDRESS addr
|
|
# define SIGSEGV_FAULT_CONTEXT scp
|
|
|
|
/* See sys/x86/include/signal.h. */
|
|
|
|
# if defined __x86_64__
|
|
/* 64 bit registers */
|
|
|
|
# define SIGSEGV_FAULT_STACKPOINTER scp->sc_rsp
|
|
|
|
# elif defined __i386__
|
|
/* 32 bit registers */
|
|
|
|
# define SIGSEGV_FAULT_STACKPOINTER scp->sc_esp
|
|
|
|
# endif
|
|
|
|
# else
|
|
/* Use signal handlers with SA_SIGINFO. */
|
|
|
|
# define SIGSEGV_FAULT_HANDLER_ARGLIST int sig, siginfo_t *sip, void *scp
|
|
# define SIGSEGV_FAULT_ADDRESS sip->si_addr
|
|
# define SIGSEGV_FAULT_CONTEXT ((struct sigcontext *) scp)
|
|
# define SIGSEGV_FAULT_ADDRESS_FROM_SIGINFO
|
|
|
|
/* See sys/x86/include/signal.h. */
|
|
|
|
# if defined __x86_64__
|
|
/* 64 bit registers */
|
|
|
|
# define SIGSEGV_FAULT_STACKPOINTER ((struct sigcontext *) scp)->sc_rsp
|
|
|
|
# elif defined __i386__
|
|
/* 32 bit registers */
|
|
|
|
# define SIGSEGV_FAULT_STACKPOINTER ((struct sigcontext *) scp)->sc_esp
|
|
|
|
# endif
|
|
|
|
# endif
|
|
|
|
# endif
|
|
|
|
#endif
|
|
|
|
#if defined __NetBSD__ /* NetBSD */
|
|
|
|
# define SIGSEGV_FAULT_HANDLER_ARGLIST int sig, siginfo_t *sip, void *ucp
|
|
# define SIGSEGV_FAULT_ADDRESS sip->si_addr
|
|
# define SIGSEGV_FAULT_CONTEXT ((ucontext_t *) ucp)
|
|
# define SIGSEGV_FAULT_ADDRESS_FROM_SIGINFO
|
|
|
|
/* _UC_MACHINE_SP is a platform independent macro.
|
|
Defined in <machine/mcontext.h>, see
|
|
https://cvsweb.netbsd.org/bsdweb.cgi/src/sys/arch/$arch/include/mcontext.h
|
|
Supported on alpha, amd64, i386, ia64, m68k, mips, powerpc, sparc since
|
|
NetBSD 2.0.
|
|
On i386, _UC_MACHINE_SP is the same as ->uc_mcontext.__gregs[_REG_UESP],
|
|
and apparently the same value as ->uc_mcontext.__gregs[_REG_ESP]. */
|
|
# ifdef _UC_MACHINE_SP
|
|
# define SIGSEGV_FAULT_STACKPOINTER _UC_MACHINE_SP ((ucontext_t *) ucp)
|
|
# endif
|
|
|
|
#endif
|
|
|
|
#if defined __OpenBSD__ /* OpenBSD */
|
|
|
|
# define SIGSEGV_FAULT_HANDLER_ARGLIST int sig, siginfo_t *sip, struct sigcontext *scp
|
|
# define SIGSEGV_FAULT_ADDRESS sip->si_addr
|
|
# define SIGSEGV_FAULT_CONTEXT scp
|
|
# define SIGSEGV_FAULT_ADDRESS_FROM_SIGINFO
|
|
|
|
# if defined __alpha__
|
|
|
|
/* See the definition of 'struct sigcontext' in
|
|
openbsd-src/sys/arch/alpha/include/signal.h. */
|
|
|
|
# define SIGSEGV_FAULT_STACKPOINTER scp->sc_regs[30]
|
|
|
|
# elif defined __arm__ || defined __armhf__
|
|
|
|
/* See the definition of 'struct sigcontext' in
|
|
openbsd-src/sys/arch/arm/include/signal.h. */
|
|
|
|
# define SIGSEGV_FAULT_STACKPOINTER scp->sc_usr_sp
|
|
|
|
# elif defined __hppa__ || defined __hppa64__
|
|
|
|
/* See the definition of 'struct sigcontext' in
|
|
openbsd-src/sys/arch/hppa/include/signal.h
|
|
and
|
|
openbsd-src/sys/arch/hppa64/include/signal.h. */
|
|
|
|
# define SIGSEGV_FAULT_STACKPOINTER scp->sc_regs[30]
|
|
|
|
# elif defined __x86_64__
|
|
/* 64 bit registers */
|
|
|
|
/* See the definition of 'struct sigcontext' in
|
|
openbsd-src/sys/arch/amd64/include/signal.h. */
|
|
|
|
# define SIGSEGV_FAULT_STACKPOINTER scp->sc_rsp
|
|
|
|
# elif defined __i386__
|
|
/* 32 bit registers */
|
|
|
|
/* See the definition of 'struct sigcontext' in
|
|
openbsd-src/sys/arch/i386/include/signal.h. */
|
|
|
|
# define SIGSEGV_FAULT_STACKPOINTER scp->sc_esp
|
|
|
|
# elif defined __m68k__
|
|
|
|
/* See the definition of 'struct sigcontext' in
|
|
openbsd-src/sys/arch/m68k/include/signal.h. */
|
|
|
|
# define SIGSEGV_FAULT_STACKPOINTER scp->sc_sp
|
|
|
|
# elif defined __m88k__
|
|
|
|
/* See the definition of 'struct sigcontext' in
|
|
openbsd-src/sys/arch/m88k/include/signal.h
|
|
and the definition of 'struct reg' in
|
|
openbsd-src/sys/arch/m88k/include/reg.h. */
|
|
|
|
# if OpenBSD >= 201211 /* OpenBSD version >= 5.2 */
|
|
# define SIGSEGV_FAULT_STACKPOINTER scp->sc_regs[31]
|
|
# else
|
|
# define SIGSEGV_FAULT_STACKPOINTER scp->sc_regs.r[31]
|
|
# endif
|
|
|
|
# elif defined __mips__ || defined __mipsn32__ || defined __mips64__
|
|
|
|
/* See the definition of 'struct sigcontext' in
|
|
openbsd-src/sys/arch/mips64/include/signal.h. */
|
|
|
|
# define SIGSEGV_FAULT_STACKPOINTER scp->sc_regs[29]
|
|
|
|
# elif defined __powerpc64__
|
|
|
|
/* See the definition of 'struct sigcontext' in
|
|
openbsd-src/sys/arch/powerpc64/include/signal.h. */
|
|
|
|
# define SIGSEGV_FAULT_STACKPOINTER scp->sc_sp
|
|
|
|
# elif defined __powerpc__
|
|
|
|
/* See the definition of 'struct sigcontext' and 'struct trapframe' in
|
|
openbsd-src/sys/arch/powerpc/include/signal.h. */
|
|
|
|
# define SIGSEGV_FAULT_STACKPOINTER scp->sc_frame.fixreg[1]
|
|
|
|
# elif defined __sh__
|
|
|
|
/* See the definition of 'struct sigcontext' in
|
|
openbsd-src/sys/arch/sh/include/signal.h
|
|
and the definition of 'struct reg' in
|
|
openbsd-src/sys/arch/sh/include/reg.h. */
|
|
|
|
# if OpenBSD >= 201211 /* OpenBSD version >= 5.2 */
|
|
# define SIGSEGV_FAULT_STACKPOINTER scp->sc_reg[20-15]
|
|
# else
|
|
# define SIGSEGV_FAULT_STACKPOINTER scp->sc_reg.r_r15
|
|
# endif
|
|
|
|
# elif defined __sparc__ || defined __sparc64__
|
|
|
|
/* See the definition of 'struct sigcontext' in
|
|
openbsd-src/sys/arch/sparc/include/signal.h
|
|
and
|
|
openbsd-src/sys/arch/sparc64/include/signal.h. */
|
|
|
|
# define SIGSEGV_FAULT_STACKPOINTER scp->sc_sp
|
|
|
|
# elif defined __vax__
|
|
|
|
/* See the definition of 'struct sigcontext' in
|
|
openbsd-src/sys/arch/vax/include/signal.h. */
|
|
|
|
# define SIGSEGV_FAULT_STACKPOINTER scp->sc_sp
|
|
|
|
# endif
|
|
|
|
#endif
|
|
|
|
#if (defined __APPLE__ && defined __MACH__) /* macOS */
|
|
|
|
# define SIGSEGV_FAULT_HANDLER_ARGLIST int sig, siginfo_t *sip, void *ucp
|
|
# define SIGSEGV_FAULT_ADDRESS sip->si_addr
|
|
# define SIGSEGV_FAULT_CONTEXT ((ucontext_t *) ucp)
|
|
# define SIGSEGV_FAULT_ADDRESS_FROM_SIGINFO
|
|
|
|
# if defined __x86_64__
|
|
|
|
/* See the definitions of
|
|
- 'ucontext_t' and 'struct __darwin_ucontext' in <sys/_types/_ucontext.h>,
|
|
- 'struct __darwin_mcontext64' in <i386/_mcontext.h>, and
|
|
- 'struct __darwin_x86_thread_state64' in <mach/i386/_structs.h>. */
|
|
# define SIGSEGV_FAULT_STACKPOINTER ((ucontext_t *) ucp)->uc_mcontext->__ss.__rsp
|
|
|
|
# elif defined __i386__
|
|
|
|
/* See the definitions of
|
|
- 'ucontext_t' and 'struct __darwin_ucontext' in <sys/_types/_ucontext.h>,
|
|
- 'struct __darwin_mcontext32' in <i386/_mcontext.h>, and
|
|
- 'struct __darwin_i386_thread_state' in <mach/i386/_structs.h>. */
|
|
# define SIGSEGV_FAULT_STACKPOINTER ((ucontext_t *) ucp)->uc_mcontext->__ss.__esp
|
|
|
|
# elif defined __arm64__
|
|
|
|
/* See the definitions of
|
|
- 'ucontext_t' and 'struct __darwin_ucontext' in <sys/_types/_ucontext.h>,
|
|
- 'struct __darwin_mcontext64' in <arm/_mcontext.h>, and
|
|
- 'struct __darwin_arm_thread_state64' in <mach/arm/_structs.h>. */
|
|
# define SIGSEGV_FAULT_STACKPOINTER ((ucontext_t *) ucp)->uc_mcontext->__ss.__sp
|
|
|
|
# elif defined __powerpc__
|
|
|
|
/* See the definitions of
|
|
- 'ucontext_t' and 'struct __darwin_ucontext' in <sys/_structs.h>,
|
|
- 'struct __darwin_mcontext' in <ppc/_structs.h>, and
|
|
- 'struct __darwin_ppc_thread_state' in <mach/ppc/_structs.h>. */
|
|
# if !(defined _STRUCT_MCONTEXT || defined _STRUCT_MCONTEXT32 || defined _STRUCT_MCONTEXT64)
|
|
/* Mac OS X 10.4 and earlier omitted the underscores. */
|
|
# define SIGSEGV_FAULT_STACKPOINTER ((ucontext_t *) ucp)->uc_mcontext->ss.r1
|
|
# else
|
|
# define SIGSEGV_FAULT_STACKPOINTER ((ucontext_t *) ucp)->uc_mcontext->__ss.__r1
|
|
# endif
|
|
|
|
# endif
|
|
|
|
#endif
|
|
|
|
#if defined _AIX /* AIX */
|
|
|
|
# define SIGSEGV_FAULT_HANDLER_ARGLIST int sig, siginfo_t *sip, void *ucp
|
|
# define SIGSEGV_FAULT_ADDRESS sip->si_addr
|
|
# define SIGSEGV_FAULT_CONTEXT ((ucontext_t *) ucp)
|
|
# define SIGSEGV_FAULT_ADDRESS_FROM_SIGINFO
|
|
|
|
# if defined __powerpc__ || defined __powerpc64__
|
|
# define SIGSEGV_FAULT_STACKPOINTER ((ucontext_t *) ucp)->uc_mcontext.jmp_context.gpr[1]
|
|
# endif
|
|
|
|
#endif
|
|
|
|
#if defined __sun /* Solaris */
|
|
|
|
# define SIGSEGV_FAULT_HANDLER_ARGLIST int sig, siginfo_t *sip, void *ucp
|
|
# define SIGSEGV_FAULT_ADDRESS sip->si_addr
|
|
# define SIGSEGV_FAULT_CONTEXT ((ucontext_t *) ucp)
|
|
# define SIGSEGV_FAULT_ADDRESS_FROM_SIGINFO
|
|
|
|
# if defined __x86_64__
|
|
/* 64 bit registers */
|
|
|
|
# define SIGSEGV_FAULT_STACKPOINTER ((ucontext_t *) ucp)->uc_mcontext.gregs[REG_RSP]
|
|
|
|
# elif defined __i386__
|
|
/* 32 bit registers */
|
|
|
|
# define SIGSEGV_FAULT_STACKPOINTER ((ucontext_t *) ucp)->uc_mcontext.gregs[ESP]
|
|
|
|
# elif defined __sparc__ || defined __sparc64__
|
|
|
|
# define SIGSEGV_FAULT_STACKPOINTER ((ucontext_t *) ucp)->uc_mcontext.gregs[REG_O6]
|
|
|
|
# if SOLARIS11
|
|
|
|
/* On Solaris 11.3/SPARC, both in 32-bit and 64-bit mode, when catching
|
|
stack overflow, the fault address is correct the first time, but is zero
|
|
or near zero the second time.
|
|
'truss tests/test-sigsegv-catch-stackoverflow1' shows it:
|
|
|
|
In 32-bit mode:
|
|
|
|
Incurred fault #6, FLTBOUNDS %pc = 0x000116E8
|
|
siginfo: SIGSEGV SEGV_MAPERR addr=0xFFB00000
|
|
Received signal #11, SIGSEGV [caught]
|
|
siginfo: SIGSEGV SEGV_MAPERR addr=0xFFB00000
|
|
then
|
|
Incurred fault #6, FLTBOUNDS %pc = 0x000116E8
|
|
siginfo: SIGSEGV SEGV_MAPERR addr=0x00000008
|
|
Received signal #11, SIGSEGV [caught]
|
|
siginfo: SIGSEGV SEGV_MAPERR addr=0x00000008
|
|
|
|
In 64-bit mode:
|
|
|
|
Incurred fault #6, FLTBOUNDS %pc = 0x100001C58
|
|
siginfo: SIGSEGV SEGV_MAPERR addr=0xFFFFFFFF7FF00000
|
|
Received signal #11, SIGSEGV [caught]
|
|
siginfo: SIGSEGV SEGV_MAPERR addr=0xFFFFFFFF7FF00000
|
|
then
|
|
Incurred fault #6, FLTBOUNDS %pc = 0x100001C58
|
|
siginfo: SIGSEGV SEGV_MAPERR addr=0x00000000
|
|
Received signal #11, SIGSEGV [caught]
|
|
siginfo: SIGSEGV SEGV_MAPERR addr=0x00000000
|
|
*/
|
|
# define BOGUS_FAULT_ADDRESS_UPON_STACK_OVERFLOW
|
|
|
|
# endif
|
|
|
|
# endif
|
|
|
|
#endif
|
|
|
|
#if defined __CYGWIN__ /* Cygwin */
|
|
|
|
# define SIGSEGV_FAULT_HANDLER_ARGLIST int sig, siginfo_t *sip, void *ucp
|
|
# define SIGSEGV_FAULT_ADDRESS sip->si_addr
|
|
# define SIGSEGV_FAULT_CONTEXT ((ucontext_t *) ucp)
|
|
# define SIGSEGV_FAULT_ADDRESS_FROM_SIGINFO
|
|
|
|
/* See the definition of 'ucontext_t' in <sys/ucontext.h> and
|
|
of 'struct __mcontext' in <cygwin/signal.h>. */
|
|
# if defined __x86_64__
|
|
/* 64 bit registers */
|
|
# define SIGSEGV_FAULT_STACKPOINTER ((ucontext_t *) ucp)->uc_mcontext.rsp
|
|
# elif defined __i386__
|
|
/* 32 bit registers */
|
|
# define SIGSEGV_FAULT_STACKPOINTER ((ucontext_t *) ucp)->uc_mcontext.esp
|
|
# endif
|
|
|
|
#endif
|
|
|
|
#if defined __HAIKU__ /* Haiku */
|
|
|
|
# define SIGSEGV_FAULT_HANDLER_ARGLIST int sig, siginfo_t *sip, void *ucp
|
|
# define SIGSEGV_FAULT_ADDRESS sip->si_addr
|
|
# define SIGSEGV_FAULT_CONTEXT ((ucontext_t *) ucp)
|
|
# define SIGSEGV_FAULT_ADDRESS_FROM_SIGINFO
|
|
|
|
# if defined __x86_64__
|
|
/* 64 bit registers */
|
|
|
|
/* See the definition of 'ucontext_t' in <signal.h> and
|
|
of 'struct vregs' in <arch/x86_64/signal.h>. */
|
|
|
|
# define SIGSEGV_FAULT_STACKPOINTER ((ucontext_t *) ucp)->uc_mcontext.rsp
|
|
|
|
# elif defined __i386__
|
|
/* 32 bit registers */
|
|
|
|
/* See the definition of 'ucontext_t' in <signal.h> and
|
|
of 'struct vregs' in <arch/x86/signal.h>. */
|
|
|
|
# define SIGSEGV_FAULT_STACKPOINTER ((ucontext_t *) ucp)->uc_mcontext.esp
|
|
|
|
# endif
|
|
|
|
#endif
|
|
|
|
/* ========================================================================== */
|
|
|
|
/* List of signals that are sent when an invalid virtual memory address
|
|
is accessed, or when the stack overflows. */
|
|
#if defined __gnu_hurd__ \
|
|
|| defined __FreeBSD_kernel__ || defined __FreeBSD__ || defined __DragonFly__ \
|
|
|| defined __NetBSD__ || defined __OpenBSD__ \
|
|
|| (defined __APPLE__ && defined __MACH__)
|
|
# if defined __CHERI__
|
|
# define SIGSEGV_FOR_ALL_SIGNALS(var,body) \
|
|
{ int var; \
|
|
var = SIGSEGV; { body } \
|
|
var = SIGBUS; { body } \
|
|
var = SIGPROT; { body } \
|
|
}
|
|
# else
|
|
# define SIGSEGV_FOR_ALL_SIGNALS(var,body) \
|
|
{ int var; \
|
|
var = SIGSEGV; { body } \
|
|
var = SIGBUS; { body } \
|
|
}
|
|
# endif
|
|
#else
|
|
# define SIGSEGV_FOR_ALL_SIGNALS(var,body) \
|
|
{ int var; var = SIGSEGV; { body } }
|
|
#endif
|
|
|
|
/* ========================================================================== */
|
|
|
|
/* Determine the virtual memory area of a given address. */
|
|
#include "stackvma.h"
|
|
|
|
/* ========================================================================== */
|
|
|
|
/* On the average Unix platform, we define
|
|
|
|
HAVE_SIGSEGV_RECOVERY
|
|
if there is a fault-*.h include file which defines
|
|
SIGSEGV_FAULT_HANDLER_ARGLIST and SIGSEGV_FAULT_ADDRESS.
|
|
|
|
HAVE_STACK_OVERFLOW_RECOVERY
|
|
if HAVE_SIGALTSTACK is set and
|
|
at least two of the following are true:
|
|
A) There is a fault-*.h include file which defines
|
|
SIGSEGV_FAULT_HANDLER_ARGLIST and SIGSEGV_FAULT_ADDRESS.
|
|
B) There is a fault-*.h include file which defines
|
|
SIGSEGV_FAULT_HANDLER_ARGLIST and SIGSEGV_FAULT_STACKPOINTER.
|
|
C) There is a stackvma-*.c, other than stackvma-none.c, which
|
|
defines sigsegv_get_vma.
|
|
|
|
Why? Obviously, to catch stack overflow, we need an alternate signal
|
|
stack; this requires kernel support. But we also need to distinguish
|
|
(with a reasonable confidence) a stack overflow from a regular SIGSEGV.
|
|
If we have A) and B), we use the
|
|
Heuristic AB: If the fault address is near the stack pointer, it's a
|
|
stack overflow.
|
|
If we have A) and C), we use the
|
|
Heuristic AC: If the fault address is near and beyond the bottom of
|
|
the stack's virtual memory area, it's a stack overflow.
|
|
If we have B) and C), we use the
|
|
Heuristic BC: If the stack pointer is near the bottom of the stack's
|
|
virtual memory area, it's a stack overflow.
|
|
This heuristic comes in two flavours: On OSes which let the stack's
|
|
VMA grow continuously, we determine the bottom by use of getrlimit().
|
|
On OSes which preallocate the stack's VMA with its maximum size
|
|
(like BeOS), we use the stack's VMA directly.
|
|
*/
|
|
|
|
#if HAVE_SIGSEGV_RECOVERY \
|
|
&& !(defined SIGSEGV_FAULT_HANDLER_ARGLIST && defined SIGSEGV_FAULT_ADDRESS)
|
|
# error "You need to define SIGSEGV_FAULT_HANDLER_ARGLIST and SIGSEGV_FAULT_ADDRESS before you can define HAVE_SIGSEGV_RECOVERY."
|
|
#endif
|
|
#if !HAVE_SIGSEGV_RECOVERY \
|
|
&& (defined SIGSEGV_FAULT_HANDLER_ARGLIST && defined SIGSEGV_FAULT_ADDRESS) \
|
|
&& !(defined __FreeBSD__ && (defined __sparc__ || defined __sparc64__))
|
|
# if __GNUC__ || (__clang_major__ >= 4)
|
|
# warning "You can define HAVE_SIGSEGV_RECOVERY on this platform."
|
|
# else
|
|
# error "You can define HAVE_SIGSEGV_RECOVERY on this platform."
|
|
# endif
|
|
#endif
|
|
|
|
#if HAVE_STACK_OVERFLOW_RECOVERY \
|
|
&& !(defined SIGSEGV_FAULT_ADDRESS + defined SIGSEGV_FAULT_STACKPOINTER + HAVE_STACKVMA >= 2)
|
|
# error "You need to define two of SIGSEGV_FAULT_ADDRESS, SIGSEGV_FAULT_STACKPOINTER, HAVE_STACKVMA, before you can define HAVE_STACK_OVERFLOW_RECOVERY."
|
|
#endif
|
|
#if !HAVE_STACK_OVERFLOW_RECOVERY \
|
|
&& (defined SIGSEGV_FAULT_ADDRESS + defined SIGSEGV_FAULT_STACKPOINTER + HAVE_STACKVMA >= 2) \
|
|
&& !(defined __FreeBSD__ && (defined __sparc__ || defined __sparc64__)) \
|
|
&& !(defined __NetBSD__ && (defined __sparc__ || defined __sparc64__))
|
|
# if __GNUC__ || (__clang_major__ >= 4)
|
|
# warning "You can define HAVE_STACK_OVERFLOW_RECOVERY on this platform."
|
|
# else
|
|
# error "You can define HAVE_STACK_OVERFLOW_RECOVERY on this platform."
|
|
# endif
|
|
#endif
|
|
|
|
/* ========================================================================== */
|
|
|
|
#if HAVE_STACK_OVERFLOW_RECOVERY
|
|
|
|
/* ======= Leaving a signal handler executing on the alternate stack ======= */
|
|
|
|
/* Platform dependent:
|
|
Leaving a signal handler executing on the alternate stack. */
|
|
static void sigsegv_reset_onstack_flag (void);
|
|
|
|
/* -------------------------- leave-sigaltstack.c -------------------------- */
|
|
|
|
# if defined __gnu_hurd__ \
|
|
|| defined __FreeBSD_kernel__ || defined __FreeBSD__ || defined __DragonFly__ \
|
|
|| defined __NetBSD__ || defined __OpenBSD__
|
|
|
|
static void
|
|
sigsegv_reset_onstack_flag (void)
|
|
{
|
|
stack_t ss;
|
|
|
|
if (sigaltstack (NULL, &ss) >= 0)
|
|
{
|
|
ss.ss_flags &= ~SS_ONSTACK;
|
|
sigaltstack (&ss, NULL);
|
|
}
|
|
}
|
|
|
|
/* --------------------------- leave-setcontext.c --------------------------- */
|
|
|
|
# elif defined __sun /* Solaris */
|
|
|
|
# include <ucontext.h>
|
|
|
|
static void
|
|
sigsegv_reset_onstack_flag (void)
|
|
{
|
|
ucontext_t uc;
|
|
|
|
if (getcontext (&uc) >= 0)
|
|
/* getcontext returns twice. We are interested in the returned context
|
|
only the first time, i.e. when the SS_ONSTACK bit is set. */
|
|
if (uc.uc_stack.ss_flags & SS_ONSTACK)
|
|
{
|
|
uc.uc_stack.ss_flags &= ~SS_ONSTACK;
|
|
/* Note that setcontext() does not refill uc. Therefore if
|
|
setcontext() keeps SS_ONSTACK set in the kernel, either
|
|
setcontext() will return -1 or getcontext() will return a
|
|
second time, with the SS_ONSTACK bit being cleared. */
|
|
setcontext (&uc);
|
|
}
|
|
}
|
|
|
|
/* ------------------------------ leave-nop.c ------------------------------ */
|
|
|
|
# else
|
|
|
|
static void
|
|
sigsegv_reset_onstack_flag (void)
|
|
{
|
|
/* Nothing to do. sigaltstack() simply looks at the stack pointer,
|
|
therefore SS_ONSTACK is not sticky. */
|
|
}
|
|
|
|
# endif
|
|
|
|
/* ========================================================================== */
|
|
|
|
# if HAVE_STACKVMA
|
|
|
|
/* Address of the last byte belonging to the stack vma. */
|
|
static uintptr_t stack_top = 0;
|
|
|
|
/* Needs to be called once only. */
|
|
static void
|
|
remember_stack_top (void *some_variable_on_stack)
|
|
{
|
|
struct vma_struct vma;
|
|
|
|
if (sigsegv_get_vma ((uintptr_t) some_variable_on_stack, &vma) >= 0)
|
|
stack_top = vma.end - 1;
|
|
}
|
|
|
|
# endif /* HAVE_STACKVMA */
|
|
|
|
static stackoverflow_handler_t stk_user_handler = (stackoverflow_handler_t)NULL;
|
|
static uintptr_t stk_extra_stack;
|
|
static size_t stk_extra_stack_size;
|
|
|
|
#endif /* HAVE_STACK_OVERFLOW_RECOVERY */
|
|
|
|
#if HAVE_SIGSEGV_RECOVERY
|
|
|
|
/* User's SIGSEGV handler. */
|
|
static sigsegv_handler_t user_handler = (sigsegv_handler_t)NULL;
|
|
|
|
#endif /* HAVE_SIGSEGV_RECOVERY */
|
|
|
|
|
|
/* Our SIGSEGV handler, with OS dependent argument list. */
|
|
|
|
#if HAVE_SIGSEGV_RECOVERY
|
|
|
|
static void
|
|
sigsegv_handler (SIGSEGV_FAULT_HANDLER_ARGLIST)
|
|
{
|
|
void *address = (void *) (SIGSEGV_FAULT_ADDRESS);
|
|
|
|
# if HAVE_STACK_OVERFLOW_RECOVERY
|
|
# if !(HAVE_STACKVMA || defined SIGSEGV_FAULT_STACKPOINTER)
|
|
#error "Insufficient heuristics for detecting a stack overflow. Either define CFG_STACKVMA and HAVE_STACKVMA correctly, or define SIGSEGV_FAULT_STACKPOINTER correctly, or undefine HAVE_STACK_OVERFLOW_RECOVERY!"
|
|
# endif
|
|
|
|
/* Call user's handler. */
|
|
if (user_handler && (*user_handler) (address, 0))
|
|
{
|
|
/* Handler successful. */
|
|
}
|
|
else
|
|
{
|
|
/* Handler declined responsibility. */
|
|
|
|
/* Did the user install a stack overflow handler? */
|
|
if (stk_user_handler)
|
|
{
|
|
/* See whether it was a stack overflow. If so, longjump away. */
|
|
# ifdef SIGSEGV_FAULT_STACKPOINTER
|
|
uintptr_t old_sp = (uintptr_t) (SIGSEGV_FAULT_STACKPOINTER);
|
|
# ifdef __ia64
|
|
uintptr_t old_bsp = (uintptr_t) (SIGSEGV_FAULT_BSP_POINTER);
|
|
# endif
|
|
# endif
|
|
|
|
# if HAVE_STACKVMA
|
|
/* Were we able to determine the stack top? */
|
|
if (stack_top)
|
|
{
|
|
/* Determine stack bounds. */
|
|
int saved_errno = errno;
|
|
struct vma_struct vma;
|
|
int ret = sigsegv_get_vma (stack_top, &vma);
|
|
errno = saved_errno;
|
|
if (ret >= 0)
|
|
{
|
|
# ifndef BOGUS_FAULT_ADDRESS_UPON_STACK_OVERFLOW
|
|
/* Heuristic AC: If the fault_address is nearer to the stack
|
|
segment's [start,end] than to the previous segment, we
|
|
consider it a stack overflow.
|
|
In the case of IA-64, we know that the previous segment
|
|
is the up-growing bsp segment, and either of the two
|
|
stacks can overflow. */
|
|
uintptr_t addr = (uintptr_t) address;
|
|
|
|
# ifdef __ia64
|
|
if (addr >= vma.prev_end && addr <= vma.end - 1)
|
|
# else
|
|
# if STACK_DIRECTION < 0
|
|
if (addr >= vma.start
|
|
? (addr <= vma.end - 1)
|
|
: vma.is_near_this (addr, &vma))
|
|
# else
|
|
if (addr <= vma.end - 1
|
|
? (addr >= vma.start)
|
|
: vma.is_near_this (addr, &vma))
|
|
# endif
|
|
# endif
|
|
{
|
|
# else /* BOGUS_FAULT_ADDRESS_UPON_STACK_OVERFLOW */
|
|
# if HAVE_GETRLIMIT && defined RLIMIT_STACK
|
|
/* Heuristic BC: If the stack size has reached its maximal size,
|
|
and old_sp is near the low end, we consider it a stack
|
|
overflow. */
|
|
saved_errno = errno;
|
|
struct rlimit rl;
|
|
ret = getrlimit (RLIMIT_STACK, &rl);
|
|
errno = saved_errno;
|
|
if (ret >= 0)
|
|
{
|
|
uintptr_t current_stack_size = vma.end - vma.start;
|
|
uintptr_t max_stack_size = rl.rlim_cur;
|
|
if (current_stack_size <= max_stack_size + 4096
|
|
&& max_stack_size <= current_stack_size + 4096
|
|
# else
|
|
{
|
|
if (1
|
|
# endif
|
|
# ifdef SIGSEGV_FAULT_STACKPOINTER
|
|
/* Heuristic BC: If we know old_sp, and it is neither
|
|
near the low end, nor in the alternate stack, then
|
|
it's probably not a stack overflow. */
|
|
&& ((old_sp >= stk_extra_stack
|
|
&& old_sp <= stk_extra_stack + stk_extra_stack_size)
|
|
# if STACK_DIRECTION < 0
|
|
|| (old_sp <= vma.start + 4096
|
|
&& vma.start <= old_sp + 4096))
|
|
# else
|
|
|| (old_sp <= vma.end + 4096
|
|
&& vma.end <= old_sp + 4096))
|
|
# endif
|
|
# endif
|
|
)
|
|
# endif /* BOGUS_FAULT_ADDRESS_UPON_STACK_OVERFLOW */
|
|
# else /* !HAVE_STACKVMA */
|
|
/* Heuristic AB: If the fault address is near the stack pointer,
|
|
it's a stack overflow. */
|
|
uintptr_t addr = (uintptr_t) address;
|
|
|
|
if ((addr <= old_sp + 4096 && old_sp <= addr + 4096)
|
|
# ifdef __ia64
|
|
|| (addr <= old_bsp + 4096 && old_bsp <= addr + 4096)
|
|
# endif
|
|
)
|
|
{
|
|
{
|
|
{
|
|
# endif /* !HAVE_STACKVMA */
|
|
{
|
|
# ifdef SIGSEGV_FAULT_STACKPOINTER
|
|
int emergency =
|
|
(old_sp >= stk_extra_stack
|
|
&& old_sp <= stk_extra_stack + stk_extra_stack_size);
|
|
stackoverflow_context_t context = (SIGSEGV_FAULT_CONTEXT);
|
|
# else
|
|
int emergency = 0;
|
|
stackoverflow_context_t context = (void *) 0;
|
|
# endif
|
|
/* Call user's handler. */
|
|
(*stk_user_handler) (emergency, context);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
# endif /* HAVE_STACK_OVERFLOW_RECOVERY */
|
|
|
|
if (user_handler && (*user_handler) (address, 1))
|
|
{
|
|
/* Handler successful. */
|
|
}
|
|
else
|
|
{
|
|
/* Handler declined responsibility for real. */
|
|
|
|
/* Remove ourselves and dump core. */
|
|
SIGSEGV_FOR_ALL_SIGNALS (signo, signal (signo, SIG_DFL);)
|
|
}
|
|
|
|
# if HAVE_STACK_OVERFLOW_RECOVERY
|
|
}
|
|
# endif /* HAVE_STACK_OVERFLOW_RECOVERY */
|
|
}
|
|
|
|
#elif HAVE_STACK_OVERFLOW_RECOVERY
|
|
|
|
static void
|
|
# ifdef SIGSEGV_FAULT_STACKPOINTER
|
|
sigsegv_handler (SIGSEGV_FAULT_HANDLER_ARGLIST)
|
|
# else
|
|
sigsegv_handler (int sig)
|
|
# endif
|
|
{
|
|
# if !((HAVE_GETRLIMIT && defined RLIMIT_STACK) || defined SIGSEGV_FAULT_STACKPOINTER)
|
|
# error "Insufficient heuristics for detecting a stack overflow. Either define SIGSEGV_FAULT_STACKPOINTER correctly, or undefine HAVE_STACK_OVERFLOW_RECOVERY!"
|
|
# endif
|
|
|
|
/* Did the user install a handler? */
|
|
if (stk_user_handler)
|
|
{
|
|
/* See whether it was a stack overflow. If so, longjump away. */
|
|
# ifdef SIGSEGV_FAULT_STACKPOINTER
|
|
uintptr_t old_sp = (uintptr_t) (SIGSEGV_FAULT_STACKPOINTER);
|
|
# endif
|
|
|
|
/* Were we able to determine the stack top? */
|
|
if (stack_top)
|
|
{
|
|
/* Determine stack bounds. */
|
|
int saved_errno = errno;
|
|
struct vma_struct vma;
|
|
int ret = sigsegv_get_vma (stack_top, &vma);
|
|
errno = saved_errno;
|
|
if (ret >= 0)
|
|
{
|
|
# if HAVE_GETRLIMIT && defined RLIMIT_STACK
|
|
/* Heuristic BC: If the stack size has reached its maximal size,
|
|
and old_sp is near the low end, we consider it a stack
|
|
overflow. */
|
|
saved_errno = errno;
|
|
struct rlimit rl;
|
|
ret = getrlimit (RLIMIT_STACK, &rl);
|
|
errno = saved_errno;
|
|
if (ret >= 0)
|
|
{
|
|
uintptr_t current_stack_size = vma.end - vma.start;
|
|
uintptr_t max_stack_size = rl.rlim_cur;
|
|
if (current_stack_size <= max_stack_size + 4096
|
|
&& max_stack_size <= current_stack_size + 4096
|
|
# else
|
|
{
|
|
if (1
|
|
# endif
|
|
# ifdef SIGSEGV_FAULT_STACKPOINTER
|
|
/* Heuristic BC: If we know old_sp, and it is neither
|
|
near the low end, nor in the alternate stack, then
|
|
it's probably not a stack overflow. */
|
|
&& ((old_sp >= stk_extra_stack
|
|
&& old_sp <= stk_extra_stack + stk_extra_stack_size)
|
|
# if STACK_DIRECTION < 0
|
|
|| (old_sp <= vma.start + 4096
|
|
&& vma.start <= old_sp + 4096))
|
|
# else
|
|
|| (old_sp <= vma.end + 4096
|
|
&& vma.end <= old_sp + 4096))
|
|
# endif
|
|
# endif
|
|
)
|
|
{
|
|
# ifdef SIGSEGV_FAULT_STACKPOINTER
|
|
int emergency =
|
|
(old_sp >= stk_extra_stack
|
|
&& old_sp <= stk_extra_stack + stk_extra_stack_size);
|
|
stackoverflow_context_t context = (SIGSEGV_FAULT_CONTEXT);
|
|
# else
|
|
int emergency = 0;
|
|
stackoverflow_context_t context = (void *) 0;
|
|
# endif
|
|
/* Call user's handler. */
|
|
(*stk_user_handler)(emergency,context);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
/* Remove ourselves and dump core. */
|
|
SIGSEGV_FOR_ALL_SIGNALS (signo, signal (signo, SIG_DFL);)
|
|
}
|
|
|
|
#endif
|
|
|
|
|
|
#if HAVE_SIGSEGV_RECOVERY || HAVE_STACK_OVERFLOW_RECOVERY
|
|
|
|
static void
|
|
install_for (int sig)
|
|
{
|
|
struct sigaction action;
|
|
|
|
# ifdef SIGSEGV_FAULT_ADDRESS_FROM_SIGINFO
|
|
action.sa_sigaction = (void (*) (int, siginfo_t *, void *)) &sigsegv_handler;
|
|
# else
|
|
action.sa_handler = (void (*) (int)) &sigsegv_handler;
|
|
# endif
|
|
/* Block most signals while SIGSEGV is being handled. */
|
|
/* Signals SIGKILL, SIGSTOP cannot be blocked. */
|
|
/* Signals SIGCONT, SIGTSTP, SIGTTIN, SIGTTOU are not blocked because
|
|
dealing with these signals seems dangerous. */
|
|
/* Signals SIGILL, SIGABRT, SIGFPE, SIGSEGV, SIGTRAP, SIGIOT, SIGEMT, SIGBUS,
|
|
SIGSYS, SIGSTKFLT are not blocked because these are synchronous signals,
|
|
which may require immediate intervention, otherwise the process may
|
|
starve. */
|
|
sigemptyset (&action.sa_mask);
|
|
# ifdef SIGHUP
|
|
sigaddset (&action.sa_mask,SIGHUP);
|
|
# endif
|
|
# ifdef SIGINT
|
|
sigaddset (&action.sa_mask,SIGINT);
|
|
# endif
|
|
# ifdef SIGQUIT
|
|
sigaddset (&action.sa_mask,SIGQUIT);
|
|
# endif
|
|
# ifdef SIGPIPE
|
|
sigaddset (&action.sa_mask,SIGPIPE);
|
|
# endif
|
|
# ifdef SIGALRM
|
|
sigaddset (&action.sa_mask,SIGALRM);
|
|
# endif
|
|
# ifdef SIGTERM
|
|
sigaddset (&action.sa_mask,SIGTERM);
|
|
# endif
|
|
# ifdef SIGUSR1
|
|
sigaddset (&action.sa_mask,SIGUSR1);
|
|
# endif
|
|
# ifdef SIGUSR2
|
|
sigaddset (&action.sa_mask,SIGUSR2);
|
|
# endif
|
|
# ifdef SIGCHLD
|
|
sigaddset (&action.sa_mask,SIGCHLD);
|
|
# endif
|
|
# ifdef SIGCLD
|
|
sigaddset (&action.sa_mask,SIGCLD);
|
|
# endif
|
|
# ifdef SIGURG
|
|
sigaddset (&action.sa_mask,SIGURG);
|
|
# endif
|
|
# ifdef SIGIO
|
|
sigaddset (&action.sa_mask,SIGIO);
|
|
# endif
|
|
# ifdef SIGPOLL
|
|
sigaddset (&action.sa_mask,SIGPOLL);
|
|
# endif
|
|
# ifdef SIGXCPU
|
|
sigaddset (&action.sa_mask,SIGXCPU);
|
|
# endif
|
|
# ifdef SIGXFSZ
|
|
sigaddset (&action.sa_mask,SIGXFSZ);
|
|
# endif
|
|
# ifdef SIGVTALRM
|
|
sigaddset (&action.sa_mask,SIGVTALRM);
|
|
# endif
|
|
# ifdef SIGPROF
|
|
sigaddset (&action.sa_mask,SIGPROF);
|
|
# endif
|
|
# ifdef SIGPWR
|
|
sigaddset (&action.sa_mask,SIGPWR);
|
|
# endif
|
|
# ifdef SIGLOST
|
|
sigaddset (&action.sa_mask,SIGLOST);
|
|
# endif
|
|
# ifdef SIGWINCH
|
|
sigaddset (&action.sa_mask,SIGWINCH);
|
|
# endif
|
|
/* Note that sigaction() implicitly adds sig itself to action.sa_mask. */
|
|
/* Ask the OS to provide a structure siginfo_t to the handler. */
|
|
# ifdef SIGSEGV_FAULT_ADDRESS_FROM_SIGINFO
|
|
action.sa_flags = SA_SIGINFO;
|
|
# else
|
|
action.sa_flags = 0;
|
|
# endif
|
|
# if HAVE_STACK_OVERFLOW_RECOVERY && HAVE_SIGALTSTACK /* not BeOS */
|
|
/* Work around Linux 2.2.5 bug: If SA_ONSTACK is specified but sigaltstack()
|
|
has not been called, the kernel will busy loop, eating CPU time. So
|
|
avoid setting SA_ONSTACK until the user has requested stack overflow
|
|
handling. */
|
|
if (stk_user_handler)
|
|
action.sa_flags |= SA_ONSTACK;
|
|
# endif
|
|
sigaction (sig, &action, (struct sigaction *) NULL);
|
|
}
|
|
|
|
#endif /* HAVE_SIGSEGV_RECOVERY || HAVE_STACK_OVERFLOW_RECOVERY */
|
|
|
|
int
|
|
sigsegv_install_handler (sigsegv_handler_t handler)
|
|
{
|
|
#if HAVE_SIGSEGV_RECOVERY
|
|
user_handler = handler;
|
|
|
|
SIGSEGV_FOR_ALL_SIGNALS (sig, install_for (sig);)
|
|
|
|
return 0;
|
|
#else
|
|
return -1;
|
|
#endif
|
|
}
|
|
|
|
void
|
|
sigsegv_deinstall_handler (void)
|
|
{
|
|
#if HAVE_SIGSEGV_RECOVERY
|
|
user_handler = (sigsegv_handler_t)NULL;
|
|
|
|
# if HAVE_STACK_OVERFLOW_RECOVERY
|
|
if (!stk_user_handler)
|
|
# endif
|
|
{
|
|
SIGSEGV_FOR_ALL_SIGNALS (sig, signal (sig, SIG_DFL);)
|
|
}
|
|
#endif
|
|
}
|
|
|
|
int
|
|
sigsegv_leave_handler (void (*continuation) (void*, void*, void*),
|
|
void* cont_arg1, void* cont_arg2, void* cont_arg3)
|
|
{
|
|
#if HAVE_STACK_OVERFLOW_RECOVERY
|
|
/*
|
|
* Reset the system's knowledge that we are executing on the alternate
|
|
* stack. If we didn't do that, siglongjmp would be needed instead of
|
|
* longjmp to leave the signal handler.
|
|
*/
|
|
sigsegv_reset_onstack_flag ();
|
|
#endif
|
|
(*continuation) (cont_arg1, cont_arg2, cont_arg3);
|
|
return 1;
|
|
}
|
|
|
|
int
|
|
stackoverflow_install_handler (stackoverflow_handler_t handler,
|
|
void *extra_stack, size_t extra_stack_size)
|
|
{
|
|
#if HAVE_STACK_OVERFLOW_RECOVERY
|
|
# if HAVE_STACKVMA
|
|
if (!stack_top)
|
|
{
|
|
int dummy;
|
|
remember_stack_top (&dummy);
|
|
if (!stack_top)
|
|
return -1;
|
|
}
|
|
# endif
|
|
|
|
stk_user_handler = handler;
|
|
stk_extra_stack = (uintptr_t) extra_stack;
|
|
stk_extra_stack_size = extra_stack_size;
|
|
{
|
|
stack_t ss;
|
|
ss.ss_sp = extra_stack;
|
|
ss.ss_size = extra_stack_size;
|
|
ss.ss_flags = 0; /* no SS_DISABLE */
|
|
if (sigaltstack (&ss, (stack_t*)0) < 0)
|
|
return -1;
|
|
}
|
|
|
|
/* Install the signal handlers with SA_ONSTACK. */
|
|
SIGSEGV_FOR_ALL_SIGNALS (sig, install_for (sig);)
|
|
return 0;
|
|
#else
|
|
return -1;
|
|
#endif
|
|
}
|
|
|
|
void
|
|
stackoverflow_deinstall_handler (void)
|
|
{
|
|
#if HAVE_STACK_OVERFLOW_RECOVERY
|
|
stk_user_handler = (stackoverflow_handler_t) NULL;
|
|
|
|
# if HAVE_SIGSEGV_RECOVERY
|
|
if (user_handler)
|
|
{
|
|
/* Reinstall the signal handlers without SA_ONSTACK, to avoid Linux
|
|
bug. */
|
|
SIGSEGV_FOR_ALL_SIGNALS (sig, install_for (sig);)
|
|
}
|
|
else
|
|
# endif
|
|
{
|
|
SIGSEGV_FOR_ALL_SIGNALS (sig, signal (sig, SIG_DFL);)
|
|
}
|
|
|
|
{
|
|
stack_t ss;
|
|
ss.ss_flags = SS_DISABLE;
|
|
if (sigaltstack (&ss, (stack_t *) 0) < 0)
|
|
perror ("gnulib sigsegv (stackoverflow_deinstall_handler)");
|
|
}
|
|
#endif
|
|
}
|