[RFA] symfile.c -- one more bfd access method change

Michael Snyder msnyder@cygnus.com
Sat Jan 12 22:11:00 GMT 2002


Last one, I promise.  Use bfd_map_over_sections function instead of
grokking the bfd structure directly.

2002-01-11  Michael Snyder  <msnyder@redhat.com>

	* symfile.c (generic_load): Use bfd_map_over_sections method
	instead of manipulating bfd structure members directly.
	(add_section_size_callback): New function, bfd sections callback.
	(load_sections_callback): New function, bfd sections callback.

Index: symfile.c
===================================================================
RCS file: /cvs/src/src/gdb/symfile.c,v
retrieving revision 1.48
diff -c -3 -p -r1.48 symfile.c
*** symfile.c	2002/01/13 05:59:30	1.48
--- symfile.c	2002/01/13 06:02:39
*************** load_command (char *arg, int from_tty)
*** 1174,1192 ****
  static int download_write_size = 512;
  static int validate_download = 0;
  
  void
  generic_load (char *args, int from_tty)
  {
    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 */
-   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;
!   bfd_size_type total_size = 0;
  
    /* Parse the input argument - the user can specify a load offset as
       a second argument. */
--- 1174,1312 ----
  static int download_write_size = 512;
  static int validate_download = 0;
  
+ /* Callback service function for generic_load (bfd_map_over_sections).  */
+ 
+ static void
+ add_section_size_callback (bfd *abfd, asection *asec, void *data)
+ {
+   bfd_size_type *sum = data;
+ 
+   *sum += bfd_get_section_size_before_reloc (asec);
+ }
+ 
+ /* Opaque data for load_section_callback.  */
+ struct load_section_data {
+   unsigned long load_offset;
+   unsigned long write_count;
+   unsigned long data_count;
+   bfd_size_type total_size;
+ };
+ 
+ /* Callback service function for generic_load (bfd_map_over_sections).  */
+ 
+ static void
+ load_section_callback (bfd *abfd, asection *asec, void *data)
+ {
+   struct load_section_data *args = data;
+ 
+   if (bfd_get_section_flags (abfd, asec) & SEC_LOAD)
+     {
+       bfd_size_type size = bfd_get_section_size_before_reloc (asec);
+       if (size > 0)
+ 	{
+ 	  char *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;
+ 
+ 	  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 (xfree, buffer);
+ 
+ 	  /* Is this really necessary?  I guess it gives the user something
+ 	     to look at during a long download.  */
+ #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 (abfd, asec, buffer, 0, size);
+ 
+ 	  sent = 0;
+ 	  do
+ 	    {
+ 	      int len;
+ 	      bfd_size_type 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;
+ 	      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 (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
+ 		  || (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, 
+ 				    args->data_count, args->total_size);
+ 	    }
+ 	  while (sent < size);
+ 
+ 	  if (err != 0)
+ 	    error ("Memory access error while loading section %s.", sect_name);
+ 
+ 	  do_cleanups (old_chain);
+ 	}
+     }
+ }
+ 
  void
  generic_load (char *args, int from_tty)
  {
    asection *s;
    bfd *loadfile_bfd;
    time_t start_time, end_time;	/* Start and end times of download */
    char *filename;
    struct cleanup *old_cleanups;
    char *offptr;
!   struct load_section_data cbdata;
!   CORE_ADDR entry;
! 
!   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. */
  
    /* Parse the input argument - the user can specify a load offset as
       a second argument. */
*************** generic_load (char *args, int from_tty)
*** 1198,1210 ****
      {
        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);
--- 1318,1330 ----
      {
        char *endptr;
  
!       cbdata.load_offset = strtoul (offptr, &endptr, 0);
        if (offptr == endptr)
  	error ("Invalid download offset:%s\n", offptr);
        *offptr = '\0';
      }
    else
!     cbdata.load_offset = 0;
  
    /* Open the file for loading. */
    loadfile_bfd = bfd_openr (filename, gnutarget);
*************** generic_load (char *args, int from_tty)
*** 1225,1353 ****
  	     bfd_errmsg (bfd_get_error ()));
      }
  
!   for (s = loadfile_bfd->sections; s; s = s->next)
!     if (bfd_get_section_flags (loadfile_bfd, s) & 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 = bfd_get_section_size_before_reloc (s);
- 
- 	  if (size > 0)
- 	    {
- 	      char *buffer;
- 	      struct cleanup *old_chain;
- 	      CORE_ADDR lma = bfd_section_lma (loadfile_bfd, s) + load_offset;
- 	      bfd_size_type block_size;
- 	      int err;
- 	      const char *sect_name = bfd_get_section_name (loadfile_bfd, s);
- 	      bfd_size_type sent;
- 
- 	      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 (xfree, buffer);
- 
- 	      /* Is this really necessary?  I guess it gives the user something
- 	         to look at during a long download.  */
- #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);
  
! 	      sent = 0;
! 	      do
! 		{
! 		  int len;
! 		  bfd_size_type 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;
! 		  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 (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);
!  		    }
! 		  data_count += len;
! 		  lma += len;
! 		  buffer += len;
! 		  write_count += 1;
! 		  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, 
! 					data_count, total_size);
! 		}
! 	      while (sent < size);
  
- 	      if (err != 0)
- 		error ("Memory access error while loading section %s.", 
- 		       sect_name);
- 
- 	      do_cleanups (old_chain);
- 	    }
- 	}
-     }
- 
    end_time = time (NULL);
-   {
-     CORE_ADDR entry = bfd_get_start_address (loadfile_bfd);
  
  #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", "%lu", data_count);
!     ui_out_text (uiout, "\n");
! 
  #else
!     fprintf_unfiltered (gdb_stdout,
! 			"Start address 0x%s, load size %lu\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);
!   }
  
    /* FIXME: are we supposed to call symbol_file_add or not?  According to
       a comment from remote-mips.c (where a call to symbol_file_add was
--- 1345,1374 ----
  	     bfd_errmsg (bfd_get_error ()));
      }
  
!   bfd_map_over_sections (loadfile_bfd, add_section_size_callback, 
! 			 (void *) &cbdata.total_size);
  
    start_time = time (NULL);
  
!   bfd_map_over_sections (loadfile_bfd, load_section_callback, &cbdata);
  
    end_time = time (NULL);
  
+   entry = bfd_get_start_address (loadfile_bfd);
  #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", "%lu", cbdata.data_count);
!   ui_out_text (uiout, "\n");
  #else
!   fprintf_unfiltered (gdb_stdout,
! 		      "Start address 0x%s, load size %lu\n",
! 		      paddr_nz (entry), cbdata.data_count);
  #endif
!   /* We were doing this in remote-mips.c, I suspect it is right
!      for other targets too.  */
!   write_pc (entry);
  
    /* FIXME: are we supposed to call symbol_file_add or not?  According to
       a comment from remote-mips.c (where a call to symbol_file_add was
*************** generic_load (char *args, int from_tty)
*** 1355,1362 ****
       loaded in.  remote-nindy.c had no call to symbol_file_add, but remote-vx.c
       does.  */
  
!   print_transfer_performance (gdb_stdout, data_count, write_count,
! 			      end_time - start_time);
  
    do_cleanups (old_cleanups);
  }
--- 1376,1383 ----
       loaded in.  remote-nindy.c had no call to symbol_file_add, but remote-vx.c
       does.  */
  
!   print_transfer_performance (gdb_stdout, cbdata.data_count, 
! 			      cbdata.write_count, end_time - start_time);
  
    do_cleanups (old_cleanups);
  }



More information about the Gdb-patches mailing list