From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from smtp.polymtl.ca (smtp.polymtl.ca [132.207.4.11]) by sourceware.org (Postfix) with ESMTPS id 41090395CC53 for ; Thu, 14 May 2020 14:10:04 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.3.2 sourceware.org 41090395CC53 Received: from pn-All-Series.dorsal.polymtl.ca (dyn38.dorsal.polymtl.ca [132.207.72.38]) by smtp.polymtl.ca (8.14.7/8.14.7) with ESMTP id 04EE9O7k022013; Thu, 14 May 2020 10:10:01 -0400 DKIM-Filter: OpenDKIM Filter v2.11.0 smtp.polymtl.ca 04EE9O7k022013 From: paul-naert To: gdb-patches@sourceware.org Cc: paul-naert Subject: [RFC][PATCH 5/7] Add the option to defer register storage for compiled object loading Date: Thu, 14 May 2020 10:08:47 -0400 Message-Id: <20200514140849.31845-6-paul_naert@hotmail.fr> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20200514140849.31845-1-paul_naert@hotmail.fr> References: <20200514140849.31845-1-paul_naert@hotmail.fr> X-Poly-FromMTA: (dyn38.dorsal.polymtl.ca [132.207.72.38]) at Thu, 14 May 2020 14:09:24 +0000 X-Spam-Status: No, score=-10.2 required=5.0 tests=BAYES_00, FREEMAIL_FROM, GIT_PATCH_0, KAM_DMARC_NONE, KAM_DMARC_STATUS, RCVD_IN_MSPIKE_H3, RCVD_IN_MSPIKE_WL, SPF_HELO_PASS, SPF_SOFTFAIL, 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: gdb-patches@sourceware.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: Gdb-patches mailing list List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Thu, 14 May 2020 14:10:05 -0000 Currently, required register values are saved to memory when the compile object is loaded. This modification allows storing the metadata of which registers should be saved instead. They can then be saved when the gdb_expr function is actually executed. --- gdb/compile/compile-c-support.c | 5 ++++ gdb/compile/compile-internal.h | 7 ++++++ gdb/compile/compile-object-load.c | 50 +++++++++++++++++++++++++++++---------- gdb/compile/compile-object-load.h | 7 ++++++ gdb/compile/compile-object-run.c | 6 +++++ gdb/defs.h | 3 +++ 6 files changed, 65 insertions(+), 13 deletions(-) diff --git a/gdb/compile/compile-c-support.c b/gdb/compile/compile-c-support.c index 9de827a..34ad568 100644 --- a/gdb/compile/compile-c-support.c +++ b/gdb/compile/compile-c-support.c @@ -320,6 +320,7 @@ struct c_add_code_header switch (type) { case COMPILE_I_SIMPLE_SCOPE: + case COMPILE_I_PATCH_SCOPE: fputs_unfiltered ("void " GCC_FE_WRAPPER_FUNCTION " (struct " @@ -367,6 +368,7 @@ struct c_add_code_footer switch (type) { case COMPILE_I_SIMPLE_SCOPE: + case COMPILE_I_PATCH_SCOPE: case COMPILE_I_PRINT_ADDRESS_SCOPE: case COMPILE_I_PRINT_VALUE_SCOPE: fputs_unfiltered ("}\n", buf); @@ -444,6 +446,7 @@ struct cplus_add_code_header switch (type) { case COMPILE_I_SIMPLE_SCOPE: + case COMPILE_I_PATCH_SCOPE: fputs_unfiltered ("void " GCC_FE_WRAPPER_FUNCTION " (struct " @@ -601,6 +604,7 @@ public: AddCodeHeaderPolicy::add_code_header (m_instance->scope (), &buf); if (m_instance->scope () == COMPILE_I_SIMPLE_SCOPE + || m_instance->scope () == COMPILE_I_PATCH_SCOPE || m_instance->scope () == COMPILE_I_PRINT_ADDRESS_SCOPE || m_instance->scope () == COMPILE_I_PRINT_VALUE_SCOPE) { @@ -630,6 +634,7 @@ public: buf.puts ("}\n"); if (m_instance->scope () == COMPILE_I_SIMPLE_SCOPE + || m_instance->scope () == COMPILE_I_PATCH_SCOPE || m_instance->scope () == COMPILE_I_PRINT_ADDRESS_SCOPE || m_instance->scope () == COMPILE_I_PRINT_VALUE_SCOPE) PopUserExpressionPolicy::pop_user_expression (&buf); diff --git a/gdb/compile/compile-internal.h b/gdb/compile/compile-internal.h index 648b2ea..14a41a8 100644 --- a/gdb/compile/compile-internal.h +++ b/gdb/compile/compile-internal.h @@ -151,6 +151,13 @@ protected: htab_up m_symbol_err_map; }; +/* Stores data needed to save registers for the patch command. */ +struct regs_store_data +{ + int regnum; + ULONGEST reg_offset; +}; + /* Define header and footers for different scopes. */ /* A simple scope just declares a function named "_gdb_expr", takes no diff --git a/gdb/compile/compile-object-load.c b/gdb/compile/compile-object-load.c index 964356c..743b2b7 100644 --- a/gdb/compile/compile-object-load.c +++ b/gdb/compile/compile-object-load.c @@ -528,7 +528,7 @@ get_regs_type (struct symbol *func_sym, struct objfile *objfile) starting at inferior address REGS_BASE. */ static void -store_regs (struct type *regs_type, CORE_ADDR regs_base) +store_regs (struct type *regs_type, CORE_ADDR regs_base, regs_store_data *deferred_store) { struct gdbarch *gdbarch = target_gdbarch (); int fieldno; @@ -546,6 +546,12 @@ store_regs (struct type *regs_type, CORE_ADDR regs_base) struct value *regval; CORE_ADDR inferior_addr; + /* Initialize deferred registers storage data. */ + if (deferred_store != NULL) + { + deferred_store[fieldno] = {-1, 0}; + } + if (strcmp (reg_name, COMPILE_I_SIMPLE_REGISTER_DUMMY) == 0) continue; @@ -561,17 +567,27 @@ store_regs (struct type *regs_type, CORE_ADDR regs_base) regnum = compile_register_name_demangle (gdbarch, reg_name); - regval = value_from_register (reg_type, regnum, get_current_frame ()); - if (value_optimized_out (regval)) - error (_("Register \"%s\" is optimized out."), reg_name); - if (!value_entirely_available (regval)) - error (_("Register \"%s\" is not available."), reg_name); - - inferior_addr = regs_base + reg_offset; - if (0 != target_write_memory (inferior_addr, value_contents (regval), - reg_size)) - error (_("Cannot write register \"%s\" to inferior memory at %s."), - reg_name, paddress (gdbarch, inferior_addr)); + /* If deferred store is null, registers are loaded instantly. + Otherwise we store the offset. */ + if (deferred_store == NULL) + { + regval = value_from_register (reg_type, regnum, get_current_frame ()); + if (value_optimized_out (regval)) + error (_ ("Register \"%s\" is optimized out."), reg_name); + if (!value_entirely_available (regval)) + error (_ ("Register \"%s\" is not available."), reg_name); + + inferior_addr = regs_base + reg_offset; + if (0 + != target_write_memory (inferior_addr, value_contents (regval), + reg_size)) + error (_ ("Cannot write register \"%s\" to inferior memory at %s."), + reg_name, paddress (gdbarch, inferior_addr)); + } + else + { + deferred_store[fieldno] = {regnum, reg_offset}; + } } } @@ -599,6 +615,7 @@ compile_object_load (const compile_file_names &file_names, struct objfile *objfile; int expect_parameters; struct type *expect_return_type; + struct regs_store_data *deferred_regs_store = NULL; gdb::unique_xmalloc_ptr filename (tilde_expand (file_names.object_file ())); @@ -654,6 +671,7 @@ compile_object_load (const compile_file_names &file_names, switch (scope) { case COMPILE_I_SIMPLE_SCOPE: + case COMPILE_I_PATCH_SCOPE: expect_parameters = 1; expect_return_type = builtin_type (target_gdbarch ())->builtin_void; break; @@ -765,7 +783,11 @@ compile_object_load (const compile_file_names &file_names, paddress (target_gdbarch (), TYPE_LENGTH (regs_type)), paddress (target_gdbarch (), regs_addr)); - store_regs (regs_type, regs_addr); + if (scope == COMPILE_I_PATCH_SCOPE) + { + deferred_regs_store = new regs_store_data[TYPE_NFIELDS(regs_type)]; + } + store_regs (regs_type, regs_addr, deferred_regs_store); } if (scope == COMPILE_I_PRINT_ADDRESS_SCOPE @@ -795,6 +817,8 @@ compile_object_load (const compile_file_names &file_names, retval->source_file = xstrdup (file_names.source_file ()); retval->func_sym = func_sym; retval->regs_addr = regs_addr; + retval->deferred_regs_store = deferred_regs_store; + retval->regs_store_num = TYPE_NFIELDS (regs_type); retval->scope = scope; retval->scope_data = scope_data; retval->out_value_type = out_value_type; diff --git a/gdb/compile/compile-object-load.h b/gdb/compile/compile-object-load.h index 730164f..7016370 100644 --- a/gdb/compile/compile-object-load.h +++ b/gdb/compile/compile-object-load.h @@ -59,6 +59,13 @@ struct compile_module require any. */ CORE_ADDR regs_addr; + /* Offsets needed to store the registers for the patch + command. NULL for the compile command. */ + struct regs_store_data *deferred_regs_store; + + /* The number of registers to be stored. */ + int regs_store_num; + /* The "scope" of this compilation. */ enum compile_i_scope_types scope; diff --git a/gdb/compile/compile-object-run.c b/gdb/compile/compile-object-run.c index 32e46f9..07aeceb 100644 --- a/gdb/compile/compile-object-run.c +++ b/gdb/compile/compile-object-run.c @@ -52,6 +52,9 @@ struct do_module_cleanup /* objfile_name of our objfile. */ char objfile_name_string[1]; + + /* Deferred store registers. */ + regs_store_data *deferred_regs_store; }; /* Cleanup everything after the inferior function dummy frame gets @@ -100,6 +103,9 @@ do_module_cleanup (void *arg, int registers_valid) delete data->munmap_list_head; + /* Delete the deferred registers storage data. */ + delete[] data->deferred_regs_store; + /* Delete the .o file. */ unlink (data->objfile_name_string); xfree (data); diff --git a/gdb/defs.h b/gdb/defs.h index f12ba36..4ce885a 100644 --- a/gdb/defs.h +++ b/gdb/defs.h @@ -80,6 +80,9 @@ enum compile_i_scope_types name already specifies its address. See get_out_value_type. */ COMPILE_I_PRINT_ADDRESS_SCOPE, COMPILE_I_PRINT_VALUE_SCOPE, + + /* A simple scope with deferred register storing. */ + COMPILE_I_PATCH_SCOPE, }; -- 2.7.4