develop
Quietust 2012-06-19 10:04:29 -05:00
commit 385d96296e
3 changed files with 118 additions and 27 deletions

@ -1172,9 +1172,9 @@ and are only documented here for completeness:
Returns the pre-extracted vtable address ``name``, or *nil*. Returns the pre-extracted vtable address ``name``, or *nil*.
* ``dfhack.internal.getBase()`` * ``dfhack.internal.getRebaseDelta()``
Returns the base address of the process. Returns the ASLR rebase offset of the DF executable.
* ``dfhack.internal.getMemRanges()`` * ``dfhack.internal.getMemRanges()``

@ -1036,10 +1036,10 @@ static void *checkaddr(lua_State *L, int idx, bool allow_null = false)
return rv; return rv;
} }
static uint32_t getBase() { return Core::getInstance().p->getBase(); } static uint32_t getRebaseDelta() { return Core::getInstance().vinfo->getRebaseDelta(); }
static const LuaWrapper::FunctionReg dfhack_internal_module[] = { static const LuaWrapper::FunctionReg dfhack_internal_module[] = {
WRAP(getBase), WRAP(getRebaseDelta),
{ NULL, NULL } { NULL, NULL }
}; };
@ -1074,6 +1074,7 @@ static int internal_setAddress(lua_State *L)
} }
// Print via printerr, so that it is definitely logged to stderr.log. // Print via printerr, so that it is definitely logged to stderr.log.
addr -= Core::getInstance().vinfo->getRebaseDelta();
std::string msg = stl_sprintf("<global-address name='%s' value='0x%x'/>", name.c_str(), addr); std::string msg = stl_sprintf("<global-address name='%s' value='0x%x'/>", name.c_str(), addr);
dfhack_printerr(L, msg); dfhack_printerr(L, msg);

