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]

[patch 12/15] PIE: Support loading PIEs from core files


Hi,

scan_dyntag() had to be made aware ABFD can be relocated despite it has only
a BFD parameter while BFD itself represents only the on-disk unrelocated file.

One general problem is that each `struct objfile' associates BFD and its
loaded symbols as separate_debug_objfile.  Contrary to that exec_bfd does not
automatically have its objfile, it can have its symbol file at symfile_objfile
but it does not have to.  You cannot arbitrarily change symbol files to
existing shared libraries as you can to exec_bfd.  As discussed with Tom
Tromey on #gdb it may be because on embedded targets one is more interested in
independent exec_bfd and its symbol file.  But on real embedded targets one
does not deal with shared libraries.

Another issue is whether `struct objfile *' passed between functions should be:
(A) caller must pass always the main binary file
(B) caller must prefer to pass the separate debug info file if available
(C) callee must accept both variants

Currently the GDB code mostly follows (A) IMO so fixed
lookup_objfile_from_block for it and assertion-checked it in
elf_lookup_lib_symbol.  Sure one could also choose (C) for
elf_lookup_lib_symbol which would be more regression-safe.

Due to the issues above (as exec_bfd is not an objfile) elf_lookup_lib_symbol
accepts the debug info file for exec_bfd but for other objfiles it requires
the binary objfile part (and not the separate debug info part).

Still even for the main executable with separate debug info file there will be
BFD exec_bfd, OBJFILE symfile_objfile and even OBJFILE
symfile_objfile->separate_debug_objfile and elf_lookup_lib_symbol still
requires only exactly symfile_objfile now so it may make sense it the way this
patch implements it.

The testcase uses the native (kernel) core dumper of the target system as
using gcore may just hide some incompatibilities with real world core files.
It is true gcore is not tested now.


Thanks,
Jan


gdb/
	* solib-svr4.c (scan_dyntag): Remove variable dyn_addr.  New variable
	target_section.  Find SECT in current_target_sections, gdb_assert it.
	(elf_lookup_lib_symbol): Pass the binary file if given symfile_objfile.
	New variable abfd.
	* symtab.c (lookup_objfile_from_block): Return the binary file instead
	of separate debug info file.
    
gdb/testsuite/
	* gdb.base/break-interp.exp (test_core): New proc.
	(test_ld): Call it.

--- a/gdb/solib-svr4.c
+++ b/gdb/solib-svr4.c
@@ -568,11 +568,12 @@ scan_dyntag (int dyntag, bfd *abfd, CORE_ADDR *ptr)
 {
   int arch_size, step, sect_size;
   long dyn_tag;
-  CORE_ADDR dyn_ptr, dyn_addr;
+  CORE_ADDR dyn_ptr;
   gdb_byte *bufend, *bufstart, *buf;
   Elf32_External_Dyn *x_dynp_32;
   Elf64_External_Dyn *x_dynp_64;
   struct bfd_section *sect;
+  struct target_section *target_section;
 
   if (abfd == NULL)
     return 0;
@@ -588,7 +589,13 @@ scan_dyntag (int dyntag, bfd *abfd, CORE_ADDR *ptr)
   sect = bfd_get_section_by_name (abfd, ".dynamic");
   if (sect == NULL)
     return 0;
-  dyn_addr = bfd_section_vma (abfd, sect);
+
+  for (target_section = current_target_sections->sections;
+       target_section < current_target_sections->sections_end;
+       target_section++)
+    if (sect == target_section->the_bfd_section)
+      break;
+  gdb_assert (target_section < current_target_sections->sections_end);
 
   /* Read in .dynamic from the BFD.  We will get the actual value
      from memory later.  */
@@ -630,7 +637,7 @@ scan_dyntag (int dyntag, bfd *abfd, CORE_ADDR *ptr)
 	     CORE_ADDR ptr_addr;
 
 	     ptr_type = builtin_type (target_gdbarch)->builtin_data_ptr;
-	     ptr_addr = dyn_addr + (buf - bufstart) + arch_size / 8;
+	     ptr_addr = target_section->addr + (buf - bufstart) + arch_size / 8;
 	     if (target_read_memory (ptr_addr, ptr_buf, arch_size / 8) == 0)
 	       dyn_ptr = extract_typed_address (ptr_buf, ptr_type);
 	     *ptr = dyn_ptr;
@@ -1901,8 +1908,19 @@ elf_lookup_lib_symbol (const struct objfile *objfile,
 		       const char *linkage_name,
 		       const domain_enum domain)
 {
-  if (objfile->obfd == NULL
-     || scan_dyntag (DT_SYMBOLIC, objfile->obfd, NULL) != 1)
+  bfd *abfd;
+
+  if (objfile == symfile_objfile)
+    abfd = exec_bfd;
+  else
+    {
+      /* OBJFILE should have been passed as the non-debug one.  */
+      gdb_assert (objfile->separate_debug_objfile_backlink == NULL);
+
+      abfd = objfile->obfd;
+    }
+
+  if (abfd == NULL || scan_dyntag (DT_SYMBOLIC, abfd, NULL) != 1)
     return NULL;
 
   return lookup_global_symbol_from_objfile
--- a/gdb/symtab.c
+++ b/gdb/symtab.c
@@ -1408,7 +1408,12 @@ lookup_objfile_from_block (const struct block *block)
   /* Go through SYMTABS.  */
   ALL_SYMTABS (obj, s)
     if (block == BLOCKVECTOR_BLOCK (BLOCKVECTOR (s), GLOBAL_BLOCK))
-      return obj;
+      {
+	if (obj->separate_debug_objfile_backlink)
+	  obj = obj->separate_debug_objfile_backlink;
+
+	return obj;
+      }
 
   return NULL;
 }
--- a/gdb/testsuite/gdb.base/break-interp.exp
+++ b/gdb/testsuite/gdb.base/break-interp.exp
@@ -237,6 +237,27 @@ proc reach {func command} {
     }
 }
 
+proc test_core {file} {
+    global srcdir subdir gdb_prompt
+
+    set corefile [core_find $file]
+    if {$corefile == ""} {
+	return
+    }
+
+    gdb_exit
+    gdb_start
+    # Clear it to never find any separate debug infos in $debug_root.
+    gdb_test "set debug-file-directory" "" "set debug-file-directory for core"
+    gdb_reinitialize_dir $srcdir/$subdir
+    gdb_load $file
+
+    # Do not check the binary filename as it may be truncated.
+    gdb_test "core-file $corefile" "Core was generated by .*\r\n#0 .*" "core loaded"
+
+    gdb_test "bt" "#\[0-9\]+ +\[^\r\n\]*\\mlibfunc\\M\[^\r\n\]*\r\n#\[0-9\]+ +\[^\r\n\]*\\mmain\\M.*" "core main bt"
+}
+
 proc test_ld {file ifmain trynosym} {
     global srcdir subdir gdb_prompt
 
@@ -259,6 +280,8 @@ proc test_ld {file ifmain trynosym} {
 	reach "libfunc" continue
 
 	gdb_test "bt" "#0 +\[^\r\n\]*\\mlibfunc\\M\[^\r\n\]*\r\n#1 +\[^\r\n\]*\\mmain\\M.*" "main bt"
+
+	test_core $file
     }
 
     if !$trynosym {


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