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.
This commit is contained in:
Luis Machado 2011-11-15 13:17:05 +00:00
parent 080f9e4f20
commit 865ecab4b2
2 changed files with 117 additions and 16 deletions

View File

@ -1,3 +1,19 @@
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.
2011-11-14 Doug Evans <dje@google.com>
Make "!" an alias for "shell".

View File

@ -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;
if (n <= 0)
return n;
info = get_auxv_inferior_data (ops);
data = info->data;
ptr = data;
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);
}