OSDN Git Service

2003-10-07 Dave Brolley <brolley@redhat.com>
authorbrolley <brolley>
Tue, 21 Oct 2003 21:30:44 +0000 (21:30 +0000)
committerbrolley <brolley>
Tue, 21 Oct 2003 21:30:44 +0000 (21:30 +0000)
        * 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  <brolley@redhat.com>

        * 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  <brolley@redhat.com>

        For Stan Cox  <scox@redhat.com>
        * elfload.c (textSegmentAddress): New function.
        * elfload.h (textSegmentAddress): Likewise.

sid/component/loader/ChangeLog
sid/component/loader/compLoader.cxx
sid/component/loader/elfload.c
sid/component/loader/elfload.h
sid/component/loader/sw-load-elf.xml

index 5150acf..4618d8b 100644 (file)
@@ -1,3 +1,34 @@
+2003-10-07  Dave Brolley  <brolley@redhat.com>
+
+       * 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  <brolley@redhat.com>
+
+       * 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  <brolley@redhat.com>
+
+       For Stan Cox  <scox@redhat.com>
+       * elfload.c (textSegmentAddress): New function.
+       * elfload.h (textSegmentAddress): Likewise.
+
 2002-02-05  Dave Brolley  <brolley@redhat.com>
 
        * elfload.c (readElfFile): Obtain the load address from offset 24 for
index 1b379b1..c78c682 100644 (file)
@@ -1,6 +1,6 @@
 // compLoader.cxx - object file loader component.  -*- C++ -*-
 
-// Copyright (C) 1999, 2000 Red Hat.
+// 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.
 
@@ -44,7 +44,7 @@ using sid::host_int_4;
 using sid::component_library;
 using sid::COMPONENT_LIBRARY_MAGIC;
 
-using sidutil::no_bus_component;
+using sidutil::fixed_bus_map_component;
 using sidutil::fixed_attribute_map_component;
 using sidutil::fixed_pin_map_component;
 using sidutil::fixed_accessor_map_component;
@@ -60,8 +60,50 @@ using sidutil::std_error_string;
 
 // ----------------------------------------------------------------------------
 
+// 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 no_bus_component,
+                     protected fixed_bus_map_component,
                      protected fixed_attribute_map_component,
                      protected fixed_pin_map_component,
                      protected fixed_accessor_map_component,
@@ -77,17 +119,25 @@ protected:
   // 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;
 
-  // loadable file names
+  // 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;
 
@@ -104,15 +154,20 @@ public:
     verbose_p(false),
     load_file("/dev/null"),
     load_accessor_insn(0),
-    load_accessor_data(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 a51432b..6300789 100644 (file)
@@ -29,6 +29,29 @@ struct LoadAreas
   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.
@@ -100,6 +123,17 @@ readElfFile (PFLOAD func, unsigned* entry_point, int* little_endian)
                                                            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++;
            }
         }
@@ -118,6 +152,17 @@ readElfFile (PFLOAD func, unsigned* entry_point, int* little_endian)
                                                            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 2a7bb18..9208f7a 100644 (file)
@@ -40,6 +40,8 @@
 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 9e7b2bc..53ef69b 100644 (file)
@@ -8,13 +8,17 @@
     <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>
 
       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" />
     <convention name="save/restore" supported="true">state is minimal.</convention>
     <convention name="triggerpoints" supported="false" />