unlink(kce->extract_filename);
 }
 
+/**
+ * populate_sdt_note : Parse raw data and identify SDT note
+ * @elf: elf of the opened file
+ * @data: raw data of a section with description offset applied
+ * @len: note description size
+ * @type: type of the note
+ * @sdt_notes: List to add the SDT note
+ *
+ * Responsible for parsing the @data in section .note.stapsdt in @elf and
+ * if its an SDT note, it appends to @sdt_notes list.
+ */
+static int populate_sdt_note(Elf **elf, const char *data, size_t len,
+                            struct list_head *sdt_notes)
+{
+       const char *provider, *name;
+       struct sdt_note *tmp = NULL;
+       GElf_Ehdr ehdr;
+       GElf_Addr base_off = 0;
+       GElf_Shdr shdr;
+       int ret = -EINVAL;
+
+       union {
+               Elf64_Addr a64[NR_ADDR];
+               Elf32_Addr a32[NR_ADDR];
+       } buf;
+
+       Elf_Data dst = {
+               .d_buf = &buf, .d_type = ELF_T_ADDR, .d_version = EV_CURRENT,
+               .d_size = gelf_fsize((*elf), ELF_T_ADDR, NR_ADDR, 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
+       };
+
+       tmp = (struct sdt_note *)calloc(1, sizeof(struct sdt_note));
+       if (!tmp) {
+               ret = -ENOMEM;
+               goto out_err;
+       }
+
+       INIT_LIST_HEAD(&tmp->note_list);
+
+       if (len < dst.d_size + 3)
+               goto out_free_note;
+
+       /* Translation from file representation to memory representation */
+       if (gelf_xlatetom(*elf, &dst, &src,
+                         elf_getident(*elf, NULL)[EI_DATA]) == NULL) {
+               pr_err("gelf_xlatetom : %s\n", elf_errmsg(-1));
+               goto out_free_note;
+       }
+
+       /* 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_free_note;
+
+       tmp->provider = strdup(provider);
+       if (!tmp->provider) {
+               ret = -ENOMEM;
+               goto out_free_note;
+       }
+       tmp->name = strdup(name);
+       if (!tmp->name) {
+               ret = -ENOMEM;
+               goto out_free_prov;
+       }
+
+       if (gelf_getclass(*elf) == ELFCLASS32) {
+               memcpy(&tmp->addr, &buf, 3 * sizeof(Elf32_Addr));
+               tmp->bit32 = true;
+       } else {
+               memcpy(&tmp->addr, &buf, 3 * sizeof(Elf64_Addr));
+               tmp->bit32 = false;
+       }
+
+       if (!gelf_getehdr(*elf, &ehdr)) {
+               pr_debug("%s : cannot get elf header.\n", __func__);
+               ret = -EBADF;
+               goto out_free_name;
+       }
+
+       /* Adjust the prelink effect :
+        * Find out the .stapsdt.base section.
+        * This scn will help us to handle prelinking (if present).
+        * Compare the retrieved file offset of the base section with the
+        * base address in the description of the SDT note. If its different,
+        * then accordingly, adjust the note location.
+        */
+       if (elf_section_by_name(*elf, &ehdr, &shdr, SDT_BASE_SCN, NULL)) {
+               base_off = shdr.sh_offset;
+               if (base_off) {
+                       if (tmp->bit32)
+                               tmp->addr.a32[0] = tmp->addr.a32[0] + base_off -
+                                       tmp->addr.a32[1];
+                       else
+                               tmp->addr.a64[0] = tmp->addr.a64[0] + base_off -
+                                       tmp->addr.a64[1];
+               }
+       }
+
+       list_add_tail(&tmp->note_list, sdt_notes);
+       return 0;
+
+out_free_name:
+       free(tmp->name);
+out_free_prov:
+       free(tmp->provider);
+out_free_note:
+       free(tmp);
+out_err:
+       return ret;
+}
+
+/**
+ * construct_sdt_notes_list : constructs a list of SDT notes
+ * @elf : elf to look into
+ * @sdt_notes : empty list_head
+ *
+ * Scans the sections in 'elf' for the section
+ * .note.stapsdt. It, then calls populate_sdt_note to find
+ * out the SDT events and populates the 'sdt_notes'.
+ */
+static int construct_sdt_notes_list(Elf *elf, struct list_head *sdt_notes)
+{
+       GElf_Ehdr ehdr;
+       Elf_Scn *scn = NULL;
+       Elf_Data *data;
+       GElf_Shdr shdr;
+       size_t shstrndx, next;
+       GElf_Nhdr nhdr;
+       size_t name_off, desc_off, offset;
+       int ret = 0;
+
+       if (gelf_getehdr(elf, &ehdr) == NULL) {
+               ret = -EBADF;
+               goto out_ret;
+       }
+       if (elf_getshdrstrndx(elf, &shstrndx) != 0) {
+               ret = -EBADF;
+               goto out_ret;
+       }
+
+       /* Look for the required section */
+       scn = elf_section_by_name(elf, &ehdr, &shdr, SDT_NOTE_SCN, NULL);
+       if (!scn) {
+               ret = -ENOENT;
+               goto out_ret;
+       }
+
+       if ((shdr.sh_type != SHT_NOTE) || (shdr.sh_flags & SHF_ALLOC)) {
+               ret = -ENOENT;
+               goto out_ret;
+       }
+
+       data = elf_getdata(scn, NULL);
+
+       /* Get the SDT notes */
+       for (offset = 0; (next = gelf_getnote(data, offset, &nhdr, &name_off,
+                                             &desc_off)) > 0; offset = next) {
+               if (nhdr.n_namesz == sizeof(SDT_NOTE_NAME) &&
+                   !memcmp(data->d_buf + name_off, SDT_NOTE_NAME,
+                           sizeof(SDT_NOTE_NAME))) {
+                       /* Check the type of the note */
+                       if (nhdr.n_type != SDT_NOTE_TYPE)
+                               goto out_ret;
+
+                       ret = populate_sdt_note(&elf, ((data->d_buf) + desc_off),
+                                               nhdr.n_descsz, sdt_notes);
+                       if (ret < 0)
+                               goto out_ret;
+               }
+       }
+       if (list_empty(sdt_notes))
+               ret = -ENOENT;
+
+out_ret:
+       return ret;
+}
+
+/**
+ * get_sdt_note_list : Wrapper to construct a list of sdt notes
+ * @head : empty list_head
+ * @target : file to find SDT notes from
+ *
+ * This opens the file, initializes
+ * the ELF and then calls construct_sdt_notes_list.
+ */
+int get_sdt_note_list(struct list_head *head, const char *target)
+{
+       Elf *elf;
+       int fd, ret;
+
+       fd = open(target, O_RDONLY);
+       if (fd < 0)
+               return -EBADF;
+
+       elf = elf_begin(fd, PERF_ELF_C_READ_MMAP, NULL);
+       if (!elf) {
+               ret = -EBADF;
+               goto out_close;
+       }
+       ret = construct_sdt_notes_list(elf, head);
+       elf_end(elf);
+out_close:
+       close(fd);
+       return ret;
+}
+
+/**
+ * cleanup_sdt_note_list : free the sdt notes' list
+ * @sdt_notes: sdt notes' list
+ *
+ * Free up the SDT notes in @sdt_notes.
+ * Returns the number of SDT notes free'd.
+ */
+int cleanup_sdt_note_list(struct list_head *sdt_notes)
+{
+       struct sdt_note *tmp, *pos;
+       int nr_free = 0;
+
+       list_for_each_entry_safe(pos, tmp, sdt_notes, note_list) {
+               list_del(&pos->note_list);
+               free(pos->name);
+               free(pos->provider);
+               free(pos);
+               nr_free++;
+       }
+       return nr_free;
+}
+
+/**
+ * sdt_notes__get_count: Counts the number of sdt events
+ * @start: list_head to sdt_notes list
+ *
+ * Returns the number of SDT notes in a list
+ */
+int sdt_notes__get_count(struct list_head *start)
+{
+       struct sdt_note *sdt_ptr;
+       int count = 0;
+
+       list_for_each_entry(sdt_ptr, start, note_list)
+               count++;
+       return count;
+}
+
 void symbol__elf_init(void)
 {
        elf_version(EV_CURRENT);