#ifndef _MEMGREP_H
#define _MEMGREP_H

#include <elf.h>

/**
 * @defgroup memgrep The memory manglement library interface.
 *
 * The memory manglement library interface.
 */
/**
 * @addtogroup memgrep
 *
 * @{
 */
/**
 * @example simple.c
 * Example for using memgrep as a library.
 */

/**
 * Initialize from a given medium.
 * 
 *	Initializes a given memgrep context to a given medium.  The 'param' argument should 
 *	be one of the enumerations in the MemoryMedium enum.  The 'data' argument should
 *	be the arbitrary value associated with the medium.  For MEMORY_MEDIUM_PID it will
 *	be the process id.  For MEMORY_MEDIUM_CORE it will be the core file.
 */
#define MEMGREP_CMD_INITIALIZE      0x00000001 
/**
 * Deinitialize from a given medium.
 * 
 *	Deinitializes a given memgrep context.  This will free up any resources that had
 *	incurred over the time of its use.
 */
#define MEMGREP_CMD_DEINITIALIZE    0x00000002
/**
 * Set parameters on a context.
 *
 * The 'param' argument can be one of the following:
 *
 * @li MEMGREP_PARAM_FLAGS
 * 		The data argument should be set to the flags that are to be enabled on the context.
 * @li MEMGREP_PARAM_LENGTH
 * 		The data argument should be set to the length that is to be used when dumping/searching.
 * @li MEMGREP_PARAM_PADDING
 * 		The data argument should be set to the length that is to be used with padding.
 */
#define MEMGREP_CMD_SET             0x00000003
/**
 * Get parameters that have been set on a context.
 *
 * The 'param' argument can be one of the following:
 *
 * @li MEMGREP_PARAM_FLAGS
 * 		The flags the context is using will be returned.
 * @li MEMGREP_PARAM_LENGTH
 * 		The length associated with dumping/searching will be returned.
 * @li MEMGREP_PARAM_PADDING
 * 		The padding associated with dumping will be returned.
 */
#define MEMGREP_CMD_GET             0x00000004
/**
 * Populate the address array from supplied address(es).
 *
 * The 'param' argument can be one of the following:
 *
 * @li A string
 * 		If the param argument is a string it should have addresses formatted 
 * 		with each address being seperated by commas.  Addresses can be specified in hex
 * 		as well as in the form of a keyword such as: bss, stack, rodata, data, all.
 *			The 'data' parameter should be set to 0.
 * @li An array
 * 		If the param argument is an array it should be an array of unsigned long's
 * 		which hold the addresses that are to be used.  The 'data' argument should 
 * 		have the number of elements the array contains.
 */
#define MEMGREP_CMD_POPULATE        0x00000005
/**
 * Search for a given criteria in the addresses specified by MEMGREP_CMD_POPULATE.
 *
 * The 'param' argument is used in conjunction with the search criteria.
 * It can be in the following format:
 *
 * @li s,example
 * 		This will search for the string 'example' in the addresses specified in MEMGREP_CMD_POPULATE
 * @li i,47
 * 		This will search for the integer 47 in the addresses specified in MEMGREP_CMD_POPULATE
 * @li x,656667
 * 		This will search for the hex \x65\x66\x67 in the addresses specified in MEMGREP_CMD_POPULATE.
 * 
 * The 'data' argument is undefined and should be set to 0.
 */
#define MEMGREP_CMD_SEARCH          0x00000006
/**
 * Replace memory with the specified data at the addresses specified by MEMGREP_CMD_POPULATE.
 *
 * The 'param' argument is used in conjunction with the replace criteria.
 * It can be in the following format:
 *
 * @li s,example
 * 		This will replace for the string 'example' in the addresses specified in MEMGREP_CMD_POPULATE
 * @li i,47
 * 		This will replace for the integer 47 in the addresses specified in MEMGREP_CMD_POPULATE
 * @li x,656667
 * 		This will replace for the hex \x65\x66\x67 in the addresses specified in MEMGREP_CMD_POPULATE.
 * 
 * The 'data' argument is undefined and should be set to 0.
 * 
 * Results are optionally returned in the 'result' argument if it is not null of type MEMGREP_RESULT_TYPE_SEARCH.
 */
