fcml  1.2.2
fcml_stateful_assembler.hpp
Go to the documentation of this file.
1 /*
2  * FCML - Free Code Manipulation Library.
3  * Copyright (C) 2010-2020 Slawomir Wojtasiak
4  *
5  * This library is free software; you can redistribute it and/or
6  * modify it under the terms of the GNU Lesser General Public
7  * License as published by the Free Software Foundation; either
8  * version 2.1 of the License, or (at your option) any later version.
9  *
10  * This library is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13  * Lesser General Public License for more details.
14  *
15  * You should have received a copy of the GNU Lesser General Public
16  * License along with this library; if not, write to the Free Software
17  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
18  */
19 
27 #ifndef FCML_STATEFUL_ASSEMBLER_HPP_
28 #define FCML_STATEFUL_ASSEMBLER_HPP_
29 
30 #include <vector>
31 
32 #include "fcml_assembler.hpp"
33 #include "fcml_parser.hpp"
34 
35 namespace fcml {
36 
51 public:
52 
54  class SAFlush {
55  };
56 
69  bool enableParser = false) :
70  _instructionBuilder(IB(FCML_TEXT("")), false),
71  _assembler(assembler),
72  _context(context),
73  _codeLength(0) {
74  // Create parser if needed.
75  _parser = enableParser ? new Parser(assembler.getDialect()) : NULL;
76  }
77 
81  virtual ~StatefulAssembler() {
82  if (_parser) {
83  delete _parser;
84  }
85  }
86 
99  return add(ib);
100  }
101 
113  StatefulAssembler& add(const IB &ib) {
114  flush();
115  _instructionBuilder.setNotNull(true);
116  _instructionBuilder.setValue(ib);
117  return *this;
118  }
119 
129  return inst(mnemonic);
130  }
131 
140  StatefulAssembler& inst(const fcml_cstring &mnemonic) {
141  flush();
142  if (_parser) {
143  // Parse instruction and then pass it to the assembler.
144  _parserContext.setIp(_context.getEntryPoint().getIP());
145  ParserConfig &config = _parserContext.getConfig();
146  config.setThrowExceptionOnError(true);
147  _parser->parse(_parserContext, mnemonic, _parserResult);
148  *this << _parserResult.getInstruction();
149  } else {
150  // Parser is not available, so treat this string as a full
151  // instruction which have to be parsed.
152  _instructionBuilder.setNotNull(true);
153  _instructionBuilder.setValue(IB(mnemonic));
154  }
155  return *this;
156  }
157 
168  return op(Operand(reg));
169  }
170 
181  return op(Operand(imm));
182  }
183 
194  return op(Operand(address));
195  }
196 
207  return op(Operand(pointer));
208  }
209 
219  return op(operand);
220  }
221 
230  StatefulAssembler& op(const Operand &operand) {
231  if (!_instructionBuilder.isNotNull()) {
232  throw IllegalStateException(
233  FCML_TEXT("No instruction builder available."));
234  }
235  IB &ib = _instructionBuilder.getValue();
236  ib.op(operand);
237  return *this;
238  }
239 
250  return op(Operand(reg));
251  }
252 
262  StatefulAssembler& op(const Integer &imm) {
263  return op(Operand(imm));
264  }
265 
275  StatefulAssembler& op(const Address &address) {
276  return op(Operand(address));
277  }
278 
288  StatefulAssembler& op(const FarPointer &pointer) {
289  return op(Operand(pointer));
290  }
291 
300  flush();
301  return *this;
302  }
303 
313  return inst(instruction);
314  }
315 
323  return set(prefix);
324  }
325 
333  return set(hint);
334  }
335 
343  return set(hint);
344  }
345 
352  StatefulAssembler& set(const InstructionPrefix &prefix) {
353  if (!_instructionBuilder.isNotNull()) {
354  throw IllegalStateException(
355  FCML_TEXT("No instruction builder available."));
356  }
357  _instructionBuilder.getValue() << prefix;
358  return *this;
359  }
360 
367  StatefulAssembler& set(const InstructionHint &hint) {
368  if (!_instructionBuilder.isNotNull()) {
369  throw IllegalStateException(
370  FCML_TEXT("No instruction builder available."));
371  }
372  _instructionBuilder.getValue() << hint;
373  return *this;
374  }
375 
382  StatefulAssembler& set(const OperandHint &hint) {
383  if (!_instructionBuilder.isNotNull()) {
384  throw IllegalStateException(
385  FCML_TEXT("No instruction builder available."));
386  }
387  _instructionBuilder.getValue() << hint;
388  return *this;
389  }
390 
399  StatefulAssembler& inst(const Instruction &instruction) {
400 
401  // Flush pending instruction if there is any.
402  flush();
403 
404  // Just in case.
405  AssemblerConf &config = _context.getConfig();
406  config.setIncrementIp(true);
407  config.setThrowExceptionOnError(true);
408 
409  // Assembler the instruction.
410  _assembler.assemble(_context, instruction, _result);
411 
412  // Store the chosen assembled instruction for future use.
413  const AssembledInstruction *assembledInstruction =
414  _result.getChosenInstruction();
415  if (assembledInstruction) {
416  _assembledInstructions.push_back(*assembledInstruction);
417  _codeLength += assembledInstruction->getCodeLength();
418  } else {
420  FCML_TEXT("Chosen instruction hasn't been set. It seems "
421  "that the instruction chooser isn't working "
422  "correctly."));
423  }
424 
425  return *this;
426  }
427 
436  flush();
437  return CodeIterator(_assembledInstructions);
438  }
439 
446  std::vector<AssembledInstruction>& getAssembledInstructions() {
447  flush();
448  return _assembledInstructions;
449  }
450 
457  fcml_usize getCodeLength() {
458  flush();
459  return _codeLength;
460  }
461 
467  void flush() {
468  if (_instructionBuilder.isNotNull()) {
469  // Build an instruction using the instruction builder.
470  Instruction instruction = _instructionBuilder.getValue().build();
471  // And clean the builder, is everything succeed.
472  _instructionBuilder.setNotNull(false);
473  // Assemble the instruction.
474  *this << instruction;
475  }
476  }
477 
483  static SAFlush FLUSH() {
484  return SAFlush();
485  }
486 
490  const ParserConfig& getParserConfig() const {
491  return _parserContext.getConfig();
492  }
493 
499  return _parserContext.getConfig();
500  }
501 
507  const SymbolTable* getSymbolTable() const {
508  return _parserContext.getSymbolTable();
509  }
510 
517  return _parserContext.getSymbolTable();
518  }
519 
525  void setSymbolTable(SymbolTable *symbolTable) {
526  _parserContext.setSymbolTable(symbolTable);
527  }
528 
529 private:
530 
532  Parser *_parser;
534  ParserResult _parserResult;
536  ParserContext _parserContext;
538  AssemblerResult _result;
540  Nullable<IB> _instructionBuilder;
541  /* Assembler used to assemble code. */
542  Assembler &_assembler;
544  AssemblerContext &_context;
545  // Assembled instructions.
546  std::vector<AssembledInstruction> _assembledInstructions;
548  fcml_usize _codeLength;
549 
550 };
551 
552 }
553 
554 #endif /* FCML_STATEFUL_ASSEMBLER_HPP_ */
An instruction builder.
Definition: fcml_common.hpp:7602
C++ wrapper for FCML assembler.
fcml_usize getCodeLength() const
Gets number of bytes in the buffer.
Definition: fcml_assembler.hpp:128
Parser wrapper.
Definition: fcml_parser.hpp:387
static SAFlush FLUSH()
Creates flush indicated for "shift" operators.
Definition: fcml_stateful_assembler.hpp:483
void setThrowExceptionOnError(bool throwExceptionOnError)
Sets the way how the error handling is done.
Definition: fcml_assembler.hpp:487
fcml_usize getCodeLength()
Gets the code length of all assembled instructions available.
Definition: fcml_stateful_assembler.hpp:457
Assembler result.
Definition: fcml_assembler.hpp:182
Illegal state exception.
Definition: fcml_common.hpp:253
StatefulAssembler & op(const Address &address)
Adds the new address operand to the instruction builder associated with the buffer.
Definition: fcml_stateful_assembler.hpp:275
Assembling failed.
Definition: fcml_assembler.hpp:45
std::vector< AssembledInstruction > & getAssembledInstructions()
Gets all chosen assembled instructions.
Definition: fcml_stateful_assembler.hpp:446
std::basic_string< fcml_char > fcml_cstring
By using this type definition here, it will be definitely much easier to support UNICODE in future re...
Definition: fcml_common.hpp:53
Address operand.
Definition: fcml_common.hpp:4601
x86 - 64 register representation.
Definition: fcml_common.hpp:1601
Wraps operand hint and exposes factory methods for instruction hints.
Definition: fcml_common.hpp:461
void flush()
Assembles all pending instructions.
Definition: fcml_stateful_assembler.hpp:467
Assembler context.
Definition: fcml_assembler.hpp:510
Wrapper for nullable value types.
Definition: fcml_common.hpp:120
ParserConfig & getParserConfig()
Gets configuration used by parser if parsing is supported.
Definition: fcml_stateful_assembler.hpp:498
#define FCML_TEXT(x)
Used to code literal strings.
Definition: fcml_types.h:61
StatefulAssembler & op(const Operand &operand)
Adds an operand to the instruction builder associated with the buffer.
Definition: fcml_stateful_assembler.hpp:230
void setSymbolTable(SymbolTable *symbolTable)
Sets a new symbol table for the parser.
Definition: fcml_stateful_assembler.hpp:525
Describes far pointer.
Definition: fcml_common.hpp:3902
Definition: fcml_assembler.hpp:39
Wraps instruction hint and exposes factory methods for instruction hints.
Definition: fcml_common.hpp:402
virtual ~StatefulAssembler()
Destructor.
Definition: fcml_stateful_assembler.hpp:81
Parser configuration.
Definition: fcml_parser.hpp:55
Parser result.
Definition: fcml_parser.hpp:275
Instruction operand.
Definition: fcml_common.hpp:5184
Represents integer value.
Definition: fcml_common.hpp:700
void setIncrementIp(bool incrementIp)
Definition: fcml_assembler.hpp:437
An assembler wrapper.
Definition: fcml_assembler.hpp:717
void op(const Operand &operand)
Sets a next operand for the instruction.
Definition: fcml_common.hpp:7694
Describes an assembled instruction.
Definition: fcml_assembler.hpp:57
StatefulAssembler & inst(const Instruction &instruction)
Assembles an instruction in the given instruction builder.
Definition: fcml_stateful_assembler.hpp:399
StatefulAssembler(Assembler &assembler, AssemblerContext &context, bool enableParser=false)
Creates a stateful assembler for the given assembler and assembler context.
Definition: fcml_stateful_assembler.hpp:68
SymbolTable * getSymbolTable()
Gets symbol table used together with the parser.
Definition: fcml_stateful_assembler.hpp:516
fcml_st_symbol_table & getSymbolTable()
Gets native FCML symbol table.
Definition: fcml_symbols.hpp:181
StatefulAssembler & op(const Register &reg)
Adds the new register operand to the instruction builder associated with the buffer.
Definition: fcml_stateful_assembler.hpp:249
StatefulAssembler & op(const FarPointer &pointer)
Adds the new far pointer operand to the instruction builder associated with the buffer.
Definition: fcml_stateful_assembler.hpp:288
StatefulAssembler & operator<<(const IB &ib)
Adds instruction builder to the stateful assembler.
Definition: fcml_stateful_assembler.hpp:98
StatefulAssembler & inst(const fcml_cstring &mnemonic)
Creates an instruction builder for the given mnemonic.
Definition: fcml_stateful_assembler.hpp:140
CodeIterator getCodeIterator()
Gets iterator which allows to iterate through the whole machine code byte by byte.
Definition: fcml_stateful_assembler.hpp:435
void setThrowExceptionOnError(bool throwExceptionOnError)
Sets exception on error flag.
Definition: fcml_parser.hpp:137
Describes an instruction.
Definition: fcml_common.hpp:7185
Wraps instruction prefix and prepares factory methods for the hints.
Definition: fcml_common.hpp:312
const ParserConfig & getParserConfig() const
Gets configuration used by parser if parsing is supported.
Definition: fcml_stateful_assembler.hpp:490
Assembler configuration.
Definition: fcml_assembler.hpp:321
Parser context.
Definition: fcml_parser.hpp:153
Definition: fcml_symbols.hpp:143
StatefulAssembler & op(const Integer &imm)
Adds the new immediate operand to the instruction builder associated with the buffer.
Definition: fcml_stateful_assembler.hpp:262
Dialect & getDialect() const
Gets dialect associated with the assembler.
Definition: fcml_assembler.hpp:855
const SymbolTable * getSymbolTable() const
Gets symbol table used together with the parser.
Definition: fcml_stateful_assembler.hpp:507
Used only to indicate the need of the flush operation.
Definition: fcml_stateful_assembler.hpp:54
Iterates over machine code bytes from assembled instructions.
Definition: fcml_assembler.hpp:872
It&#39;s a stateful assembler which can be used to assemble instructions one by one on the fly...
Definition: fcml_stateful_assembler.hpp:50
C++ wrapper for instruction parser.
StatefulAssembler & add(const IB &ib)
Adds instruction builder to the stateful assembler.
Definition: fcml_stateful_assembler.hpp:113