]> git.ipfire.org Git - thirdparty/binutils-gdb.git/blob - gprofng/src/MemorySpace.cc
Update year range in gprofng copyright notices
[thirdparty/binutils-gdb.git] / gprofng / src / MemorySpace.cc
1 /* Copyright (C) 2021-2023 Free Software Foundation, Inc.
2 Contributed by Oracle.
3
4 This file is part of GNU Binutils.
5
6 This program is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 3, or (at your option)
9 any later version.
10
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
15
16 You should have received a copy of the GNU General Public License
17 along with this program; if not, write to the Free Software
18 Foundation, 51 Franklin Street - Fifth Floor, Boston,
19 MA 02110-1301, USA. */
20
21 #include "config.h"
22 #include <ctype.h>
23
24 #include "util.h"
25 #include "DbeSession.h"
26 #include "Application.h"
27 #include "Experiment.h"
28 #include "Exp_Layout.h"
29 #include "MetricList.h"
30 #include "MemObject.h"
31 #include "PathTree.h"
32 #include "DbeView.h"
33 #include "Metric.h"
34 #include "MemorySpace.h"
35 #include "Table.h"
36 #include "IndexObject.h"
37
38 MemObjType_t::MemObjType_t ()
39 {
40 type = -1;
41 name = NULL;
42 index_expr = NULL;
43 machmodel = NULL;
44 mnemonic = 0;
45 short_description = NULL;
46 long_description = NULL;
47 }
48
49 MemObjType_t::~MemObjType_t ()
50 {
51 free (name);
52 free (index_expr);
53 free (machmodel);
54 free (short_description);
55 free (long_description);
56 }
57
58 MemorySpace::MemorySpace (DbeView *_dbev, int _mstype)
59 {
60 char *mname;
61 dbev = _dbev;
62 phaseIdx = -1;
63
64 // set up the MemoryObject information
65 objs = new HashMap<uint64_t, MemObj*>;
66 mstype = _mstype;
67 msindex_exp = NULL;
68 msname = NULL;
69 msindex_exp_str = NULL;
70
71 // find the memory space in the table
72 MemObjType_t *mot = findMemSpaceByIndex (mstype);
73 if (mot)
74 {
75 msname = dbe_strdup (mot->name);
76 if (mot->index_expr != NULL)
77 {
78 msindex_exp_str = dbe_strdup (mot->index_expr);
79 msindex_exp = dbeSession->ql_parse (msindex_exp_str);
80 if (msindex_exp == NULL)
81 // this was checked when the definition was created
82 abort ();
83 }
84 }
85
86 // create the Total and Unknown objects
87 mname = dbe_strdup (NTXT ("<Total>"));
88 total_memobj = createMemObject ((uint64_t) - 2, mname);
89 mname = dbe_strdup (GTXT ("<Unknown>"));
90 unk_memobj = createMemObject ((uint64_t) - 1, mname);
91 hist_data_all = NULL;
92 selected_mo_index = (uint64_t) - 3;
93 sel_ind = -1;
94 }
95
96 MemorySpace::~MemorySpace ()
97 {
98 reset ();
99 delete objs;
100 free (msname);
101 free (msindex_exp);
102 free (msindex_exp_str);
103 }
104
105 void
106 MemorySpace::reset ()
107 {
108 if (hist_data_all != NULL)
109 {
110 delete hist_data_all;
111 hist_data_all = NULL;
112 }
113 // do not clear the selected object's index
114 // selected_mo_index = (uint64_t)-3;
115
116 // destroy any existing objects, but keep the vector
117 // Now that we have a hashmap, which has its own vector,
118 // safe to delete and reallocate
119 delete objs;
120 objs = new HashMap<uint64_t, MemObj*>;
121 }
122
123 // find a memory object by its memory-object index
124 int
125 MemorySpace::findMemObject (uint64_t indx)
126 {
127 int index;
128 Hist_data::HistItem *hi;
129 if (indx == (uint64_t) - 3)
130 return -1;
131
132 Vec_loop (Hist_data::HistItem *, hist_data_all->hist_items, index, hi)
133 {
134 if (((uint64_t) ((MemObj *) hi->obj)->id) == indx)
135 return index;
136 }
137 // object does not exist; filter change eliminated it, for example
138 return -1;
139 }
140
141 // find the object referenced in the packet
142 MemObj *
143 MemorySpace::lookupMemObject (Experiment *exp, DataView *packets, long i)
144 {
145 uint64_t idx;
146 uint64_t va = (uint64_t) packets->getLongValue (PROP_VADDR, i);
147 if (va == ABS_UNSUPPORTED)
148 // return NULL, to ignore the record
149 return NULL;
150 if (va < ABS_CODE_RANGE)
151 // The va is not valid, rather, it's an error code
152 // return the <Unknown> object
153 return unk_memobj;
154
155 Expression::Context ctx (dbev, exp, packets, i);
156 idx = msindex_exp->eval (&ctx);
157 if (idx == (uint64_t) - 1)
158 return unk_memobj;
159
160 // do a binary search for the memory object
161 MemObj *res = objs->get (idx);
162 if (res == NULL)
163 {
164 res = createMemObject (idx, NULL);
165 objs->put (idx, res);
166 }
167 else
168 return res;
169
170 // recompute range
171 if (idx < idx_min)
172 idx_min = idx;
173 if (idx > idx_max)
174 idx_max = idx;
175 return res;
176 }
177
178 MemObj *
179 MemorySpace::createMemObject (uint64_t index, char *moname)
180 {
181 MemObj *res;
182 char *name;
183 if (moname != NULL)
184 {
185 res = new MemObj (index, moname);
186 return res;
187 }
188
189 // Custom memory objects
190 // The memory_page_size is defined in the machine model file such
191 // as ./machinemodels/t4.ermm.
192 // Most users prefer to look at the hexadecimal version of virtual
193 // addresses. Display only the hexadecimal version of virtual addresses
194 // for all machine model views with an exception of virtual page size.
195 if (dbe_strcmp (msname, NTXT ("Memory_page_size")) == 0)
196 name = dbe_sprintf (NTXT ("%s 0x%16.16llx (%llu)"), msname,
197 (long long) index, (unsigned long long) index);
198 else if (dbe_strcmp (msname, NTXT ("Memory_in_home_lgrp")) == 0)
199 name = dbe_sprintf (NTXT ("%s: %s"), msname,
200 index == 1 ? GTXT ("True") : index == 0 ? GTXT ("False")
201 : GTXT ("<Unknown>"));
202 else if (dbe_strcmp (msname, NTXT ("Memory_lgrp")) == 0)
203 name = dbe_sprintf (NTXT ("%s %llu"), msname, (unsigned long long) index);
204 else
205 name = dbe_sprintf (NTXT ("%s 0x%16.16llx"), msname, (long long) index);
206
207 res = new MemObj (index, name);
208 return res;
209 }
210
211
212 static Vector<MemObjType_t*> dyn_memobj_vec;
213 static Vector<MemObjType_t*> *dyn_memobj = &dyn_memobj_vec;
214 static Vector<int> *ordlist;
215
216 // Static function to get a vector of custom memory object definitions
217
218 Vector<void*> *
219 MemorySpace::getMemObjects ()
220 {
221 MemObjType_t *mot;
222 int ii;
223 int size = dyn_memobj->size ();
224 Vector<int> *indx = new Vector<int>(size);
225 Vector<char*> *name = new Vector<char*>(size);
226 Vector<char> *mnemonic = new Vector<char>(size);
227 Vector<char*> *formula = new Vector<char*>(size);
228 Vector<char*> *machmodel = new Vector<char*>(size);
229 Vector<int> *order = new Vector<int>(size);
230 Vector<char*> *sdesc = new Vector<char*>(size);
231 Vector<char*> *ldesc = new Vector<char*>(size);
232
233 if (size > 0)
234 {
235 Vec_loop (MemObjType_t *, dyn_memobj, ii, mot)
236 {
237 indx->store (ii, mot->type);
238 order->store (ii, ii);
239 name->store (ii, dbe_strdup (mot->name));
240 formula->store (ii, dbe_strdup (mot->index_expr));
241 mnemonic->store (ii, mot->mnemonic);
242 sdesc->store (ii, mot->short_description == NULL ? NULL
243 : dbe_strdup (mot->short_description));
244 ldesc->store (ii, mot->long_description == NULL ? NULL
245 : dbe_strdup (mot->long_description));
246 if (mot->machmodel == NULL)
247 machmodel->store (ii, NULL);
248 else
249 machmodel->store (ii, dbe_strdup (mot->machmodel));
250 }
251 }
252 Vector<void*> *res = new Vector<void*>(8);
253 res->store (0, indx);
254 res->store (1, name);
255 res->store (2, mnemonic);
256 res->store (3, formula);
257 res->store (4, machmodel);
258 res->store (5, order);
259 res->store (6, sdesc);
260 res->store (7, ldesc);
261 return (res);
262 }
263
264 // Static function to set order of memory object tabs
265 void
266 MemorySpace::set_MemTabOrder (Vector<int> *orders)
267 {
268 int size = orders->size ();
269 ordlist = new Vector<int>(size);
270 for (int i = 0; i < size; i++)
271 ordlist->store (i, orders->fetch (i));
272 }
273
274 // Static function to define a new memory object type
275 char *
276 MemorySpace::mobj_define (char *mname, char *mindex_exp, char *_machmodel,
277 char *short_description, char *long_description)
278 {
279 MemObjType_t *mot;
280
281 if (mname == NULL)
282 return dbe_strdup (GTXT ("No memory object name has been specified."));
283 if (isalpha ((int) (mname[0])) == 0)
284 return dbe_sprintf (GTXT ("Memory Object type name %s does not begin with an alphabetic character"),
285 mname);
286 char *p = mname;
287 while (*p != 0)
288 {
289 if (isalnum ((int) (*p)) == 0 && *p != '_')
290 return dbe_sprintf (GTXT ("Memory Object type name %s contains a non-alphanumeric character"),
291 mname);
292 p++;
293 }
294
295 mot = findMemSpaceByName (mname);
296 if (mot != NULL)
297 {
298 if (strcmp (mot->index_expr, mindex_exp) == 0)
299 // It's a redefinition, but the new definition is the same
300 return NULL;
301 return dbe_sprintf (GTXT ("Memory/Index Object type name %s is already defined"),
302 mname);
303 }
304
305 // make sure the name is not in use
306 if (dbeSession->findIndexSpaceByName (mname) >= 0)
307 return dbe_sprintf (GTXT ("Memory/Index Object type name %s is already defined"),
308 mname);
309
310 if (mindex_exp == NULL || *mindex_exp == 0)
311 return dbe_strdup (GTXT ("No index-expr has been specified."));
312
313 // verify that the index expression parses correctly
314 Expression *e = dbeSession->ql_parse (mindex_exp);
315 if (e == NULL)
316 return dbe_sprintf (GTXT ("Memory Object index expression is invalid: %s"),
317 mindex_exp);
318 delete e;
319
320 // It's OK, create the new table entry
321 char *s = dbeSession->indxobj_define (mname, NULL, mindex_exp,
322 short_description, long_description);
323 if (s)
324 return s;
325 IndexObjType_t *indObj = dbeSession->findIndexSpace (mname);
326
327 mot = new MemObjType_t;
328 mot->type = indObj->type;
329 indObj->memObj = mot;
330 mot->name = dbe_strdup (mname);
331 mot->index_expr = dbe_strdup (mindex_exp);
332 mot->mnemonic = MemorySpace::pickMnemonic (mname);
333 mot->machmodel = dbe_strdup (_machmodel);
334 mot->short_description = dbe_strdup (short_description);
335 mot->long_description = dbe_strdup (long_description);
336
337 // add it to the list
338 dyn_memobj->append (mot);
339
340 // tell the session
341 if (dbeSession != NULL)
342 dbeSession->mobj_define (mot);
343 return NULL;
344 }
345
346 // Static function to delete a new memory object type
347
348 char *
349 MemorySpace::mobj_delete (char *mname)
350 {
351 if (mname == NULL)
352 return dbe_strdup (GTXT ("No memory object name has been specified.\n"));
353
354 // search the dynamic types
355 for (long idx = 0, sz = VecSize (dyn_memobj); idx < sz; idx++)
356 {
357 MemObjType_t *mt = dyn_memobj->get (idx);
358 if (strcasecmp (mt->name, mname) == 0)
359 {
360 // delete it from the vector
361 mt = dyn_memobj->remove (idx);
362 delete mt;
363 dbeSession->removeIndexSpaceByName (mname);
364 return NULL;
365 }
366 }
367 return dbe_sprintf (GTXT ("Memory object `%s' is not defined.\n"), mname);
368 }
369
370 // Static function to get a list of memory object names from a machine model
371
372 Vector <char*> *
373 MemorySpace::getMachineModelMemObjs (char *mname)
374 {
375 Vector <char *> *ret = new Vector <char *> ();
376 if (mname == NULL)
377 return ret;
378
379 // search the memory objects
380 int idx;
381 MemObjType_t *mt;
382 Vec_loop (MemObjType_t*, dyn_memobj, idx, mt)
383 {
384 if (mt->machmodel != NULL && strcmp (mt->machmodel, mname) == 0)
385 {
386 char *n = dbe_strdup (mt->name);
387 ret->append (n);
388 }
389 }
390 return ret;
391 }
392
393 char
394 MemorySpace::pickMnemonic (char *name)
395 {
396 return name[0];
397 }
398
399 void
400 MemorySpace::get_filter_keywords (Vector <void*> *res)
401 {
402 Vector <char*> *kwCategory = (Vector<char*>*) res->fetch (0);
403 Vector <char*> *kwCategoryI18N = (Vector<char*>*) res->fetch (1);
404 Vector <char*> *kwDataType = (Vector<char*>*) res->fetch (2);
405 Vector <char*> *kwKeyword = (Vector<char*>*) res->fetch (3);
406 Vector <char*> *kwFormula = (Vector<char*>*) res->fetch (4);
407 Vector <char*> *kwDescription = (Vector<char*>*) res->fetch (5);
408 Vector <void*> *kwEnumDescs = (Vector<void*>*) res->fetch (6);
409
410 char *vtypeNames[] = VTYPE_TYPE_NAMES;
411 for (int i = 0, sz = dyn_memobj ? dyn_memobj->size () : 0; i < sz; i++)
412 {
413 MemObjType_t *obj = dyn_memobj->fetch (i);
414 kwCategory->append (dbe_strdup (NTXT ("FK_MEMOBJ")));
415 kwCategoryI18N->append (dbe_strdup (GTXT ("Memory Object Definitions")));
416 kwDataType->append (dbe_strdup (vtypeNames[TYPE_INT64]));
417 kwKeyword->append (dbe_strdup (obj->name));
418 kwFormula->append (dbe_strdup (obj->index_expr));
419 kwDescription->append (NULL);
420 kwEnumDescs->append (NULL);
421 }
422 }
423
424 MemObjType_t *
425 MemorySpace::findMemSpaceByName (const char *mname)
426 {
427 int idx;
428 MemObjType_t *mt;
429
430 // search the dynamic types
431 Vec_loop (MemObjType_t*, dyn_memobj, idx, mt)
432 {
433 if (strcasecmp (mt->name, mname) == 0)
434 return mt;
435 }
436 return NULL;
437 }
438
439 MemObjType_t *
440 MemorySpace::findMemSpaceByIndex (int index)
441 {
442 int idx;
443 MemObjType_t *mt;
444
445 // search the dynamic types
446 Vec_loop (MemObjType_t*, dyn_memobj, idx, mt)
447 {
448 if (mt->type == index)
449 return mt;
450 }
451 return NULL;
452 }