#include <sys/param.h>
#include <alloca.h>
#include <endian.h>
+#include <unistd.h>
/* A good size for the initial read from memory, if it's not too costly.
/* We must have seen the segment covering offset 0, or else the ELF
header we read at START was not produced by these program headers. */
if (unlikely (!found_bias))
- return finish ();
+ {
+ free (build_id);
+ return finish ();
+ }
/* Now we know enough to report a module for sure: its bounds. */
module_start += bias;
bias += fixup;
if (module->name[0] != '\0')
{
- name = module->name;
+ name = basename (module->name);
name_is_final = true;
}
break;
}
}
- /* Ignore this found module if it would conflict in address space with any
- already existing module of DWFL. */
- for (Dwfl_Module *mod = dwfl->modulelist; mod != NULL; mod = mod->next)
- if (module_end > mod->low_addr && module_start < mod->high_addr)
- return finish ();
+ if (r_debug_info != NULL)
+ {
+ bool skip_this_module = false;
+ for (struct r_debug_info_module *module = r_debug_info->module;
+ module != NULL; module = module->next)
+ if ((module_end > module->start && module_start < module->end)
+ || dyn_vaddr == module->l_ld)
+ {
+ bool close_elf = false;
+ if (! module->disk_file_has_build_id && build_id_len > 0)
+ {
+ /* Module found in segments with build-id is more reliable
+ than a module found via DT_DEBUG on disk without any
+ build-id. */
+ if (module->elf != NULL)
+ close_elf = true;
+ }
+ if (module->elf != NULL
+ && module->disk_file_has_build_id && build_id_len > 0)
+ {
+ const void *elf_build_id;
+ GElf_Addr elf_build_id_elfaddr;
+ int elf_build_id_len;
+
+ if (__libdwfl_find_elf_build_id (NULL, module->elf,
+ &elf_build_id,
+ &elf_build_id_elfaddr,
+ &elf_build_id_len) > 0)
+ {
+ if (build_id_len != (size_t) elf_build_id_len
+ || memcmp (build_id, elf_build_id, build_id_len) != 0)
+ close_elf = true;
+ }
+ }
+ if (close_elf)
+ {
+ elf_end (module->elf);
+ close (module->fd);
+ module->elf = NULL;
+ module->fd = -1;
+ }
+ if (module->elf != NULL)
+ {
+ /* Ignore this found module if it would conflict in address
+ space with any already existing module of DWFL. */
+ skip_this_module = true;
+ }
+ }
+ if (skip_this_module)
+ {
+ free (build_id);
+ return finish ();
+ }
+ }
/* Our return value now says to skip the segments contained
within the module. */