Dr. Memory
 All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Groups Pages
Umbra: DynamoRIO Shadow Memory Extension

Data Structures

struct  _umbra_shadow_memory_info_t
struct  _umbra_map_options_t

Macros

#define DRMGR_PRIORITY_NAME_EXCPT_UMBRA   "umbra_except"
#define UMBRA_MAP_SCALE_IS_UP(scale)   ((scale) >= UMBRA_MAP_SCALE_UP_2X)

Typedefs

typedef struct
_umbra_shadow_memory_info_t 
umbra_shadow_memory_info_t
typedef struct _umbra_map_t umbra_map_t
typedef void(* app_memory_create_cb_t )(umbra_map_t *map, app_pc start, size_t size)
typedef struct _umbra_map_options_t umbra_map_options_t
typedef bool(* shadow_iterate_func_t )(umbra_map_t *map, umbra_shadow_memory_info_t *info, void *user_data)

Enumerations

enum  { DRMGR_PRIORITY_EXCPT_UMBRA = -100 }
enum  umbra_map_scale_t { ,
  UMBRA_MAP_SCALE_DOWN_4X,
  UMBRA_MAP_SCALE_DOWN_2X,
  UMBRA_MAP_SCALE_SAME_1X,
  UMBRA_MAP_SCALE_UP_2X
}
enum  umbra_map_flags_t {
  UMBRA_MAP_CREATE_SHADOW_ON_TOUCH = 0x1,
  UMBRA_MAP_SHADOW_SHARED_READONLY = 0x2
}
enum  umbra_shadow_memory_flags_t { UMBRA_CREATE_SHADOW_SHARED_READONLY = 0x1 }
enum  umbra_shadow_memory_type_t {
  UMBRA_SHADOW_MEMORY_TYPE_UNKNOWN = 0x1,
  UMBRA_SHADOW_MEMORY_TYPE_NOT_SHADOW = 0x2,
  UMBRA_SHADOW_MEMORY_TYPE_NORMAL = 0x4,
  UMBRA_SHADOW_MEMORY_TYPE_SHARED = 0x8,
  UMBRA_SHADOW_MEMORY_TYPE_SHADOW_NOT_ALLOC = 0x10
}

Functions

