[ktap] [PATCH 2/4] symbol: add helpers for sdt probes.

  • From: Azat Khuzhin <a3at.mail@xxxxxxxxx>
  • To: ktap@xxxxxxxxxxxxx
  • Date: Sat, 9 Nov 2013 23:44:02 +0400

Next helpers was added:
- search_stapsdt_note()
- sdt_note_data()
- sdt_note_name()
- sdt_note_addr()

Based on this patch set: https://lkml.org/lkml/2013/10/23/10

Signed-off-by: Azat Khuzhin <a3at.mail@xxxxxxxxx>
---
 userspace/symbol.c | 108 +++++++++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 108 insertions(+)

diff --git a/userspace/symbol.c b/userspace/symbol.c
index dfbc40d..b7f677c 100644
--- a/userspace/symbol.c
+++ b/userspace/symbol.c
@@ -114,6 +114,114 @@ static vaddr_t search_symbol(Elf *elf, const char *symbol)
        return 0;
 }
 
+#define SDT_NOTE_TYPE 3
+#define SDT_NOTE_COUNT 3
+#define SDT_NOTE_SCN ".note.stapsdt"
+#define SDT_NOTE_NAME "stapsdt"
+
+static vaddr_t sdt_note_addr(Elf *elf, const char *data, size_t len, int type)
+{
+       vaddr_t vaddr;
+
+       /*
+        * dst and src are required for translation from file to memory
+        * representation
+        */
+       Elf_Data dst = {
+               .d_buf = &vaddr, .d_type = ELF_T_ADDR, .d_version = EV_CURRENT,
+               .d_size = gelf_fsize(elf, ELF_T_ADDR, SDT_NOTE_COUNT, 
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
+       };
+
+       /* Check the type of each of the notes */
+       if (type != SDT_NOTE_TYPE)
+               return 0;
+
+       if (len < dst.d_size + SDT_NOTE_COUNT)
+               return 0;
+
+       /* Translation from file representation to memory representation */
+       if (gelf_xlatetom(elf, &dst, &src,
+                         elf_getident(elf, NULL)[EI_DATA]) == NULL)
+               return 0; /* TODO */
+
+       return vaddr;
+}
+
+static const char *sdt_note_name(Elf *elf, GElf_Nhdr *nhdr, const char *data)
+{
+       const char *provider = data + gelf_fsize(elf,
+               ELF_T_ADDR, SDT_NOTE_COUNT, EV_CURRENT);
+       const char *name = (const char *)memchr(provider, '\0',
+               data + nhdr->n_descsz - provider);
+
+       if (name++ == NULL)
+               return NULL;
+
+       return name;
+}
+
+static const char *sdt_note_data(const Elf_Data *data, size_t off)
+{
+       return ((data->d_buf) + off);
+}
+
+static vaddr_t search_stapsdt_note(Elf *elf, const char *note)
+{
+       GElf_Ehdr ehdr;
+       Elf_Scn *scn = NULL;
+       Elf_Data *data;
+       GElf_Shdr shdr;
+       size_t shstrndx;
+       size_t next;
+       GElf_Nhdr nhdr;
+       size_t name_off, desc_off, offset;
+       vaddr_t vaddr = 0;
+
+       if (gelf_getehdr(elf, &ehdr) == NULL)
+               return 0;
+       if (elf_getshdrstrndx(elf, &shstrndx) != 0)
+               return 0;
+
+       /*
+        * Look for section type = SHT_NOTE, flags = no SHF_ALLOC
+        * and name = .note.stapsdt
+        */
+       scn = elf_section_by_name(elf, &ehdr, &shdr, SDT_NOTE_SCN);
+       if (!scn)
+               return 0;
+       if (!(shdr.sh_type == SHT_NOTE) || (shdr.sh_flags & SHF_ALLOC))
+               return 0;
+
+       data = elf_getdata(scn, NULL);
+
+       for (offset = 0;
+               (next = gelf_getnote(data, offset, &nhdr, &name_off, 
&desc_off)) > 0;
+               offset = next) {
+               const char *name;
+
+               if (nhdr.n_namesz != sizeof(SDT_NOTE_NAME) ||
+                   memcmp(data->d_buf + name_off, SDT_NOTE_NAME,
+                           sizeof(SDT_NOTE_NAME)))
+                       continue;
+
+               name = sdt_note_name(elf, &nhdr, sdt_note_data(data, desc_off));
+               if (!name || strcmp(name, note))
+                       continue;
+
+               vaddr = sdt_note_addr(elf, sdt_note_data(data, desc_off),
+                                       nhdr.n_descsz, nhdr.n_type);
+       }
+
+       return vaddr;
+}
+
 vaddr_t find_symbol(const char *exec, const char *symbol)
 {
        vaddr_t vaddr = 0;
-- 
1.8.4.rc3


Other related posts:

  • » [ktap] [PATCH 2/4] symbol: add helpers for sdt probes. - Azat Khuzhin