Logo AND Algorithmique Numérique Distribuée

Public GIT Repository
Merge branch 'master' of framagit.org:simgrid/simgrid
[simgrid.git] / src / mc / inspect / mc_dwarf.cpp
index 48261b0..094635d 100644 (file)
@@ -1,4 +1,4 @@
-/* Copyright (c) 2008-2021. The SimGrid Team. All rights reserved.          */
+/* Copyright (c) 2008-2023. 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/RemoteProcess.hpp"
+#include "src/mc/sosp/RemoteProcessMemory.hpp"
 
 #include <algorithm>
 #include <array>
+#include <cerrno>
 #include <cinttypes>
 #include <cstdint>
 #include <cstdlib>
+#include <cstring>
 #include <fcntl.h>
 #include <memory>
 #include <unordered_map>
@@ -101,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 };
 
@@ -202,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
 
@@ -222,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);
@@ -494,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);
 
@@ -518,13 +510,13 @@ static simgrid::mc::Type MC_dwarf_die_to_type(simgrid::mc::ObjectInformation* in
 {
   simgrid::mc::Type type;
   type.type          = dwarf_tag(die);
-  type.name          = std::string();
+  type.name          = "";
   type.element_count = -1;
 
   // Global Offset
   type.id = dwarf_dieoffset(die);
 
-  const char* prefix = "";
+  const char* prefix;
   switch (type.type) {
     case DW_TAG_structure_type:
       prefix = "struct ";
@@ -685,7 +677,7 @@ static std::unique_ptr<simgrid::mc::Variable> MC_die_to_variable(simgrid::mc::Ob
   }
 
   if (ns && variable->global)
-    variable->name = std::string(ns) + "::" + variable->name;
+    variable->name.insert(0, std::string(ns) + "::");
 
   // The current code needs a variable name,
   // generate a fake one:
@@ -739,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.
@@ -848,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");
 }
@@ -865,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;
   }
@@ -880,7 +869,7 @@ static void read_dwarf_info(simgrid::mc::ObjectInformation* info, Dwarf* dwarf)
  *  @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)
+static std::vector<std::byte> get_build_id(Elf* elf)
 {
 #ifdef __linux
   // Summary: the GNU build ID is stored in a ("GNU, NT_GNU_BUILD_ID) note
@@ -909,30 +898,28 @@ static std::vector<char> get_build_id(Elf* elf)
       // 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) {
+          memcmp(static_cast<std::byte*>(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   = start + nhdr.n_descsz;
-        return std::vector<char>(start, end);
+        std::byte* start = static_cast<std::byte*>(data->d_buf) + desc_pos;
+        std::byte* end   = start + nhdr.n_descsz;
+        return std::vector<std::byte>(start, end);
       }
     }
   }
 #endif
-  return std::vector<char>();
+  return std::vector<std::byte>();
 }
 
 /** Binary data to hexadecimal */
-static inline std::array<char, 2> to_hex(std::uint8_t byte)
+static inline std::array<char, 2> to_hex(std::byte 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]}};
+  return {hexdigits[std::to_integer<unsigned>(byte >> 4)], hexdigits[std::to_integer<unsigned>(byte & std::byte{0xF})]};
 }
 
 /** Binary data to hexadecimal */
-static std::string to_hex(const char* data, std::size_t count)
+static std::string to_hex(const std::byte* data, std::size_t count)
 {
   std::string res;
   res.resize(2 * count);
@@ -942,7 +929,7 @@ static std::string to_hex(const char* data, std::size_t count)
 }
 
 /** Binary data to hexadecimal */
-static std::string to_hex(std::vector<char> const& data)
+static std::string to_hex(std::vector<std::byte> const& data)
 {
   return to_hex(data.data(), data.size());
 }
@@ -960,7 +947,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<std::byte> id)
 {
   std::string filename;
   std::string hex = to_hex(id);
@@ -969,18 +956,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("No debug info found for build ID %s\n", hex.data());
-  return std::string();
+  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)
@@ -994,20 +982,17 @@ static void MC_load_dwarf(simgrid::mc::ObjectInformation* info)
   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:
@@ -1018,24 +1003,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<std::byte> 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);
@@ -1057,12 +1039,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);
   }
 
@@ -1123,8 +1105,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;
 }
@@ -1132,15 +1113,14 @@ 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()
 {
@@ -1151,8 +1131,8 @@ void ObjectInformation::ensure_dwarf_loaded()
   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.second);
+  for (auto& [_, entry] : this->subprograms)
+    mc_post_process_scope(this, &entry);
   MC_make_functions_index(this);
 }
 
@@ -1167,10 +1147,10 @@ std::shared_ptr<ObjectInformation> createObjectInformation(std::vector<xbt::VmMa
 
 /*************************************************************************/
 
-void postProcessObjectInformation(const RemoteProcess* process, ObjectInformation* info)
+void postProcessObjectInformation(const RemoteProcessMemory* 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)
@@ -1193,11 +1173,9 @@ void postProcessObjectInformation(const RemoteProcess* process, ObjectInformatio
   }
 }
 
-} // namespace mc
-} // namespace simgrid
+} // namespace simgrid::mc
 
-namespace simgrid {
-namespace dwarf {
+namespace simgrid::dwarf {
 
 /** Convert a DWARF register into a libunwind register
  *
@@ -1207,7 +1185,7 @@ 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__)
@@ -1226,5 +1204,4 @@ int dwarf_register_to_libunwind(int dwarf_register)
 #endif
 }
 
-} // namespace dwarf
-} // namespace simgrid
+} // namespace simgrid::dwarf