#include <mutex>
#include <stdexcept>
#include "bridge.hh"
#include "rust/cxx.h"
#include "libsla-sys/src/sys.rs.h"
ElementId ELEM_PROCESSOR_SPEC = ElementId("processor_spec",147);
RustAssemblyEmitProxy::RustAssemblyEmitProxy(RustAssemblyEmit &emit)
: inner(emit) {
}
void RustAssemblyEmitProxy::dump(
const Address &addr,
const std::string &mnemonic,
const std::string &body
) {
inner.dump(addr, mnemonic, body);
}
void RustPcodeEmitProxy::dump(
const Address &addr,
OpCode op_code,
VarnodeData *outvar,
VarnodeData *vars,
int4 len
) {
std::vector<VarnodeData> inputs(vars, vars + len);
inner.dump(addr, op_code, outvar, inputs);
}
RustLoadImageProxy::RustLoadImageProxy() : LoadImage("undefined") { }
void RustLoadImageProxy::loadFill(uint1 *output_buf, int4 size, const Address &addr) {
if (inner == nullptr) {
throw std::runtime_error(std::string("inner image loader is null"));
}
try {
inner->load_fill(output_buf, size, addr);
} catch (const rust::Error& e) {
throw DataUnavailError(string(e.what()));
}
}
string RustLoadImageProxy::getArchType() const {
return "undefined";
}
void RustLoadImageProxy::adjustVma(long adjust) {
}
RegisterVarnodeName::RegisterVarnodeName(std::pair<VarnodeData, std::string> pair) : pair(pair) {}
const VarnodeData& RegisterVarnodeName::getVarnode() const {
return std::get<0>(pair);
}
const std::string& RegisterVarnodeName::getName() const {
return std::get<1>(pair);
}
SleighProxy::SleighProxy(unique_ptr<RustLoadImageProxy> loader, unique_ptr<ContextDatabase> context)
: Sleigh(loader.get(), context.get()), loader(move(loader)), context(move(context)) {
}
unique_ptr<SleighProxy> construct_new_sleigh(unique_ptr<ContextDatabase> context) {
auto loader = std::unique_ptr<RustLoadImageProxy>(new RustLoadImageProxy());
return std::unique_ptr<SleighProxy>(new SleighProxy(move(loader), move(context)));
}
unique_ptr<ContextDatabase> construct_new_context() {
return std::unique_ptr<ContextDatabase>(new ContextInternal());
}
RustPcodeEmitProxy::RustPcodeEmitProxy(RustPcodeEmit &emit)
: inner(emit) {
}
void initialize_element_id() {
ElementId::initialize();
}
void initialize_attribute_id() {
AttributeId::initialize();
}
unique_ptr<Address> getAddress(const VarnodeData &data) {
return std::unique_ptr<Address>(new Address(data.space, data.offset));
}
uint4 getSize(const VarnodeData &data) {
return data.size;
}
const Document& parseDocumentIntoStore(DocumentStorage &store, const std::string &data) {
std::stringstream ss;
ss << data;
static std::mutex parseDocumentMutex;
const std::lock_guard<std::mutex> lock(parseDocumentMutex);
return *store.parseDocument(ss);
}
const Element& getDocumentRoot(const Document& document) {
return *document.getRoot();
}
void parseDocumentAndRegisterRootElement(DocumentStorage &store, const std::string &data) {
auto& doc = parseDocumentIntoStore(store, data);
store.registerTag(doc.getRoot());
}
void SleighProxy::parseProcessorConfig(const DocumentStorage &store) {
const Element *element = store.getTag("processor_spec");
if (element == (const Element*)0) {
throw LowlevelError("No processor_spec tag found");
}
XmlDecode decoder(this, element);
uint4 elementId = decoder.openElement(ELEM_PROCESSOR_SPEC);
for (;;) {
uint4 subId = decoder.peekElement();
if (subId == 0) {
break;
} else if (subId != ELEM_CONTEXT_DATA) {
decoder.openElement();
decoder.closeElementSkipping(subId);
} else {
context->decodeFromSpec(decoder);
}
}
}
std::unique_ptr<std::string> SleighProxy::getRegisterNameProxy(AddrSpace *base, uintb off, int4 size) const {
return std::unique_ptr<std::string>(new std::string(getRegisterName(base, off, size)));
}
std::unique_ptr<std::vector<RegisterVarnodeName>> SleighProxy::getAllRegistersProxy() const {
std::map<VarnodeData, std::string> regmap;
getAllRegisters(regmap);
auto reglist = std::unique_ptr<std::vector<RegisterVarnodeName>>(new std::vector<RegisterVarnodeName>());
for (auto ®mapEntry : regmap) {
reglist->push_back(RegisterVarnodeName(regmapEntry));
}
return reglist;
}
void SleighProxy::initializeFromSla(const std::string &sla) {
std::stringstream slaStream(sla);
if (!isInitialized()) {
sla::FormatDecode decoder(this);
decoder.ingestStream(slaStream);
decode(decoder);
}
if (isInitialized()) {
DocumentStorage store;
initialize(store);
} else {
throw LowlevelError("Failed to initialize sleigh");
}
}
void SleighProxy::initializeFromRawSla(const std::string &sla) {
std::stringstream slaStream(sla);
if (!isInitialized()) {
RawFormatDecode decoder(this);
decoder.ingestStream(slaStream);
decode(decoder);
}
if (isInitialized()) {
DocumentStorage store;
initialize(store);
} else {
throw LowlevelError("Failed to initialize sleigh");
}
}
int4 SleighProxy::disassemblePcode(const RustLoadImage &loadImage, RustPcodeEmit &emit, const Address &baseaddr) const {
RustLoadImageManager manager { *loader.get(), loadImage };
auto proxy = RustPcodeEmitProxy(emit);
return Sleigh::oneInstruction(proxy, baseaddr);
}
int4 SleighProxy::disassembleNative(const RustLoadImage &loadImage, RustAssemblyEmit &emit, const Address &baseaddr) const {
RustLoadImageManager manager { *loader.get(), loadImage };
auto proxy = RustAssemblyEmitProxy(emit);
return Sleigh::printAssembly(proxy, baseaddr);
}
RustLoadImageManager::RustLoadImageManager(RustLoadImageProxy &proxy, const RustLoadImage &loadImage)
: proxy(proxy) {
this->proxy.setInner(loadImage);
}
RustLoadImageManager::~RustLoadImageManager() {
this->proxy.resetInner();
}
const int4 RawFormatDecode::IN_BUFFER_SIZE = 4096;
RawFormatDecode::RawFormatDecode(const AddrSpaceManager *spcManager)
: PackedDecode(spcManager)
{
inBuffer = new uint1[IN_BUFFER_SIZE];
}
RawFormatDecode::~RawFormatDecode(void) {
delete[] inBuffer;
}
void RawFormatDecode::ingestStream(istream &s) {
uint1 *outBuf;
int4 outAvail = 0;
while (true) {
s.read((char *)inBuffer,IN_BUFFER_SIZE);
int4 gcount = s.gcount();
if (gcount == 0)
break;
int4 inAvail = gcount;
do {
if (outAvail == 0) {
outBuf = allocateNextInputBuffer(0);
outAvail = BUFFER_SIZE;
}
int4 copySize = std::min(outAvail, inAvail);
memcpy(outBuf + (BUFFER_SIZE - outAvail), inBuffer + (gcount - inAvail), copySize);
outAvail -= copySize;
inAvail -= copySize;
} while(outAvail == 0);
}
endIngest(BUFFER_SIZE - outAvail);
}