54 if (buflen >= 0x2c && buf[0] == 0x0d && buf[1] == 0x01 && buf[2] == 0x00 && buf[3] == 0x00) {
55 return "b.out_i960_little";
58 if (buflen >= 0x2c && buf[0] == 0x00 && buf[1] == 0x00 && buf[2] == 0x01 && buf[3] == 0x0d) {
59 return "b.out_i960_big";
67 static uint32_t unencode32(uint8_t *p,
Endianness endianness)
72 res = p[3] + (p[2] << 8) + (p[1] << 16) + (p[0] << 24);
74 res = p[0] + (p[1] << 8) + (p[2] << 16) + (p[3] << 24);
84 messages <<
"Target is not an AddressDataBus.\n";
89 if (!file.is_open()) {
90 messages <<
"Unable to read file.\n";
94 unsigned char buf[65536];
96 memset(buf, 0,
sizeof(buf));
97 file.seekg(0, std::ios_base::end);
98 uint64_t totalSize = file.tellg();
99 file.seekg(0, std::ios_base::beg);
100 file.read((
char *)buf, totalSize <
sizeof(buf)? totalSize :
sizeof(buf));
101 size_t amountRead = file.gcount();
107 messages <<
"Unknown b.out format.\n";
111 file.seekg(0, std::ios_base::beg);
115 messages <<
"Target does not have the 'bigendian' variable," 116 " which is needed to\n" 117 "load b.out files.\n";
122 if (format ==
"b.out_i960_big")
128 file.read((
char *)&header,
sizeof(header));
129 if (file.gcount() !=
sizeof(header)) {
130 messages <<
"The file is too small to be a b.out.\n";
134 entry = unencode32((
unsigned char*)&header.a_entry, endianness);
136 uint32_t textaddr = unencode32((
unsigned char*)&header.a_tload, endianness);
137 uint32_t textsize = unencode32((
unsigned char*)&header.a_text, endianness);
139 uint32_t dataaddr = unencode32((
unsigned char*)&header.a_dload, endianness);
140 uint32_t datasize = unencode32((
unsigned char*)&header.a_data, endianness);
142 int32_t symbsize = unencode32((
unsigned char*)&header.a_syms, endianness);
144 messages.flags(std::ios::hex);
145 messages <<
"b.out: entry point 0x";
146 messages << setw(8) << setfill(
'0') << (uint32_t) entry <<
"\n";
148 messages.flags(std::ios::dec);
149 messages <<
"text + data = " << textsize <<
" + " << datasize <<
" bytes\n";
152 uint32_t vaddr = textaddr;
153 while (textsize != 0) {
154 int len = textsize >
sizeof(buf) ?
sizeof(buf) : textsize;
155 file.read((
char *)buf, len);
161 for (
int k=0; k<len; ++k) {
164 messages.flags(std::ios::hex);
165 messages <<
"Failed to write data to virtual " 166 "address 0x" << vaddr <<
"\n";
177 messages <<
"Failed to read the entire file.\n";
183 while (datasize != 0) {
184 int len = datasize >
sizeof(buf) ?
sizeof(buf) : datasize;
185 file.read((
char *)buf, len);
191 for (
int k=0; k<len; ++k) {
194 messages.flags(std::ios::hex);
195 messages <<
"Failed to write data to virtual " 196 "address 0x" << vaddr <<
"\n";
207 messages <<
"Failed to read the entire file.\n";
220 if (symbolRegistry != NULL && symbsize > 0) {
221 messages.flags(std::ios::dec);
222 messages <<
"symbols: " << symbsize <<
" bytes at 0x";
223 messages.flags(std::ios::hex);
224 messages << file.tellg() <<
"\n";
226 vector<char> symbolData;
227 symbolData.resize(symbsize);
228 file.read(&symbolData[0], symbsize);
229 if (file.gcount() != symbsize) {
230 messages <<
"Failed to read all symbols.\n";
234 off_t oldpos = file.tellg();
235 file.seekg(0, std::ios_base::end);
236 size_t strings_len = (off_t)file.tellg() - oldpos;
237 file.seekg(oldpos, std::ios_base::beg);
239 messages.flags(std::ios::dec);
240 messages <<
"strings: " << strings_len <<
" bytes at 0x";
241 messages.flags(std::ios::hex);
242 messages << file.tellg() <<
"\n";
244 vector<char> symbolStrings;
246 symbolStrings.resize(strings_len + 1);
247 file.read(&symbolStrings[0], strings_len);
248 if (file.gcount() != strings_len) {
249 messages <<
"Failed to read all strings.\n";
258 int n_symbols = symbsize /
sizeof(
struct aout_symbol);
259 for (
int i = 0; i < n_symbols; i++) {
260 uint32_t index = unencode32((
unsigned char*)&aout_symbol_ptr[i].
strindex, endianness);
261 uint32_t
type = unencode32((
unsigned char*)&aout_symbol_ptr[i].type, endianness);
262 uint32_t
addr = unencode32((
unsigned char*)&aout_symbol_ptr[i].addr, endianness);
267 if (!(type & 0x01000000))
273 if ((type & 0x1f000000) == 0x1f000000)
276 if (index >= (uint32_t)strings_len) {
277 messages <<
"symbol " << i <<
" has invalid string index\n";
281 string symbol = ((
char*) &symbolStrings[0]) + index;
293 messages.flags(std::ios::dec);
294 messages << nsymbols <<
" symbols read\n";
300 ss << (int64_t)(int32_t)entry;
314 static void Test_FileLoader_bout_Constructor()
321 UNITTEST(Test_FileLoader_bout_Constructor);
A registry for loaded symbols.
virtual CPUComponent * AsCPUComponent()
Returns the component's CPUComponent interface.
StateVariable * GetVariable(const string &name)
Gets a pointer to a state variable.
void AddSymbol(const string &symbol, uint64_t vaddr)
Adds a symbol to the registry.
string DetectFileType(unsigned char *buf, size_t buflen, float &matchness) const
Attempt to detect file type.
const string & Filename() const
bool LoadIntoComponent(refcount_ptr< Component > component, ostream &messages) const
Loads the file into a Component.
virtual bool WriteData(const uint8_t &data, Endianness endianness=BigEndian)=0
Writes 8-bit data to the currently selected address.
An interface for implementing components that read/write data via an address bus. ...
#define UNITTESTS(class)
Helper for unit test case execution.
FileLoader_bout(const string &filename)
SymbolRegistry & GetSymbolRegistry()
Gets a reference to the CPU's symbol registry.
StateVariables make up the persistent state of Component objects.
A base-class for processors Component implementations.
virtual void AddressSelect(uint64_t address)=0
Place an address on the bus.
bool SetVariableValue(const string &name, const string &expression)
Sets a variable to a new value.
virtual AddressDataBus * AsAddressDataBus()
Returns the component's AddressDataBus interface, if any.
#define UNITTEST(functionname)
Helper for unit test case execution.