DR_EXPORT drmf_status_t umbra_init (client_id_t client_id)
DR_EXPORT drmf_status_t umbra_exit (void)
DR_EXPORT drmf_status_t umbra_create_mapping (IN umbra_map_options_t *ops, OUT umbra_map_t **map_out)
DR_EXPORT drmf_status_t umbra_destroy_mapping (IN umbra_map_t *map)
DR_EXPORT drmf_status_t umbra_create_shadow_memory (IN umbra_map_t *map, IN umbra_shadow_memory_flags_t flags, IN app_pc app_addr, IN size_t app_size, IN ptr_uint_t value, IN size_t value_size)
DR_EXPORT drmf_status_t umbra_delete_shadow_memory (IN umbra_map_t *map, IN app_pc app_addr, IN size_t app_size)
DR_EXPORT drmf_status_t umbra_num_scratch_regs_for_translation (OUT int *num_regs)
DR_EXPORT drmf_status_t umbra_insert_app_to_shadow (IN void *drcontext, IN umbra_map_t *map, IN instrlist_t *ilist, IN instr_t *where, IN reg_id_t addr_reg, IN reg_id_t *scratch_regs, IN int num_scratch_regs)
DR_EXPORT drmf_status_t umbra_read_shadow_memory (IN umbra_map_t *map, IN app_pc app_addr, IN size_t app_size, INOUT size_t *shadow_size, OUT byte *buffer)
DR_EXPORT drmf_status_t umbra_write_shadow_memory (IN umbra_map_t *map, IN app_pc app_addr, IN size_t app_size, INOUT size_t *shadow_size, IN byte *buffer)
DR_EXPORT drmf_status_t umbra_shadow_set_range (IN umbra_map_t *map, IN app_pc app_addr, IN size_t app_size, OUT size_t *shadow_size, IN ptr_uint_t value, IN size_t value_size)
DR_EXPORT drmf_status_t umbra_shadow_copy_range (IN umbra_map_t *map, IN app_pc app_src, IN app_pc app_dst, IN size_t app_size, OUT size_t *shadow_size)
DR_EXPORT drmf_status_t umbra_value_in_shadow_memory (IN umbra_map_t *map, INOUT app_pc *app_addr, IN size_t app_size, IN ptr_uint_t value, IN size_t value_size, OUT bool *found)
DR_EXPORT drmf_status_t umbra_get_shadow_block_size (IN umbra_map_t *map, OUT size_t *size)
DR_EXPORT drmf_status_t umbra_iterate_app_memory (IN umbra_map_t *map, IN void *user_data, IN bool(*iter_func)(umbra_map_t *map, const dr_mem_info_t *info, void *user_data))
DR_EXPORT drmf_status_t umbra_iterate_shadow_memory (IN umbra_map_t *map, IN void *user_data, IN shadow_iterate_func_t iter_func)
DR_EXPORT drmf_status_t umbra_get_shadow_memory_type (IN umbra_map_t *map, IN byte *shadow_addr, OUT umbra_shadow_memory_type_t *shadow_type)
DR_EXPORT drmf_status_t umbra_shadow_memory_is_shared (IN umbra_map_t *map, IN byte *shadow_addr, OUT umbra_shadow_memory_type_t *shadow_type)
DR_EXPORT drmf_status_t umbra_get_shadow_memory (IN umbra_map_t *map, IN app_pc app_addr, OUT byte **shadow_addr, INOUT umbra_shadow_memory_info_t *shadow_info)
DR_EXPORT drmf_status_t umbra_replace_shared_shadow_memory (IN umbra_map_t *map, IN app_pc app_addr, OUT byte **shadow_addr)
DR_EXPORT drmf_status_t umbra_create_shared_shadow_block (IN umbra_map_t *map, IN ptr_uint_t value, IN size_t value_size, OUT byte **block)
DR_EXPORT drmf_status_t umbra_get_shared_shadow_block (IN umbra_map_t *map, IN ptr_uint_t value, IN size_t value_size, OUT byte **block)
static void umbra_shadow_memory_info_init (umbra_shadow_memory_info_t *info)

Detailed Description


Macro Definition Documentation

#define DRMGR_PRIORITY_NAME_EXCPT_UMBRA   "umbra_except"

Name of Umbra signal/exception events.

#define UMBRA_MAP_SCALE_IS_UP (   scale)    ((scale) >= UMBRA_MAP_SCALE_UP_2X)

Check if a shadow memory mapping scale is scale up or down.


Typedef Documentation

typedef void(* app_memory_create_cb_t)(umbra_map_t *map, app_pc start, size_t size)

Application memory creation/deletion callback function type. These callbacks are called when the application performs system calls to allocate or delete memory.

typedef bool(* shadow_iterate_func_t)(umbra_map_t *map, umbra_shadow_memory_info_t *info, void *user_data)

Iterate callback function type for umbra_iterate_shadow_memory.

Parameters:
[in]mapThe mapping object to use.
[in]infoInformation about the shadow memory.
[in]user_dataUser data passed during iteration.

Specifies parameters controlling the behavior of umbra_create_map().

typedef struct _umbra_map_t umbra_map_t

Opaque "Umbra map handle" type used to refer to a particular Umbra mapping scheme object created by umbra_create_mapping(),

Information about a shadow memory region.


Enumeration Type Documentation

anonymous enum

Priority of Umbra events.

Enumerator:
DRMGR_PRIORITY_EXCPT_UMBRA 

Priority of the Umbra signal/exception handling event. This event must take place before any user of drsyscall in order to allocate shadow memory if necessary.

Umbra mapping creation flags for fine-grained control

Enumerator:
UMBRA_MAP_CREATE_SHADOW_ON_TOUCH 

If set, Umbra will try to create the shadow memory on the access to shadow memory that is not yet. When using this option, the user should handle exceptions caused by referencing shadow memory that Umbra fails to handle.

UMBRA_MAP_SHADOW_SHARED_READONLY 

This is an optimization hint for reducing memory usage by allowing Umbra to map different application memory regions with identical shadow value to the same shared shadow memory block. Attempts to directly write shared shadow memory will cause exceptions that should be handled by the user.

Shadow memory mapping (scaling) schemes supported by Umbra.

