From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: by sourceware.org (Postfix, from userid 1585) id 08CB7384F661; Tue, 31 Jan 2023 14:32:33 +0000 (GMT) DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org 08CB7384F661 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=sourceware.org; s=default; t=1675175553; bh=oVbrNdmyGIwB77tv8TaQljKpNhq5mZhO1k5lsFPURnw=; h=From:To:Subject:Date:From; b=GwZXcQFBgwmHYZ8D41Trh9zqnqAXRtzcI0uQf9LdDcv73hH0p3hlinvcmezOACA2g l2Xumi+b8oocjQkBte++q/0bxmEyWvv0EmC/RrEmEtOMYxo/L7eo0Jf7WF8hjiUaG/ Yhw589g+oNzJ1QQUKKOjqcQqB1cTZ7AAlHPjotxk= Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable From: Luis Machado To: gdb-cvs@sourceware.org Subject: [binutils-gdb/gdb-13-branch] gdb: dwarf2 generic implementation for caching function data X-Act-Checkin: binutils-gdb X-Git-Author: =?utf-8?q?Torbj=C3=B6rn_SVENSSON?= X-Git-Refname: refs/heads/gdb-13-branch X-Git-Oldrev: ccb99ed2cb8cb252519a3d85fe9d19e4023864a6 X-Git-Newrev: 2d36c9404e360126551fef20f3f79f5a56f6ad8b Message-Id: <20230131143233.08CB7384F661@sourceware.org> Date: Tue, 31 Jan 2023 14:32:33 +0000 (GMT) List-Id: https://sourceware.org/git/gitweb.cgi?p=3Dbinutils-gdb.git;h=3D2d36c9404e36= 0126551fef20f3f79f5a56f6ad8b commit 2d36c9404e360126551fef20f3f79f5a56f6ad8b Author: Torbj=C3=B6rn SVENSSON Date: Thu Nov 17 12:17:53 2022 +0100 gdb: dwarf2 generic implementation for caching function data =20 When there is no dwarf2 data for a register, a function can be called to provide the value of this register. In some situations, it might not be trivial to determine the value to return and it would cause a performance bottleneck to do the computation each time. =20 This patch allows the called function to have a "cache" object that it can use to store some metadata between calls to reduce the performance impact of the complex logic. =20 The cache object is unique for each function and frame, so if there are more than one function pointer stored in the dwarf2_frame_cache->reg array, then the appropriate pointer will be supplied (the type is not known by the dwarf2 implementation). =20 dwarf2_frame_get_fn_data can be used to retrieve the function unique cache object. dwarf2_frame_allocate_fn_data can be used to allocate and retrieve the function unique cache object. =20 Signed-off-by: Torbj=C3=B6rn SVENSSON Signed-off-by: Yvan Roux Diff: --- gdb/dwarf2/frame.c | 60 ++++++++++++++++++++++++++++++++++++++++++++++++++= ++++ gdb/dwarf2/frame.h | 37 +++++++++++++++++++++++++++++++-- 2 files changed, 95 insertions(+), 2 deletions(-) diff --git a/gdb/dwarf2/frame.c b/gdb/dwarf2/frame.c index bd36a6c7fb4..7f2bcf29387 100644 --- a/gdb/dwarf2/frame.c +++ b/gdb/dwarf2/frame.c @@ -831,6 +831,22 @@ dwarf2_fetch_cfa_info (struct gdbarch *gdbarch, CORE_A= DDR pc, } =20 =0C +/* Custom function data object for architecture specific prev_register + implementation. Main purpose of this object is to allow caching of + expensive data lookups in the prev_register handling. */ + +struct dwarf2_frame_fn_data +{ + /* The cookie to identify the custom function data by. */ + fn_prev_register cookie; + + /* The custom function data. */ + void *data; + + /* Pointer to the next custom function data object for this frame. */ + struct dwarf2_frame_fn_data *next; +}; + struct dwarf2_frame_cache { /* DWARF Call Frame Address. */ @@ -862,6 +878,8 @@ struct dwarf2_frame_cache dwarf2_tailcall_frame_unwind unwinder so this field does not apply for them. */ void *tailcall_cache; + + struct dwarf2_frame_fn_data *fn_data; }; =20 static struct dwarf2_frame_cache * @@ -1221,6 +1239,48 @@ dwarf2_frame_prev_register (frame_info_ptr this_fram= e, void **this_cache, } } =20 +/* See frame.h. */ + +void * +dwarf2_frame_get_fn_data (frame_info_ptr this_frame, void **this_cache, + fn_prev_register cookie) +{ + struct dwarf2_frame_fn_data *fn_data =3D nullptr; + struct dwarf2_frame_cache *cache + =3D dwarf2_frame_cache (this_frame, this_cache); + + /* Find the object for the function. */ + for (fn_data =3D cache->fn_data; fn_data; fn_data =3D fn_data->next) + if (fn_data->cookie =3D=3D cookie) + return fn_data->data; + + return nullptr; +} + +/* See frame.h. */ + +void * +dwarf2_frame_allocate_fn_data (frame_info_ptr this_frame, void **this_cach= e, + fn_prev_register cookie, unsigned long size) +{ + struct dwarf2_frame_fn_data *fn_data =3D nullptr; + struct dwarf2_frame_cache *cache + =3D dwarf2_frame_cache (this_frame, this_cache); + + /* First try to find an existing object. */ + void *data =3D dwarf2_frame_get_fn_data (this_frame, this_cache, cookie); + gdb_assert (data =3D=3D nullptr); + + /* No object found, lets create a new instance. */ + fn_data =3D FRAME_OBSTACK_ZALLOC (struct dwarf2_frame_fn_data); + fn_data->cookie =3D cookie; + fn_data->data =3D frame_obstack_zalloc (size); + fn_data->next =3D cache->fn_data; + cache->fn_data =3D fn_data; + + return fn_data->data; +} + /* Proxy for tailcall_frame_dealloc_cache for bottom frame of a virtual ta= il call frames chain. */ =20 diff --git a/gdb/dwarf2/frame.h b/gdb/dwarf2/frame.h index 4444c153741..5643e557513 100644 --- a/gdb/dwarf2/frame.h +++ b/gdb/dwarf2/frame.h @@ -66,6 +66,9 @@ enum dwarf2_frame_reg_rule =20 /* Register state. */ =20 +typedef struct value *(*fn_prev_register) (frame_info_ptr this_frame, + void **this_cache, int regnum); + struct dwarf2_frame_state_reg { /* Each register save state can be described in terms of a CFA slot, @@ -78,8 +81,7 @@ struct dwarf2_frame_state_reg const gdb_byte *start; ULONGEST len; } exp; - struct value *(*fn) (frame_info_ptr this_frame, void **this_cache, - int regnum); + fn_prev_register fn; } loc; enum dwarf2_frame_reg_rule how; }; @@ -262,4 +264,35 @@ extern int dwarf2_fetch_cfa_info (struct gdbarch *gdba= rch, CORE_ADDR pc, const gdb_byte **cfa_start_out, const gdb_byte **cfa_end_out); =20 + +/* Allocate a new instance of the function unique data. + + The main purpose of this custom function data object is to allow cachin= g the + value of expensive lookups in the prev_register implementation. + + THIS_FRAME is the frame that the custom data object should be associated + with. + THIS_CACHE is the dwarf2 cache object to store the pointer on. + COOKIE is the key for the prev_function implementation. + SIZE is the size of the custom data object to allocate. */ + +extern void *dwarf2_frame_allocate_fn_data (frame_info_ptr this_frame, + void **this_cache, + fn_prev_register cookie, + unsigned long size); + +/* Retrieve the function unique data for this frame or NULL if none exists. + + The main purpose of this custom function data object is to allow cachin= g the + value of expensive lookups in the prev_register implementation. + + THIS_FRAME is the frame that the custom data object should be associated + with. + THIS_CACHE is the dwarf2 cache object to store the pointer on. + COOKIE is the key for the prev_function implementation. */ + +extern void *dwarf2_frame_get_fn_data (frame_info_ptr this_frame, + void **this_cache, + fn_prev_register cookie); + #endif /* dwarf2-frame.h */