-/* Copyright (c) 2008-2015. The SimGrid Team.
+/* Copyright (c) 2008-2018. The SimGrid Team.
* All rights reserved. */
/* This program is free software; you can redistribute it and/or modify it
#include <fcntl.h>
#include <cstdlib>
-#define DW_LANG_Objc DW_LANG_ObjC /* fix spelling error in older dwarf.h */
-#include <dwarf.h>
#include <elfutils/libdw.h>
#include <boost/algorithm/string/predicate.hpp>
-#include <simgrid_config.h>
#include "src/simgrid/util.hpp"
-#include <xbt/log.h>
-#include <xbt/sysdep.h>
+#include "xbt/log.h"
+#include "xbt/string.hpp"
+#include "xbt/sysdep.h"
+#include <simgrid/config.h>
-#include "src/mc/mc_private.h"
#include "src/mc/mc_dwarf.hpp"
+#include "src/mc/mc_private.hpp"
-#include "src/mc/Process.hpp"
#include "src/mc/ObjectInformation.hpp"
#include "src/mc/Variable.hpp"
+#include "src/mc/remote/RemoteClient.hpp"
XBT_LOG_NEW_DEFAULT_SUBCATEGORY(mc_dwarf, mc, "DWARF processing");
int attribute)
{
Dwarf_Attribute attr;
- if (!dwarf_attr_integrate(die, attribute, &attr))
+ if (not dwarf_attr_integrate(die, attribute, &attr))
return nullptr;
else
return dwarf_formstring(&attr);
}
-/** \brief Get the linkage name of a DIE.
- *
- * Use either DW_AT_linkage_name or DW_AT_MIPS_linkage_name.
- * DW_AT_linkage_name is standardized since DWARF 4.
- * Before this version of DWARF, the MIPS extensions
- * DW_AT_MIPS_linkage_name is used (at least by GCC).
- *
- * \param the DIE
- * \return linkage name of the given DIE (or nullptr)
- * */
-static const char *MC_dwarf_at_linkage_name(Dwarf_Die * die)
-{
- const char *name = MC_dwarf_attr_integrate_string(die, DW_AT_linkage_name);
- if (!name)
- name = MC_dwarf_attr_integrate_string(die, DW_AT_MIPS_linkage_name);
- return name;
-}
-
static Dwarf_Off MC_dwarf_attr_dieoffset(Dwarf_Die * die, int attribute)
{
Dwarf_Attribute attr;
/** \brief Find the type/subtype (DW_AT_type) for a DIE
*
- * \param dit the DIE
+ * \param die the DIE
* \return DW_AT_type reference as a global offset in hexadecimal (or nullptr)
*/
static
return MC_dwarf_attr_integrate_uint(die, DW_AT_count, 0);
// Otherwise compute DW_TAG_upper_bound-DW_TAG_lower_bound + 1:
- if (!dwarf_hasattr_integrate(die, DW_AT_upper_bound))
+ if (not dwarf_hasattr_integrate(die, DW_AT_upper_bound))
// This is not really 0, but the code expects this (we do not know):
return 0;
- uint64_t upper_bound =
- MC_dwarf_attr_integrate_uint(die, DW_AT_upper_bound, -1);
+ uint64_t upper_bound = MC_dwarf_attr_integrate_uint(die, DW_AT_upper_bound, static_cast<uint64_t>(-1));
uint64_t lower_bound = 0;
if (dwarf_hasattr_integrate(die, DW_AT_lower_bound))
- lower_bound = MC_dwarf_attr_integrate_uint(die, DW_AT_lower_bound, -1);
+ lower_bound = MC_dwarf_attr_integrate_uint(die, DW_AT_lower_bound, static_cast<uint64_t>(-1));
else
lower_bound = MC_dwarf_default_lower_bound(dwarf_srclang(unit));
return upper_bound - lower_bound + 1;
if (dwarf_hasattr(child, DW_AT_data_bit_offset))
xbt_die("Can't groke DW_AT_data_bit_offset.");
- if (!dwarf_hasattr_integrate(child, DW_AT_data_member_location)) {
+ if (not dwarf_hasattr_integrate(child, DW_AT_data_member_location)) {
if (type->type == DW_TAG_union_type)
return;
xbt_die
// Offset from the base address of the object:
{
Dwarf_Word offset;
- if (!dwarf_formudata(&attr, &offset))
+ if (not dwarf_formudata(&attr, &offset))
member->offset(offset);
else
xbt_die("Cannot get %s location <%" PRIx64 ">%s",
(uint64_t) type->id, type->name.c_str());
break;
}
- case simgrid::dwarf::FormClass::LocListPtr:
- // Reference to a location list:
- // TODO
- case simgrid::dwarf::FormClass::Reference:
- // It's supposed to be possible in DWARF2 but I couldn't find its semantic
- // in the spec.
+
default:
- xbt_die("Can't handle form class (%i) / form 0x%x as DW_AT_member_location",
- (int) form_class, form);
+ // includes FormClass::LocListPtr (reference to a location list: TODO) and FormClass::Reference (it's supposed to be
+ // possible in DWARF2 but I couldn't find its semantic in the spec)
+ xbt_die("Can't handle form class (%d) / form 0x%x as DW_AT_member_location", (int)form_class, (unsigned)form);
}
}
MC_dwarf_fill_member_location(type, &member, &child);
- if (!member.type_id)
+ if (not member.type_id)
xbt_die("Missing type for member %s of <%" PRIx64 ">%s",
member.name.c_str(),
(uint64_t) type->id, type->name.c_str());
/** \brief Create a MC type object from a DIE
*
* \param info current object info object
- * \param DIE (for a given type);
+ * \param die DIE (for a given type)
* \param unit compilation unit of the current DIE
* \return MC representation of the type
*/
const char *name = MC_dwarf_attr_integrate_string(die, DW_AT_name);
if (name != nullptr) {
- char* full_name = ns ? bprintf("%s%s::%s", prefix, ns, name) :
- bprintf("%s%s", prefix, name);
- type.name = std::string(full_name);
- free(full_name);
+ if (ns)
+ type.name = simgrid::xbt::string_printf("%s%s::%s", prefix, ns, name);
+ else
+ type.name = simgrid::xbt::string_printf("%s%s", prefix, name);
}
type.type_id = MC_dwarf_at_type(die);
if (type.type == DW_TAG_pointer_type)
type.byte_size = sizeof(void*);
- // Computation of the byte_size;
+ // Computation of the byte_size
if (dwarf_hasattr_integrate(die, DW_AT_byte_size))
type.byte_size = MC_dwarf_attr_integrate_uint(die, DW_AT_byte_size, 0);
else if (type.type == DW_TAG_array_type
case DW_TAG_union_type:
case DW_TAG_class_type:
MC_dwarf_add_members(info, die, unit, &type);
- char *new_ns = ns == nullptr ? xbt_strdup(type.name.c_str())
- : bprintf("%s::%s", ns, name);
- MC_dwarf_handle_children(info, die, unit, frame, new_ns);
- free(new_ns);
+ MC_dwarf_handle_children(info, die, unit, frame,
+ ns ? simgrid::xbt::string_printf("%s::%s", ns, name).c_str() : type.name.c_str());
+ break;
+
+ default:
+ XBT_DEBUG("Unhandled type: %d (%s)", type.type, simgrid::dwarf::tagname(type.type));
break;
}
{
simgrid::mc::Type type = MC_dwarf_die_to_type(info, die, unit, frame, ns);
auto& t = (info->types[type.id] = std::move(type));
- if (!t.name.empty() && type.byte_size != 0)
+ if (not t.name.empty() && type.byte_size != 0)
info->full_types_by_name[t.name] = &t;
}
variable->address = (void *) (base + offset);
} else
variable->location_list = {
- simgrid::dwarf::DwarfExpression(expr, expr + len) };
+ simgrid::dwarf::LocationListEntry(simgrid::dwarf::DwarfExpression(expr, expr + len))};
break;
}
break;
default:
- xbt_die("Unexpected form 0x%x (%i), class 0x%x (%i) list for location "
- "in <%" PRIx64 ">%s",
- form, form, (int) form_class, (int) form_class,
- (uint64_t) variable->id,
- variable->name.c_str());
+ xbt_die("Unexpected form 0x%x (%i), class 0x%x (%i) list for location in <%" PRIx64 ">%s", (unsigned)form, form,
+ (unsigned)form_class, (int)form_class, (uint64_t)variable->id, variable->name.c_str());
}
// Handle start_scope:
dwarf_attr(die, DW_AT_start_scope, &attr);
int form = dwarf_whatform(&attr);
simgrid::dwarf::FormClass form_class = simgrid::dwarf::classify_form(form);
- switch (form_class) {
- case simgrid::dwarf::FormClass::Constant:
- {
- Dwarf_Word value;
- variable->start_scope =
- dwarf_formudata(&attr, &value) == 0 ? (size_t) value : 0;
- break;
- }
-
- case simgrid::dwarf::FormClass::RangeListPtr: // TODO
- default:
- xbt_die
- ("Unhandled form 0x%x, class 0x%X for DW_AT_start_scope of variable %s",
- form, (int) form_class, name == nullptr ? "?" : name);
+ if (form_class == simgrid::dwarf::FormClass::Constant) {
+ Dwarf_Word value;
+ variable->start_scope = dwarf_formudata(&attr, &value) == 0 ? (size_t)value : 0;
+ } else {
+ // TODO: FormClass::RangeListPtr
+ xbt_die("Unhandled form 0x%x, class 0x%X for DW_AT_start_scope of variable %s", (unsigned)form,
+ (unsigned)form_class, name == nullptr ? "?" : name);
}
}
// The current code needs a variable name,
// generate a fake one:
- if (variable->name.empty())
- variable->name =
- "@anonymous#" + std::to_string(mc_anonymous_variable_index++);
-
+ if (variable->name.empty()) {
+ variable->name = "@anonymous#" + std::to_string(mc_anonymous_variable_index);
+ mc_anonymous_variable_index++;
+ }
return variable;
}
{
std::unique_ptr<simgrid::mc::Variable> variable =
MC_die_to_variable(info, die, unit, frame, ns);
- if (!variable)
+ if (not variable)
return;
// Those arrays are sorted later:
- else if (variable->global)
+ if (variable->global)
info->global_variables.push_back(std::move(*variable));
else if (frame != nullptr)
frame->variables.push_back(std::move(*variable));
if (low_pc) {
// DW_AT_high_pc:
Dwarf_Attribute attr;
- if (!dwarf_attr_integrate(die, DW_AT_high_pc, &attr))
+ if (not dwarf_attr_integrate(die, DW_AT_high_pc, &attr))
xbt_die("Missing DW_AT_high_pc matching with DW_AT_low_pc");
Dwarf_Sword offset;
{
std::string filename;
std::string hex = to_hex(id);
- for (const char* debug_path : debug_paths) {
+ for (const char* const& debug_path : debug_paths) {
// Example:
filename = std::string(debug_path) + ".build-id/"
+ to_hex(id.data(), 1) + '/'
// 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 informations:
- // * GNU NT_GNU_BUILD_ID;
- // * .gnu_debuglink.
+ // * GNU NT_GNU_BUILD_ID
+ // * .gnu_debuglink
// See https://sourceware.org/gdb/onlinedocs/gdb/Separate-Debug-Files.html
// for reference of what we are doing.
// 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 (!build_id.empty()) {
+ if (not build_id.empty()) {
elf_end(elf);
close(fd);
// ***** Functions index
-static int MC_compare_frame_index_items(simgrid::mc::FunctionIndexEntry* a,
- simgrid::mc::FunctionIndexEntry* b)
-{
- if (a->low_pc < b->low_pc)
- return -1;
- else if (a->low_pc == b->low_pc)
- return 0;
- else
- return 1;
-}
-
static void MC_make_functions_index(simgrid::mc::ObjectInformation* info)
{
info->functions_index.clear();
// Someone needs this to be sorted but who?
boost::range::sort(info->global_variables, MC_compare_variable);
- for(simgrid::mc::Variable& variable : info->global_variables)
+ for (simgrid::mc::Variable& variable : info->global_variables)
if (variable.type_id)
variable.type = simgrid::util::find_map_ptr(
info->types, variable.type_id);
// Recursive post-processing of nested-scopes:
for (simgrid::mc::Frame& nested_scope : scope->scopes)
- mc_post_process_scope(info, &nested_scope);
-
+ mc_post_process_scope(info, &nested_scope);
}
static
simgrid::mc::Type* MC_resolve_type(
simgrid::mc::ObjectInformation* info, unsigned type_id)
{
- if (!type_id)
+ if (not type_id)
return nullptr;
simgrid::mc::Type* type = simgrid::util::find_map_ptr(info->types, type_id);
if (type == nullptr)
static void MC_post_process_types(simgrid::mc::ObjectInformation* info)
{
// Lookup "subtype" field:
- for(auto& i : info->types) {
+ for (auto& i : info->types) {
i.second.subtype = MC_resolve_type(info, i.second.type_id);
for (simgrid::mc::Member& member : i.second.members)
member.type = MC_resolve_type(info, member.type_id);
/*************************************************************************/
-void postProcessObjectInformation(simgrid::mc::Process* process, simgrid::mc::ObjectInformation* info)
+void postProcessObjectInformation(simgrid::mc::RemoteClient* process, simgrid::mc::ObjectInformation* info)
{
for (auto& i : info->types) {
break;
// Resolve full_type:
- if (!subtype->name.empty() && subtype->byte_size == 0)
+ if (not subtype->name.empty() && subtype->byte_size == 0)
for (auto const& object_info : process->object_infos) {
auto i = object_info->full_types_by_name.find(subtype->name);
- if (i != object_info->full_types_by_name.end()
- && !i->second->name.empty() && i->second->byte_size) {
+ if (i != object_info->full_types_by_name.end() && not i->second->name.empty() && i->second->byte_size) {
type->full_type = i->second;
break;
}