public inbox for gdb-patches@sourceware.org
 help / color / mirror / Atom feed
* [PATCH v17 4/5] Function is_elf_target.
  2013-10-18 13:40 [PATCH v17 0/5] remove-symbol-file & add-symbol-file Nicolas Blanc
@ 2013-10-18 13:40 ` Nicolas Blanc
  2013-10-18 13:40 ` [PATCH v17 5/5] Test adding and removing a symbol file at runtime Nicolas Blanc
                   ` (4 subsequent siblings)
  5 siblings, 0 replies; 8+ messages in thread
From: Nicolas Blanc @ 2013-10-18 13:40 UTC (permalink / raw)
  To: tromey; +Cc: gdb-patches, Nicolas Blanc

2013-27-09  Nicolas Blanc  <nicolas.blanc@intel.com>

gdb/testsuite
	* lib/gdb.exp (is_elf_target): New function.

Signed-off-by: Nicolas Blanc <nicolas.blanc@intel.com>
---
 gdb/testsuite/lib/gdb.exp |   39 +++++++++++++++++++++++++++++++++++++++
 1 files changed, 39 insertions(+), 0 deletions(-)

diff --git a/gdb/testsuite/lib/gdb.exp b/gdb/testsuite/lib/gdb.exp
index 44786ec..1b51d7a 100644
--- a/gdb/testsuite/lib/gdb.exp
+++ b/gdb/testsuite/lib/gdb.exp
@@ -1796,6 +1796,45 @@ proc supports_reverse {} {
     return 0
 }
 
+# Return 1 if target is ELF.
+gdb_caching_proc is_elf_target {
+    set me "is_elf_target"
+
+    set src [standard_temp_file is_elf_target[pid].c]
+    set obj [standard_temp_file is_elf_target[pid].o]
+
+    set fp_src [open $src "w"]
+    puts $fp_src "int foo () {return 0;}"
+    close $fp_src
+
+    verbose "$me:  compiling testfile $src" 2
+    set lines [gdb_compile $src $obj object {quiet}]
+
+    file delete $src
+
+    if ![string match "" $lines] then {
+	verbose "$me:  testfile compilation failed, returning 0" 2
+	return 0
+    }
+
+    set fp_obj [open $obj "r"]
+    fconfigure $fp_obj -translation binary
+    set data [read $fp_obj]
+    close $fp_obj
+
+    file delete $obj
+
+    set ELFMAG "\u007FELF"
+
+    if {[string compare -length 4 $data $ELFMAG] != 0} {
+	verbose "$me:  returning 0" 2
+	return 0
+    }
+
+    verbose "$me:  returning 1" 2
+    return 1
+}
+
 # Return 1 if target is ILP32.
 # This cannot be decided simply from looking at the target string,
 # as it might depend on externally passed compiler options like -m64.
-- 
1.7.6.5

^ permalink raw reply	[flat|nested] 8+ messages in thread

* [PATCH v17 0/5] remove-symbol-file & add-symbol-file.
@ 2013-10-18 13:40 Nicolas Blanc
  2013-10-18 13:40 ` [PATCH v17 4/5] Function is_elf_target Nicolas Blanc
                   ` (5 more replies)
  0 siblings, 6 replies; 8+ messages in thread
From: Nicolas Blanc @ 2013-10-18 13:40 UTC (permalink / raw)
  To: tromey; +Cc: gdb-patches, Nicolas Blanc

Hi Tom,

Thanks for the review. I updated the patches according to:

* http://sourceware.org/ml/gdb-patches/2013-10/msg00367.html (Feedback for Patch 1/5)
* http://sourceware.org/ml/gdb-patches/2013-10/msg00368.html (Feedback for Patch 3/5)
* http://sourceware.org/ml/gdb-patches/2013-10/msg00369.html (Feedback for Patch 5/5)

One of your suggestions in Patch 3/5 was to move part of add_target_section_of_objfile
from symfile.c to exec.c, which contains the similar function add_target_sections.
I tried to rewrite add_target_section_of_objfile using add_target_sections. The result
did not look good because one needs to allocate a temporary array of target
sections for the sole purpose of calling add_target_section. So I propose
to move the function to exec.c. In this way all the target-section functions are
in one file.

I rebased\retested the patches on x64 and x86 Linux. No regression was detected.

Thanks again for looking into this.

Regards,

Nicolas


Changes in v17

* is_addr_in_objfile (Patch 1/5): skip unmapped overlay sections.

* remove_symbol_file_command (Patch 1/5): Check objfile pointers.

* remove_symbol_file_command (Patch 1/5): Wrap too long line.

* Commit message (Patch 3/5): new title and description.

* Patch 3/5: Move add_target_section_of_objfile from symfile.c to exec.c.
  Update commit message accordingly.

* symfile_free_objfile (Patch 3/5): Check objfile pointer.

* sym-file.exp (Patch 5/5): Add curly braces to if-condition.

* sym-file.exp (Patch 5/5): Use the file base name instead of the fully qualified
  name in tests.

* sym-file.exp (Patch 5/5): Implement the test using standard_testfile and
  standard_output_file.

Changes in v16

* Patch 4/5: Changed ELF-target detection function. The function
  compiles a file and checks if the object file is ELF --
  see <http://sourceware.org/ml/gdb-patches/2013-09/msg00966.html>.

* Patch 5/5: Call the new ELF-target detection function.

Changes in v15

* symfile.c (remove_symbol_file_command): Reflect modification of struct objfile
  from upstream ("objf->name" => "objfile_name (objf)").

Changes in v14

* symfile.c (add_target_sections_of_objfile): Reflect modification
  of struct target_section from upstream.
  (symfile_free_objfile): Reflect modification of struct target_section
  from upstream.

Changes in v13

* Changed "is_elf_target" to "is_known_elf_target" (Patch 4/5)
  according to Doug's proposal
  (http://sourceware.org/ml/gdb-patches/2013-07/msg00426.html).

* Removed dependency to <elf.h> according to Mark's suggestion
  (http://sourceware.org/ml/gdb-patches/2013-07/msg00415.html).

Changes in v12

* symfile.c (add_target_sections_of_objfile): Reflect modification
  of struct target_section from upstream.

* gdb.base/sym-file-main.c: Move loader into a separate file as suggested
  and implemented the other recommendations from Doug.

* gdb.base/sym-file-loader.c: New file.

* gdb.base/sym-file-loader.h: New file.

* lib/gdb.exp (is_elf_target): New function.

Changes in v11

* Changed documentation for add-symbol-file according to feedback (Patch 3):
  "keeps adding to" -> "is kept in addition to".

* Fixed indentation issues in test (sym-file-main.c from Patch 2).

Changes in v10

* Dropped "USAGE" in "USAGE: remove-symbol-file FILENAME" according to suggestion.

* Fixed comment according to suggestion:
  "any reference to any objfile" -> "all references to any objfile"

* Added argument names to the prototype of is_addr_in_objfile according to suggestion.

* Fixed indentation of "macro" loops according to feedback.

* Fixed indentation issues.

Changes in v9

* Patch 4: New patch (fix  add-symbol-file for 'info files').
* Patch 5: New patch (test add-symbol-file and 'info files');

* sym-file.exp: Fixed test name string.

Changes in v8

* sym-file.exp: Call gdb_get_line_number with ${libfile}.c intead of $libsrc.

* Fixed typo in commit message for Patch 2/3.

Changes in v7

* Changed disable_breakpoints_in_freed_objfile () from feedback:
  Use is_breakpoint () and is_tracepoint ().
  Add call to mark_breakpoint_location_modified ().

* Changed command description according to suggestion.

* Changed commit log message for new functions according to feedback.

* Fixed nits in gdb/solib.c and testsuite/gdb.base/sym-file.exp.

Changes in v6

* Changed syntax of the command according to feedback:
    remove-symbol-file FILENAME
    remove-symbol-file -a ADDRESS

* Updated the documentation for the new syntax.

* Updated the test for the new syntax.

* Added check to only remove objfiles from the current program space.

Changes in v5

* The address parameter can now be any address mapping into one of the sections
  of the file to remove. This is more flexible and more judicious because the symbol
  file may have no text section, as pointed out in some reviews.

* Move is_addr_in_objfile from breakpoint.c to objfiles.c. This new function
  is now used in both symfile.c and breakpoint.c.

* is_addr_in_objfile returns now 0 if OBJFILE is NULL.

* Updated the documentation to reflect the command change.

* Removed double blank lines.

* Reworded the log entries in the commit messages, as suggested.

* The test was simplified using prepare_for_testing, as suggested.

Changes in v4

* gdb/symfile.c: add missing space character in output string.

* gdb/doc/gdb.texinfo: add usage example.

Changes in v3

* gdb/breakpoints.c (disable_breakpoints_in_freed_objfile):
  Changed name of disable_breakpoints_in_free_objfile to disable_breakpoints_in_freed_objfile.
  Call observer_breakpoint_modified at most one time per breakpoint.

* gdb/objfiles.h (struct objfile): Add comment for low_addr.

* gdb/solib.c (remove_user_added_objfile): Don't check OBJF_SHARED anymore to avoid leaving dangling pointers.

* gdb/symfile.c (add_symbol_file_command): Parse and evaluate the address parameter only once.

* gdb/symfile.c (remove_symbol_file_command): Don't use gdb_buildargv anymore. Ask the user for confirmation before removing a file.

* gdb/doc/gdb.texinfo: The parameter of the command is now referred to as "the address of the text section".

* gdb/NEWS: Move the entry for remove-symbol-file to "Changes since GDB 7.6". The address parameter is now referred to as "the beginning of the text section".

* Fixed letter case of variables in comments.

* Fixed indentation typos.



Nicolas Blanc (5):
  New remove-symbol-file command.
  Documentation for the remove-symbol-file command.
  Create target sections for user-added symbol files.
  Function is_elf_target.
  Test adding and removing a symbol file at runtime.

 gdb/NEWS                                 |    6 +
 gdb/breakpoint.c                         |   67 ++++++-
 gdb/doc/gdb.texinfo                      |   26 ++-
 gdb/doc/observer.texi                    |    4 +
 gdb/exec.c                               |   45 ++++
 gdb/exec.h                               |    6 +
 gdb/objfiles.c                           |   26 +++
 gdb/objfiles.h                           |    2 +
 gdb/printcmd.c                           |   15 +-
 gdb/solib.c                              |   19 ++
 gdb/symfile.c                            |  105 +++++++++-
 gdb/testsuite/gdb.base/sym-file-lib.c    |   26 +++
 gdb/testsuite/gdb.base/sym-file-loader.c |  353 ++++++++++++++++++++++++++++++
 gdb/testsuite/gdb.base/sym-file-loader.h |   99 +++++++++
 gdb/testsuite/gdb.base/sym-file-main.c   |   79 +++++++
 gdb/testsuite/gdb.base/sym-file.exp      |  159 ++++++++++++++
 gdb/testsuite/lib/gdb.exp                |   39 ++++
 17 files changed, 1063 insertions(+), 13 deletions(-)
 create mode 100644 gdb/testsuite/gdb.base/sym-file-lib.c
 create mode 100644 gdb/testsuite/gdb.base/sym-file-loader.c
 create mode 100644 gdb/testsuite/gdb.base/sym-file-loader.h
 create mode 100644 gdb/testsuite/gdb.base/sym-file-main.c
 create mode 100644 gdb/testsuite/gdb.base/sym-file.exp

-- 
1.7.6.5

^ permalink raw reply	[flat|nested] 8+ messages in thread

* [PATCH v17 5/5] Test adding and removing a symbol file at runtime.
  2013-10-18 13:40 [PATCH v17 0/5] remove-symbol-file & add-symbol-file Nicolas Blanc
  2013-10-18 13:40 ` [PATCH v17 4/5] Function is_elf_target Nicolas Blanc
