/* ### * IP: GHIDRA * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #include "loadimage_xml.hh" #include "translate.hh" /// \param f is the (path to the) underlying XML file /// \param el is the parsed form of the file LoadImageXml::LoadImageXml(const string &f,const Element *el) : LoadImage(f) { manage = (const AddrSpaceManager *)0; rootel = el; // Extract architecture information if (rootel->getName() != "binaryimage") throw LowlevelError("Missing binaryimage tag in "+filename); archtype = el->getAttributeValue("arch"); } /// Write out the byte chunks and symbols as XML tags /// \param s is the output stream void LoadImageXml::saveXml(ostream &s) const { s << "\n"; map >::const_iterator iter1; for(iter1=chunk.begin();iter1!=chunk.end();++iter1) { const vector &vec((*iter1).second); if (vec.size() == 0) continue; s << " saveXmlAttributes(s,(*iter1).first.getOffset()); if (readonlyset.find((*iter1).first) != readonlyset.end()) s << " readonly=\"true\""; s << ">\n " << setfill('0'); for(int4 i=0;i\n"; } map::const_iterator iter2; for(iter2=addrtosymbol.begin();iter2!=addrtosymbol.end();++iter2) { s << " saveXmlAttributes(s,(*iter2).first.getOffset()); s << " name=\"" << (*iter2).second << "\"/>\n"; } s << "\n"; } /// \param m is for looking up address space void LoadImageXml::open(const AddrSpaceManager *m) { manage = m; uint4 sz; // unused size // Read parsed xml file const List &list(rootel->getChildren()); List::const_iterator iter; iter = list.begin(); while(iter != list.end()) { Element *subel = *iter++; if (subel->getName()=="symbol") { AddrSpace *base = (AddrSpace *)0; base = manage->getSpaceByName(subel->getAttributeValue("space")); if (base == (AddrSpace *)0) throw LowlevelError("Unknown space name: "+subel->getAttributeValue("space")); Address addr(base,base->restoreXmlAttributes(subel,sz)); const string &nm(subel->getAttributeValue("name")); addrtosymbol[addr] = nm; } else if (subel->getName() == "bytechunk") { AddrSpace *base = (AddrSpace *)0; base = manage->getSpaceByName(subel->getAttributeValue("space")); if (base == (AddrSpace *)0) throw LowlevelError("Unknown space name: "+subel->getAttributeValue("space")); Address addr(base,base->restoreXmlAttributes(subel,sz)); map >::iterator chnkiter; vector &vec( chunk[addr] ); vec.clear(); for(int4 i=0;igetNumAttributes();++i) { if (subel->getAttributeName(i) == "readonly") if (xml_readbool(subel->getAttributeValue(i))) readonlyset.insert(addr); } istringstream is(subel->getContent()); int4 val; char c1,c2; is >> ws; c1 = is.get(); c2 = is.get(); while((c1>0)&&(c2>0)) { if (c1 <= '9') c1 = c1 - '0'; else if (c1 <= 'F') c1 = c1 + 10 - 'A'; else c1 = c1 + 10 - 'a'; if (c2 <= '9') c2 = c2 - '0'; else if (c2 <= 'F') c2 = c2 + 10 - 'A'; else c2 = c2 + 10 - 'a'; val = c1*16 + c2; vec.push_back((uint1)val); is >> ws; c1 = is.get(); c2 = is.get(); } } else throw LowlevelError("Unknown LoadImageXml tag: "+subel->getName()); } pad(); } void LoadImageXml::clear(void) { archtype.clear(); manage = (const AddrSpaceManager *)0; chunk.clear(); addrtosymbol.clear(); } void LoadImageXml::pad(void) { map >::iterator iter,lastiter; // Search for completely redundant chunks if (chunk.empty()) return; lastiter = chunk.begin(); iter = lastiter; ++iter; while(iter!=chunk.end()) { if ((*lastiter).first.getSpace() == (*iter).first.getSpace()) { uintb end1 = (*lastiter).first.getOffset() + (*lastiter).second.size() - 1; uintb end2 = (*iter).first.getOffset() + (*iter).second.size() - 1; if (end1 >= end2) { chunk.erase(iter); iter = lastiter; ++iter; continue; } } lastiter = iter; ++iter; } iter = chunk.begin(); while(iter!=chunk.end()) { Address endaddr = (*iter).first + (*iter).second.size(); if (endaddr < (*iter).first) { ++iter; continue; // All the way to end of space } ++iter; int4 maxsize = 512; uintb room = endaddr.getSpace()->getHighest() - endaddr.getOffset() + 1; if ((uintb)maxsize > room) maxsize = (int4)room; if ((iter!=chunk.end())&&((*iter).first.getSpace()==endaddr.getSpace())) { if (endaddr.getOffset() >= (*iter).first.getOffset()) continue; room = (*iter).first.getOffset() - endaddr.getOffset(); if ((uintb)maxsize > room) maxsize = (int4)room; } vector &vec( chunk[endaddr] ); for(int4 i=0;i >::const_iterator iter; Address curaddr; bool emptyhit = false; curaddr = addr; iter = chunk.upper_bound(curaddr); // First one greater than if (iter != chunk.begin()) --iter; // Last one less or equal while((size>0)&&(iter!=chunk.end())) { const vector &chnk((*iter).second); int4 chnksize = chnk.size(); int4 over = curaddr.overlap(0,(*iter).first,chnksize); if (over!=-1) { if (chnksize-over > size) chnksize = over+size; for(int4 i=over;i0)||emptyhit) { ostringstream errmsg; errmsg << "Bytes at "; curaddr.printRaw(errmsg); errmsg << " are not mapped"; throw DataUnavailError(errmsg.str()); } } void LoadImageXml::openSymbols(void) const { cursymbol = addrtosymbol.begin(); } bool LoadImageXml::getNextSymbol(LoadImageFunc &record) const { if (cursymbol == addrtosymbol.end()) return false; record.name = (*cursymbol).second; record.address = (*cursymbol).first; ++cursymbol; return true; } void LoadImageXml::getReadonly(RangeList &list) const { map >::const_iterator iter; // List all the readonly chunks for(iter=chunk.begin();iter!=chunk.end();++iter) { if (readonlyset.find((*iter).first) != readonlyset.end()) { const vector &chnk((*iter).second); uintb start = (*iter).first.getOffset(); uintb stop = start + chnk.size() - 1; list.insertRange((*iter).first.getSpace(),start,stop); } } } void LoadImageXml::adjustVma(long adjust) { map >::iterator iter1; map::iterator iter2; map > newchunk; map newsymbol; for(iter1=chunk.begin();iter1!=chunk.end();++iter1) { AddrSpace *spc = (*iter1).first.getSpace(); int4 off = AddrSpace::addressToByte(adjust,spc->getWordSize()); Address newaddr = (*iter1).first + off; newchunk[newaddr] = (*iter1).second; } chunk = newchunk; for(iter2=addrtosymbol.begin();iter2!=addrtosymbol.end();++iter2) { AddrSpace *spc = (*iter2).first.getSpace(); int4 off = AddrSpace::addressToByte(adjust,spc->getWordSize()); Address newaddr = (*iter2).first + off; newsymbol[newaddr] = (*iter2).second; } addrtosymbol = newsymbol; }