* gdb.base/long_long.exp: Accept optional symbol name in <...>
[deliverable/binutils-gdb.git] / gdb / symfile.c
index 396be8f00e3b667726871951a67934e280cb2222..4523b4b98bc74f1379fe9e9fe06e6cddf9210c83 100644 (file)
@@ -1,7 +1,7 @@
 /* Generic symbol file reading for the GNU debugger, GDB.
 
-   Copyright (C) 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998,
-   1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006
+   Copyright (C) 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999,
+   2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007
    Free Software Foundation, Inc.
 
    Contributed by Cygnus Support, using pieces from other GDB modules.
@@ -51,6 +51,8 @@
 #include "block.h"
 #include "observer.h"
 #include "exec.h"
+#include "parser-defs.h"
+#include "varobj.h"
 
 #include <sys/types.h>
 #include <fcntl.h>
@@ -475,8 +477,8 @@ place_section (bfd *abfd, asection *sect, void *obj)
   int done;
   ULONGEST align = ((ULONGEST) 1) << bfd_get_section_alignment (abfd, sect);
 
-  /* We are only interested in loadable sections.  */
-  if ((bfd_get_section_flags (abfd, sect) & SEC_LOAD) == 0)
+  /* We are only interested in allocated sections.  */
+  if ((bfd_get_section_flags (abfd, sect) & SEC_ALLOC) == 0)
     return;
 
   /* If the user specified an offset, honor it.  */
@@ -500,13 +502,8 @@ place_section (bfd *abfd, asection *sect, void *obj)
        if (cur_sec == sect)
          continue;
 
