Logo AND Algorithmique Numérique Distribuée

Public GIT Repository
[mc] Bring back KSM (MADV_MERGEABLE) support
[simgrid.git] / src / mc / mc_dwarf.cpp
1 /* Copyright (c) 2008-2015. The SimGrid Team.
2  * All rights reserved.                                                     */
3
4 /* This program is free software; you can redistribute it and/or modify it
5  * under the terms of the license (GNU LGPL) which comes with this package. */
6
7 #include <cinttypes>
8 #include <cstdint>
9
10 #include <algorithm>
11 #include <memory>
12
13 #include <stdlib.h>
14 #define DW_LANG_Objc DW_LANG_ObjC       /* fix spelling error in older dwarf.h */
15
16 #include <simgrid/util.hpp>
17 #include <xbt/log.h>
18 #include <xbt/sysdep.h>
19
20 #include <simgrid/util.hpp>
21
22 #include "mc/mc_dwarf.hpp"
23 #include "mc/mc_dwarf.hpp"
24 #include "mc/mc_private.h"
25 #include "mc/mc_process.h"
26
27 #include "mc/ObjectInformation.hpp"
28 #include "mc/Variable.hpp"
29
30 XBT_LOG_NEW_DEFAULT_SUBCATEGORY(mc_dwarf, mc, "DWARF processing");
31
32 // ***** Functions index
33
34 static int MC_compare_frame_index_items(simgrid::mc::FunctionIndexEntry* a,
35                                         simgrid::mc::FunctionIndexEntry* b)
36 {
37   if (a->low_pc < b->low_pc)
38     return -1;
39   else if (a->low_pc == b->low_pc)
40     return 0;
41   else
42     return 1;
43 }
44
45 static void MC_make_functions_index(simgrid::mc::ObjectInformation* info)
46 {
47   info->functions_index.clear();
48
49   for (auto& e : info->subprograms) {
50     if (e.second.low_pc == nullptr)
51       continue;
52     simgrid::mc::FunctionIndexEntry entry;
53     entry.low_pc = e.second.low_pc;
54     entry.function = &e.second;
55     info->functions_index.push_back(entry);
56   }
57
58   info->functions_index.shrink_to_fit();
59
60   // Sort the array by low_pc:
61   std::sort(info->functions_index.begin(), info->functions_index.end(),
62         [](simgrid::mc::FunctionIndexEntry const& a,
63           simgrid::mc::FunctionIndexEntry const& b)
64         {
65           return a.low_pc < b.low_pc;
66         });
67 }
68
69 static void MC_post_process_variables(simgrid::mc::ObjectInformation* info)
70 {
71   // Someone needs this to be sorted but who?
72   std::sort(info->global_variables.begin(), info->global_variables.end(),
73     MC_compare_variable);
74
75   for(simgrid::mc::Variable& variable : info->global_variables)
76     if (variable.type_id)
77       variable.type = simgrid::util::find_map_ptr(
78         info->types, variable.type_id);
79 }
80
81 static void mc_post_process_scope(
82   simgrid::mc::ObjectInformation* info, simgrid::mc::Frame* scope)
83 {
84
85   if (scope->tag == DW_TAG_inlined_subroutine) {
86     // Attach correct namespaced name in inlined subroutine:
87     auto i = info->subprograms.find(scope->abstract_origin_id);
88     xbt_assert(i != info->subprograms.end(),
89       "Could not lookup abstract origin %" PRIx64,
90       (std::uint64_t) scope->abstract_origin_id);
91     scope->name = i->second.name;
92   }
93
94   // Direct:
95   for (simgrid::mc::Variable& variable : scope->variables)
96     if (variable.type_id)
97       variable.type = simgrid::util::find_map_ptr(
98         info->types, variable.type_id);
99
100   // Recursive post-processing of nested-scopes:
101   for (simgrid::mc::Frame& nested_scope : scope->scopes)
102       mc_post_process_scope(info, &nested_scope);
103
104 }
105
106 /** \brief Fill/lookup the "subtype" field.
107  */
108 static void MC_resolve_subtype(
109   simgrid::mc::ObjectInformation* info, simgrid::mc::Type* type)
110 {
111   if (!type->type_id)
112     return;
113   type->subtype = simgrid::util::find_map_ptr(info->types, type->type_id);
114   if (type->subtype == nullptr)
115     return;
116   if (type->subtype->byte_size != 0)
117     return;
118   if (type->subtype->name.empty())
119     return;
120   // Try to find a more complete description of the type:
121   // We need to fix in order to support C++.
122   simgrid::mc::Type** subtype = simgrid::util::find_map_ptr(
123     info->full_types_by_name, type->subtype->name);
124   if (subtype)
125     type->subtype = *subtype;
126 }
127
128 static void MC_post_process_types(simgrid::mc::ObjectInformation* info)
129 {
130   // Lookup "subtype" field:
131   for(auto& i : info->types) {
132     MC_resolve_subtype(info, &(i.second));
133     for (simgrid::mc::Type& member : i.second.members)
134       MC_resolve_subtype(info, &member);
135   }
136 }
137
138 /** \brief Finds informations about a given shared object/executable */
139 std::shared_ptr<simgrid::mc::ObjectInformation> MC_find_object_info(
140   std::vector<simgrid::mc::VmMap> const& maps, const char *name, int executable)
141 {
142   std::shared_ptr<simgrid::mc::ObjectInformation> result =
143     std::make_shared<simgrid::mc::ObjectInformation>();
144   if (executable)
145     result->flags |= simgrid::mc::ObjectInformation::Executable;
146   result->file_name = name;
147   MC_find_object_address(maps, result.get());
148   MC_dwarf_get_variables(result.get());
149   MC_post_process_variables(result.get());
150   MC_post_process_types(result.get());
151   for (auto& entry : result.get()->subprograms)
152     mc_post_process_scope(result.get(), &entry.second);
153   MC_make_functions_index(result.get());
154   return std::move(result);
155 }
156
157 /*************************************************************************/
158
159 void MC_post_process_object_info(simgrid::mc::Process* process, simgrid::mc::ObjectInformation* info)
160 {
161   for (auto& i : info->types) {
162
163     simgrid::mc::Type* type = &(i.second);
164     simgrid::mc::Type* subtype = type;
165     while (subtype->type == DW_TAG_typedef
166         || subtype->type == DW_TAG_volatile_type
167         || subtype->type == DW_TAG_const_type)
168       if (subtype->subtype)
169         subtype = subtype->subtype;
170       else
171         break;
172
173     // Resolve full_type:
174     if (!subtype->name.empty() && subtype->byte_size == 0) {
175       for (auto const& object_info : process->object_infos) {
176         auto i = object_info->full_types_by_name.find(subtype->name);
177         if (i != object_info->full_types_by_name.end()
178             && !i->second->name.empty() && i->second->byte_size) {
179           type->full_type = i->second;
180           break;
181         }
182       }
183     } else type->full_type = subtype;
184
185   }
186 }