All of lore.kernel.org
 help / color / mirror / Atom feed
From: Hemant <hkshaw@linux.vnet.ibm.com>
To: linux-kernel@vger.kernel.org
Cc: srikar@linux.vnet.ibm.com, peterz@infradead.org, oleg@redhat.com,
	mingo@redhat.com, anton@redhat.com, systemtap@sourceware.org,
	masami.hiramatsu.pt@hitachi.com,
	Aravinda Prasad <aravinda@linux.vnet.ibm.com>,
	Vasant Hegde <hegdevasant@linux.vnet.ibm.com>
Subject: Re: [PATCH 1/2] SDT markers listing by perf
Date: Tue, 03 Sep 2013 13:49:35 +0530	[thread overview]
Message-ID: <52259B97.9010701@linux.vnet.ibm.com> (raw)
In-Reply-To: <20130903073655.4793.20013.stgit@hemant-fedora>

On 09/03/2013 01:06 PM, Hemant Kumar wrote:
> This patch will enable perf to list all the sdt markers present
> in an elf file. The markers are present in the .note.stapsdt section
> of the elf. We can traverse through this section and collect the
> required info about the markers.
> This hasn't been thoroughly tested with the other
> options of perf.
> ----
> Usage :
> ./perf probe --list -x /lib64/libc.so.6

There is a mismatch between usage and the patch here. This should be:
perf probe --list -S /lib64/libc.so.6

>
> Output :
> setjmp
> longjmp
> longjmp_target
> lll_futex_wake
> lll_lock_wait_private
> longjmp
> longjmp_target
> lll_futex_wake
>
> Total markers = 8

And the correct Output should be :

libc:setjmp
libc:longjmp
libc:longjmp_target
libc:lll_futex_wake
libc:lll_lock_wait_private
libc:longjmp
libc:longjmp_target
libc:lll_futex_wake

Total markers = 8

