[patch][rfa] Error checking by the loader

Dave Brolley <[email protected]>
Newsgroups gmane.comp.emulators.sid.devel
Organization Red Hat Canada, Ltd
Message-ID <[email protected]>
Hi,

This patch adds code to the elf loader which allows it to classify input 
sections as code or not-code. It also adds a passthrough bus to the 
loader ("probe-upstream", "probe-downstream"). When the "probe-upstream" 
bus is accessed, the loader checks the address against known code 
sections and drives the "write-to-code_address" pin if a write to a code 
section is attempted. All accesses are passed on to "probe-downstream" 
accessor.

This is useful in generating simulation time warnings for writes to code 
sections.

ok to commit?

Dave
loader.ChangeLog (text/plain, 1.2 KB)
2003-10-07  Dave Brolley  <[email protected]>

	* compLoader.cxx (loader_probe_bus): Now takes pin as an argument.
	Remove warn_write_to_code_p. Initialize write_to_code_address_pin.
	(SID_GB_WRITE): Drive write_to_code_address_pin instead of
	generating a message here.
	(write_to_code_address_pin): New member of generic_loader.
	(set_warn_write_to_code): Removed.
	(generic_loader): remove "warn-write-to-code?" attribute and pin.
	Add "write-to-code-address" pin.
	* sw-load-elf.xml: Remove reference to "warn-write-to-code?" pin
	and attribute. Document "write-to-code-address" pin.
	* sw-load-elf.txt: Regenerated.

2003-10-07  Dave Brolley  <[email protected]>

	* compLoader.cxx: Use sidutil::fixed_bus_map_component.
	(loader_probe_bus): New class.
	(warn_write_to_code_pin): New member of generic_loader.
	(probe_upstream): Ditto.
	(probe_downstream): Ditto.
	(set_warn_write_to_code): New method of generic_loader.
	(generic_loader): Now inherits fixed_bus_map_component.
	Initialize new members.

2003-10-07  Dave Brolley  <[email protected]>

	For Stan Cox  <[email protected]>
	* elfload.c (textSegmentAddress): New function.
	* elfload.h (textSegmentAddress): Likewise.
loader.patch.txt (text/plain, 12.1 KB)
Index: sid/component/loader/compLoader.cxx
===================================================================
RCS file: /cvs/src/src/sid/component/loader/compLoader.cxx,v
retrieving revision 1.5
diff -c -p -r1.5 compLoader.cxx
*** sid/component/loader/compLoader.cxx	3 Aug 2001 06:02:45 -0000	1.5
--- sid/component/loader/compLoader.cxx	21 Oct 2003 17:52:55 -0000
***************
*** 1,6 ****
  // compLoader.cxx - object file loader component.  -*- C++ -*-
  
! // Copyright (C) 1999, 2000 Red Hat.
  // This file is part of SID and is licensed under the GPL.
  // See the file COPYING.SID for conditions for redistribution.
  
--- 1,6 ----
  // compLoader.cxx - object file loader component.  -*- C++ -*-
  
! // Copyright (C) 1999, 2000, 2003 Red Hat.
  // This file is part of SID and is licensed under the GPL.
  // See the file COPYING.SID for conditions for redistribution.
  
*************** using sid::host_int_4;
*** 44,50 ****
  using sid::component_library;
  using sid::COMPONENT_LIBRARY_MAGIC;
  
! using sidutil::no_bus_component;
  using sidutil::fixed_attribute_map_component;
  using sidutil::fixed_pin_map_component;
  using sidutil::fixed_accessor_map_component;
--- 44,50 ----
  using sid::component_library;
  using sid::COMPONENT_LIBRARY_MAGIC;
  
! using sidutil::fixed_bus_map_component;
  using sidutil::fixed_attribute_map_component;
  using sidutil::fixed_pin_map_component;
  using sidutil::fixed_accessor_map_component;
*************** using sidutil::std_error_string;
*** 60,67 ****
  
  // ----------------------------------------------------------------------------
  
  class generic_loader: public virtual component,
