aboutsummaryrefslogtreecommitdiffstats
path: root/tools/perf/util/probe-file.c
diff options
context:
space:
mode:
authorAlexis Berlemont <alexis.berlemont@gmail.com>2016-12-13 19:07:32 -0500
committerArnaldo Carvalho de Melo <acme@redhat.com>2017-03-21 09:59:01 -0400
commit3b1f8311f6963cd11a7d1efbcd2fd900d472ba5c (patch)
treeb50763efb47b2dff1488ee22188c389a0515de14 /tools/perf/util/probe-file.c
parentbe88184b1c7054719296387c6063748fb48fa645 (diff)
perf probe: Add sdt probes arguments into the uprobe cmd string
An sdt probe can be associated with arguments but they were not passed to the user probe tracing interface (uprobe_events); this patch adapts the sdt argument descriptors according to the uprobe input format. As the uprobe parser does not support scaled address mode, perf will skip arguments which cannot be adapted to the uprobe format. Here are the results: $ perf buildid-cache -v --add test_sdt $ perf probe -x test_sdt sdt_libfoo:table_frob $ perf probe -x test_sdt sdt_libfoo:table_diddle $ perf record -e sdt_libfoo:table_frob -e sdt_libfoo:table_diddle test_sdt $ perf script test_sdt ... 666.255678: sdt_libfoo:table_frob: (4004d7) arg0=0 arg1=0 test_sdt ... 666.255683: sdt_libfoo:table_diddle: (40051a) arg0=0 arg1=0 test_sdt ... 666.255686: sdt_libfoo:table_frob: (4004d7) arg0=1 arg1=2 test_sdt ... 666.255689: sdt_libfoo:table_diddle: (40051a) arg0=3 arg1=4 test_sdt ... 666.255692: sdt_libfoo:table_frob: (4004d7) arg0=2 arg1=4 test_sdt ... 666.255694: sdt_libfoo:table_diddle: (40051a) arg0=6 arg1=8 Signed-off-by: Alexis Berlemont <alexis.berlemont@gmail.com> Acked-by: Masami Hiramatsu <mhiramat@kernel.org> Cc: Alexander Shishkin <alexander.shishkin@linux.intel.com> Cc: Hemant Kumar <hemant@linux.vnet.ibm.com> Cc: Peter Zijlstra <peterz@infradead.org> Cc: Ravi Bangoria <ravi.bangoria@linux.vnet.ibm.com> Link: http://lkml.kernel.org/r/20161214000732.1710-3-alexis.berlemont@gmail.com Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
Diffstat (limited to 'tools/perf/util/probe-file.c')
-rw-r--r--tools/perf/util/probe-file.c170
1 files changed, 166 insertions, 4 deletions
diff --git a/tools/perf/util/probe-file.c b/tools/perf/util/probe-file.c
index c3c287125be5..d741634cbfc0 100644
--- a/tools/perf/util/probe-file.c
+++ b/tools/perf/util/probe-file.c
@@ -27,6 +27,7 @@
27#include "probe-event.h" 27#include "probe-event.h"
28#include "probe-file.h" 28#include "probe-file.h"
29#include "session.h" 29#include "session.h"
30#include "perf_regs.h"
30 31
31/* 4096 - 2 ('\n' + '\0') */ 32/* 4096 - 2 ('\n' + '\0') */
32#define MAX_CMDLEN 4094 33#define MAX_CMDLEN 4094
@@ -688,6 +689,166 @@ static unsigned long long sdt_note__get_addr(struct sdt_note *note)
688 : (unsigned long long)note->addr.a64[0]; 689 : (unsigned long long)note->addr.a64[0];
689} 690}
690 691
692static const char * const type_to_suffix[] = {
693 ":s64", "", "", "", ":s32", "", ":s16", ":s8",
694 "", ":u8", ":u16", "", ":u32", "", "", "", ":u64"
695};
696
697static int synthesize_sdt_probe_arg(struct strbuf *buf, int i, const char *arg)
698{
699 char *tmp, *desc = strdup(arg);
700 const char *prefix = "", *suffix = "";
701 int ret = -1;
702
703 if (desc == NULL) {
704 pr_debug4("Allocation error\n");
705 return ret;
706 }
707
708 tmp = strchr(desc, '@');
709 if (tmp) {
710 long type_idx;
711 /*
712 * Isolate the string number and convert it into a
713 * binary value; this will be an index to get suffix
714 * of the uprobe name (defining the type)
715 */
716 tmp[0] = '\0';
717 type_idx = strtol(desc, NULL, 10);
718 /* Check that the conversion went OK */
719 if (type_idx == LONG_MIN || type_idx == LONG_MAX) {
720 pr_debug4("Failed to parse sdt type\n");
721 goto error;
722 }
723 /* Check that the converted value is OK */
724 if (type_idx < -8 || type_idx > 8) {
725 pr_debug4("Failed to get a valid sdt type\n");
726 goto error;
727 }
728 suffix = type_to_suffix[type_idx + 8];
729 /* Get rid of the sdt prefix which is now useless */
730 tmp++;
731 memmove(desc, tmp, strlen(tmp) + 1);
732 }
733
734 /*
735 * The uprobe tracer format does not support all the
736 * addressing modes (notably: in x86 the scaled mode); so, we
737 * detect ',' characters, if there is just one, there is no
738 * use converting the sdt arg into a uprobe one.
739 */
740 if (strchr(desc, ',')) {
741 pr_debug4("Skipping unsupported SDT argument; %s\n", desc);
742 goto out;
743 }
744
745 /*
746 * If the argument addressing mode is indirect, we must check
747 * a few things...
748 */
749 tmp = strchr(desc, '(');
750 if (tmp) {
751 int j;
752
753 /*
754 * ...if the addressing mode is indirect with a
755 * positive offset (ex.: "1608(%ax)"), we need to add
756 * a '+' prefix so as to be compliant with uprobe
757 * format.
758 */
759 if (desc[0] != '+' && desc[0] != '-')
760 prefix = "+";
761
762 /*
763 * ...or if the addressing mode is indirect with a symbol
764 * as offset, the argument will not be supported by
765 * the uprobe tracer format; so, let's skip this one.
766 */
767 for (j = 0; j < tmp - desc; j++) {
768 if (desc[j] != '+' && desc[j] != '-' &&
769 !isdigit(desc[j])) {
770 pr_debug4("Skipping unsupported SDT argument; "
771 "%s\n", desc);
772 goto out;
773 }
774 }
775 }
776
777 /*
778 * The uprobe tracer format does not support constants; if we
779 * find one in the current argument, let's skip the argument.
780 */
781 if (strchr(desc, '$')) {
782 pr_debug4("Skipping unsupported SDT argument; %s\n", desc);
783 goto out;
784 }
785
786 /*
787 * The uprobe parser does not support all gas register names;
788 * so, we have to replace them (ex. for x86_64: %rax -> %ax);
789 * the loop below looks for the register names (starting with
790 * a '%' and tries to perform the needed renamings.
791 */
792 tmp = strchr(desc, '%');
793 while (tmp) {
794 size_t offset = tmp - desc;
795
796 ret = sdt_rename_register(&desc, desc + offset);
797 if (ret < 0)
798 goto error;
799
800 /*
801 * The desc pointer might have changed; so, let's not
802 * try to reuse tmp for next lookup
803 */
804 tmp = strchr(desc + offset + 1, '%');
805 }
806
807 if (strbuf_addf(buf, " arg%d=%s%s%s", i + 1, prefix, desc, suffix) < 0)
808 goto error;
809
810out:
811 ret = 0;
812error:
813 free(desc);
814 return ret;
815}
816
817static char *synthesize_sdt_probe_command(struct sdt_note *note,
818 const char *pathname,
819 const char *sdtgrp)
820{
821 struct strbuf buf;
822 char *ret = NULL, **args;
823 int i, args_count;
824
825 if (strbuf_init(&buf, 32) < 0)
826 return NULL;
827
828 if (strbuf_addf(&buf, "p:%s/%s %s:0x%llx",
829 sdtgrp, note->name, pathname,
830 sdt_note__get_addr(note)) < 0)
831 goto error;
832
833 if (!note->args)
834 goto out;
835
836 if (note->args) {
837 args = argv_split(note->args, &args_count);
838
839 for (i = 0; i < args_count; ++i) {
840 if (synthesize_sdt_probe_arg(&buf, i, args[i]) < 0)
841 goto error;
842 }
843 }
844
845out:
846 ret = strbuf_detach(&buf, NULL);
847error:
848 strbuf_release(&buf);
849 return ret;
850}
851
691int probe_cache__scan_sdt(struct probe_cache *pcache, const char *pathname) 852int probe_cache__scan_sdt(struct probe_cache *pcache, const char *pathname)
692{ 853{
693 struct probe_cache_entry *entry = NULL; 854 struct probe_cache_entry *entry = NULL;
@@ -724,11 +885,12 @@ int probe_cache__scan_sdt(struct probe_cache *pcache, const char *pathname)
724 entry->pev.group = strdup(sdtgrp); 885 entry->pev.group = strdup(sdtgrp);
725 list_add_tail(&entry->node, &pcache->entries); 886 list_add_tail(&entry->node, &pcache->entries);
726 } 887 }
727 ret = asprintf(&buf, "p:%s/%s %s:0x%llx", 888 buf = synthesize_sdt_probe_command(note, pathname, sdtgrp);
728 sdtgrp, note->name, pathname, 889 if (!buf) {
729 sdt_note__get_addr(note)); 890 ret = -ENOMEM;
730 if (ret < 0)
731 break; 891 break;
892 }
893
732 strlist__add(entry->tevlist, buf); 894 strlist__add(entry->tevlist, buf);
733 free(buf); 895 free(buf);
734 entry = NULL; 896 entry = NULL;