Note:
: Umbra does not support bit operations, so parameters passed to any Umbra routine will be automatically aligned for proper translation. For example, application memory address app_addr will be aligned to 8 if using UMBRA_MAP_SCALE_DOWN_8X mapping scheme.
Enumerator:
UMBRA_MAP_SCALE_DOWN_4X 

8 app byte to 1 shadow byte

UMBRA_MAP_SCALE_DOWN_2X 

4 app byte to 1 shadow byte

UMBRA_MAP_SCALE_SAME_1X 

2 app byte to 1 shadow byte

UMBRA_MAP_SCALE_UP_2X 

1 app byte to 1 shadow byte

Shadow memory creation flags used in umbra_create_shadow_memory.

Enumerator:
UMBRA_CREATE_SHADOW_SHARED_READONLY 

This is an optimization hint for reducing memory usage by allowing Umbra to map different application memory regions with identical shadow value to the same shared shadow memory block. Attempts to directly write shared shadow memory will cause exceptions that should be handled by the user. This allows user to control each individual shadow memory creation whether using special shared block or not.

Shadow memory type.

Note:
: A shadow memory may have more than one type, e.g., an address in redzone of shared special shadow memory block will return value with both UMBRA_SHADOW_MEMORY_TYPE_SHARED and UMBRA_SHADOW_MEMORY_TYPE_REDZONE being set.
Enumerator:
UMBRA_SHADOW_MEMORY_TYPE_UNKNOWN 

Unknown memory type

UMBRA_SHADOW_MEMORY_TYPE_NOT_SHADOW 

Not a shadow memory: i.e., the address being translated is not from a valid application memory region. Umbra does not support storing metadata in shadow memory for such addresses.

UMBRA_SHADOW_MEMORY_TYPE_NORMAL 

Normal writable shadow memory

UMBRA_SHADOW_MEMORY_TYPE_SHARED 

Special read-only shadow memory

UMBRA_SHADOW_MEMORY_TYPE_SHADOW_NOT_ALLOC 

Should be shadow memory, but not allocated yet


Function Documentation

DR_EXPORT drmf_status_t umbra_create_mapping ( IN umbra_map_options_t ops,
OUT umbra_map_t **  map_out 
)

Create a shadow memory mapping according to the mapping options ops, and return the opaque pointer in map_out.

Parameters:
[in]opsThe mapping object to use.
[out]map_outThe mapping options.
DR_EXPORT drmf_status_t umbra_create_shadow_memory ( IN umbra_map_t map,
IN umbra_shadow_memory_flags_t  flags,
IN app_pc  app_addr,
IN size_t  app_size,
IN ptr_uint_t  value,
IN size_t  value_size 
)

Create shadow memory for application memory using mapping scheme map.

Parameters:
[in]mapThe mapping object to use.
[in]flagsShadow memory creation options.
[in]app_addrApplication memory address.
[in]app_sizeApplication memory size.
[in]valueThe initial value in shadow memory.
[in]value_sizeThe initial value size, could be 1, 2, 4, or 8 (x64). Only 1 is supported now.
Returns:
success code. If app_addr is not a valid application address and the shadow mapping implementation does not support shadow memory for invalid addresses, returns DRMF_ERROR_INVALID_ADDRESS.
Note:
: If the newly created shadow memory overlaps with the existing shadow memory, the value of overlapped part will be clobbered with new value.
: The actual size of created shadow memory might be larger than the required size, the extended part will be set as default value specified on map creation.
DR_EXPORT drmf_status_t umbra_create_shared_shadow_block ( IN umbra_map_t map,
IN ptr_uint_t  value,
IN size_t  value_size,
OUT byte **  block 
)

Create special shared shadow memory that Umbra can map different application regions with the same shadow value as value to it.

Parameters:
[in]mapThe mapping object to use.
[in]valueThe value used by the shadow block.
[in]value_sizeThe value size used by the shadow block.
[out]blockThe pointer pointing to the base of the shadow block. Returns NULL if Umbra fails to create one.
Note:
: Umbra only creates special shared shadow memory if necessary. This routine forces Umbra create one even Umbra may not use it.
: Umbra does not use special shared shadow block in current x64 implementation and always returns DRMF_ERROR_FEATURE_NOT_AVAILABLE.
DR_EXPORT drmf_status_t umbra_delete_shadow_memory ( IN umbra_map_t map,
IN app_pc  app_addr,
IN size_t  app_size 
)

