linux-perf-users.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
From: Athira Rajeev <atrajeev@linux.vnet.ibm.com>
To: acme@kernel.org, jolsa@kernel.org, adrian.hunter@intel.com,
	irogers@google.com, namhyung@kernel.org,
	segher@kernel.crashing.org, christophe.leroy@csgroup.eu
Cc: linux-kernel@vger.kernel.org, linux-perf-users@vger.kernel.org,
	linuxppc-dev@lists.ozlabs.org, akanksha@linux.ibm.com,
	maddy@linux.ibm.com, atrajeev@linux.vnet.ibm.com,
	kjain@linux.ibm.com, disgoel@linux.vnet.ibm.com
Subject: [PATCH V3 11/14] tools/perf: Add support to use libcapstone in powerpc
Date: Sat,  1 Jun 2024 11:39:38 +0530	[thread overview]
Message-ID: <20240601060941.13692-12-atrajeev@linux.vnet.ibm.com> (raw)
In-Reply-To: <20240601060941.13692-1-atrajeev@linux.vnet.ibm.com>

Now perf uses the capstone library to disassemble the instructions in
x86. capstone is used (if available) for perf annotate to speed up.
Currently it only supports x86 architecture. Patch includes changes to
enable this in powerpc. For now, only for data type sort keys, this
method is used and only binary code (raw instruction) is read. This is
because powerpc approach to understand instructions and reg fields uses
raw instruction. The "cs_disasm" is currently not enabled. While
attempting to do cs_disasm, observation is that some of the instructions
were not identified (ex: extswsli, maddld) and it had to fallback to use
objdump. Hence enabling "cs_disasm" is added in comment section as a
TODO for powerpc.

Signed-off-by: Athira Rajeev <atrajeev@linux.vnet.ibm.com>
---
 tools/perf/util/disasm.c | 148 ++++++++++++++++++++++++++++++++++++++-
 1 file changed, 146 insertions(+), 2 deletions(-)

