print out all malloc_conf settings in stats

This commit is contained in:
Shirui Cheng 2024-01-30 10:16:28 -08:00 committed by Qi Wang
parent 1aba4f41a3
commit 373884ab48
5 changed files with 114 additions and 18 deletions

View file

@ -38,6 +38,9 @@ extern atomic_zu_t zero_realloc_count;
extern bool opt_cache_oblivious;
extern unsigned opt_debug_double_free_max_scan;
extern const char *opt_malloc_conf_symlink;
extern const char *opt_malloc_conf_env_var;
/* Escape free-fastpath when ptr & mask == 0 (for sanitization purpose). */
extern uintptr_t san_cache_bin_nonfast_mask;

View file

@ -159,6 +159,10 @@ CTL_PROTO(opt_prof_sys_thread_name)
CTL_PROTO(opt_prof_time_res)
CTL_PROTO(opt_lg_san_uaf_align)
CTL_PROTO(opt_zero_realloc)
CTL_PROTO(opt_malloc_conf_symlink)
CTL_PROTO(opt_malloc_conf_env_var)
CTL_PROTO(opt_malloc_conf_global_var)
CTL_PROTO(opt_malloc_conf_global_var_2_conf_harder)
CTL_PROTO(tcache_create)
CTL_PROTO(tcache_flush)
CTL_PROTO(tcache_destroy)
@ -426,6 +430,14 @@ static const ctl_named_node_t config_node[] = {
{NAME("xmalloc"), CTL(config_xmalloc)}
};
static const ctl_named_node_t opt_malloc_conf_node[] = {
{NAME("symlink"), CTL(opt_malloc_conf_symlink)},
{NAME("env_var"), CTL(opt_malloc_conf_env_var)},
{NAME("global_var"), CTL(opt_malloc_conf_global_var)},
{NAME("global_var_2_conf_harder"),
CTL(opt_malloc_conf_global_var_2_conf_harder)}
};
static const ctl_named_node_t opt_node[] = {
{NAME("abort"), CTL(opt_abort)},
{NAME("abort_conf"), CTL(opt_abort_conf)},
@ -502,7 +514,8 @@ static const ctl_named_node_t opt_node[] = {
{NAME("lg_san_uaf_align"), CTL(opt_lg_san_uaf_align)},
{NAME("zero_realloc"), CTL(opt_zero_realloc)},
{NAME("debug_double_free_max_scan"),
CTL(opt_debug_double_free_max_scan)}
CTL(opt_debug_double_free_max_scan)},
{NAME("malloc_conf"), CHILD(named, opt_malloc_conf)}
};
static const ctl_named_node_t tcache_node[] = {
@ -2230,6 +2243,17 @@ CTL_RO_NL_CGEN(config_uaf_detection, opt_lg_san_uaf_align,
CTL_RO_NL_GEN(opt_zero_realloc,
zero_realloc_mode_names[opt_zero_realloc_action], const char *)
/* malloc_conf options */
CTL_RO_NL_CGEN(opt_malloc_conf_symlink, opt_malloc_conf_symlink,
opt_malloc_conf_symlink, const char *)
CTL_RO_NL_CGEN(opt_malloc_conf_env_var, opt_malloc_conf_env_var,
opt_malloc_conf_env_var, const char *)
CTL_RO_NL_CGEN(je_malloc_conf, opt_malloc_conf_global_var, je_malloc_conf,
const char *)
CTL_RO_NL_CGEN(je_malloc_conf_2_conf_harder,
opt_malloc_conf_global_var_2_conf_harder, je_malloc_conf_2_conf_harder,
const char *)
/******************************************************************************/
static int

View file

@ -57,6 +57,9 @@ const char *je_malloc_conf_2_conf_harder
#endif
;
const char *opt_malloc_conf_symlink = NULL;
const char *opt_malloc_conf_env_var = NULL;
bool opt_abort =
#ifdef JEMALLOC_DEBUG
true
@ -955,7 +958,7 @@ malloc_slow_flag_init(void) {
#define MALLOC_CONF_NSOURCES 5
static const char *
obtain_malloc_conf(unsigned which_source, char buf[PATH_MAX + 1]) {
obtain_malloc_conf(unsigned which_source, char readlink_buf[PATH_MAX + 1]) {
if (config_debug) {
static unsigned read_source = 0;
/*
@ -998,9 +1001,9 @@ obtain_malloc_conf(unsigned which_source, char buf[PATH_MAX + 1]) {
* link's name.
*/
#ifndef JEMALLOC_READLINKAT
linklen = readlink(linkname, buf, PATH_MAX);
linklen = readlink(linkname, readlink_buf, PATH_MAX);
#else
linklen = readlinkat(AT_FDCWD, linkname, buf, PATH_MAX);
linklen = readlinkat(AT_FDCWD, linkname, readlink_buf, PATH_MAX);
#endif
if (linklen == -1) {
/* No configuration specified. */
@ -1009,8 +1012,8 @@ obtain_malloc_conf(unsigned which_source, char buf[PATH_MAX + 1]) {
set_errno(saved_errno);
}
#endif
buf[linklen] = '\0';
ret = buf;
readlink_buf[linklen] = '\0';
ret = readlink_buf;
break;
} case 3: {
const char *envname =
@ -1022,10 +1025,7 @@ obtain_malloc_conf(unsigned which_source, char buf[PATH_MAX + 1]) {
;
if ((ret = jemalloc_getenv(envname)) != NULL) {
/*
* Do nothing; opts is already initialized to the value
* of the MALLOC_CONF environment variable.
*/
opt_malloc_conf_env_var = ret;
} else {
/* No configuration specified. */
ret = NULL;
@ -1084,7 +1084,7 @@ validate_hpa_settings(void) {
static void
malloc_conf_init_helper(sc_data_t *sc_data, unsigned bin_shard_sizes[SC_NBINS],
bool initial_call, const char *opts_cache[MALLOC_CONF_NSOURCES],
char buf[PATH_MAX + 1]) {
char readlink_buf[PATH_MAX + 1]) {
static const char *opts_explain[MALLOC_CONF_NSOURCES] = {
"string specified via --with-malloc-conf",
"string pointed to by the global variable malloc_conf",
@ -1101,7 +1101,7 @@ malloc_conf_init_helper(sc_data_t *sc_data, unsigned bin_shard_sizes[SC_NBINS],
for (i = 0; i < MALLOC_CONF_NSOURCES; i++) {
/* Get runtime configuration. */
if (initial_call) {
opts_cache[i] = obtain_malloc_conf(i, buf);
opts_cache[i] = obtain_malloc_conf(i, readlink_buf);
}
opts = opts_cache[i];
if (!initial_call && opt_confirm_conf) {
@ -1783,13 +1783,13 @@ malloc_conf_init_check_deps(void) {
}
static void
malloc_conf_init(sc_data_t *sc_data, unsigned bin_shard_sizes[SC_NBINS]) {
malloc_conf_init(sc_data_t *sc_data, unsigned bin_shard_sizes[SC_NBINS],
char readlink_buf[PATH_MAX + 1]) {
const char *opts_cache[MALLOC_CONF_NSOURCES] = {NULL, NULL, NULL, NULL,
NULL};
char buf[PATH_MAX + 1];
/* The first call only set the confirm_conf option and opts_cache */
malloc_conf_init_helper(NULL, NULL, true, opts_cache, buf);
malloc_conf_init_helper(NULL, NULL, true, opts_cache, readlink_buf);
malloc_conf_init_helper(sc_data, bin_shard_sizes, false, opts_cache,
NULL);
if (malloc_conf_init_check_deps()) {
@ -1855,7 +1855,9 @@ malloc_init_hard_a0_locked(void) {
if (config_prof) {
prof_boot0();
}
malloc_conf_init(&sc_data, bin_shard_sizes);
char readlink_buf[PATH_MAX + 1];
readlink_buf[0] = '\0';
malloc_conf_init(&sc_data, bin_shard_sizes, readlink_buf);
san_init(opt_lg_san_uaf_align);
sz_boot(&sc_data, opt_cache_oblivious);
bin_info_boot(&sc_data, bin_shard_sizes);
@ -1949,6 +1951,15 @@ malloc_init_hard_a0_locked(void) {
malloc_init_state = malloc_init_a0_initialized;
size_t buf_len = strlen(readlink_buf);
if (buf_len > 0) {
void *readlink_allocated = a0ialloc(buf_len + 1, false, true);
if (readlink_allocated != NULL) {
memcpy(readlink_allocated, readlink_buf, buf_len + 1);
opt_malloc_conf_symlink = readlink_allocated;
}
}
return false;
}

View file

@ -1473,6 +1473,40 @@ stats_general_print(emitter_t *emitter) {
emitter_dict_begin(emitter, "opt", "Run-time option settings");
/*
* opt.malloc_conf.
*
* Sources are documented in https://jemalloc.net/jemalloc.3.html#tuning
* - (Not Included Here) The string specified via --with-malloc-conf,
* which is already printed out above as config.malloc_conf
* - (Included) The string pointed to by the global variable malloc_conf
* - (Included) The name of the file referenced by the symbolic link
* named /etc/malloc.conf
* - (Included) The value of the environment variable MALLOC_CONF
* - (Optional, Unofficial) The string pointed to by the global variable
* malloc_conf_2_conf_harder, which is hidden from the public.
*
* Note: The outputs are strictly ordered by priorities (low -> high).
*
*/
#define MALLOC_CONF_WRITE(name, message) \
if (je_mallctl("opt.malloc_conf."name, (void *)&cpv, &cpsz, NULL, 0) != \
0) { \
cpv = ""; \
} \
emitter_kv(emitter, name, message, emitter_type_string, &cpv);
MALLOC_CONF_WRITE("global_var", "Global variable malloc_conf");
MALLOC_CONF_WRITE("symlink", "Symbolic link malloc.conf");
MALLOC_CONF_WRITE("env_var", "Environment variable MALLOC_CONF");
/* As this config is unofficial, skip the output if it's NULL */
if (je_mallctl("opt.malloc_conf.global_var_2_conf_harder",
(void *)&cpv, &cpsz, NULL, 0) == 0) {
emitter_kv(emitter, "global_var_2_conf_harder", "Global "
"variable malloc_conf_2_conf_harder", emitter_type_string, &cpv);
}
#undef MALLOC_CONF_WRITE
OPT_WRITE_BOOL("abort")
OPT_WRITE_BOOL("abort_conf")
OPT_WRITE_BOOL("cache_oblivious")
@ -1554,7 +1588,7 @@ stats_general_print(emitter_t *emitter) {
OPT_WRITE_CHAR_P("stats_interval_opts")
OPT_WRITE_CHAR_P("zero_realloc")
emitter_dict_end(emitter);
emitter_dict_end(emitter); /* Close "opt". */
#undef OPT_WRITE
#undef OPT_WRITE_MUTABLE

View file

@ -22,8 +22,32 @@ TEST_BEGIN(test_malloc_conf_2) {
}
TEST_END
TEST_BEGIN(test_mallctl_global_var) {
#ifdef _WIN32
bool windows = true;
#else
bool windows = false;
#endif
/* Windows doesn't support weak symbol linker trickery. */
test_skip_if(windows);
const char *mc;
size_t sz = sizeof(mc);
expect_d_eq(mallctl("opt.malloc_conf.global_var",
(void *)&mc, &sz, NULL, 0), 0, "Unexpected mallctl() failure");
expect_str_eq(mc, malloc_conf, "Unexpected value for the global variable "
"malloc_conf");
expect_d_eq(mallctl("opt.malloc_conf.global_var_2_conf_harder",
(void *)&mc, &sz, NULL, 0), 0, "Unexpected mallctl() failure");
expect_str_eq(mc, malloc_conf_2_conf_harder, "Unexpected value for the "
"global variable malloc_conf_2_conf_harder");
}
TEST_END
int
main(void) {
return test(
test_malloc_conf_2);
test_malloc_conf_2,
test_mallctl_global_var);
}