Enumerations and compound values

The functions of this set let you process enumerations and neatly present complex values that actually are an arbitrary number of constants ored together.

Found = OneOf(Value, EnumTable, Format)

OutStr, Rest = BitSet(Value, BitTable)
OutStr = BitSetFmt(Value, BitTable, Format)

Found = OneOf(Value, EnumTable, Format)

This function checks if the given Value is equal to one of named values in given table. If this is true, the function prints the name of the value. If the third parameter (Format) is given, then the function also prints the value according to the given format. If the value is not found in the table, then the function prints the value according to the given format (if any). The function terurns true if the value was found in the table or false otherwise.

Well, sounds awful. Seems like an example of this is much simpler than the explanation. Let's suppose we want to process the Machine field in the PE header. Here we go:

local IMAGE_FILE_MACHINE =
{
    IMAGE_FILE_MACHINE_UNKNOWN      =   0,
    IMAGE_FILE_MACHINE_I386         =   0x014c,
    IMAGE_FILE_MACHINE_R3000        =   0x0162,
    IMAGE_FILE_MACHINE_R4000        =   0x0166,
    IMAGE_FILE_MACHINE_R10000       =   0x0168,
    IMAGE_FILE_MACHINE_WCEMIPSV2    =   0x0169,
    IMAGE_FILE_MACHINE_ALPHA        =   0x0184,
    IMAGE_FILE_MACHINE_POWERPC      =   0x01F0,
    IMAGE_FILE_MACHINE_SH3          =   0x01a2,
    IMAGE_FILE_MACHINE_SH3E         =   0x01a4,
    IMAGE_FILE_MACHINE_SH4          =   0x01a6,
    IMAGE_FILE_MACHINE_ARM          =   0x01c0,
    IMAGE_FILE_MACHINE_THUMB        =   0x01c2,
    IMAGE_FILE_MACHINE_IA64         =   0x0200,
    IMAGE_FILE_MACHINE_MIPS16       =   0x0266,
    IMAGE_FILE_MACHINE_MIPSFPU      =   0x0366,
    IMAGE_FILE_MACHINE_MIPSFPU16    =   0x0466,
    IMAGE_FILE_MACHINE_ALPHA64      =   0x0284
}
 
local function Machine()
    StartType("WORD", "Machine")
    OneOf(GetUI16(), IMAGE_FILE_MACHINE, "0x%04x")
    EndType()
end

Our IMAGE_FILE_MACHINE table contains all possible name/value pairs for this field. Next, we read an unsigned 16 bit integer from the input file and pass it to the OneOf() function along with the table. Additionally, we supply a format because we are curious and want to see the value along with its name. And here is the output for two cases. In the first case the value read from the file is 0x014c, in the second case the value is equal to 0xbad (note that this value cannot be found in the table):

WORD Machine = IMAGE_FILE_MACHINE_I386 /* 0x014c */;
WORD Machine = 0x0bad;

The value returned from the function may be used for special processing when the input value was not found in the table. The function returns false in this case and if the format string hasn't been supplied to the function, it basically does nothing.

OutStr, Rest = BitSet(Value, BitTable)

This function decomposes the given numeric value according to the given table. It returns two values. The first one is a string that contains all found parts separated with the "|" sign. The second one is the rest of the input value that cannot be represented using the given table.

OutStr = BitSetFmt(Value, BitTable, Format)

This function internally uses the previous one. It does almost the same as the BitSet() function. However, it does not return the non-processed rest of the input value but adds it to the output string formatted according to the given format.

Here is an example from the actual PE File template:

local CHARACTERISTICS =
{
    IMAGE_FILE_RELOCS_STRIPPED          =   0x0001,
    IMAGE_FILE_EXECUTABLE_IMAGE         =   0x0002,
    IMAGE_FILE_LINE_NUMS_STRIPPED       =   0x0004,
    IMAGE_FILE_LOCAL_SYMS_STRIPPED      =   0x0008,
    IMAGE_FILE_AGGRESIVE_WS_TRIM        =   0x0010,
    IMAGE_FILE_LARGE_ADDRESS_AWARE      =   0x0020,
    IMAGE_FILE_BYTES_REVERSED_LO        =   0x0080,
    IMAGE_FILE_32BIT_MACHINE            =   0x0100,
    IMAGE_FILE_DEBUG_STRIPPED           =   0x0200,
    IMAGE_FILE_REMOVABLE_RUN_FROM_SWAP  =   0x0400,
    IMAGE_FILE_NET_RUN_FROM_SWAP        =   0x0800,
    IMAGE_FILE_SYSTEM                   =   0x1000,
    IMAGE_FILE_DLL                      =   0x2000,
    IMAGE_FILE_UP_SYSTEM_ONLY           =   0x4000,
    IMAGE_FILE_BYTES_REVERSED_HI        =   0x8000
}

local function Characteristics()
    StartType("WORD", "Characteristics")
    local val = GetUI16()
    PrintNumber(BitSetFmt(val, CHARACTERISTICS, "0x%04x"))
    PrintMLComment(string.format("0x%04x", val))
    EndType()
end

Our CHARACTERISTIC table contains a set of named constants. Next, we read an unsigned 16 bit integer from the input file and pass it to the BitsetFmt() function along with the table. Additionally, we supply a format for the case when the value cannot be fully represented using the given table and at last print the result. The output will look like this (note that it is artificially split into two lines just to make the listing compact, in the real life there is no such splitting):

WORD Characteristics = IMAGE_FILE_32BIT_MACHINE | IMAGE_FILE_DLL | IMAGE_FILE_LOCAL_SYMS_STRIPPED
| IMAGE_FILE_EXECUTABLE_IMAGE | IMAGE_FILE_LINE_NUMS_STRIPPED /* 0x210e */;

If the value in the file were equal to 0x214e (note the 0x40 part, which is not in our table) the output would look this way:

WORD Characteristics = IMAGE_FILE_32BIT_MACHINE | IMAGE_FILE_DLL | IMAGE_FILE_LOCAL_SYMS_STRIPPED
| IMAGE_FILE_EXECUTABLE_IMAGE | IMAGE_FILE_LINE_NUMS_STRIPPED | 0x0040 /* 0x214e */;