This is the mail archive of the gdb-patches@sourceware.org mailing list for the GDB project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Re: [PATCH, gdbserver] Further cleanup of FDPIC/DSBT divergences


Hi,

On 06/24/2013 10:47 AM, Luis Machado wrote:
On 06/24/2013 10:42 AM, Yao Qi wrote:
On 06/21/2013 02:51 AM, Luis Machado wrote:
Things have changed, and c6x is now using the exact same data structures
as FDPIC-based targets in uClibc. Please refer to
http://lists.uclibc.org/pipermail/uclibc/2013-May/047789.html  for the
uClibc changes that led to this.

Mark Salter, the author of the uClibc change, has agreed with the
solution i proposed:
http://lists.uclibc.org/pipermail/uclibc/2013-May/047790.html.

It is all good, but we've been conditionalizing the c6x-specific
target_loadmap data structure based on the presence of PT_GETDSBT. This
has always been defined in uClibc and, since Mark's change, it doesn't
work as a hint of whether to use the new or the old target_loadmap data
structure anymore. Therefore we will/already have a potential problem
with backwards compatibility.

Bernhard has stated that backwards compatibility on uClibc's side is not
a
problem:http://lists.uclibc.org/pipermail/uclibc/2013-June/047801.html.

With all that exposed, my proposed change to gdbserver is to drop all
the DSBT-specific bits, remove their definitions and explicitly use
FDPIC definitions instead, making things a little bit cleaner.

In the following patch i also changed the code slightly to stop defining
linux_read_loadmap to NULL and i switched to explicitly setting the
target hook to NULL in the absence of the required definition.

What do you think? Yao? Mike?

Luis,
Looks Mark S. proposed using FDPIC in tic6x port in kernel, instead of
DSBT which was used when we did the tic6x port in GDB.  I checked the
kernel log, and found that DSBT constants are never used in the official
kernel.  They only appeared in the linux-c6x.org git tree temporarily.
Since kernel and uclibc has migrated to the new scheme, I don't worry
about the compatibility issue here.


2013-06-20  Luis Machado<lgustavo@codesourcery.com>

    * linux-low.c: Remove check for PT_GETDSBT.
    (target_loadmap): Remove data structure conditionalized by
    the presence of PT_GETDSBT.
    (LINUX_LOADMAP, LINUX_LOADMAP_EXEC,
    LINUX_LOADMAP_INTERP): Remove definitions.

Not sure we can break words in parentheses into multiple lines.  I
suggest:

     (LINUX_LOADMAP, LINUX_LOADMAP_EXEC): Remove definitions.
     (LINUX_LOADMAP_INTERP): Likewise.

the patch is OK to me, but we also need adjustments in solib-dsbt.c.
This patch should go in together with the changes in solib-dsbt.c.


Thanks Yao. You are correct. Let me address the solib-dsbt.c bits as well.

Luis

Here is an updated patch that deals with solib-dsbt.c as well. The additional tic6x-specific fields from the loadmap were removed and dsbt_index is now fetched from the shared library file on disk instead of grabbing such information from the runtime loadmap. That information does not change anyway.

Since hardware for this platform is scarce, i could not test this change for real, only build it and certify it looks sane.

How does it look?

Luis

2013-08-08  Luis Machado  <lgustavo@codesourcery.com>

	gdb/gdbserver
	* linux-low.c: Remove check for PT_GETDSBT.
	(target_loadmap): Remove data structure conditionalized by
	the presence of PT_GETDSBT.
	(LINUX_LOADMAP, LINUX_LOADMAP_EXEC,
	LINUX_LOADMAP_INTERP): Remove definitions.
	(linux_read_loadmap): Replace LINUX_LOADMAP_EXEC with
	PTRACE_GETFDPIC_EXEC, LINUX_LOADMAP_INTERP with
	PTRACE_GETFDPIC_INTERP and LINUX_LOADMAP with PTRACE_GETFDPIC.
	Do not set linux_read_loadmap to NULL in the absence of
	PTRACE_GETFDPIC.
	(linux_target_ops) <read_loadmap>: Only set to linux_read_loadmap
	in the presence of PTRACE_GETFDPIC.

	gdb/
	* solib-dsbt.c (DT_TIC6X_DSBT_INDEX): New definition.
	(ext_elf32_dsbt_loadseg) <dsbt_table_ptr>: Remove.
	(ext_elf32_dsbt_loadseg) <dsbt_size, dsbt_index>: Remove.
	(int_elf32_dsbt_loadmap) <dsbt_table_ptr>: Remove.
	(int_elf32_dsbt_loadmap) <dsbt_size, dsbt_index>: Remove.
	(scan_dyntag_in_bfd): New function.
	(fetch_solib_dsbt_index): New function.
	(dsbt_current_sos): Extract dsbt_index based on the
	shared library filename.

 gdb/gdbserver/linux-low.c |   37 +++--------
 gdb/solib-dsbt.c          |  160 +++++++++++++++++++++++++++++++++++++--------
 2 files changed, 143 insertions(+), 54 deletions(-)