-       /* We can only conflict with loadable sections.  */
-       if ((bfd_get_section_flags (abfd, cur_sec) & SEC_LOAD) == 0)
-         continue;
-
-       /* We do not expect this to happen; just ignore sections in a
-          relocatable file with an assigned VMA.  */
-       if (bfd_section_vma (abfd, cur_sec) != 0)
+       /* We can only conflict with allocated sections.  */
+       if ((bfd_get_section_flags (abfd, cur_sec) & SEC_ALLOC) == 0)
          continue;
 
        /* If the section offset is 0, either the section has not been placed
@@ -579,9 +576,62 @@ default_symfile_offsets (struct objfile *objfile,
   if ((bfd_get_file_flags (objfile->obfd) & (EXEC_P | DYNAMIC)) == 0)
     {
       struct place_section_arg arg;
-      arg.offsets = objfile->section_offsets;
-      arg.lowest = 0;
-      bfd_map_over_sections (objfile->obfd, place_section, &arg);
+      bfd *abfd = objfile->obfd;
+      asection *cur_sec;
+      CORE_ADDR lowest = 0;
+
+      for (cur_sec = abfd->sections; cur_sec != NULL; cur_sec = cur_sec->next)
+       /* We do not expect this to happen; just skip this step if the
+          relocatable file has a section with an assigned VMA.  */
+       if (bfd_section_vma (abfd, cur_sec) != 0)
+         break;
+
+      if (cur_sec == NULL)
+       {
+         CORE_ADDR *offsets = objfile->section_offsets->offsets;
+
+         /* Pick non-overlapping offsets for sections the user did not
+            place explicitly.  */
+         arg.offsets = objfile->section_offsets;
+         arg.lowest = 0;
+         bfd_map_over_sections (objfile->obfd, place_section, &arg);
+
+         /* Correctly filling in the section offsets is not quite
+            enough.  Relocatable files have two properties that
+            (most) shared objects do not:
+
+            - Their debug information will contain relocations.  Some
+            shared libraries do also, but many do not, so this can not
+            be assumed.
+
+            - If there are multiple code sections they will be loaded
+            at different relative addresses in memory than they are
+            in the objfile, since all sections in the file will start
+            at address zero.
+
+            Because GDB has very limited ability to map from an
+            address in debug info to the correct code section,
+            it relies on adding SECT_OFF_TEXT to things which might be
+            code.  If we clear all the section offsets, and set the
+            section VMAs instead, then symfile_relocate_debug_section
+            will return meaningful debug information pointing at the
+            correct sections.
+
+            GDB has too many different data structures for section
+            addresses - a bfd, objfile, and so_list all have section
+            tables, as does exec_ops.  Some of these could probably
+            be eliminated.  */
+
+         for (cur_sec = abfd->sections; cur_sec != NULL;
+              cur_sec = cur_sec->next)
+           {
+             if ((bfd_get_section_flags (abfd, cur_sec) & SEC_ALLOC) == 0)
+               continue;
+
+             bfd_set_section_vma (abfd, cur_sec, offsets[cur_sec->index]);
+             offsets[cur_sec->index] = 0;
+           }
+       }
     }
 
   /* Remember the bfd indexes for the .text, .data, .bss and
@@ -1155,7 +1205,7 @@ separate_debug_file_exists (const char *name, unsigned long crc)
   return crc == file_crc;
 }
 
-static char *debug_file_directory = NULL;
+char *debug_file_directory = NULL;
 static void
 show_debug_file_directory (struct ui_file *file, int from_tty,
                           struct cmd_list_element *c, const char *value)
@@ -1177,6 +1227,7 @@ find_separate_debug_file (struct objfile *objfile)
   char *dir;
   char *debugfile;
   char *name_copy;
+  char *canon_name;
   bfd_size_type debuglink_size;
   unsigned long crc32;
   int i;
@@ -1244,6 +1295,30 @@ find_separate_debug_file (struct objfile *objfile)
       return xstrdup (debugfile);
     }
 
+  /* If the file is in the sysroot, try using its base path in the
+     global debugfile directory.  */
+  canon_name = lrealpath (dir);
+  if (canon_name
+      && strncmp (canon_name, gdb_sysroot, strlen (gdb_sysroot)) == 0
+      && IS_DIR_SEPARATOR (canon_name[strlen (gdb_sysroot)]))
+    {
+      strcpy (debugfile, debug_file_directory);
+      strcat (debugfile, canon_name + strlen (gdb_sysroot));
+      strcat (debugfile, "/");
+      strcat (debugfile, basename);
+
+      if (separate_debug_file_exists (debugfile, crc32))
+       {
+         xfree (canon_name);
+         xfree (basename);
+         xfree (dir);
+         return xstrdup (debugfile);
+       }
+    }
+  
+  if (canon_name)
+    xfree (canon_name);
+
   xfree (basename);
   xfree (dir);
   return NULL;
@@ -1536,114 +1611,169 @@ add_section_size_callback (bfd *abfd, asection *asec, void *data)
 /* Opaque data for load_section_callback.  */
 struct load_section_data {
   unsigned long load_offset;
+  struct load_progress_data *progress_data;
+  VEC(memory_write_request_s) *requests;
+};
+
+/* Opaque data for load_progress.  */
+struct load_progress_data {
+  /* Cumulative data.  */
   unsigned long write_count;
   unsigned long data_count;
   bfd_size_type total_size;
 };
 
