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.

227 lines
6.3 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_renderer.hpp
* C++ wrapper for FCML renderer.
*
* @copyright Copyright (C) 2010-2015 Slawomir Wojtasiak. All rights reserved.
* This project is released under the GNU Lesser General Public License.
*/
#ifndef FCML_RENDERER_HPP_
#define FCML_RENDERER_HPP_
#include "fcml_common.hpp"
#include "fcml_disassembler.hpp"
#include "fcml_renderer.h"
namespace fcml {
/**
* Component can not be initialized correctly.
*/
class RenderingFailedException: public BaseException {
public:
RenderingFailedException(const fcml_cstring &msg, fcml_ceh_error error =
FCML_CEH_GEC_NO_ERROR) :
BaseException(msg, error) {
}
};
/** Renderer configuration.
*
* It's a counterpart to the fcml_st_render_config structure.
* @since 1.1.0
*/
class RenderConfig {
public:
/**
* Creates an empty renderer configuration.
* @since 1.1.0
*/
RenderConfig() :
_throwExceptionOnError(true),
_renderFlags(0),
_preferedMnemonicPadding(FCML_REND_DEFAULT_MNEMONIC_PADDING),
_preferedCodePadding(FCML_REND_DEFAULT_CODE_PADDING) {
}
/**
* Creates a renderer configuration for given renderer flags.
*
* @param renderFlags The renderer flags.
* @since 1.1.0
*/
RenderConfig(fcml_uint32_t renderFlags) :
_throwExceptionOnError(true),
_renderFlags(renderFlags),
_preferedMnemonicPadding(0),
_preferedCodePadding(0) {
}
/** @since 1.1.0 */
fcml_uint16_t getPreferedCodePadding() const {
return _preferedCodePadding;
}
/** @since 1.1.0 */
void setPreferedCodePadding(fcml_uint16_t preferedCodePadding) {
_preferedCodePadding = preferedCodePadding;
}
/** @since 1.1.0 */
fcml_uint16_t getPreferedMnemonicPadding() const {
return _preferedMnemonicPadding;
}
/** @since 1.1.0 */
void setPreferedMnemonicPadding(fcml_uint16_t preferedMnemonicPadding) {
_preferedMnemonicPadding = preferedMnemonicPadding;
}
/** @since 1.1.0 */
fcml_uint32_t getRenderFlags() const {
return _renderFlags;
}
/** @since 1.1.0 */
void setRenderFlags(fcml_uint32_t renderFlags) {
_renderFlags = renderFlags;
}
/**
* Returns true if exception should be thrown when disassembling fails.
*
* @return True if exception is the preferred way of error handling
* in case of failure.
* @since 1.1.0
*/
bool isThrowExceptionOnError() const {
return _throwExceptionOnError;
}
/**
* Sets the way how the error handling is done.
*
* @param throwExceptionOnError True if exception should be thrown
* in case of failure.
* @since 1.1.0
*/
void setThrowExceptionOnError(bool throwExceptionOnError) {
_throwExceptionOnError = throwExceptionOnError;
}
private:
/** Throws exception in case of error. */
bool _throwExceptionOnError;
/** Flags which allows to control rendering process. */
fcml_uint32_t _renderFlags;
/** Preferred mnemonic padding in characters. */
fcml_uint16_t _preferedMnemonicPadding;
/** Preferred code padding in HEX bytes (2 characters on one byte.). */
fcml_uint16_t _preferedCodePadding;
};
/**
* Converts objects to their structures counterparts.
* @since 1.1.0
* @remarks Internal API, not intended to be used outside.
*/
class RenderTypeConverter {
public:
static void convert(const RenderConfig &src, fcml_st_render_config &dest) {
dest.prefered_code_padding = src.getPreferedCodePadding();
dest.prefered_mnemonic_padding = src.getPreferedMnemonicPadding();
dest.render_flags = src.getRenderFlags();
}
};
/** Renderer wrapper.
* @since 1.1.0
*/
class Renderer: protected DialectAware {
public:
/**
* Creates a renderer instance for the given dialect.
*
* @param dialect The dialect instance.
* @since 1.1.0
*/
Renderer(Dialect &dialect) :
_dialect(dialect) {
}
/**
* Renders a disassembled instruction.
*
* @param renderConfig A renderer configuration.
* @param assemblerResult The disassembler result.
* @param[out] result The rendered instruction.
* @throw RenderingFailedException Rendering failed.
* @return The error code.
*/
fcml_ceh_error render(const RenderConfig &renderConfig,
DisassemblerResult &assemblerResult, fcml_cstring &result) {
result.clear();
fcml_st_render_config render_config;
RenderTypeConverter::convert(renderConfig, render_config);
fcml_st_disassembler_result disassembler_result;
fcml_fn_disassembler_result_prepare(&disassembler_result);
DisassemblerTypeConverter::convert(assemblerResult,
disassembler_result);
fcml_char buffer[FCML_REND_MAX_BUFF_LEN];
fcml_ceh_error error = ::fcml_fn_render(extractDialect(_dialect),
&render_config, buffer, FCML_REND_MAX_BUFF_LEN,
&disassembler_result);
DisassemblerTypeConverter::free(disassembler_result);
if (error && renderConfig.isThrowExceptionOnError()) {
throw RenderingFailedException(
FCML_TEXT("Can not render instruction."), error);
}
result = buffer;
return error;
}
private:
/** The dialect instance associated with the renderer. */
Dialect &_dialect;
};
}
#endif /* FCML_RENDERER_HPP_ */