@ -233,19 +233,55 @@ struct HeapBlock
ULONG reserved; ULONG reserved;
}; };
*/ */
// FIXME: NEEDS TESTING!
// FIXME: <warmist> i noticed that if you enumerate it twice, second time it returns wrong .text region size static void GetDosNames(std::map<string, string> &table)
{
// Partially based on example from msdn:
// Translate path with device name to drive letters.
TCHAR szTemp[512];
szTemp[0] = '\0';
if (GetLogicalDriveStrings(sizeof(szTemp)-1, szTemp))
{
TCHAR szName[MAX_PATH];
TCHAR szDrive[3] = " :";
BOOL bFound = FALSE;
TCHAR* p = szTemp;
do
{
// Copy the drive letter to the template string
*szDrive = *p;
// Look up each device name
if (QueryDosDevice(szDrive, szName, MAX_PATH))
table[szName] = szDrive;
// Go to the next NULL character.
while (*p++);
} while (*p); // end of string
}
}
void Process::getMemRanges( vector<t_memrange> & ranges ) void Process::getMemRanges( vector<t_memrange> & ranges )
{ {
MEMORY_BASIC_INFORMATION MBI; MEMORY_BASIC_INFORMATION MBI;
//map<char *, unsigned int> heaps; //map<char *, unsigned int> heaps;
uint64_t movingStart = 0; uint64_t movingStart = 0;
PVOID LastAllocationBase = 0;
map <char *, string> nameMap; map <char *, string> nameMap;
map <string,string> dosDrives;
// get page size // get page size
SYSTEM_INFO si; SYSTEM_INFO si;
GetSystemInfo(&si); GetSystemInfo(&si);
uint64_t PageSize = si.dwPageSize; uint64_t PageSize = si.dwPageSize;
// get dos drive names
GetDosNames(dosDrives);
ranges.clear();
// enumerate heaps // enumerate heaps
// HeapNodes(d->my_pid, heaps); // HeapNodes(d->my_pid, heaps);
// go through all the VM regions, convert them to our internal format // go through all the VM regions, convert them to our internal format
@ -254,52 +290,106 @@ void Process::getMemRanges( vector<t_memrange> & ranges )
movingStart = ((uint64_t)MBI.BaseAddress + MBI.RegionSize); movingStart = ((uint64_t)MBI.BaseAddress + MBI.RegionSize);
if(movingStart % PageSize != 0) if(movingStart % PageSize != 0)
movingStart = (movingStart / PageSize + 1) * PageSize; movingStart = (movingStart / PageSize + 1) * PageSize;
// skip empty regions and regions we share with other processes (DLLs)
if( !(MBI.State & MEM_COMMIT) /*|| !(MBI.Type & MEM_PRIVATE)*/ ) // Skip unallocated address space
if (MBI.State & MEM_FREE)
continue; continue;
// Find range and permissions
t_memrange temp; t_memrange temp;
memset(&temp, 0, sizeof(temp));
temp.start = (char *) MBI.BaseAddress; temp.start = (char *) MBI.BaseAddress;
temp.end = ((char *)MBI.BaseAddress + (uint64_t)MBI.RegionSize); temp.end = ((char *)MBI.BaseAddress + (uint64_t)MBI.RegionSize);
temp.read = MBI.Protect & PAGE_EXECUTE_READ || MBI.Protect & PAGE_EXECUTE_READWRITE || MBI.Protect & PAGE_READONLY || MBI.Protect & PAGE_READWRITE; temp.valid = true;
temp.write = MBI.Protect & PAGE_EXECUTE_READWRITE || MBI.Protect & PAGE_READWRITE;
temp.execute = MBI.Protect & PAGE_EXECUTE_READ || MBI.Protect & PAGE_EXECUTE_READWRITE || MBI.Protect & PAGE_EXECUTE; if (!(MBI.State & MEM_COMMIT))
temp.valid = true; temp.valid = false; // reserved address space
if(!GetModuleBaseName(d->my_handle, (HMODULE) temp.start, temp.name, 1024)) else if (MBI.Protect & PAGE_EXECUTE)
temp.execute = true;
else if (MBI.Protect & PAGE_EXECUTE_READ)
temp.execute = temp.read = true;
else if (MBI.Protect & PAGE_EXECUTE_READWRITE)
temp.execute = temp.read = temp.write = true;
else if (MBI.Protect & PAGE_EXECUTE_WRITECOPY)
temp.execute = temp.read = temp.write = true;
else if (MBI.Protect & PAGE_READONLY)
temp.read = true;
else if (MBI.Protect & PAGE_READWRITE)
temp.read = temp.write = true;
else if (MBI.Protect & PAGE_WRITECOPY)
temp.read = temp.write = true;
// Merge areas with the same properties
if (!ranges.empty() && LastAllocationBase == MBI.AllocationBase)
{ {
if(nameMap.count((char *)temp.start)) auto &last = ranges.back();
if (last.end == temp.start &&
last.valid == temp.valid && last.execute == temp.execute &&
last.read == temp.read && last.write == temp.write)
{ {
// potential buffer overflow... last.end = temp.end;
strcpy(temp.name, nameMap[(char *)temp.start].c_str()); continue;
} }
else }
#if 1
// Find the mapped file name
if (GetMappedFileName(d->my_handle, temp.start, temp.name, 1024))
{
int vsize = strlen(temp.name);
// Translate NT name to DOS name
for (auto it = dosDrives.begin(); it != dosDrives.end(); ++it)
{ {
// filter away shared segments without a name. int ksize = it->first.size();
if( !(MBI.Type & MEM_PRIVATE) ) if (strncmp(temp.name, it->first.data(), ksize) != 0)
continue; continue;
else
temp.name[0]=0; memcpy(temp.name, it->second.data(), it->second.size());
memmove(temp.name + it->second.size(), temp.name + ksize, vsize + 1 - ksize);
break;
} }
} }
else else
temp.name[0] = 0;
#else
// Find the executable name
char *base = (char*)MBI.AllocationBase;
if(nameMap.count(base))
{
strncpy(temp.name, nameMap[base].c_str(), 1023);
}
else if(GetModuleBaseName(d->my_handle, (HMODULE)base, temp.name, 1024))
{ {
std::string nm(temp.name);
nameMap[base] = nm;
// this is our executable! (could be generalized to pull segments from libs, but whatever) // this is our executable! (could be generalized to pull segments from libs, but whatever)
if(d->base == temp.start) if(d->base == base)
{ {
for(int i = 0; i < d->pe_header.FileHeader.NumberOfSections; i++) for(int i = 0; i < d->pe_header.FileHeader.NumberOfSections; i++)
{ {
char sectionName[9]; /*char sectionName[9];
memcpy(sectionName,d->sections[i].Name,8); memcpy(sectionName,d->sections[i].Name,8);
sectionName[8] = 0; sectionName[8] = 0;
string nm; string nm;
nm.append(temp.name); nm.append(temp.name);
nm.append(" : "); nm.append(" : ");
nm.append(sectionName); nm.append(sectionName);*/
nameMap[(char *)temp.start + d->sections[i].VirtualAddress] = nm; nameMap[base + d->sections[i].VirtualAddress] = nm;
} }
} }
else
continue;
} }
else
temp.name[0] = 0;
#endif
// Push the entry
LastAllocationBase = MBI.AllocationBase;
ranges.push_back(temp); ranges.push_back(temp);
} }
} }