/// Apply implicit constraints for bitwise OR- and AND-. /// For unsigned types, bitwise OR with a constant always returns /// a value greater-or-equal than the constant, and bitwise AND /// returns a value less-or-equal then the constant. /// /// Pattern matches the expression \p Sym against those rule, /// and applies the required constraints. /// \p Input Previously established expression range set static RangeSet applyBitwiseConstraints( BasicValueFactory &BV, RangeSet::Factory &F, RangeSet Input, const SymIntExpr* SIE) { QualType T = SIE->getType(); bool IsUnsigned = T->isUnsignedIntegerType(); const llvm::APSInt &RHS = SIE->getRHS(); const llvm::APSInt &Zero = BV.getAPSIntType(T).getZeroValue(); BinaryOperator::Opcode Operator = SIE->getOpcode(); // For unsigned types, the output of bitwise-or is bigger-or-equal than RHS. if (Operator == BO_Or && IsUnsigned) return Input.Intersect(BV, F, RHS, BV.getMaxValue(T)); // Bitwise-or with a non-zero constant is always non-zero. if (Operator == BO_Or && RHS != Zero) return assumeNonZero(BV, F, SIE, Input); // For unsigned types, or positive RHS, // bitwise-and output is always smaller-or-equal than RHS (assuming two's // complement representation of signed types). if (Operator == BO_And && (IsUnsigned || RHS >= Zero)) return Input.Intersect(BV, F, BV.getMinValue(T), RHS); return Input; }
void AnalysisDriver::printLeastProgressedTasks(const RangeSetTable &rsTable, const set<size_t> taskStates, const ReducedStateVector &redVector) { if (mpiState.isRoot()) { cout << "Number of states with LP-tasks: " << taskStates.size() << endl; set<size_t>::const_iterator it; for (it = taskStates.begin(); it != taskStates.end(); ++it) { State s = redVector.vec[*it]; RangeSet rs = rsTable.getRangeOfTasks(*it); cout << "STATE " << *it << ", tasks: " << rs.toString() << endl; } // Print state names string name; cout << "States: " << endl; cout << "-------" << endl; for (size_t i=0; i < redVector.vec.size(); ++i) { State s = redVector.vec[i]; factory->findAndGetName(name, s); cout << i << ": " << name << endl; } // Print location of tasks cout << "Task locations: " << endl; cout << "---------------" << endl; for (size_t i=0; i < redVector.vec.size(); ++i) { State s = redVector.vec[i]; RangeSet r = rsTable.getRangeOfTasks(i); cout << i << ": " << r.toString() << endl; } } }
ProgramStateRef RangeConstraintManager::assumeSymLE(ProgramStateRef St, SymbolRef Sym, const llvm::APSInt &Int, const llvm::APSInt &Adjustment) { RangeSet New = getSymLERange(St, Sym, Int, Adjustment); return New.isEmpty() ? nullptr : St->set<ConstraintRange>(Sym, New); }
ProgramStateRef RangeConstraintManager::assumeSymLE(ProgramStateRef St, SymbolRef Sym, const llvm::APSInt &Int, const llvm::APSInt &Adjustment) { // Before we do any real work, see if the value can even show up. APSIntType AdjustmentType(Adjustment); switch (AdjustmentType.testInRange(Int, true)) { case APSIntType::RTR_Below: return nullptr; case APSIntType::RTR_Within: break; case APSIntType::RTR_Above: return St; } // Special case for Int == Max. This is always feasible. llvm::APSInt ComparisonVal = AdjustmentType.convert(Int); llvm::APSInt Max = AdjustmentType.getMaxValue(); if (ComparisonVal == Max) return St; llvm::APSInt Min = AdjustmentType.getMinValue(); llvm::APSInt Lower = Min-Adjustment; llvm::APSInt Upper = ComparisonVal-Adjustment; RangeSet New = GetRange(St, Sym).Intersect(getBasicVals(), F, Lower, Upper); return New.isEmpty() ? nullptr : St->set<ConstraintRange>(Sym, New); }
/** * Create the masks for sources and targets based on the contiguous * ranges given in sources and targets. We need to do some index * translation here, as the CG expects indices from 0..n for both * source and target populations, while the RangeSets sources and * targets contain NEST global indices (gids). * * The masks for the sources must contain all nodes (local+remote). * The skip of the mask was set to 1 in cg_set_masks(). The same * source mask is stored n_proc times on each process. * * The masks for the targets must only contain local nodes. This is * achieved by first setting skip to num_processes upon creation of * the mask in cg_set_masks(), and second by the fact that for each * contiguous range of nodes in a mask, each of them contains the * index-translated id of the first local neuron as the first * entry. If this renders the range empty (i.e. because the first * local id is beyond the last element of the range), the range is * not added to the mask. * * \param masks The std::vector of Masks to populate * \param sources The source ranges to create the source masks from * \param targets The target ranges to create the target masks from * * \note Each process computes the full set of source and target * masks, i.e. one mask per rank will be created on each rank. * * \note Setting the masks for all processes on each process might * become a memory bottleneck when going to very large numbers of * processes. Especially so for the source masks, which are all the * same. This could be solved by making the ConnectionGenerator * interface MPI aware and communicating the masks during connection * setup. */ void cg_create_masks( std::vector< ConnectionGenerator::Mask >* masks, RangeSet& sources, RangeSet& targets ) { // The index of the left border of the currently looked at range // (counting from 0). This is used for index translation. size_t cg_idx_left = 0; // For sources, we only need to translate from NEST to CG indices. for ( RangeSet::iterator source = sources.begin(); source != sources.end(); ++source ) { size_t num_elements = source->last - source->first; size_t right = cg_idx_left + num_elements; for ( size_t proc = 0; proc < static_cast< size_t >( Communicator::get_num_processes() ); ++proc ) ( *masks )[ proc ].sources.insert( cg_idx_left, right ); cg_idx_left += num_elements + 1; } // Reset the index of the left border of the range for index // translation for the targets. cg_idx_left = 0; for ( RangeSet::iterator target = targets.begin(); target != targets.end(); ++target ) { size_t num_elements = target->last - target->first; for ( size_t proc = 0; proc < static_cast< size_t >( Communicator::get_num_processes() ); ++proc ) { // Make sure that the range is only added on as many ranks as // there are elements in the range, or exactly on every rank, // if there are more elements in the range. if ( proc <= num_elements ) { // For the different ranks, left will take on the CG indices // of all first local nodes that are contained in the range. // The rank, where this mask is to be used is determined // below when inserting the mask. size_t left = cg_idx_left + proc; // right is set to the CG index of the right border of the // range. This is the same for all ranks. size_t right = cg_idx_left + num_elements; // We index the masks according to the modulo distribution // of neurons in NEST. This ensures that the mask is set for // the rank where left acutally is the first neuron fromt // the currently looked at range. ( *masks )[ ( proc + target->first ) % Communicator::get_num_processes() ].targets.insert( left, right ); } } // Update the CG index of the left border of the next range to // be one after the current range. cg_idx_left += num_elements + 1; } }
ProgramStateRef RangeConstraintManager::assumeSymOutsideInclusiveRange( ProgramStateRef State, SymbolRef Sym, const llvm::APSInt &From, const llvm::APSInt &To, const llvm::APSInt &Adjustment) { RangeSet RangeLT = getSymLTRange(State, Sym, From, Adjustment); RangeSet RangeGT = getSymGTRange(State, Sym, To, Adjustment); RangeSet New(RangeLT.addRange(F, RangeGT)); return New.isEmpty() ? nullptr : State->set<ConstraintRange>(Sym, New); }
ProgramStateRef RangeConstraintManager::assumeSymWithinInclusiveRange( ProgramStateRef State, SymbolRef Sym, const llvm::APSInt &From, const llvm::APSInt &To, const llvm::APSInt &Adjustment) { RangeSet New = getSymGERange(State, Sym, From, Adjustment); if (New.isEmpty()) return nullptr; RangeSet Out = getSymLERange([&] { return New; }, To, Adjustment); return Out.isEmpty() ? nullptr : State->set<ConstraintRange>(Sym, Out); }
const ProgramState* RangeConstraintManager::assumeSymEQ(const ProgramState *state, SymbolRef sym, const llvm::APSInt& Int, const llvm::APSInt& Adjustment) { // [Int-Adjustment, Int-Adjustment] BasicValueFactory &BV = state->getBasicVals(); llvm::APSInt AdjInt = Int-Adjustment; RangeSet New = GetRange(state, sym).Intersect(BV, F, AdjInt, AdjInt); return New.isEmpty() ? NULL : state->set<ConstraintRange>(sym, New); }
ProgramStateRef RangeConstraintManager::assumeSymEQ(ProgramStateRef St, SymbolRef Sym, const llvm::APSInt &Int, const llvm::APSInt &Adjustment) { // Before we do any real work, see if the value can even show up. APSIntType AdjustmentType(Adjustment); if (AdjustmentType.testInRange(Int, true) != APSIntType::RTR_Within) return nullptr; // [Int-Adjustment, Int-Adjustment] llvm::APSInt AdjInt = AdjustmentType.convert(Int) - Adjustment; RangeSet New = getRange(St, Sym).Intersect(getBasicVals(), F, AdjInt, AdjInt); return New.isEmpty() ? nullptr : St->set<ConstraintRange>(Sym, New); }
RangeSet createPredefinedSet () { RangeSet set; // Set will include: // [ 0, 5] // [10,15] // [20,25] // etc... for (int i = 0; i < 10; ++i) set.setRange (10 * i, 10 * i + 5); return set; }
const ProgramState* RangeConstraintManager::assumeSymNE(const ProgramState *state, SymbolRef sym, const llvm::APSInt& Int, const llvm::APSInt& Adjustment) { BasicValueFactory &BV = state->getBasicVals(); llvm::APSInt Lower = Int-Adjustment; llvm::APSInt Upper = Lower; --Lower; ++Upper; // [Int-Adjustment+1, Int-Adjustment-1] // Notice that the lower bound is greater than the upper bound. RangeSet New = GetRange(state, sym).Intersect(BV, F, Upper, Lower); return New.isEmpty() ? NULL : state->set<ConstraintRange>(sym, New); }
void testPrevMissing () { testcase ("prevMissing"); RangeSet const set = createPredefinedSet (); for (int i = 0; i < 100; ++i) { int const oneBelowRange = (10*(i/10))-1; int const expectedPrevMissing = ((i % 10) > 6) ? (i-1) : oneBelowRange; expect (set.prevMissing (i) == expectedPrevMissing); } }
NodePtr parsePrimitive() { NodePtr p = nullptr; RangeSet st; // lookahead switch (reader.peek()) { case '\\': reader.next(); switch (reader.peek()) { case 'd': st.insert({ '0', '9' }); reader.next(); return std::make_shared<CharsetNode>(st); break; case '{': case '}': case '|': case '(': case ')': case '.': case '+': case '*': case '?': case '\\': case 'n': case 't': return std::make_shared<CharNode>(reader.next()); break; default: throw ParseError(); } reader.next(); break; case '(': reader.next(); p = parseRE(); if (reader.peek() != ')') { throw ParseError(); } reader.next(); return p; case '\0': case '*': case '|': throw ParseError(); break; case '.': reader.next(); return std::make_shared<WildcardNode>(); break; default: return std::make_shared<CharNode>(reader.next()); } }
/// Return a range set subtracting zero from \p Domain. static RangeSet assumeNonZero( BasicValueFactory &BV, RangeSet::Factory &F, SymbolRef Sym, RangeSet Domain) { APSIntType IntType = BV.getAPSIntType(Sym->getType()); return Domain.Intersect(BV, F, ++IntType.getZeroValue(), --IntType.getZeroValue()); }
ProgramStateRef RangeConstraintManager::assumeSymNE(ProgramStateRef St, SymbolRef Sym, const llvm::APSInt &Int, const llvm::APSInt &Adjustment) { // Before we do any real work, see if the value can even show up. APSIntType AdjustmentType(Adjustment); if (AdjustmentType.testInRange(Int, true) != APSIntType::RTR_Within) return St; llvm::APSInt Lower = AdjustmentType.convert(Int) - Adjustment; llvm::APSInt Upper = Lower; --Lower; ++Upper; // [Int-Adjustment+1, Int-Adjustment-1] // Notice that the lower bound is greater than the upper bound. RangeSet New = getRange(St, Sym).Intersect(getBasicVals(), F, Upper, Lower); return New.isEmpty() ? nullptr : St->set<ConstraintRange>(Sym, New); }
const ProgramState* RangeConstraintManager::assumeSymGT(const ProgramState *state, SymbolRef sym, const llvm::APSInt& Int, const llvm::APSInt& Adjustment) { BasicValueFactory &BV = state->getBasicVals(); QualType T = state->getSymbolManager().getType(sym); const llvm::APSInt &Max = BV.getMaxValue(T); // Special case for Int == Max. This is always false. if (Int == Max) return NULL; llvm::APSInt Lower = Int-Adjustment; llvm::APSInt Upper = Max-Adjustment; ++Lower; RangeSet New = GetRange(state, sym).Intersect(BV, F, Lower, Upper); return New.isEmpty() ? NULL : state->set<ConstraintRange>(sym, New); }
bool VisitDecl(clang::Decl *decl) { if (markedAsSuppress(decl, _rule)) { clang::SourceLocation startLocation = decl->getLocStart(); clang::SourceLocation endLocation = decl->getLocEnd(); unsigned startLineNumber = _sourceManager->getPresumedLineNumber(startLocation); unsigned endLineNumber = _sourceManager->getPresumedLineNumber(endLocation); _range.insert(std::make_pair(startLineNumber, endLineNumber)); } return true; }
void cg_get_ranges(RangeSet& ranges, std::vector<long>& gids) { index right = 0, left = 0; while(true) { right = cg_get_right_border(left, (gids.size() - left) / 2, gids); ranges.push_back(Range(gids[left], gids[right])); if (right == gids.size() - 1) break; else left = right + 1; } }
/** * Splits the selected segments by inserting new nodes in the middle. The * selected segments are defined by each pair of consecutive \a indexRanges. * * This method can deal with both polygons as well as polylines. For polygons, * pass <code>true</code> for \a closed. */ static QPolygonF splitPolygonSegments(const QPolygonF &polygon, const RangeSet<int> &indexRanges, bool closed) { if (indexRanges.isEmpty()) return polygon; const int n = polygon.size(); QPolygonF result = polygon; RangeSet<int>::Range firstRange = indexRanges.begin(); RangeSet<int>::Range it = indexRanges.end(); // assert: firstRange != it if (closed) { RangeSet<int>::Range lastRange = it; --lastRange; // We know there is at least one range // Handle the case where the first and last nodes are selected if (firstRange.first() == 0 && lastRange.last() == n - 1) { const QPointF splitPoint = (result.first() + result.last()) / 2; result.append(splitPoint); } } do { --it; for (int i = it.last(); i > it.first(); --i) { const QPointF splitPoint = (result.at(i) + result.at(i - 1)) / 2; result.insert(i, splitPoint); } } while (it != firstRange); return result; }
void cg_create_masks(std::vector<ConnectionGenerator::Mask>* masks, RangeSet& sources, RangeSet& targets) { // We need to do some index translation here as the CG expects // indices from 0..n for both source and target populations. size_t length = 0; for (RangeSet::iterator source = sources.begin(); source != sources.end(); ++source) { for (size_t proc = 0; proc < static_cast<size_t>(Communicator::get_num_processes()); ++proc) { size_t last = source->last - source->first; if (proc <= last) { size_t left = proc + length; size_t right = last + length; (*masks)[(proc + source->first) % Communicator::get_num_processes()].sources.insert(left, right); } } length += source->last - source->first + 1; } length = 0; for (RangeSet::iterator target = targets.begin(); target != targets.end(); ++target) { for (size_t proc = 0; proc < static_cast<size_t>(Communicator::get_num_processes()); ++proc) { size_t last = target->last - target->first; if (proc <= last) { size_t left = proc + length; size_t right = last + length; (*masks)[(proc + target->first) % Communicator::get_num_processes()].targets.insert(left, right); } } length += target->last - target->first + 1; } }
/** * Determine all contiguous ranges found in a given vector of gids * and add the ranges to the given RangeSet. * * \param ranges A reference to the RangeSet to add to * \param gids The std::vector<long> of gids * * \note We do not store the indices into the given range, but * instead we store the actual gids. This allows us to use CG * generated indices as indices into the ranges spanned by the * RangeSet. Index translation is done in cg_create_masks(). */ void cg_get_ranges( RangeSet& ranges, std::vector< long >& gids ) { index right, left = 0; while ( true ) { // Determine the right border of the contiguous range starting // at left. The initial step is set to half the length of the // interval between left and the end of gids. right = cg_get_right_border( left, ( gids.size() - left ) / 2, gids ); ranges.push_back( Range( gids[ left ], gids[ right ] ) ); if ( right == gids.size() - 1 ) // We're at the end of gids and stop break; else left = right + 1; // The new left border is one after the old right } }
RangeSet collect(clang::ASTContext &astContext, oclint::RuleBase *rule) { _rule = rule; _sourceManager = &astContext.getSourceManager(); _range.clear(); clang::DeclContext *decl = astContext.getTranslationUnitDecl(); for (clang::DeclContext::decl_iterator declIt = decl->decls_begin(), declEnd = decl->decls_end(); declIt != declEnd; ++declIt) { clang::SourceLocation startLocation = (*declIt)->getLocStart(); if (startLocation.isValid() && _sourceManager->getMainFileID() == _sourceManager->getFileID(startLocation)) { (void) /* explicitly ignore the return of this function */ clang::RecursiveASTVisitor<DeclAnnotationRangeCollector>::TraverseDecl(*declIt); } } return _range; }
void GraphBuilder::update_node_constraints(IRList::iterator it, const RangeSet& range_set, Graph* graph) { auto insn = it->insn; auto op = insn->opcode(); if (insn->dests_size()) { auto dest = insn->dest(); auto& node = graph->m_nodes[dest]; if (opcode::is_load_param(op)) { node.m_props.set(Node::PARAM); } node.m_type_domain.meet_with(RegisterTypeDomain(dest_reg_type(insn))); auto max_vreg = max_unsigned_value(dest_bit_width(it)); node.m_max_vreg = std::min(node.m_max_vreg, max_vreg); node.m_width = insn->dest_is_wide() ? 2 : 1; if (max_vreg < max_unsigned_value(16)) { ++node.m_spill_cost; } } for (size_t i = 0; i < insn->srcs_size(); ++i) { auto src = insn->src(i); auto& node = graph->m_nodes[src]; auto type = src_reg_type(insn, i); node.m_type_domain.meet_with(RegisterTypeDomain(type)); reg_t max_vreg; if (range_set.contains(insn)) { max_vreg = max_unsigned_value(16); node.m_props.set(Node::RANGE); } else { max_vreg = max_value_for_src(insn, i, type == RegisterType::WIDE); } node.m_max_vreg = std::min(node.m_max_vreg, max_vreg); if (max_vreg < max_unsigned_value(16)) { ++node.m_spill_cost; } } }
void append(int n) { m_list.append(n,n+1); }
SelRangesNode(int n) { m_list.append(n,n+1); }
void append(int nstart, int nend) { if (nstart<=nend) m_list.append(nstart, nend+1); else m_list.append(nend, nstart+1); }
/** * Joins the nodes at the given \a indexRanges. Each consecutive sequence * of nodes will be joined into a single node at the average location. * * This method can deal with both polygons as well as polylines. For polygons, * pass <code>true</code> for \a closed. */ static QPolygonF joinPolygonNodes(const QPolygonF &polygon, const RangeSet<int> &indexRanges, bool closed) { if (indexRanges.isEmpty()) return polygon; // Do nothing when dealing with a polygon with less than 3 points // (we'd no longer have a polygon) const int n = polygon.size(); if (n < 3) return polygon; RangeSet<int>::Range firstRange = indexRanges.begin(); RangeSet<int>::Range it = indexRanges.end(); RangeSet<int>::Range lastRange = it; --lastRange; // We know there is at least one range QPolygonF result = polygon; // Indexes need to be offset when first and last range are joined. int indexOffset = 0; // Check whether the first and last ranges connect if (firstRange.first() == 0 && lastRange.last() == n - 1) { // Do nothing when the selection spans the whole polygon if (firstRange == lastRange) return polygon; // Join points of the first and last range when the polygon is closed if (closed) { QPointF averagePoint; for (int i = firstRange.first(); i <= firstRange.last(); i++) averagePoint += polygon.at(i); for (int i = lastRange.first(); i <= lastRange.last(); i++) averagePoint += polygon.at(i); averagePoint /= firstRange.length() + lastRange.length(); result.remove(lastRange.first(), lastRange.length()); result.remove(1, firstRange.length() - 1); result.replace(0, averagePoint); indexOffset = firstRange.length() - 1; // We have dealt with these ranges now // assert: firstRange != lastRange ++firstRange; --it; } } while (it != firstRange) { --it; // Merge the consecutive nodes into a single average point QPointF averagePoint; for (int i = it.first(); i <= it.last(); i++) averagePoint += polygon.at(i - indexOffset); averagePoint /= it.length(); result.remove(it.first() + 1 - indexOffset, it.length() - 1); result.replace(it.first() - indexOffset, averagePoint); } return result; }
void AnalysisDriver::dumpOutputForGUI(const DependencyMatrix &matrix, const ReducedStateVector &redVector, const RangeSetTable &rsTable) { bool doNotDump = false; bool r = false; r = AUTConfig::getBoolParameter("AUT_DO_NOT_DUMP", doNotDump); if(doNotDump) { // to resolve problem in BGQ - in BGQ we can not execute shell command to resolve functionname and address return; } bool usedcallpath = AUTConfig::getBoolParameter("AUT_USE_CALL_PATH", usedcallpath); if(usedcallpath) { cout<< "Stack created using callpath, support for filename and line number will be provided later" << endl; return; } #if STATE_TRACKER_DEBUG cout << "Writing dump file..." << endl; #endif string fileData(""); fileData += "#START_DEPENDENCY_GRAPH\n"; fileData += matrix.toCSVFormat(); fileData += "#END_DEPENDENCY_GRAPH\n"; fileData += "#START_STATES\n"; string name; for (size_t i=0; i < redVector.vec.size(); ++i) { State s = redVector.vec[i]; factory->findAndGetName(name, s); // eliminate first '|' name.erase(0,1); // get state id char stateId[5]; itoa((int)i, stateId); fileData += string(stateId) + string(":") + name + string("\n"); } fileData += "#END_STATES\n"; fileData += "#START_TASK_LOC\n"; for (size_t i=0; i < redVector.vec.size(); ++i) { State s = redVector.vec[i]; RangeSet r = rsTable.getRangeOfTasks(i); //cout << "Original state was: " << s.getId() << "\n"; // get state id char stateId[5]; itoa((int)i, stateId); // get range set string rSet(r.toString()); rSet.erase(0,1); rSet.erase(rSet.length()-1, 1); // get number of tasks unsigned int n = r.getNumberOfTasks(); char tasks[128]; sprintf(tasks, "%d", n); fileData += string(stateId) + string(":") + rSet + string(":") + string(tasks) + string("\n"); } fileData += "#END_TASK_LOC\n"; fileData += "#START_SOURCE_CODE_LINES\n"; name = ""; for (size_t i=0; i < redVector.vec.size(); ++i) { State s = redVector.vec[i]; factory->findAndGetName(name, s); // eliminate first '|' name.erase(0,1); vector<string> tokens; Tokenize(name, tokens, "|"); string setOfLines(""); for (size_t j=0; j < tokens.size(); ++j) { //cout << tokens[j] << endl; FileAndFunction f = Backtrace::findFileAndFunctionFromObject(tokens[j]); if(f.fileNameAndLine.empty()) { continue; } string line = f.fileNameAndLine.substr(0, f.fileNameAndLine.size()-1); setOfLines += line + "|" + f.functionName; if (f.fromTool) setOfLines += "|*\n"; else setOfLines += "\n"; } // get state id char stateId[5]; itoa((int)i, stateId); fileData += string(stateId) + string(",") + setOfLines; } fileData += "#END_SOURCE_CODE_LINES\n"; fileData += "#START_STATE_TYPES\n"; name = ""; for (size_t i=0; i < redVector.vec.size(); ++i) { State s = redVector.vec[i]; factory->findAndGetName(name, s); name.erase(0,1); vector<string> tokens; Tokenize(name, tokens, "|"); bool compState = false; for (size_t j=0; j < tokens.size(); ++j) { FileAndFunction f = Backtrace::findFileAndFunctionFromObject(tokens[j]); if(f.functionName.empty()) { continue; } if (f.functionName.find("transitionAfterMPICall") != string::npos) { compState = true; break; } } char stateId[5]; itoa((int)i, stateId); fileData += string(stateId) + string(":"); if (compState) fileData += "COMPUTATION_CODE\n"; else fileData += "COMMUNICATION_CODE\n"; } fileData += "#END_STATE_TYPES\n"; string fileName = writeFile(fileData, "dump"); cout << "Name of the output file: " << fileName << endl; //printf("Pointer of _r_debug.r_map: %p\n",_r_debug.r_map); //struct link_map *map = _r_debug.r_map; //while(map) //{ // printf("Name: '%s' l_addr: %lx l_ld: %lx\n", map->l_name, map->l_addr, map->l_ld); // map = map->l_next; //} }
SelRangesNode(int n1, int n2) { m_list.append(n1,n2+1); }