Esempio n. 1
0
// 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;
}