From e463a09af2f0677b9485a7e8e4e70b396b2ffb6f Mon Sep 17 00:00:00 2001 From: Peter Zijlstra Date: Sat, 4 Dec 2021 14:43:44 +0100 Subject: x86: Add straight-line-speculation mitigation Make use of an upcoming GCC feature to mitigate straight-line-speculation for x86: https://gcc.gnu.org/g:53a643f8568067d7700a9f2facc8ba39974973d3 https://gcc.gnu.org/bugzilla/show_bug.cgi?id=102952 https://bugs.llvm.org/show_bug.cgi?id=52323 It's built tested on x86_64-allyesconfig using GCC-12 and GCC-11. Maintenance overhead of this should be fairly low due to objtool validation. Size overhead of all these additional int3 instructions comes to: text data bss dec hex filename 22267751 6933356 2011368 31212475 1dc43bb defconfig-build/vmlinux 22804126 6933356 1470696 31208178 1dc32f2 defconfig-build/vmlinux.sls Or roughly 2.4% additional text. Signed-off-by: Peter Zijlstra (Intel) Signed-off-by: Borislav Petkov Link: https://lore.kernel.org/r/20211204134908.140103474@infradead.org --- scripts/link-vmlinux.sh | 3 +++ 1 file changed, 3 insertions(+) (limited to 'scripts/link-vmlinux.sh') diff --git a/scripts/link-vmlinux.sh b/scripts/link-vmlinux.sh index 5cdd9bc5c385..9716f285e404 100755 --- a/scripts/link-vmlinux.sh +++ b/scripts/link-vmlinux.sh @@ -139,6 +139,9 @@ objtool_link() if [ -n "${CONFIG_X86_SMAP}" ]; then objtoolopt="${objtoolopt} --uaccess" fi + if [ -n "${CONFIG_SLS}" ]; then + objtoolopt="${objtoolopt} --sls" + fi info OBJTOOL ${1} tools/objtool/objtool ${objtoolcmd} ${objtoolopt} ${1} fi -- cgit v1.2.3-71-gd317 From 7d153696e5db1e37387c2f7ec06ffc8d4aac70a4 Mon Sep 17 00:00:00 2001 From: Masahiro Yamada Date: Tue, 14 Dec 2021 11:53:52 +0900 Subject: kbuild: do not include include/config/auto.conf from shell scripts Richard Weinberger pointed out the risk of sourcing the kernel config from shell scripts [1], and proposed some patches [2], [3]. It is a good point, but it took a long time because I was wondering how to fix this. This commit goes with simple grep approach because there are only a few scripts including the kernel configuration. scripts/link_vmlinux.sh has references to a bunch of CONFIG options, all of which are boolean. I added is_enabled() helper as scripts/package/{mkdebian,builddeb} do. scripts/gen_autoksyms.sh uses 'eval', stating "to expand the whitelist path". I removed it since it is the issue we are trying to fix. I was a bit worried about the cost of invoking the grep command over again. I extracted the grep parts from it, and measured the cost. It was approximately 0.03 sec, which I hope is acceptable. [test code] $ cat test-grep.sh #!/bin/sh is_enabled() { grep -q "^$1=y" include/config/auto.conf } is_enabled CONFIG_LTO_CLANG is_enabled CONFIG_LTO_CLANG is_enabled CONFIG_STACK_VALIDATION is_enabled CONFIG_UNWINDER_ORC is_enabled CONFIG_FTRACE_MCOUNT_USE_OBJTOOL is_enabled CONFIG_VMLINUX_VALIDATION is_enabled CONFIG_FRAME_POINTER is_enabled CONFIG_GCOV_KERNEL is_enabled CONFIG_LTO_CLANG is_enabled CONFIG_RETPOLINE is_enabled CONFIG_X86_SMAP is_enabled CONFIG_LTO_CLANG is_enabled CONFIG_VMLINUX_MAP is_enabled CONFIG_KALLSYMS_ALL is_enabled CONFIG_KALLSYMS_ABSOLUTE_PERCPU is_enabled CONFIG_KALLSYMS_BASE_RELATIVE is_enabled CONFIG_DEBUG_INFO_BTF is_enabled CONFIG_KALLSYMS is_enabled CONFIG_DEBUG_INFO_BTF is_enabled CONFIG_BPF is_enabled CONFIG_BUILDTIME_TABLE_SORT is_enabled CONFIG_KALLSYMS $ time ./test-grep.sh real 0m0.036s user 0m0.027s sys m0.009s [1]: https://lore.kernel.org/all/1919455.eZKeABUfgV@blindfold/ [2]: https://lore.kernel.org/all/20180219092245.26404-1-richard@nod.at/ [3]: https://lore.kernel.org/all/20210920213957.1064-2-richard@nod.at/ Signed-off-by: Masahiro Yamada Reviewed-by: Nicolas Schier --- scripts/gen_autoksyms.sh | 11 +++-------- scripts/link-vmlinux.sh | 47 ++++++++++++++++++++++++----------------------- scripts/setlocalversion | 9 ++++----- 3 files changed, 31 insertions(+), 36 deletions(-) (limited to 'scripts/link-vmlinux.sh') diff --git a/scripts/gen_autoksyms.sh b/scripts/gen_autoksyms.sh index 6ed0d225c8b1..949d6a054034 100755 --- a/scripts/gen_autoksyms.sh +++ b/scripts/gen_autoksyms.sh @@ -16,20 +16,15 @@ case "$KBUILD_VERBOSE" in ;; esac -# We need access to CONFIG_ symbols -. include/config/auto.conf - needed_symbols= # Special case for modversions (see modpost.c) -if [ -n "$CONFIG_MODVERSIONS" ]; then +if grep -q "^CONFIG_MODVERSIONS=y$" include/config/auto.conf; then needed_symbols="$needed_symbols module_layout" fi -ksym_wl= -if [ -n "$CONFIG_UNUSED_KSYMS_WHITELIST" ]; then - # Use 'eval' to expand the whitelist path and check if it is relative - eval ksym_wl="$CONFIG_UNUSED_KSYMS_WHITELIST" +ksym_wl=$(sed -n 's/^CONFIG_UNUSED_KSYMS_WHITELIST="\(.*\)"$/\1/p' include/config/auto.conf) +if [ -n "$ksym_wl" ]; then [ "${ksym_wl}" != "${ksym_wl#/}" ] || ksym_wl="$abs_srctree/$ksym_wl" if [ ! -f "$ksym_wl" ] || [ ! -r "$ksym_wl" ]; then echo "ERROR: '$ksym_wl' whitelist file not found" >&2 diff --git a/scripts/link-vmlinux.sh b/scripts/link-vmlinux.sh index 5cdd9bc5c385..a4b61a2f65db 100755 --- a/scripts/link-vmlinux.sh +++ b/scripts/link-vmlinux.sh @@ -34,6 +34,10 @@ LD="$1" KBUILD_LDFLAGS="$2" LDFLAGS_vmlinux="$3" +is_enabled() { + grep -q "^$1=y" include/config/auto.conf +} + # Nice output in kbuild format # Will be supressed by "make -s" info() @@ -80,11 +84,11 @@ modpost_link() ${KBUILD_VMLINUX_LIBS} \ --end-group" - if [ -n "${CONFIG_LTO_CLANG}" ]; then + if is_enabled CONFIG_LTO_CLANG; then gen_initcalls lds="-T .tmp_initcalls.lds" - if [ -n "${CONFIG_MODVERSIONS}" ]; then + if is_enabled CONFIG_MODVERSIONS; then gen_symversions lds="${lds} -T .tmp_symversions.lds" fi @@ -104,21 +108,21 @@ objtool_link() local objtoolcmd; local objtoolopt; - if [ "${CONFIG_LTO_CLANG} ${CONFIG_STACK_VALIDATION}" = "y y" ]; then + if is_enabled CONFIG_LTO_CLANG && is_enabled CONFIG_STACK_VALIDATION; then # Don't perform vmlinux validation unless explicitly requested, # but run objtool on vmlinux.o now that we have an object file. - if [ -n "${CONFIG_UNWINDER_ORC}" ]; then + if is_enabled CONFIG_UNWINDER_ORC; then objtoolcmd="orc generate" fi objtoolopt="${objtoolopt} --duplicate" - if [ -n "${CONFIG_FTRACE_MCOUNT_USE_OBJTOOL}" ]; then + if is_enabled CONFIG_FTRACE_MCOUNT_USE_OBJTOOL; then objtoolopt="${objtoolopt} --mcount" fi fi - if [ -n "${CONFIG_VMLINUX_VALIDATION}" ]; then + if is_enabled CONFIG_VMLINUX_VALIDATION; then objtoolopt="${objtoolopt} --noinstr" fi @@ -127,16 +131,16 @@ objtool_link() objtoolcmd="check" fi objtoolopt="${objtoolopt} --vmlinux" - if [ -z "${CONFIG_FRAME_POINTER}" ]; then + if ! is_enabled CONFIG_FRAME_POINTER; then objtoolopt="${objtoolopt} --no-fp" fi - if [ -n "${CONFIG_GCOV_KERNEL}" ] || [ -n "${CONFIG_LTO_CLANG}" ]; then + if is_enabled CONFIG_GCOV_KERNEL || is_enabled CONFIG_LTO_CLANG; then objtoolopt="${objtoolopt} --no-unreachable" fi - if [ -n "${CONFIG_RETPOLINE}" ]; then + if is_enabled CONFIG_RETPOLINE; then objtoolopt="${objtoolopt} --retpoline" fi - if [ -n "${CONFIG_X86_SMAP}" ]; then + if is_enabled CONFIG_X86_SMAP; then objtoolopt="${objtoolopt} --uaccess" fi info OBJTOOL ${1} @@ -161,7 +165,7 @@ vmlinux_link() # skip output file argument shift - if [ -n "${CONFIG_LTO_CLANG}" ]; then + if is_enabled CONFIG_LTO_CLANG; then # Use vmlinux.o instead of performing the slow LTO link again. objs=vmlinux.o libs= @@ -189,7 +193,7 @@ vmlinux_link() ldflags="${ldflags} ${wl}--strip-debug" fi - if [ -n "${CONFIG_VMLINUX_MAP}" ]; then + if is_enabled CONFIG_VMLINUX_MAP; then ldflags="${ldflags} ${wl}-Map=${output}.map" fi @@ -239,15 +243,15 @@ kallsyms() { local kallsymopt; - if [ -n "${CONFIG_KALLSYMS_ALL}" ]; then + if is_enabled CONFIG_KALLSYMS_ALL; then kallsymopt="${kallsymopt} --all-symbols" fi - if [ -n "${CONFIG_KALLSYMS_ABSOLUTE_PERCPU}" ]; then + if is_enabled CONFIG_KALLSYMS_ABSOLUTE_PERCPU; then kallsymopt="${kallsymopt} --absolute-percpu" fi - if [ -n "${CONFIG_KALLSYMS_BASE_RELATIVE}" ]; then + if is_enabled CONFIG_KALLSYMS_BASE_RELATIVE; then kallsymopt="${kallsymopt} --base-relative" fi @@ -312,9 +316,6 @@ if [ "$1" = "clean" ]; then exit 0 fi -# We need access to CONFIG_ symbols -. include/config/auto.conf - # Update version info GEN .version if [ -r .version ]; then @@ -343,7 +344,7 @@ tr '\0' '\n' < modules.builtin.modinfo | sed -n 's/^[[:alnum:]:_]*\.file=//p' | tr ' ' '\n' | uniq | sed -e 's:^:kernel/:' -e 's/$/.ko/' > modules.builtin btf_vmlinux_bin_o="" -if [ -n "${CONFIG_DEBUG_INFO_BTF}" ]; then +if is_enabled CONFIG_DEBUG_INFO_BTF; then btf_vmlinux_bin_o=.btf.vmlinux.bin.o if ! gen_btf .tmp_vmlinux.btf $btf_vmlinux_bin_o ; then echo >&2 "Failed to generate BTF for vmlinux" @@ -355,7 +356,7 @@ fi kallsymso="" kallsymso_prev="" kallsyms_vmlinux="" -if [ -n "${CONFIG_KALLSYMS}" ]; then +if is_enabled CONFIG_KALLSYMS; then # kallsyms support # Generate section listing all symbols and add it into vmlinux @@ -395,12 +396,12 @@ fi vmlinux_link vmlinux "${kallsymso}" ${btf_vmlinux_bin_o} # fill in BTF IDs -if [ -n "${CONFIG_DEBUG_INFO_BTF}" -a -n "${CONFIG_BPF}" ]; then +if is_enabled CONFIG_DEBUG_INFO_BTF && is_enabled CONFIG_BPF; then info BTFIDS vmlinux ${RESOLVE_BTFIDS} vmlinux fi -if [ -n "${CONFIG_BUILDTIME_TABLE_SORT}" ]; then +if is_enabled CONFIG_BUILDTIME_TABLE_SORT; then info SORTTAB vmlinux if ! sorttable vmlinux; then echo >&2 Failed to sort kernel tables @@ -412,7 +413,7 @@ info SYSMAP System.map mksysmap vmlinux System.map # step a (see comment above) -if [ -n "${CONFIG_KALLSYMS}" ]; then +if is_enabled CONFIG_KALLSYMS; then mksysmap ${kallsyms_vmlinux} .tmp_System.map if ! cmp -s System.map .tmp_System.map; then diff --git a/scripts/setlocalversion b/scripts/setlocalversion index 6b54e46a0f12..d06137405190 100755 --- a/scripts/setlocalversion +++ b/scripts/setlocalversion @@ -111,9 +111,7 @@ if $scm_only; then exit fi -if test -e include/config/auto.conf; then - . include/config/auto.conf -else +if ! test -e include/config/auto.conf; then echo "Error: kernelrelease not valid - run 'make prepare' to update it" >&2 exit 1 fi @@ -125,10 +123,11 @@ if test ! "$srctree" -ef .; then fi # CONFIG_LOCALVERSION and LOCALVERSION (if set) -res="${res}${CONFIG_LOCALVERSION}${LOCALVERSION}" +config_localversion=$(sed -n 's/^CONFIG_LOCALVERSION="\(.*\)"$/\1/p' include/config/auto.conf) +res="${res}${config_localversion}${LOCALVERSION}" # scm version string if not at a tagged commit -if test "$CONFIG_LOCALVERSION_AUTO" = "y"; then +if grep -q "^CONFIG_LOCALVERSION_AUTO=y$" include/config/auto.conf; then # full scm version string res="$res$(scm_version)" elif [ "${LOCALVERSION+set}" != "set" ]; then -- cgit v1.2.3-71-gd317 From 72b3942a173c387b27860ba1069636726e208777 Mon Sep 17 00:00:00 2001 From: Yinan Liu Date: Sun, 12 Dec 2021 19:33:58 +0800 Subject: scripts: ftrace - move the sort-processing in ftrace_init When the kernel starts, the initialization of ftrace takes up a portion of the time (approximately 6~8ms) to sort mcount addresses. We can save this time by moving mcount-sorting to compile time. Link: https://lkml.kernel.org/r/20211212113358.34208-2-yinan@linux.alibaba.com Signed-off-by: Yinan Liu Reported-by: kernel test robot Reported-by: kernel test robot Signed-off-by: Steven Rostedt --- kernel/trace/ftrace.c | 11 ++++- scripts/Makefile | 6 ++- scripts/link-vmlinux.sh | 6 +-- scripts/sorttable.c | 2 + scripts/sorttable.h | 120 +++++++++++++++++++++++++++++++++++++++++++++++- 5 files changed, 137 insertions(+), 8 deletions(-) (limited to 'scripts/link-vmlinux.sh') diff --git a/kernel/trace/ftrace.c b/kernel/trace/ftrace.c index 30bc880c3849..9ca63df6553a 100644 --- a/kernel/trace/ftrace.c +++ b/kernel/trace/ftrace.c @@ -6406,8 +6406,15 @@ static int ftrace_process_locs(struct module *mod, if (!count) return 0; - sort(start, count, sizeof(*start), - ftrace_cmp_ips, NULL); + /* + * Sorting mcount in vmlinux at build time depend on + * CONFIG_BUILDTIME_TABLE_SORT, while mcount loc in + * modules can not be sorted at build time. + */ + if (!IS_ENABLED(CONFIG_BUILDTIME_TABLE_SORT) || mod) { + sort(start, count, sizeof(*start), + ftrace_cmp_ips, NULL); + } start_pg = ftrace_allocate_pages(count); if (!start_pg) diff --git a/scripts/Makefile b/scripts/Makefile index 9adb6d247818..b082d2f93357 100644 --- a/scripts/Makefile +++ b/scripts/Makefile @@ -17,6 +17,7 @@ hostprogs-always-$(CONFIG_SYSTEM_EXTRA_CERTIFICATE) += insert-sys-cert hostprogs-always-$(CONFIG_SYSTEM_REVOCATION_LIST) += extract-cert HOSTCFLAGS_sorttable.o = -I$(srctree)/tools/include +HOSTLDLIBS_sorttable = -lpthread HOSTCFLAGS_asn1_compiler.o = -I$(srctree)/include HOSTCFLAGS_sign-file.o = $(CRYPTO_CFLAGS) HOSTLDLIBS_sign-file = $(CRYPTO_LIBS) @@ -29,7 +30,10 @@ ARCH := x86 endif HOSTCFLAGS_sorttable.o += -I$(srctree)/tools/arch/x86/include HOSTCFLAGS_sorttable.o += -DUNWINDER_ORC_ENABLED -HOSTLDLIBS_sorttable = -lpthread +endif + +ifdef CONFIG_DYNAMIC_FTRACE +HOSTCFLAGS_sorttable.o += -DMCOUNT_SORT_ENABLED endif # The following programs are only built on demand diff --git a/scripts/link-vmlinux.sh b/scripts/link-vmlinux.sh index 5cdd9bc5c385..dd9955f45774 100755 --- a/scripts/link-vmlinux.sh +++ b/scripts/link-vmlinux.sh @@ -400,6 +400,9 @@ if [ -n "${CONFIG_DEBUG_INFO_BTF}" -a -n "${CONFIG_BPF}" ]; then ${RESOLVE_BTFIDS} vmlinux fi +info SYSMAP System.map +mksysmap vmlinux System.map + if [ -n "${CONFIG_BUILDTIME_TABLE_SORT}" ]; then info SORTTAB vmlinux if ! sorttable vmlinux; then @@ -408,9 +411,6 @@ if [ -n "${CONFIG_BUILDTIME_TABLE_SORT}" ]; then fi fi -info SYSMAP System.map -mksysmap vmlinux System.map - # step a (see comment above) if [ -n "${CONFIG_KALLSYMS}" ]; then mksysmap ${kallsyms_vmlinux} .tmp_System.map diff --git a/scripts/sorttable.c b/scripts/sorttable.c index b7c2ad71f9cf..70bdc787ddfb 100644 --- a/scripts/sorttable.c +++ b/scripts/sorttable.c @@ -30,6 +30,8 @@ #include #include #include +#include +#include #include #include diff --git a/scripts/sorttable.h b/scripts/sorttable.h index 7b9745cf8c70..1e8b77928fa4 100644 --- a/scripts/sorttable.h +++ b/scripts/sorttable.h @@ -19,6 +19,9 @@ #undef extable_ent_size #undef compare_extable +#undef get_mcount_loc +#undef sort_mcount_loc +#undef elf_mcount_loc #undef do_sort #undef Elf_Addr #undef Elf_Ehdr @@ -41,6 +44,9 @@ #ifdef SORTTABLE_64 # define extable_ent_size 16 # define compare_extable compare_extable_64 +# define get_mcount_loc get_mcount_loc_64 +# define sort_mcount_loc sort_mcount_loc_64 +# define elf_mcount_loc elf_mcount_loc_64 # define do_sort do_sort_64 # define Elf_Addr Elf64_Addr # define Elf_Ehdr Elf64_Ehdr @@ -62,6 +68,9 @@ #else # define extable_ent_size 8 # define compare_extable compare_extable_32 +# define get_mcount_loc get_mcount_loc_32 +# define sort_mcount_loc sort_mcount_loc_32 +# define elf_mcount_loc elf_mcount_loc_32 # define do_sort do_sort_32 # define Elf_Addr Elf32_Addr # define Elf_Ehdr Elf32_Ehdr @@ -84,8 +93,6 @@ #if defined(SORTTABLE_64) && defined(UNWINDER_ORC_ENABLED) /* ORC unwinder only support X86_64 */ -#include -#include #include #define ERRSTR_MAXSZ 256 @@ -191,7 +198,64 @@ static int compare_extable(const void *a, const void *b) return 1; return 0; } +#ifdef MCOUNT_SORT_ENABLED +struct elf_mcount_loc { + Elf_Ehdr *ehdr; + Elf_Shdr *init_data_sec; + uint_t start_mcount_loc; + uint_t stop_mcount_loc; +}; + +/* Sort the addresses stored between __start_mcount_loc to __stop_mcount_loc in vmlinux */ +static void *sort_mcount_loc(void *arg) +{ + struct elf_mcount_loc *emloc = (struct elf_mcount_loc *)arg; + uint_t offset = emloc->start_mcount_loc - _r(&(emloc->init_data_sec)->sh_addr) + + _r(&(emloc->init_data_sec)->sh_offset); + uint_t count = emloc->stop_mcount_loc - emloc->start_mcount_loc; + unsigned char *start_loc = (void *)emloc->ehdr + offset; + + qsort(start_loc, count/sizeof(uint_t), sizeof(uint_t), compare_extable); + return NULL; +} + +/* Get the address of __start_mcount_loc and __stop_mcount_loc in System.map */ +static void get_mcount_loc(uint_t *_start, uint_t *_stop) +{ + FILE *file_start, *file_stop; + char start_buff[20]; + char stop_buff[20]; + int len = 0; + + file_start = popen(" grep start_mcount System.map | awk '{print $1}' ", "r"); + if (!file_start) { + fprintf(stderr, "get start_mcount_loc error!"); + return; + } + + file_stop = popen(" grep stop_mcount System.map | awk '{print $1}' ", "r"); + if (!file_stop) { + fprintf(stderr, "get stop_mcount_loc error!"); + pclose(file_start); + return; + } + + while (fgets(start_buff, sizeof(start_buff), file_start) != NULL) { + len = strlen(start_buff); + start_buff[len - 1] = '\0'; + } + *_start = strtoul(start_buff, NULL, 16); + + while (fgets(stop_buff, sizeof(stop_buff), file_stop) != NULL) { + len = strlen(stop_buff); + stop_buff[len - 1] = '\0'; + } + *_stop = strtoul(stop_buff, NULL, 16); + pclose(file_start); + pclose(file_stop); +} +#endif static int do_sort(Elf_Ehdr *ehdr, char const *const fname, table_sort_t custom_sort) @@ -217,6 +281,12 @@ static int do_sort(Elf_Ehdr *ehdr, int idx; unsigned int shnum; unsigned int shstrndx; +#ifdef MCOUNT_SORT_ENABLED + struct elf_mcount_loc mstruct; + uint_t _start_mcount_loc = 0; + uint_t _stop_mcount_loc = 0; + pthread_t mcount_sort_thread; +#endif #if defined(SORTTABLE_64) && defined(UNWINDER_ORC_ENABLED) unsigned int orc_ip_size = 0; unsigned int orc_size = 0; @@ -253,6 +323,17 @@ static int do_sort(Elf_Ehdr *ehdr, symtab_shndx = (Elf32_Word *)((const char *)ehdr + _r(&s->sh_offset)); +#ifdef MCOUNT_SORT_ENABLED + /* locate the .init.data section in vmlinux */ + if (!strcmp(secstrings + idx, ".init.data")) { + get_mcount_loc(&_start_mcount_loc, &_stop_mcount_loc); + mstruct.ehdr = ehdr; + mstruct.init_data_sec = s; + mstruct.start_mcount_loc = _start_mcount_loc; + mstruct.stop_mcount_loc = _stop_mcount_loc; + } +#endif + #if defined(SORTTABLE_64) && defined(UNWINDER_ORC_ENABLED) /* locate the ORC unwind tables */ if (!strcmp(secstrings + idx, ".orc_unwind_ip")) { @@ -294,6 +375,23 @@ static int do_sort(Elf_Ehdr *ehdr, goto out; } #endif + +#ifdef MCOUNT_SORT_ENABLED + if (!mstruct.init_data_sec || !_start_mcount_loc || !_stop_mcount_loc) { + fprintf(stderr, + "incomplete mcount's sort in file: %s\n", + fname); + goto out; + } + + /* create thread to sort mcount_loc concurrently */ + if (pthread_create(&mcount_sort_thread, NULL, &sort_mcount_loc, &mstruct)) { + fprintf(stderr, + "pthread_create mcount_sort_thread failed '%s': %s\n", + strerror(errno), fname); + goto out; + } +#endif if (!extab_sec) { fprintf(stderr, "no __ex_table in file: %s\n", fname); goto out; @@ -376,5 +474,23 @@ out: } } #endif + +#ifdef MCOUNT_SORT_ENABLED + if (mcount_sort_thread) { + void *retval = NULL; + /* wait for mcount sort done */ + rc = pthread_join(mcount_sort_thread, &retval); + if (rc) { + fprintf(stderr, + "pthread_join failed '%s': %s\n", + strerror(errno), fname); + } else if (retval) { + rc = -1; + fprintf(stderr, + "failed to sort mcount '%s': %s\n", + (char *)retval, fname); + } + } +#endif return rc; } -- cgit v1.2.3-71-gd317