Logo AND Algorithmique Numérique Distribuée

Public GIT Repository
Redundant initializations.
[simgrid.git] / src / mc / inspect / mc_dwarf.cpp
index 26579d2..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/RemoteSimulation.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");
 
@@ -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);
@@ -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.
@@ -435,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;
@@ -509,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:
       // ---
@@ -533,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);
 
@@ -563,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 ";
@@ -639,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)
@@ -730,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++;
@@ -779,7 +731,7 @@ 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.
@@ -888,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");
 }
@@ -905,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;
   }
@@ -961,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]}};
@@ -976,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;
 }
 
@@ -1003,7 +949,7 @@ static constexpr auto 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);
@@ -1012,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 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)
@@ -1034,25 +981,20 @@ 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 information:
@@ -1063,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);
@@ -1102,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);
   }
 
@@ -1168,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;
 }
@@ -1177,15 +1115,28 @@ 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 {
+
+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)
@@ -1193,21 +1144,15 @@ std::shared_ptr<ObjectInformation> createObjectInformation(std::vector<xbt::VmMa
   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 RemoteSimulation* 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)
@@ -1230,11 +1175,9 @@ void postProcessObjectInformation(const RemoteSimulation* process, ObjectInforma
   }
 }
 
-} // namespace mc
-} // namespace simgrid
+} // namespace simgrid::mc
 
-namespace simgrid {
-namespace dwarf {
+namespace simgrid::dwarf {
 
 /** Convert a DWARF register into a libunwind register
  *
@@ -1244,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