You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
stage-one/dependencies/fcml/include/fcml_stateful_disassembler.hpp

211 lines
6.7 KiB

/*
* FCML - Free Code Manipulation Library.
* Copyright (C) 2010-2019 Slawomir Wojtasiak
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
/** @file fcml_stateful_disassembler.hpp
* Stateful FCML disassembler implementation.
*
* @copyright Copyright (C) 2010-2015 Slawomir Wojtasiak. All rights reserved.
* This project is released under the GNU Lesser General Public License.
*/
#ifndef FCML_STATEFUL_DISASSEMBLER_HPP_
#define FCML_STATEFUL_DISASSEMBLER_HPP_
#include "fcml_disassembler.hpp"
#include "fcml_renderer.hpp"
namespace fcml {
/** Stateful disassembler can be used when you have to disassemble a larger
* piece of code one instruction by one.
* It also supports rendering directly using internally managed renderer.
*
* @since 1.1.0
* @remarks This class isn't thread-safe.
*/
class StatefulDisassembler {
public:
/** Creates a stateful disassembler for given FCML disassembler and context.
* Rendering support can be enabled optionally.
* @param disassembler The classic FCML disassembler used to
* disassemble instructions.
* @param context The disassembler context.
* @param enableRendering Enables instruction rendering, which is
* disabled by default.
*/
StatefulDisassembler(Disassembler &disassembler,
DisassemblerContext &context, bool enableRendering = false) :
_disassembler(disassembler),
_disassemblerContext(context) {
_renderer = enableRendering ?
new Renderer(disassembler.getDialect()) : NULL;
// End of line characters to be used when instructions are
// rendered directly to the output stream.
#if defined(_WIN32)
_endOfLine = FCML_TEXT( "\r\n" );
#else
_endOfLine = FCML_TEXT("\n");
#endif
}
/** Destructor. */
virtual ~StatefulDisassembler() {
if (_renderer) {
delete _renderer;
}
}
/**
* Disassembles the next instruction pointed by the disassembler state.
* @param[out] instruction The destination instruction model.
* @return A reference to the stateful disassembler.
* @throws DisassemblingFailedException
* @since 1.1.0
*/
StatefulDisassembler& operator >>(Instruction &instruction) {
// IP has to be incremented automatically, instruction by instruction.
DisassemblerConf &config = _disassemblerContext.getDisassemblerConf();
config.setIncrementIp(true);
config.setThrowExceptionOnError(true);
// We don't care about error handling here, because it's disassembler
// who is responsible for correctly handling it.
_disassembler.disassemble(_disassemblerContext, _disassemblerResult);
instruction = _disassemblerResult.getInstruction();
return *this;
}
/**
* Disassembles the next instruction from the buffer and renders it.
* @param[out] instruction Destination string for the instruction.
* @return A reference to the stateful disassembler.
* @throws DisassemblingFailedException,
* IllegalStateException,
* RenderingFailedException
* @since 1.1.0
*/
StatefulDisassembler& operator >>(fcml_cstring &instruction) {
if (!_renderer) {
throw IllegalStateException(FCML_TEXT("Rendering is disabled."));
}
// IP has to be incremented automatically, instruction by instruction.
DisassemblerConf &config = _disassemblerContext.getDisassemblerConf();
config.setIncrementIp(true);
config.setThrowExceptionOnError(true);
_disassembler.disassemble(_disassemblerContext, _disassemblerResult);
_rendererConfig.setThrowExceptionOnError(true);
_renderer->render(_rendererConfig, _disassemblerResult, instruction);
return *this;
}
/**
* Disassembles the next instruction from the buffer and renders it
* directly into the output stream.
* @param[out] ostream The output stream.
* @return A reference to the stateful disassembler.
* @throws DisassemblingFailedException,
* IllegalStateException,
* RenderingFailedException
* @since 1.1.0
*/
StatefulDisassembler& operator >>(fcml_costream &ostream) {
fcml_cstring instruction;
// Render the next instruction into a string.
*this >> instruction;
// Appends the instruction into an output stream.
ostream << instruction << _endOfLine;
return *this;
}
/**
* Gets renderer configuration used by the instruction buffer.
* @return The renderer configuration.
* @since 1.1.0
*/
RenderConfig& getRendererConfig() {
return _rendererConfig;
}
/**
* Gets renderer configuration used by the internally managed
* instruction renderer.
* @return The renderer configuration.
* @since 1.1.0
*/
const RenderConfig& getRendererConfig() const {
return _rendererConfig;
}
/**
* Gets end of line characters sequence used by the renderer.
*
* @return End of line characters sequence used by the renderer.
* @since 1.1.0
*/
const fcml_cstring& getEndOfLine() const {
return _endOfLine;
}
/**
* Sets dedicated end of line characters.
*
* @param endOfLine A sequence of characters used as line ending.
* @since 1.1.0
*/
void setEndOfLine(const fcml_cstring &endOfLine) {
_endOfLine = endOfLine;
}
private:
/** End of line character sequence. */
fcml_cstring _endOfLine;
/** Disassembler result used when disassembling instructions. */
DisassemblerResult _disassemblerResult;
/** The disassembler used to disassemble the code. */
Disassembler &_disassembler;
/** Disassembler context pointing to the machine code. */
DisassemblerContext &_disassemblerContext;
/** Renderer configuration used when instructions have to be rendered. */
RenderConfig _rendererConfig;
/** Optional renderer used only when instructions are rendered. */
Renderer *_renderer;
};
}
#endif /* FCML_STATEFUL_DISASSEMBLER_HPP_ */