Menu

LearnEndiannessPointersErrorHandling

vinicius.ras

Endianness

The RAMvader library can deal with values that are stored in little-endian and in big-endian orders in memory. The process that runs the RAMvader library's code (also called "host process") can even operate in a different endianness scheme as compared to the target process, while RAMvader takes care of any necessary byte-order conversions. The RAMvader library can automatically detect the host process' endianness. As for the target process, its endianness can be defined through the RAMvaderTarget object, by calling its SetTargetEndianness() method.

// Tell RAMvader that the target process uses BIG-ENDIAN scheme
// (assuming "myTarget" is a RAMvaderTarget object)
myTarget.SetTargetEndianness( RAMvaderTarget.EEndianness.evEndiannessBig );

The endianness for the target process can be changed at any time, even before attaching to the target process. When RAMvader needs to perform reading and/or writing operations on the target process' memory space, it compares the target process' assumed endianness to the host process' endianness, and converts byte-orders of values as necessary (i.e., if both processes have different endianness configurations).

Whenever you do not explicitly specify the target process' endianness, the assumed endianness defaults to the same endianness scheme as the host process'.

Pointers

RAMvader supports reading/writing pointer values from/to the target process. But an important question arises here: processes in modern architectures can run either in 32-bit or 64-bit modes, and this affects directly the pointer sizes that are expected on the target process. For 32-bit processes, pointers are stored in memory as 4-byte values. For 64-bit processes, pointers are stored in memory as 8-byte values. It is also important to remember that 32 and 64 bit processes can coexist, running at the same time in the same machine. RAMvader is able to handle both types of pointers through C#'s IntPtr type, but this has some caveats.

The host process (the one which runs RAMvader library's code) and the target process might have different pointer sizes. The RAMvader library can detect the size of the host process' pointer (by checking the return value of IntPtr.Size). The target process' pointer size can be configured through a call to the SetTargetPointerSize() method.

// Tell RAMvader that the target process uses 64-bit pointers
// (assuming "myTarget" is a RAMvaderTarget object)
myTarget.SetTargetPointerSize( RAMvaderTarget.EPointerSize.evPointerSize64 );

If the pointer size for the target process is not defined, RAMvader assumes that the target process uses the same pointer size as the host process.

When reading/writing pointers from/to the target process' memory space, RAMvader checks if they are the same size as the host process'. If both processes run on the same pointer size, operations are performed normally. If both processes have different pointer size configurations, there can be data loss when exchanging data between the two processes. This data loss might lead to unexpected behaviour. So, for safety reasons, RAMvader lets you choose how RAMvaderTarget objects should react when two processes (host and target) use different pointer sizes. You can set how the object reacts to such differences by calling the SetTargetPointerSizeErrorHandling() method. This method might specify one of the following error-handling behaviours:

  • EDifferentPointerSizeError.evThrowException: this is the default behaviour, where RAMvader simply doesn't allow you to read/write from/to the target process' memory space by throwing an PointerDataLostException whenever an I/O operation which deals with pointers is attempted on the target process' memory space. This is the recommended option: it is always a good practice that both host and target processes run on the same platform/architecture.
  • EDifferentPointerSizeError.evSafeTruncation: by using this option, RAMvader allows the host and target processes to have different pointer-sizes, but whenever it performs a read or write operation which involves a 64-bits pointer being exchanged to a 32-bits process, that pointer is truncated and the RAMvader library checks if that operation has caused any data to be lost. In case data is lost, the RAMvader library throws a PointerDataLostException. Data is considered to be lost whenever the 64-bits pointer is an address outside of the range from 0x00000000 to 0xFFFFFFFF.
  • EDifferentPointerSizeError.evUnsafeTruncation: by using this option, RAMvader allows the host and target processes to have different pointer-sizes, but whenever it performs a read or write operation which involves a 64-bits pointer being exchanged to a 32-bits process, that pointer is truncated (i.e., the most significant part of the 64-bits gets discarded, keeping only the least significant 32-bits). This is the less recommended mode, as data might be lost silently during the truncation process.

RAMvader does not support pointer operations on a combination of 32-bit host process trying to attach to a 64-bit process. Pointer operations are a test feature and might not be fully stable when host and target processes run with different pointer sizes. So, it is strongly recommended that pointer operations only be performed when both host and target processes run with the very same pointer sizes (both 32-bits or both 64-bits).

The following table summarizes the support for pointer operations:

Host Process Target Process Support
32-bits 32-bits Fully supported.
64-bits 64-bits Fully supported.
32-bits 64-bits NOT supported.
64-bits 32-bits Supported by configuring RAMvaderTarget.

Related

Wiki: Home

Want the latest updates on software, tech news, and AI?
Get latest updates about software, tech news, and AI from SourceForge directly in your inbox once a month.