@ 2013-10-18 13:40 ` Nicolas Blanc
  2013-10-18 13:41 ` [PATCH v17 2/5] Documentation for the remove-symbol-file command Nicolas Blanc
                   ` (3 subsequent siblings)
  5 siblings, 0 replies; 8+ messages in thread
From: Nicolas Blanc @ 2013-10-18 13:40 UTC (permalink / raw)
  To: tromey; +Cc: gdb-patches, Nicolas Blanc

This test exercises the commands 'add-symbol-file'
and 'remove-symbol-file'.

2013-14-10  Nicolas Blanc  <nicolas.blanc@intel.com>

gdb/testsuite
	* gdb.base/sym-file-lib.c: New file.
	* gdb.base/sym-file-loader.c: New file.
	* gdb.base/sym-file-loader.h: New file.
	* gdb.base/sym-file-main.c: New file.
	* gdb.base/sym-file.exp: New file.

Signed-off-by: Nicolas Blanc <nicolas.blanc@intel.com>
---
 gdb/testsuite/gdb.base/sym-file-lib.c    |   26 +++
 gdb/testsuite/gdb.base/sym-file-loader.c |  353 ++++++++++++++++++++++++++++++
 gdb/testsuite/gdb.base/sym-file-loader.h |   99 +++++++++
 gdb/testsuite/gdb.base/sym-file-main.c   |   79 +++++++
 gdb/testsuite/gdb.base/sym-file.exp      |  159 ++++++++++++++
 5 files changed, 716 insertions(+), 0 deletions(-)
 create mode 100644 gdb/testsuite/gdb.base/sym-file-lib.c
 create mode 100644 gdb/testsuite/gdb.base/sym-file-loader.c
 create mode 100644 gdb/testsuite/gdb.base/sym-file-loader.h
 create mode 100644 gdb/testsuite/gdb.base/sym-file-main.c
 create mode 100644 gdb/testsuite/gdb.base/sym-file.exp

diff --git a/gdb/testsuite/gdb.base/sym-file-lib.c b/gdb/testsuite/gdb.base/sym-file-lib.c
new file mode 100644
index 0000000..586215d
--- /dev/null
+++ b/gdb/testsuite/gdb.base/sym-file-lib.c
@@ -0,0 +1,26 @@
+/* Copyright 2013 Free Software Foundation, Inc.
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 3 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.
+*/
+
+extern int
+bar ()
+{
+  return 1; /* gdb break at bar */
+}
+
+extern int
+foo (int a)
+{
+  return a; /* gdb break at foo */
+}
diff --git a/gdb/testsuite/gdb.base/sym-file-loader.c b/gdb/testsuite/gdb.base/sym-file-loader.c
new file mode 100644
index 0000000..c55076f
--- /dev/null
+++ b/gdb/testsuite/gdb.base/sym-file-loader.c
@@ -0,0 +1,353 @@
+/* Copyright 2013 Free Software Foundation, Inc.
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 3 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#include <unistd.h>
+#include <fcntl.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/mman.h>
+
+#include "sym-file-loader.h"
+
+#ifdef TARGET_LP64
+
+uint8_t
+elf_st_type (uint8_t st_info)
+{
+  return ELF64_ST_TYPE (st_info);
+}
+
+#elif defined TARGET_ILP32
+
+uint8_t
+elf_st_type (uint8_t st_info)
+{
+  return ELF32_ST_TYPE (st_info);
+}
+
+#endif
+
+/* Load a program segment.  */
+
+static struct segment *
+load (uint8_t *addr, Elf_External_Phdr *phdr, struct segment *tail_seg)
+{
+  struct segment *seg = NULL;
+  uint8_t *mapped_addr = NULL;
+  void *from = NULL;
+  void *to = NULL;
+
+  /* For the sake of simplicity all operations are permitted.  */
+  unsigned perm = PROT_READ | PROT_WRITE | PROT_EXEC;
+
+  mapped_addr = (uint8_t *) mmap ((void *) GETADDR (phdr, p_vaddr),
+				  GET (phdr, p_memsz), perm,
+				  MAP_ANONYMOUS | MAP_PRIVATE, -1, 0);
+
+  from = (void *) (addr + GET (phdr, p_offset));
+  to = (void *) mapped_addr;
+
+  memcpy (to, from, GET (phdr, p_filesz));
+
+  seg = (struct segment *) malloc (sizeof (struct segment));
+
+  if (seg == 0)
+    return 0;
+
+  seg->mapped_addr = mapped_addr;
+  seg->phdr = phdr;
+  seg->next = 0;
+
+  if (tail_seg != 0)
+    tail_seg->next = seg;
+
+  return seg;
+}
+
+/* Mini shared library loader.  No reallocation
+   is performed for the sake of simplicity.  */
+
+int
+load_shlib (const char *file, Elf_External_Ehdr **ehdr_out,
+	    struct segment **seg_out)
+{
+  uint64_t i;
+  int fd;
+  off_t fsize;
+  uint8_t *addr;
+  Elf_External_Ehdr *ehdr;
+  Elf_External_Phdr *phdr;
+  struct segment *head_seg = NULL;
+  struct segment *tail_seg = NULL;
+
+  /* Map the lib in memory for reading.  */
+  fd = open (file, O_RDONLY);
+  if (fd < 0)
+    {
+      perror ("fopen failed.");
+      return -1;
+    }
+
+  fsize = lseek (fd, 0, SEEK_END);
+
+  if (fsize < 0)
+    {
+      perror ("lseek failed.");
+      return -1;
+    }
+
+  addr = (uint8_t *) mmap (NULL, fsize, PROT_READ, MAP_PRIVATE, fd, 0);
+  if (addr == (uint8_t *) -1)
+    {
+      perror ("mmap failed.");
+      return -1;
+    }
+
+  /* Check if the lib is an ELF file.  */
+  ehdr = (Elf_External_Ehdr *) addr;
+  if (ehdr->e_ident[EI_MAG0] != ELFMAG0
+      || ehdr->e_ident[EI_MAG1] != ELFMAG1
+      || ehdr->e_ident[EI_MAG2] != ELFMAG2
+      || ehdr->e_ident[EI_MAG3] != ELFMAG3)
+    {
+      printf ("Not an ELF file: %x\n", ehdr->e_ident[EI_MAG0]);
+      return -1;
+    }
+
+  if (ehdr->e_ident[EI_CLASS] == ELFCLASS32)
+    {
+      if (sizeof (void *) != 4)
+	{
+	  printf ("Architecture mismatch.");
+	  return -1;
+	}
+    }
+  else if (ehdr->e_ident[EI_CLASS] == ELFCLASS64)
+    {
+      if (sizeof (void *) != 8)
+	{
+	  printf ("Architecture mismatch.");
+	  return -1;
+	}
+    }
+
+  /* Load the program segments.  For the sake of simplicity
+     assume that no reallocation is needed.  */
+  phdr = (Elf_External_Phdr *) (addr + GET (ehdr, e_phoff));
+  for (i = 0; i < GET (ehdr, e_phnum); i++, phdr++)
+    {
+      if (GET (phdr, p_type) == PT_LOAD)
+	{
+	  struct segment *next_seg = load (addr, phdr, tail_seg);
+	  if (next_seg == 0)
+	    continue;
+	  tail_seg = next_seg;
+	  if (head_seg == 0)
+	    head_seg = next_seg;
+	}
+    }
+  *ehdr_out = ehdr;
+  *seg_out = head_seg;
+  return 0;
+}
+
+/* Return the section-header table.  */
+
+Elf_External_Shdr *
+find_shdrtab (Elf_External_Ehdr *ehdr)
+{
+  return (Elf_External_Shdr *) (((uint8_t *) ehdr) + GET (ehdr, e_shoff));
+}
+
+/* Return the string table of the section headers.  */
+
+const char *
+find_shstrtab (Elf_External_Ehdr *ehdr, uint64_t *size)
+{
+  const Elf_External_Shdr *shdr;
+  const Elf_External_Shdr *shstr;
+
+  if (GET (ehdr, e_shnum) <= GET (ehdr, e_shstrndx))
+    {
+      printf ("The index of the string table is corrupt.");
+      return NULL;
+    }
+
+  shdr = find_shdrtab (ehdr);
+
+  shstr = &shdr[GET (ehdr, e_shstrndx)];
+  *size = GET (shstr, sh_size);
+  return ((const char *) ehdr) + GET (shstr, sh_offset);
+}
+
+/* Return the string table named SECTION.  */
+
+const char *
+find_strtab (Elf_External_Ehdr *ehdr,
+	     const char *section, uint64_t *strtab_size)
+{
+  uint64_t shstrtab_size = 0;
+  const char *shstrtab;
+  uint64_t i;
+  const Elf_External_Shdr *shdr = find_shdrtab (ehdr);
+
+  /* Get the string table of the section headers.  */
+  shstrtab = find_shstrtab (ehdr, &shstrtab_size);
+  if (shstrtab == NULL)
+    return NULL;
+
+  for (i = 0; i < GET (ehdr, e_shnum); i++)
+    {
+      uint64_t name = GET (shdr + i, sh_name);
+      if (GET (shdr + i, sh_type) == SHT_STRTAB && name <= shstrtab_size
+	  && strcmp ((const char *) &shstrtab[name], section) == 0)
+	{
+	  *strtab_size = GET (shdr + i, sh_size);
+	  return ((const char *) ehdr) + GET (shdr + i, sh_offset);
+	}
+
+    }
+  return NULL;
+}
+
+/* Return the section header named SECTION.  */
+
+Elf_External_Shdr *
+find_shdr (Elf_External_Ehdr *ehdr, const char *section)
+{
+  uint64_t shstrtab_size = 0;
+  const char *shstrtab;
+  uint64_t i;
+
+  /* Get the string table of the section headers.  */
+  shstrtab = find_shstrtab (ehdr, &shstrtab_size);
+  if (shstrtab == NULL)
+    return NULL;
+
+  Elf_External_Shdr *shdr = find_shdrtab (ehdr);
+  for (i = 0; i < GET (ehdr, e_shnum); i++)
+    {
+      uint64_t name = GET (shdr + i, sh_name);
+      if (name <= shstrtab_size)
+	{
+	  if (strcmp ((const char *) &shstrtab[name], section) == 0)
+	    return &shdr[i];
+	}
+
+    }
+  return NULL;
+}
+
+/* Return the symbol table.  */
+
+Elf_External_Sym *
+find_symtab (Elf_External_Ehdr *ehdr, uint64_t *symtab_size)
+{
+  uint64_t i;
+  const Elf_External_Shdr *shdr = find_shdrtab (ehdr);
+
+  for (i = 0; i < GET (ehdr, e_shnum); i++)
+    {
+      if (GET (shdr + i, sh_type) == SHT_SYMTAB)
+	{
+	  *symtab_size = GET (shdr + i, sh_size) / sizeof (Elf_External_Sym);
+	  return (Elf_External_Sym *) (((const char *) ehdr) +
+				       GET (shdr + i, sh_offset));
+	}
+    }
+  return NULL;
+}
+
+/* Translate a file offset to an address in a loaded segment.   */
+
+int
+translate_offset (uint64_t file_offset, struct segment *seg, void **addr)
+{
+  while (seg)
+    {
+      uint64_t p_from, p_to;
+
+      Elf_External_Phdr *phdr = seg->phdr;
+
+      if (phdr == NULL)
+	{
+	  seg = seg->next;
+	  continue;
+	}
+
+      p_from = GET (phdr, p_offset);
+      p_to = p_from + GET (phdr, p_filesz);
+
+      if (p_from <= file_offset && file_offset < p_to)
+	{
+	  *addr = (void *) (seg->mapped_addr + (file_offset - p_from));
+	  return 0;
+	}
+      seg = seg->next;
+    }
+
+  return -1;
+}
+
+/* Lookup the address of FUNC.  */
+
+int
+lookup_function (const char *func,
+		 Elf_External_Ehdr *ehdr, struct segment *seg, void **addr)
+{
+  const char *strtab;
+  uint64_t strtab_size = 0;
+  Elf_External_Sym *symtab;
+  uint64_t symtab_size = 0;
+  uint64_t i;
+
+  /* Get the string table for the symbols.  */
+  strtab = find_strtab (ehdr, ".strtab", &strtab_size);
+  if (strtab == NULL)
+    {
+      printf (".strtab not found.");
+      return -1;
+    }
+
+  /* Get the symbol table.  */
+  symtab = find_symtab (ehdr, &symtab_size);
+  if (symtab == NULL)
+    {
+      printf ("symbol table not found.");
+      return -1;
+    }
+
+  for (i = 0; i < symtab_size; i++)
+    {
+      Elf_External_Sym *sym = &symtab[i];
+
+      if (elf_st_type (GET (sym, st_info)) != STT_FUNC)
+	continue;
+
+      if (GET (sym, st_name) < strtab_size)
+	{
+	  const char *name = &strtab[GET (sym, st_name)];
+	  if (strcmp (name, func) == 0)
+	    {
+
+	      uint64_t offset = GET (sym, st_value);
+	      return translate_offset (offset, seg, addr);
+	    }
+	}
+    }
+
+  return -1;
+}
diff --git a/gdb/testsuite/gdb.base/sym-file-loader.h b/gdb/testsuite/gdb.base/sym-file-loader.h
new file mode 100644
index 0000000..2b21ab2
--- /dev/null
+++ b/gdb/testsuite/gdb.base/sym-file-loader.h
@@ -0,0 +1,99 @@
+/* Copyright 2013 Free Software Foundation, Inc.
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 3 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#ifndef __SYM_FILE_LOADER__
+#define __SYM_FILE_LOADER__
+
+#include <inttypes.h>
+#include <ansidecl.h>
+#include <elf/common.h>
+#include <elf/external.h>
+
+#ifdef TARGET_LP64
+
+typedef Elf64_External_Phdr Elf_External_Phdr;
+typedef Elf64_External_Ehdr Elf_External_Ehdr;
+typedef Elf64_External_Shdr Elf_External_Shdr;
+typedef Elf64_External_Sym Elf_External_Sym;
+typedef uint64_t Elf_Addr;
+
+#elif defined TARGET_ILP32
+
+typedef Elf32_External_Phdr Elf_External_Phdr;
+typedef Elf32_External_Ehdr Elf_External_Ehdr;
+typedef Elf32_External_Shdr Elf_External_Shdr;
+typedef Elf32_External_Sym Elf_External_Sym;
+typedef uint32_t Elf_Addr;
+
+#endif
+
+#define GET(hdr, field) (\
+sizeof ((hdr)->field) == 1 ? (uint64_t) (hdr)->field[0] : \
+sizeof ((hdr)->field) == 2 ? (uint64_t) *(uint16_t *) (hdr)->field : \
+sizeof ((hdr)->field) == 4 ? (uint64_t) *(uint32_t *) (hdr)->field : \
+sizeof ((hdr)->field) == 8 ? *(uint64_t *) (hdr)->field : \
+*(uint64_t *) NULL)
+
+#define GETADDR(hdr, field) (\
+sizeof ((hdr)->field) == sizeof (Elf_Addr) ? *(Elf_Addr *) (hdr)->field : \
+*(Elf_Addr *) NULL)
+
+struct segment
+{
+  uint8_t *mapped_addr;
+  Elf_External_Phdr *phdr;
+  struct segment *next;
+};
+
+/* Mini shared library loader.  No reallocation is performed
+   for the sake of simplicity.  */
+
+int
+load_shlib (const char *file, Elf_External_Ehdr **ehdr_out,
+	    struct segment **seg_out);
+
+/* Return the section-header table.  */
+
+Elf_External_Shdr *find_shdrtab (Elf_External_Ehdr *ehdr);
+
+/* Return the string table of the section headers.  */
+
+const char *find_shstrtab (Elf_External_Ehdr *ehdr, uint64_t *size);
+
+/* Return the string table named SECTION.  */
+
+const char *find_strtab (Elf_External_Ehdr *ehdr,
+			 const char *section, uint64_t *strtab_size);
+
+/* Return the section header named SECTION.  */
+
+Elf_External_Shdr *find_shdr (Elf_External_Ehdr *ehdr, const char *section);
+
+/* Return the symbol table.  */
+
+Elf_External_Sym *find_symtab (Elf_External_Ehdr *ehdr,
+			       uint64_t *symtab_size);
+
+/* Translate a file offset to an address in a loaded segment.   */
+
+int translate_offset (uint64_t file_offset, struct segment *seg, void **addr);
+
+/* Lookup the address of FUNC.  */
+
+int
+lookup_function (const char *func, Elf_External_Ehdr* ehdr,
+		 struct segment *seg, void **addr);
+
+#endif
diff --git a/gdb/testsuite/gdb.base/sym-file-main.c b/gdb/testsuite/gdb.base/sym-file-main.c
new file mode 100644
index 0000000..932ed0d
--- /dev/null
+++ b/gdb/testsuite/gdb.base/sym-file-main.c
@@ -0,0 +1,79 @@
+/* Copyright 2013 Free Software Foundation, Inc.
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 3 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#include <stdlib.h>
+#include <stdio.h>
+
+#include "sym-file-loader.h"
+
+void
+gdb_add_symbol_file (void *addr, const char *file)
+{
+  return;
+}
+
+void
+gdb_remove_symbol_file (void *addr)
+{
+  return;
+}
+
+/* Load a shared library without relying on the standard
+   loader to test GDB's commands for adding and removing
+   symbol files at runtime.  */
+
+int
+main (int argc, const char *argv[])
+{
+  const char *file = SHLIB_NAME;
+  Elf_External_Ehdr *ehdr = NULL;
+  struct segment *head_seg = NULL;
+  Elf_External_Shdr *text;
+  char *text_addr = NULL;
+  int (*pbar) () = NULL;
+  int (*pfoo) (int) = NULL;
+
+  if (load_shlib (file, &ehdr, &head_seg) != 0)
+    return -1;
+
+  /* Get the text section.  */
+  text = find_shdr (ehdr, ".text");
+  if (text == NULL)
+    return -1;
+
+  /* Notify GDB to add the symbol file.  */
+  if (translate_offset (GET (text, sh_offset), head_seg, (void **) &text_addr)
+      != 0)
+    return -1;
+
+  gdb_add_symbol_file (text_addr, file);
+
+  /* Call bar from SHLIB_NAME.  */
+  if (lookup_function ("bar", ehdr, head_seg, (void *) &pbar) != 0)
+    return -1;
+
+  (*pbar) ();
+
+  /* Call foo from SHLIB_NAME.  */
+  if (lookup_function ("foo", ehdr, head_seg, (void *) &pfoo) != 0)
+    return -1;
+
+  (*pfoo) (2);
+
+  /* Notify GDB to remove the symbol file.  */
+  gdb_remove_symbol_file (text_addr);
+
+  return 0;
+}
diff --git a/gdb/testsuite/gdb.base/sym-file.exp b/gdb/testsuite/gdb.base/sym-file.exp
new file mode 100644
index 0000000..50eb98f
--- /dev/null
+++ b/gdb/testsuite/gdb.base/sym-file.exp
@@ -0,0 +1,159 @@
+# Copyright 2013 Free Software Foundation, Inc.
+
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
+
+# Test adding and removing a symbol file dynamically:
+# 1)  Run to gdb_add_symbol_file in $srcfile.
+# 2)  Set a pending breakpoint at bar in $srcfile3.
+# 3)  Load $shlib_name using 'add-symbol-file'.
+# 4)  'info files' must display ${lib_basename}.
+# 5)  Continue to bar in $srcfile3.
+# 6)  Set a breakpoint at foo in $srcfile3.
+# 7)  Continue to foo in $srcfile3.
+# 8)  Set a breakpoint at gdb_remove_symbol_file.
+# 9)  Continue to gdb_remove_symbol_file in $srcfile.
+# 10) Remove $shlib_name using 'remove-symbol-file'.
+# 11) 'info files' must not display ${lib_basename}, anymore.
+# 12) Check that the breakpoints at foo and bar are pending.
+# 13) Check that the execution can continue without error.
+
+if {![is_elf_target]} {
+    return 0
+}
+
+if [skip_shlib_tests] {
+    return 0
+}
+
+if [is_remote target] {
+    return 0
+}
+
+set target_size TARGET_UNKNOWN
+if {[is_lp64_target]} {
+    set target_size TARGET_LP64
+} elseif {[is_ilp32_target]} {
+   set target_size TARGET_ILP32
+} else {
+    return 0
+}
+
+set main_basename sym-file-main
+set loader_basename sym-file-loader
+set lib_basename sym-file-lib
+
+standard_testfile $main_basename.c $loader_basename.c $lib_basename.c
+
+set libsrc "${srcdir}/${subdir}/${srcfile3}"
+set shlib_name [standard_output_file ${lib_basename}.so]
+set exec_opts [list debug "additional_flags= -I$srcdir/../../include/ -D$target_size\
+ -DSHLIB_NAME\\=\"$shlib_name\""]
+
+if [get_compiler_info] {
+    return -1
+}
+
+if {[gdb_compile_shlib $libsrc $shlib_name {debug}] != ""} {
+    untested ${testfile}
+    return
+}
+
+if {[prepare_for_testing $testfile  $binfile "$srcfile $srcfile2" $exec_opts]} {
+    return
+}
+
+# 1) Run to GDB_ADD_SYMBOl_FILE in $srcfile for adding
+#    $shlib_name.
+set result [runto gdb_add_symbol_file]
+if {!$result} then {
+   return
+}
+
+# 2) Set a pending breakpoint at bar in $srcfile3.
+set result [gdb_breakpoint bar allow-pending]
+if {!$result} then {
+   return
+}
+
+# 3) Add $shlib_name using 'add-symbol-file'.
+set result [gdb_test "add-symbol-file ${shlib_name} addr" \
+		     "Reading symbols from .*${lib_basename}\\.so\\.\\.\\.done\\." \
+		     "add-symbol-file .*${lib_basename}\\.so addr" \
+		     "add symbol table from file \".*${lib_basename}\\.so\"\
+ at.*\\(y or n\\) " \
+		     "y"]
+if {$result != 0} then {
+   return
+}
+
+# 4) 'info files' must display $srcfile3.
+gdb_test "info files" \
+	 "^(?=(.*${lib_basename})).*" \
+	 "info files must display ${lib_basename}"
+
+# 5) Continue to bar in $srcfile3 to ensure that the breakpoint
+#    was bound correctly after adding $shilb_name.
+set lnum_bar [gdb_get_line_number "break at bar" $srcfile3]
+gdb_continue_to_breakpoint bar ".*${lib_basename}\\.c:$lnum_bar.*"
+
+# 6) Set a breakpoint at foo in $srcfile3.
+set result [gdb_breakpoint foo]
+if {!$result} then {
+    return
+}
+
+# 7) Continue to foo in $srcfile3 to ensure that the breakpoint
+#    was bound correctly.
+set lnum_foo [gdb_get_line_number "break at foo" $srcfile3]
+gdb_continue_to_breakpoint foo ".*${lib_basename}\\.c:$lnum_foo.*"
+
+# 8) Set a breakpoint at gdb_remove_symbol_file in $srcfile for
+#    removing $shlib_name.
+set result [gdb_breakpoint gdb_remove_symbol_file]
+if {!$result} then {
+    return
+}
+
+# 9) Continue to gdb_remove_symbol_file in $srcfile.
+gdb_continue_to_breakpoint gdb_remove_symbol_file
+
+# 10) Remove $shlib_name using 'remove-symbol-file'.
+set result [gdb_test "remove-symbol-file -a addr" \
+		     ""\
+     		     "remove-symbol-file -a addr" \
+		     "Remove symbol table from file \".*${lib_basename}\\.so\"\\?\
+.*\\(y or n\\) " \
+		     "y"]
+if {$result != 0} then {
+    return
+}
+
+# 11) 'info files' must not display ${lib_basename}, anymore.
+gdb_test "info files" \
+	 "^(?!(.*${lib_basename})).*" \
+	 "info files must not display ${lib_basename}"
+
+# 12) Check that the breakpoints at foo and bar are pending after removing
+#     $shlib_name.
+gdb_test "info breakpoints 2" \
+	 ".*PENDING.*" \
+	 "check if Breakpoint 2 is pending."
+
+gdb_test "info breakpoints 3" \
+	 ".*PENDING.*" \
+	 "check if Breakpoint 3 is pending."
+
+# 13) Check that the execution can continue without error.
+gdb_continue_to_end
+
-- 
1.7.6.5

^ permalink raw reply	[flat|nested] 8+ messages in thread

* [PATCH v17 1/5] New remove-symbol-file command.
  2013-10-18 13:40 [PATCH v17 0/5] remove-symbol-file & add-symbol-file Nicolas Blanc
                   ` (3 preceding siblings ...)
  2013-10-18 13:41 ` [PATCH v17 3/5] Create target sections for user-added symbol files Nicolas Blanc
@ 2013-10-18 13:41 ` Nicolas Blanc
  2013-10-24 19:44 ` [PATCH v17 0/5] remove-symbol-file & add-symbol-file Tom Tromey
  5 siblings, 0 replies; 8+ messages in thread
From: Nicolas Blanc @ 2013-10-18 13:41 UTC (permalink / raw)
  To: tromey; +Cc: gdb-patches, Nicolas Blanc

New command for removing symbol files added via
the add-symbol-file command.

2013-14-10  Nicolas Blanc  <nicolas.blanc@intel.com>

	* breakpoint.c (disable_breakpoints_in_freed_objfile): New function.
	* objfiles.c (free_objfile): Notify free_objfile.
	(is_addr_in_objfile): New function.
	* objfiles.h (is_addr_in_objfile): New declaration.
	* printcmd.c (clear_dangling_display_expressions): Act upon free_objfile
	events instead of solib_unloaded events.
	(_initialize_printcmd): Register observer for free_objfile instead
	of solib_unloaded notifications.
	* solib.c (remove_user_added_objfile): New function.
	* symfile.c (remove_symbol_file_command): New command.
	(_initialize_symfile): Add remove-symbol-file.
gdb/doc
	* observer.texi: New free_objfile event.

Signed-off-by: Nicolas Blanc <nicolas.blanc@intel.com>
---
 gdb/breakpoint.c      |   67 +++++++++++++++++++++++++++++++++++++--
 gdb/doc/observer.texi |    4 ++
 gdb/objfiles.c        |   26 +++++++++++++++
 gdb/objfiles.h        |    2 +
 gdb/printcmd.c        |   15 +++++---
 gdb/solib.c           |   19 +++++++++++
 gdb/symfile.c         |   85 +++++++++++++++++++++++++++++++++++++++++++++++++
 7 files changed, 209 insertions(+), 9 deletions(-)

diff --git a/gdb/breakpoint.c b/gdb/breakpoint.c
index 5ce50de..f480c5b 100644
--- a/gdb/breakpoint.c
+++ b/gdb/breakpoint.c
@@ -7468,9 +7468,9 @@ disable_breakpoints_in_shlibs (void)
   }
 }
 
-/* Disable any breakpoints and tracepoints that are in an unloaded shared
-   library.  Only apply to enabled breakpoints, disabled ones can just stay
-   disabled.  */
+/* Disable any breakpoints and tracepoints that are in SOLIB upon
+   notification of unloaded_shlib.  Only apply to enabled breakpoints,
+   disabled ones can just stay disabled.  */
 
 static void
 disable_breakpoints_in_unloaded_shlib (struct so_list *solib)
@@ -7522,6 +7522,66 @@ disable_breakpoints_in_unloaded_shlib (struct so_list *solib)
   }
 }
 
+/* Disable any breakpoints and tracepoints in OBJFILE upon
+   notification of free_objfile.  Only apply to enabled breakpoints,
+   disabled ones can just stay disabled.  */
+
+static void
+disable_breakpoints_in_freed_objfile (struct objfile *objfile)
+{
+  struct breakpoint *b;
+
+  if (objfile == NULL)
+    return;
+
+  /* If the file is a shared library not loaded by the user then
+     solib_unloaded was notified and disable_breakpoints_in_unloaded_shlib
+     was called.  In that case there is no need to take action again.  */
+  if ((objfile->flags & OBJF_SHARED) && !(objfile->flags & OBJF_USERLOADED))
+    return;
+
+  ALL_BREAKPOINTS (b)
+    {
+      struct bp_location *loc;
+      int bp_modified = 0;
+
+      if (!is_breakpoint (b) && !is_tracepoint (b))
+	continue;
+
+      for (loc = b->loc; loc != NULL; loc = loc->next)
+	{
+	  CORE_ADDR loc_addr = loc->address;
+
+	  if (loc->loc_type != bp_loc_hardware_breakpoint
+	      && loc->loc_type != bp_loc_software_breakpoint)
+	    continue;
+
+	  if (loc->shlib_disabled != 0)
+	    continue;
+
+	  if (objfile->pspace != loc->pspace)
+	    continue;
+
+	  if (loc->loc_type != bp_loc_hardware_breakpoint
+	      && loc->loc_type != bp_loc_software_breakpoint)
+	    continue;
+
+	  if (is_addr_in_objfile (loc_addr, objfile))
+	    {
+	      loc->shlib_disabled = 1;
+	      loc->inserted = 0;
+
+	      mark_breakpoint_location_modified (loc);
+
+	      bp_modified = 1;
+	    }
+	}
+
+      if (bp_modified)
+	observer_notify_breakpoint_modified (b);
+    }
+}
+
 /* FORK & VFORK catchpoints.  */
 
 /* An instance of this type is used to represent a fork or vfork
@@ -15997,6 +16057,7 @@ _initialize_breakpoint (void)
   initialize_breakpoint_ops ();
 
   observer_attach_solib_unloaded (disable_breakpoints_in_unloaded_shlib);
+  observer_attach_free_objfile (disable_breakpoints_in_freed_objfile);
   observer_attach_inferior_exit (clear_syscall_counts);
   observer_attach_memory_changed (invalidate_bp_value_on_memory_change);
 
diff --git a/gdb/doc/observer.texi b/gdb/doc/observer.texi
index adb7085..f753965 100644
--- a/gdb/doc/observer.texi
+++ b/gdb/doc/observer.texi
@@ -138,6 +138,10 @@ Called with @var{objfile} equal to @code{NULL} to indicate
 previously loaded symbol table data has now been invalidated.
 @end deftypefun
 
+@deftypefun void free_objfile (struct objfile *@var{objfile})
+The object file specified by @var{objfile} is about to be freed.
+@end deftypefun
+
 @deftypefun void new_thread (struct thread_info *@var{t})
 The thread specified by @var{t} has been created.
 @end deftypefun
diff --git a/gdb/objfiles.c b/gdb/objfiles.c
index d1f3121..079b0fe 100644
--- a/gdb/objfiles.c
+++ b/gdb/objfiles.c
@@ -552,6 +552,9 @@ free_objfile_separate_debug (struct objfile *objfile)
 void
 free_objfile (struct objfile *objfile)
 {
+  /* First notify observers that this objfile is about to be freed.  */
+  observer_notify_free_objfile (objfile);
+
   /* Free all separate debug objfiles.  */
   free_objfile_separate_debug (objfile);
 
@@ -1468,6 +1471,29 @@ resume_section_map_updates_cleanup (void *arg)
   resume_section_map_updates (arg);
 }
 
+/* Return 1 if ADDR maps into one of the sections of OBJFILE and 0
+   otherwise.  */
+
+int
+is_addr_in_objfile (CORE_ADDR addr, const struct objfile *objfile)
+{
+  struct obj_section *osect;
+
+  if (objfile == NULL)
+    return 0;
+
+  ALL_OBJFILE_OSECTIONS (objfile, osect)
+    {
+      if (section_is_overlay (osect) && !section_is_mapped (osect))
+	continue;
+
+      if (obj_section_addr (osect) <= addr
+	  && addr < obj_section_endaddr (osect))
+	return 1;
+    }
+  return 0;
+}
+
 /* The default implementation for the "iterate_over_objfiles_in_search_order"
    gdbarch method.  It is equivalent to use the ALL_OBJFILES macro,
    searching the objfiles in the order they are stored internally,
diff --git a/gdb/objfiles.h b/gdb/objfiles.h
index 08771d0..9bca812 100644
--- a/gdb/objfiles.h
+++ b/gdb/objfiles.h
@@ -485,6 +485,8 @@ extern void objfile_set_sym_fns (struct objfile *objfile,
 
 extern void objfiles_changed (void);
 
+extern int is_addr_in_objfile (CORE_ADDR addr, const struct objfile *objfile);
+
 /* This operation deletes all objfile entries that represent solibs that
    weren't explicitly loaded by the user, via e.g., the add-symbol-file
    command.  */
diff --git a/gdb/printcmd.c b/gdb/printcmd.c
index 9bca6dd..7354474 100644
--- a/gdb/printcmd.c
+++ b/gdb/printcmd.c
@@ -1940,21 +1940,24 @@ disable_display_command (char *args, int from_tty)
    an item by re-parsing .exp_string field in the new execution context.  */
 
 static void
-clear_dangling_display_expressions (struct so_list *solib)
+clear_dangling_display_expressions (struct objfile *objfile)
 {
-  struct objfile *objfile = solib->objfile;
   struct display *d;
+  struct program_space *pspace;
 
   /* With no symbol file we cannot have a block or expression from it.  */
   if (objfile == NULL)
     return;
+  pspace = objfile->pspace;
   if (objfile->separate_debug_objfile_backlink)
-    objfile = objfile->separate_debug_objfile_backlink;
-  gdb_assert (objfile->pspace == solib->pspace);
+    {
+      objfile = objfile->separate_debug_objfile_backlink;
+      gdb_assert (objfile->pspace == pspace);
+    }
 
   for (d = display_chain; d != NULL; d = d->next)
     {
-      if (d->pspace != solib->pspace)
+      if (d->pspace != pspace)
 	continue;
 
       if (lookup_objfile_from_block (d->block) == objfile
@@ -2487,7 +2490,7 @@ _initialize_printcmd (void)
 
   current_display_number = -1;
 
-  observer_attach_solib_unloaded (clear_dangling_display_expressions);
+  observer_attach_free_objfile (clear_dangling_display_expressions);
 
   add_info ("address", address_info,
 	    _("Describe where symbol SYM is stored."));
diff --git a/gdb/solib.c b/gdb/solib.c
index 8ed492a..06e0b16 100644
--- a/gdb/solib.c
+++ b/gdb/solib.c
@@ -1496,6 +1496,23 @@ gdb_bfd_lookup_symbol (bfd *abfd,
   return symaddr;
 }
 
+/* SO_LIST_HEAD may contain user-loaded object files that can be removed
+   out-of-band by the user.  So upon notification of free_objfile remove
+   all references to any user-loaded file that is about to be freed.  */
+
+static void
+remove_user_added_objfile (struct objfile *objfile)
+{
+  struct so_list *so;
+
+  if (objfile != 0 && objfile->flags & OBJF_USERLOADED)
+    {
+      for (so = so_list_head; so != NULL; so = so->next)
+	if (so->objfile == objfile)
+	  so->objfile = NULL;
+    }
+}
+
 extern initialize_file_ftype _initialize_solib; /* -Wmissing-prototypes */
 
 void
@@ -1503,6 +1520,8 @@ _initialize_solib (void)
 {
   solib_data = gdbarch_data_register_pre_init (solib_init);
 
+  observer_attach_free_objfile (remove_user_added_objfile);
+
   add_com ("sharedlibrary", class_files, sharedlibrary_command,
 	   _("Load shared object library symbols for files matching REGEXP."));
   add_info ("sharedlibrary", info_sharedlibrary_command,
diff --git a/gdb/symfile.c b/gdb/symfile.c
index d260ff9..0318466 100644
--- a/gdb/symfile.c
+++ b/gdb/symfile.c
@@ -2342,6 +2342,82 @@ add_symbol_file_command (char *args, int from_tty)
 }
 \f
 
+/* This function removes a symbol file that was added via add-symbol-file.  */
+
+static void
+remove_symbol_file_command (char *args, int from_tty)
+{
+  char **argv;
+  struct objfile *objf = NULL;
+  struct cleanup *my_cleanups;
+  struct program_space *pspace = current_program_space;
+  struct gdbarch *gdbarch = get_current_arch ();
+
+  dont_repeat ();
+
+  if (args == NULL)
+    error (_("remove-symbol-file: no symbol file provided"));
+
+  my_cleanups = make_cleanup (null_cleanup, NULL);
+
+  argv = gdb_buildargv (args);
+
+  if (strcmp (argv[0], "-a") == 0)
+    {
+      /* Interpret the next argument as an address.  */
+      CORE_ADDR addr;
+
+      if (argv[1] == NULL)
+	error (_("Missing address argument"));
+
+      if (argv[2] != NULL)
+	error (_("Junk after %s"), argv[1]);
+
+      addr = parse_and_eval_address (argv[1]);
+
+      ALL_OBJFILES (objf)
+	{
+	  if (objf != 0
+	      && objf->flags & OBJF_USERLOADED
+	      && objf->pspace == pspace && is_addr_in_objfile (addr, objf))
+	    break;
+	}
+    }
+  else if (argv[0] != NULL)
+    {
+      /* Interpret the current argument as a file name.  */
+      char *filename;
+
+      if (argv[1] != NULL)
+	error (_("Junk after %s"), argv[0]);
+
+      filename = tilde_expand (argv[0]);
+      make_cleanup (xfree, filename);
+
+      ALL_OBJFILES (objf)
+	{
+	  if (objf != 0
+	      && objf->flags & OBJF_USERLOADED
+	      && objf->pspace == pspace
+	      && filename_cmp (filename, objfile_name (objf)) == 0)
+	    break;
+	}
+    }
+
+  if (objf == NULL)
+    error (_("No symbol file found"));
+
+  if (from_tty
+      && !query (_("Remove symbol table from file \"%s\"? "),
+		 objfile_name (objf)))
+    error (_("Not confirmed."));
+
+  free_objfile (objf);
+  clear_symtab_users (0);
+
+  do_cleanups (my_cleanups);
+}
+
 typedef struct objfile *objfilep;
 
 DEF_VEC_P (objfilep);
@@ -3764,6 +3840,15 @@ with the text.  SECT is a section name to be loaded at SECT_ADDR."),
 	       &cmdlist);
   set_cmd_completer (c, filename_completer);
 
+  c = add_cmd ("remove-symbol-file", class_files,
+	       remove_symbol_file_command, _("\
+Remove a symbol file added via the add-symbol-file command.\n\
+Usage: remove-symbol-file FILENAME\n\
+       remove-symbol-file -a ADDRESS\n\
+The file to remove can be identified by its filename or by an address\n\
+that lies within the boundaries of this symbol file in memory."),
+	       &cmdlist);
+
   c = add_cmd ("load", class_files, load_command, _("\
 Dynamically load FILE into the running program, and record its symbols\n\
 for access from GDB.\n\
-- 
1.7.6.5

^ permalink raw reply	[flat|nested] 8+ messages in thread

* [PATCH v17 3/5] Create target sections for user-added symbol files.
  2013-10-18 13:40 [PATCH v17 0/5] remove-symbol-file & add-symbol-file Nicolas Blanc
                   ` (2 preceding siblings ...)
  2013-10-18 13:41 ` [PATCH v17 2/5] Documentation for the remove-symbol-file command Nicolas Blanc
@ 2013-10-18 13:41 ` Nicolas Blanc
  2013-10-18 13:41 ` [PATCH v17 1/5] New remove-symbol-file command Nicolas Blanc
  2013-10-24 19:44 ` [PATCH v17 0/5] remove-symbol-file & add-symbol-file Tom Tromey
  5 siblings, 0 replies; 8+ messages in thread