> ----
> Signed-off-by: Hemant Kumar Shaw <hkshaw@linux.vnet.ibm.com>
> ---
>   tools/perf/builtin-probe.c    |   26 +++++
>   tools/perf/util/probe-event.c |    6 +
>   tools/perf/util/symbol-elf.c  |  205 +++++++++++++++++++++++++++++++++++++++++
>   tools/perf/util/symbol.h      |   19 ++++
>   4 files changed, 256 insertions(+)
>
> diff --git a/tools/perf/builtin-probe.c b/tools/perf/builtin-probe.c
> index e8a66f9..3d8dcdf 100644
> --- a/tools/perf/builtin-probe.c
> +++ b/tools/perf/builtin-probe.c
> @@ -55,6 +55,7 @@ static struct {
>   	bool show_funcs;
>   	bool mod_events;
>   	bool uprobes;
> +	bool sdt;
>   	int nevents;
>   	struct perf_probe_event events[MAX_PROBES];
>   	struct strlist *dellist;
> @@ -325,6 +326,8 @@ int cmd_probe(int argc, const char **argv, const char *prefix __maybe_unused)
>   		     opt_set_filter),
>   	OPT_CALLBACK('x', "exec", NULL, "executable|path",
>   			"target executable name or path", opt_set_target),
> +	OPT_BOOLEAN('S', "sdt", &params.sdt,
> +		    "Show and probe on the SDT markers"),
>   	OPT_END()
>   	};
>   	int ret;
> @@ -355,6 +358,28 @@ int cmd_probe(int argc, const char **argv, const char *prefix __maybe_unused)
>   	 */
>   	symbol_conf.try_vmlinux_path = (symbol_conf.vmlinux_name == NULL);
>
> +	if (params.sdt) {
> +		if (params.show_lines) {
> +			pr_err("  Error: Don't use --sdt with --line.\n");
> +			usage_with_options(probe_usage, options);
> +		}
> +		if (params.show_vars) {
> +			pr_err(" Error: Don't use --sdt with --vars.\n");
> +			usage_with_options(probe_usage, options);
> +		}
> +		if (params.show_funcs) {
> +			pr_err("  Error: Don't use --sdt with --funcs.\n");
> +			usage_with_options(probe_usage, options);
> +		}
> +		if (params.list_events) {
> +			ret = show_available_markers(params.target);
> +			if (ret < 0)
> +				pr_err("  Error: Failed to show markers."
> +				       " (%d)\n", ret);
> +			return ret;
> +		}
> +	}
> +
>   	if (params.list_events) {
>   		if (params.mod_events) {
>   			pr_err("  Error: Don't use --list with --add/--del.\n");
> @@ -382,6 +407,7 @@ int cmd_probe(int argc, const char **argv, const char *prefix __maybe_unused)
>   			       ret);
>   		return ret;
>   	}
> +
>   	if (params.show_funcs) {
>   		if (params.nevents != 0 || params.dellist) {
>   			pr_err("  Error: Don't use --funcs with"
> diff --git a/tools/perf/util/probe-event.c b/tools/perf/util/probe-event.c
> index aa04bf9..7f846f9 100644
> --- a/tools/perf/util/probe-event.c
> +++ b/tools/perf/util/probe-event.c
> @@ -2372,3 +2372,9 @@ out:
>   		free(name);
>   	return ret;
>   }
> +
> +int show_available_markers(const char *target)
> +{
> +	setup_pager();
> +	return list_markers(target);
> +}
> diff --git a/tools/perf/util/symbol-elf.c b/tools/perf/util/symbol-elf.c
> index 4b12bf8..f3630f2 100644
> --- a/tools/perf/util/symbol-elf.c
> +++ b/tools/perf/util/symbol-elf.c
> @@ -846,6 +846,211 @@ out_elf_end:
>   	return err;
>   }
>
> +/* Populate the name, type, offset and argument fields in the note structure */
> +static struct sdt_note *populate_note(Elf **elf, const char *data, size_t len,
> +				      int type)
> +{
> +	const char *provider, *name, *args;
> +	struct sdt_note *note;
> +
> +	/*
> +	 * There are 3 address values to be obtained: marker offset, base address
> +	 * and semaphore
> +	 */
> +	union {
> +		Elf64_Addr a64[3];
> +		Elf32_Addr a32[3];
> +	} buf;
> +
> +	/*
> +	 * dst and src (of Elf_Data) are required for translation from file
> +	 * to memory representation
> +	 */
> +	Elf_Data dst = {
> +		.d_buf = &buf, .d_type = ELF_T_ADDR, .d_version = EV_CURRENT,
> +		.d_size = gelf_fsize((*elf), ELF_T_ADDR, 3, EV_CURRENT),
> +		.d_off = 0, .d_align = 0
> +	};
> +
> +	Elf_Data src = {
> +		.d_buf = (void *) data, .d_type = ELF_T_ADDR,
> +		.d_version = EV_CURRENT, .d_size = dst.d_size, .d_off = 0,
> +		.d_align = 0
> +	};
> +
> +	if (type != SDT_NOTE_TYPE)
> +		goto out_ret;
> +
> +	note = zalloc(sizeof(struct sdt_note));
> +	if (note == NULL) {
> +		pr_err("memory allocation error\n");
> +		goto out_ret;
> +	}
> +	note->next = NULL;
> +
> +	if (len < dst.d_size + 3)
> +		goto out_free;
> +	/*
> +	 * Translating from file representation to memory representation
> +	 * Data now points to the address (offset)
> +	 */
> +	if (gelf_xlatetom((*elf), &dst, &src,
> +			  elf_getident((*elf), NULL)[EI_DATA]) == NULL)
> +		pr_debug("gelf_xlatetom : %s", elf_errmsg(-1));
> +
> +	/* Populate the fields of sdt_note */
> +	provider = data + dst.d_size;
> +
> +	name = (const char *)memchr(provider, '\0', data + len - provider);
> +	if (name++ == NULL)
> +		goto out_ret;
> +
> +	args = (const char *)memchr(name, '\0', data + len - name);
> +	if (args++ == NULL ||
> +	    memchr(args, '\0', data + len - name) != data + len - 1)
> +		goto out_ret;
> +	note->provider = provider;
> +	note->name = name;
> +
> +	/* Three addr's for location, base and semaphore addresses */
> +	note->addr.a64[0] = (buf.a64[0]);
> +	note->addr.a64[1] = (buf.a64[1]);
> +	note->addr.a64[2] = (buf.a64[2]);
> +	return note;
> +
> +out_free:
> +	free(note);
> +out_ret:
> +	return NULL;
> +}
> +
> +/*
> + * Traverse the elf of the object, find out the .note.stapsdt section
> + * and accordingly initialize the notes' list head
> + */
> +static struct sdt_note *get_elf_markers(Elf *elf, bool *exe, bool probe)
> +{
> +	Elf_Scn *scn = NULL;
> +	Elf_Data *data;
> +	GElf_Shdr shdr;
> +	GElf_Ehdr ehdr;
> +	size_t  shstrndx;
> +	size_t next;
> +	GElf_Nhdr nhdr;
> +	size_t name_off, desc_off, offset;
> +	struct sdt_note *note = NULL, *tmp, *head = NULL;
> +
> +	if (gelf_getehdr(elf, &ehdr) == NULL) {
> +		pr_debug("%s: cannot get elf header.\n", __func__);
> +		goto out_end;
> +	}
> +
> +	if (elf_getshdrstrndx(elf, &shstrndx) != 0) {
> +		pr_debug("getshdrstrndx failed\n");
> +		goto out_end;
> +	}
> +
> +	/* library or exec */
> +	if (probe) {
> +		if (ehdr.e_type == ET_EXEC)
> +			*exe = true;
> +	}
> +
> +	/*
> +	 * Look for Section type = SHT_NOTE, flags = no SHF_ALLOC
> +	 * and name = .note.stapsdt
> +	 */
> +	scn = elf_section_by_name(elf, &ehdr, &shdr, NOTE_SCN, NULL);
> +	if (scn == NULL) {
> +		pr_err("%s section not found!\n", NOTE_SCN);
> +		goto out_end;
> +	}
> +
> +	if (!(shdr.sh_type == SHT_NOTE) || (shdr.sh_flags & SHF_ALLOC))
> +		goto out_end;
> +
> +	data = elf_getdata(scn, NULL);
> +
> +	/* Get the notes */
> +	for (offset = 0; (next = gelf_getnote(data, offset, &nhdr, &name_off,
> +					      &desc_off)) > 0; offset = next) {
> +		tmp = populate_note(&elf, (const char *)((long)(data->d_buf) +
> +							 (long)desc_off),
> +				    nhdr.n_descsz, nhdr.n_type);
> +		/* For first note */
> +		if (!head) {
> +			note = tmp;
> +			head = note;
> +			continue;
> +		}
> +		note->next = tmp;
> +		note = note->next;
> +	}
> +
> +	if (!head)
> +		pr_err("No markers found\n");
> +
> +out_end:
> +	return head;
> +}
> +
> +static void print_notes(struct sdt_note *start)
> +{
> +	struct sdt_note *temp;
> +	int c;
> +
> +	for (temp = start, c = 0; temp != NULL; temp = temp->next, c++)
> +		printf("%s:%s\n", temp->provider, temp->name);
> +
> +	printf("\nTotal markers = %d\n", c);
> +}
> +
> +int list_markers(const char *name)
> +{
> +	int fd, ret = -1;
> +	Elf *elf;
> +	struct sdt_note *head = NULL;
> +
> +	fd = open(name, O_RDONLY);
> +	if (fd < 0) {
> +		pr_err("Failed to open %s\n", name);
> +		goto out_ret;
> +	}
> +
> +	symbol__elf_init();
> +	elf = elf_begin(fd, PERF_ELF_C_READ_MMAP, NULL);
> +	if (elf == NULL) {
> +		pr_err("%s: cannot read %s ELF file.\n", __func__, name);
> +		goto out_close;
> +	}
> +
> +	head = get_elf_markers(elf, NULL, false);
> +	if (head) {
> +		print_notes(head);
> +		cleanup_notes(head);
> +		ret = 0;
> +	} else {
> +		pr_err("No SDT markers found in %s\n", name);
> +	}
> +	elf_end(elf);
> +
> +out_close:
> +	close(fd);
> +out_ret:
> +	return ret;
> +}
> +
> +void cleanup_notes(struct sdt_note *start)
> +{
> +	struct sdt_note *tmp;
> +
> +	while (start) {
> +		tmp = start->next;
> +		free(start);
> +		start = tmp;
> +	}
> +}
> +
>   void symbol__elf_init(void)
>   {
>   	elf_version(EV_CURRENT);
> diff --git a/tools/perf/util/symbol.h b/tools/perf/util/symbol.h
> index 5f720dc..f2d17b7 100644
> --- a/tools/perf/util/symbol.h
> +++ b/tools/perf/util/symbol.h
> @@ -197,6 +197,17 @@ struct symsrc {
>   #endif
>   };
>
> +/* Note structure */
> +struct sdt_note {
> +	const char *name;
> +	const char *provider;
> +	union {
> +		Elf64_Addr a64[3];
> +		Elf32_Addr a32[3];
> +	} addr;
> +	struct sdt_note *next;
> +};
> +
>   void symsrc__destroy(struct symsrc *ss);
>   int symsrc__init(struct symsrc *ss, struct dso *dso, const char *name,
>   		 enum dso_binary_type type);
> @@ -247,4 +258,12 @@ void symbols__fixup_duplicate(struct rb_root *symbols);
>   void symbols__fixup_end(struct rb_root *symbols);
>   void __map_groups__fixup_end(struct map_groups *mg, enum map_type type);
>
> +/* For SDT markers */
> +int show_available_markers(const char *module);
> +int list_markers(const char *name);
> +void cleanup_notes(struct sdt_note *start);
> +
> +#define SDT_NOTE_TYPE 3
> +#define NOTE_SCN ".note.stapsdt"
> +
>   #endif /* __PERF_SYMBOL */
>
>


  reply	other threads:[~2013-09-03  8:19 UTC|newest]

Thread overview: 43+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2013-09-03  7:36 [RFC PATCH 0/2] Perf support to SDT markers Hemant Kumar Shaw
2013-09-03  7:36 ` [PATCH 1/2] SDT markers listing by perf Hemant Kumar
2013-09-03  8:19   ` Hemant [this message]
2013-09-04  6:43     ` Namhyung Kim
2013-09-04 17:40       ` Hemant
2013-09-04  6:42   ` Namhyung Kim
2013-09-04  8:01     ` Masami Hiramatsu
2013-09-04 17:58       ` Hemant
2013-09-15 11:28       ` Hemant
2013-09-25  4:37         ` Masami Hiramatsu
2013-09-25  6:03           ` Hemant
2013-09-25  8:45             ` Masami Hiramatsu
2013-09-04 17:37     ` Hemant
2013-09-06  6:37       ` Namhyung Kim
2013-09-06  8:41         ` Hemant
2013-09-04  7:21   ` Masami Hiramatsu
2013-09-04 17:52     ` Hemant
2013-09-03  7:37 ` [PATCH 2/2] Support to perf to probe on SDT markers: Hemant Kumar
2013-09-03  9:14   ` Masami Hiramatsu
2013-09-04  7:00   ` Namhyung Kim
2013-09-04  8:10     ` Masami Hiramatsu
2013-09-04 18:00       ` Hemant
2013-09-04 17:50     ` Hemant
2013-09-03  8:25 ` [RFC PATCH 0/2] Perf support to SDT markers Ingo Molnar
2013-09-03  9:17   ` Masami Hiramatsu
2013-09-03 13:23     ` Hemant
2013-09-03 14:21       ` Ingo Molnar
2013-09-03 15:11         ` Mark Wielaard
2013-09-03 19:24           ` Ingo Molnar
2013-09-03 15:24         ` Hemant
2013-09-04  6:49       ` Namhyung Kim
2013-09-04  8:22         ` Masami Hiramatsu
2013-09-04  8:25         ` Mark Wielaard
2013-09-04  8:39           ` Masami Hiramatsu
2013-09-04 18:08             ` Hemant
2013-09-05  4:59               ` Masami Hiramatsu
2013-09-04 18:12           ` Hemant
2013-09-04 18:52             ` Mark Wielaard
2013-09-04 20:39               ` Hemant
2013-09-04 17:45         ` Hemant
2013-09-04  6:08 ` Namhyung Kim
2013-09-04 17:08   ` Hemant
2013-09-04 23:41 ` Andi Kleen

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=52259B97.9010701@linux.vnet.ibm.com \
    --to=hkshaw@linux.vnet.ibm.com \
    --cc=anton@redhat.com \
    --cc=aravinda@linux.vnet.ibm.com \
    --cc=hegdevasant@linux.vnet.ibm.com \
    --cc=linux-kernel@vger.kernel.org \
    --cc=masami.hiramatsu.pt@hitachi.com \
    --cc=mingo@redhat.com \
    --cc=oleg@redhat.com \
    --cc=peterz@infradead.org \
    --cc=srikar@linux.vnet.ibm.com \
    --cc=systemtap@sourceware.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 an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.