MemorySpace.cc revision 1.1.1.1
1/* Copyright (C) 2021 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 38MemObjType_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 49MemObjType_t::~MemObjType_t () 50{ 51 free (name); 52 free (index_expr); 53 free (machmodel); 54 free (short_description); 55 free (long_description); 56} 57 58MemorySpace::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 96MemorySpace::~MemorySpace () 97{ 98 reset (); 99 delete objs; 100 free (msname); 101 free (msindex_exp); 102 free (msindex_exp_str); 103} 104 105void 106MemorySpace::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 124int 125MemorySpace::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 142MemObj * 143MemorySpace::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 178MemObj * 179MemorySpace::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 212static Vector<MemObjType_t*> dyn_memobj_vec; 213static Vector<MemObjType_t*> *dyn_memobj = &dyn_memobj_vec; 214static Vector<int> *ordlist; 215 216// Static function to get a vector of custom memory object definitions 217 218Vector<void*> * 219MemorySpace::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 265void 266MemorySpace::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 275char * 276MemorySpace::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 348char * 349MemorySpace::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 372Vector <char*> * 373MemorySpace::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 393char 394MemorySpace::pickMnemonic (char *name) 395{ 396 return name[0]; 397} 398 399void 400MemorySpace::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 424MemObjType_t * 425MemorySpace::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 439MemObjType_t * 440MemorySpace::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} 453