Logo AND Algorithmique Numérique Distribuée

Public GIT Repository
Redundant initializations.
[simgrid.git] / src / mc / inspect / mc_dwarf.cpp
index 814449b..44ad73e 100644 (file)
@@ -1,4 +1,4 @@
-/* Copyright (c) 2008-2020. The SimGrid Team. All rights reserved.          */
+/* Copyright (c) 2008-2022. The SimGrid Team. All rights reserved.          */
 
 /* This program is free software; you can redistribute it and/or modify it
  * under the terms of the license (GNU LGPL) which comes with this package. */
 #include "src/mc/inspect/Variable.hpp"
 #include "src/mc/inspect/mc_dwarf.hpp"
 #include "src/mc/mc_private.hpp"
-#include "src/mc/remote/RemoteClientMemory.hpp"
+#include "src/mc/remote/RemoteProcess.hpp"
 
+#include <algorithm>
+#include <array>
+#include <cerrno>
 #include <cinttypes>
 #include <cstdint>
 #include <cstdlib>
+#include <cstring>
 #include <fcntl.h>
 #include <memory>
+#include <unordered_map>
 #include <utility>
 
 #include <boost/range/algorithm.hpp>
 
 #include <elfutils/libdw.h>
-
-#include <boost/algorithm/string/predicate.hpp>
+#include <elfutils/version.h>
 
 XBT_LOG_NEW_DEFAULT_SUBCATEGORY(mc_dwarf, mc, "DWARF processing");
 
@@ -59,7 +63,7 @@ static uint64_t MC_dwarf_array_element_count(Dwarf_Die* die, Dwarf_Die* unit);
 
 /** @brief Process a DIE
  *
- *  @param info the resulting object fot the library/binary file (output)
+ *  @param info the resulting object for the library/binary file (output)
  *  @param die  the current DIE
  *  @param unit the DIE of the compile unit of the current DIE
  *  @param frame containing frame if any
@@ -74,7 +78,7 @@ static void MC_dwarf_handle_type_die(simgrid::mc::ObjectInformation* info, Dwarf
 
 /** @brief Calls MC_dwarf_handle_die on all children of the given die
  *
- *  @param info the resulting object fot the library/binary file (output)
+ *  @param info the resulting object for the library/binary file (output)
  *  @param die  the current DIE
  *  @param unit the DIE of the compile unit of the current DIE
  *  @param frame containing frame if any
@@ -84,7 +88,7 @@ static void MC_dwarf_handle_children(simgrid::mc::ObjectInformation* info, Dwarf
 
 /** @brief Handle a variable (DW_TAG_variable or other)
  *
- *  @param info the resulting object fot the library/binary file (output)
+ *  @param info the resulting object for the library/binary file (output)
  *  @param die  the current DIE
  *  @param unit the DIE of the compile unit of the current DIE
  *  @param frame containing frame if any
@@ -99,8 +103,7 @@ static void MC_dwarf_handle_variable_die(simgrid::mc::ObjectInformation* info, D
  */
 static std::uint64_t MC_dwarf_at_type(Dwarf_Die* die);
 