From: Nicolas Blanc @ 2013-10-18 13:41 UTC (permalink / raw)
  To: tromey; +Cc: gdb-patches, Nicolas Blanc

Add the sections of the symbol files that are provided via
'add-symbol-file' to the set of current target sections.
User-added sections are removed upon notification of free_objfile
when their corresponding object file is deleted.

2013-14-10  Nicolas Blanc  <nicolas.blanc@intel.com>

	* exec.h (add_target_sections_of_objfile): New declaration.
	* exec.c (add_target_sections_of_objfile): New function.
	* symfile.c (add_symbol_file_command): Update current target sections.
	(symfile_free_objfile): New function.
	(_initialize_symfile): Register observer for free_objf events.

Signed-off-by: Nicolas Blanc <nicolas.blanc@intel.com>
---
 gdb/exec.c    |   45 +++++++++++++++++++++++++++++++++++++++++++++
 gdb/exec.h    |    6 ++++++
 gdb/symfile.c |   20 ++++++++++++++++++--
 3 files changed, 69 insertions(+), 2 deletions(-)

diff --git a/gdb/exec.c b/gdb/exec.c
index 758cdc1..187c412 100644
--- a/gdb/exec.c
+++ b/gdb/exec.c
@@ -438,6 +438,51 @@ add_target_sections (void *owner,
     }
 }
 