diff --git a/gdb/gdbserver/linux-low.c b/gdb/gdbserver/linux-low.c
index 47ea76d..4013829 100644
--- a/gdb/gdbserver/linux-low.c
+++ b/gdb/gdbserver/linux-low.c
@@ -5262,7 +5262,7 @@ linux_qxfer_spu (const char *annex, unsigned char *readbuf,
   return ret;
 }
 
-#if defined PT_GETDSBT || defined PTRACE_GETFDPIC
+#if defined PTRACE_GETFDPIC
 struct target_loadseg
 {
   /* Core address to which the segment is mapped.  */
@@ -5273,23 +5273,6 @@ struct target_loadseg
   Elf32_Word p_memsz;
 };
 
-# if defined PT_GETDSBT
-struct target_loadmap
-{
-  /* Protocol version number, must be zero.  */
-  Elf32_Word version;
-  /* Pointer to the DSBT table, its size, and the DSBT index.  */
-  unsigned *dsbt_table;
-  unsigned dsbt_size, dsbt_index;
-  /* Number of segments in this map.  */
-  Elf32_Word nsegs;
-  /* The actual memory map.  */
-  struct target_loadseg segs[/*nsegs*/];
-};
-#  define LINUX_LOADMAP		PT_GETDSBT
-#  define LINUX_LOADMAP_EXEC	PTRACE_GETDSBT_EXEC
-#  define LINUX_LOADMAP_INTERP	PTRACE_GETDSBT_INTERP
-# else
 struct target_loadmap
 {
   /* Protocol version number, must be zero.  */
@@ -5299,10 +5282,6 @@ struct target_loadmap
   /* The actual memory map.  */
   struct target_loadseg segs[/*nsegs*/];
 };
