Example #1
0
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));
		}
	}
}
Example #2
0
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));
		}
	}
}
Example #3
0
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
	}
}
Example #4
0
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;
	}
}
Example #5
0
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
	}
}
Example #6
0
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;
}