void processCommand(std::vector< std::string > &args) { /* printf("PROCESS: "); for(int i = 0; i < args.size(); i ++) { printf("[%s] ", args[i].c_str()); } printf("\n");*/ if(args.empty()) { *mAction = BNBActions::ERASE; } else if(args[0] == "forward") { *mAction = BNBActions::FORWARD | BNBActions::ERASE; eraseCommand(); } else if(args[0] == "drop") { *mAction = BNBActions::DROP | BNBActions::ERASE; eraseCommand(); } else if(args[0] == "var") { BNB_ASSERT(args.size() == 2); processVar(args[1]); } else if(args[0] == "set") { BNB_ASSERT(args.size() == 3); processAssign(args[1], args[2]); } else if(args[0] == "inc") { BNB_ASSERT(args.size() == 3); processInc(args[1], args[2]); } else if(args[0] == "cat") { BNB_ASSERT(args.size() == 3); processCat(args[1], args[2]); } else if(args[0] == "wait") { BNB_ASSERT(args.size() == 4); processWait(args[1], args[2], args[3]); } else if(args[0] == "echo") { processEcho(args); } else if(args[0] == "erase") { *mAction = BNBActions::ERASE; eraseCommand(); } else if(args[0] == "save") { processSave(args[1], args[2]); } else if(args[0] == "append") { processAppend(args[1], args[2]); } else if(args[0] == "load") { processLoad(args[1], args[2]); } else if(args[0] == "mkdir") { processMkdir(args[1]); } else if(args[0] == "skip") { eraseCommand(); } else if(args[0] == "exec") { processExec(args[1]); } else if(args[0] == "exit") { *mAction = BNBActions::EXIT; eraseCommand(); } else { printf("%s\n", args[0].c_str()); BNB_ERROR_REPORT("Unrecognized command"); } }
bool PointerAnalysis::processNode(PSNode *node) { bool changed = false; std::vector<MemoryObject *> objects; #ifdef DEBUG_ENABLED size_t prev_size = node->pointsTo.size(); #endif switch(node->type) { case LOAD: changed |= processLoad(node); break; case STORE: for (const Pointer& ptr : node->getOperand(1)->pointsTo) { PSNode *target = ptr.target; assert(target && "Got nullptr as target"); if (ptr.isNull()) continue; objects.clear(); getMemoryObjects(node, ptr, objects); for (MemoryObject *o : objects) { for (const Pointer& to : node->getOperand(0)->pointsTo) changed |= o->addPointsTo(ptr.offset, to); } } break; case GEP: for (const Pointer& ptr : node->getOperand(0)->pointsTo) { uint64_t new_offset; if (ptr.offset.isUnknown() || node->offset.isUnknown()) // set it like this to avoid overflow when adding new_offset = UNKNOWN_OFFSET; else new_offset = *ptr.offset + *node->offset; // in the case the memory has size 0, then every pointer // will have unknown offset with the exception that it points // to the begining of the memory - therefore make 0 exception if ((new_offset == 0 || new_offset < ptr.target->getSize()) && new_offset < max_offset) changed |= node->addPointsTo(ptr.target, new_offset); else changed |= node->addPointsToUnknownOffset(ptr.target); } break; case CAST: // cast only copies the pointers for (const Pointer& ptr : node->getOperand(0)->pointsTo) changed |= node->addPointsTo(ptr); break; case CONSTANT: // maybe warn? It has no sense to insert the constants into the graph. // On the other hand it is harmless. We can at least check if it is // correctly initialized 8-) assert(node->pointsTo.size() == 1 && "Constant should have exactly one pointer"); break; case CALL_RETURN: case RETURN: // gather pointers returned from subprocedure - the same way // as PHI works case PHI: for (PSNode *op : node->operands) changed |= node->addPointsTo(op->pointsTo); break; case CALL_FUNCPTR: // call via function pointer: // first gather the pointers that can be used to the // call and if something changes, let backend take some action // (for example build relevant subgraph) for (const Pointer& ptr : node->getOperand(0)->pointsTo) { if (node->addPointsTo(ptr)) { changed = true; if (ptr.isValid()) { functionPointerCall(node, ptr.target); } else { error(node, "Calling invalid pointer as a function!"); continue; } } } break; case MEMCPY: changed |= processMemcpy(node); break; case ALLOC: case DYN_ALLOC: case FUNCTION: // these two always points to itself assert(node->doesPointsTo(node, 0)); assert(node->pointsTo.size() == 1); case CALL: case ENTRY: case NOOP: // just no op break; default: assert(0 && "Unknown type"); } #ifdef DEBUG_ENABLED // the change of points-to set is not the only // change that can happen, so we don't use it as an // indicator and we use the 'changed' variable instead. // However, this assertion must hold: assert((node->pointsTo.size() == prev_size || changed) && "BUG: Did not set change but changed points-to sets"); #endif return changed; }