Delete shadow memory from mapping scheme map for application memory at app_addr.

Parameters:
[in]mapThe mapping object to use.
[in]app_addrApplication memory address.
[in]app_sizeApplication memory size.
Returns:
success code. If app_addr is not a valid application address and the shadow mapping implementation does not support shadow memory for invalid addresses, returns DRMF_ERROR_INVALID_ADDRESS.
Note:
: part of the shadow memory might not be actually deleted, which will be set to the value specified on map creation instead.
DR_EXPORT drmf_status_t umbra_destroy_mapping ( IN umbra_map_t map)

Destroy a shadow memory mapping map created by umbra_create_mapping.

DR_EXPORT drmf_status_t umbra_exit ( void  )

Clean up the Umbra extension.

DR_EXPORT drmf_status_t umbra_get_shadow_block_size ( IN umbra_map_t map,
OUT size_t *  size 
)

Get the shadow block size, which is the unit size Umbra allocates/frees the shadow memory.

Parameters:
[in]mapThe mapping object to use.
[out]sizeThe shadow memory block size.
DR_EXPORT drmf_status_t umbra_get_shadow_memory ( IN umbra_map_t map,
IN app_pc  app_addr,
OUT byte **  shadow_addr,
INOUT umbra_shadow_memory_info_t shadow_info 
)

Get shadow memory address for application memory address app_addr.

Parameters:
[in]mapThe mapping object to use.
[in]app_addrThe application memory address.
[out]shadow_addrThe shadow memory address for app_addr.
[in,out]shadow_infoThe information about the shadow memory for app_addr.

For lazily allocated shadow memory, this routine will not allocate shadow memory that is not yet allocated. The caller must explicitly call umbra_create_shadow_memory() prior to de-referencing the returned shadow address if the type is UMBRA_SHADOW_MEMORY_TYPE_SHADOW_NOT_ALLOC. Use umbra_read_shadow_memory() or umbra_write_shadow_memory() if automatic allocation is desired.

Note:
: shadow_info->struct_size must be set to sizeof(umbra_shadow_memory_info_t) for compatiblity.
: shadow_info contains the information about the shadow memory block and its application memory, so the caller can cache the information and access the shadow memory later without querying Umbra again. However, if the shadow memory is a special shared memory block, it may be replaced with normal shadow memory and the caller will not see it, and the caller will see the old special value if using cached information. It is up to the caller to decide whether this is acceptable.
: No redzone will be included in the shadow_info.
DR_EXPORT drmf_status_t umbra_get_shadow_memory_type ( IN umbra_map_t map,
IN byte *  shadow_addr,
OUT umbra_shadow_memory_type_t shadow_type 
)

Get shadow memory type for address shadow_addr.

Parameters:
[in]mapThe mapping object to use.
[in]shadow_addrThe shadow memory address for app_addr.
[out]shadow_typeThe type of the shadow memory at shadow_addr.
Note:
: this routine has high runtime overhead since it may need iterate all shadow memory to determine the shadow memory type for shadow_addr.
DR_EXPORT drmf_status_t umbra_get_shared_shadow_block ( IN umbra_map_t map,
IN ptr_uint_t  value,
IN size_t  value_size,
OUT byte **  block 
)

Get special shared shadow memory created by umbra_create_shared_shadow_block or Umbra with identical value and value_size.

Parameters:
[in]mapThe mapping object to use.
[in]valueThe value used by the shadow block.
[in]value_sizeThe value size used by the shadow block.
[out]blockThe pointer pointing to the base of the shadow block. Returns NULL if Umbra fails to find one.
Note:
: Umbra does not use special shared shadow block in current x64 implementation and always returns DRMF_ERROR_FEATURE_NOT_AVAILABLE.
DR_EXPORT drmf_status_t umbra_init ( client_id_t  client_id)

Initialize the Umbra extension. Must be called prior to any of the other routines. Can be called multiple times (by separate components, normally) but each call must be paired with a corresponding call to umbra_exit().