+/* Opaque data for load_progress for a single section.  */
+struct load_progress_section_data {
+  struct load_progress_data *cumulative;
+
+  /* Per-section data.  */
+  const char *section_name;
+  ULONGEST section_sent;
+  ULONGEST section_size;
+  CORE_ADDR lma;
+  gdb_byte *buffer;
+};
+
+/* Target write callback routine for progress reporting.  */
+
+static void
+load_progress (ULONGEST bytes, void *untyped_arg)
+{
+  struct load_progress_section_data *args = untyped_arg;
+  struct load_progress_data *totals;
+
+  if (args == NULL)
+    /* Writing padding data.  No easy way to get at the cumulative
+       stats, so just ignore this.  */
+    return;
+
+  totals = args->cumulative;
+
+  if (bytes == 0 && args->section_sent == 0)
+    {
+      /* The write is just starting.  Let the user know we've started
+        this section.  */
+      ui_out_message (uiout, 0, "Loading section %s, size 0x%s lma 0x%s\n",
+                     args->section_name, paddr_nz (args->section_size),
+                     paddr_nz (args->lma));
+      return;
+    }
+
+  if (validate_download)
+    {
+      /* Broken memories and broken monitors manifest themselves here
+        when bring new computers to life.  This doubles already slow
+        downloads.  */
+      /* NOTE: cagney/1999-10-18: A more efficient implementation
+        might add a verify_memory() method to the target vector and
+        then use that.  remote.c could implement that method using
+        the ``qCRC'' packet.  */
+      gdb_byte *check = xmalloc (bytes);
+      struct cleanup *verify_cleanups = make_cleanup (xfree, check);
+
+      if (target_read_memory (args->lma, check, bytes) != 0)
+       error (_("Download verify read failed at 0x%s"),
+              paddr (args->lma));
+      if (memcmp (args->buffer, check, bytes) != 0)
+       error (_("Download verify compare failed at 0x%s"),
+              paddr (args->lma));
+      do_cleanups (verify_cleanups);
+    }
+  totals->data_count += bytes;
+  args->lma += bytes;
+  args->buffer += bytes;
+  totals->write_count += 1;
+  args->section_sent += bytes;
+  if (quit_flag
+      || (deprecated_ui_load_progress_hook != NULL
+         && deprecated_ui_load_progress_hook (args->section_name,
+                                              args->section_sent)))
+    error (_("Canceled the download"));
+
+  if (deprecated_show_load_progress != NULL)
+    deprecated_show_load_progress (args->section_name,
+                                  args->section_sent,
+                                  args->section_size,
+                                  totals->data_count,
+                                  totals->total_size);
+}
+
 /* Callback service function for generic_load (bfd_map_over_sections).  */
 
 static void
 load_section_callback (bfd *abfd, asection *asec, void *data)
 {
+  struct memory_write_request *new_request;
   struct load_section_data *args = data;
+  struct load_progress_section_data *section_data;
+  bfd_size_type size = bfd_get_section_size (asec);
+  gdb_byte *buffer;
+  const char *sect_name = bfd_get_section_name (abfd, asec);
 
-  if (bfd_get_section_flags (abfd, asec) & SEC_LOAD)
-    {
-      bfd_size_type size = bfd_get_section_size (asec);
-      if (size > 0)
-       {
-         gdb_byte *buffer;
-         struct cleanup *old_chain;
-         CORE_ADDR lma = bfd_section_lma (abfd, asec) + args->load_offset;
-         bfd_size_type block_size;
-         int err;
-         const char *sect_name = bfd_get_section_name (abfd, asec);
-         bfd_size_type sent;
-
-         buffer = xmalloc (size);
-         old_chain = make_cleanup (xfree, buffer);
-
-         /* Is this really necessary?  I guess it gives the user something
-            to look at during a long download.  */
-         ui_out_message (uiout, 0, "Loading section %s, size 0x%s lma 0x%s\n",
-                         sect_name, paddr_nz (size), paddr_nz (lma));
-
-         bfd_get_section_contents (abfd, asec, buffer, 0, size);
-
-         sent = 0;
-         do
-           {
-             int len;
-             bfd_size_type this_transfer = size - sent;
-
-             len = target_write_memory_partial (lma, buffer,
-                                                this_transfer, &err);
-             if (err)
-               break;
-             if (validate_download)
-               {
-                 /* Broken memories and broken monitors manifest
-                    themselves here when bring new computers to
-                    life.  This doubles already slow downloads.  */
-                 /* NOTE: cagney/1999-10-18: A more efficient
-                    implementation might add a verify_memory()
-                    method to the target vector and then use
-                    that.  remote.c could implement that method
-                    using the ``qCRC'' packet.  */
-                 gdb_byte *check = xmalloc (len);
-                 struct cleanup *verify_cleanups =
-                   make_cleanup (xfree, check);
-
-                 if (target_read_memory (lma, check, len) != 0)
-                   error (_("Download verify read failed at 0x%s"),
-                          paddr (lma));
-                 if (memcmp (buffer, check, len) != 0)
-                   error (_("Download verify compare failed at 0x%s"),
-                          paddr (lma));
-                 do_cleanups (verify_cleanups);
-               }
-             args->data_count += len;
-             lma += len;
-             buffer += len;
-             args->write_count += 1;
-             sent += len;
-             if (quit_flag
-                 || (deprecated_ui_load_progress_hook != NULL
-                     && deprecated_ui_load_progress_hook (sect_name, sent)))
-               error (_("Canceled the download"));
-
-             if (deprecated_show_load_progress != NULL)
-               deprecated_show_load_progress (sect_name, sent, size,
-                                              args->data_count,
-                                              args->total_size);
-           }
-         while (sent < size);
+  if ((bfd_get_section_flags (abfd, asec) & SEC_LOAD) == 0)
+    return;
+
+  if (size == 0)
+    return;
 
-         if (err != 0)
-           error (_("Memory access error while loading section %s."), sect_name);
+  new_request = VEC_safe_push (memory_write_request_s,
+                              args->requests, NULL);
+  memset (new_request, 0, sizeof (struct memory_write_request));
+  section_data = xcalloc (1, sizeof (struct load_progress_section_data));
+  new_request->begin = bfd_section_lma (abfd, asec) + args->load_offset;
+  new_request->end = new_request->begin + size; /* FIXME Should size be in instead?  */
+  new_request->data = xmalloc (size);
+  new_request->baton = section_data;
 
-         do_cleanups (old_chain);
-       }
+  buffer = new_request->data;
+
+  section_data->cumulative = args->progress_data;
+  section_data->section_name = sect_name;
+  section_data->section_size = size;
+  section_data->lma = new_request->begin;
+  section_data->buffer = buffer;
+
+  bfd_get_section_contents (abfd, asec, buffer, 0, size);
+}
+
+/* Clean up an entire memory request vector, including load
+   data and progress records.  */
+
+static void
+clear_memory_write_data (void *arg)
+{
+  VEC(memory_write_request_s) **vec_p = arg;
+  VEC(memory_write_request_s) *vec = *vec_p;
+  int i;
+  struct memory_write_request *mr;
+
+  for (i = 0; VEC_iterate (memory_write_request_s, vec, i, mr); ++i)
+    {
+      xfree (mr->data);
+      xfree (mr->baton);
     }
+  VEC_free (memory_write_request_s, vec);
 }
 
 void
 generic_load (char *args, int from_tty)
 {
-  asection *s;
   bfd *loadfile_bfd;
   struct timeval start_time, end_time;
   char *filename;
   struct cleanup *old_cleanups = make_cleanup (null_cleanup, 0);
   struct load_section_data cbdata;
+  struct load_progress_data total_progress;
+
   CORE_ADDR entry;
   char **argv;
 
-  cbdata.load_offset = 0;      /* Offset to add to vma for each section. */
-  cbdata.write_count = 0;      /* Number of writes needed. */
-  cbdata.data_count = 0;       /* Number of bytes written to target memory. */
-  cbdata.total_size = 0;       /* Total size of all bfd sectors. */
+  memset (&cbdata, 0, sizeof (cbdata));
+  memset (&total_progress, 0, sizeof (total_progress));
+  cbdata.progress_data = &total_progress;
+
+  make_cleanup (clear_memory_write_data, &cbdata.requests);
 
   argv = buildargv (args);
 
@@ -1690,11 +1820,15 @@ generic_load (char *args, int from_tty)
     }
 
   bfd_map_over_sections (loadfile_bfd, add_section_size_callback,
-                        (void *) &cbdata.total_size);
+                        (void *) &total_progress.total_size);
+
+  bfd_map_over_sections (loadfile_bfd, load_section_callback, &cbdata);
 
   gettimeofday (&start_time, NULL);
 
