diff options
author | Jan Kratochvil <jan.kratochvil@redhat.com> | 2015-06-03 21:22:56 +0200 |
---|---|---|
committer | Jan Kratochvil <jan.kratochvil@redhat.com> | 2015-06-03 21:26:04 +0200 |
commit | 7f36105668d57c26b52037202f5d97dbad91336b (patch) | |
tree | 2407b3a87ac36d7cdf19708fbec9669b55810203 /gdb/compile | |
parent | f277626b45b9d4af76e5d61a7efe09ce417ac200 (diff) | |
download | gdb-7f36105668d57c26b52037202f5d97dbad91336b.zip gdb-7f36105668d57c26b52037202f5d97dbad91336b.tar.gz gdb-7f36105668d57c26b52037202f5d97dbad91336b.tar.bz2 |
compile: Use also inferior munmap
Currently inferior memory is allocated by inferior mmap() but it is never
deallocated; despite the injected objfile incl. its symbols is freed. This was
intentional so that one can do for example:
inferior:
char *str = "foo";
GDB:
(gdb) compile code str = "bar";
I believe later patches will be needed to introduce full control over keeping
vs. discarding the injected module as being discussed in:
compile: objfiles lifetime UI
https://sourceware.org/ml/gdb/2015-04/msg00051.html
Message-ID: <20150429135735.GA16974@host1.jankratochvil.net>
https://sourceware.org/ml/gdb/2015-05/msg00007.html
As decided by Phil it is better not to leak inferior pages as users can
workaround the issue above for example by:
(gdb) compile code str = strdup ("bar");
I have checked that in fact gdb/doc/ (written by Phil) already expects the
injected code will be unmapped so that does not need to be changed:
compile code int ff = 5; p = &ff;
In this example, @code{p} would point to @code{ff} when the
@code{compile} command is executing the source code provided to it.
However, as variables in the (example) program persist with their
assigned values, the variable @code{p} would point to an invalid
location when the command exists.
gdb/ChangeLog
2015-04-28 Jan Kratochvil <jan.kratochvil@redhat.com>
* arch-utils.c (default_infcall_munmap): New.
* arch-utils.h (default_infcall_munmap): New declaration.
* compile/compile-object-load.c (struct munmap_list, munmap_list_add)
(munmap_list_free, munmap_listp_free_cleanup): New.
(struct setup_sections_data): Add field munmap_list_headp.
(setup_sections): Call munmap_list_add.
(compile_object_load): New variable munmap_list_head, initialize
setup_sections_data.munmap_list_headp, return munmap_list_head.
* compile/compile-object-load.h (struct munmap_list): New declaration.
(struct compile_module): Add field munmap_list_head.
(munmap_list_free): New declaration.
* compile/compile-object-run.c (struct do_module_cleanup): Add field
munmap_list_head.
(do_module_cleanup): Call munmap_list_free.
(compile_object_run): Pass munmap_list_head to do_module_cleanup.
* gdbarch.c: Regenerate.
* gdbarch.h: Regenerate.
* gdbarch.sh (infcall_munmap): New.
* linux-tdep.c (linux_infcall_munmap): New.
(linux_init_abi): Install it.
gdb/testsuite/ChangeLog
2015-04-28 Jan Kratochvil <jan.kratochvil@redhat.com>
* gdb.compile/compile.exp (keep jit in memory): Rename to ...
(do not keep jit in memory): ... this.
(expect 5): Change it to ...
(expect no 5): ... this.
Diffstat (limited to 'gdb/compile')
-rw-r--r-- | gdb/compile/compile-object-load.c | 71 | ||||
-rw-r--r-- | gdb/compile/compile-object-load.h | 6 | ||||
-rw-r--r-- | gdb/compile/compile-object-run.c | 6 |
3 files changed, 82 insertions, 1 deletions
diff --git a/gdb/compile/compile-object-load.c b/gdb/compile/compile-object-load.c index 15deaaf..2b29b8b 100644 --- a/gdb/compile/compile-object-load.c +++ b/gdb/compile/compile-object-load.c @@ -32,6 +32,58 @@ #include "block.h" #include "arch-utils.h" +/* Track inferior memory reserved by inferior mmap. */ + +struct munmap_list +{ + struct munmap_list *next; + CORE_ADDR addr, size; +}; + +/* Add inferior mmap memory range ADDR..ADDR+SIZE (exclusive) to list + HEADP. *HEADP needs to be initialized to NULL. */ + +static void +munmap_list_add (struct munmap_list **headp, CORE_ADDR addr, CORE_ADDR size) +{ + struct munmap_list *head_new = xmalloc (sizeof (*head_new)); + + head_new->next = *headp; + *headp = head_new; + head_new->addr = addr; + head_new->size = size; +} + +/* Free list of inferior mmap memory ranges HEAD. HEAD is the first + element of the list, it can be NULL. After calling this function + HEAD pointer is invalid and the possible list needs to be + reinitialized by caller to NULL. */ + +void +munmap_list_free (struct munmap_list *head) +{ + while (head) + { + struct munmap_list *todo = head; + + head = todo->next; + gdbarch_infcall_munmap (target_gdbarch (), todo->addr, todo->size); + xfree (todo); + } +} + +/* Stub for munmap_list_free suitable for make_cleanup. Contrary to + munmap_list_free this function's parameter is a pointer to the first + list element pointer. */ + +static void +munmap_listp_free_cleanup (void *headp_voidp) +{ + struct munmap_list **headp = headp_voidp; + + munmap_list_free (*headp); +} + /* Helper data for setup_sections. */ struct setup_sections_data @@ -48,6 +100,10 @@ struct setup_sections_data /* Maximum of alignments of all sections matching LAST_PROT. This value is always at least 1. This value is always a power of 2. */ CORE_ADDR last_max_alignment; + + /* List of inferior mmap ranges where setup_sections should add its + next range. */ + struct munmap_list **munmap_list_headp; }; /* Place all ABFD sections next to each other obeying all constraints. */ @@ -97,6 +153,7 @@ setup_sections (bfd *abfd, asection *sect, void *data_voidp) { addr = gdbarch_infcall_mmap (target_gdbarch (), data->last_size, data->last_prot); + munmap_list_add (data->munmap_list_headp, addr, data->last_size); if (compile_debug) fprintf_unfiltered (gdb_stdlog, "allocated %s bytes at %s prot %u\n", @@ -580,6 +637,7 @@ compile_object_load (const char *object_file, const char *source_file, struct objfile *objfile; int expect_parameters; struct type *expect_return_type; + struct munmap_list *munmap_list_head = NULL; filename = tilde_expand (object_file); cleanups = make_cleanup (xfree, filename); @@ -601,6 +659,8 @@ compile_object_load (const char *object_file, const char *source_file, setup_sections_data.last_section_first = abfd->sections; setup_sections_data.last_prot = -1; setup_sections_data.last_max_alignment = 1; + setup_sections_data.munmap_list_headp = &munmap_list_head; + make_cleanup (munmap_listp_free_cleanup, &munmap_list_head); bfd_map_over_sections (abfd, setup_sections, &setup_sections_data); setup_sections (abfd, NULL, &setup_sections_data); @@ -715,6 +775,7 @@ compile_object_load (const char *object_file, const char *source_file, TYPE_LENGTH (regs_type), GDB_MMAP_PROT_READ); gdb_assert (regs_addr != 0); + munmap_list_add (&munmap_list_head, regs_addr, TYPE_LENGTH (regs_type)); if (compile_debug) fprintf_unfiltered (gdb_stdlog, "allocated %s bytes at %s for registers\n", @@ -739,6 +800,8 @@ compile_object_load (const char *object_file, const char *source_file, (GDB_MMAP_PROT_READ | GDB_MMAP_PROT_WRITE)); gdb_assert (out_value_addr != 0); + munmap_list_add (&munmap_list_head, out_value_addr, + TYPE_LENGTH (out_value_type)); if (compile_debug) fprintf_unfiltered (gdb_stdlog, "allocated %s bytes at %s for printed value\n", @@ -748,7 +811,6 @@ compile_object_load (const char *object_file, const char *source_file, } discard_cleanups (cleanups_free_objfile); - do_cleanups (cleanups); retval = xmalloc (sizeof (*retval)); retval->objfile = objfile; @@ -759,5 +821,12 @@ compile_object_load (const char *object_file, const char *source_file, retval->scope_data = scope_data; retval->out_value_type = out_value_type; retval->out_value_addr = out_value_addr; + + /* CLEANUPS will free MUNMAP_LIST_HEAD. */ + retval->munmap_list_head = munmap_list_head; + munmap_list_head = NULL; + + do_cleanups (cleanups); + return retval; } diff --git a/gdb/compile/compile-object-load.h b/gdb/compile/compile-object-load.h index 5afacda..44a7592 100644 --- a/gdb/compile/compile-object-load.h +++ b/gdb/compile/compile-object-load.h @@ -17,6 +17,8 @@ #ifndef GDB_COMPILE_OBJECT_LOAD_H #define GDB_COMPILE_OBJECT_LOAD_H +struct munmap_list; + struct compile_module { /* objfile for the compiled module. */ @@ -45,10 +47,14 @@ struct compile_module /* If the inferior function has an out value, this is its address. Otherwise it is zero. */ CORE_ADDR out_value_addr; + + /* Track inferior memory reserved by inferior mmap. */ + struct munmap_list *munmap_list_head; }; extern struct compile_module *compile_object_load (const char *object_file, const char *source_file, enum compile_i_scope_types scope, void *scope_data); +extern void munmap_list_free (struct munmap_list *head); #endif /* GDB_COMPILE_OBJECT_LOAD_H */ diff --git a/gdb/compile/compile-object-run.c b/gdb/compile/compile-object-run.c index 771a209..ce47831 100644 --- a/gdb/compile/compile-object-run.c +++ b/gdb/compile/compile-object-run.c @@ -47,6 +47,9 @@ struct do_module_cleanup struct type *out_value_type; CORE_ADDR out_value_addr; + /* Copy from struct compile_module. */ + struct munmap_list *munmap_list_head; + /* objfile_name of our objfile. */ char objfile_name_string[1]; }; @@ -96,6 +99,8 @@ do_module_cleanup (void *arg, int registers_valid) unlink (data->source_file); xfree (data->source_file); + munmap_list_free (data->munmap_list_head); + /* Delete the .o file. */ unlink (data->objfile_name_string); xfree (data); @@ -128,6 +133,7 @@ compile_object_run (struct compile_module *module) data->scope_data = module->scope_data; data->out_value_type = module->out_value_type; data->out_value_addr = module->out_value_addr; + data->munmap_list_head = module->munmap_list_head; xfree (module->source_file); xfree (module); |