Parameters:
[in]client_idThe client id for version check.
Returns:
success code.
DR_EXPORT drmf_status_t umbra_insert_app_to_shadow ( IN void *  drcontext,
IN umbra_map_t map,
IN instrlist_t *  ilist,
IN instr_t *  where,
IN reg_id_t  addr_reg,
IN reg_id_t *  scratch_regs,
IN int  num_scratch_regs 
)

Insert instructions into ilist before where to translate application address stored in reg_addr to shadow address and store it into reg_addr.

Umbra may use page faults to implement lazy shadow memory allocation. When generating meta instructions to read shadow values, be sure to assign translation values to the instructions.

Parameters:
[in]drcontextThe DynamoRIO context for current thread.
[in]mapThe mapping object to use.
[in]ilistThe instruction list to be inserted into.
[in]whereThe instruction to be inserted before
[in]addr_regThe Register holding the application address for translation, and holding the shadow memory address after translation.
[in]scratch_regsThe array of scratch registers for use.
[in]num_scratch_regsNumber of scratch register
Note:
: num_scratch_regs must not be smaller than the value returned from umbra_num_scratch_regs_for_translation, otherwise error code DRMF_ERROR_NOT_ENOUGH_REGS is returned.
DR_EXPORT drmf_status_t umbra_iterate_app_memory ( IN umbra_map_t map,
IN void *  user_data,
IN bool(*)(umbra_map_t *map, const dr_mem_info_t *info, void *user_data)  iter_func 
)

