From patchwork Tue Jun 16 12:51:00 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: =?utf-8?q?Martin_Li=C5=A1ka?= X-Patchwork-Id: 1310283 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=gcc.gnu.org (client-ip=2620:52:3:1:0:246e:9693:128c; helo=sourceware.org; envelope-from=gcc-patches-bounces@gcc.gnu.org; receiver=) Authentication-Results: ozlabs.org; dmarc=none (p=none dis=none) header.from=suse.cz Received: from sourceware.org (server2.sourceware.org [IPv6:2620:52:3:1:0:246e:9693:128c]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest SHA256) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 49mSk25B3fz9sT6 for ; Tue, 16 Jun 2020 22:51:06 +1000 (AEST) Received: from server2.sourceware.org (localhost [IPv6:::1]) by sourceware.org (Postfix) with ESMTP id EA17C388C036; Tue, 16 Jun 2020 12:51:03 +0000 (GMT) X-Original-To: gcc-patches@gcc.gnu.org Delivered-To: gcc-patches@gcc.gnu.org Received: from mx2.suse.de (mx2.suse.de [195.135.220.15]) by sourceware.org (Postfix) with ESMTPS id 7FB0D388C030 for ; Tue, 16 Jun 2020 12:51:01 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.3.2 sourceware.org 7FB0D388C030 Authentication-Results: sourceware.org; dmarc=none (p=none dis=none) header.from=suse.cz Authentication-Results: sourceware.org; spf=pass smtp.mailfrom=mliska@suse.cz X-Virus-Scanned: by amavisd-new at test-mx.suse.de Received: from relay2.suse.de (unknown [195.135.220.254]) by mx2.suse.de (Postfix) with ESMTP id 9E94BAD83 for ; Tue, 16 Jun 2020 12:51:04 +0000 (UTC) From: =?utf-8?q?Martin_Li=C5=A1ka?= Subject: [PATCH] gcov: fix gcov-tool merge for TOPN counters To: gcc-patches@gcc.gnu.org Message-ID: <4b5b8222-c5d5-85cf-209e-4fb6b98cf10b@suse.cz> Date: Tue, 16 Jun 2020 14:51:00 +0200 User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:68.0) Gecko/20100101 Thunderbird/68.9.0 MIME-Version: 1.0 Content-Language: en-US X-Spam-Status: No, score=-14.3 required=5.0 tests=BAYES_00, GIT_PATCH_0, KAM_DMARC_STATUS, RCVD_IN_MSPIKE_H3, RCVD_IN_MSPIKE_WL, SPF_HELO_NONE, SPF_PASS, TXREP autolearn=ham autolearn_force=no version=3.4.2 X-Spam-Checker-Version: SpamAssassin 3.4.2 (2018-09-13) on server2.sourceware.org X-BeenThere: gcc-patches@gcc.gnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: Gcc-patches mailing list List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: gcc-patches-bounces@gcc.gnu.org Sender: "Gcc-patches" Hello. The patch is about corrupted gcov-tool merge command for a TOPN counter. What was missing is transition of a on-disk representation to a memory representation expected by __gcov_merge_topn function. Patch can bootstrap on x86_64-linux-gnu and survives regression tests. I'm going to install it if there are no objections. Martin libgcc/ChangeLog: * libgcov-util.c (read_gcda_finalize): Remove const operator. (merge_wrapper): Add both counts and use them properly. (topn_to_memory_representation): New function. (gcov_merge): Covert on disk representation to in memory representation. * libgcov.h: Remove const operator. --- libgcc/libgcov-util.c | 70 ++++++++++++++++++++++++++++++++++++------- libgcc/libgcov.h | 2 +- 2 files changed, 61 insertions(+), 11 deletions(-) diff --git a/libgcc/libgcov-util.c b/libgcc/libgcov-util.c index fff54c6a3f6..224c190ee63 100644 --- a/libgcc/libgcov-util.c +++ b/libgcc/libgcov-util.c @@ -243,7 +243,7 @@ read_gcda_finalize (struct gcov_info *obj_info) /* We set the following fields: merge, n_functions, functions and summary. */ obj_info->n_functions = num_fn_info; - obj_info->functions = (const struct gcov_fn_info**) obstack_finish (&fn_info); + obj_info->functions = (struct gcov_fn_info**) obstack_finish (&fn_info); /* wrap all the counter array. */ for (i=0; i< GCOV_COUNTERS; i++) @@ -506,14 +506,58 @@ gcov_get_merge_weight (void) value buffer and weights and then calls the merge function. */ static void -merge_wrapper (gcov_merge_fn f, gcov_type *v1, gcov_unsigned_t n, - gcov_type *v2, unsigned w) +merge_wrapper (gcov_merge_fn f, gcov_type *v1, gcov_unsigned_t n1, + gcov_type *v2, gcov_unsigned_t n2, unsigned w) { gcov_value_buf = v2; gcov_value_buf_pos = 0; - gcov_value_buf_size = n; + gcov_value_buf_size = n2; gcov_merge_weight = w; - (*f) (v1, n); + (*f) (v1, n1); +} + +/* Convert on disk representation of a TOPN counter to in memory representation + that is expected from __gcov_merge_topn function. */ + +static void +topn_to_memory_representation (struct gcov_ctr_info *info) +{ + auto_vec output; + gcov_type *values = info->values; + int count = info->num; + + while (count > 0) + { + output.safe_push (values[0]); + gcov_type n = values[1]; + output.safe_push (n); + if (n > 0) + { + struct gcov_kvp *tuples + = (struct gcov_kvp *)xcalloc (sizeof (struct gcov_kvp), n); + for (unsigned i = 0; i < n - 1; i++) + tuples[i].next = &tuples[i + 1]; + for (unsigned i = 0; i < n; i++) + { + tuples[i].value = values[2 + 2 * i]; + tuples[i].count = values[2 + 2 * i + 1]; + } + output.safe_push ((intptr_t)&tuples[0]); + } + else + output.safe_push (0); + + unsigned len = 2 * n + 2; + values += len; + count -= len; + } + gcc_assert (count == 0); + + /* Allocate new buffer and copy it there. */ + info->num = output.length (); + info->values = (gcov_type *)xmalloc (sizeof (gcov_type) * info->num); + for (unsigned i = 0; i < info->num; i++) + info->values[i] = output[i]; } /* Offline tool to manipulate profile data. @@ -543,9 +587,9 @@ gcov_merge (struct gcov_info *info1, struct gcov_info *info2, int w) for (f_ix = 0; f_ix < n_functions; f_ix++) { unsigned t_ix; - const struct gcov_fn_info *gfi_ptr1 = info1->functions[f_ix]; - const struct gcov_fn_info *gfi_ptr2 = info2->functions[f_ix]; - const struct gcov_ctr_info *ci_ptr1, *ci_ptr2; + struct gcov_fn_info *gfi_ptr1 = info1->functions[f_ix]; + struct gcov_fn_info *gfi_ptr2 = info2->functions[f_ix]; + struct gcov_ctr_info *ci_ptr1, *ci_ptr2; if (!gfi_ptr1 || gfi_ptr1->key != info1) continue; @@ -569,8 +613,14 @@ gcov_merge (struct gcov_info *info1, struct gcov_info *info2, int w) gcc_assert (merge1 == merge2); if (!merge1) continue; - gcc_assert (ci_ptr1->num == ci_ptr2->num); - merge_wrapper (merge1, ci_ptr1->values, ci_ptr1->num, ci_ptr2->values, w); + + if (merge1 == __gcov_merge_topn) + topn_to_memory_representation (ci_ptr1); + else + gcc_assert (ci_ptr1->num == ci_ptr2->num); + + merge_wrapper (merge1, ci_ptr1->values, ci_ptr1->num, + ci_ptr2->values, ci_ptr2->num, w); ci_ptr1++; ci_ptr2++; } diff --git a/libgcc/libgcov.h b/libgcc/libgcov.h index 5d237a4c730..ffa9a690af4 100644 --- a/libgcc/libgcov.h +++ b/libgcc/libgcov.h @@ -216,7 +216,7 @@ struct gcov_info const struct gcov_fn_info *const *functions; /* pointer to pointers to function information */ #else - const struct gcov_fn_info **functions; + struct gcov_fn_info **functions; #endif /* !IN_GCOV_TOOL */ };