These have special semantics (number of elements in C# vs. number of bytes in IL), and so pointer arithmetic must go through the special HandlePointerArithmetic() code path --> the normal logic in HandleBinaryNumeric must not ever emit pointer arithmetic.
Based on the definition of the "BaseOfData" field as found in the official documentation ( https://docs.microsoft.com/en-us/windows/win32/debug/pe-format#optional-header-standard-fields-image-only ), and confirmed via a PE32+ SQL Server DLL (sqlaccess):
1. Updated the "Meaning" to include:
1. the value that this particular value is relative to (i.e. "ImageBase").
2. the fact that this value is _not_ present in PE32Plus (only regular 'ol PE32):
1. Placed this info at the beginning (i.e. far left) of the "Meaning" to increase visibility and reduce the chances of it not being seen (since it might be unexpected to simply not exist for certain images).
2. Intentionally stated both that it's not present in PE32Plus, _and_ only present in PE32, to be as clear as possible as to why the offset is 0 for PE32Plus.
2. Updated the "Offset" to be conditional, based on whether or not image is PE32Plus (same condition used for "Size" and "Value"). It now shows 0 for PE32Plus as this field does not exist under this condition. Showing a 0 offset is preferable to removing this field / entry entirely as that might lead to confusion for those who would have no idea why this field / entry was missing.
3. Updated the "Value" to be a literal 0 (ulong; was reading next UInt64 from the header).
4. Updated the "Size" to be 0 if image is PE32Plus (was 8 bytes).
Also:
5. Simplified multiple occurrences of `header.Magic == PEMagic.PE32Plus` test with a new variable: `isPE32Plus`.
Made changes to several of the "Meaning" values of the "DLL Characteristics" flags in order to match the official documentation ( https://docs.microsoft.com/en-us/dotnet/api/system.reflection.portableexecutable.dllcharacteristics ):
1. Added definitions for first four values (0x01, 0x02, 0x04, and 0x08); it seems that they are "Reserved" instead of "Unused". I'm not sure if these values will ever be seen, but I figured it best to include the definitions since they seems to exist.
2. Changed wording in option 0x1000 to be "must" instead of "should" as it's both clearer and matches the documentation.
3. For option 0x20, the description here was "ASLR with 64-bit address space", while the documentation has it as "The image can handle a high entropy 64-bit virtual address space". After reviewing https://en.wikipedia.org/wiki/Address_space_layout_randomization I believe it's best to favor the documentation but also include 'ASLR' since that's really what the option pertains to.
Please note that options 0x80 and 0x4000 (copied below) are, for some odd reason, missing from the official documentation. I don't see a reason to remove them as the documentation is not 100% correct and sometimes things are left out. Should we add a comment in the C# code on each of those two lines indicating the disparity? For now I'm not doing that but might not be a bad idea to make it visible there since nobody will ever see this note here:
<0080> Code integrity checks are enforced
<4000> Image supports Control Flow Guard
Offsets in this metadata section are missing the base offset and thus start at 00000000 instead of at something like 00000098. I applied the base offset in the same manner that it's being applied in CoffHeaderTreeNode.cs.