Replace ../include/wait.h with gdb_wait.h.
[deliverable/binutils-gdb.git] / gdb / symfile.c
index 40105b44d14a98287034db6ef0171f7c20bf6366..5b2a2ff56579a8123e0b70f6ea22ece686c1d3b0 100644 (file)
@@ -1,6 +1,5 @@
 /* Generic symbol file reading for the GNU debugger, GDB.
-   Copyright 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1998
-   Free Software Foundation, Inc.
+   Copyright 1990-1996, 1998, 2000 Free Software Foundation, Inc.
    Contributed by Cygnus Support, using pieces from other GDB modules.
 
    This file is part of GDB.
@@ -63,9 +62,15 @@ extern int hp_cxx_exception_support_initialized;
                               } while (0)
 #endif
 
-int (*ui_load_progress_hook) PARAMS ((char *, unsigned long));
+int (*ui_load_progress_hook) (const char *section, unsigned long num);
+void (*show_load_progress) (const char *section,
+                           unsigned long section_sent, 
+                           unsigned long section_size, 
+                           unsigned long total_sent, 
+                           unsigned long total_size);
 void (*pre_add_symbol_hook) PARAMS ((char *));
 void (*post_add_symbol_hook) PARAMS ((void));
+void (*target_new_objfile_hook) PARAMS ((struct objfile *));
 
 /* Global variables owned by this file */
 int readnow_symbol_files;      /* Read full symbols immediately */
@@ -820,24 +825,16 @@ new_symfile_objfile (objfile, mainline, verbo)
    as dynamically loaded code.  If !mainline, ADDR is the address
    where the text segment was loaded.
 
-   USER_LOADED is TRUE if the add-symbol-file command was how this
-   symbol file came to be processed.
-
-   IS_SOLIB is TRUE if this symbol file represents a solib, as discovered
-   by the target's implementation of the solib package.
-
    Upon success, returns a pointer to the objfile that was added.
    Upon failure, jumps back to command level (never returns). */
 
 struct objfile *
-symbol_file_add (name, from_tty, addrs, mainline, flags, user_loaded, is_solib)
+symbol_file_add (name, from_tty, addrs, mainline, flags)
      char *name;
      int from_tty;
      struct section_addr_info *addrs;
      int mainline;
      int flags;
-     int user_loaded;
-     int is_solib;
 {
   struct objfile *objfile;
   struct partial_symtab *psymtab;
@@ -854,7 +851,7 @@ symbol_file_add (name, from_tty, addrs, mainline, flags, user_loaded, is_solib)
       && !query ("Load new symbol table from \"%s\"? ", name))
     error ("Not confirmed.");
 
-  objfile = allocate_objfile (abfd, flags & OBJF_MAPPED, user_loaded, is_solib);
+  objfile = allocate_objfile (abfd, flags);
 
   /* If the objfile uses a mapped symbol file, and we have a psymtab for
      it, then skip reading any symbols at this time. */
@@ -928,7 +925,8 @@ symbol_file_add (name, from_tty, addrs, mainline, flags, user_loaded, is_solib)
 
   new_symfile_objfile (objfile, mainline, from_tty);
 
-  target_new_objfile (objfile);
+  if (target_new_objfile_hook)
+    target_new_objfile_hook (objfile);
 
   return (objfile);
 }
@@ -952,7 +950,7 @@ symbol_file_command (args, from_tty)
   char *name = NULL;
   CORE_ADDR text_relocation = 0;       /* text_relocation */
   struct cleanup *cleanups;
-  int flags = 0;
+  int flags = OBJF_USERLOADED;
 
   dont_repeat ();
 
@@ -1023,8 +1021,7 @@ symbol_file_command (args, from_tty)
                return;
              else if (text_relocation == (CORE_ADDR) -1)
                {
-                 symbol_file_add (name, from_tty, NULL,
-                                  1, flags, 1, 0);
+                 symbol_file_add (name, from_tty, NULL, 1, flags);
 #ifdef HPUXHPPA
                  RESET_HP_UX_GLOBALS ();
 #endif
@@ -1034,8 +1031,7 @@ symbol_file_command (args, from_tty)
                  struct section_addr_info section_addrs;
                  memset (&section_addrs, 0, sizeof (section_addrs));
                  section_addrs.text_addr = (CORE_ADDR) text_relocation;
-                 symbol_file_add (name, from_tty, &section_addrs,
-                                  0, flags, 1, 0);
+                 symbol_file_add (name, from_tty, &section_addrs, 0, flags);
                }
 
              /* Getting new symbols may change our opinion about what is
@@ -1217,42 +1213,54 @@ load_command (arg, from_tty)
    to worry about finding it, and (b) On VMS, fork() is very slow and so
    we don't want to run a subprocess.  On the other hand, I'm not sure how
    performance compares.  */
