Logo AND Algorithmique Numérique Distribuée

Public GIT Repository
Use std::string::rfind to match string prefix.
[simgrid.git] / src / mc / inspect / mc_dwarf.cpp
index aeff911..48261b0 100644 (file)
@@ -1,4 +1,4 @@
-/* Copyright (c) 2008-2020. The SimGrid Team. All rights reserved.          */
+/* Copyright (c) 2008-2021. 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. */
@@ -13,7 +13,7 @@
 #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>
@@ -28,8 +28,7 @@
 #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");
 
@@ -165,20 +164,23 @@ static FormClass classify_form(int form)
   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_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},
+      {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_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_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_flag, FormClass::Flag},              {DW_FORM_flag_present, FormClass::Flag},
 
       {DW_FORM_exprloc, FormClass::ExprLoc}
 
@@ -296,13 +298,14 @@ static bool MC_dwarf_attr_flag(Dwarf_Die* die, int attribute, bool integrate)
 static uint64_t MC_dwarf_default_lower_bound(int lang)
 {
   const std::unordered_map<int, unsigned> map = {
-      {DW_LANG_C, 0},         {DW_LANG_C89, 0},     {DW_LANG_C99, 0},       {DW_LANG_C_plus_plus, 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_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_Modula2, 1}, {DW_LANG_Pascal83, 1},  {DW_LANG_PL1, 1},
-      {DW_LANG_Cobol74, 1},   {DW_LANG_Cobol85, 1}};
+      {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);
@@ -394,10 +397,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;
@@ -468,8 +471,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:
       // ---
@@ -598,8 +600,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)
@@ -689,6 +689,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++;
@@ -990,9 +991,7 @@ 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);
@@ -1143,24 +1142,32 @@ static void MC_post_process_types(simgrid::mc::ObjectInformation* info)
 namespace simgrid {
 namespace 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.second);
+  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)
 {
   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);