! 		      protected no_bus_component,
  		      protected fixed_attribute_map_component,
  		      protected fixed_pin_map_component,
  		      protected fixed_accessor_map_component,
--- 60,109 ----
  
  // ----------------------------------------------------------------------------
  
+ // A bus for allowing the loader to perform random checks against reads and writes
+ // to memory. For example writing to a code area. Default implementation
+ extern "C" int textSegmentAddress(int);
+ 
+ class loader_probe_bus: public sidutil::passthrough_bus
+   {
+   public:
+     loader_probe_bus (sid::bus **t, output_pin *p) :
+       sidutil::passthrough_bus (t),
+       write_to_code_address_pin (p)
+     {
+       assert (t);
+     }
+     ~loader_probe_bus() throw() {}
+     
+     // Some macros to make manufacturing of the cartesian-product
+     // calls simpler.
+ #define SID_GB_WRITE(dtype) \
+       sid::bus::status write(sid::host_int_4 addr, dtype data) throw ()\
+ 	  { if (LIKELY(*target)) \
+               { \
+                 if (write_to_code_address_pin && textSegmentAddress (addr)) \
+                   write_to_code_address_pin->drive (addr); \
+                 return (*target)->write(addr, data); \
+               } \
+             else return sid::bus::unpermitted; \
+           }
+ 
+     SID_GB_WRITE(sid::little_int_1)
+     SID_GB_WRITE(sid::big_int_1)
+     SID_GB_WRITE(sid::little_int_2)
+     SID_GB_WRITE(sid::big_int_2)
+     SID_GB_WRITE(sid::little_int_4)
+     SID_GB_WRITE(sid::big_int_4)
+     SID_GB_WRITE(sid::little_int_8)
+     SID_GB_WRITE(sid::big_int_8)
+ 
+ #undef SID_GB_WRITE
+ 
+     output_pin *write_to_code_address_pin;
+   };
+ 
  class generic_loader: public virtual component,
! 		      protected fixed_bus_map_component,
  		      protected fixed_attribute_map_component,
  		      protected fixed_pin_map_component,
  		      protected fixed_accessor_map_component,
*************** protected:
*** 77,93 ****
    // The value is one of sidutil::endian_*.
    output_pin endian_pin;
  
    // Signal this if something went wrong.
    output_pin error_pin;
  
!   // loadable file names
    bool verbose_p;
    string load_file;
  
    // accessors
    bus* load_accessor_insn;
    bus* load_accessor_data;
  
    // The load pin was triggered.
    virtual void load_it (host_int_4) = 0;
  
--- 119,143 ----
    // The value is one of sidutil::endian_*.
    output_pin endian_pin;
  
+   // Provide address of write attempt to code section
+   output_pin write_to_code_address_pin;
+ 
    // Signal this if something went wrong.
    output_pin error_pin;
  
!   // Attribute settings
    bool verbose_p;
+ 
+   // loadable file names
    string load_file;
  
    // accessors
    bus* load_accessor_insn;
    bus* load_accessor_data;
  
+   loader_probe_bus probe_upstream;
+   bus           *probe_downstream;
+ 
    // The load pin was triggered.
    virtual void load_it (host_int_4) = 0;
  
*************** public:
*** 104,118 ****
      verbose_p(false),
      load_file("/dev/null"),
      load_accessor_insn(0),
