// Tries to find a static array within structVar whose address is within // range of targetAddr. The struct's base addr is structVarBaseAddr. // The return value is the static array variable. // Remember to recurse on non-pointer struct variables within structVar // and repeat this same process because they themselves might contain // static arrays // *baseAddr = base address of the array variable // Pre: VAR_IS_BASE_STRUCT(structVar) static VariableEntry* searchForArrayWithinStruct(VariableEntry* structVar, Addr structVarBaseAddr, Addr targetAddr, Addr* baseAddr) { VarNode* v = 0; tl_assert(structVar->varType->aggType); FJALAR_DPRINTF("searchForArrayWithinStruct: %s, structVarBaseAddr: %p, targetAddr: %p, baseAddr: %p\n", structVar->name, (void*)structVarBaseAddr, (void*)targetAddr, (void*)baseAddr); // FJALAR_DPRINTF("aggType: %p, memberVarList: %p\n", // structVar->varType->aggType, // (structVar->varType->aggType ? structVar->varType->aggType->memberVarList : 0)); if (structVar->varType->aggType->memberVarList) { for (v = structVar->varType->aggType->memberVarList->first; v != 0; v = v->next) { VariableEntry* potentialVar; Addr potentialVarBaseAddr; potentialVar = v->var; tl_assert(IS_MEMBER_VAR(potentialVar)); FJALAR_DPRINTF("examining: %s, offset: %ld\n", potentialVar->name, potentialVar->memberVar->data_member_location); // FJALAR_DPRINTF("staticArr: %p, ptrLevels: %d, varType: %d\n", // potentialVar->staticArr, potentialVar->ptrLevels, // (potentialVar->varType ? potentialVar->varType->decType : 0)); potentialVarBaseAddr = structVarBaseAddr + potentialVar->memberVar->data_member_location; if (IS_STATIC_ARRAY_VAR(potentialVar) && (potentialVarBaseAddr <= targetAddr) && (targetAddr < (potentialVarBaseAddr + (potentialVar->staticArr->upperBounds[0] * getBytesBetweenElts(potentialVar))))) { *baseAddr = potentialVarBaseAddr; FJALAR_DPRINTF("Wins: %s\n", potentialVar->name); return potentialVar; } // Recursive step (be careful to avoid infinite recursion) else if VAR_IS_BASE_STRUCT(potentialVar) { VariableEntry* targetVar = searchForArrayWithinStruct(potentialVar, potentialVarBaseAddr, targetAddr, baseAddr); if (targetVar) { FJALAR_DPRINTF("wins: %s\n", potentialVar->name); return targetVar; } } } } *baseAddr = 0; return 0; }
// Prints a .disambig file entry for a given variable // This consists of 2 lines: // variable name, disambig type // e.g., // /foo <-- variable name // S <-- disambig type static TraversalResult printDisambigAction(VariableEntry* var, char* varName, VariableOrigin varOrigin, UInt numDereferences, UInt layersBeforeBase, Bool overrideIsInit, DisambigOverride disambigOverride, Bool isSequence, Addr pValue, Addr pValueGuest, Addr* pValueArray, Addr* pValueArrayGuest, UInt numElts, FunctionEntry* varFuncInfo, Bool isEnter) { /* silence unused variable warnings */ (void)varOrigin; (void)numDereferences; (void)layersBeforeBase; (void)overrideIsInit; (void)disambigOverride; (void)isSequence; (void)pValue; (void)pValueArray; (void)numElts; (void)varFuncInfo; (void)isEnter; (void)pValueGuest; (void)pValueArrayGuest; // If this is not a variable that's worthy of being outputted to the // .disambig file, then punt: if (!shouldOutputVarToDisambig(var)) { // We do not want to traverse any further than the surface level // for .disambig: return STOP_TRAVERSAL; } // Line 1: Variable name fputs(varName, disambig_fp); fputs("\n", disambig_fp); // Line 2: Disambig type /* Default values: Base type "char" and "unsigned char": 'I' for integer Pointer to "char": 'S' for string Pointer to all other types: - 'A' for array if var->disambigMultipleElts, which means that we've observed array behavior during program's execution or if !var->pointerHasEverBeenObserved, which means that the pointer has never been observed so a conservative guess of 'A' should be the default or if var->isStructUnionMember - don't try to be smart about member variables within structs/unions - just default to "A" - 'P' for pointer if (var->pointerHasEverBeenObserved && !var->disambigMultipleElts) */ if (0 == var->ptrLevels) { if ((D_CHAR == var->varType->decType) || (D_UNSIGNED_CHAR == var->varType->decType)) { fputs("I", disambig_fp); } } // Special case for C++ 'this' parameter - always make it 'P' else if (VG_STREQ(var->name, "this")) { fputs("P", disambig_fp); } // Normal string, not pointer to string else if (IS_STRING(var) && (1 == var->ptrLevels)) { fputs("S", disambig_fp); } else if (var->ptrLevels > 0) { if (IS_MEMBER_VAR(var)) { fputs("A", disambig_fp); } else { if (var->pointerHasEverBeenObserved) { if (var->disambigMultipleElts) { fputs("A", disambig_fp); } else { fputs("P", disambig_fp); } } // default behavior for variable that was // never observed during the execution else { fputs("A", disambig_fp); } } } fputs("\n", disambig_fp); // We do not want to traverse any further than the surface level for // .disambig: return STOP_TRAVERSAL; }