record.cpp 43 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262
  1. /*
  2. * Copyright (C) 2015 The Android Open Source Project
  3. *
  4. * Licensed under the Apache License, Version 2.0 (the "License");
  5. * you may not use this file except in compliance with the License.
  6. * You may obtain a copy of the License at
  7. *
  8. * http://www.apache.org/licenses/LICENSE-2.0
  9. *
  10. * Unless required by applicable law or agreed to in writing, software
  11. * distributed under the License is distributed on an "AS IS" BASIS,
  12. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  13. * See the License for the specific language governing permissions and
  14. * limitations under the License.
  15. */
  16. #include "record.h"
  17. #include <inttypes.h>
  18. #include <algorithm>
  19. #include <unordered_map>
  20. #include <android-base/logging.h>
  21. #include <android-base/stringprintf.h>
  22. #include "dso.h"
  23. #include "OfflineUnwinder.h"
  24. #include "perf_regs.h"
  25. #include "tracing.h"
  26. #include "utils.h"
  27. using namespace simpleperf;
  28. static std::string RecordTypeToString(int record_type) {
  29. static std::unordered_map<int, std::string> record_type_names = {
  30. {PERF_RECORD_MMAP, "mmap"},
  31. {PERF_RECORD_LOST, "lost"},
  32. {PERF_RECORD_COMM, "comm"},
  33. {PERF_RECORD_EXIT, "exit"},
  34. {PERF_RECORD_THROTTLE, "throttle"},
  35. {PERF_RECORD_UNTHROTTLE, "unthrottle"},
  36. {PERF_RECORD_FORK, "fork"},
  37. {PERF_RECORD_READ, "read"},
  38. {PERF_RECORD_SAMPLE, "sample"},
  39. {PERF_RECORD_BUILD_ID, "build_id"},
  40. {PERF_RECORD_MMAP2, "mmap2"},
  41. {PERF_RECORD_TRACING_DATA, "tracing_data"},
  42. {SIMPLE_PERF_RECORD_KERNEL_SYMBOL, "kernel_symbol"},
  43. {SIMPLE_PERF_RECORD_DSO, "dso"},
  44. {SIMPLE_PERF_RECORD_SYMBOL, "symbol"},
  45. {SIMPLE_PERF_RECORD_EVENT_ID, "event_id"},
  46. {SIMPLE_PERF_RECORD_CALLCHAIN, "callchain"},
  47. {SIMPLE_PERF_RECORD_UNWINDING_RESULT, "unwinding_result"},
  48. {SIMPLE_PERF_RECORD_TRACING_DATA, "tracing_data"},
  49. };
  50. auto it = record_type_names.find(record_type);
  51. if (it != record_type_names.end()) {
  52. return it->second;
  53. }
  54. return android::base::StringPrintf("unknown(%d)", record_type);
  55. }
  56. template <>
  57. void MoveToBinaryFormat(const RecordHeader& data, char*& p) {
  58. data.MoveToBinaryFormat(p);
  59. }
  60. SampleId::SampleId() { memset(this, 0, sizeof(SampleId)); }
  61. // Return sample_id size in binary format.
  62. size_t SampleId::CreateContent(const perf_event_attr& attr, uint64_t event_id) {
  63. sample_id_all = attr.sample_id_all;
  64. sample_type = attr.sample_type;
  65. id_data.id = event_id;
  66. // Other data are not necessary. TODO: Set missing SampleId data.
  67. return Size();
  68. }
  69. void SampleId::ReadFromBinaryFormat(const perf_event_attr& attr, const char* p,
  70. const char* end) {
  71. sample_id_all = attr.sample_id_all;
  72. sample_type = attr.sample_type;
  73. if (sample_id_all) {
  74. if (sample_type & PERF_SAMPLE_TID) {
  75. MoveFromBinaryFormat(tid_data, p);
  76. }
  77. if (sample_type & PERF_SAMPLE_TIME) {
  78. MoveFromBinaryFormat(time_data, p);
  79. }
  80. if (sample_type & PERF_SAMPLE_ID) {
  81. MoveFromBinaryFormat(id_data, p);
  82. }
  83. if (sample_type & PERF_SAMPLE_STREAM_ID) {
  84. MoveFromBinaryFormat(stream_id_data, p);
  85. }
  86. if (sample_type & PERF_SAMPLE_CPU) {
  87. MoveFromBinaryFormat(cpu_data, p);
  88. }
  89. if (sample_type & PERF_SAMPLE_IDENTIFIER) {
  90. MoveFromBinaryFormat(id_data, p);
  91. }
  92. }
  93. CHECK_LE(p, end);
  94. if (p < end) {
  95. LOG(DEBUG) << "Record SampleId part has " << end - p << " bytes left\n";
  96. }
  97. }
  98. void SampleId::WriteToBinaryFormat(char*& p) const {
  99. if (sample_id_all) {
  100. if (sample_type & PERF_SAMPLE_TID) {
  101. MoveToBinaryFormat(tid_data, p);
  102. }
  103. if (sample_type & PERF_SAMPLE_TIME) {
  104. MoveToBinaryFormat(time_data, p);
  105. }
  106. if (sample_type & PERF_SAMPLE_ID) {
  107. MoveToBinaryFormat(id_data, p);
  108. }
  109. if (sample_type & PERF_SAMPLE_STREAM_ID) {
  110. MoveToBinaryFormat(stream_id_data, p);
  111. }
  112. if (sample_type & PERF_SAMPLE_CPU) {
  113. MoveToBinaryFormat(cpu_data, p);
  114. }
  115. }
  116. }
  117. void SampleId::Dump(size_t indent) const {
  118. if (sample_id_all) {
  119. if (sample_type & PERF_SAMPLE_TID) {
  120. PrintIndented(indent, "sample_id: pid %u, tid %u\n", tid_data.pid,
  121. tid_data.tid);
  122. }
  123. if (sample_type & PERF_SAMPLE_TIME) {
  124. PrintIndented(indent, "sample_id: time %" PRId64 "\n", time_data.time);
  125. }
  126. if (sample_type & (PERF_SAMPLE_ID | PERF_SAMPLE_IDENTIFIER)) {
  127. PrintIndented(indent, "sample_id: id %" PRId64 "\n", id_data.id);
  128. }
  129. if (sample_type & PERF_SAMPLE_STREAM_ID) {
  130. PrintIndented(indent, "sample_id: stream_id %" PRId64 "\n",
  131. stream_id_data.stream_id);
  132. }
  133. if (sample_type & PERF_SAMPLE_CPU) {
  134. PrintIndented(indent, "sample_id: cpu %u, res %u\n", cpu_data.cpu,
  135. cpu_data.res);
  136. }
  137. }
  138. }
  139. size_t SampleId::Size() const {
  140. size_t size = 0;
  141. if (sample_id_all) {
  142. if (sample_type & PERF_SAMPLE_TID) {
  143. size += sizeof(PerfSampleTidType);
  144. }
  145. if (sample_type & PERF_SAMPLE_TIME) {
  146. size += sizeof(PerfSampleTimeType);
  147. }
  148. if (sample_type & PERF_SAMPLE_ID) {
  149. size += sizeof(PerfSampleIdType);
  150. }
  151. if (sample_type & PERF_SAMPLE_STREAM_ID) {
  152. size += sizeof(PerfSampleStreamIdType);
  153. }
  154. if (sample_type & PERF_SAMPLE_CPU) {
  155. size += sizeof(PerfSampleCpuType);
  156. }
  157. if (sample_type & PERF_SAMPLE_IDENTIFIER) {
  158. size += sizeof(PerfSampleIdType);
  159. }
  160. }
  161. return size;
  162. }
  163. Record::Record(Record&& other) noexcept {
  164. header = other.header;
  165. sample_id = other.sample_id;
  166. binary_ = other.binary_;
  167. own_binary_ = other.own_binary_;
  168. other.binary_ = nullptr;
  169. other.own_binary_ = false;
  170. }
  171. void Record::Dump(size_t indent) const {
  172. PrintIndented(indent, "record %s: type %u, misc %u, size %u\n",
  173. RecordTypeToString(type()).c_str(), type(), misc(), size());
  174. DumpData(indent + 1);
  175. sample_id.Dump(indent + 1);
  176. }
  177. uint64_t Record::Timestamp() const { return sample_id.time_data.time; }
  178. uint32_t Record::Cpu() const { return sample_id.cpu_data.cpu; }
  179. uint64_t Record::Id() const { return sample_id.id_data.id; }
  180. void Record::UpdateBinary(char* new_binary) {
  181. if (own_binary_) {
  182. delete[] binary_;
  183. }
  184. own_binary_ = true;
  185. binary_ = new_binary;
  186. }
  187. MmapRecord::MmapRecord(const perf_event_attr& attr, char* p) : Record(p) {
  188. const char* end = p + size();
  189. p += header_size();
  190. data = reinterpret_cast<const MmapRecordDataType*>(p);
  191. p += sizeof(*data);
  192. filename = p;
  193. p += Align(strlen(filename) + 1, 8);
  194. CHECK_LE(p, end);
  195. sample_id.ReadFromBinaryFormat(attr, p, end);
  196. }
  197. MmapRecord::MmapRecord(const perf_event_attr& attr, bool in_kernel,
  198. uint32_t pid, uint32_t tid, uint64_t addr, uint64_t len,
  199. uint64_t pgoff, const std::string& filename,
  200. uint64_t event_id, uint64_t time) {
  201. SetTypeAndMisc(PERF_RECORD_MMAP,
  202. in_kernel ? PERF_RECORD_MISC_KERNEL : PERF_RECORD_MISC_USER);
  203. sample_id.CreateContent(attr, event_id);
  204. sample_id.time_data.time = time;
  205. MmapRecordDataType data;
  206. data.pid = pid;
  207. data.tid = tid;
  208. data.addr = addr;
  209. data.len = len;
  210. data.pgoff = pgoff;
  211. SetDataAndFilename(data, filename);
  212. }
  213. void MmapRecord::SetDataAndFilename(const MmapRecordDataType& data,
  214. const std::string& filename) {
  215. SetSize(header_size() + sizeof(data) + Align(filename.size() + 1, 8) +
  216. sample_id.Size());
  217. char* new_binary = new char[size()];
  218. char* p = new_binary;
  219. MoveToBinaryFormat(header, p);
  220. this->data = reinterpret_cast<MmapRecordDataType*>(p);
  221. MoveToBinaryFormat(data, p);
  222. this->filename = p;
  223. strcpy(p, filename.c_str());
  224. p += Align(filename.size() + 1, 8);
  225. sample_id.WriteToBinaryFormat(p);
  226. UpdateBinary(new_binary);
  227. }
  228. void MmapRecord::DumpData(size_t indent) const {
  229. PrintIndented(indent,
  230. "pid %u, tid %u, addr 0x%" PRIx64 ", len 0x%" PRIx64 "\n",
  231. data->pid, data->tid, data->addr, data->len);
  232. PrintIndented(indent, "pgoff 0x%" PRIx64 ", filename %s\n", data->pgoff,
  233. filename);
  234. }
  235. Mmap2Record::Mmap2Record(const perf_event_attr& attr, char* p) : Record(p) {
  236. const char* end = p + size();
  237. p += header_size();
  238. data = reinterpret_cast<const Mmap2RecordDataType*>(p);
  239. p += sizeof(*data);
  240. filename = p;
  241. p += Align(strlen(filename) + 1, 8);
  242. CHECK_LE(p, end);
  243. sample_id.ReadFromBinaryFormat(attr, p, end);
  244. }
  245. Mmap2Record::Mmap2Record(const perf_event_attr& attr, bool in_kernel, uint32_t pid, uint32_t tid,
  246. uint64_t addr, uint64_t len, uint64_t pgoff, uint32_t prot,
  247. const std::string& filename, uint64_t event_id, uint64_t time) {
  248. SetTypeAndMisc(PERF_RECORD_MMAP2, in_kernel ? PERF_RECORD_MISC_KERNEL : PERF_RECORD_MISC_USER);
  249. sample_id.CreateContent(attr, event_id);
  250. sample_id.time_data.time = time;
  251. Mmap2RecordDataType data;
  252. data.pid = pid;
  253. data.tid = tid;
  254. data.addr = addr;
  255. data.len = len;
  256. data.pgoff = pgoff;
  257. data.prot = prot;
  258. SetDataAndFilename(data, filename);
  259. }
  260. void Mmap2Record::SetDataAndFilename(const Mmap2RecordDataType& data,
  261. const std::string& filename) {
  262. SetSize(header_size() + sizeof(data) + Align(filename.size() + 1, 8) +
  263. sample_id.Size());
  264. char* new_binary = new char[size()];
  265. char* p = new_binary;
  266. MoveToBinaryFormat(header, p);
  267. this->data = reinterpret_cast<Mmap2RecordDataType*>(p);
  268. MoveToBinaryFormat(data, p);
  269. this->filename = p;
  270. strcpy(p, filename.c_str());
  271. p += Align(filename.size() + 1, 8);
  272. sample_id.WriteToBinaryFormat(p);
  273. UpdateBinary(new_binary);
  274. }
  275. void Mmap2Record::DumpData(size_t indent) const {
  276. PrintIndented(indent,
  277. "pid %u, tid %u, addr 0x%" PRIx64 ", len 0x%" PRIx64 "\n",
  278. data->pid, data->tid, data->addr, data->len);
  279. PrintIndented(indent, "pgoff 0x%" PRIx64 ", maj %u, min %u, ino %" PRId64
  280. ", ino_generation %" PRIu64 "\n",
  281. data->pgoff, data->maj, data->min, data->ino,
  282. data->ino_generation);
  283. PrintIndented(indent, "prot %u, flags %u, filename %s\n", data->prot,
  284. data->flags, filename);
  285. }
  286. CommRecord::CommRecord(const perf_event_attr& attr, char* p) : Record(p) {
  287. const char* end = p + size();
  288. p += header_size();
  289. data = reinterpret_cast<const CommRecordDataType*>(p);
  290. p += sizeof(*data);
  291. comm = p;
  292. p += Align(strlen(p) + 1, 8);
  293. CHECK_LE(p, end);
  294. sample_id.ReadFromBinaryFormat(attr, p, end);
  295. }
  296. CommRecord::CommRecord(const perf_event_attr& attr, uint32_t pid, uint32_t tid,
  297. const std::string& comm, uint64_t event_id, uint64_t time) {
  298. SetTypeAndMisc(PERF_RECORD_COMM, 0);
  299. CommRecordDataType data;
  300. data.pid = pid;
  301. data.tid = tid;
  302. size_t sample_id_size = sample_id.CreateContent(attr, event_id);
  303. sample_id.time_data.time = time;
  304. SetSize(header_size() + sizeof(data) + Align(comm.size() + 1, 8) +
  305. sample_id_size);
  306. char* new_binary = new char[size()];
  307. char* p = new_binary;
  308. MoveToBinaryFormat(header, p);
  309. this->data = reinterpret_cast<CommRecordDataType*>(p);
  310. MoveToBinaryFormat(data, p);
  311. this->comm = p;
  312. strcpy(p, comm.c_str());
  313. p += Align(comm.size() + 1, 8);
  314. sample_id.WriteToBinaryFormat(p);
  315. UpdateBinary(new_binary);
  316. }
  317. void CommRecord::SetCommandName(const std::string& name) {
  318. if (name.compare(comm) == 0) {
  319. return;
  320. }
  321. // The kernel uses a 8-byte aligned space to store command name. Follow it here to allow the same
  322. // reading code.
  323. size_t old_name_len = Align(strlen(comm) + 1, 8);
  324. size_t new_name_len = Align(name.size() + 1, 8);
  325. size_t new_size = size() - old_name_len + new_name_len;
  326. char* new_binary = new char[new_size];
  327. char* p = new_binary;
  328. header.size = new_size;
  329. MoveToBinaryFormat(header, p);
  330. MoveToBinaryFormat(*data, p);
  331. data = reinterpret_cast<CommRecordDataType*>(p - sizeof(CommRecordDataType));
  332. comm = p;
  333. strcpy(p, name.c_str());
  334. p += new_name_len;
  335. sample_id.WriteToBinaryFormat(p);
  336. CHECK_EQ(p, new_binary + new_size);
  337. UpdateBinary(new_binary);
  338. }
  339. void CommRecord::DumpData(size_t indent) const {
  340. PrintIndented(indent, "pid %u, tid %u, comm %s\n", data->pid, data->tid,
  341. comm);
  342. }
  343. ExitOrForkRecord::ExitOrForkRecord(const perf_event_attr& attr, char* p)
  344. : Record(p) {
  345. const char* end = p + size();
  346. p += header_size();
  347. data = reinterpret_cast<const ExitOrForkRecordDataType*>(p);
  348. p += sizeof(*data);
  349. CHECK_LE(p, end);
  350. sample_id.ReadFromBinaryFormat(attr, p, end);
  351. }
  352. void ExitOrForkRecord::DumpData(size_t indent) const {
  353. PrintIndented(indent, "pid %u, ppid %u, tid %u, ptid %u\n", data->pid,
  354. data->ppid, data->tid, data->ptid);
  355. }
  356. ForkRecord::ForkRecord(const perf_event_attr& attr, uint32_t pid, uint32_t tid,
  357. uint32_t ppid, uint32_t ptid, uint64_t event_id) {
  358. SetTypeAndMisc(PERF_RECORD_FORK, 0);
  359. ExitOrForkRecordDataType data;
  360. data.pid = pid;
  361. data.ppid = ppid;
  362. data.tid = tid;
  363. data.ptid = ptid;
  364. data.time = 0;
  365. size_t sample_id_size = sample_id.CreateContent(attr, event_id);
  366. SetSize(header_size() + sizeof(data) + sample_id_size);
  367. char* new_binary = new char[size()];
  368. char* p = new_binary;
  369. MoveToBinaryFormat(header, p);
  370. this->data = reinterpret_cast<ExitOrForkRecordDataType*>(p);
  371. MoveToBinaryFormat(data, p);
  372. sample_id.WriteToBinaryFormat(p);
  373. UpdateBinary(new_binary);
  374. }
  375. LostRecord::LostRecord(const perf_event_attr& attr, char* p) : Record(p) {
  376. const char* end = p + size();
  377. p += header_size();
  378. MoveFromBinaryFormat(id, p);
  379. MoveFromBinaryFormat(lost, p);
  380. CHECK_LE(p, end);
  381. sample_id.ReadFromBinaryFormat(attr, p, end);
  382. }
  383. void LostRecord::DumpData(size_t indent) const {
  384. PrintIndented(indent, "id %" PRIu64 ", lost %" PRIu64 "\n", id, lost);
  385. }
  386. SampleRecord::SampleRecord(const perf_event_attr& attr, char* p) : Record(p) {
  387. const char* end = p + size();
  388. p += header_size();
  389. sample_type = attr.sample_type;
  390. // Set a default id value to report correctly even if ID is not recorded.
  391. id_data.id = 0;
  392. if (sample_type & PERF_SAMPLE_IDENTIFIER) {
  393. MoveFromBinaryFormat(id_data, p);
  394. }
  395. if (sample_type & PERF_SAMPLE_IP) {
  396. MoveFromBinaryFormat(ip_data, p);
  397. }
  398. if (sample_type & PERF_SAMPLE_TID) {
  399. MoveFromBinaryFormat(tid_data, p);
  400. }
  401. if (sample_type & PERF_SAMPLE_TIME) {
  402. MoveFromBinaryFormat(time_data, p);
  403. }
  404. if (sample_type & PERF_SAMPLE_ADDR) {
  405. MoveFromBinaryFormat(addr_data, p);
  406. }
  407. if (sample_type & PERF_SAMPLE_ID) {
  408. MoveFromBinaryFormat(id_data, p);
  409. }
  410. if (sample_type & PERF_SAMPLE_STREAM_ID) {
  411. MoveFromBinaryFormat(stream_id_data, p);
  412. }
  413. if (sample_type & PERF_SAMPLE_CPU) {
  414. MoveFromBinaryFormat(cpu_data, p);
  415. }
  416. if (sample_type & PERF_SAMPLE_PERIOD) {
  417. MoveFromBinaryFormat(period_data, p);
  418. }
  419. if (sample_type & PERF_SAMPLE_CALLCHAIN) {
  420. MoveFromBinaryFormat(callchain_data.ip_nr, p);
  421. callchain_data.ips = reinterpret_cast<uint64_t*>(p);
  422. p += callchain_data.ip_nr * sizeof(uint64_t);
  423. }
  424. if (sample_type & PERF_SAMPLE_RAW) {
  425. MoveFromBinaryFormat(raw_data.size, p);
  426. raw_data.data = p;
  427. p += raw_data.size;
  428. }
  429. if (sample_type & PERF_SAMPLE_BRANCH_STACK) {
  430. MoveFromBinaryFormat(branch_stack_data.stack_nr, p);
  431. branch_stack_data.stack = reinterpret_cast<BranchStackItemType*>(p);
  432. p += branch_stack_data.stack_nr * sizeof(BranchStackItemType);
  433. }
  434. if (sample_type & PERF_SAMPLE_REGS_USER) {
  435. MoveFromBinaryFormat(regs_user_data.abi, p);
  436. if (regs_user_data.abi == 0) {
  437. regs_user_data.reg_mask = 0;
  438. } else {
  439. regs_user_data.reg_mask = attr.sample_regs_user;
  440. size_t bit_nr = __builtin_popcountll(regs_user_data.reg_mask);
  441. regs_user_data.reg_nr = bit_nr;
  442. regs_user_data.regs = reinterpret_cast<uint64_t*>(p);
  443. p += bit_nr * sizeof(uint64_t);
  444. }
  445. }
  446. if (sample_type & PERF_SAMPLE_STACK_USER) {
  447. MoveFromBinaryFormat(stack_user_data.size, p);
  448. if (stack_user_data.size == 0) {
  449. stack_user_data.dyn_size = 0;
  450. } else {
  451. stack_user_data.data = p;
  452. p += stack_user_data.size;
  453. MoveFromBinaryFormat(stack_user_data.dyn_size, p);
  454. }
  455. }
  456. // TODO: Add parsing of other PERF_SAMPLE_*.
  457. CHECK_LE(p, end);
  458. if (p < end) {
  459. LOG(DEBUG) << "Record has " << end - p << " bytes left\n";
  460. }
  461. }
  462. SampleRecord::SampleRecord(const perf_event_attr& attr, uint64_t id,
  463. uint64_t ip, uint32_t pid, uint32_t tid,
  464. uint64_t time, uint32_t cpu, uint64_t period,
  465. const std::vector<uint64_t>& ips, const std::vector<char>& stack,
  466. uint64_t dyn_stack_size) {
  467. SetTypeAndMisc(PERF_RECORD_SAMPLE, PERF_RECORD_MISC_USER);
  468. sample_type = attr.sample_type;
  469. CHECK_EQ(0u, sample_type & ~(PERF_SAMPLE_IP | PERF_SAMPLE_TID
  470. | PERF_SAMPLE_TIME | PERF_SAMPLE_ID | PERF_SAMPLE_CPU
  471. | PERF_SAMPLE_PERIOD | PERF_SAMPLE_CALLCHAIN | PERF_SAMPLE_REGS_USER
  472. | PERF_SAMPLE_STACK_USER));
  473. ip_data.ip = ip;
  474. tid_data.pid = pid;
  475. tid_data.tid = tid;
  476. time_data.time = time;
  477. id_data.id = id;
  478. cpu_data.cpu = cpu;
  479. cpu_data.res = 0;
  480. period_data.period = period;
  481. callchain_data.ip_nr = ips.size();
  482. raw_data.size = 0;
  483. branch_stack_data.stack_nr = 0;
  484. regs_user_data.abi = 0;
  485. regs_user_data.reg_mask = 0;
  486. regs_user_data.reg_nr = 0;
  487. stack_user_data.size = stack.size();
  488. stack_user_data.dyn_size = dyn_stack_size;
  489. uint32_t size = header_size();
  490. if (sample_type & PERF_SAMPLE_IP) {
  491. size += sizeof(ip_data);
  492. }
  493. if (sample_type & PERF_SAMPLE_TID) {
  494. size += sizeof(tid_data);
  495. }
  496. if (sample_type & PERF_SAMPLE_TIME) {
  497. size += sizeof(time_data);
  498. }
  499. if (sample_type & PERF_SAMPLE_ID) {
  500. size += sizeof(id_data);
  501. }
  502. if (sample_type & PERF_SAMPLE_CPU) {
  503. size += sizeof(cpu_data);
  504. }
  505. if (sample_type & PERF_SAMPLE_PERIOD) {
  506. size += sizeof(period_data);
  507. }
  508. if (sample_type & PERF_SAMPLE_CALLCHAIN) {
  509. size += sizeof(uint64_t) * (ips.size() + 1);
  510. }
  511. if (sample_type & PERF_SAMPLE_REGS_USER) {
  512. size += sizeof(uint64_t);
  513. }
  514. if (sample_type & PERF_SAMPLE_STACK_USER) {
  515. size += sizeof(uint64_t) + (stack.empty() ? 0 : stack.size() + sizeof(uint64_t));
  516. }
  517. SetSize(size);
  518. char* new_binary = new char[size];
  519. char* p = new_binary;
  520. MoveToBinaryFormat(header, p);
  521. if (sample_type & PERF_SAMPLE_IP) {
  522. MoveToBinaryFormat(ip_data, p);
  523. }
  524. if (sample_type & PERF_SAMPLE_TID) {
  525. MoveToBinaryFormat(tid_data, p);
  526. }
  527. if (sample_type & PERF_SAMPLE_TIME) {
  528. MoveToBinaryFormat(time_data, p);
  529. }
  530. if (sample_type & PERF_SAMPLE_ID) {
  531. MoveToBinaryFormat(id_data, p);
  532. }
  533. if (sample_type & PERF_SAMPLE_CPU) {
  534. MoveToBinaryFormat(cpu_data, p);
  535. }
  536. if (sample_type & PERF_SAMPLE_PERIOD) {
  537. MoveToBinaryFormat(period_data, p);
  538. }
  539. if (sample_type & PERF_SAMPLE_CALLCHAIN) {
  540. MoveToBinaryFormat(callchain_data.ip_nr, p);
  541. callchain_data.ips = reinterpret_cast<uint64_t*>(p);
  542. MoveToBinaryFormat(ips.data(), ips.size(), p);
  543. }
  544. if (sample_type & PERF_SAMPLE_REGS_USER) {
  545. MoveToBinaryFormat(regs_user_data.abi, p);
  546. }
  547. if (sample_type & PERF_SAMPLE_STACK_USER) {
  548. MoveToBinaryFormat(stack_user_data.size, p);
  549. if (stack_user_data.size > 0) {
  550. stack_user_data.data = p;
  551. MoveToBinaryFormat(stack.data(), stack_user_data.size, p);
  552. MoveToBinaryFormat(stack_user_data.dyn_size, p);
  553. }
  554. }
  555. CHECK_EQ(p, new_binary + size);
  556. UpdateBinary(new_binary);
  557. }
  558. void SampleRecord::ReplaceRegAndStackWithCallChain(const std::vector<uint64_t>& ips) {
  559. uint32_t size_added_in_callchain = sizeof(uint64_t) * (ips.size() + 1);
  560. uint32_t size_reduced_in_reg_stack = regs_user_data.reg_nr * sizeof(uint64_t) +
  561. stack_user_data.size + sizeof(uint64_t);
  562. uint32_t new_size = size() + size_added_in_callchain - size_reduced_in_reg_stack;
  563. BuildBinaryWithNewCallChain(new_size, ips);
  564. }
  565. bool SampleRecord::ExcludeKernelCallChain() {
  566. if (!(sample_type & PERF_SAMPLE_CALLCHAIN)) {
  567. return true;
  568. }
  569. size_t i;
  570. for (i = 0; i < callchain_data.ip_nr; ++i) {
  571. if (callchain_data.ips[i] == PERF_CONTEXT_USER) {
  572. break;
  573. }
  574. // Erase kernel callchain.
  575. callchain_data.ips[i] = PERF_CONTEXT_USER;
  576. }
  577. while (++i < callchain_data.ip_nr) {
  578. if (callchain_data.ips[i] < PERF_CONTEXT_MAX) {
  579. // Change the sample to make it hit the user space ip address.
  580. ip_data.ip = callchain_data.ips[i];
  581. if (sample_type & PERF_SAMPLE_IP) {
  582. *reinterpret_cast<uint64_t*>(binary_ + header_size()) = ip_data.ip;
  583. }
  584. header.misc = (header.misc & ~PERF_RECORD_MISC_CPUMODE_MASK) | PERF_RECORD_MISC_USER;
  585. reinterpret_cast<perf_event_header*>(binary_)->misc = header.misc;
  586. return true;
  587. }
  588. }
  589. return false;
  590. }
  591. bool SampleRecord::HasUserCallChain() const {
  592. if ((sample_type & PERF_SAMPLE_CALLCHAIN) == 0) {
  593. return false;
  594. }
  595. bool in_user_context = !InKernel();
  596. for (size_t i = 0; i < callchain_data.ip_nr; ++i) {
  597. if (in_user_context && callchain_data.ips[i] < PERF_CONTEXT_MAX) {
  598. return true;
  599. }
  600. if (callchain_data.ips[i] == PERF_CONTEXT_USER) {
  601. in_user_context = true;
  602. }
  603. }
  604. return false;
  605. }
  606. void SampleRecord::UpdateUserCallChain(const std::vector<uint64_t>& user_ips) {
  607. size_t kernel_ip_count = 0;
  608. for (size_t i = 0; i < callchain_data.ip_nr; ++i) {
  609. if (callchain_data.ips[i] == PERF_CONTEXT_USER) {
  610. break;
  611. }
  612. kernel_ip_count++;
  613. }
  614. if (kernel_ip_count + 1 + user_ips.size() <= callchain_data.ip_nr) {
  615. // Callchain isn't changed.
  616. return;
  617. }
  618. size_t new_size = size() + (kernel_ip_count + 1 + user_ips.size() - callchain_data.ip_nr) *
  619. sizeof(uint64_t);
  620. callchain_data.ip_nr = kernel_ip_count;
  621. BuildBinaryWithNewCallChain(new_size, user_ips);
  622. }
  623. void SampleRecord::BuildBinaryWithNewCallChain(uint32_t new_size,
  624. const std::vector<uint64_t>& ips) {
  625. size_t callchain_pos = reinterpret_cast<char*>(callchain_data.ips) - binary_ - sizeof(uint64_t);
  626. char* new_binary = binary_;
  627. if (new_size > size()) {
  628. new_binary = new char[new_size];
  629. memcpy(new_binary, binary_, callchain_pos);
  630. }
  631. char* p = new_binary;
  632. SetSize(new_size);
  633. MoveToBinaryFormat(header, p);
  634. p = new_binary + new_size;
  635. if (sample_type & PERF_SAMPLE_STACK_USER) {
  636. stack_user_data.size = 0;
  637. p -= sizeof(uint64_t);
  638. memcpy(p, &stack_user_data.size, sizeof(uint64_t));
  639. }
  640. if (sample_type & PERF_SAMPLE_REGS_USER) {
  641. regs_user_data.abi = 0;
  642. p -= sizeof(uint64_t);
  643. memcpy(p, &regs_user_data.abi, sizeof(uint64_t));
  644. }
  645. if (sample_type & PERF_SAMPLE_BRANCH_STACK) {
  646. p -= branch_stack_data.stack_nr * sizeof(BranchStackItemType);
  647. memcpy(p, branch_stack_data.stack, branch_stack_data.stack_nr * sizeof(BranchStackItemType));
  648. branch_stack_data.stack = reinterpret_cast<BranchStackItemType*>(p);
  649. p -= sizeof(uint64_t);
  650. memcpy(p, &branch_stack_data.stack_nr, sizeof(uint64_t));
  651. }
  652. if (sample_type & PERF_SAMPLE_RAW) {
  653. p -= raw_data.size;
  654. memcpy(p, raw_data.data, raw_data.size);
  655. raw_data.data = p;
  656. p -= sizeof(uint32_t);
  657. memcpy(p, &raw_data.size, sizeof(uint32_t));
  658. }
  659. uint64_t* p64 = reinterpret_cast<uint64_t*>(p);
  660. p64 -= ips.size();
  661. memcpy(p64, ips.data(), ips.size() * sizeof(uint64_t));
  662. *--p64 = PERF_CONTEXT_USER;
  663. if (callchain_data.ip_nr > 0) {
  664. p64 -= callchain_data.ip_nr;
  665. memcpy(p64, callchain_data.ips, callchain_data.ip_nr * sizeof(uint64_t));
  666. }
  667. callchain_data.ips = p64;
  668. callchain_data.ip_nr += 1 + ips.size();
  669. *--p64 = callchain_data.ip_nr;
  670. CHECK_EQ(callchain_pos, static_cast<size_t>(reinterpret_cast<char*>(p64) - new_binary))
  671. << "record time " << time_data.time;
  672. if (new_binary != binary_) {
  673. UpdateBinary(new_binary);
  674. }
  675. }
  676. void SampleRecord::DumpData(size_t indent) const {
  677. PrintIndented(indent, "sample_type: 0x%" PRIx64 "\n", sample_type);
  678. if (sample_type & PERF_SAMPLE_IP) {
  679. PrintIndented(indent, "ip %p\n", reinterpret_cast<void*>(ip_data.ip));
  680. }
  681. if (sample_type & PERF_SAMPLE_TID) {
  682. PrintIndented(indent, "pid %u, tid %u\n", tid_data.pid, tid_data.tid);
  683. }
  684. if (sample_type & PERF_SAMPLE_TIME) {
  685. PrintIndented(indent, "time %" PRId64 "\n", time_data.time);
  686. }
  687. if (sample_type & PERF_SAMPLE_ADDR) {
  688. PrintIndented(indent, "addr %p\n", reinterpret_cast<void*>(addr_data.addr));
  689. }
  690. if (sample_type & (PERF_SAMPLE_ID | PERF_SAMPLE_IDENTIFIER)) {
  691. PrintIndented(indent, "id %" PRId64 "\n", id_data.id);
  692. }
  693. if (sample_type & PERF_SAMPLE_STREAM_ID) {
  694. PrintIndented(indent, "stream_id %" PRId64 "\n", stream_id_data.stream_id);
  695. }
  696. if (sample_type & PERF_SAMPLE_CPU) {
  697. PrintIndented(indent, "cpu %u, res %u\n", cpu_data.cpu, cpu_data.res);
  698. }
  699. if (sample_type & PERF_SAMPLE_PERIOD) {
  700. PrintIndented(indent, "period %" PRId64 "\n", period_data.period);
  701. }
  702. if (sample_type & PERF_SAMPLE_CALLCHAIN) {
  703. PrintIndented(indent, "callchain nr=%" PRIu64 "\n", callchain_data.ip_nr);
  704. for (uint64_t i = 0; i < callchain_data.ip_nr; ++i) {
  705. PrintIndented(indent + 1, "0x%" PRIx64 "\n", callchain_data.ips[i]);
  706. }
  707. }
  708. if (sample_type & PERF_SAMPLE_RAW) {
  709. PrintIndented(indent, "raw size=%zu\n", raw_data.size);
  710. const uint32_t* data = reinterpret_cast<const uint32_t*>(raw_data.data);
  711. size_t size = raw_data.size / sizeof(uint32_t);
  712. for (size_t i = 0; i < size; ++i) {
  713. PrintIndented(indent + 1, "0x%08x (%zu)\n", data[i], data[i]);
  714. }
  715. }
  716. if (sample_type & PERF_SAMPLE_BRANCH_STACK) {
  717. PrintIndented(indent, "branch_stack nr=%" PRIu64 "\n",
  718. branch_stack_data.stack_nr);
  719. for (uint64_t i = 0; i < branch_stack_data.stack_nr; ++i) {
  720. auto& item = branch_stack_data.stack[i];
  721. PrintIndented(indent + 1, "from 0x%" PRIx64 ", to 0x%" PRIx64
  722. ", flags 0x%" PRIx64 "\n",
  723. item.from, item.to, item.flags);
  724. }
  725. }
  726. if (sample_type & PERF_SAMPLE_REGS_USER) {
  727. PrintIndented(indent, "user regs: abi=%" PRId64 "\n", regs_user_data.abi);
  728. for (size_t i = 0, pos = 0; i < 64; ++i) {
  729. if ((regs_user_data.reg_mask >> i) & 1) {
  730. PrintIndented(
  731. indent + 1, "reg (%s) 0x%016" PRIx64 "\n",
  732. GetRegName(i, ScopedCurrentArch::GetCurrentArch()).c_str(),
  733. regs_user_data.regs[pos++]);
  734. }
  735. }
  736. }
  737. if (sample_type & PERF_SAMPLE_STACK_USER) {
  738. PrintIndented(indent, "user stack: size %zu dyn_size %" PRIu64 "\n",
  739. stack_user_data.size, stack_user_data.dyn_size);
  740. const uint64_t* p = reinterpret_cast<const uint64_t*>(stack_user_data.data);
  741. const uint64_t* end = p + (stack_user_data.size / sizeof(uint64_t));
  742. while (p < end) {
  743. PrintIndented(indent + 1, "");
  744. for (size_t i = 0; i < 4 && p < end; ++i, ++p) {
  745. printf(" %016" PRIx64, *p);
  746. }
  747. printf("\n");
  748. }
  749. printf("\n");
  750. }
  751. }
  752. uint64_t SampleRecord::Timestamp() const { return time_data.time; }
  753. uint32_t SampleRecord::Cpu() const { return cpu_data.cpu; }
  754. uint64_t SampleRecord::Id() const { return id_data.id; }
  755. void SampleRecord::AdjustCallChainGeneratedByKernel() {
  756. // The kernel stores return addrs in the callchain, but we want the addrs of call instructions
  757. // along the callchain.
  758. uint64_t* ips = callchain_data.ips;
  759. uint64_t context = header.misc == PERF_RECORD_MISC_KERNEL ? PERF_CONTEXT_KERNEL
  760. : PERF_CONTEXT_USER;
  761. bool first_frame = true;
  762. for (size_t i = 0; i < callchain_data.ip_nr; ++i) {
  763. if (ips[i] < PERF_CONTEXT_MAX) {
  764. if (first_frame) {
  765. first_frame = false;
  766. } else {
  767. if (ips[i] < 2) {
  768. // A wrong ip address, erase it.
  769. ips[i] = context;
  770. } else {
  771. // Here we want to change the return addr to the addr of the previous instruction. We
  772. // don't need to find the exact start addr of the previous instruction. A location in
  773. // [start_addr_of_call_inst, start_addr_of_next_inst) is enough.
  774. #if defined(__arm__) || defined(__aarch64__)
  775. // If we are built for arm/aarch64, this may be a callchain of thumb code. For thumb code,
  776. // the real instruction addr is (ip & ~1), and ip - 2 can used to hit the address range
  777. // of the previous instruction. For non thumb code, any addr in [ip - 4, ip - 1] is fine.
  778. ips[i] -= 2;
  779. #else
  780. ips[i]--;
  781. #endif
  782. }
  783. }
  784. } else {
  785. context = ips[i];
  786. }
  787. }
  788. }
  789. std::vector<uint64_t> SampleRecord::GetCallChain(size_t* kernel_ip_count) const {
  790. std::vector<uint64_t> ips;
  791. bool in_kernel = InKernel();
  792. ips.push_back(ip_data.ip);
  793. *kernel_ip_count = in_kernel ? 1 : 0;
  794. if ((sample_type & PERF_SAMPLE_CALLCHAIN) == 0) {
  795. return ips;
  796. }
  797. bool first_ip = true;
  798. for (uint64_t i = 0; i < callchain_data.ip_nr; ++i) {
  799. uint64_t ip = callchain_data.ips[i];
  800. if (ip >= PERF_CONTEXT_MAX) {
  801. switch (ip) {
  802. case PERF_CONTEXT_KERNEL:
  803. CHECK(in_kernel) << "User space callchain followed by kernel callchain.";
  804. break;
  805. case PERF_CONTEXT_USER:
  806. in_kernel = false;
  807. break;
  808. default:
  809. LOG(DEBUG) << "Unexpected perf_context in callchain: " << std::hex << ip << std::dec;
  810. }
  811. } else {
  812. if (first_ip) {
  813. first_ip = false;
  814. // Remove duplication with sample ip.
  815. if (ip == ip_data.ip) {
  816. continue;
  817. }
  818. }
  819. ips.push_back(ip);
  820. if (in_kernel) {
  821. ++*kernel_ip_count;
  822. }
  823. }
  824. }
  825. return ips;
  826. }
  827. BuildIdRecord::BuildIdRecord(char* p) : Record(p) {
  828. const char* end = p + size();
  829. p += header_size();
  830. MoveFromBinaryFormat(pid, p);
  831. build_id = BuildId(p, BUILD_ID_SIZE);
  832. p += Align(build_id.Size(), 8);
  833. filename = p;
  834. p += Align(strlen(filename) + 1, 64);
  835. CHECK_EQ(p, end);
  836. }
  837. void BuildIdRecord::DumpData(size_t indent) const {
  838. PrintIndented(indent, "pid %u\n", pid);
  839. PrintIndented(indent, "build_id %s\n", build_id.ToString().c_str());
  840. PrintIndented(indent, "filename %s\n", filename);
  841. }
  842. BuildIdRecord::BuildIdRecord(bool in_kernel, pid_t pid, const BuildId& build_id,
  843. const std::string& filename) {
  844. SetTypeAndMisc(PERF_RECORD_BUILD_ID,
  845. in_kernel ? PERF_RECORD_MISC_KERNEL : PERF_RECORD_MISC_USER);
  846. this->pid = pid;
  847. this->build_id = build_id;
  848. SetSize(header_size() + sizeof(pid) + Align(build_id.Size(), 8) +
  849. Align(filename.size() + 1, 64));
  850. char* new_binary = new char[size()];
  851. char* p = new_binary;
  852. MoveToBinaryFormat(header, p);
  853. MoveToBinaryFormat(pid, p);
  854. memcpy(p, build_id.Data(), build_id.Size());
  855. p += Align(build_id.Size(), 8);
  856. this->filename = p;
  857. strcpy(p, filename.c_str());
  858. UpdateBinary(new_binary);
  859. }
  860. KernelSymbolRecord::KernelSymbolRecord(char* p) : Record(p) {
  861. const char* end = p + size();
  862. p += header_size();
  863. MoveFromBinaryFormat(kallsyms_size, p);
  864. kallsyms = p;
  865. p += Align(kallsyms_size, 8);
  866. CHECK_EQ(p, end);
  867. }
  868. void KernelSymbolRecord::DumpData(size_t indent) const {
  869. PrintIndented(indent, "kallsyms: %s\n",
  870. std::string(kallsyms, kallsyms + kallsyms_size).c_str());
  871. }
  872. KernelSymbolRecord::KernelSymbolRecord(const std::string& kallsyms) {
  873. SetTypeAndMisc(SIMPLE_PERF_RECORD_KERNEL_SYMBOL, 0);
  874. kallsyms_size = kallsyms.size();
  875. SetSize(header_size() + 4 + Align(kallsyms.size(), 8));
  876. char* new_binary = new char[size()];
  877. char* p = new_binary;
  878. MoveToBinaryFormat(header, p);
  879. MoveToBinaryFormat(kallsyms_size, p);
  880. this->kallsyms = p;
  881. memcpy(p, kallsyms.data(), kallsyms_size);
  882. UpdateBinary(new_binary);
  883. }
  884. DsoRecord::DsoRecord(char* p) : Record(p) {
  885. const char* end = p + size();
  886. p += header_size();
  887. MoveFromBinaryFormat(dso_type, p);
  888. MoveFromBinaryFormat(dso_id, p);
  889. MoveFromBinaryFormat(min_vaddr, p);
  890. dso_name = p;
  891. p += Align(strlen(dso_name) + 1, 8);
  892. CHECK_EQ(p, end);
  893. }
  894. DsoRecord::DsoRecord(uint64_t dso_type, uint64_t dso_id,
  895. const std::string& dso_name, uint64_t min_vaddr) {
  896. SetTypeAndMisc(SIMPLE_PERF_RECORD_DSO, 0);
  897. this->dso_type = dso_type;
  898. this->dso_id = dso_id;
  899. this->min_vaddr = min_vaddr;
  900. SetSize(header_size() + 3 * sizeof(uint64_t) + Align(dso_name.size() + 1, 8));
  901. char* new_binary = new char[size()];
  902. char* p = new_binary;
  903. MoveToBinaryFormat(header, p);
  904. MoveToBinaryFormat(dso_type, p);
  905. MoveToBinaryFormat(dso_id, p);
  906. MoveToBinaryFormat(min_vaddr, p);
  907. this->dso_name = p;
  908. strcpy(p, dso_name.c_str());
  909. UpdateBinary(new_binary);
  910. }
  911. void DsoRecord::DumpData(size_t indent) const {
  912. PrintIndented(indent, "dso_type: %s(%" PRIu64 ")\n",
  913. DsoTypeToString(static_cast<DsoType>(dso_type)), dso_type);
  914. PrintIndented(indent, "dso_id: %" PRIu64 "\n", dso_id);
  915. PrintIndented(indent, "min_vaddr: 0x%" PRIx64 "\n", min_vaddr);
  916. PrintIndented(indent, "dso_name: %s\n", dso_name);
  917. }
  918. SymbolRecord::SymbolRecord(char* p) : Record(p) {
  919. const char* end = p + size();
  920. p += header_size();
  921. MoveFromBinaryFormat(addr, p);
  922. MoveFromBinaryFormat(len, p);
  923. MoveFromBinaryFormat(dso_id, p);
  924. name = p;
  925. p += Align(strlen(name) + 1, 8);
  926. CHECK_EQ(p, end);
  927. }
  928. SymbolRecord::SymbolRecord(uint64_t addr, uint64_t len, const std::string& name,
  929. uint64_t dso_id) {
  930. SetTypeAndMisc(SIMPLE_PERF_RECORD_SYMBOL, 0);
  931. this->addr = addr;
  932. this->len = len;
  933. this->dso_id = dso_id;
  934. SetSize(header_size() + 3 * sizeof(uint64_t) + Align(name.size() + 1, 8));
  935. char* new_binary = new char[size()];
  936. char* p = new_binary;
  937. MoveToBinaryFormat(header, p);
  938. MoveToBinaryFormat(addr, p);
  939. MoveToBinaryFormat(len, p);
  940. MoveToBinaryFormat(dso_id, p);
  941. this->name = p;
  942. strcpy(p, name.c_str());
  943. UpdateBinary(new_binary);
  944. }
  945. void SymbolRecord::DumpData(size_t indent) const {
  946. PrintIndented(indent, "name: %s\n", name);
  947. PrintIndented(indent, "addr: 0x%" PRIx64 "\n", addr);
  948. PrintIndented(indent, "len: 0x%" PRIx64 "\n", len);
  949. PrintIndented(indent, "dso_id: %" PRIu64 "\n", dso_id);
  950. }
  951. TracingDataRecord::TracingDataRecord(char* p) : Record(p) {
  952. const char* end = p + size();
  953. p += header_size();
  954. MoveFromBinaryFormat(data_size, p);
  955. data = p;
  956. p += Align(data_size, 64);
  957. CHECK_EQ(p, end);
  958. }
  959. TracingDataRecord::TracingDataRecord(const std::vector<char>& tracing_data) {
  960. SetTypeAndMisc(SIMPLE_PERF_RECORD_TRACING_DATA, 0);
  961. data_size = tracing_data.size();
  962. SetSize(header_size() + sizeof(uint32_t) + Align(tracing_data.size(), 64));
  963. char* new_binary = new char[size()];
  964. char* p = new_binary;
  965. MoveToBinaryFormat(header, p);
  966. MoveToBinaryFormat(data_size, p);
  967. data = p;
  968. memcpy(p, tracing_data.data(), data_size);
  969. UpdateBinary(new_binary);
  970. }
  971. void TracingDataRecord::DumpData(size_t indent) const {
  972. Tracing tracing(std::vector<char>(data, data + data_size));
  973. tracing.Dump(indent);
  974. }
  975. EventIdRecord::EventIdRecord(char* p) : Record(p) {
  976. const char* end = p + size();
  977. p += header_size();
  978. MoveFromBinaryFormat(count, p);
  979. data = reinterpret_cast<const EventIdData*>(p);
  980. p += sizeof(data[0]) * count;
  981. CHECK_EQ(p, end);
  982. }
  983. EventIdRecord::EventIdRecord(const std::vector<uint64_t>& data) {
  984. SetTypeAndMisc(SIMPLE_PERF_RECORD_EVENT_ID, 0);
  985. SetSize(header_size() + sizeof(uint64_t) * (1 + data.size()));
  986. char* new_binary = new char[size()];
  987. char* p = new_binary;
  988. MoveToBinaryFormat(header, p);
  989. count = data.size() / 2;
  990. MoveToBinaryFormat(count, p);
  991. this->data = reinterpret_cast<EventIdData*>(p);
  992. memcpy(p, data.data(), sizeof(uint64_t) * data.size());
  993. UpdateBinary(new_binary);
  994. }
  995. void EventIdRecord::DumpData(size_t indent) const {
  996. PrintIndented(indent, "count: %" PRIu64 "\n", count);
  997. for (size_t i = 0; i < count; ++i) {
  998. PrintIndented(indent, "attr_id[%" PRIu64 "]: %" PRIu64 "\n", i,
  999. data[i].attr_id);
  1000. PrintIndented(indent, "event_id[%" PRIu64 "]: %" PRIu64 "\n", i,
  1001. data[i].event_id);
  1002. }
  1003. }
  1004. CallChainRecord::CallChainRecord(char* p) : Record(p) {
  1005. const char* end = p + size();
  1006. p += header_size();
  1007. MoveFromBinaryFormat(pid, p);
  1008. MoveFromBinaryFormat(tid, p);
  1009. MoveFromBinaryFormat(chain_type, p);
  1010. MoveFromBinaryFormat(time, p);
  1011. MoveFromBinaryFormat(ip_nr, p);
  1012. ips = reinterpret_cast<uint64_t*>(p);
  1013. p += ip_nr * sizeof(uint64_t);
  1014. sps = reinterpret_cast<uint64_t*>(p);
  1015. p += ip_nr * sizeof(uint64_t);
  1016. CHECK_EQ(p, end);
  1017. }
  1018. CallChainRecord::CallChainRecord(pid_t pid, pid_t tid, CallChainJoiner::ChainType type,
  1019. uint64_t time, const std::vector<uint64_t>& ips,
  1020. const std::vector<uint64_t>& sps) {
  1021. CHECK_EQ(ips.size(), sps.size());
  1022. SetTypeAndMisc(SIMPLE_PERF_RECORD_CALLCHAIN, 0);
  1023. this->pid = pid;
  1024. this->tid = tid;
  1025. this->chain_type = static_cast<int>(type);
  1026. this->time = time;
  1027. this->ip_nr = ips.size();
  1028. SetSize(header_size() + (4 + ips.size() * 2) * sizeof(uint64_t));
  1029. char* new_binary = new char[size()];
  1030. char* p = new_binary;
  1031. MoveToBinaryFormat(header, p);
  1032. MoveToBinaryFormat(this->pid, p);
  1033. MoveToBinaryFormat(this->tid, p);
  1034. MoveToBinaryFormat(this->chain_type, p);
  1035. MoveToBinaryFormat(this->time, p);
  1036. MoveToBinaryFormat(this->ip_nr, p);
  1037. this->ips = reinterpret_cast<uint64_t*>(p);
  1038. MoveToBinaryFormat(ips.data(), ips.size(), p);
  1039. this->sps = reinterpret_cast<uint64_t*>(p);
  1040. MoveToBinaryFormat(sps.data(), sps.size(), p);
  1041. UpdateBinary(new_binary);
  1042. }
  1043. void CallChainRecord::DumpData(size_t indent) const {
  1044. const char* type_name = "";
  1045. switch (chain_type) {
  1046. case CallChainJoiner::ORIGINAL_OFFLINE: type_name = "ORIGINAL_OFFLINE"; break;
  1047. case CallChainJoiner::ORIGINAL_REMOTE: type_name = "ORIGINAL_REMOTE"; break;
  1048. case CallChainJoiner::JOINED_OFFLINE: type_name = "JOINED_OFFLINE"; break;
  1049. case CallChainJoiner::JOINED_REMOTE: type_name = "JOINED_REMOTE"; break;
  1050. }
  1051. PrintIndented(indent, "pid %u\n", pid);
  1052. PrintIndented(indent, "tid %u\n", tid);
  1053. PrintIndented(indent, "chain_type %s\n", type_name);
  1054. PrintIndented(indent, "time %" PRIu64 "\n", time);
  1055. PrintIndented(indent, "ip_nr %" PRIu64 "\n", ip_nr);
  1056. for (size_t i = 0; i < ip_nr; ++i) {
  1057. PrintIndented(indent + 1, "ip 0x%" PRIx64 ", sp 0x%" PRIx64 "\n", ips[i], sps[i]);
  1058. }
  1059. }
  1060. UnwindingResultRecord::UnwindingResultRecord(char* p) : Record(p) {
  1061. const char* end = p + size();
  1062. p += header_size();
  1063. MoveFromBinaryFormat(time, p);
  1064. MoveFromBinaryFormat(unwinding_result.used_time, p);
  1065. uint64_t stop_reason;
  1066. MoveFromBinaryFormat(stop_reason, p);
  1067. unwinding_result.stop_reason = static_cast<decltype(unwinding_result.stop_reason)>(stop_reason);
  1068. MoveFromBinaryFormat(unwinding_result.stop_info, p);
  1069. MoveFromBinaryFormat(unwinding_result.stack_start, p);
  1070. MoveFromBinaryFormat(unwinding_result.stack_end, p);
  1071. CHECK_EQ(p, end);
  1072. }
  1073. UnwindingResultRecord::UnwindingResultRecord(uint64_t time,
  1074. const UnwindingResult& unwinding_result) {
  1075. SetTypeAndMisc(SIMPLE_PERF_RECORD_UNWINDING_RESULT, 0);
  1076. SetSize(header_size() + 6 * sizeof(uint64_t));
  1077. this->time = time;
  1078. this->unwinding_result = unwinding_result;
  1079. char* new_binary = new char[size()];
  1080. char* p = new_binary;
  1081. MoveToBinaryFormat(header, p);
  1082. MoveToBinaryFormat(this->time, p);
  1083. MoveToBinaryFormat(unwinding_result.used_time, p);
  1084. uint64_t stop_reason = unwinding_result.stop_reason;
  1085. MoveToBinaryFormat(stop_reason, p);
  1086. MoveToBinaryFormat(unwinding_result.stop_info, p);
  1087. MoveToBinaryFormat(unwinding_result.stack_start, p);
  1088. MoveToBinaryFormat(unwinding_result.stack_end, p);
  1089. UpdateBinary(new_binary);
  1090. }
  1091. void UnwindingResultRecord::DumpData(size_t indent) const {
  1092. PrintIndented(indent, "time %" PRIu64 "\n", time);
  1093. PrintIndented(indent, "used_time %" PRIu64 "\n", unwinding_result.used_time);
  1094. static std::unordered_map<int, std::string> map = {
  1095. {UnwindingResult::UNKNOWN_REASON, "UNKNOWN_REASON"},
  1096. {UnwindingResult::EXCEED_MAX_FRAMES_LIMIT, "EXCEED_MAX_FRAME_LIMIT"},
  1097. {UnwindingResult::ACCESS_REG_FAILED, "ACCESS_REG_FAILED"},
  1098. {UnwindingResult::ACCESS_STACK_FAILED, "ACCESS_STACK_FAILED"},
  1099. {UnwindingResult::ACCESS_MEM_FAILED, "ACCESS_MEM_FAILED"},
  1100. {UnwindingResult::FIND_PROC_INFO_FAILED, "FIND_PROC_INFO_FAILED"},
  1101. {UnwindingResult::EXECUTE_DWARF_INSTRUCTION_FAILED, "EXECUTE_DWARF_INSTRUCTION_FAILED"},
  1102. {UnwindingResult::DIFFERENT_ARCH, "DIFFERENT_ARCH"},
  1103. {UnwindingResult::MAP_MISSING, "MAP_MISSING"},
  1104. };
  1105. PrintIndented(indent, "stop_reason %s\n", map[unwinding_result.stop_reason].c_str());
  1106. if (unwinding_result.stop_reason == UnwindingResult::ACCESS_REG_FAILED) {
  1107. PrintIndented(indent, "regno %" PRIu64 "\n", unwinding_result.stop_info);
  1108. } else if (unwinding_result.stop_reason == UnwindingResult::ACCESS_STACK_FAILED ||
  1109. unwinding_result.stop_reason == UnwindingResult::ACCESS_MEM_FAILED) {
  1110. PrintIndented(indent, "addr 0x%" PRIx64 "\n", unwinding_result.stop_info);
  1111. }
  1112. PrintIndented(indent, "stack_start 0x%" PRIx64 "\n", unwinding_result.stack_start);
  1113. PrintIndented(indent, "stack_end 0x%" PRIx64 "\n", unwinding_result.stack_end);
  1114. }
  1115. UnknownRecord::UnknownRecord(char* p) : Record(p) {
  1116. p += header_size();
  1117. data = p;
  1118. }
  1119. void UnknownRecord::DumpData(size_t) const {}
  1120. std::unique_ptr<Record> ReadRecordFromBuffer(const perf_event_attr& attr, uint32_t type, char* p) {
  1121. switch (type) {
  1122. case PERF_RECORD_MMAP:
  1123. return std::unique_ptr<Record>(new MmapRecord(attr, p));
  1124. case PERF_RECORD_MMAP2:
  1125. return std::unique_ptr<Record>(new Mmap2Record(attr, p));
  1126. case PERF_RECORD_COMM:
  1127. return std::unique_ptr<Record>(new CommRecord(attr, p));
  1128. case PERF_RECORD_EXIT:
  1129. return std::unique_ptr<Record>(new ExitRecord(attr, p));
  1130. case PERF_RECORD_FORK:
  1131. return std::unique_ptr<Record>(new ForkRecord(attr, p));
  1132. case PERF_RECORD_LOST:
  1133. return std::unique_ptr<Record>(new LostRecord(attr, p));
  1134. case PERF_RECORD_SAMPLE:
  1135. return std::unique_ptr<Record>(new SampleRecord(attr, p));
  1136. case PERF_RECORD_TRACING_DATA:
  1137. return std::unique_ptr<Record>(new TracingDataRecord(p));
  1138. case SIMPLE_PERF_RECORD_KERNEL_SYMBOL:
  1139. return std::unique_ptr<Record>(new KernelSymbolRecord(p));
  1140. case SIMPLE_PERF_RECORD_DSO:
  1141. return std::unique_ptr<Record>(new DsoRecord(p));
  1142. case SIMPLE_PERF_RECORD_SYMBOL:
  1143. return std::unique_ptr<Record>(new SymbolRecord(p));
  1144. case SIMPLE_PERF_RECORD_EVENT_ID:
  1145. return std::unique_ptr<Record>(new EventIdRecord(p));
  1146. case SIMPLE_PERF_RECORD_CALLCHAIN:
  1147. return std::unique_ptr<Record>(new CallChainRecord(p));
  1148. case SIMPLE_PERF_RECORD_UNWINDING_RESULT:
  1149. return std::unique_ptr<Record>(new UnwindingResultRecord(p));
  1150. case SIMPLE_PERF_RECORD_TRACING_DATA:
  1151. return std::unique_ptr<Record>(new TracingDataRecord(p));
  1152. default:
  1153. return std::unique_ptr<Record>(new UnknownRecord(p));
  1154. }
  1155. }
  1156. std::unique_ptr<Record> ReadRecordFromOwnedBuffer(const perf_event_attr& attr,
  1157. uint32_t type, char* p) {
  1158. std::unique_ptr<Record> record = ReadRecordFromBuffer(attr, type, p);
  1159. if (record != nullptr) {
  1160. record->OwnBinary();
  1161. } else {
  1162. delete[] p;
  1163. }
  1164. return record;
  1165. }
  1166. std::vector<std::unique_ptr<Record>> ReadRecordsFromBuffer(
  1167. const perf_event_attr& attr, char* buf, size_t buf_size) {
  1168. std::vector<std::unique_ptr<Record>> result;
  1169. char* p = buf;
  1170. char* end = buf + buf_size;
  1171. while (p < end) {
  1172. RecordHeader header(p);
  1173. CHECK_LE(p + header.size, end);
  1174. CHECK_NE(0u, header.size);
  1175. result.push_back(ReadRecordFromBuffer(attr, header.type, p));
  1176. p += header.size;
  1177. }
  1178. return result;
  1179. }
  1180. std::unique_ptr<Record> ReadRecordFromBuffer(const perf_event_attr& attr, char* p) {
  1181. auto header = reinterpret_cast<const perf_event_header*>(p);
  1182. return ReadRecordFromBuffer(attr, header->type, p);
  1183. }