void SymbolMap::AddData(u32 address, u32 size, DataType type, int moduleIndex) { lock_guard guard(lock_); if (moduleIndex == -1) { moduleIndex = GetModuleIndex(address); } // Is there an existing one? u32 relAddress = GetModuleRelativeAddr(address, moduleIndex); auto symbolKey = std::make_pair(moduleIndex, relAddress); auto existing = data.find(symbolKey); if (existing == data.end()) { // Fall back: maybe it's got moduleIndex = 0. existing = data.find(std::make_pair(0, address)); } if (existing != data.end()) { existing->second.size = size; existing->second.type = type; if (existing->second.module != moduleIndex) { DataEntry entry = existing->second; entry.module = moduleIndex; entry.start = relAddress; data.erase(existing); data[symbolKey] = entry; } // Refresh the active item if it exists. auto active = activeData.find(address); if (active != activeData.end() && active->second.module == moduleIndex) { activeData.erase(active); activeData.insert(std::make_pair(address, existing->second)); } } else { DataEntry entry; entry.start = relAddress; entry.size = size; entry.type = type; entry.module = moduleIndex; data[symbolKey] = entry; if (IsModuleActive(moduleIndex)) { activeData.insert(std::make_pair(address, entry)); } } }
void SymbolMap::AddLabel(const char* name, u32 address, int moduleIndex) { lock_guard guard(lock_); if (moduleIndex == -1) { moduleIndex = GetModuleIndex(address); } // Is there an existing one? u32 relAddress = GetModuleRelativeAddr(address, moduleIndex); auto symbolKey = std::make_pair(moduleIndex, relAddress); auto existing = labels.find(symbolKey); if (existing == labels.end()) { // Fall back: maybe it's got moduleIndex = 0. existing = labels.find(std::make_pair(0, address)); } if (existing != labels.end()) { // We leave an existing label alone, rather than overwriting. // But we'll still upgrade it to the correct module / relative address. if (existing->second.module != moduleIndex) { LabelEntry label = existing->second; label.addr = relAddress; label.module = moduleIndex; labels.erase(existing); labels[symbolKey] = label; // Refresh the active item if it exists. auto active = activeLabels.find(address); if (active != activeLabels.end() && active->second.module == moduleIndex) { activeLabels.erase(active); activeLabels.insert(std::make_pair(address, existing->second)); } } } else { LabelEntry label; label.addr = relAddress; label.module = moduleIndex; strncpy(label.name, name, 128); label.name[127] = 0; labels[symbolKey] = label; if (IsModuleActive(moduleIndex)) { activeLabels.insert(std::make_pair(address, label)); } } }
u32 GetSyscallOp(const char *moduleName, u32 nib) { int modindex = GetModuleIndex(moduleName); if (modindex != -1) { int funcindex = GetFuncIndex(modindex, nib); if (funcindex != -1) { return (0x0000000c | (modindex<<18) | (funcindex<<6)); } else { return (0x0003FFCC | (modindex<<18)); // invalid syscall } } else { ERROR_LOG(HLE, "Unknown module %s!", moduleName); return (0x0003FFCC); // invalid syscall } }
bool WriteSyscall(const char *moduleName, u32 nib, u32 address) { if (nib == 0) { WARN_LOG_REPORT(HLE, "Wrote patched out nid=0 syscall (%s)", moduleName); Memory::Write_U32(MIPS_MAKE_JR_RA(), address); //patched out? Memory::Write_U32(MIPS_MAKE_NOP(), address+4); //patched out? return true; } int modindex = GetModuleIndex(moduleName); if (modindex != -1) { Memory::Write_U32(MIPS_MAKE_JR_RA(), address); // jr ra Memory::Write_U32(GetSyscallOp(moduleName, nib), address + 4); return true; } else { ERROR_LOG_REPORT(HLE, "Unable to write unknown syscall: %s/%08x", moduleName, nib); return false; } }
u32 GetSyscallOp(const char *moduleName, u32 nib) { // Special case to hook up bad imports. if (moduleName == NULL) { return (0x03FFFFCC); // invalid syscall } int modindex = GetModuleIndex(moduleName); if (modindex != -1) { int funcindex = GetFuncIndex(modindex, nib); if (funcindex != -1) { return (0x0000000c | (modindex<<18) | (funcindex<<6)); } else { INFO_LOG(HLE, "Syscall (%s, %08x) unknown", moduleName, nib); return (0x0003FFCC | (modindex<<18)); // invalid syscall } } else { ERROR_LOG(HLE, "Unknown module %s!", moduleName); return (0x03FFFFCC); // invalid syscall } }
ULONG NextAsmToken (PULONG pvalue) { ULONG base; UCHAR chSymbol[SYMBOLSIZE]; UCHAR chPreSym[9]; ULONG cbSymbol = 0; UCHAR fNumber = TRUE; UCHAR fSymbol = TRUE; UCHAR fForceReg = FALSE; ULONG errNumber = 0; UCHAR ch; UCHAR chlow; UCHAR chtemp; UCHAR limit1 = '9'; UCHAR limit2 = '9'; UCHAR fDigit = FALSE; ULONG value = 0; ULONG tmpvalue; ULONG index; CHAR iModule; PIMAGE_INFO pImage; base = baseDefault; // skip leading white space chlow = (UCHAR)PeekAsmChar(); chlow = (UCHAR)tolower(chlow); pchAsmLine++; // test for special character operators and register variable switch (chlow) { case '\0': pchAsmLine--; return ASM_EOL_CLASS; case ',': return ASM_COMMA_CLASS; case '+': *pvalue = ASM_ADDOP_PLUS; return ASM_ADDOP_CLASS; case '-': *pvalue = ASM_ADDOP_MINUS; return ASM_ADDOP_CLASS; case '*': *pvalue = ASM_MULOP_MULT; return ASM_MULOP_CLASS; case '/': *pvalue = ASM_MULOP_DIVIDE; return ASM_MULOP_CLASS; case ':': return ASM_COLNOP_CLASS; case '(': return ASM_LPAREN_CLASS; case ')': return ASM_RPAREN_CLASS; case '[': return ASM_LBRACK_CLASS; case ']': return ASM_RBRACK_CLASS; case '@': fForceReg = TRUE; chlow = (UCHAR)*pchAsmLine++; chlow = (UCHAR)tolower(chLow); break; case '.': return ASM_DOTOP_CLASS; case '\'': for (index = 0; index < 5; index++) { ch = *pchAsmLine++; if (ch == '\'' || ch == '\0') break; value = (value << 8) + (ULONG)ch; } if (ch == '\0' || index == 0 || index == 5) { pchAsmLine--; *pvalue = SYNTAX; return ASM_ERROR_CLASS; } pchAsmLine++; *pvalue = value; return ASM_NUMBER_CLASS; } // if first character is a decimal digit, it cannot // be a symbol. leading '0' implies octal, except // a leading '0x' implies hexadecimal. if (chlow >= '0' && chlow <= '9') { if (fForceReg) { *pvalue = SYNTAX; return ASM_ERROR_CLASS; } fSymbol = FALSE; if (chlow == '0') { ch = *pchAsmLine++; chlow = (UCHAR)tolower(ch); if (chlow == 'x') { base = 16; ch = *pchAsmLine++; chlow = (UCHAR)tolower(ch); } else if (chlow == 'n') { base = 10; ch = *pchAsmLine++; chlow = (UCHAR)tolower(ch); } else { base = 8; fDigit = TRUE; } } } // a number can start with a letter only if base is // hexadecimal and it is a hexadecimal digit 'a'-'f'. else if ((chlow < 'a' && chlow > 'f') || base != 16) fNumber = FALSE; // set limit characters for the appropriate base. if (base == 8) limit1 = '7'; if (base == 16) limit2 = 'f'; // perform processing while character is a letter, // digit, or underscore. while ((chlow >= 'a' && chlow <= 'z') || (chlow >= '0' && chlow <= '9') || (chlow == '_')) { // if possible number, test if within proper range, // and if so, accumulate sum. if (fNumber) { if ((chlow >= '0' && chlow <= limit1) || (chlow >= 'a' && chlow <= limit2)) { fDigit = TRUE; tmpvalue = value * base; if (tmpvalue < value) errNumber = OVERFLOW; chtemp = (UCHAR)(chlow - '0'); if (chtemp > 9) chtemp -= 'a' - '0' - 10; value = tmpvalue + (ULONG)chtemp; if (value < tmpvalue) errNumber = OVERFLOW; } else { fNumber = FALSE; errNumber = SYNTAX; } } if (fSymbol) { if (cbSymbol < 9) chPreSym[cbSymbol] = chlow; if (cbSymbol < SYMBOLSIZE - 1) chSymbol[cbSymbol++] = ch; } ch = *pchAsmLine++; chlow = (UCHAR)tolower(ch); } // back up pointer to first character after token. pchAsmLine--; if (cbSymbol < 9) chPreSym[cbSymbol] = '\0'; // if fForceReg, check for register name and return // success or failure if (fForceReg) if ((index = GetAsmReg(chPreSym, pvalue)) != 0) { if (index == ASM_REG_SEGMENT) if (PeekAsmChar() == ':') { pchAsmLine++; index = ASM_SEGOVR_CLASS; } return index; // class type returned by GetAsmReg } else { *pvalue = BADREG; return ASM_ERROR_CLASS; } // next test for reserved word and symbol string if (fSymbol) { // if possible symbol, check lowercase string in chPreSym // for text operator or register name. // otherwise, return symbol value from name in chSymbol. for (index = 0; index < RESERVESIZE; index++) if (!strcmp(chPreSym, AsmReserved[index].pchRes)) { *pvalue = AsmReserved[index].valueRes; return AsmReserved[index].valueRes & ASM_CLASS_MASK; } // start processing string as symbol chSymbol[cbSymbol] = '\0'; // test if symbol is a module name (with '!' after it) // if so, get next token and treat as symbol pImage = GetModuleIndex(chSymbol); if (pImage && (ch = PeekAsmChar()) == '!') { pchAsmLine++; ch = PeekAsmChar(); pchAsmLine++; cbSymbol = 0; while ((ch >= 'A' && ch <= 'Z') || (ch >= 'a' && ch <= 'z') || (ch >= '0' && ch <= '9') || (ch == '_')) { chSymbol[cbSymbol++] = ch; ch = *pchAsmLine++; } chSymbol[cbSymbol] = '\0'; pchAsmLine--; iModule = pImage->index; } else iModule = -1; if (GetOffsetFromSym(chSymbol, pvalue, iModule)) return ASM_SYMBOL_CLASS; // symbol is undefined. // if a possible hex number, do not set the error type if (!fNumber) errNumber = VARDEF; } // if possible number and no error, return the number if (fNumber && !errNumber) { if (fDigit) { // check for possible segment specification // "<16-bit number>:" if (PeekAsmChar() == ':') { pchAsmLine++; if (value > 0xffff) error(BADSEG); *pvalue = value; return ASM_SEGMENT_CLASS; } *pvalue = value; return ASM_NUMBER_CLASS; } else errNumber = SYNTAX; } // last chance, undefined symbol and illegal number, // so test for register, will handle old format if ((index = GetAsmReg(chPreSym, pvalue)) != 0) { if (index == ASM_REG_SEGMENT) if (PeekAsmChar() == ':') { pchAsmLine++; index = ASM_SEGOVR_CLASS; } return index; // class type returned by GetAsmReg } *pvalue = (ULONG) errNumber; return ASM_ERROR_CLASS; }