* 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.
+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
// 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.
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;
// ----------------------------------------------------------------------------
+// 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,
// 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;
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,
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.
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++;
}
}
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++;
}
}
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*);
<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" />