-/* 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. */
#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 <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");
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}
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);
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;
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:
// ---
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)
// 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++;
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);
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);