Logo AND Algorithmique Numérique Distribuée

Public GIT Repository
[mc] Remove MCer_ignore_global_variable
[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 }
137 }