1 /* Copyright (c) 2007-2023. The SimGrid Team. All rights reserved. */
3 /* This program is free software; you can redistribute it and/or modify it
4 * under the terms of the license (GNU LGPL) which comes with this package. */
6 #ifndef SIMGRID_MC_OBJECT_INFORMATION_HPP
7 #define SIMGRID_MC_OBJECT_INFORMATION_HPP
11 #include <unordered_map>
14 #include "src/mc/inspect/Frame.hpp"
15 #include "src/mc/inspect/Type.hpp"
16 #include "src/mc/mc_forward.hpp"
17 #include "src/xbt/memory_map.hpp"
19 #include "src/smpi/include/private.hpp"
21 namespace simgrid::mc {
23 /** An entry in the functions index
25 * See the code of ObjectInformation::find_function.
27 struct FunctionIndexEntry {
29 simgrid::mc::Frame* function;
32 /** Information about an ELF module (executable or shared object)
34 * This contains all the information we need about an executable or
35 * shared-object in the model-checked process:
37 * - where it is located in the virtual address space;
39 * - where are located its different memory mappings in the the
40 * virtual address space;
42 * - all the debugging (DWARF) information
44 * - location of the functions and their local variables,
49 class ObjectInformation {
50 bool dwarf_loaded = false; // Lazily loads the dwarf info
53 void ensure_dwarf_loaded(); // Used by functions that need the dwarf
54 ObjectInformation() = default;
57 ObjectInformation(ObjectInformation const&) = delete;
58 ObjectInformation& operator=(ObjectInformation const&) = delete;
61 static const int Executable = 1;
63 /** Bitfield of flags */
65 std::string file_name;
66 const void* start = nullptr;
67 const void* end = nullptr;
68 // Location of its text segment:
69 char* start_exec = nullptr;
70 char* end_exec = nullptr;
71 // Location of the read-only part of its data segment:
72 char* start_rw = nullptr;
73 char* end_rw = nullptr;
74 // Location of the read/write part of its data segment:
75 char* start_ro = nullptr;
76 char* end_ro = nullptr;
78 /** All of its subprograms indexed by their address */
79 std::unordered_map<std::uint64_t, simgrid::mc::Frame> subprograms;
81 /** Index of functions by instruction address
83 * We need to efficiently find the function from any given instruction
84 * address inside its range. This index is sorted by low_pc
86 * The entries are sorted by low_pc and a binary search can be used to look
87 * them up. In order to have a better cache locality, we only keep the
88 * information we need for the lookup in this vector. We could probably
89 * replace subprograms by an ordered vector of Frame and replace this one b
90 * a parallel `std::vector<void*>`.
92 std::vector<FunctionIndexEntry> functions_index;
94 std::vector<simgrid::mc::Variable> global_variables;
96 /** Types indexed by DWARF ID */
97 std::unordered_map<std::uint64_t, simgrid::mc::Type> types;
99 /** Types indexed by name
101 * Different compilation units have their separate type definitions
102 * (for the same type). When we find an opaque type in one compilation unit,
103 * we use this in order to try to find its definition in another compilation
106 std::unordered_map<std::string, simgrid::mc::Type*> full_types_by_name;
108 /** Whether this module is an executable
110 * More precisely we check if this is an ET_EXE ELF. These ELF files
111 * use fixed addresses instead of base-address relative addresses.
112 * Position independent executables are in fact ET_DYN.
114 bool executable() const { return this->flags & simgrid::mc::ObjectInformation::Executable; }
116 /** Base address of the module
118 * All the location information in ELF and DWARF are expressed as an offsets
119 * from this base address:
121 * - location of the functions and global variables
123 * - the DWARF instruction `OP_addr` pushes this on the DWARF stack.
125 void* base_address() const;
127 /** Find a function by instruction address
129 * Loads the dwarf information on need.
131 * @param ip instruction address
132 * @return corresponding function (if any) or nullptr
134 simgrid::mc::Frame* find_function(const void* ip);
136 /** Find a global variable by name
138 * Loads the dwarf information on need.
140 * This is used to ignore global variables and to find well-known variables
141 * (`__mmalloc_default_mdp`).
143 * @param name scopes name of the global variable (`myproject::Foo::count`)
144 * @return corresponding variable (if any) or nullptr
146 const simgrid::mc::Variable* find_variable(const char* name);
148 /** Remove a global variable (in order to ignore it)
150 * This is used to ignore a global variable for the snapshot comparison.
152 void remove_global_variable(const char* name);
154 /** Remove a local variables (in order to ignore it)
156 * @param name Name of the local variable
157 * @param scope scopes name name of the function (myproject::Foo::count) or null for all functions
159 void remove_local_variable(const char* name, const char* scope);
162 XBT_PRIVATE std::shared_ptr<ObjectInformation> createObjectInformation(std::vector<simgrid::xbt::VmMap> const& maps,
165 /** Augment the current module with information about the other ones */
166 XBT_PRIVATE void postProcessObjectInformation(const simgrid::mc::RemoteProcessMemory* process,
167 simgrid::mc::ObjectInformation* info);
168 } // namespace simgrid::mc