diff options
author | Luis Machado <luisgpm@br.ibm.com> | 2011-11-15 13:17:05 +0000 |
---|---|---|
committer | Luis Machado <luisgpm@br.ibm.com> | 2011-11-15 13:17:05 +0000 |
commit | 865ecab4b2b7d6efeaec3072ee843d2d830d2dae (patch) | |
tree | 2a17c5ab92a7196613bac62de02b19c000c30465 /gdb/auxv.c | |
parent | 080f9e4f20da18de6c34ef23a9a015ba81c5d6e7 (diff) | |
download | gdb-865ecab4b2b7d6efeaec3072ee843d2d830d2dae.zip gdb-865ecab4b2b7d6efeaec3072ee843d2d830d2dae.tar.gz gdb-865ecab4b2b7d6efeaec3072ee843d2d830d2dae.tar.bz2 |
2011-11-15 Pedro Alves <pedro@codesourcery.com>
Luis Machado <lgustavo@codesourcery.com>
* 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.
Diffstat (limited to 'gdb/auxv.c')
-rw-r--r-- | gdb/auxv.c | 117 |
1 files changed, 101 insertions, 16 deletions
@@ -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); } |