#define MEMGREP_CMD_REPLACE         0x00000007
/**
 * Search and replace memory that matches the criteria for the addresses specified by MEMGREP_CMD_POUPLATE.
 *
 * The 'param' argument is used in conjunction with the search criteria.
 * It can be in the following format:
 *
 * @li s,example
 * 		This will search for the string 'example' in the addresses specified in MEMGREP_CMD_POPULATE
 * @li i,47
 * 		This will search for the integer 47 in the addresses specified in MEMGREP_CMD_POPULATE
 * @li x,656667
 * 		This will search for the hex \x65\x66\x67 in the addresses specified in MEMGREP_CMD_POPULATE.
 * 
 * The 'data' argument is used in conjunction with the replace criteria.
 * It can be in the following format:
 *
 * @li s,example
 * 		This will replace for the string 'example' in the addresses that match the search criteria.
 * @li i,47
 * 		This will replace for the integer 47 in the addresses that match the search criteria.
 * @li x,656667
 * 		This will replace for the hex \x65\x66\x67 in the addresses that match the search criteria.
 *
 * Results are optionally returned in the 'result' argument if it is not null of type MEMGREP_RESULT_TYPE_REPLACE.
 */
#define MEMGREP_CMD_SEARCHREPLACE   0x00000008
/**
 * Dump memory for the addresses specified in MEMGREP_CMD_POPULATE.
 *
 * No parameters are required.
 * 
 * Results are optionally returned in the 'result' argument if it is not null of type MEMGREP_RESULT_TYPE_DUMP.
 */
#define MEMGREP_CMD_DUMP            0x00000009
/**
 * List all the segments of a given medium such as rodata, stack, bss, etc.
 *
 * No parameters are required.
 */
#define MEMGREP_CMD_LISTSEGMENTS    0x0000000A
/**
 * Destroy the contents of a result that was handed back by a command
 *
 * The 'param' argument should be a pointer to a result structure.
 *
 * The 'data' argument is undefined and should be 0.
 */
#define MEMGREP_CMD_DESTROYRESULT   0x0000000B
/**
 * Enumerate the heap of a running process
 *
 * The 'param' argument is the minimize size of the heap unit, or 0.
 *
 * The 'data' argument is undefined and should be 0.
 */
#define MEMGREP_CMD_HEAPENUMERATE   0x0000000C

/**
 * Specifies that the data parameter will be flags when used in conjunction with MEMGREP_CMD_SET.
 */ 
#define MEMGREP_PARAM_FLAGS         0x00000001
/**
 * Specifies that the data parameter will be the length when used in conjunction with MEMGREP_CMD_SET.
 */ 
#define MEMGREP_PARAM_LENGTH        0x00000002
/**
 * Specifies that the data parameter will be dump padding size when used in conjunction with MEMGREP_CMD_SET.
 */ 
#define MEMGREP_PARAM_PADDING       0x00000003
/**
 * Specifies that the data parameter will be the format to use when dumping.
 */
#define MEMGREP_PARAM_DUMPFORMAT    0x00000004

/**
 * The derived instance of this row is a MEMGREP_RESULT_ROW_SEARCH and should be cast as such.
 */
#define MEMGREP_RESULT_TYPE_SEARCH  0x00000001
/**
 * The derived instance of this row is a MEMGREP_RESULT_ROW_REPLACE and should be cast as such.
 */
#define MEMGREP_RESULT_TYPE_REPLACE 0x00000002
/**
 * The derived instance of this row is a MEMGREP_RESULT_ROW_DUMP and should be cast as such.
 */
#define MEMGREP_RESULT_TYPE_DUMP    0x00000003
/**
 * The derived instance of this row is a MEMGREP_RESULT_ROW_HEAP and should be cast as such.
 */
#define MEMGREP_RESULT_TYPE_HEAP    0x00000004

/**
 * Flag used to enable verbose output when performing actions.
 */
#define MEMGREP_FLAG_VERBOSE        (1 << 0)
/**
 * Flag used to enable prompting before replacing memory.
 */
#define MEMGREP_FLAG_PROMPT         (1 << 1)
/**
 * Flag used to enable output of dumping memory in a clear-text format rather than hex.
 */
#define MEMGREP_FLAG_DUMPCLEAN      (1 << 2)

/**
 * Mediums used when operating with memgrep.  
 *
 * @short memory access mediums
 */
enum MemoryMedium {
	/**
	 * An unknown medium
	 */
	MEMORY_MEDIUM_UNKNOWN = 0,
	/**
	 * Access memory via a process id
	 */
	MEMORY_MEDIUM_PID     = 1,
	/**
	 * Access memory via a core file
	 */
	MEMORY_MEDIUM_CORE    = 2
};

/**
 * The format to use when dumping memory
 *
 * @short memory dumping format
 */
