Class AssemblyBuffer

java.lang.Object
ghidra.app.plugin.assembler.AssemblyBuffer

public class AssemblyBuffer extends Object
A convenience for accumulating bytes output by an Assembler

This is most useful when there is not a Program available for assembly. If a program is available, consider using GenericAssembler.assemble(Address, String...) and reading the bytes from the program. If not, or the program should not be modified, then the pattern of use is generally:

 Address start = space.getAdddress(0x00400000);
 Assembler asm = Assemblers.getAssembler(...);
 AssemblyBuffer buffer = new AssemblyBuffer(asm, start);
 
 buffer.assemble("PUSH R15");
 buffer.assemble("PUSH R14");
 buffer.assemble("PUSH R13");
 ...
 byte[] bytes = buffer.getBytes();
 state.setVar(start, bytes.length, true, bytes);
 
  • Constructor Details

    • AssemblyBuffer

      public AssemblyBuffer(Assembler asm, Address entry)
      Create a buffer with the given assembler starting at the given entry
      Parameters:
      asm - the assembler
      entry - the starting address where the resulting code will be located
  • Method Details

    • getNext

      public Address getNext()
      Get the address of the "cursor" where the next instruction will be assembled
      Returns:
      the address
    • assemble

      public byte[] assemble(String line) throws AssemblySyntaxException, AssemblySemanticException, IOException
      Assemble a line and append it to the buffer
      Parameters:
      line - the line
      Returns:
      the resulting bytes for the assembled instruction
      Throws:
      AssemblySyntaxException - if the instruction cannot be parsed
      AssemblySemanticException - if the instruction cannot be encoded
      IOException - if the buffer cannot be written
    • assemble

      public byte[] assemble(Address at, String line) throws AssemblySyntaxException, AssemblySemanticException, IOException
      Assemble a line and patch into the buffer

      This will not grow the buffer, so the instruction being patched must already exist in the buffer. The typical use case is to fix up a reference:

       AssemblyBuffer buf = new AssemblyBuffer(asm, entry);
       // ...
       Address jumpCheck = buf.getNext();
       buf.assemble("JMP 0x" + buf.getNext()); // Template must accommodate expected jump distance
       // ...
       Address labelCheck = buf.getNext();
       buf.assemble(jumpCheck, "JMP 0x" + labelCheck);
       buf.assemble("CMP ECX, 0");
       // ...
       

      This does not check that the patched instruction matches length with the new instruction. In fact, the buffer does not remember instruction boundaries at all. If verification is needed, the caller should check the lengths of the returned byte arrays for the template and the patch.

      Parameters:
      at - the address of the instruction to patch
      line - the line
      Returns:
      the resulting bytes for the assembled instruction
      Throws:
      AssemblySyntaxException - if the instruction cannot be parsed
      AssemblySemanticException - if the instruction cannot be encoded
      IOException - if the buffer cannot be written
    • emit

      public byte[] emit(byte[] bytes) throws IOException
      Append arbitrary bytes to the buffer
      Parameters:
      bytes - the bytes to append
      Returns:
      bytes
      Throws:
      IOException - if the buffer cannot be written
    • getBytes

      public byte[] getBytes()
      Get the complete buffer of bytes

      However used, the bytes should be placed at the entry given at construction, unless the client is certain the code is position independent.

      Returns:
      the bytes