;; z Constant call address operand.
;; C Integer SSE constant with all bits set operand.
;; F Floating-point SSE constant with all bits set operand.
+;; M x86-64 memory operand.
(define_constraint "Bf"
"@internal Flags register operand."
(and (match_test "TARGET_SSE")
(match_operand 0 "float_vector_all_ones_operand")))
+;; NB: Similar to 'm', but don't use define_memory_constraint on x86-64
+;; to prevent LRA from converting the operand to the form '(mem (reg X))'
+;; where X is a base register.
+(define_constraint "BM"
+ "@internal x86-64 memory operand."
+ (and (match_code "mem")
+ (match_test "memory_address_addr_space_p (GET_MODE (op), XEXP (op, 0),
+ MEM_ADDR_SPACE (op))")))
+
;; Integer constant constraints.
(define_constraint "Wb"
"Integer constant in the range 0 @dots{} 7, for 8-bit shifts."
;; General operand constraint for word modes.
(define_mode_attr g [(QI "qmn") (HI "rmn") (SI "rme") (DI "rme")])
+;; Memory operand constraint for word modes.
+(define_mode_attr m [(QI "m") (HI "m") (SI "BM") (DI "BM")])
+
;; Immediate operand constraint for double integer modes.
(define_mode_attr di [(SI "nF") (DI "Wd")])
(define_insn "*cmp<mode>_1"
[(set (reg FLAGS_REG)
(compare (match_operand:SWI 0 "nonimmediate_operand" "<r>m,<r>")
- (match_operand:SWI 1 "<general_operand>" "<r><i>,<r>m")))]
+ (match_operand:SWI 1 "<general_operand>" "<r><i>,<r><m>")))]
"ix86_match_ccmode (insn, CCmode)"
"cmp{<imodesuffix>}\t{%1, %0|%0, %1}"
[(set_attr "type" "icmp")
[(set (reg FLAGS_REG)
(compare
(minus:SWI (match_operand:SWI 0 "nonimmediate_operand" "<r>m,<r>")
- (match_operand:SWI 1 "<general_operand>" "<r><i>,<r>m"))
+ (match_operand:SWI 1 "<general_operand>" "<r><i>,<r><m>"))
(const_int 0)))]
"ix86_match_ccmode (insn, CCGOCmode)"
"cmp{<imodesuffix>}\t{%1, %0|%0, %1}"
[(set (match_operand:SWI48 0 "nonimmediate_operand" "=rm,r,r,r")
(plus:SWI48
(match_operand:SWI48 1 "nonimmediate_operand" "%0,0,r,r")
- (match_operand:SWI48 2 "x86_64_general_operand" "re,m,0,le")))
+ (match_operand:SWI48 2 "x86_64_general_operand" "re,BM,0,le")))
(clobber (reg:CC FLAGS_REG))]
"ix86_binary_operator_ok (PLUS, <MODE>mode, operands)"
{
[(set (match_operand:DI 0 "register_operand" "=r,r,r")
(zero_extend:DI
(plus:SI (match_operand:SI 1 "nonimmediate_operand" "%0,r,r")
- (match_operand:SI 2 "x86_64_general_operand" "rme,0,le"))))
+ (match_operand:SI 2 "x86_64_general_operand" "rBMe,0,le"))))
(clobber (reg:CC FLAGS_REG))]
"TARGET_64BIT && ix86_binary_operator_ok (PLUS, SImode, operands)"
{
(compare
(plus:SWI
(match_operand:SWI 1 "nonimmediate_operand" "%0,0,<r>")
- (match_operand:SWI 2 "<general_operand>" "<r><i>,m,0"))
+ (match_operand:SWI 2 "<general_operand>" "<r><i>,<m>,0"))
(const_int 0)))
(set (match_operand:SWI 0 "nonimmediate_operand" "=<r>m,<r>,<r>")
(plus:SWI (match_dup 1) (match_dup 2)))]
[(set (reg FLAGS_REG)
(compare
(plus:SI (match_operand:SI 1 "nonimmediate_operand" "%0,r")
- (match_operand:SI 2 "x86_64_general_operand" "rme,0"))
+ (match_operand:SI 2 "x86_64_general_operand" "rBMe,0"))
(const_int 0)))
(set (match_operand:DI 0 "register_operand" "=r,r")
(zero_extend:DI (plus:SI (match_dup 1) (match_dup 2))))]
(define_insn "*addsi_3_zext"
[(set (reg FLAGS_REG)
(compare
- (neg:SI (match_operand:SI 2 "x86_64_general_operand" "rme,0"))
+ (neg:SI (match_operand:SI 2 "x86_64_general_operand" "rBMe,0"))
(match_operand:SI 1 "nonimmediate_operand" "%0,r")))
(set (match_operand:DI 0 "register_operand" "=r,r")
(zero_extend:DI (plus:SI (match_dup 1) (match_dup 2))))]
[(set (match_operand:SWI 0 "nonimmediate_operand" "=<r>m,<r>")
(minus:SWI
(match_operand:SWI 1 "nonimmediate_operand" "0,0")
- (match_operand:SWI 2 "<general_operand>" "<r><i>,m")))
+ (match_operand:SWI 2 "<general_operand>" "<r><i>,<m>")))
(clobber (reg:CC FLAGS_REG))]
"ix86_binary_operator_ok (MINUS, <MODE>mode, operands)"
"sub{<imodesuffix>}\t{%2, %0|%0, %2}"
[(set (match_operand:DI 0 "register_operand" "=r")
(zero_extend:DI
(minus:SI (match_operand:SI 1 "register_operand" "0")
- (match_operand:SI 2 "x86_64_general_operand" "rme"))))
+ (match_operand:SI 2 "x86_64_general_operand" "rBMe"))))
(clobber (reg:CC FLAGS_REG))]
"TARGET_64BIT && ix86_binary_operator_ok (MINUS, SImode, operands)"
"sub{l}\t{%2, %k0|%k0, %2}"
(compare
(minus:SWI
(match_operand:SWI 1 "nonimmediate_operand" "0,0")
- (match_operand:SWI 2 "<general_operand>" "<r><i>,m"))
+ (match_operand:SWI 2 "<general_operand>" "<r><i>,<m>"))
(const_int 0)))
(set (match_operand:SWI 0 "nonimmediate_operand" "=<r>m,<r>")
(minus:SWI (match_dup 1) (match_dup 2)))]
[(set (reg FLAGS_REG)
(compare
(minus:SI (match_operand:SI 1 "register_operand" "0")
- (match_operand:SI 2 "x86_64_general_operand" "rme"))
+ (match_operand:SI 2 "x86_64_general_operand" "rBMe"))
(const_int 0)))
(set (match_operand:DI 0 "register_operand" "=r")
(zero_extend:DI
(define_insn "*sub<mode>_3"
[(set (reg FLAGS_REG)
(compare (match_operand:SWI 1 "nonimmediate_operand" "0,0")
- (match_operand:SWI 2 "<general_operand>" "<r><i>,m")))
+ (match_operand:SWI 2 "<general_operand>" "<r><i>,<m>")))
(set (match_operand:SWI 0 "nonimmediate_operand" "=<r>m,<r>")
(minus:SWI (match_dup 1) (match_dup 2)))]
"ix86_match_ccmode (insn, CCmode)
(define_insn "*subsi_3_zext"
[(set (reg FLAGS_REG)
(compare (match_operand:SI 1 "register_operand" "0")
- (match_operand:SI 2 "x86_64_general_operand" "rme")))
+ (match_operand:SI 2 "x86_64_general_operand" "rBMe")))
(set (match_operand:DI 0 "register_operand" "=r")
(zero_extend:DI
(minus:SI (match_dup 1)
(match_operator:SWI 4 "ix86_carry_flag_operator"
[(match_operand 3 "flags_reg_operand") (const_int 0)])
(match_operand:SWI 1 "nonimmediate_operand" "%0,0"))
- (match_operand:SWI 2 "<general_operand>" "<r><i>,m")))
+ (match_operand:SWI 2 "<general_operand>" "<r><i>,<m>")))
(clobber (reg:CC FLAGS_REG))]
"ix86_binary_operator_ok (PLUS, <MODE>mode, operands)"
"adc{<imodesuffix>}\t{%2, %0|%0, %2}"
(plus:SI (match_operator:SI 3 "ix86_carry_flag_operator"
[(reg FLAGS_REG) (const_int 0)])
(match_operand:SI 1 "register_operand" "%0"))
- (match_operand:SI 2 "x86_64_general_operand" "rme"))))
+ (match_operand:SI 2 "x86_64_general_operand" "rBMe"))))
(clobber (reg:CC FLAGS_REG))]
"TARGET_64BIT && ix86_binary_operator_ok (PLUS, SImode, operands)"
"adc{l}\t{%2, %k0|%k0, %2}"
(match_operand:SWI 1 "nonimmediate_operand" "0,0")
(match_operator:SWI 4 "ix86_carry_flag_operator"
[(match_operand 3 "flags_reg_operand") (const_int 0)]))
- (match_operand:SWI 2 "<general_operand>" "<r><i>,m")))
+ (match_operand:SWI 2 "<general_operand>" "<r><i>,<m>")))
(clobber (reg:CC FLAGS_REG))]
"ix86_binary_operator_ok (MINUS, <MODE>mode, operands)"
"sbb{<imodesuffix>}\t{%2, %0|%0, %2}"
(match_operand:SI 1 "register_operand" "0")
(match_operator:SI 3 "ix86_carry_flag_operator"
[(reg FLAGS_REG) (const_int 0)]))
- (match_operand:SI 2 "x86_64_general_operand" "rme"))))
+ (match_operand:SI 2 "x86_64_general_operand" "rBMe"))))
(clobber (reg:CC FLAGS_REG))]
"TARGET_64BIT && ix86_binary_operator_ok (MINUS, SImode, operands)"
"sbb{l}\t{%2, %k0|%k0, %2}"
(define_insn "@sub<mode>3_carry_ccgz"
[(set (reg:CCGZ FLAGS_REG)
(unspec:CCGZ [(match_operand:DWIH 1 "register_operand" "0")
- (match_operand:DWIH 2 "x86_64_general_operand" "rme")
+ (match_operand:DWIH 2 "x86_64_general_operand" "rBMe")
(ltu:DWIH (reg:CC FLAGS_REG) (const_int 0))]
UNSPEC_SBB))
(clobber (match_scratch:DWIH 0 "=r"))]
(compare:CCC
(plus:SWI
(match_operand:SWI 1 "nonimmediate_operand" "%0,0")
- (match_operand:SWI 2 "<general_operand>" "<r><i>,m"))
+ (match_operand:SWI 2 "<general_operand>" "<r><i>,<m>"))
(match_dup 1)))
(set (match_operand:SWI 0 "nonimmediate_operand" "=<r>m,<r>")
(plus:SWI (match_dup 1) (match_dup 2)))]
(compare:CCC
(plus:SI
(match_operand:SI 1 "nonimmediate_operand" "%0")
- (match_operand:SI 2 "x86_64_general_operand" "rme"))
+ (match_operand:SI 2 "x86_64_general_operand" "rBMe"))
(match_dup 1)))
(set (match_operand:DI 0 "register_operand" "=r")
(zero_extend:DI (plus:SI (match_dup 1) (match_dup 2))))]
(compare:CCC
(plus:SWI
(match_operand:SWI 1 "nonimmediate_operand" "%0,0")
- (match_operand:SWI 2 "<general_operand>" "<r><i>,m"))
+ (match_operand:SWI 2 "<general_operand>" "<r><i>,<m>"))
(match_dup 2)))
(set (match_operand:SWI 0 "nonimmediate_operand" "=<r>m,<r>")
(plus:SWI (match_dup 1) (match_dup 2)))]
(compare:CCC
(plus:SI
(match_operand:SI 1 "nonimmediate_operand" "%0")
- (match_operand:SI 2 "x86_64_general_operand" "rme"))
+ (match_operand:SI 2 "x86_64_general_operand" "rBMe"))
(match_dup 2)))
(set (match_operand:DI 0 "register_operand" "=r")
(zero_extend:DI (plus:SI (match_dup 1) (match_dup 2))))]
[(set (match_operand:SWIM248 0 "register_operand" "=r,r,r")
(mult:SWIM248
(match_operand:SWIM248 1 "nonimmediate_operand" "%rm,rm,0")
- (match_operand:SWIM248 2 "<general_operand>" "K,<i>,mr")))
+ (match_operand:SWIM248 2 "<general_operand>" "K,<i>,<m>r")))
(clobber (reg:CC FLAGS_REG))]
"!(MEM_P (operands[1]) && MEM_P (operands[2]))"
"@
[(set (match_operand:DI 0 "register_operand" "=r,r,r")
(zero_extend:DI
(mult:SI (match_operand:SI 1 "nonimmediate_operand" "%rm,rm,0")
- (match_operand:SI 2 "x86_64_general_operand" "K,e,mr"))))
+ (match_operand:SI 2 "x86_64_general_operand" "K,e,BMr"))))
(clobber (reg:CC FLAGS_REG))]
"TARGET_64BIT
&& !(MEM_P (operands[1]) && MEM_P (operands[2]))"
[(set (match_operand:DI 0 "register_operand" "=r")
(zero_extend:DI
(and:SI (match_operand:SI 1 "nonimmediate_operand" "%0")
- (match_operand:SI 2 "x86_64_general_operand" "rme"))))
+ (match_operand:SI 2 "x86_64_general_operand" "rBMe"))))
(clobber (reg:CC FLAGS_REG))]
"TARGET_64BIT && ix86_binary_operator_ok (AND, SImode, operands)"
"and{l}\t{%2, %k0|%k0, %2}"
(define_insn "*and<mode>_1"
[(set (match_operand:SWI24 0 "nonimmediate_operand" "=rm,r,Ya,?k")
(and:SWI24 (match_operand:SWI24 1 "nonimmediate_operand" "%0,0,qm,k")
- (match_operand:SWI24 2 "<general_operand>" "r<i>,m,L,k")))
+ (match_operand:SWI24 2 "<general_operand>" "r<i>,<m>,L,k")))
(clobber (reg:CC FLAGS_REG))]
"ix86_binary_operator_ok (AND, <MODE>mode, operands)"
"@
[(set (reg FLAGS_REG)
(compare (and:SI
(match_operand:SI 1 "nonimmediate_operand" "%0")
- (match_operand:SI 2 "x86_64_general_operand" "rme"))
+ (match_operand:SI 2 "x86_64_general_operand" "rBMe"))
(const_int 0)))
(set (match_operand:DI 0 "register_operand" "=r")
(zero_extend:DI (and:SI (match_dup 1) (match_dup 2))))]
[(set (reg FLAGS_REG)
(compare (and:SWI124
(match_operand:SWI124 1 "nonimmediate_operand" "%0,0")
- (match_operand:SWI124 2 "<general_operand>" "<r><i>,m"))
+ (match_operand:SWI124 2 "<general_operand>" "<r><i>,<m>"))
(const_int 0)))
(set (match_operand:SWI124 0 "nonimmediate_operand" "=<r>m,<r>")
(and:SWI124 (match_dup 1) (match_dup 2)))]
[(set (match_operand:SWI248 0 "nonimmediate_operand" "=rm,r,?k")
(any_or:SWI248
(match_operand:SWI248 1 "nonimmediate_operand" "%0,0,k")
- (match_operand:SWI248 2 "<general_operand>" "r<i>,m,k")))
+ (match_operand:SWI248 2 "<general_operand>" "r<i>,<m>,k")))
(clobber (reg:CC FLAGS_REG))]
"ix86_binary_operator_ok (<CODE>, <MODE>mode, operands)"
"@
[(set (match_operand:DI 0 "register_operand" "=r")
(zero_extend:DI
(any_or:SI (match_operand:SI 1 "nonimmediate_operand" "%0")
- (match_operand:SI 2 "x86_64_general_operand" "rme"))))
+ (match_operand:SI 2 "x86_64_general_operand" "rBMe"))))
(clobber (reg:CC FLAGS_REG))]
"TARGET_64BIT && ix86_binary_operator_ok (<CODE>, SImode, operands)"
"<logic>{l}\t{%2, %k0|%k0, %2}"
[(set (reg FLAGS_REG)
(compare (any_or:SWI
(match_operand:SWI 1 "nonimmediate_operand" "%0,0")
- (match_operand:SWI 2 "<general_operand>" "<r><i>,m"))
+ (match_operand:SWI 2 "<general_operand>" "<r><i>,<m>"))
(const_int 0)))
(set (match_operand:SWI 0 "nonimmediate_operand" "=<r>m,<r>")
(any_or:SWI (match_dup 1) (match_dup 2)))]
(define_insn "*<code>si_2_zext"
[(set (reg FLAGS_REG)
(compare (any_or:SI (match_operand:SI 1 "nonimmediate_operand" "%0")
- (match_operand:SI 2 "x86_64_general_operand" "rme"))
+ (match_operand:SI 2 "x86_64_general_operand" "rBMe"))
(const_int 0)))
(set (match_operand:DI 0 "register_operand" "=r")
(zero_extend:DI (any_or:SI (match_dup 1) (match_dup 2))))]
--- /dev/null
+/* { dg-do compile } */
+/* { dg-options "-O2 -std=gnu11 -fgnu89-inline" } */
+/* { dg-final { scan-assembler-not ".quad\[\\t \]+tunable_list" { target lp64 } } } */
+/* { dg-final { scan-assembler-not ".long\[\\t \]+tunable_list" { target { ! lp64 } } } } */
+
+typedef unsigned long int size_t;
+typedef long long int intmax_t;
+typedef unsigned long long int uintmax_t;
+typedef unsigned long long int uint64_t;
+typedef intmax_t tunable_num_t;
+typedef union
+{
+ tunable_num_t numval;
+ const char *strval;
+} tunable_val_t;
+enum
+{
+ HWCAP_X86_SSE2 = 1 << 0,
+ HWCAP_X86_64 = 1 << 1,
+ HWCAP_X86_AVX512_1 = 1 << 2
+};
+typedef void (*tunable_callback_t) (tunable_val_t *);
+extern void *__minimal_malloc (size_t n)
+ __attribute__ ((visibility ("hidden")));
+extern int __libc_enable_secure __attribute__ ((section (".data.rel.ro")));
+extern uint64_t _dl_strtoul (const char *, char **)
+ __attribute__ ((visibility ("hidden")));
+extern void _dl_fatal_printf (const char *fmt, ...)
+ __attribute__ ((__format__ (__printf__, 1, 2), __noreturn__));
+typedef enum
+{
+ glibc_rtld_nns,
+ glibc_elision_skip_lock_after_retries,
+ glibc_malloc_trim_threshold,
+ glibc_malloc_perturb,
+ glibc_cpu_x86_shared_cache_size,
+ glibc_pthread_rseq,
+ glibc_mem_tagging,
+ glibc_elision_tries,
+ glibc_elision_enable,
+ glibc_malloc_hugetlb,
+ glibc_cpu_x86_rep_movsb_threshold,
+ glibc_malloc_mxfast,
+ glibc_rtld_dynamic_sort,
+ glibc_elision_skip_lock_busy,
+ glibc_malloc_top_pad,
+ glibc_cpu_x86_rep_stosb_threshold,
+ glibc_cpu_x86_non_temporal_threshold,
+ glibc_cpu_x86_shstk,
+ glibc_pthread_stack_cache_size,
+ glibc_cpu_hwcap_mask,
+ glibc_malloc_mmap_max,
+ glibc_elision_skip_trylock_internal_abort,
+ glibc_malloc_tcache_unsorted_limit,
+ glibc_cpu_x86_ibt,
+ glibc_cpu_hwcaps,
+ glibc_elision_skip_lock_internal_abort,
+ glibc_malloc_arena_max,
+ glibc_malloc_mmap_threshold,
+ glibc_cpu_x86_data_cache_size,
+ glibc_malloc_tcache_count,
+ glibc_malloc_arena_test,
+ glibc_pthread_mutex_spin_count,
+ glibc_rtld_optional_static_tls,
+ glibc_malloc_tcache_max,
+ glibc_malloc_check,
+} tunable_id_t;
+typedef enum
+{
+ TUNABLE_TYPE_INT_32,
+ TUNABLE_TYPE_UINT_64,
+ TUNABLE_TYPE_SIZE_T,
+ TUNABLE_TYPE_STRING
+} tunable_type_code_t;
+typedef struct
+{
+ tunable_type_code_t type_code;
+ tunable_num_t min;
+ tunable_num_t max;
+} tunable_type_t;
+typedef enum
+{
+ TUNABLE_SECLEVEL_SXID_ERASE = 0,
+ TUNABLE_SECLEVEL_SXID_IGNORE = 1,
+ TUNABLE_SECLEVEL_NONE = 2,
+} tunable_seclevel_t;
+struct _tunable
+{
+ const char name[42];
+ tunable_type_t type;
+ tunable_val_t val;
+ _Bool initialized;
+ tunable_seclevel_t security_level;
+ const char env_alias[23];
+};
+typedef struct _tunable tunable_t;
+extern _Bool unsigned_tunable_type (tunable_type_code_t t);
+
+static tunable_t tunable_list[] __attribute__ ((section (".data.rel.ro"))) = {
+ { "glibc"
+ "."
+ "rtld"
+ "."
+ "nns",
+ { TUNABLE_TYPE_SIZE_T, 1, 16 },
+ { .numval = 4 },
+ ((void *)0),
+ TUNABLE_SECLEVEL_SXID_ERASE,
+ { 0 } },
+ { "glibc"
+ "."
+ "elision"
+ "."
+ "skip_lock_after_retries",
+ { TUNABLE_TYPE_INT_32, 0, (2147483647) },
+ { .numval = 3 },
+ ((void *)0),
+ TUNABLE_SECLEVEL_SXID_ERASE,
+ { 0 } },
+ { "glibc"
+ "."
+ "malloc"
+ "."
+ "trim_threshold",
+ { TUNABLE_TYPE_SIZE_T, 0, (18446744073709551615UL) },
+ {},
+ ((void *)0),
+ TUNABLE_SECLEVEL_SXID_IGNORE,
+ "MALLOC_TRIM_THRESHOLD_" },
+ { "glibc"
+ "."
+ "malloc"
+ "."
+ "perturb",
+ { TUNABLE_TYPE_INT_32, 0, 0xff },
+ {},
+ ((void *)0),
+ TUNABLE_SECLEVEL_SXID_IGNORE,
+ "MALLOC_PERTURB_" },
+ { "glibc"
+ "."
+ "cpu"
+ "."
+ "x86_shared_cache_size",
+ { TUNABLE_TYPE_SIZE_T, 0, (18446744073709551615UL) },
+ {},
+ ((void *)0),
+ TUNABLE_SECLEVEL_SXID_ERASE,
+ { 0 } },
+ { "glibc"
+ "."
+ "pthread"
+ "."
+ "rseq",
+ { TUNABLE_TYPE_INT_32, 0, 1 },
+ { .numval = 1 },
+ ((void *)0),
+ TUNABLE_SECLEVEL_SXID_ERASE,
+ { 0 } },
+ { "glibc"
+ "."
+ "mem"
+ "."
+ "tagging",
+ { TUNABLE_TYPE_INT_32, 0, 255 },
+ {},
+ ((void *)0),
+ TUNABLE_SECLEVEL_SXID_IGNORE,
+ { 0 } },
+ { "glibc"
+ "."
+ "elision"
+ "."
+ "tries",
+ { TUNABLE_TYPE_INT_32, 0, (2147483647) },
+ { .numval = 3 },
+ ((void *)0),
+ TUNABLE_SECLEVEL_SXID_ERASE,
+ { 0 } },
+ { "glibc"
+ "."
+ "elision"
+ "."
+ "enable",
+ { TUNABLE_TYPE_INT_32, 0, 1 },
+ {},
+ ((void *)0),
+ TUNABLE_SECLEVEL_SXID_ERASE,
+ { 0 } },
+ { "glibc"
+ "."
+ "malloc"
+ "."
+ "hugetlb",
+ { TUNABLE_TYPE_SIZE_T, 0, (18446744073709551615UL) },
+ {},
+ ((void *)0),
+ TUNABLE_SECLEVEL_SXID_ERASE,
+ { 0 } },
+ { "glibc"
+ "."
+ "cpu"
+ "."
+ "x86_rep_movsb_threshold",
+ { TUNABLE_TYPE_SIZE_T, 1, (18446744073709551615UL) },
+ {},
+ ((void *)0),
+ TUNABLE_SECLEVEL_SXID_ERASE,
+ { 0 } },
+ { "glibc"
+ "."
+ "malloc"
+ "."
+ "mxfast",
+ { TUNABLE_TYPE_SIZE_T, 0, (18446744073709551615UL) },
+ {},
+ ((void *)0),
+ TUNABLE_SECLEVEL_SXID_IGNORE,
+ { 0 } },
+ { "glibc"
+ "."
+ "rtld"
+ "."
+ "dynamic_sort",
+ { TUNABLE_TYPE_INT_32, 1, 2 },
+ { .numval = 2 },
+ ((void *)0),
+ TUNABLE_SECLEVEL_SXID_ERASE,
+ { 0 } },
+ { "glibc"
+ "."
+ "elision"
+ "."
+ "skip_lock_busy",
+ { TUNABLE_TYPE_INT_32, 0, (2147483647) },
+ { .numval = 3 },
+ ((void *)0),
+ TUNABLE_SECLEVEL_SXID_ERASE,
+ { 0 } },
+ { "glibc"
+ "."
+ "malloc"
+ "."
+ "top_pad",
+ { TUNABLE_TYPE_SIZE_T, 0, (18446744073709551615UL) },
+ {},
+ ((void *)0),
+ TUNABLE_SECLEVEL_SXID_IGNORE,
+ "MALLOC_TOP_PAD_" },
+ { "glibc"
+ "."
+ "cpu"
+ "."
+ "x86_rep_stosb_threshold",
+ { TUNABLE_TYPE_SIZE_T, 1, (18446744073709551615UL) },
+ { .numval = 2048 },
+ ((void *)0),
+ TUNABLE_SECLEVEL_SXID_ERASE,
+ { 0 } },
+ { "glibc"
+ "."
+ "cpu"
+ "."
+ "x86_non_temporal_threshold",
+ { TUNABLE_TYPE_SIZE_T, 0, (18446744073709551615UL) },
+ {},
+ ((void *)0),
+ TUNABLE_SECLEVEL_SXID_ERASE,
+ { 0 } },
+ { "glibc"
+ "."
+ "cpu"
+ "."
+ "x86_shstk",
+ { TUNABLE_TYPE_STRING, 0, 0 },
+ {},
+ ((void *)0),
+ TUNABLE_SECLEVEL_SXID_ERASE,
+ { 0 } },
+ { "glibc"
+ "."
+ "pthread"
+ "."
+ "stack_cache_size",
+ { TUNABLE_TYPE_SIZE_T, 0, (18446744073709551615UL) },
+ { .numval = 41943040 },
+ ((void *)0),
+ TUNABLE_SECLEVEL_SXID_ERASE,
+ { 0 } },
+ { "glibc"
+ "."
+ "cpu"
+ "."
+ "hwcap_mask",
+ { TUNABLE_TYPE_UINT_64, 0, (18446744073709551615UL) },
+ { .numval = (HWCAP_X86_64 | HWCAP_X86_AVX512_1) },
+ ((void *)0),
+ TUNABLE_SECLEVEL_SXID_ERASE,
+ "LD_HWCAP_MASK" },
+ { "glibc"
+ "."
+ "malloc"
+ "."
+ "mmap_max",
+ { TUNABLE_TYPE_INT_32, 0, (2147483647) },
+ {},
+ ((void *)0),
+ TUNABLE_SECLEVEL_SXID_IGNORE,
+ "MALLOC_MMAP_MAX_" },
+ { "glibc"
+ "."
+ "elision"
+ "."
+ "skip_trylock_internal_abort",
+ { TUNABLE_TYPE_INT_32, 0, (2147483647) },
+ { .numval = 3 },
+ ((void *)0),
+ TUNABLE_SECLEVEL_SXID_ERASE,
+ { 0 } },
+ { "glibc"
+ "."
+ "malloc"
+ "."
+ "tcache_unsorted_limit",
+ { TUNABLE_TYPE_SIZE_T, 0, (18446744073709551615UL) },
+ {},
+ ((void *)0),
+ TUNABLE_SECLEVEL_SXID_ERASE,
+ { 0 } },
+ { "glibc"
+ "."
+ "cpu"
+ "."
+ "x86_ibt",
+ { TUNABLE_TYPE_STRING, 0, 0 },
+ {},
+ ((void *)0),
+ TUNABLE_SECLEVEL_SXID_ERASE,
+ { 0 } },
+ { "glibc"
+ "."
+ "cpu"
+ "."
+ "hwcaps",
+ { TUNABLE_TYPE_STRING, 0, 0 },
+ {},
+ ((void *)0),
+ TUNABLE_SECLEVEL_SXID_ERASE,
+ { 0 } },
+ { "glibc"
+ "."
+ "elision"
+ "."
+ "skip_lock_internal_abort",
+ { TUNABLE_TYPE_INT_32, 0, (2147483647) },
+ { .numval = 3 },
+ ((void *)0),
+ TUNABLE_SECLEVEL_SXID_ERASE,
+ { 0 } },
+ { "glibc"
+ "."
+ "malloc"
+ "."
+ "arena_max",
+ { TUNABLE_TYPE_SIZE_T, 1, (18446744073709551615UL) },
+ {},
+ ((void *)0),
+ TUNABLE_SECLEVEL_SXID_IGNORE,
+ "MALLOC_ARENA_MAX" },
+ { "glibc"
+ "."
+ "malloc"
+ "."
+ "mmap_threshold",
+ { TUNABLE_TYPE_SIZE_T, 0, (18446744073709551615UL) },
+ {},
+ ((void *)0),
+ TUNABLE_SECLEVEL_SXID_IGNORE,
+ "MALLOC_MMAP_THRESHOLD_" },
+ { "glibc"
+ "."
+ "cpu"
+ "."
+ "x86_data_cache_size",
+ { TUNABLE_TYPE_SIZE_T, 0, (18446744073709551615UL) },
+ {},
+ ((void *)0),
+ TUNABLE_SECLEVEL_SXID_ERASE,
+ { 0 } },
+ { "glibc"
+ "."
+ "malloc"
+ "."
+ "tcache_count",
+ { TUNABLE_TYPE_SIZE_T, 0, (18446744073709551615UL) },
+ {},
+ ((void *)0),
+ TUNABLE_SECLEVEL_SXID_ERASE,
+ { 0 } },
+ { "glibc"
+ "."
+ "malloc"
+ "."
+ "arena_test",
+ { TUNABLE_TYPE_SIZE_T, 1, (18446744073709551615UL) },
+ {},
+ ((void *)0),
+ TUNABLE_SECLEVEL_SXID_IGNORE,
+ "MALLOC_ARENA_TEST" },
+ { "glibc"
+ "."
+ "pthread"
+ "."
+ "mutex_spin_count",
+ { TUNABLE_TYPE_INT_32, 0, 32767 },
+ { .numval = 100 },
+ ((void *)0),
+ TUNABLE_SECLEVEL_SXID_ERASE,
+ { 0 } },
+ { "glibc"
+ "."
+ "rtld"
+ "."
+ "optional_static_tls",
+ { TUNABLE_TYPE_SIZE_T, 0, (18446744073709551615UL) },
+ { .numval = 512 },
+ ((void *)0),
+ TUNABLE_SECLEVEL_SXID_ERASE,
+ { 0 } },
+ { "glibc"
+ "."
+ "malloc"
+ "."
+ "tcache_max",
+ { TUNABLE_TYPE_SIZE_T, 0, (18446744073709551615UL) },
+ {},
+ ((void *)0),
+ TUNABLE_SECLEVEL_SXID_ERASE,
+ { 0 } },
+ { "glibc"
+ "."
+ "malloc"
+ "."
+ "check",
+ { TUNABLE_TYPE_INT_32, 0, 3 },
+ {},
+ ((void *)0),
+ TUNABLE_SECLEVEL_SXID_ERASE,
+ "MALLOC_CHECK_" },
+};
+extern void __tunables_init (char **);
+extern void __tunables_print (void);
+extern void __tunable_get_val (tunable_id_t, void *, tunable_callback_t);
+extern void __tunable_set_val (tunable_id_t, tunable_val_t *, tunable_num_t *,
+ tunable_num_t *);
+static __inline __attribute__ ((__always_inline__)) _Bool
+tunable_val_lt (tunable_num_t lhs, tunable_num_t rhs, _Bool unsigned_cmp)
+{
+ if (unsigned_cmp)
+ return (uintmax_t)lhs < (uintmax_t)rhs;
+ else
+ return lhs < rhs;
+}
+static __inline __attribute__ ((__always_inline__)) _Bool
+tunable_val_gt (tunable_num_t lhs, tunable_num_t rhs, _Bool unsigned_cmp)
+{
+ if (unsigned_cmp)
+ return (uintmax_t)lhs > (uintmax_t)rhs;
+ else
+ return lhs > rhs;
+}
+static __inline __attribute__ ((__always_inline__)) _Bool
+tunable_is_name (const char *orig, const char *envname)
+{
+ for (; *orig != '\0' && *envname != '\0'; envname++, orig++)
+ if (*orig != *envname)
+ break;
+ if (*orig == '\0' && *envname == '=')
+ return 1;
+ else
+ return 0;
+}
+static char *
+tunables_strdup (const char *in)
+{
+ size_t i = 0;
+ while (in[i++] != '\0')
+ ;
+ char *out = __minimal_malloc (i + 1);
+ if (out == ((void *)0))
+ _dl_fatal_printf ("failed to allocate memory to process tunables\n");
+ while (i-- > 0)
+ out[i] = in[i];
+ return out;
+}
+static char **
+get_next_env (char **envp, char **name, size_t *namelen, char **val,
+ char ***prev_envp)
+{
+ while (envp != ((void *)0) && *envp != ((void *)0))
+ {
+ char **prev = envp;
+ char *envline = *envp++;
+ int len = 0;
+ while (envline[len] != '\0' && envline[len] != '=')
+ len++;
+ if (envline[len] == '\0')
+ continue;
+ *name = envline;
+ *namelen = len;
+ *val = &envline[len + 1];
+ *prev_envp = prev;
+ return envp;
+ }
+ return ((void *)0);
+}
+static void
+do_tunable_update_val (tunable_t *cur, const tunable_val_t *valp,
+ const tunable_num_t *minp, const tunable_num_t *maxp)
+{
+ tunable_num_t val, min, max;
+ if (cur->type.type_code == TUNABLE_TYPE_STRING)
+ {
+ cur->val.strval = valp->strval;
+ cur->initialized = 1;
+ return;
+ }
+ _Bool unsigned_cmp = unsigned_tunable_type (cur->type.type_code);
+ val = valp->numval;
+ min = minp != ((void *)0) ? *minp : cur->type.min;
+ max = maxp != ((void *)0) ? *maxp : cur->type.max;
+ if (tunable_val_lt (min, cur->type.min, unsigned_cmp))
+ min = cur->type.min;
+ if (tunable_val_gt (max, cur->type.max, unsigned_cmp))
+ max = cur->type.max;
+ if (tunable_val_gt (min, max, unsigned_cmp))
+ {
+ min = cur->type.min;
+ max = cur->type.max;
+ }
+ if (tunable_val_lt (val, min, unsigned_cmp)
+ || tunable_val_lt (max, val, unsigned_cmp))
+ return;
+ cur->val.numval = val;
+ cur->type.min = min;
+ cur->type.max = max;
+ cur->initialized = 1;
+}
+static void
+tunable_initialize (tunable_t *cur, const char *strval)
+{
+ tunable_val_t val;
+ if (cur->type.type_code != TUNABLE_TYPE_STRING)
+ val.numval = (tunable_num_t)_dl_strtoul (strval, ((void *)0));
+ else
+ val.strval = strval;
+ do_tunable_update_val (cur, &val, ((void *)0), ((void *)0));
+}
+static void
+parse_tunables (char *tunestr, char *valstring)
+{
+ if (tunestr == ((void *)0) || *tunestr == '\0')
+ return;
+ char *p = tunestr;
+ size_t off = 0;
+ while (1)
+ {
+ char *name = p;
+ size_t len = 0;
+ while (p[len] != '=' && p[len] != ':' && p[len] != '\0')
+ len++;
+ if (p[len] == '\0')
+ {
+ if (__libc_enable_secure)
+ tunestr[off] = '\0';
+ return;
+ }
+ if (p[len] == ':')
+ {
+ p += len + 1;
+ continue;
+ }
+ p += len + 1;
+ char *value = &valstring[p - tunestr];
+ len = 0;
+ while (p[len] != ':' && p[len] != '\0')
+ len++;
+ for (size_t i = 0; i < sizeof (tunable_list) / sizeof (tunable_t); i++)
+ {
+ tunable_t *cur = &tunable_list[i];
+ if (tunable_is_name (cur->name, name))
+ {
+ if (__libc_enable_secure)
+ {
+ if (cur->security_level != TUNABLE_SECLEVEL_SXID_ERASE)
+ {
+ if (off > 0)
+ tunestr[off++] = ':';
+ const char *n = cur->name;
+ while (*n != '\0')
+ tunestr[off++] = *n++;
+ tunestr[off++] = '=';
+ for (size_t j = 0; j < len; j++)
+ tunestr[off++] = value[j];
+ }
+ if (cur->security_level != TUNABLE_SECLEVEL_NONE)
+ break;
+ }
+ value[len] = '\0';
+ tunable_initialize (cur, value);
+ break;
+ }
+ }
+ if (p[len] != '\0')
+ p += len + 1;
+ }
+}
+void
+__tunables_init (char **envp)
+{
+ char *envname = ((void *)0);
+ char *envval = ((void *)0);
+ size_t len = 0;
+ char **prev_envp = envp;
+ while ((envp = get_next_env (envp, &envname, &len, &envval, &prev_envp))
+ != ((void *)0))
+ {
+ if (tunable_is_name ("GLIBC_TUNABLES", envname))
+ {
+ char *new_env = tunables_strdup (envname);
+ if (new_env != ((void *)0))
+ parse_tunables (new_env + len + 1, envval);
+ *prev_envp = new_env;
+ continue;
+ }
+ for (int i = 0; i < sizeof (tunable_list) / sizeof (tunable_t); i++)
+ {
+ tunable_t *cur = &tunable_list[i];
+ const char *name = cur->env_alias;
+ if (tunable_is_name (name, envname))
+ {
+ tunable_initialize (cur, envval);
+ break;
+ }
+ }
+ }
+}
--- /dev/null
+/* { dg-do compile } */
+/* { dg-require-effective-target pie } */
+/* { dg-options "-O2 -std=gnu11 -fgnu89-inline -fpie" } */
+/* { dg-final { scan-assembler-not ".quad\[\\t \]+tunable_list" { target lp64 } } } */
+/* { dg-final { scan-assembler-not ".long\[\\t \]+tunable_list" { target { ! lp64 } } } } */
+
+#include "pr103762-1a.c"
--- /dev/null
+/* { dg-do compile } */
+/* { dg-require-effective-target fpic } */
+/* { dg-options "-O2 -std=gnu11 -fgnu89-inline -fpic" } */
+/* { dg-final { scan-assembler-not ".quad\[\\t \]+tunable_list" { target lp64 } } } */
+/* { dg-final { scan-assembler-not ".long\[\\t \]+tunable_list" { target { ! lp64 } } } } */
+
+#include "pr103762-1a.c"