enum MemoryDumpFormat {
	/**
	 * Dump as hex integers (0xabcdef00)
	 */
	MEMORY_DUMP_FORMAT_HEXINT   = 0,
	/**
	 * Dump as hex shorts (0xabcd)
	 */
	MEMORY_DUMP_FORMAT_HEXSHORT = 1,
	/**
	 * Dump as hex characters (0xab)
	 */
	MEMORY_DUMP_FORMAT_HEXBYTE  = 2,
	/**
	 * Dump as decimal integers (1234)
	 */
	MEMORY_DUMP_FORMAT_DECINT   = 3,
	/**
	 * Dump as decimal shorts (65535)
	 */
	MEMORY_DUMP_FORMAT_DECSHORT = 4,
	/**
	 * Dump as decimal characters (127)
	 */
	MEMORY_DUMP_FORMAT_DECBYTE  = 5,
	/**
	 * Dump as ascii printable characters
	 */
	MEMORY_DUMP_FORMAT_PRINTABLE = 6,
};

/**
 * Holds the addresses that signify the start of a given logical section.
 *
 * @short Section addresses
 */
typedef struct _process_section_addrs {

	/**
	 * 0.8.0+: Text section of the binary image.
	 */
	unsigned long text;
	/**
	 * 0.8.0+: The length of the text section of the binary image.
	 */
	unsigned long textLength;
	/**
	 * Read-only data, commonly associated with static text.
	 */
	unsigned long rodata;
	/**
	 * 0.8.0+: The length of the read-only data section.
	 */
	unsigned long rodataLength;
	/**
	 * Data, commonly associated with global or static variables.
	 */
	unsigned long data;
	/**
	 * 0.8.0+: The length of the data section.
	 */
	unsigned long dataLength;
	/**
	 * bss, commonly associated with the 'heap'.
	 */
	unsigned long bss;

	/**
	 * stack, self explanatory.
	 */
	unsigned long stack;

} PROCESS_SECTION_ADDRS;

/**
 * Holds virtual memory segments of a core file as well as their length.
 *
 * @short Core file virtual-memory segments.
 */
typedef struct _core_memory_sections {

	/**
	 * The virtual memory addresses of the segment
	 */
	unsigned long vma;
	/**
	 * The length of the segment
	 */
	unsigned long length;

	/**
	 * The mmap()'d address of the segment.
	 */
	unsigned long rma;

} CORE_MEMORY_SECTIONS;

/**
 * Extended data structure holding information about a core file.
 *
 * @short Core file information.
 */
typedef struct _mem_ctx_core_data {

	/**
	 * The file descriptor associated with the core file.
	 */
	int                  fd;

	/**
	 * The elf header of the core file.
	 */
	Elf32_Ehdr           elfHeader;
	/**
	 * The array of program headers.
	 */
	Elf32_Phdr           *programHeaders;

	/**
	 * The array of virtual memory segments.
	 */
	CORE_MEMORY_SECTIONS *sections;
	/**
	 * The number of segments.
	 */
	unsigned long        numSections;

} MEM_CTX_CORE_DATA;

struct _mem_ctx;

/**
 * The medium-independant function table used internally by memgrep.
 *
 * @short Medium-independant function table.
 */
typedef struct _memgrep_functions {

	/**
	 * Open the medium and prepare it for operation.
	 *
	 * @param  ctx [in] The memgrep context.
	 * @return On success, 1 is returned, otherwise 0 is returned.
	 */
	unsigned long  (*open)(struct _mem_ctx *ctx);
	/**
	 * Closes the medium, releasing any resources used.
	 *
	 * @param  ctx [in] The memgrep context.
	 * @return On success, 1 is returned, otherwise 0 is returned.
	 */
	unsigned long  (*close)(struct _mem_ctx *ctx);

	/**
	 * Get the sections (rodata, bss, data, stack) associated with a given medium.
	 *
	 * @param  ctx [in] The memgrep context.
	 * @return On success, 1 is returned, otherwise 0 is returned.
	 */
	unsigned long  (*getSections)(struct _mem_ctx *ctx);
	/**
	 * Gets a memory address for a specified number of bytes.
	 *
	 * @param  ctx    [in] The memgrep context.
	 * @param  addr   [in] The address to start from.
	 * @param  length [in] The number of bytes to get.
	 * @return On success, a buffer containing the data at the specified address is returned.  Otherwise, NULL is returned.
	 */
	unsigned char *(*get)(struct _mem_ctx *ctx, unsigned long addr, unsigned long length);
	/**
	 * Puts arbitrary data into memory at the specified address for a given length.
	 *
	 * @param  ctx       [in] The memgrep context.
	 * @param  addr      [in] The address to start from.
	 * @param  buf       [in] The buffer to write from.
	 * @param  bufLength [in] The number of bytes to write.
	 * @return On success, 1 is returned, otherwise 0 is returned.
	 */
	unsigned long  (*put)(struct _mem_ctx *ctx, unsigned long addr, unsigned char *buf, unsigned long bufLength);
	/**
	 * Populate the addresses array from a given keyword.
	 *
	 * @param  ctx     [in] The memgrep context.
	 * @param  keyword [in] The keyword to replace (such as 'bss').
	 * @return If the keyword is valid, 1 is returned, otherwise 0 is returned.
	 */
	unsigned long  (*populateKeyword)(struct _mem_ctx *ctx, const char *keyword);
	/**
	 * List the segments of a given medium.
	 *
	 * @param  ctx [in] The memgrep context.
	 * @return On success, 1 is returned, otherwise 0 is returned.
	 */
	unsigned long  (*listSegments)(struct _mem_ctx *ctx);

	/**
	 * Enumerate the heap of the given medium.
	 *
	 * @param  ctx     [in]  The memgrep context.
	 * @param  current [in]  The current node in the list, or 0 if the first node.
	 * @param  addr    [out] The adderss of the allocation unit at this point.
	 * @param  size    [out] The size of the allocation unit at this point.
	 * @return On success, 1 is returned, otherwise 0 is returned.
	 */
	unsigned long  (*heapEnumerate)(struct _mem_ctx *ctx, unsigned long current, unsigned long *addr, unsigned long *size);

} MEMGREP_FUNCTIONS;

