Add lua internal api functions needed for scanning memory.

develop
Alexander Gavrilov 2012-06-16 13:33:49 +04:00
parent 94dfdb486d
commit dc5bef2cb8
3 changed files with 141 additions and 1 deletions

@ -1176,6 +1176,26 @@ and are only documented here for completeness:
Returns a sequence of tables describing virtual memory ranges of the process.
* ``dfhack.internal.memmove(dest,src,count)``
Wraps the standard memmove function. Accepts both numbers and refs as pointers.
* ``dfhack.internal.memcmp(ptr1,ptr2,count)``
Wraps the standard memcmp function.
* ``dfhack.internal.memscan(haystack,count,step,needle,nsize)``
Searches for ``needle`` of ``nsize`` bytes in ``haystack``,
using ``count`` steps of ``step`` bytes.
Returns: *step_idx, sum_idx, found_ptr*, or *nil* if not found.
* ``dfhack.internal.diffscan(old_data, new_data, start_idx, end_idx, eltsize[, oldval, newval, delta])``
Searches for differences between buffers at ptr1 and ptr2, as integers of size eltsize.
The oldval, newval or delta arguments may be used to specify additional constraints.
Returns: *found_index*, or *nil* if end reached.
Core interpreter context
========================

@ -1332,6 +1332,22 @@ global environment, persistent between calls to the script.</p>
<li><p class="first"><tt class="docutils literal">dfhack.internal.getMemRanges()</tt></p>
<p>Returns a sequence of tables describing virtual memory ranges of the process.</p>
</li>
<li><p class="first"><tt class="docutils literal">dfhack.internal.memmove(dest,src,count)</tt></p>
<p>Wraps the standard memmove function. Accepts both numbers and refs as pointers.</p>
</li>
<li><p class="first"><tt class="docutils literal">dfhack.internal.memcmp(ptr1,ptr2,count)</tt></p>
<p>Wraps the standard memcmp function.</p>
</li>
<li><p class="first"><tt class="docutils literal">dfhack.internal.memscan(haystack,count,step,needle,nsize)</tt></p>
<p>Searches for <tt class="docutils literal">needle</tt> of <tt class="docutils literal">nsize</tt> bytes in <tt class="docutils literal">haystack</tt>,
using <tt class="docutils literal">count</tt> steps of <tt class="docutils literal">step</tt> bytes.
Returns: <em>step_idx, sum_idx, found_ptr</em>, or <em>nil</em> if not found.</p>
</li>
<li><p class="first"><tt class="docutils literal">dfhack.internal.diffscan(old_data, new_data, start_idx, end_idx, eltsize[, oldval, newval, delta])</tt></p>
<p>Searches for differences between buffers at ptr1 and ptr2, as integers of size eltsize.
The oldval, newval or delta arguments may be used to specify additional constraints.
Returns: <em>found_index</em>, or <em>nil</em> if end reached.</p>
</li>
</ul>
</div>
</div>

@ -1021,6 +1021,21 @@ static const luaL_Reg dfhack_constructions_funcs[] = {
/***** Internal module *****/
static void *checkaddr(lua_State *L, int idx, bool allow_null = false)
{
luaL_checkany(L, idx);
void *rv;
if (lua_isnil(L, idx))
rv = NULL;
else if (lua_type(L, idx) == LUA_TNUMBER)
rv = (void*)lua_tointeger(L, idx);
else
rv = Lua::CheckDFObject(L, NULL, idx);
if (!rv && !allow_null)
luaL_argerror(L, idx, "null pointer");
return rv;
}
static uint32_t getBase() { return Core::getInstance().p->getBase(); }
static const LuaWrapper::FunctionReg dfhack_internal_module[] = {
@ -1042,7 +1057,7 @@ static int internal_getAddress(lua_State *L)
static int internal_setAddress(lua_State *L)
{
std::string name = luaL_checkstring(L, 1);
uint32_t addr = luaL_checkint(L, 2);
uint32_t addr = (uint32_t)checkaddr(L, 2, true);
internal_getAddress(L);
// Set the address
@ -1097,10 +1112,99 @@ static int internal_getMemRanges(lua_State *L)
return 1;
}
static int internal_memmove(lua_State *L)
{
void *dest = checkaddr(L, 1);
void *src = checkaddr(L, 2);
int size = luaL_checkint(L, 3);
if (size < 0) luaL_argerror(L, 1, "negative size");
memmove(dest, src, size);
return 0;
}
static int internal_memcmp(lua_State *L)
{
void *dest = checkaddr(L, 1);
void *src = checkaddr(L, 2);
int size = luaL_checkint(L, 3);
if (size < 0) luaL_argerror(L, 1, "negative size");
lua_pushinteger(L, memcmp(dest, src, size));
return 1;
}
static int internal_memscan(lua_State *L)
{
uint8_t *haystack = (uint8_t*)checkaddr(L, 1);
int hcount = luaL_checkint(L, 2);
int hstep = luaL_checkint(L, 3);
if (hstep == 0) luaL_argerror(L, 3, "zero step");
void *needle = checkaddr(L, 4);
int nsize = luaL_checkint(L, 5);
if (nsize < 0) luaL_argerror(L, 5, "negative size");
for (int i = 0; i <= hcount; i++)
{
uint8_t *p = haystack + i*hstep;
if (memcmp(p, needle, nsize) == 0) {
lua_pushinteger(L, i);
lua_pushinteger(L, (lua_Integer)p);
return 2;
}
}
lua_pushnil(L);
return 1;
}
static int internal_diffscan(lua_State *L)
{
lua_settop(L, 8);
void *old_data = checkaddr(L, 1);
void *new_data = checkaddr(L, 2);
int start_idx = luaL_checkint(L, 3);
int end_idx = luaL_checkint(L, 4);
int eltsize = luaL_checkint(L, 5);
bool has_oldv = !lua_isnil(L, 6);
bool has_newv = !lua_isnil(L, 7);
bool has_diffv = !lua_isnil(L, 8);
#define LOOP(esz, etype) \
case esz: { \
etype *pold = (etype*)old_data; \
etype *pnew = (etype*)new_data; \
etype oldv = (etype)luaL_optint(L, 6, 0); \
etype newv = (etype)luaL_optint(L, 7, 0); \
etype diffv = (etype)luaL_optint(L, 8, 0); \
for (int i = start_idx; i < end_idx; i++) { \
if (pold[i] == pnew[i]) continue; \
if (has_oldv && pold[i] != oldv) continue; \
if (has_newv && pnew[i] != newv) continue; \
if (has_diffv && etype(pnew[i]-pold[i]) != diffv) continue; \
lua_pushinteger(L, i); return 1; \
} \
break; \
}
switch (eltsize) {
LOOP(1, uint8_t);
LOOP(2, uint16_t);
LOOP(4, uint32_t);
default:
luaL_argerror(L, 5, "invalid element size");
}
#undef LOOP
lua_pushnil(L);
return 1;
}
static const luaL_Reg dfhack_internal_funcs[] = {
{ "getAddress", internal_getAddress },
{ "setAddress", internal_setAddress },
{ "getMemRanges", internal_getMemRanges },
{ "memmove", internal_memmove },
{ "memcmp", internal_memcmp },
{ "memscan", internal_memscan },
{ "diffscan", internal_diffscan },
{ NULL, NULL }
};