- if (dwarf_offdie(dwarf, offset + length, &unit_die) != NULL) {
-
- // For each child DIE:
- Dwarf_Die child;
- int res;
- for (res = dwarf_child(&unit_die, &child); res == 0;
- res = dwarf_siblingof(&child, &child)) {
- MC_dwarf_handle_die(info, &child, &unit_die, NULL, NULL);
+ if (dwarf_offdie(dwarf, offset + length, &unit_die) != nullptr)
+ MC_dwarf_handle_children(info, &unit_die, &unit_die, nullptr, nullptr);
+ offset = next_offset;
+ }
+}
+
+/** Get the build-id (NT_GNU_BUILD_ID) from the ELF file
+ *
+ * This build-id may is used to locate an external debug (DWARF) file
+ * for this ELF file.
+ *
+ * @param elf libelf handle for an ELF file
+ * @return build-id for this ELF file (or an empty vector if none is found)
+ */
+static
+std::vector<char> get_build_id(Elf* elf)
+{
+#ifdef __linux
+ // Summary: the GNU build ID is stored in a ("GNU, NT_GNU_BUILD_ID) note
+ // found in a PT_NOTE entry in the program header table.
+
+ size_t phnum;
+ if (elf_getphdrnum (elf, &phnum) != 0)
+ xbt_die("Could not read program headers");
+
+ // Iterate over the program headers and find the PT_NOTE ones:
+ for (size_t i = 0; i < phnum; ++i) {
+ GElf_Phdr phdr_temp;
+ GElf_Phdr *phdr = gelf_getphdr(elf, i, &phdr_temp);
+ if (phdr->p_type != PT_NOTE)
+ continue;
+
+ Elf_Data* data = elf_getdata_rawchunk(elf, phdr->p_offset, phdr->p_filesz, ELF_T_NHDR);
+
+ // Iterate over the notes and find the NT_GNU_BUILD_ID one:
+ size_t pos = 0;
+ while (pos < data->d_size) {
+ GElf_Nhdr nhdr;
+ // Location of the name within Elf_Data:
+ size_t name_pos;
+ size_t desc_pos;
+ pos = gelf_getnote(data, pos, &nhdr, &name_pos, &desc_pos);
+ // A build ID note is identified by the pair ("GNU", NT_GNU_BUILD_ID)
+ // (a namespace and a type within this namespace):
+ if (nhdr.n_type == NT_GNU_BUILD_ID
+ && nhdr.n_namesz == sizeof("GNU")
+ && memcmp((char*) data->d_buf + name_pos, "GNU", sizeof("GNU")) == 0) {
+ XBT_DEBUG("Found GNU/NT_GNU_BUILD_ID note");
+ char* start = (char*) data->d_buf + desc_pos;
+ char* end = (char*) start + nhdr.n_descsz;
+ return std::vector<char>(start, end);