return result;
}
-Frame* ObjectInformation::find_function(const void* ip) const
+Frame* ObjectInformation::find_function(const void* ip)
{
+ ensure_dwarf_loaded();
+
/* This is implemented by binary search on a sorted array.
*
* We do quite a lot of those so we want this to be cache efficient.
: nullptr;
}
-const Variable* ObjectInformation::find_variable(const char* var_name) const
+const Variable* ObjectInformation::find_variable(const char* var_name)
{
+ ensure_dwarf_loaded();
+
auto pos = std::lower_bound(this->global_variables.begin(), this->global_variables.end(), var_name,
[](auto const& var, const char* name) { return var.name < name; });
return (pos != this->global_variables.end() && pos->name == var_name) ? &(*pos) : nullptr;
* - etc.
*/
class ObjectInformation {
+ bool dwarf_loaded = false; // Lazily loads the dwarf info
+
public:
+ void ensure_dwarf_loaded(); // Used by functions that need the dwarf
ObjectInformation() = default;
// Not copiable:
void* base_address() const;
/** Find a function by instruction address
+ *
+ * Loads the dwarf information on need.
*
* @param ip instruction address
* @return corresponding function (if any) or nullptr
*/
- simgrid::mc::Frame* find_function(const void* ip) const;
+ simgrid::mc::Frame* find_function(const void* ip);
/** Find a global variable by name
+ *
+ * Loads the dwarf information on need.
*
* This is used to ignore global variables and to find well-known variables
* (`__mmalloc_default_mdp`).
* @param name scopes name of the global variable (`myproject::Foo::count`)
* @return corresponding variable (if any) or nullptr
*/
- const simgrid::mc::Variable* find_variable(const char* name) const;
+ const simgrid::mc::Variable* find_variable(const char* name);
/** Remove a global variable (in order to ignore it)
*
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;
}
this->binary_info = info;
}
- // Resolve time (including across different objects):
- for (auto const& object_info : this->object_infos)
- postProcessObjectInformation(this, object_info.get());
-
xbt_assert(this->maestro_stack_start_, "Did not find maestro_stack_start");
xbt_assert(this->maestro_stack_end_, "Did not find maestro_stack_end");
const simgrid::mc::Variable* var = this->find_variable(name);
xbt_assert(var, "Variable %s not found", name);
xbt_assert(var->address, "No simple location for this variable");
- xbt_assert(var->type->full_type, "Partial type for %s, cannot check size", name);
- xbt_assert((size_t)var->type->full_type->byte_size == size, "Unexpected size for %s (expected %zu, was %zu)", name,
- size, (size_t)var->type->full_type->byte_size);
+
+ if (not var->type->full_type) // Try to resolve this type. The needed ObjectInfo was maybe (lazily) loaded recently
+ for (auto const& object_info : this->object_infos)
+ postProcessObjectInformation(this, object_info.get());
+ xbt_assert(var->type->full_type, "Partial type for %s (even after re-resolving types), cannot retrieve its size.",
+ name);
+ xbt_assert((size_t)var->type->full_type->byte_size == size, "Unexpected size for %s (expected %zu, received %zu).",
+ name, size, (size_t)var->type->full_type->byte_size);
this->read_bytes(target, size, remote(var->address));
}
}
static const simgrid::mc::Variable* test_global_variable(const simgrid::mc::RemoteProcess& process,
- const simgrid::mc::ObjectInformation* info, const char* name,
+ simgrid::mc::ObjectInformation* info, const char* name,
void* address, long byte_size)
{
const simgrid::mc::Variable* variable = info->find_variable(name);