+/* Add the sections of OBJFILE to the current set of target sections.  */
+
+void
+add_target_sections_of_objfile (struct objfile *objfile)
+{
+  struct target_section_table *table = current_target_sections;
+  struct obj_section *osect;
+  int space;
+  unsigned count = 0;
+  struct target_section *ts;
+
+  if (objfile == NULL)
+    return;
+
+  /* Compute the number of sections to add.  */
+  ALL_OBJFILE_OSECTIONS (objfile, osect)
+    {
+      if (bfd_get_section_size (osect->the_bfd_section) == 0)
+	continue;
+      count++;
+    }
+
+  if (count == 0)
+    return;
+
+  space = resize_section_table (table, count);
+
+  ts = table->sections + space;
+
+  ALL_OBJFILE_OSECTIONS (objfile, osect)
+    {
+      if (bfd_get_section_size (osect->the_bfd_section) == 0)
+	continue;
+
+      gdb_assert (ts < table->sections + space + count);
+
+      ts->addr = obj_section_addr (osect);
+      ts->endaddr = obj_section_endaddr (osect);
+      ts->the_bfd_section = osect->the_bfd_section;
+      ts->owner = (void *) objfile;
+
+      ts++;
+    }
+}
+
 /* Remove all target sections owned by OWNER.
    OWNER must be the same value passed to add_target_sections.  */
 
