1
0
mirror of https://github.com/rbmm/SC synced 2026-06-08 17:03:41 +00:00
Files
rbmm a26d61b194 ++
2025-03-13 15:01:09 +02:00

236 lines
3.5 KiB
C++

#include "stdafx.h"
#include "map2.h"
#include "file.h"
#include "undname.h"
struct MAP::RO
{
ULONG rva, ofs;
static int __cdecl compare(const RO* pa, const RO* pb)
{
if (pa->rva < pb->rva) return -1;
if (pa->rva > pb->rva) return +1;
return 0;
}
};
MAP::RO* MAP::Parse(PSTR pcsz, PIMAGE_NT_HEADERS pinth)
{
PSTR buf = pcsz;
ULONG n = 0;
ULONG64 u;
ULONG_PTR ImageBase = 0;
__0:
static const char plai[] = " Preferred load address is ";
if (!memcmp(pcsz, plai, _countof(plai) - 1))
{
if (ImageBase)
{
return 0;
}
u = _strtoui64(pcsz + _countof(plai) - 1, const_cast<char**>(&pcsz), 16);
if (!u || '\r' != *pcsz++ || '\n' != *pcsz++)
{
return 0;
}
ImageBase = (ULONG_PTR)u;
goto __0;
}
ULONG s = strtoul(pcsz, const_cast<char**>(&pcsz), 16);
if (':' != *pcsz)
{
__1:
if (!(pcsz = strchr(pcsz, '\r')) || '\n' != *++pcsz)
{
return 0;
}
if (!*++pcsz)
{
if (n)
{
_M_n = n;
return (RO*)(((ULONG_PTR)buf + (__alignof(RO) - 1)) & ~(__alignof(RO) - 1));
}
return 0;
}
goto __0;
}
ULONG o = strtoul(pcsz + 1, const_cast<char**>(&pcsz), 16);
if (' ' != *pcsz)
{
return 0;
}
if ('0' == *++pcsz)
{
ULONG i = strtoul(pcsz + 1, &pcsz, 16);
// <iSection>:<ofs> <s>H segment class
if ('H' != *pcsz)
{
return 0;
}
//skip space
while (' ' == *++pcsz);
PCSTR pszSegmentName = pcsz;
while (' ' != *++pcsz);
*pcsz++ = 0;
if (!strcmp(pszSegmentName, ".text$mn$cpp$u"))
{
if (--s < pinth->FileHeader.NumberOfSections)
{
PIMAGE_SECTION_HEADER pish = IMAGE_FIRST_SECTION(pinth) + s;
if (o < pish->Misc.VirtualSize && (o + i) <= pish->Misc.VirtualSize)
{
_M_rvaU = pish->VirtualAddress + o;
_M_sizeU = i;
}
}
}
goto __1;
}
//skip space
while (' ' == *++pcsz);
PSTR pszFunc = pcsz;
while (' ' != *++pcsz);
*pcsz = 0;
u = _strtoui64(pcsz + 1, &pcsz, 16);
if (' ' != *pcsz || !ImageBase)
{
return 0;
}
if (u <= ImageBase)
{
goto __1;
}
if (0x1000000 < (u -= ImageBase))
{
goto __1;
}
if (!memcmp("??_C@_", pszFunc, 6))
{
if (PSTR name = UndecorateString(pszFunc + 6))
{
pszFunc = name;
}
else
{
strcpy(pszFunc, "`string");
}
}
int len = sprintf_s(buf, pszFunc - buf, "%x%c%hs%c", (ULONG)u, 0, pszFunc, 0);
if (0 >= len)
{
return 0;
}
buf += len, n++;
goto __1;
}
BOOL MAP::Init(PCWSTR pszMap, PIMAGE_NT_HEADERS pinth)
{
PBYTE pb;
ULONG cb;
if (0 <= ReadFromFile(pszMap, &pb, &cb, 0, 1))
{
pb[cb] = 0;
if (RO* pr = Parse((PSTR)pb, pinth))
{
ULONG n = _M_n;
if (sizeof(RO) * n <= (cb - RtlPointerToOffset(pb, pr)))
{
_M_pr = pr;
PSTR pc = (PSTR)pb;
do
{
ULONG u = strtoul(pc, &pc, 16);
if (*pc)
{
break;
}
pr->rva = u;
pr++->ofs = RtlPointerToOffset(pb, ++pc);
pc += strlen(pc) + 1;
} while (--n);
if (!n)
{
qsort(pr = _M_pr, n = _M_n, sizeof(RO), (int(__cdecl*)(const void*, const void*))RO::compare);
_M_minRVA = pr->rva, _M_maxRVA = pr[n - 1].rva;
_M_buf = (PSTR)pb;
return TRUE;
}
}
}
delete[] pb;
}
return FALSE;
}
PCSTR MAP::GetName(_In_ ULONG_PTR rva, _Out_ ULONG* d)
{
ULONG a = 0, o, b = _M_n;
RO* pr = _M_pr;
if (rva < _M_minRVA || _M_maxRVA <= rva)
{
*d = (ULONG)rva;
return "";
}
do
{
ULONG r = pr[o = (a + b) >> 1].rva;
if (rva == r)
{
*d = 0;
return _M_buf + pr[o].ofs;
}
rva < r ? b = o : a = o + 1;
} while (a < b);
*d = (ULONG)rva - pr[--a].rva;
return _M_buf + pr[a].ofs;
}