mirror of
https://github.com/NationalSecurityAgency/ghidra.git
synced 2025-10-05 10:49:34 +02:00
Candidate release of source code.
This commit is contained in:
parent
db81e6b3b0
commit
79d8f164f8
12449 changed files with 2800756 additions and 16 deletions
174
Ghidra/Features/Decompiler/src/decompile/cpp/ghidra_translate.cc
Normal file
174
Ghidra/Features/Decompiler/src/decompile/cpp/ghidra_translate.cc
Normal file
|
@ -0,0 +1,174 @@
|
|||
/* ###
|
||||
* 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 "ghidra_translate.hh"
|
||||
#include "funcdata.hh"
|
||||
|
||||
/// \brief Associate a Varnode with a register name
|
||||
///
|
||||
/// \param nm is the register name
|
||||
/// \param data is the Varnode description
|
||||
/// \return a reference to the cached VarnodeData
|
||||
const VarnodeData &GhidraTranslate::cacheRegister(const string &nm,const VarnodeData &data) const
|
||||
|
||||
{
|
||||
VarnodeData &res(nm2addr[nm]);
|
||||
res = data;
|
||||
addr2nm[data] = nm;
|
||||
return res;
|
||||
}
|
||||
|
||||
void GhidraTranslate::initialize(DocumentStorage &store)
|
||||
|
||||
{
|
||||
const Element *el = store.getTag("sleigh");
|
||||
if (el == (const Element *)0)
|
||||
throw LowlevelError("Could not find ghidra sleigh tag");
|
||||
restoreXml(el);
|
||||
}
|
||||
|
||||
const VarnodeData &GhidraTranslate::getRegister(const string &nm) const
|
||||
|
||||
{
|
||||
map<string,VarnodeData>::const_iterator iter = nm2addr.find(nm);
|
||||
if (iter != nm2addr.end())
|
||||
return (*iter).second;
|
||||
Document *doc;
|
||||
try {
|
||||
doc = glb->getRegister(nm); // Ask Ghidra client about the register
|
||||
}
|
||||
catch(XmlError &err) {
|
||||
ostringstream errmsg;
|
||||
errmsg << "Error parsing XML response for query of register: " << nm;
|
||||
errmsg << " -- " << err.explain;
|
||||
throw LowlevelError(errmsg.str());
|
||||
}
|
||||
if (doc == (Document *)0)
|
||||
throw LowlevelError("No register named "+nm);
|
||||
Address regaddr;
|
||||
int4 regsize;
|
||||
regaddr = Address::restoreXml( doc->getRoot(), this, regsize);
|
||||
VarnodeData vndata;
|
||||
vndata.space = regaddr.getSpace();
|
||||
vndata.offset = regaddr.getOffset();
|
||||
vndata.size = regsize;
|
||||
delete doc;
|
||||
return cacheRegister(nm,vndata);
|
||||
}
|
||||
|
||||
string GhidraTranslate::getRegisterName(AddrSpace *base,uintb off,int4 size) const
|
||||
|
||||
{
|
||||
if (base->getType() != IPTR_PROCESSOR) return "";
|
||||
VarnodeData vndata;
|
||||
vndata.space = base;
|
||||
vndata.offset = off;
|
||||
vndata.size = size;
|
||||
map<VarnodeData,string>::const_iterator iter = addr2nm.find(vndata);
|
||||
if (iter != addr2nm.end())
|
||||
return (*iter).second;
|
||||
string res = glb->getRegisterName(vndata);
|
||||
if (res.size()!=0) // Cause this register to be cached if not already
|
||||
getRegister(res); // but make sure we get full register, vndata may be truncated
|
||||
return res;
|
||||
}
|
||||
|
||||
void GhidraTranslate::getUserOpNames(vector<string> &res) const
|
||||
|
||||
{
|
||||
int4 i=0;
|
||||
for(;;) {
|
||||
string nm = glb->getUserOpName(i); // Ask for the next user-defined operator
|
||||
if (nm.size()==0) break;
|
||||
res.push_back(nm);
|
||||
i += 1;
|
||||
}
|
||||
}
|
||||
|
||||
int4 GhidraTranslate::oneInstruction(PcodeEmit &emit,const Address &baseaddr) const
|
||||
|
||||
{
|
||||
int4 offset;
|
||||
uint1 *doc;
|
||||
try {
|
||||
doc = glb->getPcodePacked(baseaddr); // Request p-code for one instruction
|
||||
}
|
||||
catch(JavaError &err) {
|
||||
ostringstream s;
|
||||
s << "Error generating pcode at address: " << baseaddr.getShortcut();
|
||||
baseaddr.printRaw(s);
|
||||
throw LowlevelError(s.str());
|
||||
}
|
||||
if (doc == (uint1 *)0) {
|
||||
ostringstream s;
|
||||
s << "No pcode could be generated at address: " << baseaddr.getShortcut();
|
||||
baseaddr.printRaw(s);
|
||||
throw BadDataError(s.str());
|
||||
}
|
||||
|
||||
uintb val;
|
||||
const uint1 *ptr = PcodeEmit::unpackOffset(doc+1,val);
|
||||
offset = (int4)val;
|
||||
|
||||
if (*doc == PcodeEmit::unimpl_tag) {
|
||||
ostringstream s;
|
||||
s << "Instruction not implemented in pcode:\n ";
|
||||
baseaddr.printRaw(s);
|
||||
delete [] doc;
|
||||
throw UnimplError(s.str(),offset);
|
||||
}
|
||||
|
||||
int4 spcindex = (int4)(*ptr++ - 0x20);
|
||||
AddrSpace *spc = getSpace(spcindex);
|
||||
uintb instoffset;
|
||||
ptr = PcodeEmit::unpackOffset(ptr,instoffset);
|
||||
Address pc(spc,instoffset);
|
||||
|
||||
while(*ptr == PcodeEmit::op_tag)
|
||||
ptr = emit.restorePackedOp(pc,ptr,this);
|
||||
delete [] doc;
|
||||
return offset;
|
||||
}
|
||||
|
||||
/// The Ghidra client passes descriptions of address spaces and other
|
||||
/// information that needs to be cached by the decompiler
|
||||
/// \param el is the element of the initialization tag
|
||||
void GhidraTranslate::restoreXml(const Element *el)
|
||||
|
||||
{
|
||||
setBigEndian(xml_readbool(el->getAttributeValue("bigendian")));
|
||||
{
|
||||
istringstream s(el->getAttributeValue("uniqbase"));
|
||||
s.unsetf(ios::dec | ios::hex | ios::oct);
|
||||
uintm ubase;
|
||||
s >> ubase;
|
||||
setUniqueBase(ubase);
|
||||
}
|
||||
const List &list(el->getChildren());
|
||||
List::const_iterator iter;
|
||||
iter = list.begin();
|
||||
restoreXmlSpaces(*iter,this);
|
||||
++iter;
|
||||
while(iter != list.end()) {
|
||||
const Element *subel = *iter;
|
||||
if (subel->getName() == "truncate_space") {
|
||||
TruncationTag tag;
|
||||
tag.restoreXml(subel);
|
||||
truncateSpace(tag);
|
||||
}
|
||||
++iter;
|
||||
}
|
||||
}
|
||||
|
Loading…
Add table
Add a link
Reference in a new issue