From a2142f91802e84106ddaa8d23e1f84300ec6ea87 Mon Sep 17 00:00:00 2001
From: brolley
Date: Tue, 21 Oct 2003 21:30:44 +0000
Subject: [PATCH] 2003-10-07 Dave Brolley
* 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
* 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
For Stan Cox
* elfload.c (textSegmentAddress): New function.
* elfload.h (textSegmentAddress): Likewise.
---
sid/component/loader/ChangeLog | 31 +++++++++++++++++
sid/component/loader/compLoader.cxx | 65 +++++++++++++++++++++++++++++++++---
sid/component/loader/elfload.c | 45 +++++++++++++++++++++++++
sid/component/loader/elfload.h | 2 ++
sid/component/loader/sw-load-elf.xml | 15 +++++++++
5 files changed, 153 insertions(+), 5 deletions(-)
diff --git a/sid/component/loader/ChangeLog b/sid/component/loader/ChangeLog
index 5150acf3e1..4618d8b208 100644
--- a/sid/component/loader/ChangeLog
+++ b/sid/component/loader/ChangeLog
@@ -1,3 +1,34 @@
+2003-10-07 Dave Brolley
+
+ * 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
+
+ * 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
+
+ For Stan Cox
+ * elfload.c (textSegmentAddress): New function.
+ * elfload.h (textSegmentAddress): Likewise.
+
2002-02-05 Dave Brolley
* elfload.c (readElfFile): Obtain the load address from offset 24 for
diff --git a/sid/component/loader/compLoader.cxx b/sid/component/loader/compLoader.cxx
index 1b379b1a9e..c78c68238b 100644
--- a/sid/component/loader/compLoader.cxx
+++ b/sid/component/loader/compLoader.cxx
@@ -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,
diff --git a/sid/component/loader/elfload.c b/sid/component/loader/elfload.c
index a51432b4f9..6300789033 100644
--- a/sid/component/loader/elfload.c
+++ b/sid/component/loader/elfload.c
@@ -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++;
}
}
diff --git a/sid/component/loader/elfload.h b/sid/component/loader/elfload.h
index 2a7bb188d0..9208f7aa30 100644
--- a/sid/component/loader/elfload.h
+++ b/sid/component/loader/elfload.h
@@ -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*);
diff --git a/sid/component/loader/sw-load-elf.xml b/sid/component/loader/sw-load-elf.xml
index 9e7b2bc65c..53ef69b0ac 100644
--- a/sid/component/loader/sw-load-elf.xml
+++ b/sid/component/loader/sw-load-elf.xml
@@ -8,13 +8,17 @@
+
+
+
+
@@ -62,6 +66,17 @@
than gdb would.
+
+
+ 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.
+
+
+
state is minimal.
--
2.11.0