-#  define LINUX_LOADMAP		PTRACE_GETFDPIC
-#  define LINUX_LOADMAP_EXEC	PTRACE_GETFDPIC_EXEC
-#  define LINUX_LOADMAP_INTERP	PTRACE_GETFDPIC_INTERP
-# endif
 
 static int
 linux_read_loadmap (const char *annex, CORE_ADDR offset,
@@ -5314,13 +5293,13 @@ linux_read_loadmap (const char *annex, CORE_ADDR offset,
   unsigned int actual_length, copy_length;
 
   if (strcmp (annex, "exec") == 0)
-    addr = (int) LINUX_LOADMAP_EXEC;
+    addr = (int) PTRACE_GETFDPIC_EXEC;
   else if (strcmp (annex, "interp") == 0)
-    addr = (int) LINUX_LOADMAP_INTERP;
+    addr = (int) PTRACE_GETFDPIC_INTERP;
   else
     return -1;
 
-  if (ptrace (LINUX_LOADMAP, pid, addr, &data) != 0)
+  if (ptrace (PTRACE_GETFDPIC, pid, addr, &data) != 0)
     return -1;
 
   if (data == NULL)
@@ -5336,9 +5315,7 @@ linux_read_loadmap (const char *annex, CORE_ADDR offset,
   memcpy (myaddr, (char *) data + offset, copy_length);
   return copy_length;
 }
-#else
-# define linux_read_loadmap NULL
-#endif /* defined PT_GETDSBT || defined PTRACE_GETFDPIC */
+#endif /* defined PTRACE_GETFDPIC */
 
 static void
 linux_process_qsupported (const char *query)
@@ -6036,7 +6013,11 @@ static struct target_ops linux_target_ops = {
   NULL,
 #endif
   linux_common_core_of_thread,
+#if defined PTRACE_GETFDPIC
   linux_read_loadmap,
+#else
+  NULL,
+#endif /* defined PTRACE_GETFDPIC */
   linux_process_qsupported,
   linux_supports_tracepoints,
   linux_read_pc,
diff --git a/gdb/solib-dsbt.c b/gdb/solib-dsbt.c
index 4fe24f8..4fd3eca 100644
--- a/gdb/solib-dsbt.c
+++ b/gdb/solib-dsbt.c
@@ -33,6 +33,7 @@
 #include "gdb_bfd.h"
 
 #define GOT_MODULE_OFFSET 4
+#define DT_TIC6X_DSBT_INDEX 0x70000003
 
 /* Flag which indicates whether internal debug messages should be printed.  */
 static unsigned int solib_dsbt_debug = 0;
@@ -62,11 +63,6 @@ struct ext_elf32_dsbt_loadseg
 struct ext_elf32_dsbt_loadmap {
   /* Protocol version number, must be zero.  */
   ext_Elf32_Word version;
-  /* A pointer to the DSBT table; the DSBT size and the index of this
-     module.  */
-  ext_Elf32_Word dsbt_table_ptr;
-  ext_Elf32_Word dsbt_size;
-  ext_Elf32_Word dsbt_index;
   /* Number of segments in this map.  */
   ext_Elf32_Word nsegs;
   /* The actual memory map.  */
@@ -90,10 +86,6 @@ struct int_elf32_dsbt_loadmap
 {
   /* Protocol version number, must be zero.  */
   int version;
-  CORE_ADDR dsbt_table_ptr;
-  /* A pointer to the DSBT table; the DSBT size and the index of this
-     module.  */
-  int dsbt_size, dsbt_index;
   /* Number of segments in this map.  */
   int nsegs;
   /* The actual memory map.  */
@@ -619,6 +611,123 @@ lm_base (void)
   return info->lm_base_cache;
 }
 
+/* Scan for DYNTAG in .dynamic section of ABFD. If DYNTAG is found 1
+   is returned and the corresponding PTR is set.  We only search in
+   the BFD, not in the target's memory.  */
+
+static int
+scan_dyntag_in_bfd (int dyntag, bfd *abfd, CORE_ADDR *ptr)
+{
+  int step, sect_size;
+  long dyn_tag;
+  CORE_ADDR dyn_ptr, dyn_addr;
+  gdb_byte *bufend, *bufstart, *buf;
+  Elf64_External_Dyn *x_dynp_64;
+  struct bfd_section *sect;
+  struct target_section *target_section;
+
+  if (abfd == NULL)
+    return 0;
+
+  if (bfd_get_flavour (abfd) != bfd_target_elf_flavour)
+    return 0;
+
+  /* Make sure the size is sane.  */
+  if (bfd_get_arch_size (abfd) == -1)
+    return 0;
+
+  /* Find the start address of the .dynamic section.  */
+  sect = bfd_get_section_by_name (abfd, ".dynamic");
+  if (sect == NULL)
+    return 0;
+
+  for (target_section = current_target_sections->sections;
+       target_section < current_target_sections->sections_end;
+       target_section++)
+    if (sect == target_section->the_bfd_section)
+      break;
+  if (target_section < current_target_sections->sections_end)
+    dyn_addr = target_section->addr;
+  else
+    {
+      /* ABFD may come from OBJFILE acting only as a symbol file
+	 without being loaded into the target
+	 (see add_symbol_file_command).  This case is such fallback
+	 to the file VMA address without the possibility of having
+	 the section relocated to its actual in-memory address.  */
+
+      dyn_addr = bfd_section_vma (abfd, sect);
+    }
+
+  /* Read in .dynamic from the BFD.  */
+  sect_size = bfd_section_size (abfd, sect);
+  buf = bufstart = alloca (sect_size);
+  if (!bfd_get_section_contents (abfd, sect,
+				 buf, 0, sect_size))
+    return 0;
+
+  /* Iterate over BUF and scan for DYNTAG.  If found, set PTR and
+     return.  */
+  step = sizeof (Elf64_External_Dyn);
+
+  for (bufend = buf + sect_size;
+       buf < bufend;
+       buf += step)
+  {
+    x_dynp_64 = (Elf64_External_Dyn *) buf;
+    dyn_tag = bfd_h_get_64 (abfd, (bfd_byte *) x_dynp_64->d_tag);
+    dyn_ptr = bfd_h_get_64 (abfd, (bfd_byte *) x_dynp_64->d_un.d_ptr);
+
+    if (dyn_tag == DT_NULL)
+      return 0;
+    if (dyn_tag == dyntag)
+      {
+	if (ptr)
+	  {
+	    /* We don't want to read this information from memory.
+	       If a relocation is needed, it should be done
+	       elsewhere.  */
+	    *ptr = dyn_ptr;
+	  }
+	return 1;
+      }
+  }
+
+  return 0;
+}
+
+/* Given a shared library filename, load it up and find
+   out what is its dsbt index.  */
+
+static int
+fetch_solib_dsbt_index (char *filename)
+{
+  unsigned long dsbt_index;
+  CORE_ADDR addr;
+  bfd *solib_bfd = NULL;
+  volatile struct gdb_exception ex;
+
+  if (filename == NULL)
+    return 0;
+
+  /* Open the shared library.  */
+  TRY_CATCH (ex, RETURN_MASK_ALL)
+    {
+      solib_bfd = solib_bfd_open (filename);
+    }
+  if (solib_bfd == NULL)
+    {
+      return 0;
+    }
+
+  /* Fetch the DSBT_INDEX from the shared library file on disk.  */
+  if (scan_dyntag_in_bfd (DT_TIC6X_DSBT_INDEX, solib_bfd, &addr) == 0)
+    return -1;
+
+  bfd_close (solib_bfd);
+
+  return addr;
+}
 
 /* Build a list of `struct so_list' objects describing the shared
    objects currently loaded in the inferior.  This list does not
@@ -661,10 +770,12 @@ dsbt_current_sos (void)
   while (lm_addr)
     {
       struct ext_link_map lm_buf;
-      ext_Elf32_Word indexword;
       CORE_ADDR map_addr;
       int dsbt_index;
       int ret;
+      CORE_ADDR addr;
+      int errcode;
+      char *name_buf = NULL;
 
       if (solib_dsbt_debug)
 	fprintf_unfiltered (gdb_stdlog,
@@ -684,24 +795,26 @@ dsbt_current_sos (void)
 					   sizeof lm_buf.l_addr.map,
 					   byte_order);
 
-      ret = target_read_memory (map_addr + 12, (gdb_byte *) &indexword,
-				sizeof indexword);
-      if (ret)
+      /* Fetch the name.  */
+      addr = extract_unsigned_integer (lm_buf.l_name,
+				       sizeof (lm_buf.l_name),
+				       byte_order);
+      target_read_string (addr, &name_buf, SO_NAME_MAX_PATH_SIZE - 1,
+			  &errcode);
+
+      if (errcode != 0)
+	dsbt_index = 0;
+      else
 	{
-	  warning (_("dsbt_current_sos: Unable to read dsbt index."
-		     "  Shared object chain may be incomplete."));
-	  break;
+	  /* Fetch the DSBT index of this load module.  */
+	  dsbt_index = fetch_solib_dsbt_index (name_buf);
 	}
-      dsbt_index = extract_unsigned_integer (indexword, sizeof indexword,
-					     byte_order);
 
       /* If the DSBT index is zero, then we're looking at the entry
 	 for the main executable.  By convention, we don't include
 	 this in the list of shared objects.  */
       if (dsbt_index != 0)
 	{
-	  int errcode;
-	  char *name_buf;
 	  struct int_elf32_dsbt_loadmap *loadmap;
 	  struct so_list *sop;
 	  CORE_ADDR addr;
@@ -717,12 +830,6 @@ dsbt_current_sos (void)
 	  sop = xcalloc (1, sizeof (struct so_list));
 	  sop->lm_info = xcalloc (1, sizeof (struct lm_info));
 	  sop->lm_info->map = loadmap;
-	  /* Fetch the name.  */
-	  addr = extract_unsigned_integer (lm_buf.l_name,
-					   sizeof (lm_buf.l_name),
-					   byte_order);
-	  target_read_string (addr, &name_buf, SO_NAME_MAX_PATH_SIZE - 1,
-			      &errcode);
 
 	  if (errcode != 0)
 	    warning (_("Can't read pathname for link map entry: %s."),
@@ -744,6 +851,7 @@ dsbt_current_sos (void)
 	}
       else
 	{
+	  xfree (name_buf);
 	  info->main_lm_addr = lm_addr;
 	}
 

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]