-#define GENERIC_LOAD_CHUNK 256
-#define VALIDATE_DOWNLOAD 0
+
+static int download_write_size = 512;
+static int validate_download = 0;
+
 void
-generic_load (filename, from_tty)
-     char *filename;
-     int from_tty;
+generic_load (char *args, int from_tty)
 {
-  struct cleanup *old_cleanups;
   asection *s;
   bfd *loadfile_bfd;
   time_t start_time, end_time; /* Start and end times of download */
   unsigned long data_count = 0;        /* Number of bytes transferred to memory */
-  int n;
-  unsigned long load_offset = 0;       /* offset to add to vma for each section */
-  char buf[GENERIC_LOAD_CHUNK + 8];
-#if VALIDATE_DOWNLOAD
-  char verify_buffer[GENERIC_LOAD_CHUNK + 8];
-#endif
-
-  /* enable user to specify address for downloading as 2nd arg to load */
-  n = sscanf (filename, "%s 0x%lx", buf, &load_offset);
-  if (n > 1)
-    filename = buf;
+  unsigned long write_count = 0;       /* Number of writes needed. */
+  unsigned long load_offset;   /* offset to add to vma for each section */
+  char *filename;
+  struct cleanup *old_cleanups;
+  char *offptr;
+  CORE_ADDR total_size = 0;
+  CORE_ADDR total_sent = 0;
+
+  /* Parse the input argument - the user can specify a load offset as
+     a second argument. */
+  filename = xmalloc (strlen (args) + 1);
+  old_cleanups = make_cleanup (free, filename);
+  strcpy (filename, args);
+  offptr = strchr (filename, ' ');
+  if (offptr != NULL)
+    {
+      char *endptr;
+      load_offset = strtoul (offptr, &endptr, 0);
+      if (offptr == endptr)
+       error ("Invalid download offset:%s\n", offptr);
+      *offptr = '\0';
+    }
   else
     load_offset = 0;
 
+  /* Open the file for loading. */
   loadfile_bfd = bfd_openr (filename, gnutarget);
   if (loadfile_bfd == NULL)
     {
       perror_with_name (filename);
       return;
     }
+
   /* FIXME: should be checking for errors from bfd_close (for one thing,
      on error it does not free all the storage associated with the
      bfd).  */
-  old_cleanups = make_cleanup ((make_cleanup_func) bfd_close, loadfile_bfd);
+  make_cleanup ((make_cleanup_func) bfd_close, loadfile_bfd);
 
   if (!bfd_check_format (loadfile_bfd, bfd_object))
     {
@@ -1260,78 +1268,97 @@ generic_load (filename, from_tty)
             bfd_errmsg (bfd_get_error ()));
     }
 