/**
 * The base for all rows in a result
 *
 * @short Result row base structure.
 */
typedef struct _memgrep_result_row {

	/**
	 * The length in bytes of the structure.
	 */
	unsigned long length;
	/**
	 * The type of structure.  This can be one of the following:
	 *
	 * @li MEMGREP_RESULT_TYPE_SEARCH
	 * 		The derived structure is 'MEMGREP_RESULT_ROW_SEARCH'
	 * @li MEMGREP_RESULT_TYPE_REPLACE
	 * 		The derived structure is 'MEMGREP_RESULT_ROW_REPLACE'
	 * @li MEMGREP_RESULT_TYPE_DUMP
	 * 		The derived structure is 'MEMGREP_RESULT_ROW_DUMP'
	 */
	unsigned long type;

} MEMGREP_RESULT_ROW;

/**
 * The result from a given operation, including any rows that were returned.
 *
 * @short The result of a given operation.
 */
typedef struct _memgrep_result {

	/**
	 * The error code, 0 if no error.
	 */
	unsigned long      error;

	/**
	 * The number of rows returned by the query.
	 */
	unsigned long      numRows;
	/**
	 * The array of rows.
	 */
	MEMGREP_RESULT_ROW **rows;

} MEMGREP_RESULT;

/**
 * Used in association with MEMGREP_CMD_SEARCH.
 *
 * @short Row for search results.
 */
typedef struct _memgrep_result_row_search {

	/**
	 * The base structure for all rows
	 */
	MEMGREP_RESULT_ROW base;

	/**
	 * The address that a matching instance of the search criteria was found at
	 */
	unsigned long      addr;

} MEMGREP_RESULT_ROW_SEARCH;

/**
 * Used in association with MEMGREP_CMD_HEAPENUMERATE
 *
 * @short Row for heap enumeration results.
 */
typedef struct _memgrep_result_row_heap {

	/**
	 * The base structure for all rows
	 */
	MEMGREP_RESULT_ROW base;

	/**
	 * The base address of the allocation in the heap
	 */
	unsigned long      addr;

	/**
	 * The size of the allocation
	 */
	unsigned long      size;

} MEMGREP_RESULT_ROW_HEAP;

/**
 * Used in association MEMGREP_CMD_SEARCHREPLACE and MEMGREP_CMD_REPLACE
 *
 * @short Row for replace reuslts.
 */
typedef struct _memgrep_result_row_replace {

	/**
	 * The base structure for all rows
	 */
	MEMGREP_RESULT_ROW base;

	/**
	 * The address where an instance of memory was replaced at.
	 */
	unsigned long      addr;

} MEMGREP_RESULT_ROW_REPLACE;

/**
 * Used in association with MEMGREP_CMD_DUMP
 *
 * @short Row for memory dump results.
 */
typedef struct _memgrep_result_row_dump {

	/**
	 * The base structure for all rows
	 */
	MEMGREP_RESULT_ROW base;

	/**
	 * The adderss that the dump occured at.
	 */
	unsigned long      addr;
	/**
	 * The memory at that address
	 */
	unsigned char      *buf;
	/**
	 * The number of bytes held in buf
	 */
	unsigned long      bufLength;

} MEMGREP_RESULT_ROW_DUMP;

