X-Git-Url: http://info.iut-bm.univ-fcomte.fr/pub/gitweb/simgrid.git/blobdiff_plain/09abefeb928cd7ea4679407a6b4387d4f75beaa9..4c753f8d4cabd4104f3f7109823f16be2ebdcce3:/src/mc/inspect/mc_dwarf.cpp diff --git a/src/mc/inspect/mc_dwarf.cpp b/src/mc/inspect/mc_dwarf.cpp index a11a069d7a..7b0c0f5089 100644 --- a/src/mc/inspect/mc_dwarf.cpp +++ b/src/mc/inspect/mc_dwarf.cpp @@ -1,4 +1,4 @@ -/* Copyright (c) 2008-2021. 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. */ @@ -17,9 +17,11 @@ #include #include +#include #include #include #include +#include #include #include #include @@ -30,8 +32,6 @@ #include #include -#include - XBT_LOG_NEW_DEFAULT_SUBCATEGORY(mc_dwarf, mc, "DWARF processing"); /** @brief The default DW_TAG_lower_bound for a given DW_AT_language. @@ -103,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 }; @@ -204,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 @@ -224,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); @@ -399,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; @@ -473,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: // --- @@ -497,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); @@ -521,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 "; @@ -688,7 +677,7 @@ static std::unique_ptr 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: @@ -742,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. @@ -851,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"); } @@ -868,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; } @@ -963,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 id) +static int find_by_build_id(std::vector id) { std::string filename; std::string hex = to_hex(id); @@ -972,18 +958,19 @@ static std::string find_by_build_id(std::vector 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,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: @@ -1023,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 build_id = get_build_id(elf); - if (not build_id.empty()) { + if (std::vector 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); @@ -1062,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); } @@ -1128,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; } @@ -1137,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 createObjectInformation(std::vector const& maps, const char* name) @@ -1153,12 +1144,6 @@ std::shared_ptr createObjectInformation(std::vector(); 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; } @@ -1166,8 +1151,8 @@ std::shared_ptr createObjectInformation(std::vectortypes) { - 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) @@ -1190,11 +1175,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 * @@ -1204,7 +1187,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__) @@ -1223,5 +1206,4 @@ int dwarf_register_to_libunwind(int dwarf_register) #endif } -} // namespace dwarf -} // namespace simgrid +} // namespace simgrid::dwarf