diff --git a/INSTALL.md b/INSTALL.md index abbfefda..d618a701 100644 --- a/INSTALL.md +++ b/INSTALL.md @@ -139,7 +139,6 @@ any of the following arguments (not a definitive list) to 'configure': in the following list that appears to function correctly: + libunwind (requires --enable-prof-libunwind) - + frame pointer (requires --enable-prof-frameptr) + libgcc (unless --disable-prof-libgcc) + gcc intrinsics (unless --disable-prof-gcc) @@ -148,12 +147,6 @@ any of the following arguments (not a definitive list) to 'configure': Use the libunwind library (http://www.nongnu.org/libunwind/) for stack backtracing. -* `--enable-prof-frameptr` - - Use the optimized frame pointer unwinder for stack backtracing. Safe - to use in mixed code (with and without frame pointers) - but requires - frame pointers to produce meaningful stacks. Linux only. - * `--disable-prof-libgcc` Disable the use of libgcc's backtracing functionality. diff --git a/Makefile.in b/Makefile.in index b151f817..08275b3c 100644 --- a/Makefile.in +++ b/Makefile.in @@ -146,7 +146,6 @@ C_SRCS := $(srcroot)src/jemalloc.c \ $(srcroot)src/prof_data.c \ $(srcroot)src/prof_log.c \ $(srcroot)src/prof_recent.c \ - $(srcroot)src/prof_stack_range.c \ $(srcroot)src/prof_stats.c \ $(srcroot)src/prof_sys.c \ $(srcroot)src/psset.c \ diff --git a/configure.ac b/configure.ac index b43fbc09..93bcd9e7 100644 --- a/configure.ac +++ b/configure.ac @@ -1557,33 +1557,6 @@ if test "x$backtrace_method" = "x" -a "x$enable_prof_libunwind" = "x1" ; then fi fi -if test `uname -s` = "Linux" -then - AC_ARG_ENABLE([prof-frameptr], - [AS_HELP_STRING([--enable-prof-frameptr], [Use optimized frame pointer unwinder for backtracing (Linux only)])], - [if test "x$enable_prof_frameptr" = "xno" ; then - enable_prof_frameptr="0" - else - enable_prof_frameptr="1" - if test "x$enable_prof" = "x0" ; then - AC_MSG_ERROR([--enable-prof-frameptr should only be used with --enable-prof]) - fi - fi - ], - [enable_prof_frameptr="0"] - ) - if test "x$backtrace_method" = "x" -a "x$enable_prof_frameptr" = "x1" \ - -a "x$GCC" = "xyes" ; then - JE_CFLAGS_ADD([-fno-omit-frame-pointer]) - backtrace_method="frame pointer linux" - AC_DEFINE([JEMALLOC_PROF_FRAME_POINTER], [ ], [ ]) - else - enable_prof_frameptr="0" - fi -else - enable_prof_frameptr="0" -fi - AC_ARG_ENABLE([prof-libgcc], [AS_HELP_STRING([--disable-prof-libgcc], [Do not use libgcc for backtracing])], @@ -3186,7 +3159,6 @@ AC_MSG_RESULT([user_config : ${enable_user_config}]) AC_MSG_RESULT([experimental_smallocx : ${enable_experimental_smallocx}]) AC_MSG_RESULT([prof : ${enable_prof}]) AC_MSG_RESULT([prof-libunwind : ${enable_prof_libunwind}]) -AC_MSG_RESULT([prof-frameptr : ${enable_prof_frameptr}]) AC_MSG_RESULT([prof-libgcc : ${enable_prof_libgcc}]) AC_MSG_RESULT([prof-gcc : ${enable_prof_gcc}]) AC_MSG_RESULT([fill : ${enable_fill}]) diff --git a/include/jemalloc/internal/jemalloc_internal_defs.h.in b/include/jemalloc/internal/jemalloc_internal_defs.h.in index d64e08c3..d79c6def 100644 --- a/include/jemalloc/internal/jemalloc_internal_defs.h.in +++ b/include/jemalloc/internal/jemalloc_internal_defs.h.in @@ -175,9 +175,6 @@ /* Use gcc intrinsics for profile backtracing if defined. */ #undef JEMALLOC_PROF_GCC -/* Use frame pointer for profile backtracing if defined. Linux only. */ -#undef JEMALLOC_PROF_FRAME_POINTER - /* JEMALLOC_PAGEID enabled page id */ #undef JEMALLOC_PAGEID diff --git a/include/jemalloc/internal/jemalloc_preamble.h.in b/include/jemalloc/internal/jemalloc_preamble.h.in index b00e0b7a..7a0fd5c6 100644 --- a/include/jemalloc/internal/jemalloc_preamble.h.in +++ b/include/jemalloc/internal/jemalloc_preamble.h.in @@ -130,13 +130,6 @@ static const bool config_prof_libunwind = false #endif ; -static const bool config_prof_frameptr = -#ifdef JEMALLOC_PROF_FRAME_POINTER - true -#else - false -#endif - ; static const bool maps_coalesce = #ifdef JEMALLOC_MAPS_COALESCE true diff --git a/include/jemalloc/internal/malloc_io.h b/include/jemalloc/internal/malloc_io.h index 0f70c3c3..99b0fca3 100644 --- a/include/jemalloc/internal/malloc_io.h +++ b/include/jemalloc/internal/malloc_io.h @@ -89,13 +89,4 @@ malloc_close(int fd) { #endif } -static inline off_t -malloc_lseek(int fd, off_t offset, int whence) { -#if defined(JEMALLOC_USE_SYSCALL) && defined(SYS_lseek) - return (off_t)syscall(SYS_lseek, fd, offset, whence); -#else - return lseek(fd, offset, whence); -#endif -} - #endif /* JEMALLOC_INTERNAL_MALLOC_IO_H */ diff --git a/include/jemalloc/internal/prof_sys.h b/include/jemalloc/internal/prof_sys.h index e671a47c..5b2ab778 100644 --- a/include/jemalloc/internal/prof_sys.h +++ b/include/jemalloc/internal/prof_sys.h @@ -21,7 +21,6 @@ void prof_fdump_impl(tsd_t *tsd); void prof_idump_impl(tsd_t *tsd); bool prof_mdump_impl(tsd_t *tsd, const char *filename); void prof_gdump_impl(tsd_t *tsd); -int prof_thread_stack_range(uintptr_t fp, uintptr_t *low, uintptr_t *high); /* Used in unit tests. */ typedef int(prof_sys_thread_name_read_t)(char *buf, size_t limit); diff --git a/scripts/gen_gh_actions.py b/scripts/gen_gh_actions.py index e35196d5..1dac79e3 100755 --- a/scripts/gen_gh_actions.py +++ b/scripts/gen_gh_actions.py @@ -224,11 +224,8 @@ def generate_linux_job(arch): if arch != ARM64: exclude += [LARGE_HUGEPAGE] - linux_configure_flags = list(configure_flag_unusuals) - linux_configure_flags.append(Option.as_configure_flag("--enable-prof --enable-prof-frameptr")) - linux_unusuals = (compilers_unusual + feature_unusuals - + linux_configure_flags + malloc_conf_unusuals) + + configure_flag_unusuals + malloc_conf_unusuals) matrix_entries = generate_job_matrix_entries(os, arch, exclude, max_unusual_opts, linux_unusuals) diff --git a/scripts/gen_travis.py b/scripts/gen_travis.py index 3f7aeab0..4fe4b7a3 100755 --- a/scripts/gen_travis.py +++ b/scripts/gen_travis.py @@ -264,11 +264,8 @@ def generate_linux(arch): if arch != ARM64: exclude += [LARGE_HUGEPAGE] - linux_configure_flags = list(configure_flag_unusuals) - linux_configure_flags.append(Option.as_configure_flag("--enable-prof --enable-prof-frameptr")) - linux_unusuals = (compilers_unusual + feature_unusuals - + linux_configure_flags + malloc_conf_unusuals) + + configure_flag_unusuals + malloc_conf_unusuals) return generate_jobs(os, arch, exclude, max_unusual_opts, linux_unusuals) diff --git a/src/ctl.c b/src/ctl.c index fc93856d..6622d135 100644 --- a/src/ctl.c +++ b/src/ctl.c @@ -121,7 +121,6 @@ CTL_PROTO(config_opt_safety_checks) CTL_PROTO(config_prof) CTL_PROTO(config_prof_libgcc) CTL_PROTO(config_prof_libunwind) -CTL_PROTO(config_prof_frameptr) CTL_PROTO(config_stats) CTL_PROTO(config_utrace) CTL_PROTO(config_xmalloc) @@ -495,7 +494,6 @@ static const ctl_named_node_t config_node[] = { {NAME("prof"), CTL(config_prof)}, {NAME("prof_libgcc"), CTL(config_prof_libgcc)}, {NAME("prof_libunwind"), CTL(config_prof_libunwind)}, - {NAME("prof_frameptr"), CTL(config_prof_frameptr)}, {NAME("stats"), CTL(config_stats)}, {NAME("utrace"), CTL(config_utrace)}, {NAME("xmalloc"), CTL(config_xmalloc)}}; @@ -2210,7 +2208,6 @@ CTL_RO_CONFIG_GEN(config_opt_safety_checks, bool) CTL_RO_CONFIG_GEN(config_prof, bool) CTL_RO_CONFIG_GEN(config_prof_libgcc, bool) CTL_RO_CONFIG_GEN(config_prof_libunwind, bool) -CTL_RO_CONFIG_GEN(config_prof_frameptr, bool) CTL_RO_CONFIG_GEN(config_stats, bool) CTL_RO_CONFIG_GEN(config_utrace, bool) CTL_RO_CONFIG_GEN(config_xmalloc, bool) diff --git a/src/prof_stack_range.c b/src/prof_stack_range.c deleted file mode 100644 index ef5e8062..00000000 --- a/src/prof_stack_range.c +++ /dev/null @@ -1,174 +0,0 @@ -#include "jemalloc/internal/jemalloc_preamble.h" - -#include "jemalloc/internal/malloc_io.h" -#include "jemalloc/internal/prof_sys.h" - -#if defined(__linux__) && defined(JEMALLOC_HAVE_GETTID) - -# include -# include -# include -# include // strtoul -# include -# include - -/* - * Converts a string representing a hexadecimal number to an unsigned long long - * integer. Functionally equivalent to strtoull() (for base 16) but faster for - * that case. - * - * @param nptr Pointer to the string to be converted. - * @param endptr Pointer to a pointer to character, which will be set to the - * character in `nptr` where parsing stopped. Can be NULL. - * @return The converted unsigned long long integer value. - */ -static inline unsigned long long int -strtoull_hex(const char *nptr, char **endptr) { - unsigned long long int val = 0; - int ii = 0; - for (; ii < 16; ++ii) { - char c = nptr[ii]; - if (c >= '0' && c <= '9') { - val = (val << 4) + (c - '0'); - } else if (c >= 'a' && c <= 'f') { - val = (val << 4) + (c - 'a' + 10); - } else { - break; - } - } - if (endptr) { - *endptr = (char *)(nptr + ii); - } - return val; -} - -static int -prof_mapping_containing_addr(uintptr_t addr, const char *maps_path, - uintptr_t *mm_start, uintptr_t *mm_end) { - int ret = ENOENT; /* not found */ - *mm_start = *mm_end = 0; - - /* - * Each line of /proc//maps is: - * - - * - * The fields we care about are always within the first 34 characters so - * as long as `buf` contains the start of a mapping line it can always be - * parsed. - */ - static const int kMappingFieldsWidth = 34; - - int fd = -1; - char buf[4096]; - ssize_t remaining = 0; /* actual number of bytes read to buf */ - char *line = NULL; - - while (1) { - if (fd < 0) { - /* case 0: initial open of maps file */ - fd = malloc_open(maps_path, O_RDONLY); - if (fd < 0) { - return errno; - } - - remaining = malloc_read_fd(fd, buf, sizeof(buf)); - if (remaining < 0) { - ret = errno; - break; - } else if (remaining == 0) { - break; - } - line = buf; - } else if (line == NULL) { - /* case 1: no newline found in buf */ - remaining = malloc_read_fd(fd, buf, sizeof(buf)); - if (remaining < 0) { - ret = errno; - break; - } else if (remaining == 0) { - break; - } - line = memchr(buf, '\n', remaining); - if (line != NULL) { - line++; /* advance to character after newline */ - remaining -= (line - buf); - } - } else if (line != NULL && remaining < kMappingFieldsWidth) { - /* - * case 2: found newline but insufficient characters remaining in - * buf - */ - memcpy(buf, line, - remaining); /* copy remaining characters to start of buf */ - line = buf; - - ssize_t count = malloc_read_fd( - fd, buf + remaining, sizeof(buf) - remaining); - if (count < 0) { - ret = errno; - break; - } else if (count == 0) { - break; - } - - remaining += - count; /* actual number of bytes read to buf */ - } else { - /* case 3: found newline and sufficient characters to parse */ - - /* parse - */ - char *tmp = line; - uintptr_t start_addr = (uintptr_t)strtoull_hex( - tmp, &tmp); - if (addr >= start_addr) { - tmp++; /* advance to character after '-' */ - uintptr_t end_addr = (uintptr_t)strtoull_hex( - tmp, NULL); - if (addr < end_addr) { - *mm_start = start_addr; - *mm_end = end_addr; - ret = 0; - break; - } - } - - /* Advance to character after next newline in the current buf. */ - char *prev_line = line; - line = memchr(line, '\n', remaining); - if (line != NULL) { - line++; /* advance to character after newline */ - remaining -= (line - prev_line); - } - } - } - - malloc_close(fd); - return ret; -} - -int -prof_thread_stack_range(uintptr_t fp, uintptr_t *low, uintptr_t *high) { - /* - * NOTE: Prior to kernel 4.5 an entry for every thread stack was included in - * /proc//maps as [STACK:]. Starting with kernel 4.5 only the main - * thread stack remains as the [stack] mapping. For other thread stacks the - * mapping is still visible in /proc//task//maps (though not - * labeled as [STACK:tid]). - * https://lists.ubuntu.com/archives/kernel-team/2016-March/074681.html - */ - char maps_path[64]; // "/proc//task//maps" - malloc_snprintf(maps_path, sizeof(maps_path), "/proc/%d/task/%d/maps", - getpid(), gettid()); - return prof_mapping_containing_addr(fp, maps_path, low, high); -} - -#else - -int -prof_thread_stack_range( - UNUSED uintptr_t addr, uintptr_t *stack_start, uintptr_t *stack_end) { - *stack_start = *stack_end = 0; - return ENOENT; -} - -#endif // __linux__ diff --git a/src/prof_sys.c b/src/prof_sys.c index be59746c..0c086bc9 100644 --- a/src/prof_sys.c +++ b/src/prof_sys.c @@ -28,11 +28,6 @@ JEMALLOC_TEST_HOOK(_Unwind_Backtrace, test_hooks_libc_hook) #endif -#ifdef JEMALLOC_PROF_FRAME_POINTER -// execinfo backtrace() as fallback unwinder -# include -#endif - /******************************************************************************/ malloc_mutex_t prof_dump_filename_mtx; @@ -109,103 +104,6 @@ prof_backtrace_impl(void **vec, unsigned *len, unsigned max_len) { _Unwind_Backtrace(prof_unwind_callback, &data); } -#elif (defined(JEMALLOC_PROF_FRAME_POINTER)) -JEMALLOC_DIAGNOSTIC_PUSH -JEMALLOC_DIAGNOSTIC_IGNORE_FRAME_ADDRESS - -struct stack_range { - uintptr_t start; - uintptr_t end; -}; - -struct thread_unwind_info { - struct stack_range stack_range; - bool fallback; -}; -static __thread struct thread_unwind_info unwind_info = { - .stack_range = - { - .start = 0, - .end = 0, - }, - .fallback = false, -}; /* thread local */ - -static void -prof_backtrace_impl(void **vec, unsigned *len, unsigned max_len) { - /* fp: current stack frame pointer - * - * stack_range: readable stack memory range for the current thread. - * Used to validate frame addresses during stack unwinding. - * For most threads there is a single valid stack range - * that is fixed at thread creation time. This may not be - * the case when folly fibers or boost contexts are used. - * In those cases fall back to using execinfo backtrace() - * (DWARF unwind). - */ - - /* always safe to get the current stack frame address */ - uintptr_t fp = (uintptr_t)__builtin_frame_address(0); - - /* new thread - get the stack range */ - if (!unwind_info.fallback - && unwind_info.stack_range.start == unwind_info.stack_range.end) { - if (prof_thread_stack_range(fp, &unwind_info.stack_range.start, - &unwind_info.stack_range.end) - != 0) { - unwind_info.fallback = true; - } else { - assert(fp >= unwind_info.stack_range.start - && fp < unwind_info.stack_range.end); - } - } - - if (unwind_info.fallback) { - goto label_fallback; - } - - unsigned ii = 0; - while (ii < max_len && fp != 0) { - if (fp < unwind_info.stack_range.start - || fp >= unwind_info.stack_range.end) { - /* - * Determining the stack range from procfs can be - * relatively expensive especially for programs with - * many threads / shared libraries. If the stack - * range has changed, it is likely to change again - * in the future (fibers or some other stack - * manipulation). So fall back to backtrace for this - * thread. - */ - unwind_info.fallback = true; - goto label_fallback; - } - void *ip = ((void **)fp)[1]; - if (ip == 0) { - break; - } - vec[ii++] = ip; - fp = ((uintptr_t *)fp)[0]; - } - *len = ii; - return; - -label_fallback: - /* - * Using the backtrace from execinfo.h here. Note that it may get - * redirected to libunwind when a libunwind not built with build-time - * flag --disable-weak-backtrace is linked. - */ - assert(unwind_info.fallback); - int nframes = backtrace(vec, max_len); - if (nframes > 0) { - *len = nframes; - } else { - *len = 0; - } -} - -JEMALLOC_DIAGNOSTIC_POP #elif (defined(JEMALLOC_PROF_GCC)) JEMALLOC_DIAGNOSTIC_PUSH JEMALLOC_DIAGNOSTIC_IGNORE_FRAME_ADDRESS diff --git a/src/stats.c b/src/stats.c index d4b0f4e6..f619055a 100644 --- a/src/stats.c +++ b/src/stats.c @@ -1667,7 +1667,6 @@ stats_general_print(emitter_t *emitter) { CONFIG_WRITE_BOOL(prof); CONFIG_WRITE_BOOL(prof_libgcc); CONFIG_WRITE_BOOL(prof_libunwind); - CONFIG_WRITE_BOOL(prof_frameptr); CONFIG_WRITE_BOOL(stats); CONFIG_WRITE_BOOL(utrace); CONFIG_WRITE_BOOL(xmalloc); diff --git a/test/unit/mallctl.c b/test/unit/mallctl.c index 4452d3cb..a634570a 100644 --- a/test/unit/mallctl.c +++ b/test/unit/mallctl.c @@ -489,7 +489,6 @@ TEST_BEGIN(test_mallctl_config) { TEST_MALLCTL_CONFIG(prof, bool); TEST_MALLCTL_CONFIG(prof_libgcc, bool); TEST_MALLCTL_CONFIG(prof_libunwind, bool); - TEST_MALLCTL_CONFIG(prof_frameptr, bool); TEST_MALLCTL_CONFIG(stats, bool); TEST_MALLCTL_CONFIG(utrace, bool); TEST_MALLCTL_CONFIG(xmalloc, bool);