diff --git a/gdb/exec.h b/gdb/exec.h
index 39d5ea5..d8ea389 100644
--- a/gdb/exec.h
+++ b/gdb/exec.h
@@ -27,6 +27,7 @@
 struct target_section;
 struct target_ops;
 struct bfd;
+struct objfile;
 
 extern struct target_ops exec_ops;
 
@@ -93,6 +94,11 @@ extern void add_target_sections (void *owner,
 				 struct target_section *sections,
 				 struct target_section *sections_end);
 
+/* Add the sections of OBJFILE to the current set of target sections.
+ * OBJFILE owns the new target sections.  */
+
+extern void add_target_sections_of_objfile (struct objfile *objfile);
+
 /* Prints info about all sections defined in the TABLE.  ABFD is
    special cased --- it's filename is omitted; if it is the executable
    file, its entry point is printed.  */
diff --git a/gdb/symfile.c b/gdb/symfile.c
index 0318466..e0a234c 100644
--- a/gdb/symfile.c
+++ b/gdb/symfile.c
@@ -57,6 +57,7 @@
 #include "stack.h"
 #include "gdb_bfd.h"
 #include "cli/cli-utils.h"
+#include "target.h"
 
 #include <sys/types.h>
 #include <fcntl.h>
@@ -2206,6 +2207,7 @@ add_symbol_file_command (char *args, int from_tty)
   int expecting_sec_name = 0;
   int expecting_sec_addr = 0;
   char **argv;