Iterate the application memory (i.e., any memory that are not part of shadow memory, DynamoRIO internal memory, or DynamoRIO's client memory).

Parameters:
[in]mapThe mapping object to use.
[in]user_dataThe user data passed to iter_func.
[in]iter_funcThe iterate callback function. It can return false to stop the iteration.
Note:
: the memory allocated by dr_raw_mem_alloc by client might be iterated since they are not considered as part of DynamoRIO internal or client memory.
DR_EXPORT drmf_status_t umbra_iterate_shadow_memory ( IN umbra_map_t map,
IN void *  user_data,
IN shadow_iterate_func_t  iter_func 
)

Iterate shadow memory and call iter_func on each shadow memory block.

Parameters:
[in]mapThe mapping object to use.
[in]user_dataThe user data passed to iter_func.
[in]iter_funcThe iterate callback function. It can return false to stop the iteration.
DR_EXPORT drmf_status_t umbra_num_scratch_regs_for_translation ( OUT int *  num_regs)

Query the number of scratch registers needed (excluding the register holding the application address) for address translation from application memory to shadow memory.

Parameters:
[out]num_regsNumber of scratch register required for translation.
DR_EXPORT drmf_status_t umbra_read_shadow_memory ( IN umbra_map_t map,
IN app_pc  app_addr,
IN size_t  app_size,
INOUT size_t *  shadow_size,
OUT byte *  buffer 
)

Read shadow memory for application memory at app_addr to buffer.

Parameters:
[in]mapThe mapping object to use.
[in]app_addrApplication memory address.
[in]app_sizeApplication memory size.
[in,out]shadow_sizeThe max buffer size. Return the number of bytes actually read.
[out]bufferThe buffer holds the read value.
Returns:
success code. If app_addr is not a valid application address and the shadow mapping implementation does not support shadow memory for invalid addresses, returns DRMF_ERROR_INVALID_ADDRESS.
DR_EXPORT drmf_status_t umbra_replace_shared_shadow_memory ( IN umbra_map_t map,
IN app_pc  app_addr,
OUT byte **  shadow_addr 
)

Replace the special shared shadow memory for application address app_addr with normal writable shadow memory. Do nothing if it is already uses normal writable shadow memory or not allocated yet.

Parameters:
[in]mapThe mapping object to use.
[in]app_addrThe application memory address to be replaced.
[out]shadow_addrReturn the replaced shadow memory address.
DR_EXPORT drmf_status_t umbra_shadow_copy_range ( IN umbra_map_t map,
IN app_pc  app_src,
IN app_pc  app_dst,
IN size_t  app_size,
OUT size_t *  shadow_size 
)

Copy value from shadow memory for application memory at app_src to shadow memory for application memory at app_dst.

Parameters:
[in]mapThe mapping object to use.
[in]app_srcSource application memory address.
[in]app_dstDestination application memory address.
[in]app_sizeApplication memory size.
[out]shadow_sizeThe number of bytes actually copied.
Returns:
success code. If app_addr is not a valid application address and the shadow mapping implementation does not support shadow memory for invalid addresses, returns DRMF_ERROR_INVALID_ADDRESS.
Note:
: Overlap is allowed.
static void umbra_shadow_memory_info_init ( umbra_shadow_memory_info_t info)
inlinestatic

Convenience routine for initializing umbra_shadow_memory_info.

DR_EXPORT drmf_status_t umbra_shadow_memory_is_shared ( IN umbra_map_t map,
IN byte *  shadow_addr,
OUT umbra_shadow_memory_type_t shadow_type 
)

Similar to umbra_get_shadow_memory_type, but only check if shadow_addr is in a special shared shadow memory block. shadow_type is set to be UMBRA_SHADOW_MEMORY_TYPE_SHARED (optionally with UMBRA_SHADOW_MEMORY_TYPE_REDZONE also set) if shadow_addr is in any special shared shadow memory block and UMBRA_SHADOW_MEMORY_TYPE_UNKNOWN otherwise. If shadow_addr is in the redzone of a special shared shadow memory block, UMBRA_SHADOW_MEMORY_TYPE_REDZONE is also set along with UMBRA_SHADOW_MEMORY_TYPE_SHARED.

Parameters:
[in]mapThe mapping object to use.
[in]shadow_addrThe shadow memory address.
[out]shadow_typeThe type of the shadow memory at shadow_addr.
Note:
: This is a routine for efficient check if shadow_addr is in a special shared shadow memory. UMBRA_SHADOW_MEMORY_TYPE_UNKNOWN is set even shadow_addr could be normal writable shadow memory.
DR_EXPORT drmf_status_t umbra_shadow_set_range ( IN umbra_map_t map,
IN app_pc  app_addr,
IN size_t  app_size,
OUT size_t *  shadow_size,
IN ptr_uint_t  value,
IN size_t  value_size 
)

Set a range of shadow memory for application memory at app_addr.

Parameters:
[in]mapThe mapping object to use.
[in]app_addrApplication memory address.
[in]app_sizeApplication memory size.
[out]shadow_sizeThe number of bytes actually written.
[in]valueThe value to be set in shadow memory.
[in]value_sizeThe value size for value, could be 1, 2, 4, or 8 (x64). Only 1 is supported now.
Returns:
success code. If app_addr is not a valid application address and the shadow mapping implementation does not support shadow memory for invalid addresses, returns DRMF_ERROR_INVALID_ADDRESS.
DR_EXPORT drmf_status_t umbra_value_in_shadow_memory ( IN umbra_map_t map,
INOUT app_pc *  app_addr,
IN size_t  app_size,
IN ptr_uint_t  value,
IN size_t  value_size,
OUT bool *  found 
)

Check whether value is in the shadow memory for application memory at app_addr.

Parameters:
[in]mapThe mapping object to use.
[in,out]app_addrStarting application memory address. Return the application address at which if found.
[in]app_sizeApplication memory size.
[in]valueThe value to be set in shadow memory.
[in]value_sizeThe value size for value, could be 1, 2, 4, or 8 (x64). Only 1 is supported now.
[out]foundReturn true if value found in the range.
Returns:
success code. If app_addr is not a valid application address and the shadow mapping implementation does not support shadow memory for invalid addresses, returns DRMF_ERROR_INVALID_ADDRESS.
DR_EXPORT drmf_status_t umbra_write_shadow_memory ( IN umbra_map_t map,
IN app_pc  app_addr,
IN size_t  app_size,
INOUT size_t *  shadow_size,
IN byte *  buffer 
)

Write shadow memory for application memory at app_addr from buffer.

Parameters:
[in]mapThe mapping object to use.
[in]app_addrApplication memory address.
[in]app_sizeApplication memory size.
[in,out]shadow_sizeThe max buffer size. Return the number of bytes actually written.
[in]bufferThe buffer holds the value to write.
Returns:
success code. If app_addr is not a valid application address and the shadow mapping implementation does not support shadow memory for invalid addresses, returns DRMF_ERROR_INVALID_ADDRESS.