-  bfd_map_over_sections (loadfile_bfd, load_section_callback, &cbdata);
+  if (target_write_memory_blocks (cbdata.requests, flash_discard,
+                                 load_progress) != 0)
+    error (_("Load failed"));
 
   gettimeofday (&end_time, NULL);
 
@@ -1702,7 +1836,7 @@ generic_load (char *args, int from_tty)
   ui_out_text (uiout, "Start address ");
   ui_out_field_fmt (uiout, "address", "0x%s", paddr_nz (entry));
   ui_out_text (uiout, ", load size ");
-  ui_out_field_fmt (uiout, "load-size", "%lu", cbdata.data_count);
+  ui_out_field_fmt (uiout, "load-size", "%lu", total_progress.data_count);
   ui_out_text (uiout, "\n");
   /* We were doing this in remote-mips.c, I suspect it is right
      for other targets too.  */
@@ -1714,8 +1848,9 @@ generic_load (char *args, int from_tty)
      file is loaded in.  Some targets do (e.g., remote-vx.c) but
      others don't (or didn't - perhaps they have all been deleted).  */
 
-  print_transfer_performance (gdb_stdout, cbdata.data_count,
-                             cbdata.write_count, &start_time, &end_time);
+  print_transfer_performance (gdb_stdout, total_progress.data_count,
+                             total_progress.write_count,
+                             &start_time, &end_time);
 
   do_cleanups (old_cleanups);
 }
