Logo AND Algorithmique Numérique Distribuée

Public GIT Repository
[mc] Move ignore_local_variable() into Process
[simgrid.git] / src / mc / ObjectInformation.cpp
1 #include "src/mc/Frame.hpp"
2 #include "src/mc/ObjectInformation.hpp"
3 #include "src/mc/Variable.hpp"
4
5 namespace simgrid {
6 namespace mc {
7
8 ObjectInformation::ObjectInformation()
9 {
10   this->flags = 0;
11   this->start = nullptr;
12   this->end = nullptr;
13   this->start_exec = nullptr;
14   this->end_exec = nullptr;
15   this->start_rw = nullptr;
16   this->end_rw = nullptr;
17   this->start_ro = nullptr;
18   this->end_ro = nullptr;
19 }
20
21 /** Find the DWARF offset for this ELF object
22  *
23  *  An offset is applied to address found in DWARF:
24  *
25  *  * for an executable obejct, addresses are virtual address
26  *    (there is no offset) i.e.
27  *    \f$\text{virtual address} = \{dwarf address}\f$;
28  *
29  *  * for a shared object, the addreses are offset from the begining
30  *    of the shared object (the base address of the mapped shared
31  *    object must be used as offset
32  *    i.e. \f$\text{virtual address} = \text{shared object base address}
33  *             + \text{dwarf address}\f$.
34  */
35 void *ObjectInformation::base_address() const
36 {
37   if (this->executable())
38     return nullptr;
39
40   void *result = this->start_exec;
41   if (this->start_rw != NULL && result > (void *) this->start_rw)
42     result = this->start_rw;
43   if (this->start_ro != NULL && result > (void *) this->start_ro)
44     result = this->start_ro;
45   return result;
46 }
47
48 /* Find a function by instruction pointer */
49 simgrid::mc::Frame* ObjectInformation::find_function(const void *ip) const
50 {
51   /* This is implemented by binary search on a sorted array.
52    *
53    * We do quite a lot ot those so we want this to be cache efficient.
54    * We pack the only information we need in the index entries in order
55    * to successfully do the binary search. We do not need the high_pc
56    * during the binary search (only at the end) so it is not included
57    * in the index entry. We could use parallel arrays as well.
58    *
59    * We cannot really use the std:: alogrithm for this.
60    * We could use std::binary_search by including the high_pc inside
61    * the FunctionIndexEntry.
62    */
63   const simgrid::mc::FunctionIndexEntry* base =
64     this->functions_index.data();
65   int i = 0;
66   int j = this->functions_index.size() - 1;
67   while (j >= i) {
68     int k = i + ((j - i) / 2);
69
70     /* In most of the search, we do not dereference the base[k].function.
71      * This way the memory accesses are located in the base[k] array. */
72     if (ip < base[k].low_pc)
73       j = k - 1;
74     else if (k < j && ip >= base[k + 1].low_pc)
75       i = k + 1;
76
77     /* At this point, the search is over.
78      * Either we have found the correct function or we do not know
79      * any function corresponding to this instruction address.
80      * Only at the point do we derefernce the function pointer. */
81     else if (ip < base[k].function->high_pc)
82       return base[k].function;
83     else
84       return nullptr;
85   }
86   return nullptr;
87 }
88
89 simgrid::mc::Variable* ObjectInformation::find_variable(const char* name) const
90 {
91   for (simgrid::mc::Variable& variable : this->global_variables)
92     if(variable.name == name)
93       return &variable;
94   return nullptr;
95 }
96
97 void ObjectInformation::remove_global_variable(const char* name)
98 {
99   typedef std::vector<Variable>::size_type size_type;
100
101   if (this->global_variables.empty())
102     return;
103
104   // Binary search:
105   size_type start = 0;
106   size_type end = this->global_variables.size() - 1;
107
108   while (start <= end) {
109     size_type cursor = start + (end - start) / 2;
110     simgrid::mc::Variable& current_var = this->global_variables[cursor];
111     int cmp = current_var.name.compare(name);
112
113     if (cmp == 0) {
114       // Find the whole range:
115       start = cursor;
116       while (start != 0 && this->global_variables[start - 1].name == name)
117         start--;
118       size_type size = this->global_variables.size();
119       end = cursor;
120       while (end != size - 1 && this->global_variables[end + 1].name == name)
121         end++;
122       // Remove the whole range:
123       this->global_variables.erase(
124         this->global_variables.begin() + cursor,
125         this->global_variables.begin() + end + 1);
126       return;
127     } else if (cmp < 0)
128       start = cursor + 1;
129     else if (cursor != 0)
130       end = cursor - 1;
131     else
132       break;
133   }
134 }
135
136 /** \brief Ignore a local variable in a scope
137  *
138  *  Ignore all instances of variables with a given name in
139  *  any (possibly inlined) subprogram with a given namespaced
140  *  name.
141  *
142  *  \param var_name        Name of the local variable (or parameter to ignore)
143  *  \param subprogram_name Name of the subprogram fo ignore (NULL for any)
144  *  \param subprogram      (possibly inlined) Subprogram of the scope
145  *  \param scope           Current scope
146  */
147 static void remove_local_variable(simgrid::mc::Frame& scope,
148                             const char *var_name,
149                             const char *subprogram_name,
150                             simgrid::mc::Frame const& subprogram)
151 {
152   typedef std::vector<Variable>::size_type size_type;
153
154   // If the current subprogram matches the given name:
155   if ((subprogram_name == nullptr ||
156       (!subprogram.name.empty()
157         && subprogram.name == subprogram_name))
158       && !scope.variables.empty()) {
159
160     // Try to find the variable and remove it:
161     size_type start = 0;
162     size_type end = scope.variables.size() - 1;
163
164     // Binary search:
165     while (start <= end) {
166       size_type cursor = start + (end - start) / 2;
167       simgrid::mc::Variable& current_var = scope.variables[cursor];
168       int compare = current_var.name.compare(var_name);
169       if (compare == 0) {
170         // Variable found, remove it:
171         scope.variables.erase(scope.variables.begin() + cursor);
172         break;
173       } else if (compare < 0)
174         start = cursor + 1;
175       else if (cursor != 0)
176         end = cursor - 1;
177       else
178         break;
179     }
180   }
181
182   // And recursive processing in nested scopes:
183   for (simgrid::mc::Frame& nested_scope : scope.scopes) {
184     // The new scope may be an inlined subroutine, in this case we want to use its
185     // namespaced name in recursive calls:
186     simgrid::mc::Frame const& nested_subprogram =
187         nested_scope.tag ==
188         DW_TAG_inlined_subroutine ? nested_scope : subprogram;
189     remove_local_variable(nested_scope, var_name, subprogram_name,
190                           nested_subprogram);
191   }
192 }
193
194 void ObjectInformation::remove_local_variable(
195   const char* var_name, const char* subprogram_name)
196 {
197   for (auto& entry : this->subprograms)
198     simgrid::mc::remove_local_variable(entry.second,
199       var_name, subprogram_name, entry.second);
200 }
201
202 }
203 }