]> git.kernelconcepts.de Git - karo-tx-linux.git/blobdiff - tools/perf/tests/code-reading.c
Merge branch 'sched-core-for-linus' of git://git.kernel.org/pub/scm/linux/kernel...
[karo-tx-linux.git] / tools / perf / tests / code-reading.c
index 39c784a100a955143e401fc46cbcb93a2a3d8136..49b1959dda41f0ceb5bc248f3c3e90b558ce9169 100644 (file)
@@ -33,20 +33,20 @@ static unsigned int hex(char c)
        return c - 'A' + 10;
 }
 
-static void read_objdump_line(const char *line, size_t line_len, void **buf,
-                             size_t *len)
+static size_t read_objdump_line(const char *line, size_t line_len, void *buf,
+                             size_t len)
 {
        const char *p;
-       size_t i;
+       size_t i, j = 0;
 
        /* Skip to a colon */
        p = strchr(line, ':');
        if (!p)
-               return;
+               return 0;
        i = p + 1 - line;
 
        /* Read bytes */
-       while (*len) {
+       while (j < len) {
                char c1, c2;
 
                /* Skip spaces */
@@ -65,20 +65,26 @@ static void read_objdump_line(const char *line, size_t line_len, void **buf,
                if (i < line_len && line[i] && !isspace(line[i]))
                        break;
                /* Store byte */
-               *(unsigned char *)*buf = (hex(c1) << 4) | hex(c2);
-               *buf += 1;
-               *len -= 1;
+               *(unsigned char *)buf = (hex(c1) << 4) | hex(c2);
+               buf += 1;
+               j++;
        }
+       /* return number of successfully read bytes */
+       return j;
 }
 
-static int read_objdump_output(FILE *f, void **buf, size_t *len)
+static int read_objdump_output(FILE *f, void *buf, size_t *len, u64 start_addr)
 {
        char *line = NULL;
-       size_t line_len;
+       size_t line_len, off_last = 0;
        ssize_t ret;
        int err = 0;
+       u64 addr, last_addr = start_addr;
+
+       while (off_last < *len) {
+               size_t off, read_bytes, written_bytes;
+               unsigned char tmp[BUFSZ];
 
-       while (1) {
                ret = getline(&line, &line_len, f);
                if (feof(f))
                        break;
@@ -87,9 +93,33 @@ static int read_objdump_output(FILE *f, void **buf, size_t *len)
                        err = -1;
                        break;
                }
-               read_objdump_line(line, ret, buf, len);
+
+               /* read objdump data into temporary buffer */
+               read_bytes = read_objdump_line(line, ret, tmp, sizeof(tmp));
+               if (!read_bytes)
+                       continue;
+
+               if (sscanf(line, "%"PRIx64, &addr) != 1)
+                       continue;
+               if (addr < last_addr) {
+                       pr_debug("addr going backwards, read beyond section?\n");
+                       break;
+               }
+               last_addr = addr;
+
+               /* copy it from temporary buffer to 'buf' according
+                * to address on current objdump line */
+               off = addr - start_addr;
+               if (off >= *len)
+                       break;
+               written_bytes = MIN(read_bytes, *len - off);
+               memcpy(buf + off, tmp, written_bytes);
+               off_last = off + written_bytes;
        }
 
+       /* len returns number of bytes that could not be read */
+       *len -= off_last;
+
        free(line);
 
        return err;
@@ -103,7 +133,7 @@ static int read_via_objdump(const char *filename, u64 addr, void *buf,
        FILE *f;
        int ret;
 
-       fmt = "%s -d --start-address=0x%"PRIx64" --stop-address=0x%"PRIx64" %s";
+       fmt = "%s -z -d --start-address=0x%"PRIx64" --stop-address=0x%"PRIx64" %s";
        ret = snprintf(cmd, sizeof(cmd), fmt, "objdump", addr, addr + len,
                       filename);
        if (ret <= 0 || (size_t)ret >= sizeof(cmd))
@@ -120,7 +150,7 @@ static int read_via_objdump(const char *filename, u64 addr, void *buf,
                return -1;
        }
 
-       ret = read_objdump_output(f, &buf, &len);
+       ret = read_objdump_output(f, buf, &len, addr);
        if (len) {
                pr_debug("objdump read too few bytes\n");
                if (!ret)
@@ -132,6 +162,18 @@ static int read_via_objdump(const char *filename, u64 addr, void *buf,
        return ret;
 }
 
+static void dump_buf(unsigned char *buf, size_t len)
+{
+       size_t i;
+
+       for (i = 0; i < len; i++) {
+               pr_debug("0x%02x ", buf[i]);
+               if (i % 16 == 15)
+                       pr_debug("\n");
+       }
+       pr_debug("\n");
+}
+
 static int read_object_code(u64 addr, size_t len, u8 cpumode,
                            struct thread *thread, struct state *state)
 {
@@ -234,6 +276,10 @@ static int read_object_code(u64 addr, size_t len, u8 cpumode,
        /* The results should be identical */
        if (memcmp(buf1, buf2, len)) {
                pr_debug("Bytes read differ from those read by objdump\n");
+               pr_debug("buf1 (dso):\n");
+               dump_buf(buf1, len);
+               pr_debug("buf2 (objdump):\n");
+               dump_buf(buf2, len);
                return -1;
        }
        pr_debug("Bytes read match those read by objdump\n");
@@ -427,7 +473,7 @@ static int do_test_code_reading(bool try_kcore)
                symbol_conf.kallsyms_name = "/proc/kallsyms";
 
        /* Load kernel map */
-       map = machine->vmlinux_maps[MAP__FUNCTION];
+       map = machine__kernel_map(machine);
        ret = map__load(map, NULL);
        if (ret < 0) {
                pr_debug("map__load failed\n");