exec (Execute Yaml Script)

Description

The exec command allows you to execute a series of commands defined in a YAML file. This feature enables you to create reusable scripts and automation for debugging tasks.

Syntax

exec <yamlFilePath> [arg1] [arg2] ... [argN]
  • <yamlFilePath>: Path to the YAML file containing the commands to execute.
  • [arg1] [arg2] ... [argN]: Optional arguments that can be passed to the YAML script.
YAML File Structure

The YAML script has following structure:

YAML Structure

variables:
  var1: value1
  var2: value2

commands:
  - command1
  - command2
  - command3
  • variables: A dictionary of key-value pairs that can be used in the commands with mustache templating. Can be a constant, watch expression, or script argument and must not contain any spaces.
  • commands: A list of commands to be executed in order.
Variables Definition & Templating

Variables can be defined and templated in the following ways:

Constants:
variables:
  var1: "filename.txt"
Watch / Debugger expression for evaluation:

Sample code

int main()
{
    // buffer size
    int   bufferSize   = 1024;
    // create buffer
    void* buffer       = calloc(1, bufferSize);
    // release memory
    free(buffer);
    return 0;
}

Script variables using definitions in the code

variables:
  # var1 is evaluated in debugger and replaced with 1024 (see code above)
  var1: "bufferSize"
  # var2 is evaluated in debugger as (512+512) and replaced with result: 1024 (see code above)
  # NOTE: expressions must not contain spaces! "(512 + 512)" will not work.
  var2: "512+512"
Script arguments:
exec dump.yaml buffer.bin buffer 1024

dump.yaml

variables:
  file: "{{$1}}"
  address: "{{$2}}"
  size: "{{$3}}"

commands:
  - dumpmem -f {{file}} {{address}} {{size}}

The above script results in the following command execution:

dumpmem buffer.bin buffer 1024
Example code and yaml script

CPP Code sample

#include <stdint.h>
#include <Windows.h>

int main()
{
    // buffer size
    int   segmentSize = 16;
    // number of segments
    int   numSegments = 3;
    // create buffer
    char* buffer = (char*)calloc(numSegments, segmentSize);
    
    memset(buffer + (0 * segmentSize), 0xA0, segmentSize);
    memset(buffer + (1 * segmentSize), 0xB0, segmentSize);
    memset(buffer + (2 * segmentSize), 0xC0, segmentSize);

    // release memory
    free(buffer);

    return 0;
}

Download

The script below will split the buffer in 3 segment files, and also write all 3 segments in reverse order in segments.bin:

YAML Script

variables:
  # 'buffer' is evaluated at runtime in debug engine api
  ptr_base: "buffer"
  # 'segmentSize' variable will be valuated at execution time in debug engine api
  size: "segmentSize"
  # expressions don't support spaces. 'buffer+(0*segmentSize)' is evaluated later in debug engine api
  # ptr_base mustache variable will be replaced  with 'buffer'
  segData0: "{{ptr_base}}+(0*segmentSize)"
  segFile0: "segment0.bin"
  # expressions don't support spaces.
  segData1: "{{ptr_base}}+(1*segmentSize)"
  segFile1: "segment1.bin"
  # expressions don't support spaces.
  segData2: "{{ptr_base}}+(2*segmentSize)"
  segFile2: "segment2.bin"

commands:
  # write each individual segment to a file
  - dumpmem -f {{segFile0}} {{segData0}} {{size}}
  - dumpmem -f {{segFile1}} {{segData1}} {{size}}
  - dumpmem -f {{segFile2}} {{segData2}} {{size}}
  # write all segments to a single file, but in reverse order
  - dumpmem -a segments.bin {{segData2}} {{size}}
  - dumpmem -a segments.bin {{segData1}} {{size}}
  - dumpmem -a segments.bin {{segData0}} {{size}}

Script Execution

exec segments.yaml
Wrote: 16 bytes to: <file://E:\workspace\segment0.bin>.
Wrote: 16 bytes to: <file://E:\workspace\segment1.bin>.
Wrote: 16 bytes to: <file://E:\workspace\segment2.bin>.
Wrote: 16 bytes to: <file://E:\workspace\segments.bin>.
Wrote: 16 bytes to: <file://E:\workspace\segments.bin>.
Wrote: 16 bytes to: <file://E:\workspace\segments.bin>.

The resulting files have the following content:

segment0.bin

A0 A0 A0 A0 A0 A0 A0 A0 A0 A0 A0 A0 A0 A0 A0 A0

segment1.bin

B0 B0 B0 B0 B0 B0 B0 B0 B0 B0 B0 B0 B0 B0 B0 B0

segment2.bin

C0 C0 C0 C0 C0 C0 C0 C0 C0 C0 C0 C0 C0 C0 C0 C0

segments.bin

C0 C0 C0 C0 C0 C0 C0 C0 C0 C0 C0 C0 C0 C0 C0 C0 
B0 B0 B0 B0 B0 B0 B0 B0 B0 B0 B0 B0 B0 B0 B0 B0 
A0 A0 A0 A0 A0 A0 A0 A0 A0 A0 A0 A0 A0 A0 A0 A0