+  for (s = loadfile_bfd->sections; s; s = s->next)
+    if (s->flags & SEC_LOAD)
+      total_size += bfd_get_section_size_before_reloc (s);
+
   start_time = time (NULL);
 
   for (s = loadfile_bfd->sections; s; s = s->next)
     {
       if (s->flags & SEC_LOAD)
        {
-         bfd_size_type size;
-
-         size = bfd_get_section_size_before_reloc (s);
+         CORE_ADDR size = bfd_get_section_size_before_reloc (s);
          if (size > 0)
            {
              char *buffer;
              struct cleanup *old_chain;
-             bfd_vma lma;
-             unsigned long l = size;
+             CORE_ADDR lma = s->lma + load_offset;
+             CORE_ADDR block_size;
              int err;
-             char *sect;
-             unsigned long sent;
-             unsigned long len;
+             const char *sect_name = bfd_get_section_name (loadfile_bfd, s);
+             CORE_ADDR sent;
 
-             l = l > GENERIC_LOAD_CHUNK ? GENERIC_LOAD_CHUNK : l;
+             if (download_write_size > 0 && size > download_write_size)
+               block_size = download_write_size;
+             else
+               block_size = size;
 
              buffer = xmalloc (size);
              old_chain = make_cleanup (free, buffer);
 
-             lma = s->lma;
-             lma += load_offset;
-
              /* Is this really necessary?  I guess it gives the user something
                 to look at during a long download.  */
-             printf_filtered ("Loading section %s, size 0x%lx lma ",
-                              bfd_get_section_name (loadfile_bfd, s),
-                              (unsigned long) size);
-             print_address_numeric (lma, 1, gdb_stdout);
-             printf_filtered ("\n");
+#ifdef UI_OUT
+             ui_out_message (uiout, 0, "Loading section %s, size 0x%s lma 0x%s\n",
+                          sect_name, paddr_nz (size), paddr_nz (lma));
+#else
+             fprintf_unfiltered (gdb_stdout,
+                                 "Loading section %s, size 0x%s lma 0x%s\n",
+                                 sect_name, paddr_nz (size), paddr_nz (lma));
+#endif
 
              bfd_get_section_contents (loadfile_bfd, s, buffer, 0, size);
 
-             sect = (char *) bfd_get_section_name (loadfile_bfd, s);
              sent = 0;
              do
                {
-                 len = (size - sent) < l ? (size - sent) : l;
-                 sent += len;
-                 err = target_write_memory (lma, buffer, len);
-                 if (ui_load_progress_hook)
-                   if (ui_load_progress_hook (sect, sent))
-                     error ("Canceled the download");
-#if VALIDATE_DOWNLOAD
-                 /* Broken memories and broken monitors manifest themselves
-                    here when bring new computers to life.
-                    This doubles already slow downloads.
-                  */
+                 CORE_ADDR len;
+                 CORE_ADDR this_transfer = size - sent;
+                 if (this_transfer >= block_size)
+                   this_transfer = block_size;
+                 len = target_write_memory_partial (lma, buffer,
+                                                    this_transfer, &err);
                  if (err)
                    break;
-                 {
-                   target_read_memory (lma, verify_buffer, len);
-                   if (0 != bcmp (buffer, verify_buffer, len))
-                     error ("Download verify failed at %08x",
-                            (unsigned long) lma);
-                 }
-
-#endif
+                 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.  */
+                     char *check = xmalloc (len);
+                     struct cleanup *verify_cleanups = make_cleanup (free, 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);
+                   }
                  data_count += len;
                  lma += len;
                  buffer += len;
-               }               /* od */
-             while (err == 0 && sent < size);
+                 write_count += 1;
+                 sent += len;
+                 total_sent += len;
+                 if (quit_flag
+                     || (ui_load_progress_hook != NULL
+                         && ui_load_progress_hook (sect_name, sent)))
+                   error ("Canceled the download");
+
+                 if (show_load_progress != NULL)
+                   show_load_progress (sect_name, sent, size, total_sent, total_size);
+               }
+             while (sent < size);
 
              if (err != 0)
-               error ("Memory access error while loading section %s.",
-                      bfd_get_section_name (loadfile_bfd, s));
+               error ("Memory access error while loading section %s.", sect_name);
 
              do_cleanups (old_chain);
            }
@@ -1340,9 +1367,20 @@ generic_load (filename, from_tty)
 
   end_time = time (NULL);
   {
-    unsigned long entry;
+    CORE_ADDR entry;
     entry = bfd_get_start_address (loadfile_bfd);
-    printf_filtered ("Start address 0x%lx , load size %ld\n", entry, data_count);
+#ifdef UI_OUT
+   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", "%ld" , data_count);
+   ui_out_text (uiout, "\n");
+
+#else
+    fprintf_unfiltered (gdb_stdout,
+                       "Start address 0x%s , load size %ld\n",
+                       paddr_nz (entry), data_count);
+#endif
     /* We were doing this in remote-mips.c, I suspect it is right
        for other targets too.  */
     write_pc (entry);
@@ -1354,25 +1392,62 @@ generic_load (filename, from_tty)
      loaded in.  remote-nindy.c had no call to symbol_file_add, but remote-vx.c
      does.  */
 
-  report_transfer_performance (data_count, start_time, end_time);
+  print_transfer_performance (gdb_stdout, data_count, write_count,
+                             end_time - start_time);
 
   do_cleanups (old_cleanups);
 }
 
 /* Report how fast the transfer went. */
 
