QStringList MemoryMap::loadedKernelModules() { QStringList ret; const MemoryDump* mem = _symbols->memDumps().at(_vmem->memDumpIndex()); Instance modules = mem->queryInstance("modules", ksNone); const Structured* module_t = dynamic_cast<const Structured*>( factory()->findBaseTypeByName("module")); if (modules.isValid() && module_t) { // First module in the list Instance m = modules.member("next", BaseType::trAny, 1, ksNone); qint64 offset = -module_t->memberOffset("list"); // Go through linked list and add all module names while (m.isValid() && m.address() != modules.address()) { m.setType(module_t); m.addToAddress(offset); QString name = m.member("name").toString(); if (!name.isEmpty()) { // Get rid of quotes if (name.startsWith('"')) name = name.mid(1, name.size() - 2); // Module binaries use dashes, the names use underscores name.replace('_', "-"); ret += name + ".ko"; } m = m.member("list").member("next", BaseType::trAny, 1, ksNone); } } return ret; }
QVector<quint64> MemoryMap::perCpuOffsets() { // Get all the data that we need to handle per_cpu variables. quint32 nr_cpus = 1; // Get the number of cpus from the dump if possible Variable *var = factory()->findVarByName("nr_cpu_ids"); if (var != 0) nr_cpus = var->value<quint32>(_vmem); // Get the per_cpu offsets QVector<quint64> per_cpu_offset(nr_cpus, 0); // Get the variable var = factory()->findVarByName("__per_cpu_offset"); Instance inst = var ? var->toInstance(_vmem, BaseType::trLexical, ksNone) : Instance(); // Fill the array for (quint32 i = 0; i < nr_cpus; ++i) { if (!inst.isNull()) { per_cpu_offset[i] = inst.toULong(); // Go to next array field inst.addToAddress(_vmem->memSpecs().sizeofLong); } else per_cpu_offset[i] = -1ULL; } return per_cpu_offset; }
void MemoryMap::addVariableWithCandidates(const Variable *var) { // Check manually: Is this a per_cpu variable? if (var->name().startsWith("per_cpu__")) { // Dereference the variable for each cpu for (int i = 0; i < _perCpuOffset.size(); i++) { Instance inst = var->toInstance(_vmem, BaseType::trLexical, ksNone); // Add offset if (!inst.isNull() && _perCpuOffset[i] != -1ULL) inst.addToAddress(_perCpuOffset[i]); addVarInstance(inst); } } else { addVarInstance(var->toInstance(_vmem, BaseType::trLexical, _knowSrc)); } }
Instance MemoryDump::getNextInstance(const QString& component, const Instance& instance, KnowledgeSources src) const { Instance result; QString typeString, symbol, offsetString, candidate, arrayIndexString; bool okay; // quint32 compatibleCnt = 0; // A component should have the form (symbol(-offset)?)?symbol(<candidate>)?([index])? #define SYMBOL "[A-Za-z0-9_]+" #define NUMBER "\\d+" QRegExp re( "^\\s*(?:" "\\(\\s*" "(" SYMBOL ")" "(?:" "\\s*-\\s*(" SYMBOL ")" ")?" "\\s*\\)" ")?" "\\s*(" SYMBOL ")\\s*" "(?:<\\s*(" NUMBER ")\\s*>\\s*)?" "((?:\\[\\s*" NUMBER "\\s*\\]\\s*)*)\\s*"); if (!re.exactMatch(component)) { queryError(QString("Could not parse a part of the query string: %1") .arg(component)); } // Set variables according to the matching typeString = re.cap(1); offsetString = re.cap(2).trimmed(); symbol = re.cap(3); candidate = re.cap(4); arrayIndexString = re.cap(5).trimmed(); int candidateIndex = candidate.isEmpty() ? -1 : candidate.toInt(); // debugmsg(QString("1: %1, 2: %2, 3: %3, 4: %4, 5: %5") // .arg(re.cap(1)) // .arg(re.cap(2)) // .arg(re.cap(3)) // .arg(re.cap(4)) // .arg(re.cap(5))); // A candidate index of 0 means to ignore the alternative types if (candidateIndex == 0) src = static_cast<KnowledgeSources>(src|ksNoAltTypes); // If the given instance is Null, we interpret this as the first component // in the query string and will therefore try to resolve the variable. if (!instance.isValid()) { Variable* v = _factory->findVarByName(symbol); if (!v) queryError(QString("Variable does not exist: %1").arg(symbol)); if (candidateIndex > 0) { if (v->altRefTypeCount() < candidateIndex) queryError(QString("Variable \"%1\" does not have a candidate " "with index %2") .arg(symbol) .arg(candidateIndex)); result = v->altRefTypeInstance(_vmem, candidateIndex - 1); } else { result = v->toInstance(_vmem, BaseType::trLexical, src); } } else { // Dereference any pointers/arrays first result = instance.dereference(BaseType::trAnyNonNull); // Did we get a null instance? if (!(result.type()->type() & StructOrUnion) && (result.isNull() || !result.toPointer())) queryError(QString("Member \"%1\" is null") .arg(result.fullName())); // We have a instance therefore we resolve the member if (!(result.type()->type() & StructOrUnion)) queryError(QString("Member \"%1\" is not a struct or union") .arg(result.fullName())); if (!result.memberExists(symbol)) queryError(QString("Struct \"%1\" has no member named \"%2\"") .arg(result.typeName()) .arg(symbol)); // Do we have a candidate index? if (candidateIndex > 0) { if (result.memberCandidatesCount(symbol) < candidateIndex) queryError(QString("Member \"%1\" does not have a candidate " "with index %2") .arg(symbol) .arg(candidateIndex)); result = result.memberCandidate(symbol, candidateIndex - 1); } else { result = result.member(symbol, BaseType::trLexical, 0, src); } } if (!result.isValid()) return result; // Cast the instance if necessary if (!typeString.isEmpty()) { quint32 offset = 0; // Is a offset given? if (!offsetString.isEmpty()) { // Is the offset given as string or as int? offset = offsetString.toUInt(&okay, 10); if (!okay) { // String. BaseType* type = getType(typeString); if (!type || !(type->type() & StructOrUnion)) queryError(QString("The given type \"%1\" is not a struct " "or union and therefore has no offset") .arg(typeString)); Structured* structd = dynamic_cast<Structured *>(type); if (!structd->memberExists(offsetString)) { queryError(QString("Struct of type \"%1\" has no member " "named \"%2\"") .arg(typeString) .arg(offsetString)); } else { StructuredMember* structdMember = structd->member(offsetString); offset = structdMember->offset(); } } } // Get address size_t address; if (result.type()->type() & (rtPointer)) address = (size_t)result.toPointer() - offset; else address = result.address() - offset; result = getInstanceAt(typeString, address, result.fullNameComponents()); } // Add array index if (!arrayIndexString.isEmpty()) { QRegExp reArrayIndex("\\[\\s*(" NUMBER ")\\s*\\]\\s*"); QStringList matches; int strpos = 0; while (strpos < arrayIndexString.size() && (strpos = arrayIndexString.indexOf(reArrayIndex, strpos)) >= 0) { matches.append(reArrayIndex.cap(1)); strpos += reArrayIndex.cap(0).size(); } for (int i = 0; i < matches.count(); ++i) { quint32 arrayIndex = matches[i].toUInt(&okay, 10); if (okay) { // Is the result already an instance list? if (result.isList()) { InstanceList list(result.toList()); if (arrayIndex < (quint32)list.size()) result = list[arrayIndex]; else queryError(QString("Given array index %1 is out of bounds.") .arg(arrayIndex)); } else { // Is this a pointer or an array type? Instance tmp = result.arrayElem(arrayIndex); if (!tmp.isNull()) result = tmp.dereference(BaseType::trLexical); // Manually update the address else { result.addToAddress(arrayIndex * result.type()->size()); result.setName(QString("%1[%2]").arg(result.name()).arg(arrayIndex)); } } } else { queryError(QString("Given array index %1 could not be converted " "to a number.") .arg(matches[i])); } } } // Try to dereference this instance as deep as possible return result.dereference(BaseType::trLexicalAndPointers); }