diff --git a/tools/perf/util/disasm.c b/tools/perf/util/disasm.c
index d8b357055302..915508d2e197 100644
--- a/tools/perf/util/disasm.c
+++ b/tools/perf/util/disasm.c
@@ -1540,12 +1540,18 @@ static int open_capstone_handle(struct annotate_args *args, bool is_64bit,
 {
 	struct annotation_options *opt = args->options;
 	cs_mode mode = is_64bit ? CS_MODE_64 : CS_MODE_32;
+	int ret;
 
 	/* TODO: support more architectures */
-	if (!arch__is(args->arch, "x86"))
+	if ((!arch__is(args->arch, "x86")) && (!arch__is(args->arch, "powerpc")))
 		return -1;
 
-	if (cs_open(CS_ARCH_X86, mode, handle) != CS_ERR_OK)
+	if (arch__is(args->arch, "x86"))
+		ret = cs_open(CS_ARCH_X86, mode, handle);
+	else
+		ret = cs_open(CS_ARCH_PPC, mode, handle);
+
+	if (ret != CS_ERR_OK)
 		return -1;
 
 	if (!opt->disassembler_style ||
@@ -1635,6 +1641,139 @@ static void print_capstone_detail(cs_insn *insn, char *buf, size_t len,
 	}
 }
 
+static int symbol__disassemble_capstone_powerpc(char *filename, struct symbol *sym,
+					struct annotate_args *args)
+{
+	struct annotation *notes = symbol__annotation(sym);
+	struct map *map = args->ms.map;
+	struct dso *dso = map__dso(map);
+	struct nscookie nsc;
+	u64 start = map__rip_2objdump(map, sym->start);
+	u64 end = map__rip_2objdump(map, sym->end);
+	u64 len = end - start;
+	u64 offset;
+	int i, fd, count;
+	bool is_64bit = false;
+	bool needs_cs_close = false;
+	u8 *buf = NULL;
+	struct find_file_offset_data data = {
+		.ip = start,
+	};
+	csh handle;
+	char disasm_buf[512];
+	struct disasm_line *dl;
+	u32 *line;
+
+	if (args->options->objdump_path)
+		return -1;
+
+	nsinfo__mountns_enter(dso->nsinfo, &nsc);
+	fd = open(filename, O_RDONLY);
+	nsinfo__mountns_exit(&nsc);
+	if (fd < 0)
+		return -1;
+
+	if (file__read_maps(fd, /*exe=*/true, find_file_offset, &data,
+			    &is_64bit) == 0)
+		goto err;
+
+	if (open_capstone_handle(args, is_64bit, &handle) < 0)
+		goto err;
+
+	needs_cs_close = true;
+
+	buf = malloc(len);
+	if (buf == NULL)
+		goto err;
+
+	count = pread(fd, buf, len, data.offset);
+	close(fd);
+	fd = -1;
+
+	if ((u64)count != len)
+		goto err;
+
+	line = (u32 *)buf;
+
+	/* add the function address and name */
+	scnprintf(disasm_buf, sizeof(disasm_buf), "%#"PRIx64" <%s>:",
+		  start, sym->name);
+
+	args->offset = -1;
+	args->line = disasm_buf;
+	args->line_nr = 0;
+	args->fileloc = NULL;
+	args->ms.sym = sym;
+
+	dl = disasm_line__new(args);
+	if (dl == NULL)
+		goto err;
+
+	annotation_line__add(&dl->al, &notes->src->source);
+
+	/*
+	 * TODO: enable disassm for powerpc
+	 * count = cs_disasm(handle, buf, len, start, len, &insn);
+	 *
+	 * For now, only binary code is saved in disassembled line
+	 * to be used in "type" and "typeoff" sort keys. Each raw code
+	 * is 32 bit instruction. So use "len/4" to get the number of
+	 * entries.
+	 */
+	count = len/4;
+
+	for (i = 0, offset = 0; i < count; i++) {
+		args->offset = offset;
+		sprintf(args->line, "%x", line[i]);
+
+		dl = disasm_line__new(args);
+		if (dl == NULL)
+			goto err;
+
+		annotation_line__add(&dl->al, &notes->src->source);
+
+		offset += 4;
+	}
+
+	/* It failed in the middle */
+	if (offset != len) {
+		struct list_head *list = &notes->src->source;
+
+		/* Discard all lines and fallback to objdump */
+		while (!list_empty(list)) {
+			dl = list_first_entry(list, struct disasm_line, al.node);
+
+			list_del_init(&dl->al.node);
+			disasm_line__free(dl);
+		}
+		count = -1;
+	}
+
+out:
+	if (needs_cs_close)
+		cs_close(&handle);
+	free(buf);
+	return count < 0 ? count : 0;
+
+err:
+	if (fd >= 0)
+		close(fd);
+	if (needs_cs_close) {
+		struct disasm_line *tmp;
+
+		/*
+		 * It probably failed in the middle of the above loop.
+		 * Release any resources it might add.
+		 */
+		list_for_each_entry_safe(dl, tmp, &notes->src->source, al.node) {
+			list_del(&dl->al.node);
+			free(dl);
+		}
+	}
+	count = -1;
+	goto out;
+}
+
 static int symbol__disassemble_capstone(char *filename, struct symbol *sym,
 					struct annotate_args *args)
 {
@@ -1987,6 +2126,11 @@ int symbol__disassemble(struct symbol *sym, struct annotate_args *args)
 			err = symbol__disassemble_dso(symfs_filename, sym, args);
 			if (err == 0)
 				goto out_remove_tmp;
+#ifdef HAVE_LIBCAPSTONE_SUPPORT
+			err = symbol__disassemble_capstone_powerpc(symfs_filename, sym, args);
+			if (err == 0)
+				goto out_remove_tmp;
+#endif
 		}
 	}
 
-- 
2.43.0


  parent reply	other threads:[~2024-06-01  6:10 UTC|newest]

Thread overview: 28+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2024-06-01  6:09 [PATCH V3 00/14] Add data type profiling support for powerpc Athira Rajeev
2024-06-01  6:09 ` [PATCH V3 01/14] tools/perf: Move the data structures related to register type to header file Athira Rajeev
2024-06-01  6:09 ` [PATCH V3 02/14] tools/perf: Add "update_insn_state" callback function to handle arch specific instruction tracking Athira Rajeev
2024-06-01  6:09 ` [PATCH V3 03/14] tools/perf: Add support to capture and parse raw instruction in powerpc using dso__data_read_offset utility Athira Rajeev
2024-06-01  6:09 ` [PATCH V3 04/14] tools/perf: Use sort keys to determine whether to pick objdump to disassemble Athira Rajeev
2024-06-01  6:09 ` [PATCH V3 05/14] tools/perf: Add disasm_line__parse to parse raw instruction for powerpc Athira Rajeev
2024-06-06  6:33   ` Namhyung Kim
2024-06-08  7:08     ` Athira Rajeev
2024-06-08  8:58     ` Christophe Leroy
2024-06-12  8:42       ` Athira Rajeev
2024-06-01  6:09 ` [PATCH V3 06/14] tools/perf: Update parameters for reg extract functions to use raw instruction on powerpc Athira Rajeev
2024-06-06  6:52   ` Namhyung Kim
2024-06-08  7:08     ` Athira Rajeev
2024-06-01  6:09 ` [PATCH V3 07/14] tools/perf: Add support to identify memory instructions of opcode 31 in powerpc Athira Rajeev
2024-06-01  6:09 ` [PATCH V3 08/14] tools/perf: Add some of the arithmetic instructions to support instruction tracking " Athira Rajeev
2024-06-01  6:09 ` [PATCH V3 09/14] tools/perf: Add more instructions for instruction tracking Athira Rajeev
2024-06-01  6:09 ` [PATCH V3 10/14] tools/perf: Update instruction tracking for powerpc Athira Rajeev
2024-06-06  6:53   ` Namhyung Kim
2024-06-08  7:05     ` Athira Rajeev
2024-06-01  6:09 ` Athira Rajeev [this message]
2024-06-03 16:30   ` [PATCH V3 11/14] tools/perf: Add support to use libcapstone in powerpc Ian Rogers
2024-06-03 16:58     ` Adrian Hunter
2024-06-10 12:20       ` Athira Rajeev
2024-06-11 16:29         ` Adrian Hunter
2024-06-08  7:05     ` Athira Rajeev
2024-06-01  6:09 ` [PATCH V3 12/14] tools/perf: Add support to find global register variables using find_data_type_global_reg Athira Rajeev
2024-06-01  6:09 ` [PATCH V3 13/14] tools/perf: Add support for global_die to capture name of variable in case of register defined variable Athira Rajeev
2024-06-01  6:09 ` [PATCH V3 14/14] tools/perf: Set instruction name to be used with insn-stat when using raw instruction Athira Rajeev

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20240601060941.13692-12-atrajeev@linux.vnet.ibm.com \
    --to=atrajeev@linux.vnet.ibm.com \
    --cc=acme@kernel.org \
    --cc=adrian.hunter@intel.com \
    --cc=akanksha@linux.ibm.com \
    --cc=christophe.leroy@csgroup.eu \
    --cc=disgoel@linux.vnet.ibm.com \
    --cc=irogers@google.com \
    --cc=jolsa@kernel.org \
    --cc=kjain@linux.ibm.com \
    --cc=linux-kernel@vger.kernel.org \
    --cc=linux-perf-users@vger.kernel.org \
    --cc=linuxppc-dev@lists.ozlabs.org \
    --cc=maddy@linux.ibm.com \
    --cc=namhyung@kernel.org \
    --cc=segher@kernel.crashing.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).