+  struct objfile *objf;
 
   struct sect_opt
   {
@@ -2332,8 +2334,10 @@ add_symbol_file_command (char *args, int from_tty)
   if (from_tty && (!query ("%s", "")))
     error (_("Not confirmed."));
 
-  symbol_file_add (filename, from_tty ? SYMFILE_VERBOSE : 0,
-                   section_addrs, flags);
+  objf = symbol_file_add (filename, from_tty ? SYMFILE_VERBOSE : 0,
+			  section_addrs, flags);
+
+  add_target_sections_of_objfile (objf);
 
   /* Getting new symbols may change our opinion about what is
      frameless.  */
@@ -3819,11 +3823,23 @@ symfile_find_segment_sections (struct objfile *objfile)
   free_symfile_segment_data (data);
 }
 
+/* Listen for free_objfile events.  */
+
+static void
+symfile_free_objfile (struct objfile *objfile)
+{
+  /* Remove the target sections of user-added objfiles.  */
+  if (objfile != 0 && objfile->flags & OBJF_USERLOADED)
+    remove_target_sections ((void *) objfile);
+}
+
 void
 _initialize_symfile (void)
 {
   struct cmd_list_element *c;
 
+  observer_attach_free_objfile (symfile_free_objfile);
+
   c = add_cmd ("symbol-file", class_files, symbol_file_command, _("\
 Load symbol table from executable file FILE.\n\
 The `file' command can also load symbol tables, as well as setting the file\n\
-- 
1.7.6.5

^ permalink raw reply	[flat|nested] 8+ messages in thread

* [PATCH v17 2/5] Documentation for the remove-symbol-file command.
  2013-10-18 13:40 [PATCH v17 0/5] remove-symbol-file & add-symbol-file Nicolas Blanc
  2013-10-18 13:40 ` [PATCH v17 4/5] Function is_elf_target Nicolas Blanc
  2013-10-18 13:40 ` [PATCH v17 5/5] Test adding and removing a symbol file at runtime Nicolas Blanc
@ 2013-10-18 13:41 ` Nicolas Blanc
  2013-10-18 13:41 ` [PATCH v17 3/5] Create target sections for user-added symbol files Nicolas Blanc
                   ` (2 subsequent siblings)
  5 siblings, 0 replies; 8+ messages in thread
From: Nicolas Blanc @ 2013-10-18 13:41 UTC (permalink / raw)
  To: tromey; +Cc: gdb-patches, Nicolas Blanc

2013-04-05  Nicolas Blanc  <nicolas.blanc@intel.com>

	* NEWS: Add description of the remove-symbol-file command.
gdb/doc
	* gdb.texinfo (Commands to Specify Files): Add description
	of the remove-symbol-file command.

Signed-off-by: Nicolas Blanc <nicolas.blanc@intel.com>
---
 gdb/NEWS            |    6 ++++++
 gdb/doc/gdb.texinfo |   26 ++++++++++++++++++++++++--
 2 files changed, 30 insertions(+), 2 deletions(-)

diff --git a/gdb/NEWS b/gdb/NEWS
index 10834df..ca2d8da 100644
--- a/gdb/NEWS
+++ b/gdb/NEWS
@@ -74,6 +74,12 @@ maint set|show per-command time
 maint set|show per-command symtab
   Enable display of per-command gdb resource usage.
 
+remove-symbol-file FILENAME
+remove-symbol-file -a ADDRESS
+  Remove a symbol file added via add-symbol-file.  The file to remove
+  can be identified by its filename or by an address that lies within
+  the boundaries of this symbol file in memory.
+
 * New options
 
 set debug symfile off|on
diff --git a/gdb/doc/gdb.texinfo b/gdb/doc/gdb.texinfo
index 44fb174..8333e90 100644
--- a/gdb/doc/gdb.texinfo
+++ b/gdb/doc/gdb.texinfo
@@ -16690,8 +16690,9 @@ section name and base address for that section.  You can specify any
 The symbol table of the file @var{filename} is added to the symbol table
 originally read with the @code{symbol-file} command.  You can use the
 @code{add-symbol-file} command any number of times; the new symbol data
-thus read keeps adding to the old.  To discard all old symbol data
-instead, use the @code{symbol-file} command without any arguments.
+thus read is kept in addition to the old.
+
+Changes can be reverted using the command @code{remove-symbol-file}.
 
 @cindex relocatable object files, reading symbols from
 @cindex object files, relocatable, reading symbols from
@@ -16729,6 +16730,27 @@ way.
 
 @code{add-symbol-file} does not repeat if you press @key{RET} after using it.
 
+@kindex remove-symbol-file
+@item remove-symbol-file @var{filename}
+@item remove-symbol-file -a @var{address}
+Remove a symbol file added via the @code{add-symbol-file} command.  The
+file to remove can be identified by its @var{filename} or by an @var{address}
+that lies within the boundaries of this symbol file in memory.  Example:
+
+@smallexample
+(gdb) add-symbol-file /home/user/gdb/mylib.so 0x7ffff7ff9480
+add symbol table from file "/home/user/gdb/mylib.so" at
+    .text_addr = 0x7ffff7ff9480
+(y or n) y
+Reading symbols from /home/user/gdb/mylib.so...done.
+(gdb) remove-symbol-file -a 0x7ffff7ff9480
+Remove symbol table from file "/home/user/gdb/mylib.so"? (y or n) y
+(gdb)
+@end smallexample
+
+
+@code{remove-symbol-file} does not repeat if you press @key{RET} after using it.
+
 @kindex add-symbol-file-from-memory
 @cindex @code{syscall DSO}
 @cindex load symbols from memory
-- 
1.7.6.5

^ permalink raw reply	[flat|nested] 8+ messages in thread

* Re: [PATCH v17 0/5] remove-symbol-file & add-symbol-file.
  2013-10-18 13:40 [PATCH v17 0/5] remove-symbol-file & add-symbol-file Nicolas Blanc
                   ` (4 preceding siblings ...)
  2013-10-18 13:41 ` [PATCH v17 1/5] New remove-symbol-file command Nicolas Blanc
@ 2013-10-24 19:44 ` Tom Tromey
  2013-10-29 11:06   ` Blanc, Nicolas
  5 siblings, 1 reply; 8+ messages in thread
From: Tom Tromey @ 2013-10-24 19:44 UTC (permalink / raw)
  To: Nicolas Blanc; +Cc: gdb-patches

>>>>> "Nicolas" == Nicolas Blanc <nicolas.blanc@intel.com> writes:

Nicolas> Thanks for the review. I updated the patches according to:

Thanks Nicolas.

I have no further comments.
Your series is ok.  Please check it in.

I feel that even for gdb, 17 revisions is unusual.  Thank you for
persevering.

Tom

^ permalink raw reply	[flat|nested] 8+ messages in thread

* RE: [PATCH v17 0/5] remove-symbol-file & add-symbol-file.
  2013-10-24 19:44 ` [PATCH v17 0/5] remove-symbol-file & add-symbol-file Tom Tromey
@ 2013-10-29 11:06   ` Blanc, Nicolas
  0 siblings, 0 replies; 8+ messages in thread
From: Blanc, Nicolas @ 2013-10-29 11:06 UTC (permalink / raw)
  To: gdb-patches

Hi,

I committed the remove-symbol-file series. This was my first contribution.
Thank you all for your reviews and help to improve the patch.

Regards,

Nicolas

-----Original Message-----
From: gdb-patches-owner@sourceware.org [mailto:gdb-patches-owner@sourceware.org] On Behalf Of Tom Tromey
Sent: Thursday, October 24, 2013 9:44 PM
To: Blanc, Nicolas
Cc: gdb-patches@sourceware.org
Subject: Re: [PATCH v17 0/5] remove-symbol-file & add-symbol-file.

>>>>> "Nicolas" == Nicolas Blanc <nicolas.blanc@intel.com> writes:

Nicolas> Thanks for the review. I updated the patches according to:

Thanks Nicolas.

I have no further comments.
Your series is ok.  Please check it in.

I feel that even for gdb, 17 revisions is unusual.  Thank you for persevering.

Tom
Intel GmbH
Dornacher Strasse 1
85622 Feldkirchen/Muenchen, Deutschland
Sitz der Gesellschaft: Feldkirchen bei Muenchen
Geschaeftsfuehrer: Christian Lamprechter, Hannes Schwaderer, Douglas Lusk
Registergericht: Muenchen HRB 47456
Ust.-IdNr./VAT Registration No.: DE129385895
Citibank Frankfurt a.M. (BLZ 502 109 00) 600119052

^ permalink raw reply	[flat|nested] 8+ messages in thread

end of thread, other threads:[~2013-10-29 11:06 UTC | newest]

Thread overview: 8+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2013-10-18 13:40 [PATCH v17 0/5] remove-symbol-file & add-symbol-file Nicolas Blanc
2013-10-18 13:40 ` [PATCH v17 4/5] Function is_elf_target Nicolas Blanc
2013-10-18 13:40 ` [PATCH v17 5/5] Test adding and removing a symbol file at runtime Nicolas Blanc
2013-10-18 13:41 ` [PATCH v17 2/5] Documentation for the remove-symbol-file command Nicolas Blanc
2013-10-18 13:41 ` [PATCH v17 3/5] Create target sections for user-added symbol files Nicolas Blanc
2013-10-18 13:41 ` [PATCH v17 1/5] New remove-symbol-file command Nicolas Blanc
2013-10-24 19:44 ` [PATCH v17 0/5] remove-symbol-file & add-symbol-file Tom Tromey
2013-10-29 11:06   ` Blanc, Nicolas

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).