From b44790219f43369883b3dd8eaf3971bdc5fe656b Mon Sep 17 00:00:00 2001 From: Yifan Hong Date: Thu, 2 Mar 2017 16:54:11 -0800 Subject: lshal: also list libraries in 32-bit. Add an "Arch" column (selected by -r) to lshal to show whether the HAL runs in 32 bit or 64 bit. * For binderized services, whether the process runs in 32bit or 64bit (__LP64__) * For passthrough libraries (-impl.so), whether the library is in /{system,vendor,odm}/lib/hw or /{system,vendor,odm}lib64/hw Bug: 35803184 Test: lshal -itrpc Change-Id: I328da4ad9eacbf2959be4ac2e478c16535a89068 --- cmds/lshal/Lshal.cpp | 70 ++++++++++++++++++++++++++++++++++++++++++------- cmds/lshal/Lshal.h | 4 ++- cmds/lshal/TableEntry.h | 12 ++++++++- 3 files changed, 75 insertions(+), 11 deletions(-) diff --git a/cmds/lshal/Lshal.cpp b/cmds/lshal/Lshal.cpp index e953dedea2..2140471488 100644 --- a/cmds/lshal/Lshal.cpp +++ b/cmds/lshal/Lshal.cpp @@ -174,7 +174,9 @@ void Lshal::postprocess() { void Lshal::printLine( const std::string &interfaceName, - const std::string &transport, const std::string &server, + const std::string &transport, + const std::string &arch, + const std::string &server, const std::string &serverCmdline, const std::string &address, const std::string &clients, const std::string &clientCmdlines) const { @@ -182,6 +184,8 @@ void Lshal::printLine( mOut << std::setw(80) << interfaceName << "\t"; if (mSelectedColumns & ENABLE_TRANSPORT) mOut << std::setw(10) << transport << "\t"; + if (mSelectedColumns & ENABLE_ARCH) + mOut << std::setw(5) << arch << "\t"; if (mSelectedColumns & ENABLE_SERVER_PID) { if (mEnableCmdlines) { mOut << std::setw(15) << serverCmdline << "\t"; @@ -272,13 +276,44 @@ void Lshal::dumpVintf() const { mOut << vintf::gHalManifestConverter(manifest); } +static const std::string &getArchString(Architecture arch) { + static const std::string sStr64 = "64"; + static const std::string sStr32 = "32"; + static const std::string sStrBoth = "64&32"; + static const std::string sStrUnknown = ""; + switch (arch) { + case ARCH64: + return sStr64; + case ARCH32: + return sStr32; + case ARCH_BOTH: + return sStrBoth; + case ARCH_UNKNOWN: // fall through + default: + return sStrUnknown; + } +} + +static Architecture fromBaseArchitecture(::android::hidl::base::V1_0::DebugInfo::Architecture a) { + switch (a) { + case ::android::hidl::base::V1_0::DebugInfo::Architecture::IS_64BIT: + return ARCH64; + case ::android::hidl::base::V1_0::DebugInfo::Architecture::IS_32BIT: + return ARCH32; + case ::android::hidl::base::V1_0::DebugInfo::Architecture::UNKNOWN: // fallthrough + default: + return ARCH_UNKNOWN; + } +} + void Lshal::dumpTable() const { mOut << "All services:" << std::endl; mOut << std::left; - printLine("Interface", "Transport", "Server", "Server CMD", "PTR", "Clients", "Clients CMD"); + printLine("Interface", "Transport", "Arch", "Server", "Server CMD", "PTR", "Clients", "Clients CMD"); for (const auto &entry : mTable) { printLine(entry.interfaceName, entry.transport, + getArchString(entry.arch), entry.serverPid == NO_PID ? "N/A" : std::to_string(entry.serverPid), entry.serverCmdline, entry.serverObjectAddress == NO_PTR ? "N/A" : toHexString(entry.serverObjectAddress), @@ -309,16 +344,23 @@ Status Lshal::fetchAllLibraries(const sp &manager) { using namespace ::android::hardware; using namespace ::android::hidl::manager::V1_0; using namespace ::android::hidl::base::V1_0; - auto ret = timeoutIPC(manager, &IServiceManager::list, [&] (const auto &fqInstanceNames) { - for (const auto &fqInstanceName : fqInstanceNames) { - putEntry({ - .interfaceName = fqInstanceName, + auto ret = timeoutIPC(manager, &IServiceManager::debugDump, [&] (const auto &infos) { + std::map entries; + for (const auto &info : infos) { + std::string interfaceName = std::string{info.interfaceName.c_str()} + "/" + + std::string{info.instanceName.c_str()}; + entries.emplace(std::string{interfaceName}, TableEntry{ + .interfaceName = interfaceName, .transport = "passthrough", .serverPid = NO_PID, .serverObjectAddress = NO_PTR, .clientPids = {}, + .arch = ARCH_UNKNOWN, .source = LIST_DLLIB - }); + }).first->second.arch |= fromBaseArchitecture(info.arch); + } + for (auto &&pair : entries) { + putEntry(std::move(pair.second)); } }); if (!ret.isOk()) { @@ -331,6 +373,7 @@ Status Lshal::fetchAllLibraries(const sp &manager) { Status Lshal::fetchPassthrough(const sp &manager) { using namespace ::android::hardware; + using namespace ::android::hardware::details; using namespace ::android::hidl::manager::V1_0; using namespace ::android::hidl::base::V1_0; auto ret = timeoutIPC(manager, &IServiceManager::debugDump, [&] (const auto &infos) { @@ -343,6 +386,7 @@ Status Lshal::fetchPassthrough(const sp &manager) { .serverPid = info.clientPids.size() == 1 ? info.clientPids[0] : NO_PID, .serverObjectAddress = NO_PTR, .clientPids = info.clientPids, + .arch = fromBaseArchitecture(info.arch), .source = PTSERVICEMANAGER_REG_CLIENT }); } @@ -426,6 +470,7 @@ Status Lshal::fetchBinderized(const sp &manager) { .serverPid = NO_PID, .serverObjectAddress = NO_PTR, .clientPids = {}, + .arch = ARCH_UNKNOWN, .source = HWSERVICEMANAGER_LIST }); continue; @@ -438,6 +483,7 @@ Status Lshal::fetchBinderized(const sp &manager) { .serverObjectAddress = info.ptr, .clientPids = info.pid == NO_PID || info.ptr == NO_PTR ? Pids{} : allPids[info.pid][info.ptr], + .arch = fromBaseArchitecture(info.arch), .source = HWSERVICEMANAGER_LIST }); } @@ -470,12 +516,13 @@ void Lshal::usage() const { mErr << "usage: lshal" << std::endl << " Dump all hals with default ordering and columns [-itpc]." << std::endl - << " lshal [--interface|-i] [--transport|-t]" << std::endl + << " lshal [--interface|-i] [--transport|-t] [-r|--arch]" << std::endl << " [--pid|-p] [--address|-a] [--clients|-c] [--cmdline|-m]" << std::endl << " [--sort={interface|i|pid|p}] [--init-vintf[=path]]" << std::endl << " -i, --interface: print the interface name column" << std::endl << " -n, --instance: print the instance name column" << std::endl << " -t, --transport: print the transport mode column" << std::endl + << " -r, --arch: print if the HAL is in 64-bit or 32-bit" << std::endl << " -p, --pid: print the server PID, or server cmdline if -m is set" << std::endl << " -a, --address: print the server object address column" << std::endl << " -c, --clients: print the client PIDs, or client cmdlines if -m is set" @@ -495,6 +542,7 @@ Status Lshal::parseArgs(int argc, char **argv) { {"help", no_argument, 0, 'h' }, {"interface", no_argument, 0, 'i' }, {"transport", no_argument, 0, 't' }, + {"arch", no_argument, 0, 'r' }, {"pid", no_argument, 0, 'p' }, {"address", no_argument, 0, 'a' }, {"clients", no_argument, 0, 'c' }, @@ -511,7 +559,7 @@ Status Lshal::parseArgs(int argc, char **argv) { optind = 1; for (;;) { // using getopt_long in case we want to add other options in the future - c = getopt_long(argc, argv, "hitpacm", longOptions, &optionIndex); + c = getopt_long(argc, argv, "hitrpacm", longOptions, &optionIndex); if (c == -1) { break; } @@ -547,6 +595,10 @@ Status Lshal::parseArgs(int argc, char **argv) { mSelectedColumns |= ENABLE_TRANSPORT; break; } + case 'r': { + mSelectedColumns |= ENABLE_ARCH; + break; + } case 'p': { mSelectedColumns |= ENABLE_SERVER_PID; break; diff --git a/cmds/lshal/Lshal.h b/cmds/lshal/Lshal.h index 1c30908189..a1bc3b06fa 100644 --- a/cmds/lshal/Lshal.h +++ b/cmds/lshal/Lshal.h @@ -63,7 +63,9 @@ private: void dumpVintf() const; void printLine( const std::string &interfaceName, - const std::string &transport, const std::string &server, + const std::string &transport, + const std::string &arch, + const std::string &server, const std::string &serverCmdline, const std::string &address, const std::string &clients, const std::string &clientCmdlines) const ; diff --git a/cmds/lshal/TableEntry.h b/cmds/lshal/TableEntry.h index e55806e2b6..8154cb2adc 100644 --- a/cmds/lshal/TableEntry.h +++ b/cmds/lshal/TableEntry.h @@ -35,6 +35,14 @@ enum : unsigned int { }; using TableEntrySource = unsigned int; +enum : unsigned int { + ARCH_UNKNOWN = 0, + ARCH64 = 1 << 0, + ARCH32 = 1 << 1, + ARCH_BOTH = ARCH32 | ARCH64 +}; +using Architecture = unsigned int; + struct TableEntry { std::string interfaceName; std::string transport; @@ -44,6 +52,7 @@ struct TableEntry { Pids clientPids; std::vector clientCmdlines; TableEntrySource source; + Architecture arch; static bool sortByInterfaceName(const TableEntry &a, const TableEntry &b) { return a.interfaceName < b.interfaceName; @@ -61,7 +70,8 @@ enum : unsigned int { ENABLE_TRANSPORT = 1 << 1, ENABLE_SERVER_PID = 1 << 2, ENABLE_SERVER_ADDR = 1 << 3, - ENABLE_CLIENT_PIDS = 1 << 4 + ENABLE_CLIENT_PIDS = 1 << 4, + ENABLE_ARCH = 1 << 5 }; using TableEntrySelect = unsigned int; -- cgit v1.2.3-59-g8ed1b From a3b8709a5dfc57d6d6bcc0ee89bbeb4aed3e908c Mon Sep 17 00:00:00 2001 From: Yifan Hong Date: Thu, 2 Mar 2017 19:19:29 -0800 Subject: lshal: Put more description to output Split the output by three parts according to the source of information. Describe each part before the table. --sort will be applied to each table individually. Bug: 35803917 Test: lshal Change-Id: Ief0dae21fdeb58ebaed46d2aa68f298b8b75218d --- cmds/lshal/Lshal.cpp | 235 ++++++++++++++++++++++++++++-------------------- cmds/lshal/Lshal.h | 11 ++- cmds/lshal/TableEntry.h | 13 ++- 3 files changed, 156 insertions(+), 103 deletions(-) diff --git a/cmds/lshal/Lshal.cpp b/cmds/lshal/Lshal.cpp index 2140471488..7646febd51 100644 --- a/cmds/lshal/Lshal.cpp +++ b/cmds/lshal/Lshal.cpp @@ -159,19 +159,32 @@ bool Lshal::getReferencedPids( return true; } -void Lshal::postprocess() { - if (mSortColumn) { - std::sort(mTable.begin(), mTable.end(), mSortColumn); +void Lshal::forEachTable(const std::function &f) { + for (const Table &table : {mServicesTable, mPassthroughRefTable, mImplementationsTable}) { + f(const_cast(table)); } - for (TableEntry &entry : mTable) { - entry.serverCmdline = getCmdline(entry.serverPid); - removeDeadProcesses(&entry.clientPids); - for (auto pid : entry.clientPids) { - entry.clientCmdlines.push_back(this->getCmdline(pid)); - } +} +void Lshal::forEachTable(const std::function &f) const { + for (const Table &table : {mServicesTable, mPassthroughRefTable, mImplementationsTable}) { + f(table); } } +void Lshal::postprocess() { + forEachTable([this](Table &table) { + if (mSortColumn) { + std::sort(table.begin(), table.end(), mSortColumn); + } + for (TableEntry &entry : table) { + entry.serverCmdline = getCmdline(entry.serverPid); + removeDeadProcesses(&entry.clientPids); + for (auto pid : entry.clientPids) { + entry.clientCmdlines.push_back(this->getCmdline(pid)); + } + } + }); +} + void Lshal::printLine( const std::string &interfaceName, const std::string &transport, @@ -207,72 +220,74 @@ void Lshal::printLine( void Lshal::dumpVintf() const { vintf::HalManifest manifest; - for (const TableEntry &entry : mTable) { + forEachTable([this, &manifest] (const Table &table) { + for (const TableEntry &entry : table) { - std::string fqInstanceName = entry.interfaceName; - - if (entry.source == LIST_DLLIB) { - // Quick hack to work around *'s - replaceAll(&fqInstanceName, '*', 'D'); - } - auto splittedFqInstanceName = splitFirst(fqInstanceName, '/'); - FQName fqName(splittedFqInstanceName.first); - if (!fqName.isValid()) { - mErr << "Warning: '" << splittedFqInstanceName.first - << "' is not a valid FQName." << std::endl; - continue; - } - // Strip out system libs. - // TODO(b/34772739): might want to add other framework HAL packages - if (fqName.inPackage("android.hidl")) { - continue; - } - std::string interfaceName = - entry.source == LIST_DLLIB ? "" : fqName.name(); - std::string instanceName = - entry.source == LIST_DLLIB ? "" : splittedFqInstanceName.second; - - vintf::Transport transport; - if (entry.transport == "hwbinder") { - transport = vintf::Transport::HWBINDER; - } else if (entry.transport == "passthrough") { - transport = vintf::Transport::PASSTHROUGH; - } else { - mErr << "Warning: '" << entry.transport << "' is not a valid transport." << std::endl; - continue; - } + std::string fqInstanceName = entry.interfaceName; - vintf::ManifestHal *hal = manifest.getHal(fqName.package()); - if (hal == nullptr) { - if (!manifest.add(vintf::ManifestHal{ - .format = vintf::HalFormat::HIDL, - .name = fqName.package(), - .impl = {.implLevel = vintf::ImplLevel::GENERIC, .impl = ""}, - .transport = transport - })) { - mErr << "Warning: cannot add hal '" << fqInstanceName << "'" << std::endl; + if (&table == &mImplementationsTable) { + // Quick hack to work around *'s + replaceAll(&fqInstanceName, '*', 'D'); + } + auto splittedFqInstanceName = splitFirst(fqInstanceName, '/'); + FQName fqName(splittedFqInstanceName.first); + if (!fqName.isValid()) { + mErr << "Warning: '" << splittedFqInstanceName.first + << "' is not a valid FQName." << std::endl; continue; } - hal = manifest.getHal(fqName.package()); - } - if (hal == nullptr) { - mErr << "Warning: cannot get hal '" << fqInstanceName - << "' after adding it" << std::endl; - continue; - } - vintf::Version version{fqName.getPackageMajorVersion(), fqName.getPackageMinorVersion()}; - if (std::find(hal->versions.begin(), hal->versions.end(), version) == hal->versions.end()) { - hal->versions.push_back(version); - } - if (entry.source != LIST_DLLIB) { - auto it = hal->interfaces.find(interfaceName); - if (it == hal->interfaces.end()) { - hal->interfaces.insert({interfaceName, {interfaceName, {{instanceName}}}}); + // Strip out system libs. + // TODO(b/34772739): might want to add other framework HAL packages + if (fqName.inPackage("android.hidl")) { + continue; + } + std::string interfaceName = + &table == &mImplementationsTable ? "" : fqName.name(); + std::string instanceName = + &table == &mImplementationsTable ? "" : splittedFqInstanceName.second; + + vintf::Transport transport; + if (entry.transport == "hwbinder") { + transport = vintf::Transport::HWBINDER; + } else if (entry.transport == "passthrough") { + transport = vintf::Transport::PASSTHROUGH; } else { - it->second.instances.insert(instanceName); + mErr << "Warning: '" << entry.transport << "' is not a valid transport." << std::endl; + continue; + } + + vintf::ManifestHal *hal = manifest.getHal(fqName.package()); + if (hal == nullptr) { + if (!manifest.add(vintf::ManifestHal{ + .format = vintf::HalFormat::HIDL, + .name = fqName.package(), + .impl = {.implLevel = vintf::ImplLevel::GENERIC, .impl = ""}, + .transport = transport + })) { + mErr << "Warning: cannot add hal '" << fqInstanceName << "'" << std::endl; + continue; + } + hal = manifest.getHal(fqName.package()); + } + if (hal == nullptr) { + mErr << "Warning: cannot get hal '" << fqInstanceName + << "' after adding it" << std::endl; + continue; + } + vintf::Version version{fqName.getPackageMajorVersion(), fqName.getPackageMinorVersion()}; + if (std::find(hal->versions.begin(), hal->versions.end(), version) == hal->versions.end()) { + hal->versions.push_back(version); + } + if (&table != &mImplementationsTable) { + auto it = hal->interfaces.find(interfaceName); + if (it == hal->interfaces.end()) { + hal->interfaces.insert({interfaceName, {interfaceName, {{instanceName}}}}); + } else { + it->second.instances.insert(instanceName); + } } } - } + }); mOut << vintf::gHalManifestConverter(manifest); } @@ -306,20 +321,36 @@ static Architecture fromBaseArchitecture(::android::hidl::base::V1_0::DebugInfo: } } -void Lshal::dumpTable() const { - mOut << "All services:" << std::endl; - mOut << std::left; - printLine("Interface", "Transport", "Arch", "Server", "Server CMD", "PTR", "Clients", "Clients CMD"); - for (const auto &entry : mTable) { - printLine(entry.interfaceName, - entry.transport, - getArchString(entry.arch), - entry.serverPid == NO_PID ? "N/A" : std::to_string(entry.serverPid), - entry.serverCmdline, - entry.serverObjectAddress == NO_PTR ? "N/A" : toHexString(entry.serverObjectAddress), - join(entry.clientPids, " "), - join(entry.clientCmdlines, ";")); - } +void Lshal::dumpTable() { + mServicesTable.description = + "All binderized services (registered services through hwservicemanager)"; + mPassthroughRefTable.description = + "All interfaces that getService() has ever return a passthrough interface;\n" + "PIDs / processes shown below might be inaccurate because the process\n" + "might have relinquish the interface or might have died.\n" + "The Server / Server CMD column can be ignored.\n" + "The Clients / Clients CMD column shows all process that have ever dlopen the library\n" + "and successfully fetch the passthrough implementation."; + mImplementationsTable.description = + "All available passthrough implementations (all -impl.so files)"; + forEachTable([this] (const Table &table) { + mOut << table.description << std::endl; + mOut << std::left; + printLine("Interface", "Transport", "Arch", "Server", "Server CMD", + "PTR", "Clients", "Clients CMD"); + for (const auto &entry : table) { + printLine(entry.interfaceName, + entry.transport, + getArchString(entry.arch), + entry.serverPid == NO_PID ? "N/A" : std::to_string(entry.serverPid), + entry.serverCmdline, + entry.serverObjectAddress == NO_PTR ? "N/A" : toHexString(entry.serverObjectAddress), + join(entry.clientPids, " "), + join(entry.clientCmdlines, ";")); + } + mOut << std::endl; + }); + } void Lshal::dump() { @@ -336,8 +367,21 @@ void Lshal::dump() { } } -void Lshal::putEntry(TableEntry &&entry) { - mTable.push_back(std::forward(entry)); +void Lshal::putEntry(TableEntrySource source, TableEntry &&entry) { + Table *table = nullptr; + switch (source) { + case HWSERVICEMANAGER_LIST : + table = &mServicesTable; break; + case PTSERVICEMANAGER_REG_CLIENT : + table = &mPassthroughRefTable; break; + case LIST_DLLIB : + table = &mImplementationsTable; break; + default: + mErr << "Error: Unknown source of entry " << source << std::endl; + } + if (table) { + table->entries.push_back(std::forward(entry)); + } } Status Lshal::fetchAllLibraries(const sp &manager) { @@ -355,12 +399,11 @@ Status Lshal::fetchAllLibraries(const sp &manager) { .serverPid = NO_PID, .serverObjectAddress = NO_PTR, .clientPids = {}, - .arch = ARCH_UNKNOWN, - .source = LIST_DLLIB + .arch = ARCH_UNKNOWN }).first->second.arch |= fromBaseArchitecture(info.arch); } for (auto &&pair : entries) { - putEntry(std::move(pair.second)); + putEntry(LIST_DLLIB, std::move(pair.second)); } }); if (!ret.isOk()) { @@ -378,7 +421,7 @@ Status Lshal::fetchPassthrough(const sp &manager) { using namespace ::android::hidl::base::V1_0; auto ret = timeoutIPC(manager, &IServiceManager::debugDump, [&] (const auto &infos) { for (const auto &info : infos) { - putEntry({ + putEntry(PTSERVICEMANAGER_REG_CLIENT, { .interfaceName = std::string{info.interfaceName.c_str()} + "/" + std::string{info.instanceName.c_str()}, @@ -386,8 +429,7 @@ Status Lshal::fetchPassthrough(const sp &manager) { .serverPid = info.clientPids.size() == 1 ? info.clientPids[0] : NO_PID, .serverObjectAddress = NO_PTR, .clientPids = info.clientPids, - .arch = fromBaseArchitecture(info.arch), - .source = PTSERVICEMANAGER_REG_CLIENT + .arch = fromBaseArchitecture(info.arch) }); } }); @@ -464,19 +506,18 @@ Status Lshal::fetchBinderized(const sp &manager) { for (const auto &fqInstanceName : fqInstanceNames) { auto it = allDebugInfos.find(fqInstanceName); if (it == allDebugInfos.end()) { - putEntry({ + putEntry(HWSERVICEMANAGER_LIST, { .interfaceName = fqInstanceName, .transport = mode, .serverPid = NO_PID, .serverObjectAddress = NO_PTR, .clientPids = {}, - .arch = ARCH_UNKNOWN, - .source = HWSERVICEMANAGER_LIST + .arch = ARCH_UNKNOWN }); continue; } const DebugInfo &info = it->second; - putEntry({ + putEntry(HWSERVICEMANAGER_LIST, { .interfaceName = fqInstanceName, .transport = mode, .serverPid = info.pid, @@ -484,7 +525,6 @@ Status Lshal::fetchBinderized(const sp &manager) { .clientPids = info.pid == NO_PID || info.ptr == NO_PTR ? Pids{} : allPids[info.pid][info.ptr], .arch = fromBaseArchitecture(info.arch), - .source = HWSERVICEMANAGER_LIST }); } return status; @@ -515,7 +555,7 @@ Status Lshal::fetch() { void Lshal::usage() const { mErr << "usage: lshal" << std::endl - << " Dump all hals with default ordering and columns [-itpc]." << std::endl + << " Dump all hals with default ordering and columns [-ipc]." << std::endl << " lshal [--interface|-i] [--transport|-t] [-r|--arch]" << std::endl << " [--pid|-p] [--address|-a] [--clients|-c] [--cmdline|-m]" << std::endl << " [--sort={interface|i|pid|p}] [--init-vintf[=path]]" << std::endl @@ -623,8 +663,7 @@ Status Lshal::parseArgs(int argc, char **argv) { } if (mSelectedColumns == 0) { - mSelectedColumns = ENABLE_INTERFACE_NAME - | ENABLE_TRANSPORT | ENABLE_SERVER_PID | ENABLE_CLIENT_PIDS; + mSelectedColumns = ENABLE_INTERFACE_NAME | ENABLE_SERVER_PID | ENABLE_CLIENT_PIDS; } return OK; } diff --git a/cmds/lshal/Lshal.h b/cmds/lshal/Lshal.h index a1bc3b06fa..c9c66605f9 100644 --- a/cmds/lshal/Lshal.h +++ b/cmds/lshal/Lshal.h @@ -53,13 +53,13 @@ private: void postprocess(); void dump(); void usage() const; - void putEntry(TableEntry &&entry); + void putEntry(TableEntrySource source, TableEntry &&entry); Status fetchPassthrough(const sp<::android::hidl::manager::V1_0::IServiceManager> &manager); Status fetchBinderized(const sp<::android::hidl::manager::V1_0::IServiceManager> &manager); Status fetchAllLibraries(const sp<::android::hidl::manager::V1_0::IServiceManager> &manager); bool getReferencedPids( pid_t serverPid, std::map *objects) const; - void dumpTable() const; + void dumpTable(); void dumpVintf() const; void printLine( const std::string &interfaceName, @@ -74,8 +74,13 @@ private: // Call getCmdline on all pid in pids. If it returns empty string, the process might // have died, and the pid is removed from pids. void removeDeadProcesses(Pids *pids); + void forEachTable(const std::function &f); + void forEachTable(const std::function &f) const; + + Table mServicesTable{}; + Table mPassthroughRefTable{}; + Table mImplementationsTable{}; - Table mTable{}; NullableOStream mErr = std::cerr; NullableOStream mOut = std::cout; NullableOStream mFileOutput = nullptr; diff --git a/cmds/lshal/TableEntry.h b/cmds/lshal/TableEntry.h index 8154cb2adc..2407b42cdf 100644 --- a/cmds/lshal/TableEntry.h +++ b/cmds/lshal/TableEntry.h @@ -51,7 +51,6 @@ struct TableEntry { uint64_t serverObjectAddress; Pids clientPids; std::vector clientCmdlines; - TableEntrySource source; Architecture arch; static bool sortByInterfaceName(const TableEntry &a, const TableEntry &b) { @@ -62,7 +61,17 @@ struct TableEntry { }; }; -using Table = std::vector; +struct Table { + using Entries = std::vector; + std::string description; + Entries entries; + + Entries::iterator begin() { return entries.begin(); } + Entries::const_iterator begin() const { return entries.begin(); } + Entries::iterator end() { return entries.end(); } + Entries::const_iterator end() const { return entries.end(); } +}; + using TableEntryCompare = std::function; enum : unsigned int { -- cgit v1.2.3-59-g8ed1b