diff options
author | Yabin Cui <yabinc@google.com> | 2018-07-17 16:06:21 -0700 |
---|---|---|
committer | Yabin Cui <yabinc@google.com> | 2018-07-17 17:49:45 -0700 |
commit | 38335f4c3a6f14ee1f30e896757537e7d310c25c (patch) | |
tree | 09850e2f307522402033fe7cd5a771096507d6b7 | |
parent | 57bb921048889b011480317b6153a5f68935ba0f (diff) | |
download | extras-38335f4c3a6f14ee1f30e896757537e7d310c25c.tar.gz |
simpleperf: record complete process name.
The kernel limits length of process name to 15. But many app processes
have name with length longer than 15. This patch records complete
process name: When receiving a comm record for a process, try reading
complete name from /proc/pid/cmdline and storing the name in the comm
record.
Bug: none
Test: run simpleperf manually, it shows complete app name in reports.
Test: run simpleperf_unit_test.
Change-Id: Id29f2a2522ef5d2949828450be2d9d2f508a328d
-rw-r--r-- | simpleperf/cmd_record.cpp | 18 | ||||
-rw-r--r-- | simpleperf/environment.cpp | 14 | ||||
-rw-r--r-- | simpleperf/environment.h | 2 | ||||
-rw-r--r-- | simpleperf/record.cpp | 23 | ||||
-rw-r--r-- | simpleperf/record.h | 2 | ||||
-rw-r--r-- | simpleperf/record_test.cpp | 14 |
6 files changed, 68 insertions, 5 deletions
diff --git a/simpleperf/cmd_record.cpp b/simpleperf/cmd_record.cpp index 2597629f..3ae111cf 100644 --- a/simpleperf/cmd_record.cpp +++ b/simpleperf/cmd_record.cpp @@ -277,7 +277,7 @@ class RecordCommand : public Command { bool ProcessJITDebugInfo(const std::vector<JITSymFile>& jit_symfiles, const std::vector<DexSymFile>& dex_symfiles, bool sync_kernel_records); - void UpdateRecordForEmbeddedPath(Record* record); + void UpdateRecord(Record* record); bool UnwindRecord(SampleRecord& r); bool PostUnwindRecords(); bool JoinCallChains(); @@ -1037,8 +1037,8 @@ bool RecordCommand::DumpProcessMaps(pid_t pid, const std::unordered_set<pid_t>& } } // Dump process name. - std::string name; - if (GetThreadName(pid, &name)) { + std::string name = GetCompleteProcessName(pid); + if (!name.empty()) { CommRecord record(attr, pid, pid, name, event_id, last_record_timestamp_); if (!ProcessRecord(&record)) { return false; @@ -1057,7 +1057,7 @@ bool RecordCommand::DumpProcessMaps(pid_t pid, const std::unordered_set<pid_t>& } bool RecordCommand::ProcessRecord(Record* record) { - UpdateRecordForEmbeddedPath(record); + UpdateRecord(record); if (ShouldOmitRecord(record)) { return true; } @@ -1241,12 +1241,20 @@ void UpdateMmapRecordForEmbeddedPath(RecordType& r, bool has_prot, uint32_t prot } } -void RecordCommand::UpdateRecordForEmbeddedPath(Record* record) { +void RecordCommand::UpdateRecord(Record* record) { if (record->type() == PERF_RECORD_MMAP) { UpdateMmapRecordForEmbeddedPath(*static_cast<MmapRecord*>(record), false, 0); } else if (record->type() == PERF_RECORD_MMAP2) { auto r = static_cast<Mmap2Record*>(record); UpdateMmapRecordForEmbeddedPath(*r, true, r->data->prot); + } else if (record->type() == PERF_RECORD_COMM) { + auto r = static_cast<CommRecord*>(record); + if (r->data->pid == r->data->tid) { + std::string s = GetCompleteProcessName(r->data->pid); + if (!s.empty()) { + r->SetCommandName(s); + } + } } } diff --git a/simpleperf/environment.cpp b/simpleperf/environment.cpp index 7b05c7d1..b90606ba 100644 --- a/simpleperf/environment.cpp +++ b/simpleperf/environment.cpp @@ -754,3 +754,17 @@ bool MappedFileOnlyExistInMemory(const char* filename) { strncmp(filename, "//", 2) == 0 || strncmp(filename, "/dev/", 5) == 0; } + +std::string GetCompleteProcessName(pid_t pid) { + std::string s; + if (!android::base::ReadFileToString(android::base::StringPrintf("/proc/%d/cmdline", pid), &s)) { + s.clear(); + } + for (size_t i = 0; i < s.size(); ++i) { + if (isspace(s[i])) { + s.resize(i); + break; + } + } + return s; +} diff --git a/simpleperf/environment.h b/simpleperf/environment.h index b2bb549b..db547f8b 100644 --- a/simpleperf/environment.h +++ b/simpleperf/environment.h @@ -129,4 +129,6 @@ std::string GetHardwareFromCpuInfo(const std::string& cpu_info); bool MappedFileOnlyExistInMemory(const char* filename); +std::string GetCompleteProcessName(pid_t pid); + #endif // SIMPLE_PERF_ENVIRONMENT_H_ diff --git a/simpleperf/record.cpp b/simpleperf/record.cpp index ab2ef72a..1e9c945b 100644 --- a/simpleperf/record.cpp +++ b/simpleperf/record.cpp @@ -343,6 +343,29 @@ CommRecord::CommRecord(const perf_event_attr& attr, uint32_t pid, uint32_t tid, UpdateBinary(new_binary); } +void CommRecord::SetCommandName(const std::string& name) { + if (name.compare(comm) == 0) { + return; + } + // The kernel uses a 8-byte aligned space to store command name. Follow it here to allow the same + // reading code. + size_t old_name_len = Align(strlen(comm) + 1, 8); + size_t new_name_len = Align(name.size() + 1, 8); + size_t new_size = size() - old_name_len + new_name_len; + char* new_binary = new char[new_size]; + char* p = new_binary; + header.size = new_size; + MoveToBinaryFormat(header, p); + MoveToBinaryFormat(*data, p); + data = reinterpret_cast<CommRecordDataType*>(p - sizeof(CommRecordDataType)); + comm = p; + strcpy(p, name.c_str()); + p += new_name_len; + sample_id.WriteToBinaryFormat(p); + CHECK_EQ(p, new_binary + new_size); + UpdateBinary(new_binary); +} + void CommRecord::DumpData(size_t indent) const { PrintIndented(indent, "pid %u, tid %u, comm %s\n", data->pid, data->tid, comm); diff --git a/simpleperf/record.h b/simpleperf/record.h index e002370c..3ba73ec0 100644 --- a/simpleperf/record.h +++ b/simpleperf/record.h @@ -327,6 +327,8 @@ struct CommRecord : public Record { CommRecord(const perf_event_attr& attr, uint32_t pid, uint32_t tid, const std::string& comm, uint64_t event_id, uint64_t time); + void SetCommandName(const std::string& name); + protected: void DumpData(size_t indent) const override; }; diff --git a/simpleperf/record_test.cpp b/simpleperf/record_test.cpp index c14fdacb..954acfaa 100644 --- a/simpleperf/record_test.cpp +++ b/simpleperf/record_test.cpp @@ -131,3 +131,17 @@ TEST_F(RecordTest, SampleRecord_AdjustCallChainGeneratedByKernel) { expected.header.misc = PERF_RECORD_MISC_KERNEL; CheckRecordEqual(r, expected); } + +TEST_F(RecordTest, CommRecord) { + CommRecord r(event_attr, 1, 2, "init_name", 3, 4); + size_t record_size = r.size(); + std::string new_name = "a_much_longer_name"; + r.SetCommandName(new_name); + ASSERT_EQ(r.size(), record_size + 8); + ASSERT_EQ(std::string(r.comm), new_name); + ASSERT_EQ(r.data->pid, 1u); + ASSERT_EQ(r.data->tid, 2u); + ASSERT_EQ(r.sample_id.id_data.id, 3u); + ASSERT_EQ(r.sample_id.time_data.time, 4u); + CheckRecordMatchBinary(r); +} |