|
@@ -434,12 +434,15 @@ static int probe_cache__load(struct probe_cache *pcache)
|
|
p = strchr(buf, '\n');
|
|
p = strchr(buf, '\n');
|
|
if (p)
|
|
if (p)
|
|
*p = '\0';
|
|
*p = '\0';
|
|
- if (buf[0] == '#') { /* #perf_probe_event */
|
|
|
|
|
|
+ /* #perf_probe_event or %sdt_event */
|
|
|
|
+ if (buf[0] == '#' || buf[0] == '%') {
|
|
entry = probe_cache_entry__new(NULL);
|
|
entry = probe_cache_entry__new(NULL);
|
|
if (!entry) {
|
|
if (!entry) {
|
|
ret = -ENOMEM;
|
|
ret = -ENOMEM;
|
|
goto out;
|
|
goto out;
|
|
}
|
|
}
|
|
|
|
+ if (buf[0] == '%')
|
|
|
|
+ entry->sdt = true;
|
|
entry->spev = strdup(buf + 1);
|
|
entry->spev = strdup(buf + 1);
|
|
if (entry->spev)
|
|
if (entry->spev)
|
|
ret = parse_perf_probe_command(buf + 1,
|
|
ret = parse_perf_probe_command(buf + 1,
|
|
@@ -621,19 +624,79 @@ out_err:
|
|
return ret;
|
|
return ret;
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+static unsigned long long sdt_note__get_addr(struct sdt_note *note)
|
|
|
|
+{
|
|
|
|
+ return note->bit32 ? (unsigned long long)note->addr.a32[0]
|
|
|
|
+ : (unsigned long long)note->addr.a64[0];
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+int probe_cache__scan_sdt(struct probe_cache *pcache, const char *pathname)
|
|
|
|
+{
|
|
|
|
+ struct probe_cache_entry *entry = NULL;
|
|
|
|
+ struct list_head sdtlist;
|
|
|
|
+ struct sdt_note *note;
|
|
|
|
+ char *buf;
|
|
|
|
+ char sdtgrp[64];
|
|
|
|
+ int ret;
|
|
|
|
+
|
|
|
|
+ INIT_LIST_HEAD(&sdtlist);
|
|
|
|
+ ret = get_sdt_note_list(&sdtlist, pathname);
|
|
|
|
+ if (ret < 0) {
|
|
|
|
+ pr_debug("Failed to get sdt note: %d\n", ret);
|
|
|
|
+ return ret;
|
|
|
|
+ }
|
|
|
|
+ list_for_each_entry(note, &sdtlist, note_list) {
|
|
|
|
+ ret = snprintf(sdtgrp, 64, "sdt_%s", note->provider);
|
|
|
|
+ if (ret < 0)
|
|
|
|
+ break;
|
|
|
|
+ /* Try to find same-name entry */
|
|
|
|
+ entry = probe_cache__find_by_name(pcache, sdtgrp, note->name);
|
|
|
|
+ if (!entry) {
|
|
|
|
+ entry = probe_cache_entry__new(NULL);
|
|
|
|
+ if (!entry) {
|
|
|
|
+ ret = -ENOMEM;
|
|
|
|
+ break;
|
|
|
|
+ }
|
|
|
|
+ entry->sdt = true;
|
|
|
|
+ ret = asprintf(&entry->spev, "%s:%s=%s", sdtgrp,
|
|
|
|
+ note->name, note->name);
|
|
|
|
+ if (ret < 0)
|
|
|
|
+ break;
|
|
|
|
+ entry->pev.event = strdup(note->name);
|
|
|
|
+ entry->pev.group = strdup(sdtgrp);
|
|
|
|
+ list_add_tail(&entry->node, &pcache->entries);
|
|
|
|
+ }
|
|
|
|
+ ret = asprintf(&buf, "p:%s/%s %s:0x%llx",
|
|
|
|
+ sdtgrp, note->name, pathname,
|
|
|
|
+ sdt_note__get_addr(note));
|
|
|
|
+ if (ret < 0)
|
|
|
|
+ break;
|
|
|
|
+ strlist__add(entry->tevlist, buf);
|
|
|
|
+ free(buf);
|
|
|
|
+ entry = NULL;
|
|
|
|
+ }
|
|
|
|
+ if (entry) {
|
|
|
|
+ list_del_init(&entry->node);
|
|
|
|
+ probe_cache_entry__delete(entry);
|
|
|
|
+ }
|
|
|
|
+ cleanup_sdt_note_list(&sdtlist);
|
|
|
|
+ return ret;
|
|
|
|
+}
|
|
|
|
+
|
|
static int probe_cache_entry__write(struct probe_cache_entry *entry, int fd)
|
|
static int probe_cache_entry__write(struct probe_cache_entry *entry, int fd)
|
|
{
|
|
{
|
|
struct str_node *snode;
|
|
struct str_node *snode;
|
|
struct stat st;
|
|
struct stat st;
|
|
struct iovec iov[3];
|
|
struct iovec iov[3];
|
|
|
|
+ const char *prefix = entry->sdt ? "%" : "#";
|
|
int ret;
|
|
int ret;
|
|
/* Save stat for rollback */
|
|
/* Save stat for rollback */
|
|
ret = fstat(fd, &st);
|
|
ret = fstat(fd, &st);
|
|
if (ret < 0)
|
|
if (ret < 0)
|
|
return ret;
|
|
return ret;
|
|
|
|
|
|
- pr_debug("Writing cache: #%s\n", entry->spev);
|
|
|
|
- iov[0].iov_base = (void *)"#"; iov[0].iov_len = 1;
|
|
|
|
|
|
+ pr_debug("Writing cache: %s%s\n", prefix, entry->spev);
|
|
|
|
+ iov[0].iov_base = (void *)prefix; iov[0].iov_len = 1;
|
|
iov[1].iov_base = entry->spev; iov[1].iov_len = strlen(entry->spev);
|
|
iov[1].iov_base = entry->spev; iov[1].iov_len = strlen(entry->spev);
|
|
iov[2].iov_base = (void *)"\n"; iov[2].iov_len = 1;
|
|
iov[2].iov_base = (void *)"\n"; iov[2].iov_len = 1;
|
|
ret = writev(fd, iov, 3);
|
|
ret = writev(fd, iov, 3);
|