Kernel build does not link in libgcc, which defines the function. David
On Fri, Dec 21, 2012 at 8:31 AM, Teresa Johnson <tejohn...@google.com> wrote: > On Wed, Dec 19, 2012 at 12:11 PM, Rong Xu <x...@google.com> wrote: >> Hi, >> >> This patch updates the support for FDO build in linux kernel for gcc 4.7. >> Tested with 2.6.34 kernel and google internal benchmarks. >> >> Thanks, >> >> -Rong >> >> 2012-12-19 Rong Xu <x...@google.com> >> >> * libgcc/libgcov.c >> (gcov_counter_active): v4.7 kernel fdo support. >> (crc32_unsigned): Include in GCOV_KERNEL build. >> (gcov_alloc_filename): Remove from GCOV_KERNEL build. >> (gcov_sort_icall_topn_counter): Ditto. >> (gcov_dump_module_info): Ditto. >> (gcov_compute_histogram): v4.7 kernel fdo support. >> (gcov_merge_gcda_file): Ditto. >> (gcov_gcda_file_size): Ditto. >> (gcov_write_gcda_file): Ditto. >> (__gcov_topn_value_profiler_body): Ditto. >> (gcov_set_vfile): Ditto. >> (gcov_kernel_dump_gcov_init): Ditto. >> (gcov_kernel_dump_one_gcov): Ditto. >> * gcc/gcov-io.c (gcov_read_string): Ditto. >> (static int k_popcountll): Ditto. >> (gcov_read_summary): Ditto. >> (kernel_file_fclose): Ditto. >> (kernel_file_ftell): Ditto. >> (kernel_file_fwrite): Ditto. >> * gcc/gcov-io.h (struct gcov_info): remove const keyword. >> >> Index: libgcc/libgcov.c >> =================================================================== >> --- libgcc/libgcov.c (revision 194562) >> +++ libgcc/libgcov.c (working copy) >> @@ -46,11 +46,11 @@ see the files COPYING3 and COPYING.RUNTIME respect >> #include "tsystem.h" >> #include "coretypes.h" >> #include "tm.h" >> -#endif /* __KERNEL__ */ >> #include "libgcc_tm.h" >> #include "gthr.h" >> +#endif /* __KERNEL__ */ >> >> -#if 1 >> +#ifndef __KERNEL__ >> #define THREAD_PREFIX __thread >> #else >> #define THREAD_PREFIX >> @@ -120,6 +120,7 @@ extern int gcov_dump_complete ATTRIBUTE_HIDDEN; >> #ifdef L_gcov >> #include "gcov-io.c" >> >> +#ifndef __GCOV_KERNEL__ >> /* Create a strong reference to these symbols so that they are >> unconditionally pulled into the instrumented binary, even when >> the only reference is a weak reference. This is necessary because >> @@ -134,6 +135,7 @@ extern int gcov_dump_complete ATTRIBUTE_HIDDEN; >> these symbols will always need to be resolved. */ >> void (*__gcov_dummy_ref1)() = &__gcov_reset; >> void (*__gcov_dummy_ref2)() = &__gcov_dump; >> +#endif /* __GCOV_KERNEL__ */ >> >> /* Utility function for outputing errors. */ >> static int >> @@ -151,6 +153,10 @@ gcov_error (const char *fmt, ...) >> return ret; >> } >> >> +/* A program checksum allows us to distinguish program data for an >> + object file included in multiple programs. */ >> +static gcov_unsigned_t gcov_crc32; >> + >> #ifndef __GCOV_KERNEL__ >> /* Emitted in coverage.c. */ >> extern char * __gcov_pmu_profile_filename; >> @@ -183,10 +189,6 @@ THREAD_PREFIX gcov_unsigned_t __gcov_sample_counte >> /* Chain of per-object gcov structures. */ >> extern struct gcov_info *__gcov_list; >> >> -/* A program checksum allows us to distinguish program data for an >> - object file included in multiple programs. */ >> -static gcov_unsigned_t gcov_crc32; >> - >> /* Size of the longest file name. */ >> static size_t gcov_max_filename = 0; >> >> @@ -323,8 +325,6 @@ gcov_counter_active (const struct gcov_info *info, >> return (info->merge[type] != 0); >> } >> >> -#ifndef __GCOV_KERNEL__ >> - >> /* Add an unsigned value to the current crc */ >> >> static gcov_unsigned_t >> @@ -344,6 +344,8 @@ crc32_unsigned (gcov_unsigned_t crc32, gcov_unsign >> return crc32; >> } >> >> +#ifndef __GCOV_KERNEL__ >> + >> /* Check if VERSION of the info block PTR matches libgcov one. >> Return 1 on success, or zero in case of versions mismatch. >> If FILENAME is not NULL, its value used for reporting purposes >> @@ -464,6 +466,8 @@ gcov_alloc_filename (void) >> gi_filename_up = gi_filename + prefix_length; >> } >> >> +#endif /* __GCOV_KERNEL__ */ >> + >> /* Sort N entries in VALUE_ARRAY in descending order. >> Each entry in VALUE_ARRAY has two values. The sorting >> is based on the second value. */ >> @@ -509,6 +513,8 @@ gcov_sort_icall_topn_counter (const struct gcov_ct >> } >> } >> >> +#ifndef __GCOV_KERNEL__ >> + >> /* Write imported files (auxiliary modules) for primary module GI_PTR >> into file GI_FILENAME. */ >> >> @@ -586,6 +592,8 @@ gcov_dump_module_info (void) >> __gcov_finalize_dyn_callgraph (); >> } >> >> +#endif /* __GCOV_KERNEL__ */ >> + >> /* Insert counter VALUE into HISTOGRAM. */ >> >> static void >> @@ -656,6 +664,8 @@ gcov_compute_histogram (struct gcov_summary *sum) >> } >> } >> >> +#ifndef __GCOV_KERNEL__ >> + >> /* Dump the coverage counts. We merge with existing counts when >> possible, to avoid growing the .da files ad infinitum. We use this >> program's checksum to make sure we only accumulate whole program >> @@ -1013,12 +1023,7 @@ gcov_merge_gcda_file (struct gcov_info *gi_ptr) >> goto read_error; >> } >> if (tag && tag != GCOV_TAG_MODULE_INFO) >> - { >> - read_mismatch:; >> - fprintf (stderr, "profiling:%s:Merge mismatch for %s\n", >> - gi_filename, f_ix + 1 ? "function" : "summaries"); >> - goto read_fatal; >> - } >> + goto read_mismatch; >> } >> goto rewrite; >> >> @@ -1031,6 +1036,11 @@ read_error:; >> >> goto rewrite; >> >> +read_mismatch:; >> + gcov_error ("profiling:%s:Merge mismatch for %s\n", >> + gi_filename, f_ix + 1 ? "function" : "summaries"); >> + goto read_fatal; >> + >> read_fatal:; >> gcov_close (); >> return 1; >> @@ -1076,7 +1086,7 @@ rewrite:; >> sizeof (*cs_all) - (sizeof (gcov_bucket_type) >> * GCOV_HISTOGRAM_SIZE))) >> { >> - fprintf (stderr, "profiling:%s:Invocation mismatch - " >> + gcov_error ("profiling:%s:Invocation mismatch - " >> "some data files may have been removed%s\n", >> gi_filename, GCOV_LOCKED >> ? "" : " or concurrent update without locking support"); >> @@ -1093,14 +1103,14 @@ rewrite:; >> the size is in units of gcov_type. */ >> >> GCOV_LINKAGE unsigned >> -gcov_gcda_file_size (struct gcov_info *gi_ptr, >> - struct gcov_summary *sum) >> +gcov_gcda_file_size (struct gcov_info *gi_ptr) >> { >> unsigned size; >> const struct gcov_fn_info *fi_ptr; >> unsigned f_ix, t_ix, h_ix, h_cnt = 0; >> unsigned n_counts; >> const struct gcov_ctr_info *ci_ptr; >> + struct gcov_summary *sum = &this_program; >> const struct gcov_ctr_summary *csum; >> >> /* GCOV_DATA_MAGIC, GCOV_VERSION and time_stamp. */ >> @@ -1181,13 +1191,14 @@ gcov_write_gcda_file (struct gcov_info *gi_ptr) >> ci_ptr = gfi_ptr->ctrs; >> for (t_ix = 0; t_ix < GCOV_COUNTERS; t_ix++) >> { >> + gcov_type *c_ptr; >> if (!gi_ptr->merge[t_ix]) >> continue; >> >> n_counts = ci_ptr->num; >> gcov_write_tag_length (GCOV_TAG_FOR_COUNTER (t_ix), >> GCOV_TAG_COUNTER_LENGTH (n_counts)); >> - gcov_type *c_ptr = ci_ptr->values; >> + c_ptr = ci_ptr->values; >> while (n_counts--) >> gcov_write_counter (*c_ptr++); >> ci_ptr++; >> @@ -1692,7 +1703,7 @@ __gcov_topn_value_profiler_body (gcov_type *counte >> { >> unsigned i, j; >> gcov_type *p, minv; >> - gcov_type* tmp_cnts >> + gcov_type* tmp_cnts >> = (gcov_type *)alloca (topn_val * sizeof(gcov_type)); >> >> *num_eviction = 0; >> @@ -2050,15 +2061,20 @@ gcov_set_vfile (gcov_kernel_vfile *file) >> gcov_current_file = file; >> } >> >> +/* Init function before dumping the gcda file in kernel. */ >> + >> +void >> +gcov_kernel_dump_gcov_init (void) >> +{ >> + gcov_exit_init (); >> +} >> + >> /* Dump one entry in the gcov_info list (for one object) in kernel. */ >> >> void >> gcov_kernel_dump_one_gcov (struct gcov_info *info) >> { >> gcc_assert (gcov_current_file); >> - >> - gcov_exit_init (); >> - >> gcov_dump_one_gcov (info); >> } >> >> Index: gcc/gcov-io.c >> =================================================================== >> --- gcc/gcov-io.c (revision 194562) >> +++ gcc/gcov-io.c (working copy) >> @@ -662,6 +662,30 @@ gcov_read_string (void) >> return (const char *) gcov_read_words (length); >> } >> >> +#ifdef __GCOV_KERNEL__ >> +static const unsigned char __popcount_tab[256] = >> +{ >> + 0,1,1,2,1,2,2,3,1,2,2,3,2,3,3,4,1,2,2,3,2,3,3,4,2,3,3,4,3,4,4,5, >> + 1,2,2,3,2,3,3,4,2,3,3,4,3,4,4,5,2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6, >> + 1,2,2,3,2,3,3,4,2,3,3,4,3,4,4,5,2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6, >> + 2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6,3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7, >> + 1,2,2,3,2,3,3,4,2,3,3,4,3,4,4,5,2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6, >> + 2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6,3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7, >> + 2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6,3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7, >> + 3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8 >> +}; >> + >> +static int k_popcountll (long long x) >> +{ >> + int i, ret = 0; >> + >> + for (i = 0; i < 8*sizeof(long long) ; i += 8) >> + ret += __popcount_tab[(x >> i) & 0xff]; >> + >> + return ret; >> +} >> +#endif >> + >> GCOV_LINKAGE void >> gcov_read_summary (struct gcov_summary *summary) >> { >> @@ -683,7 +707,11 @@ gcov_read_summary (struct gcov_summary *summary) >> for (bv_ix = 0; bv_ix < GCOV_HISTOGRAM_BITVECTOR_SIZE; bv_ix++) >> { >> histo_bitvector[bv_ix] = gcov_read_unsigned (); >> +#ifndef __GCOV_KERNEL__ >> h_cnt += __builtin_popcountll (histo_bitvector[bv_ix]); >> +#else >> + h_cnt += k_popcountll (histo_bitvector[bv_ix]); >> +#endif > > Is the issue here that __builtin_popcountll is not available? I just > committed a fix to trunk to deal with a similar issue, can you see if > this would address the problem here too? > > http://gcc.gnu.org/ml/gcc-bugs/2012-12/msg01976.html > > Thanks, > Teresa > >> } >> bv_ix = 0; >> h_ix = 0; >> @@ -1137,7 +1165,6 @@ kernel_file_fclose (gcov_kernel_vfile *fp) >> long >> kernel_file_ftell (gcov_kernel_vfile *fp) >> { >> - gcc_assert (0); /* should not reach here */ >> return 0; >> } >> >> @@ -1192,8 +1219,9 @@ kernel_file_fwrite (const void *ptr, size_t size, >> if (vsize <= vpos) >> { >> printk (KERN_ERR >> - "GCOV_KERNEL: something wrong: vbuf=%p vsize=%u vpos=%u\n", >> - vbuf, vsize, vpos); >> + "GCOV_KERNEL: something wrong in file %s: vbuf=%p vsize=%u" >> + " vpos=%u\n", >> + fp->info->filename, vbuf, vsize, vpos); >> return 0; >> } >> len = vsize - vpos; >> @@ -1207,8 +1235,9 @@ kernel_file_fwrite (const void *ptr, size_t size, >> >> if (len != nitems) >> printk (KERN_ERR >> - "GCOV_KERNEL: something wrong: size=%lu nitems=%lu ret=%d\n", >> - size, nitems, len); >> + "GCOV_KERNEL: something wrong in file %s: size=%lu nitems=%lu" >> + " ret=%d, vsize=%u vpos=%u \n", >> + fp->info->filename, size, nitems, len, vsize, vpos); >> return len; >> } >> >> Index: gcc/gcov-io.h >> =================================================================== >> --- gcc/gcov-io.h (revision 194562) >> +++ gcc/gcov-io.h (working copy) >> @@ -300,6 +300,14 @@ typedef unsigned gcov_type_unsigned __attribute__ >> >> #endif /* BITS_PER_UNIT == 8 */ >> >> +#if LONG_LONG_TYPE_SIZE > 32 >> +#define GCOV_TYPE_SYNC_FETCH_AND_ADD_FN __sync_fetch_and_add_8 >> +#define GCOV_TYPE_SYNC_FETCH_AND_ADD BUILT_IN_SYNC_FETCH_AND_ADD_8 >> +#else >> +#define GCOV_TYPE_SYNC_FETCH_AND_ADD_FN __sync_fetch_and_add_4 >> +#define GCOV_TYPE_SYNC_FETCH_AND_ADD BUILT_IN_SYNC_FETCH_AND_ADD_4 >> +#endif >> + >> #undef EXTRACT_MODULE_ID_FROM_GLOBAL_ID >> #undef EXTRACT_FUNC_ID_FROM_GLOBAL_ID >> #undef GEN_FUNC_GLOBAL_ID >> @@ -322,6 +330,18 @@ typedef unsigned gcov_type_unsigned __attribute__ >> typedef unsigned gcov_unsigned_t; >> typedef unsigned gcov_position_t; >> >> +#if LONG_LONG_TYPE_SIZE > 32 >> +#define GCOV_TYPE_SYNC_FETCH_AND_ADD_FN __sync_fetch_and_add_8 >> +#define GCOV_TYPE_SYNC_FETCH_AND_ADD BUILT_IN_SYNC_FETCH_AND_ADD_8 >> +#else >> +#define GCOV_TYPE_SYNC_FETCH_AND_ADD_FN __sync_fetch_and_add_4 >> +#define GCOV_TYPE_SYNC_FETCH_AND_ADD BUILT_IN_SYNC_FETCH_AND_ADD_4 >> +#endif >> +#define PROFILE_GEN_EDGE_ATOMIC (flag_profile_gen_atomic == 1 || \ >> + flag_profile_gen_atomic == 3) >> +#define PROFILE_GEN_VALUE_ATOMIC (flag_profile_gen_atomic == 2 || \ >> + flag_profile_gen_atomic == 3) >> + >> /* gcov_type is typedef'd elsewhere for the compiler */ >> #if IN_GCOV >> #define GCOV_LINKAGE static >> @@ -781,8 +801,8 @@ struct gcov_info >> unused) */ >> >> unsigned n_functions; /* number of functions */ >> - const struct gcov_fn_info *const *functions; /* pointer to pointers >> - to function information */ >> + const struct gcov_fn_info **functions; /* pointer to pointers >> + to function information */ >> }; >> >> /* Information about a single imported module. */ >> @@ -988,8 +1008,7 @@ static void gcov_rewrite (void); >> GCOV_LINKAGE void gcov_seek (gcov_position_t /*position*/) ATTRIBUTE_HIDDEN; >> GCOV_LINKAGE void gcov_truncate (void) ATTRIBUTE_HIDDEN; >> GCOV_LINKAGE gcov_unsigned_t gcov_string_length (const char *) >> ATTRIBUTE_HIDDEN; >> -GCOV_LINKAGE unsigned gcov_gcda_file_size (struct gcov_info *, >> - struct gcov_summary *); >> +GCOV_LINKAGE unsigned gcov_gcda_file_size (struct gcov_info *); >> #else >> /* Available outside libgcov */ >> GCOV_LINKAGE void gcov_sync (gcov_position_t /*base*/, >> >> -- >> This patch is available for review at http://codereview.appspot.com/6968046 > > > > -- > Teresa Johnson | Software Engineer | tejohn...@google.com | 408-460-2413