/*-----------------------------------------------------------------*/ static S4O_RET termScanAtFunc (const lineNode *pl, int rIdx) { sym_link *ftype; bool banked_reg = (rIdx == R0_IDX) || (rIdx == R1_IDX) || (rIdx == R2_IDX); if (!isFunc (pl)) return S4O_CONTINUE; // let's assume calls to literally given locations use the default // most notably : (*(void (*)()) 0) (); see bug 1749275 if (IS_VALOP (IC_LEFT (pl->ic))) return (options.model == MODEL_HUGE) && banked_reg ? S4O_ABORT : options.all_callee_saves ? S4O_CONTINUE : S4O_TERM; ftype = OP_SYM_TYPE(IC_LEFT(pl->ic)); if (IS_FUNCPTR (ftype)) ftype = ftype->next; if (IFFUNC_ISBANKEDCALL(ftype) && banked_reg) return S4O_ABORT; if (FUNC_ARGS (ftype) && getSize (FUNC_ARGS (ftype)->type) > 4) return S4O_ABORT; if (FUNC_CALLEESAVES(ftype)) return S4O_CONTINUE; if (FUNC_ISNAKED(ftype)) return S4O_CONTINUE; return S4O_TERM; }
// SUBEXP statment_type subexp::getStatmentType() { build_in_func buildInFunc; char *pFuncName; parser parParser; int iFuncNameLen; for (int i = 0; exp[i]; i++) { if (exp[i] == '=') return Setter; else if (isChar(exp[i])) { iFuncNameLen = isFunc(exp, i); if (iFuncNameLen) { pFuncName = new char[iFuncNameLen]; parParser.parseFuncName(exp, pFuncName, i); if (buildInFunc.chooseFunc(pFuncName) == buildInFunc.chooseFunc("show")) { delete pFuncName; return VoidFunc; } delete pFuncName; } } } return Equation; }
tid_t create_vtbl_struct(ea_t vtbl_addr, ea_t vtbl_addr_end, char* vtbl_name, uval_t idx, unsigned int* vtbl_len) { qstring struc_name = vtbl_name; tid_t id = add_struc(BADADDR, struc_name.c_str()); if (id == BADADDR) { struc_name.clear(); struc_name = askstr(HIST_IDENT, NULL, "Default name %s not correct. Enter other structure name: ", struc_name.c_str()); id = add_struc(BADADDR, struc_name.c_str()); set_struc_cmt(id, vtbl_name, true); } struc_t* new_struc = get_struc(id); if (!new_struc) return BADNODE; ea_t ea = vtbl_addr; int offset = 0; while (ea < vtbl_addr_end) { offset = ea - vtbl_addr; qstring method_name; ea_t method_ea = get_long(ea); if (method_ea == 0) break; if (!isEnabled(method_ea)) break; flags_t method_flags = getFlags(method_ea); char* struc_member_name = NULL; if (isFunc(method_flags)) { method_name = get_short_name(method_ea); if (method_name.length() != 0) struc_member_name = (char*)method_name.c_str(); } add_struc_member(new_struc, NULL, offset, dwrdflag(), NULL, 4); if (struc_member_name) { if (!set_member_name(new_struc, offset, struc_member_name)) { //get_name(NULL, method_ea, method_name, sizeof(method_name)); get_ea_name(&method_name, method_ea); set_member_name(new_struc, offset, struc_member_name); } } ea = ea + 4; flags_t ea_flags = getFlags(ea); if (has_any_name(ea_flags)) break; } return id; }
int parser::parseFuncArgs(char *p, int &iStartParse, subexp *pSubExp, float *pArgs, int &iArgsNum, variable_scope &varScope) { iStartParse++; int iSubIndex = floatToInt(parseDigit(p,iStartParse,true)); // Implement unary minus here for (int i = 0; pSubExp[iSubIndex].exp[i]; i++) { // Parse digit if (isDigit(pSubExp[iSubIndex].exp[i])) { pArgs[iArgsNum] = parseDigit(pSubExp[iSubIndex].exp, i, true); } // Parse unary minus else if (pSubExp[iSubIndex].exp[i]=='-' && pSubExp[iSubIndex].exp[i+1] && isDigit(pSubExp[iSubIndex].exp[i+1])) { i++; pArgs[iArgsNum] = parseDigit(pSubExp[iSubIndex].exp, i, true, true); } // Parse next arg else if (pSubExp[iSubIndex].exp[i]==',') { iArgsNum += 1; continue; } // Parse build in func else if (isChar(pSubExp[iSubIndex].exp[i]) && isFunc(pSubExp[iSubIndex].exp, i)) { pArgs[iArgsNum] = pSubExp[parseBuildInFunc(pSubExp[iSubIndex].exp, i, pSubExp, varScope, true)].result; } // Parse variable else if (isChar(pSubExp[iSubIndex].exp[i])) { pArgs[iArgsNum] = varScope.vScope[parseVariable(pSubExp[iSubIndex].exp, i, varScope, false)].getValue(); } // Parse sub string else if (pSubExp[iSubIndex].exp[i]=='$') { pArgs[iArgsNum] = pSubExp[parseSubExp(pSubExp[iSubIndex].exp, i, pSubExp, varScope, true)].result; } } iArgsNum += 1; return iSubIndex; }
/*-----------------------------------------------------------------*/ static S4O_RET scan4op (lineNode **pl, const char *pReg, const char *untilOp, lineNode **plCond) { char *p; int len; bool isConditionalJump; int rIdx; S4O_RET ret; bool findPushPop; findPushPop = untilOp && (strcmp (untilOp, "push") == 0 || strcmp (untilOp, "pop") == 0); /* pReg points to e.g. "ar0"..."ar7" */ len = strlen (pReg); /* get index into pReg table */ for (rIdx = 0; rIdx < mcs51_nRegs; ++rIdx) if (strcmp (regs8051[rIdx].name, pReg + 1) == 0) break; /* sanity check */ if (rIdx >= mcs51_nRegs) { DEADMOVEERROR(); return S4O_ABORT; } for (; *pl; *pl = (*pl)->next) { if (!(*pl)->line || (*pl)->isDebug || (*pl)->isComment) continue; /* don't optimize across inline assembler, e.g. isLabel doesn't work there */ if ((*pl)->isInline) return S4O_ABORT; if ((*pl)->visited) return S4O_VISITED; (*pl)->visited = TRUE; /* found untilOp? */ if (untilOp && strncmp ((*pl)->line, untilOp, strlen (untilOp)) == 0) { p = (*pl)->line + strlen (untilOp); if (*p == '\t' && strncmp (p + 1, pReg, len) == 0) return S4O_FOUNDOPCODE; else { /* found untilOp but without our pReg */ return S4O_ABORT; } } /* found pReg? */ p = strchr ((*pl)->line, '\t'); if (p) { /* skip '\t' */ p++; /* when looking for push or pop and we find a direct access of sp: abort */ if (findPushPop && strstr (p, "sp")) return S4O_ABORT; /* course search */ if (strstr (p, pReg + 1)) { /* ok, let's have a closer look */ /* does opcode read from pReg? */ if (bitVectBitValue (port->peep.getRegsRead ((*pl)), rIdx)) return S4O_RD_OP; /* does opcode write to pReg? */ if (bitVectBitValue (port->peep.getRegsWritten ((*pl)), rIdx)) return S4O_WR_OP; /* we can get here, if the register name is part of a variable name: ignore it */ } } /* found label? */ if ((*pl)->isLabel) { const char *start; char label[SDCC_NAME_MAX + 1]; int len; if (!isLabelDefinition ((*pl)->line, &start, &len, FALSE)) return S4O_ABORT; memcpy (label, start, len); label[len] = '\0'; /* register passing this label */ if (!setLabelRefPassedLabel (label)) { DEADMOVEERROR(); return S4O_ABORT; } continue; } /* branch or terminate? */ isConditionalJump = FALSE; switch ((*pl)->line[0]) { case 'a': if (strncmp ("acall", (*pl)->line, 5) == 0) { /* for comments see 'lcall' */ ret = termScanAtFunc (*pl, rIdx); if (ret != S4O_CONTINUE) return ret; break; } if (strncmp ("ajmp", (*pl)->line, 4) == 0) { *pl = findLabel (*pl); if (!*pl) return S4O_ABORT; } break; case 'c': if (strncmp ("cjne", (*pl)->line, 4) == 0) { isConditionalJump = TRUE; break; } break; case 'd': if (strncmp ("djnz", (*pl)->line, 4) == 0) { isConditionalJump = TRUE; break; } break; case 'j': if (strncmp ("jmp", (*pl)->line, 3) == 0) /* "jmp @a+dptr": no chance to trace execution */ return S4O_ABORT; if (strncmp ("jc", (*pl)->line, 2) == 0 || strncmp ("jnc", (*pl)->line, 3) == 0 || strncmp ("jz", (*pl)->line, 2) == 0 || strncmp ("jnz", (*pl)->line, 3) == 0) { isConditionalJump = TRUE; break; } if (strncmp ("jbc", (*pl)->line, 3) == 0 || strncmp ("jb", (*pl)->line, 2) == 0 || strncmp ("jnb", (*pl)->line, 3) == 0) { isConditionalJump = TRUE; break; } break; case 'l': if (strncmp ("lcall", (*pl)->line, 5) == 0) { const char *p = (*pl)->line+5; while (*p == ' ' || *p == '\t') p++; while (isdigit (*p)) p++; if (isdigit(p[-1]) && *p == '$') /* at least one digit */ { /* this is a temp label for a pcall */ *pl = findLabel (*pl); if (!*pl) return S4O_ABORT; break; } ret = termScanAtFunc (*pl, rIdx); /* If it's a 'normal' 'caller save' function call, all registers have been saved until the 'lcall'. The 'life range' of all registers end at the lcall, and we can terminate our search. * If the function is 'banked', the registers r0, r1 and r2 are used to tell the trampoline the destination. After that their 'life range' ends just like the other registers. * If it's a 'callee save' function call, registers are saved by the callee. We've got no information, if the register might live beyond the lcall. Therefore we've to continue the search. */ if (ret != S4O_CONTINUE) return ret; break; } if (strncmp ("ljmp", (*pl)->line, 4) == 0) { *pl = findLabel (*pl); if (!*pl) return S4O_ABORT; } break; case 'p': if (strncmp ("pop", (*pl)->line, 3) == 0 || strncmp ("push", (*pl)->line, 4) == 0) return S4O_PUSHPOP; break; case 'r': if (strncmp ("reti", (*pl)->line, 4) == 0) return S4O_TERM; if (strncmp ("ret", (*pl)->line, 3) == 0) { /* pcall uses 'ret' */ if (isFunc (*pl)) { /* for comments see 'lcall' */ ret = termScanAtFunc (*pl, rIdx); if (ret != S4O_CONTINUE) return ret; break; } /* it's a normal function return */ if (!((*pl)->ic) || (IS_SYMOP (IC_LEFT ((*pl)->ic)) && IS_FUNC (OP_SYM_TYPE(IC_LEFT ((*pl)->ic))) && FUNC_CALLEESAVES (OP_SYM_TYPE(IC_LEFT ((*pl)->ic))))) return S4O_ABORT; else return S4O_TERM; } break; case 's': if (strncmp ("sjmp", (*pl)->line, 4) == 0) { *pl = findLabel (*pl); if (!*pl) return S4O_ABORT; } break; default: break; } /* switch ((*pl)->line[0]) */ if (isConditionalJump) { *plCond = findLabel (*pl); if (!*plCond) return S4O_ABORT; return S4O_CONDJMP; } } /* for (; *pl; *pl = (*pl)->next) */ return S4O_ABORT; }
tid_t create_vtbl_struct(ea_t vtbl_addr, ea_t vtbl_addr_end, char* vtbl_name, uval_t idx, unsigned int* vtbl_len) { qstring struc_name = vtbl_name; //struc_name.append(qstring("_vtbl_struct")); tid_t id = add_struc(BADADDR, struc_name.c_str()); if (id == BADADDR) { struc_name.clear(); struc_name = askstr(HIST_IDENT, NULL, "Default name %s not correct. Enter other structure name: ", struc_name.c_str()); id = add_struc(BADADDR, struc_name.c_str()); set_struc_cmt(id, vtbl_name, true); } struc_t* new_struc = get_struc(id); if (!new_struc) return BADNODE; ea_t ea = vtbl_addr; ea_t offset = 0; while (ea < vtbl_addr_end) { offset = ea - vtbl_addr; qstring method_name; #ifndef __EA64__ ea_t method_ea = get_long(ea); // get function ea #else ea_t method_ea = get_64bit(ea); #endif if (method_ea == 0) break; if (!isEnabled(method_ea)) break; flags_t method_flags = getFlags(method_ea); char* struc_member_name = NULL; if (isFunc(method_flags)) { method_name = f_get_short_name(method_ea); // this line crash ida when compare qstring with null if (method_name.length() != 0) { struc_member_name = (char*)method_name.c_str(); } } #ifndef __EA64__ add_struc_member(new_struc, NULL, offset, dwrdflag(), NULL, 4); #else add_struc_member(new_struc, NULL, offset, qwrdflag(), NULL, sizeof(UINT64)); #endif if (struc_member_name) { if (!set_member_name(new_struc, offset, struc_member_name)) { //get_name(NULL, method_ea, method_name, sizeof(method_name)); f_get_ea_name(&method_name, method_ea); set_member_name(new_struc, offset, struc_member_name); } } #ifndef __EA64__ ea = ea + 4; #else ea = ea + sizeof(UINT64); #endif flags_t ea_flags = getFlags(ea); if (has_any_name(ea_flags)) break; } return id; }
// RAW_MATERIALS void raw_materials::getTokens(char *p, subexp *pSubExp, variable_scope &varScope ) { int iStartNum = -1, iEndNum = 0, iOperandsPos = 0, iOperationsPos = 0; char cSymbols[] = "*/+-", cDigits[] = "0123456789", cSpecialSymbols[] = ".$,"; parser parParser; string_func stringFunc; statment_type statmentType = Equation; for (int i = 0; p[i]; i++) { // Parse digits block if (isDigit(p[i])) { fOperands[iOperandsPos] = parParser.parseDigit(p,i,true); iCountDigits++; iOperandsPos++; } // Parse digit with unary minus else if(i == 0 && p[i] == '-') { i++; fOperands[iOperandsPos] = parParser.parseDigit(p,i,true,true); iCountDigits++; iOperandsPos++; } // Parse sub expression else if (p[i] == '$') { fOperands[iOperandsPos] = pSubExp[parParser.parseSubExp(p, i, pSubExp, varScope, true)].result; iCountDigits++; iOperandsPos++; } // Parse symbols block else if (isInArray(p[i], cSymbols)) { // Validate that no dublicated symbols if (i > 0 && isInArray(p[i - 1], cSymbols)) throw SymbolDuplication; opOperations[iOperationsPos].symbol = p[i]; opOperations[iOperationsPos].left_op = iOperationsPos; opOperations[iOperationsPos].right_op = iOperationsPos + 1; iOperationsPos++; iCountSymbols++; } // Parse build in function else if (isChar(p[i]) && isFunc(p,i)) { fOperands[iOperandsPos] = pSubExp[parParser.parseBuildInFunc(p, i, pSubExp, varScope, true)].result; iCountDigits++; iOperandsPos++; } // Parse variable else if (isChar(p[i])) { // !Here we become aware, whether it variable set or variable use int iCurVarIndex = parParser.parseVariable(p, i, varScope); if (iOperandsPos == 0 && p[i] && p[i] == '=' && stringFunc.isSameStr(p, pSubExp[0].exp)) { i++; statmentType = Setter; varScope.vScope[iCurVarIndex].setValue(pSubExp[parParser.parseSubExp(p, i, pSubExp, varScope, true)].result); } else if (varScope.vScope[iCurVarIndex].isInit()) { // As after parse our "i" is higher than it previous was on 1. i--; fOperands[iOperandsPos] = varScope.vScope[iCurVarIndex].getValue(); iCountDigits++; iOperandsPos++; } else { throw VariableInitError; } } else { throw SyntaxError; } } if (iCountDigits - iCountSymbols != 1 && statmentType == Equation) throw SyntaxError; }