+/* DEPRECATED: cagney/1999-10-18: report_transfer_performance is being
+   replaced by print_transfer_performance (with a very different
+   function signature). */
+
 void
 report_transfer_performance (data_count, start_time, end_time)
      unsigned long data_count;
      time_t start_time, end_time;
 {
-  printf_filtered ("Transfer rate: ");
-  if (end_time != start_time)
-    printf_filtered ("%ld bits/sec",
-                    (data_count * 8) / (end_time - start_time));
+  print_transfer_performance (gdb_stdout, data_count, end_time - start_time, 0);
+}
+
+void
+print_transfer_performance (struct ui_file *stream,
+                           unsigned long data_count,
+                           unsigned long write_count,
+                           unsigned long time_count)
+{
+#ifdef UI_OUT
+  ui_out_text (uiout, "Transfer rate: ");
+  if (time_count > 0)
+    {
+      ui_out_field_fmt (uiout, "transfer-rate", "%ld", 
+                       (data_count * 8) / time_count);
+      ui_out_text (uiout, " bits/sec");
+    }
   else
-    printf_filtered ("%ld bits in <1 sec", (data_count * 8));
-  printf_filtered (".\n");
+    {
+      ui_out_field_fmt (uiout, "transferred-bits", "%ld", (data_count * 8));
+      ui_out_text (uiout, " bits in <1 sec");    
+    }
+  if (write_count > 0)
+    {
+      ui_out_text (uiout, ", ");
+      ui_out_field_fmt (uiout, "write-rate", "%ld", data_count / write_count);
+      ui_out_text (uiout, " bytes/write");
+    }
+  ui_out_text (uiout, ".\n");
+#else
+  fprintf_unfiltered (stream, "Transfer rate: ");
+  if (time_count > 0)
+    fprintf_unfiltered (stream, "%ld bits/sec", (data_count * 8) / time_count);
+  else
+    fprintf_unfiltered (stream, "%ld bits in <1 sec", (data_count * 8));
+  if (write_count > 0)
+    fprintf_unfiltered (stream, ", %ld bytes/write", data_count / write_count);
+  fprintf_unfiltered (stream, ".\n");
+#endif
 }
 
 /* This function allows the addition of incrementally linked object files.
@@ -1386,7 +1461,7 @@ add_symbol_file_command (args, from_tty)
 {
   char *name = NULL;
   CORE_ADDR text_addr;
-  int flags = 0;
+  int flags = OBJF_USERLOADED;
   char *arg;
   int expecting_option = 0;
   int option_index = 0;
@@ -1410,7 +1485,7 @@ add_symbol_file_command (args, from_tty)
 
   /* Make a copy of the string that we can safely write into. */
 
-  args = strdup (args);
+  args = xstrdup (args);
   make_cleanup (free, args);
 
   /* Ensure section_addrs is initialized */
@@ -1535,7 +1610,7 @@ add_symbol_file_command (args, from_tty)
                    text data or bss section. This is redundent but
                    eventually, none will be given special treatment */
                {
-                 section_addrs.other[sec_num].name = strdup (sec);
+                 section_addrs.other[sec_num].name = xstrdup (sec);
                  make_cleanup (free, section_addrs.other[sec_num].name);
                  section_addrs.other[sec_num++].addr = addr;
                  printf_filtered ("\t%s_addr = %s\n",
@@ -1572,9 +1647,7 @@ add_symbol_file_command (args, from_tty)
   if (from_tty && (!query ("%s", "")))
     error ("Not confirmed.");
 
-  symbol_file_add (name, from_tty, &section_addrs, 0, flags,
-                  1,           /* user_loaded */
-                  0);          /* We'll guess it's ! is_solib */
+  symbol_file_add (name, from_tty, &section_addrs, 0, flags);
 
   /* Getting new symbols may change our opinion about what is
      frameless.  */
@@ -1692,9 +1765,7 @@ reread_symbols ()
                      sizeof (objfile->static_psymbols));
 
              /* Free the obstacks for non-reusable objfiles */
-             obstack_free (&objfile->psymbol_cache.cache, 0);
-             memset (&objfile->psymbol_cache, 0,
-                     sizeof (objfile->psymbol_cache));
+             free_bcache (&objfile->psymbol_cache);
              obstack_free (&objfile->psymbol_obstack, 0);
              obstack_free (&objfile->symbol_obstack, 0);
              obstack_free (&objfile->type_obstack, 0);
@@ -2075,7 +2146,8 @@ clear_symtab_users ()
   current_source_symtab = 0;
   current_source_line = 0;
   clear_pc_function_cache ();
-  target_new_objfile (NULL);
+  if (target_new_objfile_hook)
+    target_new_objfile_hook (NULL);
 }
 
 /* clear_symtab_users_once:
@@ -3303,4 +3375,16 @@ Usage: set extension-language .foo bar",
 
   add_info ("extensions", info_ext_lang_command,
            "All filename extensions associated with a source language.");
+
+  add_show_from_set
+    (add_set_cmd ("download-write-size", class_obscure,
+                 var_integer, (char *) &download_write_size,
+                 "Set the write size used when downloading a program.\n"
+                 "Only used when downloading a program onto a remote\n"
+                 "target. Specify zero, or a negative value, to disable\n"
+                 "blocked writes. The actual size of each transfer is also\n"
+                 "limited by the size of the target packet and the memory\n"
+                 "cache.\n",
+                 &setlist),
+     &showlist);
 }
This page took 0.028835 seconds and 4 git commands to generate.