1 // $Header$
2 //
3 // Copyright (C) 2002 - 2004, by
4 //
5 // Carlo Wood, Run on IRC <carlo@alinoe.com>
6 // RSA-1024 0x624ACAD5 1997-01-26 Sign & Encrypt
7 // Fingerprint16 = 32 EC A7 B6 AC DB 65 A6 F6 F6 55 DD 1C DC FF 61
8 //
9 // This file may be distributed under the terms of the Q Public License
10 // version 1.0 as appearing in the file LICENSE.QPL included in the
11 // packaging of this file.
12 //
13
14 #include "sys.h"
15 #include <libcwd/config.h>
16 #if CWDEBUG_ALLOC
17 #include "cwd_debug.h"
18 #include "cwd_bfd.h"
19 #ifndef LIBCWD_PRIVATE_THREADING_H
20 #include <libcwd/private_threading.h>
21 #endif
22 #ifndef LIBCWD_CLASS_ALLOC_FILTER_H
23 #include <libcwd/class_alloc_filter.h>
24 #endif
25
26 namespace libcwd {
27
28 #if LIBCWD_THREAD_SAFE
29 #define ACQUIRE_LISTALLOC_LOCK mutex_tct<list_allocations_instance>::lock()
30 #define RELEASE_LISTALLOC_LOCK mutex_tct<list_allocations_instance>::unlock()
31 using _private_::mutex_tct;
32 using _private_::list_allocations_instance;
33
34 #else
35 #define ACQUIRE_LISTALLOC_LOCK
36 #define RELEASE_LISTALLOC_LOCK
37 #endif
38
39 #if CWDEBUG_LOCATION
40 int alloc_filter_ct::S_id = 0; // Id of alloc_filter_ct object that is currently synchronized with the other
41 // global variables of the critical area(s) of list_allocations_instance.
42 int alloc_filter_ct::S_next_id = 0; // Id of the last alloc_filter_ct object that was created.
43 #endif
44
45 // Use '1' instead of '0' because 0 is more likely to be used by the user
46 // as an extreme but real limit.
47 struct timeval const alloc_filter_ct::no_time_limit = { 1, 0 };
48
set_flags(alloc_format_t flags)49 void alloc_filter_ct::set_flags(alloc_format_t flags)
50 {
51 #if CWDEBUG_DEBUGT
52 LIBCWD_TSD_DECLARATION;
53 #endif
54 LIBCWD_DEFER_CLEANUP_PUSH(&mutex_tct<list_allocations_instance>::cleanup, NULL);
55 ACQUIRE_LISTALLOC_LOCK;
56 M_flags &= ~format_mask;
57 M_flags |= flags;
58 RELEASE_LISTALLOC_LOCK;
59 LIBCWD_CLEANUP_POP_RESTORE(false);
60 }
61
get_flags(void) const62 alloc_format_t alloc_filter_ct::get_flags(void) const
63 {
64 // Makes little sense to add locking here (alloc_format_t is an atomic type).
65 return (M_flags & format_mask);
66 }
67
set_time_interval(struct timeval const & start,struct timeval const & end)68 void alloc_filter_ct::set_time_interval(struct timeval const& start, struct timeval const& end)
69 {
70 #if CWDEBUG_DEBUGT
71 LIBCWD_TSD_DECLARATION;
72 #endif
73 LIBCWD_DEFER_CLEANUP_PUSH(&mutex_tct<list_allocations_instance>::cleanup, NULL);
74 ACQUIRE_LISTALLOC_LOCK;
75 M_start = start;
76 M_end = end;
77 RELEASE_LISTALLOC_LOCK;
78 LIBCWD_CLEANUP_POP_RESTORE(false);
79 }
80
get_time_start(void) const81 struct timeval alloc_filter_ct::get_time_start(void) const
82 {
83 #if CWDEBUG_DEBUGT
84 LIBCWD_TSD_DECLARATION;
85 #endif
86 struct timeval res;
87 LIBCWD_DEFER_CLEANUP_PUSH(&mutex_tct<list_allocations_instance>::cleanup, NULL);
88 ACQUIRE_LISTALLOC_LOCK;
89 res = M_start;
90 RELEASE_LISTALLOC_LOCK;
91 LIBCWD_CLEANUP_POP_RESTORE(false);
92 return res;
93 }
94
get_time_end(void) const95 struct timeval alloc_filter_ct::get_time_end(void) const
96 {
97 #if CWDEBUG_DEBUGT
98 LIBCWD_TSD_DECLARATION;
99 #endif
100 struct timeval res;
101 LIBCWD_DEFER_CLEANUP_PUSH(&mutex_tct<list_allocations_instance>::cleanup, NULL);
102 ACQUIRE_LISTALLOC_LOCK;
103 res = M_end;
104 RELEASE_LISTALLOC_LOCK;
105 LIBCWD_CLEANUP_POP_RESTORE(false);
106 return res;
107 }
108
109 #if CWDEBUG_LOCATION
get_objectfile_list(void) const110 std::vector<std::string> alloc_filter_ct::get_objectfile_list(void) const
111 {
112 #if CWDEBUG_DEBUGT
113 LIBCWD_TSD_DECLARATION;
114 #endif
115 std::vector<std::string> res;
116 LIBCWD_DEFER_CLEANUP_PUSH(&mutex_tct<list_allocations_instance>::cleanup, NULL);
117 ACQUIRE_LISTALLOC_LOCK;
118 for(vector_type::const_iterator iter = M_objectfile_masks.begin(); iter != M_objectfile_masks.end(); ++iter)
119 res.push_back(std::string(iter->data(), iter->length()));
120 RELEASE_LISTALLOC_LOCK;
121 LIBCWD_CLEANUP_POP_RESTORE(false);
122 return res;
123 }
124
get_sourcefile_list(void) const125 std::vector<std::string> alloc_filter_ct::get_sourcefile_list(void) const
126 {
127 #if CWDEBUG_DEBUGT
128 LIBCWD_TSD_DECLARATION;
129 #endif
130 std::vector<std::string> res;
131 LIBCWD_DEFER_CLEANUP_PUSH(&mutex_tct<list_allocations_instance>::cleanup, NULL);
132 ACQUIRE_LISTALLOC_LOCK;
133 for(vector_type::const_iterator iter = M_sourcefile_masks.begin(); iter != M_sourcefile_masks.end(); ++iter)
134 res.push_back(std::string(iter->data(), iter->length()));
135 RELEASE_LISTALLOC_LOCK;
136 LIBCWD_CLEANUP_POP_RESTORE(false);
137 return res;
138 }
139
get_function_list(void) const140 std::vector<std::pair<std::string, std::string> > alloc_filter_ct::get_function_list(void) const
141 {
142 #if CWDEBUG_DEBUGT
143 LIBCWD_TSD_DECLARATION;
144 #endif
145 std::vector<std::pair<std::string, std::string> > res;
146 LIBCWD_DEFER_CLEANUP_PUSH(&mutex_tct<list_allocations_instance>::cleanup, NULL);
147 ACQUIRE_LISTALLOC_LOCK;
148 for(vector_pair_type::const_iterator iter = M_function_masks.begin(); iter != M_function_masks.end(); ++iter)
149 res.push_back(std::pair<std::string, std::string>(std::string(iter->first.data(), iter->first.length()),
150 std::string(iter->second.data(), iter->second.length())));
151 RELEASE_LISTALLOC_LOCK;
152 LIBCWD_CLEANUP_POP_RESTORE(false);
153 return res;
154 }
155
hide_objectfiles_matching(std::vector<std::string> const & masks)156 void alloc_filter_ct::hide_objectfiles_matching(std::vector<std::string> const& masks)
157 {
158 #if CWDEBUG_DEBUGT
159 LIBCWD_TSD_DECLARATION;
160 #endif
161 LIBCWD_DEFER_CLEANUP_PUSH(&mutex_tct<list_allocations_instance>::cleanup, NULL);
162 ACQUIRE_LISTALLOC_LOCK;
163 M_objectfile_masks.clear();
164 for(std::vector<std::string>::const_iterator iter = masks.begin(); iter != masks.end(); ++iter)
165 M_objectfile_masks.push_back(string_type(iter->data(), iter->length()));
166 S_id = -1; // Force resynchronization.
167 RELEASE_LISTALLOC_LOCK;
168 LIBCWD_CLEANUP_POP_RESTORE(false);
169 }
170
hide_sourcefiles_matching(std::vector<std::string> const & masks)171 void alloc_filter_ct::hide_sourcefiles_matching(std::vector<std::string> const& masks)
172 {
173 #if CWDEBUG_DEBUGT
174 LIBCWD_TSD_DECLARATION;
175 #endif
176 LIBCWD_DEFER_CLEANUP_PUSH(&mutex_tct<list_allocations_instance>::cleanup, NULL);
177 ACQUIRE_LISTALLOC_LOCK;
178 M_sourcefile_masks.clear();
179 for(std::vector<std::string>::const_iterator iter = masks.begin(); iter != masks.end(); ++iter)
180 M_sourcefile_masks.push_back(string_type(iter->data(), iter->length()));
181 S_id = -1; // Force resynchronization.
182 RELEASE_LISTALLOC_LOCK;
183 LIBCWD_CLEANUP_POP_RESTORE(false);
184 }
185
hide_functions_matching(std::vector<std::pair<std::string,std::string>> const & masks)186 void alloc_filter_ct::hide_functions_matching(std::vector<std::pair<std::string, std::string> > const& masks)
187 {
188 #if CWDEBUG_DEBUGT
189 LIBCWD_TSD_DECLARATION;
190 #endif
191 LIBCWD_DEFER_CLEANUP_PUSH(&mutex_tct<list_allocations_instance>::cleanup, NULL);
192 ACQUIRE_LISTALLOC_LOCK;
193 M_sourcefile_masks.clear();
194 for(std::vector<std::pair<std::string, std::string> >::const_iterator iter = masks.begin(); iter != masks.end(); ++iter)
195 M_function_masks.push_back(std::pair<string_type, string_type>
196 (string_type(iter->first.data(), iter->first.length()), string_type(iter->second.data(), iter->second.length())));
197 S_id = -1; // Force resynchronization.
198 RELEASE_LISTALLOC_LOCK;
199 LIBCWD_CLEANUP_POP_RESTORE(false);
200 }
201
check_hide(char const * filepath) const202 _private_::hidden_st alloc_filter_ct::check_hide(char const* filepath) const
203 {
204 for (vector_type::const_iterator iter(M_sourcefile_masks.begin()); iter != M_sourcefile_masks.end(); ++iter)
205 if (_private_::match(iter->data(), iter->length(), filepath))
206 return _private_::filtered_location;
207 return _private_::unfiltered_location;
208 }
209
check_hide(object_file_ct const * object_file,char const * mangled_function_name) const210 _private_::hidden_st alloc_filter_ct::check_hide(object_file_ct const* object_file, char const* mangled_function_name) const
211 {
212 char const* file_path = object_file->filepath();
213 char const* file_name = object_file->filename();
214 for (vector_pair_type::const_iterator iter = M_function_masks.begin(); iter != M_function_masks.end(); ++iter)
215 {
216 char const* objectfile_mask = iter->first.data();
217 size_t objectfile_mask_length = iter->first.length();
218 char c;
219 if ((objectfile_mask_length == 0 ||
220 (((c = *objectfile_mask) == '/' || c == '*') &&
221 _private_::match(objectfile_mask, objectfile_mask_length, file_path)) ||
222 (!(c == '/' || c == '*') &&
223 _private_::match(objectfile_mask, objectfile_mask_length, file_name))) &&
224 (iter->second.length() == 0 ||
225 _private_::match(iter->second.data(), iter->second.length(), mangled_function_name)))
226 return _private_::filtered_location;
227 }
228 return _private_::unfiltered_location;
229 }
230 #endif // CWDEBUG_LOCATION
231
232 #if CWDEBUG_LOCATION
M_synchronize(void) const233 void alloc_filter_ct::M_synchronize(void) const
234 {
235 #if LIBCWD_THREAD_SAFE && CWDEBUG_DEBUG
236 LIBCWD_ASSERT( _private_::is_locked(list_allocations_instance) );
237 #endif
238 BFD_ACQUIRE_WRITE_LOCK;
239 // First clear the list, unhiding everything.
240 for (cwbfd::object_files_ct::iterator iter = cwbfd::NEEDS_WRITE_LOCK_object_files().begin();
241 iter != cwbfd::NEEDS_WRITE_LOCK_object_files().end();
242 ++iter)
243 (*iter)->get_object_file()->M_hide = false;
244 // Next hide what matches.
245 if (!M_objectfile_masks.empty())
246 {
247 for (cwbfd::object_files_ct::iterator iter = cwbfd::NEEDS_WRITE_LOCK_object_files().begin();
248 iter != cwbfd::NEEDS_WRITE_LOCK_object_files().end();
249 ++iter)
250 {
251 for (vector_type::const_iterator iter2(M_objectfile_masks.begin()); iter2 != M_objectfile_masks.end(); ++iter2)
252 if (_private_::match((*iter2).data(), (*iter2).length(), (*iter)->get_object_file()->M_filename))
253 {
254 (*iter)->get_object_file()->M_hide = true;
255 break;
256 }
257 }
258 }
259 BFD_RELEASE_WRITE_LOCK;
260 M_synchronize_locations();
261 S_id = M_id;
262 }
263 #endif
264
alloc_filter_ct(alloc_format_t flags)265 alloc_filter_ct::alloc_filter_ct(alloc_format_t flags) : M_flags(flags & format_mask), M_start(no_time_limit), M_end(no_time_limit)
266 {
267 #if CWDEBUG_LOCATION
268 #if CWDEBUG_DEBUGT
269 LIBCWD_TSD_DECLARATION;
270 #endif
271 LIBCWD_DEFER_CLEANUP_PUSH(&mutex_tct<list_allocations_instance>::cleanup, NULL);
272 ACQUIRE_LISTALLOC_LOCK;
273 M_id = ++S_next_id;
274 RELEASE_LISTALLOC_LOCK;
275 LIBCWD_CLEANUP_POP_RESTORE(false);
276 #endif
277 }
278
279 } // namespace libcwd
280
281 #endif // CWDEBUG_ALLOC
282