parent
50ce7be0c3
commit
9f42cfe31b
|
@ -53,7 +53,7 @@ static bool _sectionfromaddr(duint addr, char* section)
|
|||
|
||||
static bool _patchget(duint addr)
|
||||
{
|
||||
return patchget(addr, 0);
|
||||
return PatchGet(addr, 0);
|
||||
}
|
||||
|
||||
static bool _patchinrange(duint start, duint end)
|
||||
|
@ -84,13 +84,13 @@ static void _patchrestorerange(duint start, duint end)
|
|||
end = a;
|
||||
}
|
||||
for(duint i = start; i < end + 1; i++)
|
||||
patchdel(i, true);
|
||||
PatchDelete(i, true);
|
||||
GuiUpdatePatches();
|
||||
}
|
||||
|
||||
static bool _patchrestore(duint addr)
|
||||
{
|
||||
return patchdel(addr, true);
|
||||
return PatchDelete(addr, true);
|
||||
}
|
||||
|
||||
static void _getcallstack(DBGCALLSTACK* callstack)
|
||||
|
@ -178,9 +178,9 @@ void dbgfunctionsinit()
|
|||
_dbgfunctions.PatchInRange = _patchinrange;
|
||||
_dbgfunctions.MemPatch = _mempatch;
|
||||
_dbgfunctions.PatchRestoreRange = _patchrestorerange;
|
||||
_dbgfunctions.PatchEnum = (PATCHENUM)patchenum;
|
||||
_dbgfunctions.PatchEnum = (PATCHENUM)PatchEnum;
|
||||
_dbgfunctions.PatchRestore = _patchrestore;
|
||||
_dbgfunctions.PatchFile = (PATCHFILE)patchfile;
|
||||
_dbgfunctions.PatchFile = (PATCHFILE)PatchFile;
|
||||
_dbgfunctions.ModPathFromAddr = ModPathFromAddr;
|
||||
_dbgfunctions.ModPathFromName = ModPathFromName;
|
||||
_dbgfunctions.DisasmFast = disasmfast;
|
||||
|
|
|
@ -101,7 +101,7 @@ void dbclose()
|
|||
FunctionClear();
|
||||
loopclear();
|
||||
BpClear();
|
||||
patchclear();
|
||||
PatchClear();
|
||||
}
|
||||
|
||||
///api functions
|
||||
|
|
|
@ -42,8 +42,8 @@ bool LabelSet(uint Address, const char* Text, bool Manual)
|
|||
// Insert label by key
|
||||
uint key = ModHashFromAddr(Address);
|
||||
|
||||
if(!labels.insert(std::make_pair(ModHashFromAddr(key), label)).second)
|
||||
labels[key] = label;
|
||||
if(!labels.insert(std::make_pair(ModHashFromAddr(key), labelInfo)).second)
|
||||
labels[key] = labelInfo;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
@ -252,7 +252,7 @@ bool LabelEnum(LABELSINFO* List, size_t* Size)
|
|||
for (auto& itr : labels)
|
||||
{
|
||||
*List = itr.second;
|
||||
List->addr += ModBaseFromName(itr.econd.mod);
|
||||
List->addr += ModBaseFromName(itr.second.mod);
|
||||
List++;
|
||||
}
|
||||
|
||||
|
|
|
@ -10,12 +10,12 @@ struct LABELSINFO
|
|||
bool manual;
|
||||
};
|
||||
|
||||
bool LabelSet(uint addr, const char* text, bool manual);
|
||||
bool labelfromstring(const char* text, uint* addr);
|
||||
bool LabelGet(uint addr, char* text);
|
||||
bool LabelDelete(uint addr);
|
||||
void LabelDelRange(uint start, uint end);
|
||||
bool LabelSet(uint Address, const char* Text, bool Manual);
|
||||
bool LabelFromString(const char* Text, uint* Address);
|
||||
bool LabelGet(uint Address, char* Text);
|
||||
bool LabelDelete(uint Address);
|
||||
void LabelDelRange(uint Start, uint End);
|
||||
void labelcachesave(JSON root);
|
||||
void labelcacheload(JSON root);
|
||||
bool LabelEnum(LABELSINFO* labellist, size_t* cbsize);
|
||||
bool LabelEnum(LABELSINFO* List, size_t* Size);
|
||||
void LabelClear();
|
|
@ -277,7 +277,7 @@ bool MemPatch(void* BaseAddress, void* Buffer, SIZE_T Size, SIZE_T* NumberOfByte
|
|||
}
|
||||
|
||||
for(SIZE_T i = 0; i < Size; i++)
|
||||
patchset((uint)BaseAddress + i, oldData[i], ((unsigned char*)Buffer)[i]);
|
||||
PatchSet((uint)BaseAddress + i, oldData[i], ((unsigned char*)Buffer)[i]);
|
||||
|
||||
return MemWrite(BaseAddress, Buffer, Size, NumberOfBytesWritten);
|
||||
}
|
||||
|
|
|
@ -6,198 +6,307 @@
|
|||
#include "threading.h"
|
||||
#include "module.h"
|
||||
|
||||
typedef std::map<uint, PATCHINFO> PatchesInfo;
|
||||
|
||||
static PatchesInfo patches;
|
||||
|
||||
bool patchset(uint addr, unsigned char oldbyte, unsigned char newbyte)
|
||||
bool PatchSet(uint Address, unsigned char OldByte, unsigned char NewByte)
|
||||
{
|
||||
if(!DbgIsDebugging() || !MemIsValidReadPtr(addr))
|
||||
// MemIsValidReadPtr also checks if the debugger is actually
|
||||
// debugging
|
||||
if(!MemIsValidReadPtr(Address))
|
||||
return false;
|
||||
if(oldbyte == newbyte)
|
||||
return true; //no need to make a patch for a byte that is equal to itself
|
||||
|
||||
// Don't patch anything if the new and old values are the same
|
||||
if(OldByte == NewByte)
|
||||
return true;
|
||||
|
||||
PATCHINFO newPatch;
|
||||
newPatch.addr = addr - ModBaseFromAddr(addr);
|
||||
ModNameFromAddr(addr, newPatch.mod, true);
|
||||
newPatch.oldbyte = oldbyte;
|
||||
newPatch.newbyte = newbyte;
|
||||
uint key = ModHashFromAddr(addr);
|
||||
CriticalSectionLocker locker(LockPatches);
|
||||
PatchesInfo::iterator found = patches.find(key);
|
||||
if(found != patches.end()) //we found a patch on the specified address
|
||||
newPatch.addr = Address - ModBaseFromAddr(Address);
|
||||
newPatch.oldbyte = OldByte;
|
||||
newPatch.newbyte = NewByte;
|
||||
ModNameFromAddr(Address, newPatch.mod, true);
|
||||
|
||||
// Generate a key for this address
|
||||
uint key = ModHashFromAddr(Address);
|
||||
|
||||
EXCLUSIVE_ACQUIRE(LockPatches);
|
||||
|
||||
// Find any patch with this specific address
|
||||
auto found = patches.find(key);
|
||||
|
||||
if(found != patches.end())
|
||||
{
|
||||
if(found->second.oldbyte == newbyte) //patch is undone
|
||||
if(found->second.oldbyte == NewByte)
|
||||
{
|
||||
// The patch was undone here
|
||||
patches.erase(found);
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
newPatch.oldbyte = found->second.oldbyte; //keep the original byte from the previous patch
|
||||
found->second = newPatch;
|
||||
// Keep the original byte from the previous patch
|
||||
newPatch.oldbyte = found->second.oldbyte;
|
||||
found->second = newPatch;
|
||||
}
|
||||
}
|
||||
else
|
||||
patches.insert(std::make_pair(key, newPatch));
|
||||
else
|
||||
{
|
||||
// The entry was never found, insert it
|
||||
patches.insert(std::make_pair(key, newPatch));
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool patchget(uint addr, PATCHINFO* patch)
|
||||
bool PatchGet(uint Address, PATCHINFO* Patch)
|
||||
{
|
||||
// CHECK: Export
|
||||
if(!DbgIsDebugging())
|
||||
return false;
|
||||
CriticalSectionLocker locker(LockPatches);
|
||||
PatchesInfo::iterator found = patches.find(ModHashFromAddr(addr));
|
||||
if(found == patches.end()) //not found
|
||||
|
||||
SHARED_ACQUIRE(LockPatches);
|
||||
|
||||
// Find this specific address in the list
|
||||
auto found = patches.find(ModHashFromAddr(Address));
|
||||
|
||||
if(found == patches.end())
|
||||
return false;
|
||||
if(patch)
|
||||
|
||||
// Did the user request an output buffer?
|
||||
if(Patch)
|
||||
{
|
||||
*patch = found->second;
|
||||
patch->addr += ModBaseFromAddr(addr);
|
||||
return true;
|
||||
*Patch = found->second;
|
||||
Patch->addr += ModBaseFromAddr(Address);
|
||||
}
|
||||
return (found->second.oldbyte != found->second.newbyte);
|
||||
|
||||
// Return true because the patch was found
|
||||
return true;
|
||||
}
|
||||
|
||||
bool patchdel(uint addr, bool restore)
|
||||
bool PatchDelete(uint Address, bool Restore)
|
||||
{
|
||||
// CHECK: Export function
|
||||
if(!DbgIsDebugging())
|
||||
return false;
|
||||
CriticalSectionLocker locker(LockPatches);
|
||||
PatchesInfo::iterator found = patches.find(ModHashFromAddr(addr));
|
||||
|
||||
EXCLUSIVE_ACQUIRE(LockPatches);
|
||||
|
||||
// Do a list lookup with hash
|
||||
auto found = patches.find(ModHashFromAddr(Address));
|
||||
|
||||
if(found == patches.end()) //not found
|
||||
return false;
|
||||
if(restore)
|
||||
MemWrite((void*)(found->second.addr + ModBaseFromAddr(addr)), &found->second.oldbyte, sizeof(char), 0);
|
||||
|
||||
// Restore the original byte at this address
|
||||
if(Restore)
|
||||
MemWrite((void*)(found->second.addr + ModBaseFromAddr(Address)), &found->second.oldbyte, sizeof(char), nullptr);
|
||||
|
||||
// Finally remove it from the list
|
||||
patches.erase(found);
|
||||
return true;
|
||||
}
|
||||
|
||||
void patchdelrange(uint start, uint end, bool restore)
|
||||
void PatchDelRange(uint Start, uint End, bool Restore)
|
||||
{
|
||||
if(!DbgIsDebugging())
|
||||
return;
|
||||
bool bDelAll = (start == 0 && end == ~0); //0x00000000-0xFFFFFFFF
|
||||
uint modbase = ModBaseFromAddr(start);
|
||||
if(modbase != ModBaseFromAddr(end))
|
||||
return;
|
||||
start -= modbase;
|
||||
end -= modbase;
|
||||
CriticalSectionLocker locker(LockPatches);
|
||||
PatchesInfo::iterator i = patches.begin();
|
||||
while(i != patches.end())
|
||||
{
|
||||
if(bDelAll || (i->second.addr >= start && i->second.addr < end))
|
||||
{
|
||||
if(restore)
|
||||
MemWrite((void*)(i->second.addr + modbase), &i->second.oldbyte, sizeof(char), 0);
|
||||
patches.erase(i++);
|
||||
}
|
||||
else
|
||||
i++;
|
||||
}
|
||||
// CHECK: Export call
|
||||
if (!DbgIsDebugging())
|
||||
return;
|
||||
|
||||
// Are all bookmarks going to be deleted?
|
||||
// 0x00000000 - 0xFFFFFFFF
|
||||
if (Start == 0 && End == ~0)
|
||||
{
|
||||
EXCLUSIVE_ACQUIRE(LockPatches);
|
||||
patches.clear();
|
||||
}
|
||||
else
|
||||
{
|
||||
// Make sure 'Start' and 'End' reference the same module
|
||||
uint moduleBase = ModBaseFromAddr(Start);
|
||||
|
||||
if (moduleBase != ModBaseFromAddr(End))
|
||||
return;
|
||||
|
||||
// VA to RVA in module
|
||||
Start -= moduleBase;
|
||||
End -= moduleBase;
|
||||
|
||||
EXCLUSIVE_ACQUIRE(LockPatches);
|
||||
for (auto itr = patches.begin(); itr != patches.end();)
|
||||
{
|
||||
// [Start, End)
|
||||
if (itr->second.addr >= Start && itr->second.addr < End)
|
||||
{
|
||||
// Restore the original byte if necessary
|
||||
if (Restore)
|
||||
MemWrite((void*)(itr->second.addr + moduleBase), &itr->second.oldbyte, sizeof(char), nullptr);
|
||||
|
||||
itr = patches.erase(itr);
|
||||
}
|
||||
else
|
||||
itr++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void patchclear(const char* mod)
|
||||
{
|
||||
CriticalSectionLocker locker(LockPatches);
|
||||
if(!mod or !*mod)
|
||||
patches.clear();
|
||||
else
|
||||
{
|
||||
PatchesInfo::iterator i = patches.begin();
|
||||
while(i != patches.end())
|
||||
{
|
||||
if(!_stricmp(i->second.mod, mod))
|
||||
patches.erase(i++);
|
||||
else
|
||||
i++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool patchenum(PATCHINFO* patcheslist, size_t* cbsize)
|
||||
bool PatchEnum(PATCHINFO* List, size_t* Size)
|
||||
{
|
||||
// CHECK: Exported
|
||||
if(!DbgIsDebugging())
|
||||
return false;
|
||||
if(!patcheslist && !cbsize)
|
||||
|
||||
// At least one parameter is needed
|
||||
if(!List && !Size)
|
||||
return false;
|
||||
CriticalSectionLocker locker(LockPatches);
|
||||
if(!patcheslist && cbsize)
|
||||
|
||||
SHARED_ACQUIRE(LockPatches);
|
||||
|
||||
// Did the user request the size?
|
||||
if(Size)
|
||||
{
|
||||
*cbsize = patches.size() * sizeof(PATCHINFO);
|
||||
return true;
|
||||
*Size = patches.size() * sizeof(PATCHINFO);
|
||||
|
||||
if (!List)
|
||||
return true;
|
||||
}
|
||||
int j = 0;
|
||||
for(PatchesInfo::iterator i = patches.begin(); i != patches.end(); ++i, j++)
|
||||
|
||||
// Copy each vector entry to a C-style array
|
||||
for(auto& itr : patches)
|
||||
{
|
||||
patcheslist[j] = i->second;
|
||||
uint modbase = ModBaseFromName(patcheslist[j].mod);
|
||||
patcheslist[j].addr += modbase;
|
||||
*List = itr.second;
|
||||
List->addr += ModBaseFromName(itr.second.mod);;
|
||||
List++;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
int patchfile(const PATCHINFO* patchlist, int count, const char* szFileName, char* error)
|
||||
int PatchFile(const PATCHINFO* List, int Count, const char* FileName, char* Error)
|
||||
{
|
||||
if(!count)
|
||||
//
|
||||
// This function returns an int based on the number
|
||||
// of patches applied. -1 indicates a failure.
|
||||
//
|
||||
if(Count <= 0)
|
||||
{
|
||||
if(error)
|
||||
strcpy_s(error, MAX_ERROR_SIZE, "no patches to apply");
|
||||
// Notify the user of the error
|
||||
if(Error)
|
||||
strcpy_s(Error, MAX_ERROR_SIZE, "No patches to apply");
|
||||
|
||||
return -1;
|
||||
}
|
||||
char modname[MAX_MODULE_SIZE] = "";
|
||||
strcpy_s(modname, patchlist[0].mod);
|
||||
//check if all patches are in the same module
|
||||
for(int i = 0; i < count; i++)
|
||||
if(_stricmp(patchlist[i].mod, modname))
|
||||
{
|
||||
if(error)
|
||||
sprintf(error, "not all patches are in module %s", modname);
|
||||
return -1;
|
||||
}
|
||||
uint modbase = ModBaseFromName(modname);
|
||||
if(!modbase) //module not loaded
|
||||
|
||||
// Get a copy of the first module name in the array
|
||||
char moduleName[MAX_MODULE_SIZE];
|
||||
strcpy_s(moduleName, List[0].mod);
|
||||
|
||||
// Check if all patches are in the same module
|
||||
for (int i = 0; i < Count; i++)
|
||||
{
|
||||
if (_stricmp(List[i].mod, moduleName))
|
||||
{
|
||||
if (Error)
|
||||
sprintf_s(Error, MAX_ERROR_SIZE, "not all patches are in module %s", moduleName);
|
||||
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
// See if the module was loaded
|
||||
uint moduleBase = ModBaseFromName(moduleName);
|
||||
|
||||
if(!moduleBase)
|
||||
{
|
||||
if(error)
|
||||
sprintf(error, "failed to get base of module %s", modname);
|
||||
if(Error)
|
||||
sprintf_s(Error, MAX_ERROR_SIZE, "failed to get base of module %s", moduleName);
|
||||
|
||||
return -1;
|
||||
}
|
||||
wchar_t szOriginalName[MAX_PATH] = L"";
|
||||
if(!GetModuleFileNameExW(fdProcessInfo->hProcess, (HMODULE)modbase, szOriginalName, MAX_PATH))
|
||||
|
||||
// Get the unicode version of the module's path
|
||||
wchar_t originalName[MAX_PATH];
|
||||
|
||||
if(!GetModuleFileNameExW(fdProcessInfo->hProcess, (HMODULE)moduleBase, originalName, ARRAYSIZE(originalName)))
|
||||
{
|
||||
if(error)
|
||||
sprintf(error, "failed to get module path of module %s", modname);
|
||||
if(Error)
|
||||
sprintf_s(Error, MAX_ERROR_SIZE, "Failed to get module path of module %s", moduleName);
|
||||
|
||||
return -1;
|
||||
}
|
||||
if(!CopyFileW(szOriginalName, StringUtils::Utf8ToUtf16(szFileName).c_str(), false))
|
||||
|
||||
// Create a temporary backup file
|
||||
if(!CopyFileW(originalName, StringUtils::Utf8ToUtf16(FileName).c_str(), false))
|
||||
{
|
||||
if(error)
|
||||
strcpy_s(error, MAX_ERROR_SIZE, "failed to make a copy of the original file (patch target is in use?)");
|
||||
if(Error)
|
||||
strcpy_s(Error, MAX_ERROR_SIZE, "Failed to make a copy of the original file (patch target is in use?)");
|
||||
|
||||
return -1;
|
||||
}
|
||||
HANDLE FileHandle;
|
||||
DWORD LoadedSize;
|
||||
HANDLE FileMap;
|
||||
ULONG_PTR FileMapVA;
|
||||
if(StaticFileLoadW(StringUtils::Utf8ToUtf16(szFileName).c_str(), UE_ACCESS_ALL, false, &FileHandle, &LoadedSize, &FileMap, &FileMapVA))
|
||||
|
||||
HANDLE fileHandle;
|
||||
DWORD loadedSize;
|
||||
HANDLE fileMap;
|
||||
ULONG_PTR fileMapVa;
|
||||
if (!StaticFileLoadW(StringUtils::Utf8ToUtf16(FileName).c_str(), UE_ACCESS_ALL, false, &fileHandle, &loadedSize, &fileMap, &fileMapVa))
|
||||
{
|
||||
strcpy_s(Error, MAX_ERROR_SIZE, "StaticFileLoad failed");
|
||||
return -1;
|
||||
}
|
||||
|
||||
// Begin iterating all patches, applying them to a file
|
||||
int patchCount = 0;
|
||||
|
||||
for(int i = 0; i < Count; i++)
|
||||
{
|
||||
int patched = 0;
|
||||
for(int i = 0; i < count; i++)
|
||||
{
|
||||
unsigned char* ptr = (unsigned char*)ConvertVAtoFileOffsetEx(FileMapVA, LoadedSize, modbase, patchlist[i].addr, false, true);
|
||||
if(!ptr) //skip patches that do not have a raw address
|
||||
continue;
|
||||
dprintf("patch%.4d|%s[%.8X]:%.2X/%.2X->%.2X\n", i + 1, modname, ptr - FileMapVA, *ptr, patchlist[i].oldbyte, patchlist[i].newbyte);
|
||||
*ptr = patchlist[i].newbyte;
|
||||
patched++;
|
||||
}
|
||||
if(!StaticFileUnloadW(StringUtils::Utf8ToUtf16(szFileName).c_str(), true, FileHandle, LoadedSize, FileMap, FileMapVA))
|
||||
{
|
||||
if(error)
|
||||
strcpy_s(error, MAX_ERROR_SIZE, "StaticFileUnload failed");
|
||||
return -1;
|
||||
}
|
||||
return patched;
|
||||
// Convert the virtual address to an offset within disk file data
|
||||
unsigned char* ptr = (unsigned char*)ConvertVAtoFileOffsetEx(fileMapVa, loadedSize, moduleBase, List[i].addr, false, true);
|
||||
|
||||
// Skip patches that do not have a raw address
|
||||
if(!ptr)
|
||||
continue;
|
||||
|
||||
dprintf("patch%.4d|%s[%.8X]:%.2X/%.2X->%.2X\n", i + 1, moduleName, ptr - fileMapVa, *ptr, List[i].oldbyte, List[i].newbyte);
|
||||
*ptr = List[i].newbyte;
|
||||
patchCount++;
|
||||
}
|
||||
strcpy_s(error, MAX_ERROR_SIZE, "StaticFileLoad failed");
|
||||
return -1;
|
||||
|
||||
// Unload the file from memory and commit changes to disk
|
||||
if(!StaticFileUnloadW(StringUtils::Utf8ToUtf16(FileName).c_str(), true, fileHandle, loadedSize, fileMap, fileMapVa))
|
||||
{
|
||||
if(Error)
|
||||
strcpy_s(Error, MAX_ERROR_SIZE, "StaticFileUnload failed");
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
// Zero the error message and return count
|
||||
if (Error)
|
||||
memset(Error, 0, MAX_ERROR_SIZE * sizeof(char));
|
||||
|
||||
return patchCount;
|
||||
}
|
||||
|
||||
void PatchClear(const char* Module)
|
||||
{
|
||||
EXCLUSIVE_ACQUIRE(LockPatches);
|
||||
|
||||
// Was a module specified?
|
||||
if (!Module || Module[0] == '\0')
|
||||
{
|
||||
// No specific entries to delete, so remove all of them
|
||||
patches.clear();
|
||||
}
|
||||
else
|
||||
{
|
||||
// Otherwise iterate over each patch and check the owner
|
||||
// module for the address
|
||||
for (auto itr = patches.begin(); itr != patches.end();)
|
||||
{
|
||||
if (!_stricmp(itr->second.mod, Module))
|
||||
itr = patches.erase(itr);
|
||||
else
|
||||
itr++;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,5 +1,4 @@
|
|||
#ifndef _PATCHES_H
|
||||
#define _PATCHES_H
|
||||
#pragma once
|
||||
|
||||
#include "_global.h"
|
||||
|
||||
|
@ -10,14 +9,11 @@ struct PATCHINFO
|
|||
unsigned char oldbyte;
|
||||
unsigned char newbyte;
|
||||
};
|
||||
typedef std::map<uint, PATCHINFO> PatchesInfo;
|
||||
|
||||
bool patchset(uint addr, unsigned char oldbyte, unsigned char newbyte);
|
||||
bool patchget(uint addr, PATCHINFO* patch);
|
||||
bool patchdel(uint addr, bool restore);
|
||||
void patchdelrange(uint start, uint end, bool restore);
|
||||
void patchclear(const char* mod = 0);
|
||||
bool patchenum(PATCHINFO* patchlist, size_t* cbsize);
|
||||
int patchfile(const PATCHINFO* patchlist, int count, const char* szFileName, char* error);
|
||||
|
||||
#endif //_PATCHES_H
|
||||
bool PatchSet(uint Address, unsigned char OldByte, unsigned char NewByte);
|
||||
bool PatchGet(uint Address, PATCHINFO* Patch);
|
||||
bool PatchDelete(uint Address, bool Restore);
|
||||
void PatchDelRange(uint Start, uint End, bool Restore);
|
||||
bool PatchEnum(PATCHINFO* List, size_t* Size);
|
||||
int PatchFile(const PATCHINFO* List, int Count, const char* FileName, char* Error);
|
||||
void PatchClear(const char* Module = nullptr);
|
|
@ -1557,7 +1557,7 @@ bool valfromstring(const char* string, uint* value, bool silent, bool baseonly,
|
|||
return false;
|
||||
else if(valapifromstring(string, value, value_size, true, silent, hexonly)) //then come APIs
|
||||
return true;
|
||||
else if(labelfromstring(string, value)) //then come labels
|
||||
else if(LabelFromString(string, value)) //then come labels
|
||||
return true;
|
||||
else if(SymAddrFromName(string, value)) //then come symbols
|
||||
return true;
|
||||
|
|
Loading…
Reference in New Issue