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 <assert.h> 23 #include <string.h> 24 #include <ctype.h> 25 26 #include "util.h" 27 #include "DbeSession.h" 28 #include "Application.h" 29 #include "DataObject.h" 30 #include "Module.h" 31 #include "debug.h" 32 33 DataObject::DataObject () 34 { 35 name = NULL; 36 parent = NULL; 37 master = NULL; 38 _unannotated_name = NULL; 39 _typename = NULL; 40 _instname = NULL; 41 scope = NULL; 42 EAs = new Vector<DbeEA*>; 43 size = 0; 44 offset = (uint64_t) (-1); 45 } 46 47 DataObject::~DataObject () 48 { 49 free (_unannotated_name); 50 free (_typename); 51 free (_instname); 52 EAs->destroy (); 53 delete EAs; 54 } 55 56 // get_addr() doesn't return an actual address for a DataObject 57 // but rather synthesises an address-like identifier tuple. 58 // XXXX since an aggregate and its first element have identical tuples 59 // may need to arrange for special-purpose sorting "by address" 60 uint64_t 61 DataObject::get_addr () 62 { 63 uint64_t addr; 64 if (parent && parent->get_typename ()) 65 addr = MAKE_ADDRESS (parent->id, offset); // element 66 else if (parent) 67 addr = MAKE_ADDRESS (parent->id, id) | 0x8000000000000000ULL; // Scalar, Unknown 68 else if (id == dbeSession->get_Scalars_DataObject ()->id) 69 addr = MAKE_ADDRESS (id, 0) | 0x8000000000000000ULL; // Scalar aggregate 70 else if (id == dbeSession->get_Unknown_DataObject ()->id) 71 addr = MAKE_ADDRESS (id, 0) | 0x8000000000000000ULL; // Unknown aggregate 72 else 73 addr = MAKE_ADDRESS (id, 0); // aggregate 74 return addr; 75 } 76 77 Histable * 78 DataObject::convertto (Histable_type type, Histable *) 79 { 80 return type == DOBJECT ? this : NULL; 81 } 82 83 char 84 DataObject::get_offset_mark () 85 { 86 enum 87 { 88 blocksize = 32 89 }; 90 91 if (size == 0 || offset == -1) 92 return '?'; // undefined 93 if (size > blocksize) 94 return '#'; // requires multiple blocks 95 if (size == blocksize && (offset % blocksize == 0)) 96 return '<'; // fits block entirely 97 if (offset % blocksize == 0) 98 return '/'; // starts block 99 if ((offset + size) % blocksize == 0) 100 return '\\'; // closes block 101 if (offset / blocksize == ((offset + size) / blocksize)) 102 return '|'; // inside block 103 return 'X'; // crosses blocks unnecessarily 104 } 105 106 char * 107 DataObject::get_offset_name () 108 { 109 char *offset_name; 110 if (parent && parent->get_typename ()) // element 111 offset_name = dbe_sprintf (GTXT ("%c%+6lld .{%s %s}"), 112 get_offset_mark (), (long long) offset, 113 _typename ? _typename : GTXT ("NO_TYPE"), 114 _instname ? _instname : GTXT ("-")); // "NO_NAME" 115 else if ((offset != -1) && (offset > 0)) // filler 116 offset_name = dbe_sprintf (GTXT ("%c%+6lld %s"), get_offset_mark (), 117 (long long) offset, get_name ()); 118 else if (parent) // Scalar/Unknown element 119 offset_name = dbe_sprintf (GTXT (" .%s"), get_unannotated_name ()); 120 else // aggregate 121 offset_name = dbe_strdup (get_name ()); 122 return offset_name; 123 } 124 125 void 126 DataObject::set_dobjname (char *type_name, char *inst_name) 127 { 128 _unannotated_name = _typename = _instname = NULL; 129 if (inst_name) 130 _instname = dbe_strdup (inst_name); 131 132 char *buf; 133 if (parent == dbeSession->get_Scalars_DataObject ()) 134 { 135 if (type_name) 136 _typename = dbe_strdup (type_name); 137 _unannotated_name = dbe_sprintf (NTXT ("{%s %s}"), type_name, 138 inst_name ? inst_name : NTXT ("-")); 139 buf = dbe_sprintf (NTXT ("%s.%s"), parent->get_name (), _unannotated_name); 140 } 141 else if (parent == dbeSession->get_Unknown_DataObject ()) 142 { 143 _unannotated_name = dbe_strdup (type_name); 144 buf = dbe_sprintf (NTXT ("%s.%s"), parent->get_name (), _unannotated_name); 145 } 146 else 147 { 148 if (type_name) 149 _typename = dbe_strdup (type_name); 150 if (parent && parent->get_typename ()) 151 buf = dbe_sprintf (NTXT ("%s.{%s %s}"), 152 parent->get_name () ? parent->get_name () : NTXT ("ORPHAN"), 153 type_name ? type_name : NTXT ("NO_TYPE"), 154 inst_name ? inst_name : NTXT ("-")); // "NO_NAME" 155 else 156 buf = dbe_sprintf (NTXT ("{%s %s}"), 157 type_name ? type_name : NTXT ("NO_TYPE"), 158 inst_name ? inst_name : NTXT ("-")); // "NO_NAME" 159 } 160 name = buf; 161 dbeSession->dobj_updateHT (this); 162 } 163 164 void 165 DataObject::set_name (char *string) 166 { 167 name = dbe_strdup (string); 168 dbeSession->dobj_updateHT (this); 169 } 170 171 DbeEA * 172 DataObject::find_dbeEA (Vaddr EA) 173 { 174 DbeEA *dbeEA; 175 int left = 0; 176 int right = EAs->size () - 1; 177 while (left <= right) 178 { 179 int index = (left + right) / 2; 180 dbeEA = EAs->fetch (index); 181 if (EA < dbeEA->eaddr) 182 right = index - 1; 183 else if (EA > dbeEA->eaddr) 184 left = index + 1; 185 else 186 return dbeEA; 187 } 188 189 // None found, create a new one 190 dbeEA = new DbeEA (this, EA); 191 EAs->insert (left, dbeEA); 192 return dbeEA; 193 } 194