perf: Save and emit the command line
authorBarret Rhoden <brho@cs.berkeley.edu>
Tue, 31 May 2016 19:05:44 +0000 (15:05 -0400)
committerBarret Rhoden <brho@cs.berkeley.edu>
Thu, 16 Jun 2016 15:48:39 +0000 (11:48 -0400)
Signed-off-by: Barret Rhoden <brho@cs.berkeley.edu>
tools/profile/perf/perf.c
tools/profile/perf/perfconv.c
tools/profile/perf/perfconv.h

index 1fd615b..b9e2c8c 100644 (file)
@@ -103,6 +103,25 @@ static void run_process_and_wait(int argc, char *argv[],
        waitpid(pid, &status, 0);
 }
 
+static void save_cmdline(int argc, char *argv[])
+{
+       size_t len = 0;
+       char *p;
+
+       for (int i = 0; i < argc; i++)
+               len += strlen(argv[i]) + 1;
+       cmd_line_save = xmalloc(len);
+       p = cmd_line_save;
+       for (int i = 0; i < argc; i++) {
+               strcpy(p, argv[i]);
+               p += strlen(argv[i]);
+               if (!(i == argc - 1)) {
+                       *p = ' ';       /* overwrite \0 with ' ' */
+                       p++;
+               }
+       }
+}
+
 int main(int argc, char *argv[])
 {
        int i, icmd = -1, num_events = 0;
@@ -113,6 +132,8 @@ int main(int argc, char *argv[])
        struct core_set cores;
        const char *events[MAX_CPU_EVENTS];
 
+       save_cmdline(argc, argv);
+
        ros_get_all_cores_set(&cores);
 
        for (i = 2; i < argc; i++) {
index 66ca868..db8a404 100644 (file)
@@ -38,6 +38,8 @@
 
 #define MBWR_SOLID (1 << 0)
 
+char *cmd_line_save;
+
 struct perf_record {
        uint64_t type;
        uint64_t size;
@@ -373,6 +375,31 @@ static void hdr_do_nrcpus(struct perf_header *ph, struct perf_headers *hdrs)
        headers_add_header(ph, hdrs, HEADER_NRCPUS, mb);
 }
 
+/* Unfortunately, HEADER_CMDLINE doesn't just take a string.  It takes a list of
+ * null-terminated perf_header_strings (i.e. argv), with the a u32 for the
+ * number of strings.  We can just send one string for the entire cmd line. */
+static void hdr_do_cmdline(struct perf_header *ph, struct perf_headers *hdrs)
+{
+       struct perf_header_string *hdr;
+       struct mem_block *mb;
+       size_t str_sz = strlen(cmd_line_save) + 1;
+       size_t hdr_sz = sizeof(uint32_t) +
+                       ROUNDUP(str_sz + sizeof(struct perf_header_string),
+                               PERF_STRING_ALIGN);
+
+       mb = mem_block_alloc(hdr_sz);
+       /* emit the nr strings (1) */
+       *(uint32_t*)mb->wptr = 1;
+       mb->wptr += sizeof(uint32_t);
+       /* emit the perf_header_string, as usual */
+       hdr = (struct perf_header_string*)mb->wptr;
+       mb->wptr += hdr_sz - sizeof(uint32_t);
+       hdr->len = str_sz;
+       memcpy(hdr->string, cmd_line_save, str_sz);
+
+       headers_add_header(ph, hdrs, HEADER_CMDLINE, mb);
+}
+
 /* Returns TRUE if we already emitted a build-id for path.  If this gets too
  * slow (which we'll know because of perf!) we can use a hash table (don't hash
  * on the first few bytes btw - they are usually either /bin or /lib). */
@@ -480,6 +507,7 @@ static void headers_build(struct perf_header *ph, struct perf_headers *hdrs,
 {
        hdr_do_osrelease(ph, hdrs);
        hdr_do_nrcpus(ph, hdrs);
+       hdr_do_cmdline(ph, hdrs);
 
        headers_finalize(hdrs, feat_hdrs);
 }
index b014aa1..107ce92 100644 (file)
@@ -67,6 +67,8 @@ struct perfconv_context {
        struct mem_file fhdrs, attr_ids, attrs, data, event_types;
 };
 
+extern char *cmd_line_save;
+
 struct perfconv_context *perfconv_create_context(struct perf_context *pctx);
 void perfconv_free_context(struct perfconv_context *cctx);
 void perfconv_set_dbglevel(int level, struct perfconv_context *cctx);