This is the mail archive of the
sid@sources.redhat.com
mailing list for the SID project.
[patch][rfa] Error checking by the loader
- From: Dave Brolley <brolley at redhat dot com>
- To: sid at sources dot redhat dot com
- Date: Tue, 21 Oct 2003 15:26:47 -0400
- Subject: [patch][rfa] Error checking by the loader
- Organization: Red Hat Canada, Ltd
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
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.
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;
};