| /* Copyright (C) 2021-2024 Free Software Foundation, Inc. |
| Contributed by Oracle. |
| |
| This file is part of GNU Binutils. |
| |
| This program is free software; you can redistribute it and/or modify |
| it under the terms of the GNU General Public License as published by |
| the Free Software Foundation; either version 3, or (at your option) |
| any later version. |
| |
| This program is distributed in the hope that it will be useful, |
| but WITHOUT ANY WARRANTY; without even the implied warranty of |
| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
| GNU General Public License for more details. |
| |
| You should have received a copy of the GNU General Public License |
| along with this program; if not, write to the Free Software |
| Foundation, 51 Franklin Street - Fifth Floor, Boston, |
| MA 02110-1301, USA. */ |
| |
| #include "config.h" |
| #include <assert.h> |
| #include <string.h> |
| #include <ctype.h> |
| |
| #include "util.h" |
| #include "DbeSession.h" |
| #include "Application.h" |
| #include "DataObject.h" |
| #include "Module.h" |
| #include "debug.h" |
| |
| DataObject::DataObject () |
| { |
| name = NULL; |
| parent = NULL; |
| master = NULL; |
| _unannotated_name = NULL; |
| _typename = NULL; |
| _instname = NULL; |
| scope = NULL; |
| EAs = new Vector<DbeEA*>; |
| size = 0; |
| offset = (uint64_t) (-1); |
| } |
| |
| DataObject::~DataObject () |
| { |
| free (_unannotated_name); |
| free (_typename); |
| free (_instname); |
| EAs->destroy (); |
| delete EAs; |
| } |
| |
| // get_addr() doesn't return an actual address for a DataObject |
| // but rather synthesises an address-like identifier tuple. |
| // XXXX since an aggregate and its first element have identical tuples |
| // may need to arrange for special-purpose sorting "by address" |
| uint64_t |
| DataObject::get_addr () |
| { |
| uint64_t addr; |
| if (parent && parent->get_typename ()) |
| addr = MAKE_ADDRESS (parent->id, offset); // element |
| else if (parent) |
| addr = MAKE_ADDRESS (parent->id, id) | 0x8000000000000000ULL; // Scalar, Unknown |
| else if (id == dbeSession->get_Scalars_DataObject ()->id) |
| addr = MAKE_ADDRESS (id, 0) | 0x8000000000000000ULL; // Scalar aggregate |
| else if (id == dbeSession->get_Unknown_DataObject ()->id) |
| addr = MAKE_ADDRESS (id, 0) | 0x8000000000000000ULL; // Unknown aggregate |
| else |
| addr = MAKE_ADDRESS (id, 0); // aggregate |
| return addr; |
| } |
| |
| Histable * |
| DataObject::convertto (Histable_type type, Histable *) |
| { |
| return type == DOBJECT ? this : NULL; |
| } |
| |
| char |
| DataObject::get_offset_mark () |
| { |
| enum |
| { |
| blocksize = 32 |
| }; |
| |
| if (size == 0 || offset == -1) |
| return '?'; // undefined |
| if (size > blocksize) |
| return '#'; // requires multiple blocks |
| if (size == blocksize && (offset % blocksize == 0)) |
| return '<'; // fits block entirely |
| if (offset % blocksize == 0) |
| return '/'; // starts block |
| if ((offset + size) % blocksize == 0) |
| return '\\'; // closes block |
| if (offset / blocksize == ((offset + size) / blocksize)) |
| return '|'; // inside block |
| return 'X'; // crosses blocks unnecessarily |
| } |
| |
| char * |
| DataObject::get_offset_name () |
| { |
| char *offset_name; |
| if (parent && parent->get_typename ()) // element |
| offset_name = dbe_sprintf (GTXT ("%c%+6lld .{%s %s}"), |
| get_offset_mark (), (long long) offset, |
| _typename ? _typename : GTXT ("NO_TYPE"), |
| _instname ? _instname : GTXT ("-")); // "NO_NAME" |
| else if ((offset != -1) && (offset > 0)) // filler |
| offset_name = dbe_sprintf (GTXT ("%c%+6lld %s"), get_offset_mark (), |
| (long long) offset, get_name ()); |
| else if (parent) // Scalar/Unknown element |
| offset_name = dbe_sprintf (GTXT (" .%s"), get_unannotated_name ()); |
| else // aggregate |
| offset_name = dbe_strdup (get_name ()); |
| return offset_name; |
| } |
| |
| void |
| DataObject::set_dobjname (char *type_name, char *inst_name) |
| { |
| _unannotated_name = _typename = _instname = NULL; |
| if (inst_name) |
| _instname = dbe_strdup (inst_name); |
| |
| char *buf; |
| if (parent == dbeSession->get_Scalars_DataObject ()) |
| { |
| if (type_name) |
| _typename = dbe_strdup (type_name); |
| _unannotated_name = dbe_sprintf (NTXT ("{%s %s}"), type_name, |
| inst_name ? inst_name : NTXT ("-")); |
| buf = dbe_sprintf (NTXT ("%s.%s"), parent->get_name (), _unannotated_name); |
| } |
| else if (parent == dbeSession->get_Unknown_DataObject ()) |
| { |
| _unannotated_name = dbe_strdup (type_name); |
| buf = dbe_sprintf (NTXT ("%s.%s"), parent->get_name (), _unannotated_name); |
| } |
| else |
| { |
| if (type_name) |
| _typename = dbe_strdup (type_name); |
| if (parent && parent->get_typename ()) |
| buf = dbe_sprintf (NTXT ("%s.{%s %s}"), |
| parent->get_name () ? parent->get_name () : NTXT ("ORPHAN"), |
| type_name ? type_name : NTXT ("NO_TYPE"), |
| inst_name ? inst_name : NTXT ("-")); // "NO_NAME" |
| else |
| buf = dbe_sprintf (NTXT ("{%s %s}"), |
| type_name ? type_name : NTXT ("NO_TYPE"), |
| inst_name ? inst_name : NTXT ("-")); // "NO_NAME" |
| } |
| name = buf; |
| dbeSession->dobj_updateHT (this); |
| } |
| |
| void |
| DataObject::set_name (char *string) |
| { |
| name = dbe_strdup (string); |
| dbeSession->dobj_updateHT (this); |
| } |
| |
| DbeEA * |
| DataObject::find_dbeEA (Vaddr EA) |
| { |
| DbeEA *dbeEA; |
| int left = 0; |
| int right = EAs->size () - 1; |
| while (left <= right) |
| { |
| int index = (left + right) / 2; |
| dbeEA = EAs->fetch (index); |
| if (EA < dbeEA->eaddr) |
| right = index - 1; |
| else if (EA > dbeEA->eaddr) |
| left = index + 1; |
| else |
| return dbeEA; |
| } |
| |
| // None found, create a new one |
| dbeEA = new DbeEA (this, EA); |
| EAs->insert (left, dbeEA); |
| return dbeEA; |
| } |