From 865ecab4b2b7d6efeaec3072ee843d2d830d2dae Mon Sep 17 00:00:00 2001 From: Luis Machado Date: Tue, 15 Nov 2011 13:17:05 +0000 Subject: 2011-11-15 Pedro Alves Luis Machado * auxv.c: Include observer.h. (auxv_inferior_data_cleanup): New. (invalidate_auxv_cache_inf): New. (invalidate_auxv_cache): New. (get_auxv_inferior_data): New. (auxv_inferior_data): New static global. (auxv_info): New structure. (target_auxv_search): Use get_auxv_inferior_data instead of target_read_alloc and don't free cached buffers. (fprint_target_auxv): Likewise (_initialize_auxv): Register per-inferior auxv cache and register observers to invalidate auxv cache when needed. --- gdb/ChangeLog | 16 ++++++++ gdb/auxv.c | 117 ++++++++++++++++++++++++++++++++++++++++++++++++++-------- 2 files changed, 117 insertions(+), 16 deletions(-) diff --git a/gdb/ChangeLog b/gdb/ChangeLog index eefae59..2e866ba 100644 --- a/gdb/ChangeLog +++ b/gdb/ChangeLog @@ -1,3 +1,19 @@ +2011-11-15 Pedro Alves + Luis Machado + + * auxv.c: Include observer.h. + (auxv_inferior_data_cleanup): New. + (invalidate_auxv_cache_inf): New. + (invalidate_auxv_cache): New. + (get_auxv_inferior_data): New. + (auxv_inferior_data): New static global. + (auxv_info): New structure. + (target_auxv_search): Use get_auxv_inferior_data instead of + target_read_alloc and don't free cached buffers. + (fprint_target_auxv): Likewise + (_initialize_auxv): Register per-inferior auxv cache and register + observers to invalidate auxv cache when needed. + 2011-11-14 Doug Evans Make "!" an alias for "shell". diff --git a/gdb/auxv.c b/gdb/auxv.c index 28196b4..934441b 100644 --- a/gdb/auxv.c +++ b/gdb/auxv.c @@ -26,6 +26,7 @@ #include "valprint.h" #include "gdb_assert.h" #include "gdbcore.h" +#include "observer.h" #include "auxv.h" #include "elf/common.h" @@ -277,6 +278,78 @@ target_auxv_parse (struct target_ops *ops, gdb_byte **readptr, return default_auxv_parse (ops, readptr, endptr, typep, valp); } + +/* Per-inferior data key for auxv. */ +static const struct inferior_data *auxv_inferior_data; + +/* Auxiliary Vector information structure. This is used by GDB + for caching purposes for each inferior. This helps reduce the + overhead of transfering data from a remote target to the local host. */ +struct auxv_info +{ + LONGEST length; + gdb_byte *data; +}; + +/* Handles the cleanup of the auxv cache for inferior INF. ARG is ignored. + Frees whatever allocated space there is to be freed and sets INF's auxv cache + data pointer to NULL. + + This function is called when the following events occur: inferior_appeared, + inferior_exit and executable_changed. */ + +static void +auxv_inferior_data_cleanup (struct inferior *inf, void *arg) +{ + struct auxv_info *info; + + info = inferior_data (inf, auxv_inferior_data); + if (info != NULL) + { + xfree (info->data); + xfree (info); + set_inferior_data (inf, auxv_inferior_data, NULL); + } +} + +/* Invalidate INF's auxv cache. */ + +static void +invalidate_auxv_cache_inf (struct inferior *inf) +{ + auxv_inferior_data_cleanup (inf, NULL); +} + +/* Invalidate current inferior's auxv cache. */ + +static void +invalidate_auxv_cache (void) +{ + invalidate_auxv_cache_inf (current_inferior ()); +} + +/* Fetch the auxv object from inferior INF. If auxv is cached already, + return a pointer to the cache. If not, fetch the auxv object from the + target and cache it. This function always returns a valid INFO pointer. */ + +static struct auxv_info * +get_auxv_inferior_data (struct target_ops *ops) +{ + struct auxv_info *info; + struct inferior *inf = current_inferior (); + + info = inferior_data (inf, auxv_inferior_data); + if (info == NULL) + { + info = XZALLOC (struct auxv_info); + info->length = target_read_alloc (ops, TARGET_OBJECT_AUXV, + NULL, &info->data); + set_inferior_data (inf, auxv_inferior_data, info); + } + + return info; +} + /* Extract the auxiliary vector entry with a_type matching MATCH. Return zero if no such entry was found, or -1 if there was an error getting the information. On success, return 1 after @@ -286,28 +359,30 @@ target_auxv_search (struct target_ops *ops, CORE_ADDR match, CORE_ADDR *valp) { CORE_ADDR type, val; gdb_byte *data; - LONGEST n = target_read_alloc (ops, TARGET_OBJECT_AUXV, NULL, &data); - gdb_byte *ptr = data; + gdb_byte *ptr; + struct auxv_info *info; + + info = get_auxv_inferior_data (ops); + + data = info->data; + ptr = data; - if (n <= 0) - return n; + if (info->length <= 0) + return info->length; while (1) - switch (target_auxv_parse (ops, &ptr, data + n, &type, &val)) + switch (target_auxv_parse (ops, &ptr, data + info->length, &type, &val)) { case 1: /* Here's an entry, check it. */ if (type == match) { - xfree (data); *valp = val; return 1; } break; case 0: /* End of the vector. */ - xfree (data); return 0; default: /* Bogosity. */ - xfree (data); return -1; } @@ -321,15 +396,18 @@ fprint_target_auxv (struct ui_file *file, struct target_ops *ops) { CORE_ADDR type, val; gdb_byte *data; - LONGEST len = target_read_alloc (ops, TARGET_OBJECT_AUXV, NULL, - &data); - gdb_byte *ptr = data; + gdb_byte *ptr; + struct auxv_info *info; int ents = 0; - if (len <= 0) - return len; + info = get_auxv_inferior_data (ops); - while (target_auxv_parse (ops, &ptr, data + len, &type, &val) > 0) + data = info->data; + ptr = data; + if (info->length <= 0) + return info->length; + + while (target_auxv_parse (ops, &ptr, data + info->length, &type, &val) > 0) { const char *name = "???"; const char *description = ""; @@ -418,8 +496,6 @@ fprint_target_auxv (struct ui_file *file, struct target_ops *ops) break; } - xfree (data); - return ents; } @@ -448,4 +524,13 @@ _initialize_auxv (void) add_info ("auxv", info_auxv_command, _("Display the inferior's auxiliary vector.\n\ This is information provided by the operating system at program startup.")); + + /* Set an auxv cache per-inferior. */ + auxv_inferior_data + = register_inferior_data_with_cleanup (auxv_inferior_data_cleanup); + + /* Observers used to invalidate the auxv cache when needed. */ + observer_attach_inferior_exit (invalidate_auxv_cache_inf); + observer_attach_inferior_appeared (invalidate_auxv_cache_inf); + observer_attach_executable_changed (invalidate_auxv_cache); } -- cgit v1.1