Package ghidra.app.plugin.assembler

# 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 `Assembler.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 Summary

  Constructors
  Constructor
  Description
  `AssemblyBuffer(Assembler asm, Address entry)`
  Create a buffer with the given assembler starting at the given entry

- ## Method Summary

  Modifier and Type
  Method
  Description
  `byte[]`
  `assemble(Address at, String line)`
  Assemble a line and patch into the buffer
  `byte[]`
  `assemble(String line)`
  Assemble a line and append it to the buffer
  `byte[]`
  `emit(byte[] bytes)`
  Append arbitrary bytes to the buffer
  `byte[]`
  `getBytes()`
  Get the complete buffer of bytes
  `Address`
  `getNext()`
  Get the address of the "cursor" where the next instruction will be assembled

  ### Methods inherited from class java.lang.Object

  `clone, equals, finalize, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait`

- ## 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