@@ -1841,7 +1976,7 @@ add_symbol_file_command (char *args, int from_tty)
                to load the program. */
            sect_opts[section_index].name = ".text";
            sect_opts[section_index].value = arg;
-           if (++section_index > num_sect_opts)
+           if (++section_index >= num_sect_opts)
              {
                num_sect_opts *= 2;
                sect_opts = ((struct sect_opt *)
@@ -1877,7 +2012,7 @@ add_symbol_file_command (char *args, int from_tty)
                    {
                      sect_opts[section_index].value = arg;
                      expecting_sec_addr = 0;
-                     if (++section_index > num_sect_opts)
+                     if (++section_index >= num_sect_opts)
                        {
                          num_sect_opts *= 2;
                          sect_opts = ((struct sect_opt *)
@@ -2420,14 +2555,6 @@ allocate_symtab (char *filename, struct objfile *objfile)
   symtab->next = objfile->symtabs;
   objfile->symtabs = symtab;
 
-  /* FIXME: This should go away.  It is only defined for the Z8000,
-     and the Z8000 definition of this macro doesn't have anything to
-     do with the now-nonexistent EXTRA_SYMTAB_INFO macro, it's just
-     here for convenience.  */
-#ifdef INIT_EXTRA_SYMTAB_INFO
-  INIT_EXTRA_SYMTAB_INFO (symtab);
-#endif
-
   return (symtab);
 }
 
@@ -2518,6 +2645,16 @@ clear_symtab_users (void)
   clear_pc_function_cache ();
   if (deprecated_target_new_objfile_hook)
     deprecated_target_new_objfile_hook (NULL);
+
+  /* Clear globals which might have pointed into a removed objfile.
+     FIXME: It's not clear which of these are supposed to persist
+     between expressions and which ought to be reset each time.  */
+  expression_context_block = NULL;
+  innermost_block = NULL;
+
+  /* Varobj may refer to old symbols, perform a cleanup.  */
+  varobj_invalidate ();
+
 }
 
 static void
@@ -3790,7 +3927,6 @@ Usage: set extension-language .foo bar"),
   add_info ("extensions", info_ext_lang_command,
            _("All filename extensions associated with a source language."));
 
-  debug_file_directory = xstrdup (DEBUGDIR);
   add_setshow_optional_filename_cmd ("debug-file-directory", class_support,
                                     &debug_file_directory, _("\
 Set the directory where separate debug symbols are searched for."), _("\
This page took 0.028783 seconds and 4 git commands to generate.