/**
 * The memgrep context.
 *
 * @short memgrep context
 */
typedef struct _mem_ctx {

	/**
	 * Holds the flags for the conetxt.  These can be a combination of the following:
	 *
	 * @li MEMGREP_FLAG_VERBOSE
	 * 		Be verbose.  This enables output for given commands.
	 * @li MEMGREP_FLAG_PROMPT
	 * 		Prompt before overwriting memory.
	 * @li MEMGREP_FLAG_DUMPCLEAN
	 * 		Dump the memory in human read-able format.  This is only useful with verbose set.
	 */
	unsigned long         flags;

	/**
	 * The medium that will be operated upon.  This can be:
	 *
	 * @li MEMORY_MEDIUM_PID
	 * 		Operate on a process id.
	 * @li MEMORY_MEDIUM_CORE
	 * 		Operate on a core file.
	 */
	enum MemoryMedium     medium;

	/**
	 * The process id to operate on.
	 */
	int                   pid;
	/**
	 * The core file to operate on.
	 */
	char                  *core;

	/**
	 * Medium specific function table.
	 */
	MEMGREP_FUNCTIONS     functions;
	/**
	 * Section addresses associated with the medium.
	 */
	PROCESS_SECTION_ADDRS sections;

	/**
	 * Array of addresses populated by MEMGREP_CMD_POPULATE
	 */
	unsigned long         *addrs;
	/**
	 * Number of elements in the 'addrs' array.
	 */
	unsigned long         numAddrs;
	/**
	 * The length used when searching, and dumping.
	 */
	unsigned long         length;
	/**
	 * Padding used when dumping memory.
	 */
	unsigned long         padding;
	/**
	 * Format for use when dumping
	 */
	enum MemoryDumpFormat dumpFormat;

	/**
	 * Extended data related to core files
	 */
	MEM_CTX_CORE_DATA     coreData;


	/**
	 * MISC:
	 *
	 * procFd => Solaris fd for proc access
	 */
	int procCtlFd;
	int procAsFd;

} MEM_CTX;

/**
 * The method used to operate memgrep.
 *
 * @param  ctx    [in]  The memgrep context.
 * @param  cmd    [in]  The command to execute.  See each command for a description of its parameters.
 * @param  result [out] The result of a given action.  This can be NULL.
 * @param  param  [in]  An arbitrary parameter for a given command.
 * @param  data   [in]  An arbitrary parameter for a given command.
 * @return Return values vary from one command to another.
 */
unsigned long memgrep(MEM_CTX *ctx, unsigned long cmd, MEMGREP_RESULT *result, unsigned long param, unsigned long data);

/*
 * These functions should not be called directly.
 */

unsigned long memgrep_initialize(MEM_CTX *ctx, enum MemoryMedium medium, void *data); // 1 for success, 0 for failure
unsigned long memgrep_deinitialize(MEM_CTX *ctx); // 1 for success, 0 for failure
unsigned long memgrep_set(MEM_CTX *ctx, unsigned long param, unsigned long data); // 1 for success, 0 for failure
unsigned long memgrep_get(MEM_CTX *ctx, unsigned long param); // the value associated w/ the param
unsigned long memgrep_populate_string(MEM_CTX *ctx, const char *addresses); // number of addresses populated
unsigned long memgrep_populate_array(MEM_CTX *ctx, unsigned long *array, unsigned long elements); // number of addresses populated
unsigned long memgrep_search(MEM_CTX *ctx, MEMGREP_RESULT *result, const char *searchPhrase); // number of addresses found
unsigned long memgrep_replace(MEM_CTX *ctx, MEMGREP_RESULT *result, const char *replacePhrase); // number of addresses replaced
unsigned long memgrep_searchreplace(MEM_CTX *ctx, MEMGREP_RESULT *result, const char *searchPhrase, const char *replacePhrase); // number of addresses search/replaced
unsigned long memgrep_dump(MEM_CTX *ctx, MEMGREP_RESULT *result); // 1 for success, 0 for failure
unsigned long memgrep_listSegments(MEM_CTX *ctx); // 1 for success, 0 for failure
unsigned long memgrep_destroy(MEM_CTX *ctx, MEMGREP_RESULT *result); // Destroy a resultant value, 1 for success 0 for failure
unsigned long memgrep_heapenumerate(MEM_CTX *ctx, MEMGREP_RESULT *result, unsigned long minSize); // 1 for success, 0 for failure

/**
 * @}
 */

#endif


syntax highlighted by Code2HTML, v. 0.9.1