Logo AND Algorithmique Numérique Distribuée

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