-namespace simgrid {
-namespace dwarf {
+namespace simgrid::dwarf {
 
 enum class TagClass { Unknown, Type, Subprogram, Variable, Scope, Namespace };
 
@@ -122,52 +125,32 @@ enum class FormClass {
 
 static TagClass classify_tag(int tag)
 {
-  switch (tag) {
-    case DW_TAG_array_type:
-    case DW_TAG_class_type:
-    case DW_TAG_enumeration_type:
-    case DW_TAG_typedef:
-    case DW_TAG_pointer_type:
-    case DW_TAG_reference_type:
-    case DW_TAG_rvalue_reference_type:
-    case DW_TAG_string_type:
-    case DW_TAG_structure_type:
-    case DW_TAG_subroutine_type:
-    case DW_TAG_union_type:
-    case DW_TAG_ptr_to_member_type:
-    case DW_TAG_set_type:
-    case DW_TAG_subrange_type:
-    case DW_TAG_base_type:
-    case DW_TAG_const_type:
-    case DW_TAG_file_type:
-    case DW_TAG_packed_type:
-    case DW_TAG_volatile_type:
-    case DW_TAG_restrict_type:
-    case DW_TAG_interface_type:
-    case DW_TAG_unspecified_type:
-    case DW_TAG_shared_type:
-      return TagClass::Type;
-
-    case DW_TAG_subprogram:
-      return TagClass::Subprogram;
-
-    case DW_TAG_variable:
-    case DW_TAG_formal_parameter:
-      return TagClass::Variable;
-
-    case DW_TAG_lexical_block:
-    case DW_TAG_try_block:
-    case DW_TAG_catch_block:
-    case DW_TAG_inlined_subroutine:
-    case DW_TAG_with_stmt:
-      return TagClass::Scope;
-
-    case DW_TAG_namespace:
-      return TagClass::Namespace;
-
-    default:
-      return TagClass::Unknown;
-  }
+  static const std::unordered_map<int, TagClass> map = {
+      {DW_TAG_array_type, TagClass::Type},            {DW_TAG_class_type, TagClass::Type},
+      {DW_TAG_enumeration_type, TagClass::Type},      {DW_TAG_typedef, TagClass::Type},
+      {DW_TAG_pointer_type, TagClass::Type},          {DW_TAG_reference_type, TagClass::Type},
+      {DW_TAG_rvalue_reference_type, TagClass::Type}, {DW_TAG_string_type, TagClass::Type},
+      {DW_TAG_structure_type, TagClass::Type},        {DW_TAG_subroutine_type, TagClass::Type},
+      {DW_TAG_union_type, TagClass::Type},            {DW_TAG_ptr_to_member_type, TagClass::Type},
+      {DW_TAG_set_type, TagClass::Type},              {DW_TAG_subrange_type, TagClass::Type},
+      {DW_TAG_base_type, TagClass::Type},             {DW_TAG_const_type, TagClass::Type},
+      {DW_TAG_file_type, TagClass::Type},             {DW_TAG_packed_type, TagClass::Type},
+      {DW_TAG_volatile_type, TagClass::Type},         {DW_TAG_restrict_type, TagClass::Type},
+      {DW_TAG_interface_type, TagClass::Type},        {DW_TAG_unspecified_type, TagClass::Type},
+      {DW_TAG_shared_type, TagClass::Type},
+
+      {DW_TAG_subprogram, TagClass::Subprogram},
+
+      {DW_TAG_variable, TagClass::Variable},          {DW_TAG_formal_parameter, TagClass::Variable},
+
+      {DW_TAG_lexical_block, TagClass::Scope},        {DW_TAG_try_block, TagClass::Scope},
+      {DW_TAG_catch_block, TagClass::Scope},          {DW_TAG_inlined_subroutine, TagClass::Scope},
+      {DW_TAG_with_stmt, TagClass::Scope},
+
+      {DW_TAG_namespace, TagClass::Namespace}};
+
+  auto res = map.find(tag);
+  return res != map.end() ? res->second : TagClass::Unknown;
 }
 
 /** @brief Find the DWARF data class for a given DWARF data form
@@ -179,41 +162,35 @@ static TagClass classify_tag(int tag)
  * */
 static FormClass classify_form(int form)
 {
-  switch (form) {
-    case DW_FORM_addr:
-      return FormClass::Address;
-    case DW_FORM_block2:
-    case DW_FORM_block4:
-    case DW_FORM_block:
-    case DW_FORM_block1:
-      return FormClass::Block;
-    case DW_FORM_data1:
-    case DW_FORM_data2:
-    case DW_FORM_data4:
-    case DW_FORM_data8:
-    case DW_FORM_udata:
-    case DW_FORM_sdata:
-      return FormClass::Constant;
-    case DW_FORM_string:
-    case DW_FORM_strp:
-      return FormClass::String;
-    case DW_FORM_ref_addr:
-    case DW_FORM_ref1:
-    case DW_FORM_ref2:
-    case DW_FORM_ref4:
-    case DW_FORM_ref8:
-    case DW_FORM_ref_udata:
-      return FormClass::Reference;
-    case DW_FORM_flag:
-    case DW_FORM_flag_present:
-      return FormClass::Flag;
-    case DW_FORM_exprloc:
-      return FormClass::ExprLoc;
+  static const std::unordered_map<int, FormClass> map = {
+      {DW_FORM_addr, FormClass::Address},
+
+      {DW_FORM_block2, FormClass::Block},           {DW_FORM_block4, FormClass::Block},
+      {DW_FORM_block, FormClass::Block},            {DW_FORM_block1, FormClass::Block},
+
+      {DW_FORM_data1, FormClass::Constant},         {DW_FORM_data2, FormClass::Constant},
+      {DW_FORM_data4, FormClass::Constant},         {DW_FORM_data8, FormClass::Constant},
+      {DW_FORM_udata, FormClass::Constant},         {DW_FORM_sdata, FormClass::Constant},
+#if _ELFUTILS_PREREQ(0, 171)
+      {DW_FORM_implicit_const, FormClass::Constant},
+#endif
+
+      {DW_FORM_string, FormClass::String},          {DW_FORM_strp, FormClass::String},
+
+      {DW_FORM_ref_addr, FormClass::Reference},     {DW_FORM_ref1, FormClass::Reference},
+      {DW_FORM_ref2, FormClass::Reference},         {DW_FORM_ref4, FormClass::Reference},
+      {DW_FORM_ref8, FormClass::Reference},         {DW_FORM_ref_udata, FormClass::Reference},
+
+      {DW_FORM_flag, FormClass::Flag},              {DW_FORM_flag_present, FormClass::Flag},
+
+      {DW_FORM_exprloc, FormClass::ExprLoc}
+
       // TODO sec offset
       // TODO indirect
-    default:
-      return FormClass::Unknown;
-  }
+  };
+
+  auto res = map.find(form);
+  return res != map.end() ? res->second : FormClass::Unknown;
 }
 
 /** @brief Get the name of the tag of a given DIE
@@ -226,8 +203,7 @@ inline XBT_PRIVATE const char* tagname(Dwarf_Die* die)
   return tagname(dwarf_tag(die));
 }
 
-} // namespace dwarf
-} // namespace simgrid
+} // namespace simgrid::dwarf
 
 // ***** Attributes
 
@@ -246,23 +222,12 @@ static const char* MC_dwarf_attr_integrate_string(Dwarf_Die* die, int attribute)
     return dwarf_formstring(&attr);
 }
 
-static Dwarf_Off MC_dwarf_attr_dieoffset(Dwarf_Die* die, int attribute)
-{
-  Dwarf_Attribute attr;
-  if (dwarf_hasattr_integrate(die, attribute) == 0)
-    return 0;
-  dwarf_attr_integrate(die, attribute, &attr);
-  Dwarf_Die subtype_die;
-  xbt_assert(dwarf_formref_die(&attr, &subtype_die) != nullptr, "Could not find DIE");
-  return dwarf_dieoffset(&subtype_die);
-}
-
 static Dwarf_Off MC_dwarf_attr_integrate_dieoffset(Dwarf_Die* die, int attribute)
 {
   Dwarf_Attribute attr;
   if (dwarf_hasattr_integrate(die, attribute) == 0)
     return 0;
-  dwarf_attr_integrate(die, DW_AT_type, &attr);
+  dwarf_attr_integrate(die, attribute, &attr);
   Dwarf_Die subtype_die;
   xbt_assert(dwarf_formref_die(&attr, &subtype_die) != nullptr, "Could not find DIE");
   return dwarf_dieoffset(&subtype_die);
@@ -302,7 +267,7 @@ static uint64_t MC_dwarf_attr_integrate_uint(Dwarf_Die* die, int attribute, uint
 static bool MC_dwarf_attr_flag(Dwarf_Die* die, int attribute, bool integrate)
 {
   Dwarf_Attribute attr;
-  if ((integrate ? dwarf_attr_integrate(die, attribute, &attr) : dwarf_attr(die, attribute, &attr)) == 0)
+  if ((integrate ? dwarf_attr_integrate(die, attribute, &attr) : dwarf_attr(die, attribute, &attr)) == nullptr)
     return false;
 
   bool result;
@@ -321,33 +286,19 @@ static bool MC_dwarf_attr_flag(Dwarf_Die* die, int attribute, bool integrate)
  * */
 static uint64_t MC_dwarf_default_lower_bound(int lang)
 {
-  switch (lang) {
-    case DW_LANG_C:
-    case DW_LANG_C89:
-    case DW_LANG_C99:
-    case DW_LANG_C_plus_plus:
-    case DW_LANG_D:
-    case DW_LANG_Java:
-    case DW_LANG_ObjC:
-    case DW_LANG_ObjC_plus_plus:
-    case DW_LANG_Python:
-    case DW_LANG_UPC:
-      return 0;
-    case DW_LANG_Ada83:
-    case DW_LANG_Ada95:
-    case DW_LANG_Fortran77:
-    case DW_LANG_Fortran90:
-    case DW_LANG_Fortran95:
-    case DW_LANG_Modula2:
-    case DW_LANG_Pascal83:
-    case DW_LANG_PL1:
-    case DW_LANG_Cobol74:
-    case DW_LANG_Cobol85:
-      return 1;
-    default:
-      xbt_die("No default DW_TAG_lower_bound for language %i and none given", lang);
-      return 0;
-  }
+  const std::unordered_map<int, unsigned> map = {
+      {DW_LANG_C, 0},           {DW_LANG_C89, 0},            {DW_LANG_C99, 0},            {DW_LANG_C11, 0},
+      {DW_LANG_C_plus_plus, 0}, {DW_LANG_C_plus_plus_11, 0}, {DW_LANG_C_plus_plus_14, 0}, {DW_LANG_D, 0},
+      {DW_LANG_Java, 0},        {DW_LANG_ObjC, 0},           {DW_LANG_ObjC_plus_plus, 0}, {DW_LANG_Python, 0},
+      {DW_LANG_UPC, 0},
+
+      {DW_LANG_Ada83, 1},       {DW_LANG_Ada95, 1},          {DW_LANG_Fortran77, 1},      {DW_LANG_Fortran90, 1},
+      {DW_LANG_Fortran95, 1},   {DW_LANG_Fortran03, 1},      {DW_LANG_Fortran08, 1},      {DW_LANG_Modula2, 1},
+      {DW_LANG_Pascal83, 1},    {DW_LANG_PL1, 1},            {DW_LANG_Cobol74, 1},        {DW_LANG_Cobol85, 1}};
+
+  auto res = map.find(lang);
+  xbt_assert(res != map.end(), "No default DW_TAG_lower_bound for language %i and none given", lang);
+  return res->second;
 }
 
 /** @brief Finds the number of elements in a DW_TAG_subrange_type or DW_TAG_enumeration_type DIE
@@ -380,7 +331,7 @@ static uint64_t MC_dwarf_subrange_element_count(Dwarf_Die* die, Dwarf_Die* unit)
   return upper_bound - lower_bound + 1;
 }
 
-/** @brief Finds the number of elements in a array type (DW_TAG_array_type)
+/** @brief Finds the number of elements in an array type (DW_TAG_array_type)
  *
  *  The compilation unit might be needed because the default lower
  *  bound depends on the language of the compilation unit.
@@ -396,8 +347,7 @@ static uint64_t MC_dwarf_array_element_count(Dwarf_Die* die, Dwarf_Die* unit)
 
   int result = 1;
   Dwarf_Die child;
-  int res;
-  for (res = dwarf_child(die, &child); res == 0; res = dwarf_siblingof(&child, &child)) {
+  for (int res = dwarf_child(die, &child); res == 0; res = dwarf_siblingof(&child, &child)) {
     int child_tag = dwarf_tag(&child);
     if (child_tag == DW_TAG_subrange_type || child_tag == DW_TAG_enumeration_type)
       result *= MC_dwarf_subrange_element_count(&child, unit);
@@ -436,10 +386,10 @@ static void MC_dwarf_fill_member_location(const simgrid::mc::Type* type, simgrid
   xbt_assert(not dwarf_hasattr(child, DW_AT_data_bit_offset), "Can't groke DW_AT_data_bit_offset.");
 
   if (not dwarf_hasattr_integrate(child, DW_AT_data_member_location)) {
-    if (type->type == DW_TAG_union_type)
-      return;
-    xbt_die("Missing DW_AT_data_member_location field in DW_TAG_member %s of type <%" PRIx64 ">%s",
-            member->name.c_str(), (uint64_t)type->id, type->name.c_str());
+    xbt_assert(type->type == DW_TAG_union_type,
+               "Missing DW_AT_data_member_location field in DW_TAG_member %s of type <%" PRIx64 ">%s",
+               member->name.c_str(), (uint64_t)type->id, type->name.c_str());
+    return;
   }
 
   Dwarf_Attribute attr;
@@ -487,10 +437,9 @@ static void MC_dwarf_fill_member_location(const simgrid::mc::Type* type, simgrid
 static void MC_dwarf_add_members(const simgrid::mc::ObjectInformation* /*info*/, Dwarf_Die* die,
                                  const Dwarf_Die* /*unit*/, simgrid::mc::Type* type)
 {
-  int res;
   Dwarf_Die child;
   xbt_assert(type->members.empty());
-  for (res = dwarf_child(die, &child); res == 0; res = dwarf_siblingof(&child, &child)) {
+  for (int res = dwarf_child(die, &child); res == 0; res = dwarf_siblingof(&child, &child)) {
     int tag = dwarf_tag(&child);
     if (tag == DW_TAG_member || tag == DW_TAG_inheritance) {
       // Skip declarations:
@@ -511,8 +460,7 @@ static void MC_dwarf_add_members(const simgrid::mc::ObjectInformation* /*info*/,
         member.name = name;
       // Those base names are used by GCC and clang for virtual table pointers
       // respectively ("__vptr$ClassName", "__vptr.ClassName"):
-      if (boost::algorithm::starts_with(member.name, "__vptr$") ||
-          boost::algorithm::starts_with(member.name, "__vptr."))
+      if (member.name.rfind("__vptr$", 0) == 0 || member.name.rfind("__vptr.", 0) == 0)
         member.flags |= simgrid::mc::Member::VIRTUAL_POINTER_FLAG;
       // A cleaner solution would be to check against the type:
       // ---
@@ -535,7 +483,10 @@ static void MC_dwarf_add_members(const simgrid::mc::ObjectInformation* /*info*/,
       member.byte_size = MC_dwarf_attr_integrate_uint(&child, DW_AT_byte_size, 0);
       member.type_id   = MC_dwarf_at_type(&child);
 
-      xbt_assert(not dwarf_hasattr(&child, DW_AT_data_bit_offset), "Can't groke DW_AT_data_bit_offset.");
+      if (dwarf_hasattr(&child, DW_AT_data_bit_offset)) {
+        XBT_WARN("Can't groke DW_AT_data_bit_offset for %s", name);
+        continue;
+      }
 
       MC_dwarf_fill_member_location(type, &member, &child);
 
@@ -565,7 +516,7 @@ static simgrid::mc::Type MC_dwarf_die_to_type(simgrid::mc::ObjectInformation* in
   // Global Offset
   type.id = dwarf_dieoffset(die);
 
-  const char* prefix = "";
+  const char* prefix;
   switch (type.type) {
     case DW_TAG_structure_type:
       prefix = "struct ";
@@ -641,8 +592,6 @@ static void MC_dwarf_handle_type_die(simgrid::mc::ObjectInformation* info, Dwarf
     info->full_types_by_name[t.name] = &t;
 }
 
-static int mc_anonymous_variable_index = 0;
-
 static std::unique_ptr<simgrid::mc::Variable> MC_die_to_variable(simgrid::mc::ObjectInformation* info, Dwarf_Die* die,
                                                                  const Dwarf_Die* /*unit*/,
                                                                  const simgrid::mc::Frame* frame, const char* ns)
@@ -660,10 +609,10 @@ static std::unique_ptr<simgrid::mc::Variable> MC_die_to_variable(simgrid::mc::Ob
     // No location: do not add it ?
     return nullptr;
 
-  std::unique_ptr<simgrid::mc::Variable> variable = std::unique_ptr<simgrid::mc::Variable>(new simgrid::mc::Variable());
-  variable->id                                    = dwarf_dieoffset(die);
-  variable->global                                = frame == nullptr; // Can be override base on DW_AT_location
-  variable->object_info                           = info;
+  auto variable         = std::make_unique<simgrid::mc::Variable>();
+  variable->id          = dwarf_dieoffset(die);
+  variable->global      = frame == nullptr; // Can be override base on DW_AT_location
+  variable->object_info = info;
 
   const char* name = MC_dwarf_attr_integrate_string(die, DW_AT_name);
   if (name)
@@ -690,9 +639,9 @@ static std::unique_ptr<simgrid::mc::Variable> MC_die_to_variable(simgrid::mc::Ob
 
         if (len == 1 && expr[0].atom == DW_OP_addr) {
           variable->global  = true;
-          uintptr_t offset  = (uintptr_t)expr[0].number;
-          uintptr_t base    = (uintptr_t)info->base_address();
-          variable->address = (void*)(base + offset);
+          auto offset       = static_cast<uintptr_t>(expr[0].number);
+          auto base         = reinterpret_cast<uintptr_t>(info->base_address());
+          variable->address = reinterpret_cast<void*>(base + offset);
         } else
           variable->location_list = {
               simgrid::dwarf::LocationListEntry(simgrid::dwarf::DwarfExpression(expr, expr + len))};
@@ -732,6 +681,7 @@ static std::unique_ptr<simgrid::mc::Variable> MC_die_to_variable(simgrid::mc::Ob
 
   // The current code needs a variable name,
   // generate a fake one:
+  static int mc_anonymous_variable_index = 0;
   if (variable->name.empty()) {
     variable->name = "@anonymous#" + std::to_string(mc_anonymous_variable_index);
     mc_anonymous_variable_index++;
@@ -781,16 +731,16 @@ static void MC_dwarf_handle_scope_die(simgrid::mc::ObjectInformation* info, Dwar
       frame.name = name;
   }
 
-  frame.abstract_origin_id = MC_dwarf_attr_dieoffset(die, DW_AT_abstract_origin);
+  frame.abstract_origin_id = MC_dwarf_attr_integrate_dieoffset(die, DW_AT_abstract_origin);
 
   // This is the base address for DWARF addresses.
   // Relocated addresses are offset from this base address.
   // See DWARF4 spec 7.5
-  std::uint64_t base = (std::uint64_t)info->base_address();
+  auto base = reinterpret_cast<std::uint64_t>(info->base_address());
 
   // TODO, support DW_AT_ranges
   uint64_t low_pc     = MC_dwarf_attr_integrate_addr(die, DW_AT_low_pc);
-  frame.range.begin() = low_pc ? (std::uint64_t)base + low_pc : 0;
+  frame.range.begin() = low_pc ? base + low_pc : 0;
   if (low_pc) {
     // DW_AT_high_pc:
     Dwarf_Attribute attr;
@@ -853,8 +803,7 @@ static void MC_dwarf_handle_children(simgrid::mc::ObjectInformation* info, Dwarf
 {
   // For each child DIE:
   Dwarf_Die child;
-  int res;
-  for (res = dwarf_child(die, &child); res == 0; res = dwarf_siblingof(&child, &child))
+  for (int res = dwarf_child(die, &child); res == 0; res = dwarf_siblingof(&child, &child))
     MC_dwarf_handle_die(info, &child, unit, frame, ns);
 }
 
@@ -891,11 +840,9 @@ static void MC_dwarf_handle_die(simgrid::mc::ObjectInformation* info, Dwarf_Die*
 
 static Elf64_Half get_type(Elf* elf)
 {
-  const Elf64_Ehdr* ehdr64 = elf64_getehdr(elf);
-  if (ehdr64)
+  if (const Elf64_Ehdr* ehdr64 = elf64_getehdr(elf))
     return ehdr64->e_type;
-  const Elf32_Ehdr* ehdr32 = elf32_getehdr(elf);
-  if (ehdr32)
+  if (const Elf32_Ehdr* ehdr32 = elf32_getehdr(elf))
     return ehdr32->e_type;
   xbt_die("Could not get ELF heeader");
 }
@@ -908,8 +855,7 @@ static void read_dwarf_info(simgrid::mc::ObjectInformation* info, Dwarf* dwarf)
   size_t length;
 
   while (dwarf_nextcu(dwarf, offset, &next_offset, &length, nullptr, nullptr, nullptr) == 0) {
-    Dwarf_Die unit_die;
-    if (dwarf_offdie(dwarf, offset + length, &unit_die) != nullptr)
+    if (Dwarf_Die unit_die; dwarf_offdie(dwarf, offset + length, &unit_die) != nullptr)
       MC_dwarf_handle_children(info, &unit_die, &unit_die, nullptr, nullptr);
     offset = next_offset;
   }
@@ -955,7 +901,7 @@ static std::vector<char> get_build_id(Elf* elf)
           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;
+        char* end   = start + nhdr.n_descsz;
         return std::vector<char>(start, end);
       }
     }
@@ -964,11 +910,11 @@ static std::vector<char> get_build_id(Elf* elf)
   return std::vector<char>();
 }
 
-static char hexdigits[16] = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'};
-
 /** Binary data to hexadecimal */
 static inline std::array<char, 2> to_hex(std::uint8_t byte)
 {
+  constexpr std::array<char, 16> hexdigits{
+      {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'}};
   // Horrid double braces!
   // Apparently, this is needed in C++11 (not in C++14).
   return {{hexdigits[byte >> 4], hexdigits[byte & 0xF]}};
@@ -979,11 +925,8 @@ static std::string to_hex(const char* data, std::size_t count)
 {
   std::string res;
   res.resize(2 * count);
-  for (std::size_t i = 0; i < count; i++) {
-    std::array<char, 2> hex_byte = to_hex(data[i]);
-    for (int j = 0; j < 2; ++j)
-      res[2 * i + j] = hex_byte[j];
-  }
+  for (std::size_t i = 0; i < count; i++)
+    std::copy_n(cbegin(to_hex(data[i])), 2, &res[2 * i]);
   return res;
 }
 
@@ -994,7 +937,7 @@ static std::string to_hex(std::vector<char> const& data)
 }
 
 /** Base directories for external debug files */
-static const char* debug_paths[] = {
+static constexpr auto debug_paths = {
     "/usr/lib/debug/",
     "/usr/local/lib/debug/",
 };
@@ -1006,7 +949,7 @@ static const char* debug_paths[] = {
  */
 // Example:
 // /usr/lib/debug/.build-id/0b/dc77f1c29aea2b14ff5acd9a19ab3175ffdeae.debug
-static std::string find_by_build_id(std::vector<char> id)
+static int find_by_build_id(std::vector<char> id)
 {
   std::string filename;
   std::string hex = to_hex(id);
@@ -1015,18 +958,19 @@ static std::string find_by_build_id(std::vector<char> id)
     filename = std::string(debug_path) + ".build-id/" + to_hex(id.data(), 1) + '/' +
                to_hex(id.data() + 1, id.size() - 1) + ".debug";
     XBT_DEBUG("Checking debug file: %s", filename.c_str());
-    if (access(filename.c_str(), F_OK) == 0) {
+    if (int fd = open(filename.c_str(), O_RDONLY); fd != -1) {
       XBT_DEBUG("Found debug file: %s\n", hex.c_str());
-      return filename;
+      return fd;
     }
+    xbt_assert(errno != ENOENT, "Could not open file: %s", strerror(errno));
   }
-  XBT_DEBUG("Not debuf info found for build ID %s\n", hex.data());
-  return std::string();
+  XBT_DEBUG("No debug info found for build ID %s\n", hex.data());
+  return -1;
 }
 
-/** @brief Populate the debugging informations of the given ELF object
+/** @brief Populate the debugging information of the given ELF object
  *
- *  Read the DWARf information of the EFFL object and populate the
+ *  Read the DWARF information of the ELF object and populate the
  *  lists of types, variables, functions.
  */
 static void MC_load_dwarf(simgrid::mc::ObjectInformation* info)
@@ -1037,28 +981,23 @@ static void MC_load_dwarf(simgrid::mc::ObjectInformation* info)
   int fd = open(info->file_name.c_str(), O_RDONLY);
   xbt_assert(fd >= 0, "Could not open file %s", info->file_name.c_str());
   Elf* elf = elf_begin(fd, ELF_C_READ, nullptr);
-  xbt_assert(elf != nullptr, "Not an ELF file");
-  Elf_Kind kind = elf_kind(elf);
-  xbt_assert(kind == ELF_K_ELF, "Not an ELF file");
+  xbt_assert(elf != nullptr && elf_kind(elf) == ELF_K_ELF, "%s is not an ELF file", info->file_name.c_str());
 
   // Remember if this is a `ET_EXEC` (fixed location) or `ET_DYN`:
-  Elf64_Half type = get_type(elf);
-  if (type == ET_EXEC)
+  if (get_type(elf) == ET_EXEC)
     info->flags |= simgrid::mc::ObjectInformation::Executable;
 
   // Read DWARF debug information in the file:
-  Dwarf* dwarf = dwarf_begin_elf(elf, DWARF_C_READ, nullptr);
-  if (dwarf != nullptr) {
+  if (Dwarf* dwarf = dwarf_begin_elf(elf, DWARF_C_READ, nullptr)) {
     read_dwarf_info(info, dwarf);
     dwarf_end(dwarf);
     elf_end(elf);
     close(fd);
     return;
   }
-  dwarf_end(dwarf);
 
   // If there was no DWARF in the file, try to find it in a separate file.
-  // Different methods might be used to store the DWARF informations:
+  // Different methods might be used to store the DWARF information:
   //  * GNU NT_GNU_BUILD_ID
   //  * .gnu_debuglink
   // See https://sourceware.org/gdb/onlinedocs/gdb/Separate-Debug-Files.html
@@ -1066,24 +1005,21 @@ static void MC_load_dwarf(simgrid::mc::ObjectInformation* info)
 
   // Try with NT_GNU_BUILD_ID: we find the build ID in the ELF file and then
   // use this ID to find the file in some known locations in the filesystem.
-  std::vector<char> build_id = get_build_id(elf);
-  if (not build_id.empty()) {
+  if (std::vector<char> build_id = get_build_id(elf); not build_id.empty()) {
     elf_end(elf);
     close(fd);
 
     // Find the debug file using the build id:
-    std::string debug_file = find_by_build_id(build_id);
-    xbt_assert(not debug_file.empty(),
+    fd = find_by_build_id(build_id);
+    xbt_assert(fd != -1,
                "Missing debug info for %s with build-id %s\n"
                "You might want to install the suitable debugging package.\n",
                info->file_name.c_str(), to_hex(build_id).c_str());
 
     // Load the DWARF info from this file:
-    XBT_DEBUG("Load DWARF for %s from %s", info->file_name.c_str(), debug_file.c_str());
-    fd = open(debug_file.c_str(), O_RDONLY);
-    xbt_assert(fd >= 0, "Could not open file %s", debug_file.c_str());
-    dwarf = dwarf_begin(fd, DWARF_C_READ);
-    xbt_assert(dwarf != nullptr, "No DWARF info in %s for %s", debug_file.c_str(), info->file_name.c_str());
+    XBT_DEBUG("Load DWARF for %s", info->file_name.c_str());
+    Dwarf* dwarf = dwarf_begin(fd, DWARF_C_READ);
+    xbt_assert(dwarf != nullptr, "No DWARF info for %s", info->file_name.c_str());
     read_dwarf_info(info, dwarf);
     dwarf_end(dwarf);
     close(fd);
@@ -1105,12 +1041,12 @@ static void MC_make_functions_index(simgrid::mc::ObjectInformation* info)
 {
   info->functions_index.clear();
 
-  for (auto& e : info->subprograms) {
-    if (e.second.range.begin() == 0)
+  for (auto& [_, e] : info->subprograms) {
+    if (e.range.begin() == 0)
       continue;
     simgrid::mc::FunctionIndexEntry entry;
-    entry.low_pc   = (void*)e.second.range.begin();
-    entry.function = &e.second;
+    entry.low_pc   = (void*)e.range.begin();
+    entry.function = &e;
     info->functions_index.push_back(entry);
   }
 
@@ -1171,8 +1107,7 @@ static simgrid::mc::Type* MC_resolve_type(simgrid::mc::ObjectInformation* info,
 
   // Try to find a more complete description of the type:
   // We need to fix in order to support C++.
-  simgrid::mc::Type** subtype = simgrid::util::find_map_ptr(info->full_types_by_name, type->name);
-  if (subtype)
+  if (simgrid::mc::Type** subtype = simgrid::util::find_map_ptr(info->full_types_by_name, type->name))
     type = *subtype;
   return type;
 }
@@ -1180,37 +1115,44 @@ static simgrid::mc::Type* MC_resolve_type(simgrid::mc::ObjectInformation* info,
 static void MC_post_process_types(simgrid::mc::ObjectInformation* info)
 {
   // Lookup "subtype" field:
-  for (auto& i : info->types) {
-    i.second.subtype = MC_resolve_type(info, i.second.type_id);
-    for (simgrid::mc::Member& member : i.second.members)
+  for (auto& [_, i] : info->types) {
+    i.subtype = MC_resolve_type(info, i.type_id);
+    for (simgrid::mc::Member& member : i.members)
       member.type = MC_resolve_type(info, member.type_id);
   }
 }
 
-namespace simgrid {
-namespace mc {
+namespace simgrid::mc {
 
-/** @brief Finds informations about a given shared object/executable */
+void ObjectInformation::ensure_dwarf_loaded()
+{
+  if (dwarf_loaded)
+    return;
+  dwarf_loaded = true;
+
+  MC_load_dwarf(this);
+  MC_post_process_variables(this);
+  MC_post_process_types(this);
+  for (auto& [_, entry] : this->subprograms)
+    mc_post_process_scope(this, &entry);
+  MC_make_functions_index(this);
+}
+
+/** @brief Finds information about a given shared object/executable */
 std::shared_ptr<ObjectInformation> createObjectInformation(std::vector<xbt::VmMap> const& maps, const char* name)
 {
-  std::shared_ptr<ObjectInformation> result = std::make_shared<ObjectInformation>();
-  result->file_name                         = name;
+  auto result       = std::make_shared<ObjectInformation>();
+  result->file_name = name;
   simgrid::mc::find_object_address(maps, result.get());
-  MC_load_dwarf(result.get());
-  MC_post_process_variables(result.get());
-  MC_post_process_types(result.get());
-  for (auto& entry : result.get()->subprograms)
-    mc_post_process_scope(result.get(), &entry.second);
-  MC_make_functions_index(result.get());
   return result;
 }
 
 /*************************************************************************/
 
-void postProcessObjectInformation(const RemoteClientMemory* process, ObjectInformation* info)
+void postProcessObjectInformation(const RemoteProcess* process, ObjectInformation* info)
 {
-  for (auto& t : info->types) {
-    Type* type    = &(t.second);
+  for (auto& [_, t] : info->types) {
+    Type* type    = &t;
     Type* subtype = type;
     while (subtype->type == DW_TAG_typedef || subtype->type == DW_TAG_volatile_type ||
            subtype->type == DW_TAG_const_type)
@@ -1233,11 +1175,9 @@ void postProcessObjectInformation(const RemoteClientMemory* process, ObjectInfor
   }
 }
 
-} // namespace mc
-} // namespace simgrid
+} // namespace simgrid::mc
 
-namespace simgrid {
-namespace dwarf {
+namespace simgrid::dwarf {
 
 /** Convert a DWARF register into a libunwind register
  *
@@ -1247,68 +1187,23 @@ namespace dwarf {
  */
 int dwarf_register_to_libunwind(int dwarf_register)
 {
-#if defined(__x86_64__)
+#if defined(__x86_64__) || defined(__aarch64__)
   // It seems for this arch, DWARF and libunwind agree in the numbering:
   return dwarf_register;
 #elif defined(__i386__)
   // Couldn't find the authoritative source of information for this.
   // This is inspired from http://source.winehq.org/source/dlls/dbghelp/cpu_i386.c#L517.
-  switch (dwarf_register) {
-    case 0:
-      return UNW_X86_EAX;
-    case 1:
-      return UNW_X86_ECX;
-    case 2:
-      return UNW_X86_EDX;
-    case 3:
-      return UNW_X86_EBX;
-    case 4:
-      return UNW_X86_ESP;
-    case 5:
-      return UNW_X86_EBP;
-    case 6:
-      return UNW_X86_ESI;
-    case 7:
-      return UNW_X86_EDI;
-    case 8:
-      return UNW_X86_EIP;
-    case 9:
-      return UNW_X86_EFLAGS;
-    case 10:
-      return UNW_X86_CS;
-    case 11:
-      return UNW_X86_SS;
-    case 12:
-      return UNW_X86_DS;
-    case 13:
-      return UNW_X86_ES;
-    case 14:
-      return UNW_X86_FS;
-    case 15:
-      return UNW_X86_GS;
-    case 16:
-      return UNW_X86_ST0;
-    case 17:
-      return UNW_X86_ST1;
-    case 18:
-      return UNW_X86_ST2;
-    case 19:
-      return UNW_X86_ST3;
-    case 20:
-      return UNW_X86_ST4;
-    case 21:
-      return UNW_X86_ST5;
-    case 22:
-      return UNW_X86_ST6;
-    case 23:
-      return UNW_X86_ST7;
-    default:
-      xbt_die("Bad/unknown register number.");
-  }
+  constexpr std::array<int, 24> regs{
+      {/*  0 */ UNW_X86_EAX, /*  1 */ UNW_X86_ECX,    /*  2 */ UNW_X86_EDX, /*  3 */ UNW_X86_EBX,
+       /*  4 */ UNW_X86_ESP, /*  5 */ UNW_X86_EBP,    /*  6 */ UNW_X86_ESI, /*  7 */ UNW_X86_EDI,
+       /*  8 */ UNW_X86_EIP, /*  9 */ UNW_X86_EFLAGS, /* 10 */ UNW_X86_CS,  /* 11 */ UNW_X86_SS,
+       /* 12 */ UNW_X86_DS,  /* 13 */ UNW_X86_ES,     /* 14 */ UNW_X86_FS,  /* 15 */ UNW_X86_GS,
+       /* 16 */ UNW_X86_ST0, /* 17 */ UNW_X86_ST1,    /* 18 */ UNW_X86_ST2, /* 19 */ UNW_X86_ST3,
+       /* 20 */ UNW_X86_ST4, /* 21 */ UNW_X86_ST5,    /* 22 */ UNW_X86_ST6, /* 23 */ UNW_X86_ST7}};
+  return regs.at(dwarf_register);
 #else
 #error This architecture is not supported yet for DWARF expression evaluation.
 #endif
 }
 
-} // namespace dwarf
-} // namespace simgrid
+} // namespace simgrid::dwarf