!     load_accessor_data(0)
      {
        add_pin("load!", & this->doit_pin);
        add_pin("start-pc-set", & this->start_pc_pin);
        add_pin("endian-set", & this->endian_pin);
        add_pin("error", & this->error_pin);
        add_accessor("load-accessor-insn", & this->load_accessor_insn);
        add_accessor("load-accessor-data", & this->load_accessor_data);
        add_attribute("file", & this->load_file, "setting");
        add_attribute("verbose?", & this->verbose_p, "setting");
        add_attribute_virtual ("state-snapshot", this,
  			     & generic_loader::save_state,
--- 154,173 ----
      verbose_p(false),
      load_file("/dev/null"),
      load_accessor_insn(0),
!     load_accessor_data(0),
!     probe_upstream (& probe_downstream, & this->write_to_code_address_pin),
!     probe_downstream(0)
      {
        add_pin("load!", & this->doit_pin);
        add_pin("start-pc-set", & this->start_pc_pin);
        add_pin("endian-set", & this->endian_pin);
        add_pin("error", & this->error_pin);
+       add_pin("write-to-code-address", & this->write_to_code_address_pin);
        add_accessor("load-accessor-insn", & this->load_accessor_insn);
        add_accessor("load-accessor-data", & this->load_accessor_data);
        add_attribute("file", & this->load_file, "setting");
+       add_bus ("probe-upstream", & this->probe_upstream);
+       add_accessor ("probe-downstream", & this->probe_downstream);
        add_attribute("verbose?", & this->verbose_p, "setting");
        add_attribute_virtual ("state-snapshot", this,
  			     & generic_loader::save_state,
Index: sid/component/loader/elfload.c
===================================================================
RCS file: /cvs/src/src/sid/component/loader/elfload.c,v
retrieving revision 1.4
diff -c -p -r1.4 elfload.c
*** sid/component/loader/elfload.c	5 Feb 2002 16:36:48 -0000	1.4
--- sid/component/loader/elfload.c	21 Oct 2003 17:52:55 -0000
*************** struct LoadAreas
*** 29,34 ****
--- 29,57 ----
    int loaded;
  } loadAreas[100]; // XXX: limit on number of loadable sections
  
+ static struct TextSegment
+ {
+   host_int_8 lbound;
+   host_int_8 hbound;
+ } textSegments[100];
+ static int textSegmentsCount = 0;
+ enum {execute_flag = 1};
+ 
+ 
+ int
+ textSegmentAddress (int address)
+ {
+   int i;
+   for (i = 0; i < textSegmentsCount ; i++)
+     {
+       if (textSegments[i].lbound <= address
+ 	  && address <= textSegments[i].hbound)
+ 	return 1;
+     }
+   return 0;
+ }
+ 
+ 
  /* Read in an ELF file, using FUNC to read data from the stream.
     The result is a boolean indicating success.
     The entry point as specified in the ELF header is stored in *ENTRY_POINT.
*************** readElfFile (PFLOAD func, unsigned* entr
*** 100,105 ****
--- 123,139 ----
  							    littleEndian);
  	      loadAreas[loadAreaCount].flags = fetchWord(psymHdr+4, littleEndian);
  	      loadAreas[loadAreaCount].loaded = 0;
+ 	      
+ 	      if (loadAreas[loadAreaCount].flags & execute_flag)
+ 		{
+ 		  textSegments[textSegmentsCount].lbound = 
+ 		    loadAreas[loadAreaCount].loadAddr;
+ 		  textSegments[textSegmentsCount].hbound = 
+ 		    loadAreas[loadAreaCount].loadAddr
+ 		    + loadAreas[loadAreaCount].filesize;
+ 		  textSegmentsCount++;
+ 		}
+ 
  	      loadAreaCount++;
  	    }
          }
*************** readElfFile (PFLOAD func, unsigned* entr
*** 118,123 ****
--- 152,168 ----
  							    littleEndian);
  	      loadAreas[loadAreaCount].flags = fetchWord(psymHdr+24, littleEndian);
  	      loadAreas[loadAreaCount].loaded = 0;
+ 
+ 	      if (loadAreas[loadAreaCount].flags & execute_flag)
+ 		{
+ 		  textSegments[textSegmentsCount].lbound = 
+ 		    loadAreas[loadAreaCount].loadAddr;
+ 		  textSegments[textSegmentsCount].hbound = 
+ 		    loadAreas[loadAreaCount].loadAddr
+ 		    + loadAreas[loadAreaCount].filesize;
+ 		  textSegmentsCount++;
+ 		}
+ 
  	      loadAreaCount++;
  	    }
          }
Index: sid/component/loader/elfload.h
===================================================================
RCS file: /cvs/src/src/sid/component/loader/elfload.h,v
retrieving revision 1.2
diff -c -p -r1.2 elfload.h
*** sid/component/loader/elfload.h	13 Jan 2001 14:26:05 -0000	1.2
--- sid/component/loader/elfload.h	21 Oct 2003 17:52:55 -0000
***************
*** 40,45 ****
--- 40,47 ----
  typedef unsigned long long host_int_8;	/* XXX */
  
  typedef int (*PFLOAD)(host_int_8 dest, char *dest2, host_int_8 offset, host_int_8 amount, int insn_space);
+ /* Is address in the text segment? */
+ extern int textSegmentAddress(int);
  /* Load an ELF executable into memory. FUNC is used to actually read the
     file. */
  extern int readElfFile(PFLOAD func, unsigned*, int*);
Index: sid/component/loader/sw-load-elf.xml
===================================================================
RCS file: /cvs/src/src/sid/component/loader/sw-load-elf.xml,v
retrieving revision 1.2
diff -c -p -r1.2 sw-load-elf.xml
*** sid/component/loader/sw-load-elf.xml	5 Oct 2001 00:36:17 -0000	1.2
--- sid/component/loader/sw-load-elf.xml	21 Oct 2003 17:52:55 -0000
***************
*** 8,20 ****
--- 8,24 ----
      <defpin name="start-pc-set" direction="out" legalvalues="any" behaviors="loading"/>
      <defpin name="endian-set" direction="out" legalvalues="0/1/2" behaviors="loading"/>
      <defpin name="error" direction="out" legalvalues="any" behaviors="loading"/>
+     <defpin name="write-to-code-address" direction="out" legalvalues="any address" behaviors="error checking"/>
  
      <defattribute name="state-snapshot" legalvalues="opaque string" behaviors="save/restore"/>
      <defattribute name="file" category="setting" legalvalues="file name" defaultvalue='"/dev/null"' behaviors="configuration"/>
      <defattribute name="verbose?" category="setting" legalvalues="1/0" defaultvalue="0" behaviors="configuration"/>
      
+     <defbus name="probe-upstream" accesses="read/write" behaviors="error checking"/>
+ 
      <defaccessor name="load-accessor-insn" accesses="write little_int_1" behaviors="loading"/>
      <defaccessor name="load-accessor-data" accesses="write little_int_1" behaviors="loading"/>
+     <defaccessor name="probe-downstream" accesses="read/write" behaviors="error checking"/>
  
    </defcomponent>
  
***************
*** 60,65 ****
--- 64,80 ----
        to identify the bytes to load into memory.  It does not use the
        "section header".  This means that it tends to load more bytes
        than <tt>gdb</tt> would.</p>
+     </behavior>
+ 
+     <behavior name="error checking">
+       <p>
+       All read requests coming in though the "probe-upstream" bus are
+       checked against known code segments and, for each attempt to write
+       to a code segment, the write-to-code-address pin is driven with the
+       address of the write attempt. All reads and writes
+       coming in through the probe-upstream bus are passed on to the
+       probe-downstream accessor.
+       </p>
      </behavior>
  
      <convention name="functional" supported="true" />
Index: sid/include/sidbusutil.h
===================================================================
RCS file: /cvs/src/src/sid/include/sidbusutil.h,v
retrieving revision 1.13
diff -c -p -r1.13 sidbusutil.h
*** sid/include/sidbusutil.h	6 Feb 2003 20:27:49 -0000	1.13
--- sid/include/sidbusutil.h	21 Oct 2003 17:59:06 -0000
*************** namespace sidutil
*** 251,257 ****
  #undef SID_GB_WRITE
  #undef SID_GB_READ
  
!   private:
      sid::bus** target;
    };
  
--- 251,257 ----
  #undef SID_GB_WRITE
  #undef SID_GB_READ
  
!   protected:
      sid::bus** target;
    };
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.