📄 fc_binutils.cpp
字号:
string::size_type pos2;
/* 拞恎傪嬻偵偟偰偍偔 */
address = 0;
if(!attribute.empty())
attribute.erase();
if(!symbolname.empty())
symbolname.erase();
//師偺峴傪庢摼 (嬻峴, 枹掕媊僔儞儃儖偼撉傒旘偽偡)
do {
if(file.eof())
return false;
getline(file, src, '\n');
} while(src.empty() || src.at(0) == ' ');
//峴傪暘夝
pos1 = src.find_first_of(' ');
addr = src.substr(0, pos1);
pos2 = src.find_first_of(' ', pos1 + 1);
attribute = src.substr(pos1 + 1, pos2 - pos1 - 1);
symbolname = src.substr(pos2 + 1);
//傾僪儗僗偺僷乕僗 (拲 : 側傫偱偙傫側偪傑偪傑傗偭偰傞偐偲偄偆偲丄傾僪儗僗偑32bit傪挻偊傞僞乕僎僢僩偑偄傞偐傜)
while(!addr.empty()) {
size_t length = addr.size();
const char * src = addr.c_str();
if(length > sizeof(unsigned int) * 2)
length = sizeof(unsigned int) * 2;
address = (address << (length * 2)) | (hextodec(src, length));
addr.erase(0, length);
}
return true;
}
/* 僔儞儃儖偺撉傒崬傒 */
void FileContainerBinutilsImpl::loadSymbols(fstream & file) throw(Exception)
{
assert(file.is_open());
address_t address;
string attribute;
string symbolname;
while(readGnuNmLine(file, address, attribute, symbolname)) {
symbol_table.insert(map<string, address_t>::value_type(symbolname, address));
}
VerboseMessage("% symbols loaded\n") << symbol_table.size() << &throwException;
file.close();
}
/* contents偵1僶僀僩彂偒崬傒 */
void FileContainerBinutilsImpl::writeByte(address_t address, unsigned int value) throw(Exception)
{
address_t & base = last_address;
char * & page = last_page;
/* 僉儍僢僔儏傕偳偒偑巊偊側偄側傜丄儁乕僕傪扵偡 */
if(MAKE_BASEADDRESS(address) != last_address || last_page == 0) {
map<address_t, char *>::iterator scope;
base = MAKE_BASEADDRESS(address);
scope = contents.find(base);
if(scope == contents.end()) {
page = new(nothrow) char [SIZE_LOADPAGE];
if(page == 0) {
ExceptionMessage("Not enough memory available to store the contents","嬻偒儊儌儕晄懌偺偨傔丄僨乕僞偺奿擺偵幐攕偟傑偟偨").throwException();
return;
}
contents.insert(map<address_t,char*>::value_type(base, page));
}
else
page = scope->second;
}
*(page + (address - base)) = static_cast<char>(value & 0xff);
}
/* 枛旜偺嬻敀暥帤傪愗傝庢傞 */
void trimString(string & src) throw()
{
string::size_type pos;
pos = src.find_last_not_of(" \t\r\n");
if(pos != string::npos && pos != src.size())
src.erase(pos + 1);
}
/* 儌僩儘乕儔S儗僐乕僪傪堦峴撉傒崬傓 */
/*
The general format of an S-record follows:
+-------------------//------------------//-----------------------+
| type | count | address | data | checksum |
+-------------------//------------------//-----------------------+
*/
bool readRecord(fstream & file, string & dest) throw(Exception)
{
unsigned int sum;
unsigned int count;
unsigned int i;
const char * pos;
/* 師偺峴傪撉傒崬傓 */
do {
//getline偑ReadFile傪屇傫偱僽儘僢僋偡傞偺偱丄妋幚偵EOF傪斀墳偝偣傞偨傔偵偙偆偡傞
int ch = file.get();
if(ch == EOF)
return false;
file.putback(static_cast<char>(ch));
getline(file, dest);
} while(dest.empty());
trimString(dest);
/* 惓摉惈偺敾掕 */
if(dest[0] != 'S') //峴摢偑'S'偱巒傑傜側偄
ExceptionMessage("The file is not a Motorola S-Record file.","儌僩儘乕儔S僼僅乕儅僢僩偱柍偄峴偑尒偮偐傝傑偟偨") << throwException;
pos = dest.c_str() + 2;
count = hextodec(pos, 2);
if(dest.size() != (count + 2)*2)
ExceptionMessage("Illegal S-Record found (count unmatched).","晄惓側S儗僐乕僪偑偁傝傑偡 (僒僀僘晄堦抳)") << throwException;
sum = count;
for(i = 0; i < count; ++ i)
sum += hextodec(pos, 2);
if((sum & 0xff) != 0xff)
ExceptionMessage("Illegal S-Record found (check-sum unmatched).","晄惓側S儗僐乕僪偑偁傝傑偡 (僠僃僢僋僒儉晄堦抳)") << throwException;
return true;
}
/* 師偺奐巒傾僪儗僗傪摼傞 */
FileContainer::address_t parseRecordAddress(const string & src, FileContainer::address_t base) throw()
{
const char * record = src.c_str();
FileContainer::address_t result = 0;
record += 4;
switch(*(record - 3)) {
case '1':
result = hextodec(record, 4);
break;
case '2':
result = hextodec(record, 6);
break;
case '3':
result = hextodec(record, 8);
break;
case '5':
result = base;
break;
default:
break;
}
return result;
}
/* 僨乕僞晹暘偩偗傪巆偟偰僠儑僢僾 */
void chopRecord(string & src) throw()
{
string::size_type start;
switch(src[1]) {
case '1': start = 4 + 4; break;
case '2': start = 4 + 6; break;
case '3': start = 4 + 8; break;
default: start = 4; break;
}
//愭摢4僶僀僩 + 傾僪儗僗晹 + 嵟屻偺僒儉傪庢傝彍偔
src = src.substr(start, src.size() - start - 2);
}
/* 僾儘僌儔儉僨乕僞偺撉傒崬傒 */
void FileContainerBinutilsImpl::loadDataContents(fstream & file) throw(Exception)
{
assert(file.is_open());
address_t address;
string line;
address = 0;
while(readRecord(file, line)) {
address = parseRecordAddress(line, address);
chopRecord(line);
/* 僨乕僞偺奿擺 */
const char * pos = line.c_str();
while(*pos != '\x0') {
unsigned int data = hextodec(pos, 2);
writeByte(address, data);
++ address;
}
}
file.close();
}
/* 僔儞儃儖僾儗僼傿僋僗偺帺摦敾掕 */
void FileContainerBinutilsImpl::searchSymbolPrefix(void) throw()
{
const char * candidate_list[] = {"", "_", NULL};
const char ** candidate;
for(candidate = candidate_list; *candidate != NULL; ++ candidate) {
map<string, address_t>::const_iterator scope;
string symbol;
symbol = string(*candidate) + MAGIC_SYMBOL;
scope = symbol_table.find(symbol);
if(scope != symbol_table.end())
break;
}
if(*candidate != NULL)
symbol_prefix.assign(*candidate);
}
/* 僄儞僨傿傾儞偺帺摦敾掕 */
void FileContainerBinutilsImpl::searchByteOrder(void) throw()
{
address_t address;
union {
char buffer[4];
unsigned int value;
};
try {
value = 0;
address = getSymbolAddress(MAGIC_SYMBOL);
loadContents(buffer, address, 4);
if(value == MAGIC_NUMBER) {
byteorder = HOSTORDER;
}
else {
buffer[0] ^= buffer[3], buffer[3] ^= buffer[0], buffer[0] ^= buffer[3]; // swap(buffer[0], buffer[3])
buffer[1] ^= buffer[2], buffer[2] ^= buffer[1], buffer[1] ^= buffer[2]; // swap(buffer[1], buffer[2])
if(value == MAGIC_NUMBER)
byteorder = HOSTORDER == LITTLE ? BIG : LITTLE;
else
throw false;
}
}
catch(...) {}
}
/* 儌僕儏乕儖偺傾僞僢僠 -> 僔儞儃儖撉弌偟, 僨乕僞奿擺 */
void FileContainerBinutilsImpl::attachModule(const string & filename) throw(Exception)
{
fstream file;
string symbol_filename;
string contents_filename;
splitFilename(filename, symbol_filename, contents_filename);
openTextFile(file, symbol_filename, interceptWithGnuNM);
loadSymbols(file);
openTextFile(file, contents_filename, interceptWithGnuObjcopy);
loadDataContents(file);
searchSymbolPrefix();
searchByteOrder();
}
/* 奿擺偟偰偄傞撪梕偺庢摼 */
void FileContainerBinutilsImpl::loadContents(void * _dest, address_t address, size_t size) throw(Exception)
{
char * dest = static_cast<char *>(_dest);
while(size > 0) {
map<address_t, char *>::const_iterator scope;
address_t base = MAKE_BASEADDRESS(address);
address_t offset = MAKE_OFFSETADDRESS(address);
size_t transfer_size = size;
if(transfer_size > SIZE_LOADPAGE - offset)
transfer_size = SIZE_LOADPAGE - offset;
scope = contents.find(base);
if(scope == contents.end())
ExceptionMessage("[Internel error] Memory read with unmapped address","[撪晹僄儔乕] 儅僢僾偝傟偰側偄傾僪儗僗傪巊偭偰儊儌儕儕乕僪偑峴傢傟傑偟偨").throwException();
memcpy(dest, scope->second + offset, transfer_size);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -