From f657c20a1da4b5d6ce0ae95d60c5f2921c68ebf9 Mon Sep 17 00:00:00 2001 From: Alexander Gavrilov Date: Sun, 11 Nov 2012 15:49:01 +0400 Subject: [PATCH] Add an internal API for converting between file and memory offsets. --- Lua API.html | 8 +++++++ Lua API.rst | 10 +++++++++ library/LuaApi.cpp | 15 +++++++++++++ library/Process-darwin.cpp | 9 ++++++-- library/Process-linux.cpp | 9 ++++++-- library/Process-windows.cpp | 39 +++++++++++++++++++++++++++++++--- library/VersionInfoFactory.cpp | 4 ++-- library/include/MemAccess.h | 4 +++- 8 files changed, 88 insertions(+), 10 deletions(-) diff --git a/Lua API.html b/Lua API.html index 226afa98a..d2e0da1ef 100644 --- a/Lua API.html +++ b/Lua API.html @@ -1763,9 +1763,17 @@ global environment, persistent between calls to the script.

  • dfhack.internal.getVTable(name)

    Returns the pre-extracted vtable address name, or nil.

  • +
  • dfhack.internal.getImageBase()

    +

    Returns the mmap base of the executable.

    +
  • dfhack.internal.getRebaseDelta()

    Returns the ASLR rebase offset of the DF executable.

  • +
  • dfhack.internal.adjustOffset(offset[,to_file])

    +

    Returns the re-aligned offset, or nil if invalid. +If to_file is true, the offset is adjusted from memory to file. +This function returns the original value everywhere except windows.

    +
  • dfhack.internal.getMemRanges()

    Returns a sequence of tables describing virtual memory ranges of the process.

  • diff --git a/Lua API.rst b/Lua API.rst index d06e3d2e6..f89750e88 100644 --- a/Lua API.rst +++ b/Lua API.rst @@ -1618,10 +1618,20 @@ and are only documented here for completeness: Returns the pre-extracted vtable address ``name``, or *nil*. +* ``dfhack.internal.getImageBase()`` + + Returns the mmap base of the executable. + * ``dfhack.internal.getRebaseDelta()`` Returns the ASLR rebase offset of the DF executable. +* ``dfhack.internal.adjustOffset(offset[,to_file])`` + + Returns the re-aligned offset, or *nil* if invalid. + If ``to_file`` is true, the offset is adjusted from memory to file. + This function returns the original value everywhere except windows. + * ``dfhack.internal.getMemRanges()`` Returns a sequence of tables describing virtual memory ranges of the process. diff --git a/library/LuaApi.cpp b/library/LuaApi.cpp index 0151ed404..3862530dd 100644 --- a/library/LuaApi.cpp +++ b/library/LuaApi.cpp @@ -1718,9 +1718,11 @@ static void *checkaddr(lua_State *L, int idx, bool allow_null = false) return rv; } +static uint32_t getImageBase() { return Core::getInstance().p->getBase(); } static int getRebaseDelta() { return Core::getInstance().vinfo->getRebaseDelta(); } static const LuaWrapper::FunctionReg dfhack_internal_module[] = { + WRAP(getImageBase), WRAP(getRebaseDelta), { NULL, NULL } }; @@ -1774,6 +1776,18 @@ static int internal_getVTable(lua_State *L) return 1; } +static int internal_adjustOffset(lua_State *L) +{ + lua_settop(L, 2); + int off = luaL_checkint(L, 1); + int rv = Core::getInstance().p->adjustOffset(off, lua_toboolean(L, 2)); + if (rv >= 0) + lua_pushinteger(L, rv); + else + lua_pushnil(L); + return 1; +} + static int internal_getMemRanges(lua_State *L) { std::vector ranges; @@ -1981,6 +1995,7 @@ static const luaL_Reg dfhack_internal_funcs[] = { { "getAddress", internal_getAddress }, { "setAddress", internal_setAddress }, { "getVTable", internal_getVTable }, + { "adjustOffset", internal_adjustOffset }, { "getMemRanges", internal_getMemRanges }, { "patchMemory", internal_patchMemory }, { "patchBytes", internal_patchBytes }, diff --git a/library/Process-darwin.cpp b/library/Process-darwin.cpp index c5e4e4b85..d081c8c5c 100644 --- a/library/Process-darwin.cpp +++ b/library/Process-darwin.cpp @@ -220,9 +220,14 @@ void Process::getMemRanges( vector & ranges ) }*/ } -uint32_t Process::getBase() +uintptr_t Process::getBase() { - return 0; + return 0x1000000; +} + +int Process::adjustOffset(int offset, bool /*to_file*/) +{ + return offset; } static int getdir (string dir, vector &files) diff --git a/library/Process-linux.cpp b/library/Process-linux.cpp index f88279b3f..046b7696d 100644 --- a/library/Process-linux.cpp +++ b/library/Process-linux.cpp @@ -155,9 +155,14 @@ void Process::getMemRanges( vector & ranges ) fclose(mapFile); } -uint32_t Process::getBase() +uintptr_t Process::getBase() { - return 0; + return 0x8048000; +} + +int Process::adjustOffset(int offset, bool /*to_file*/) +{ + return offset; } static int getdir (string dir, vector &files) diff --git a/library/Process-windows.cpp b/library/Process-windows.cpp index 966468fb5..6f79236f9 100644 --- a/library/Process-windows.cpp +++ b/library/Process-windows.cpp @@ -160,7 +160,7 @@ Process::Process(VersionInfoFactory * factory) identified = true; // give the process a data model and memory layout fixed for the base of first module my_descriptor = new VersionInfo(*vinfo); - my_descriptor->rebaseTo((uint32_t)d->base); + my_descriptor->rebaseTo(getBase()); for(size_t i = 0; i < threads_ids.size();i++) { HANDLE hThread = OpenThread(THREAD_ALL_ACCESS, FALSE, (DWORD) threads_ids[i]); @@ -394,13 +394,46 @@ void Process::getMemRanges( vector & ranges ) } } -uint32_t Process::getBase() +uintptr_t Process::getBase() { if(d) - return (uint32_t) d->base; + return (uintptr_t) d->base; return 0x400000; } +int Process::adjustOffset(int offset, bool to_file) +{ + if (!d) + return -1; + + for(int i = 0; i < d->pe_header.FileHeader.NumberOfSections; i++) + { + auto §ion = d->sections[i]; + + if (to_file) + { + unsigned delta = offset - section.VirtualAddress; + if (delta >= section.Misc.VirtualSize) + continue; + if (!section.PointerToRawData || delta >= section.SizeOfRawData) + return -1; + return (int)(section.PointerToRawData + delta); + } + else + { + unsigned delta = offset - section.PointerToRawData; + if (!section.PointerToRawData || delta >= section.SizeOfRawData) + continue; + if (delta >= section.Misc.VirtualSize) + return -1; + return (int)(section.VirtualAddress + delta); + } + } + + return -1; +} + + string Process::doReadClassName (void * vptr) { char * rtti = readPtr((char *)vptr - 0x4); diff --git a/library/VersionInfoFactory.cpp b/library/VersionInfoFactory.cpp index e8c0561cd..7142233d8 100644 --- a/library/VersionInfoFactory.cpp +++ b/library/VersionInfoFactory.cpp @@ -103,13 +103,13 @@ void VersionInfoFactory::ParseVersion (TiXmlElement* entry, VersionInfo* mem) { mem->setOS(OS_LINUX); // this is wrong... I'm not going to do base image relocation on linux though. - mem->setBase(0x0); + mem->setBase(0x8048000); } else if(os == "darwin") { mem->setOS(OS_APPLE); // this is wrong... I'm not going to do base image relocation on linux though. - mem->setBase(0x0); + mem->setBase(0x1000000); } else { diff --git a/library/include/MemAccess.h b/library/include/MemAccess.h index 1b8e687b9..22f15eecf 100644 --- a/library/include/MemAccess.h +++ b/library/include/MemAccess.h @@ -275,11 +275,13 @@ namespace DFHack { return my_descriptor; }; - uint32_t getBase(); + uintptr_t getBase(); /// get the DF Process ID int getPID(); /// get the DF Process FilePath std::string getPath(); + /// Adjust between in-memory and in-file image offset + int adjustOffset(int offset, bool to_file = false); /// millisecond tick count, exactly as DF uses uint32_t getTickCount();