1*cb63e24eSchristos /* Copyright (C) 2021-2024 Free Software Foundation, Inc.
24f645668Schristos Contributed by Oracle.
34f645668Schristos
44f645668Schristos This file is part of GNU Binutils.
54f645668Schristos
64f645668Schristos This program is free software; you can redistribute it and/or modify
74f645668Schristos it under the terms of the GNU General Public License as published by
84f645668Schristos the Free Software Foundation; either version 3, or (at your option)
94f645668Schristos any later version.
104f645668Schristos
114f645668Schristos This program is distributed in the hope that it will be useful,
124f645668Schristos but WITHOUT ANY WARRANTY; without even the implied warranty of
134f645668Schristos MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
144f645668Schristos GNU General Public License for more details.
154f645668Schristos
164f645668Schristos You should have received a copy of the GNU General Public License
174f645668Schristos along with this program; if not, write to the Free Software
184f645668Schristos Foundation, 51 Franklin Street - Fifth Floor, Boston,
194f645668Schristos MA 02110-1301, USA. */
204f645668Schristos
214f645668Schristos #include "config.h"
224f645668Schristos #include <assert.h>
234f645668Schristos #include <string.h>
244f645668Schristos #include <ctype.h>
254f645668Schristos
264f645668Schristos #include "util.h"
274f645668Schristos #include "DbeSession.h"
284f645668Schristos #include "Application.h"
294f645668Schristos #include "DataObject.h"
304f645668Schristos #include "Module.h"
314f645668Schristos #include "debug.h"
324f645668Schristos
DataObject()334f645668Schristos DataObject::DataObject ()
344f645668Schristos {
354f645668Schristos name = NULL;
364f645668Schristos parent = NULL;
374f645668Schristos master = NULL;
384f645668Schristos _unannotated_name = NULL;
394f645668Schristos _typename = NULL;
404f645668Schristos _instname = NULL;
414f645668Schristos scope = NULL;
424f645668Schristos EAs = new Vector<DbeEA*>;
434f645668Schristos size = 0;
444f645668Schristos offset = (uint64_t) (-1);
454f645668Schristos }
464f645668Schristos
~DataObject()474f645668Schristos DataObject::~DataObject ()
484f645668Schristos {
494f645668Schristos free (_unannotated_name);
504f645668Schristos free (_typename);
514f645668Schristos free (_instname);
524f645668Schristos EAs->destroy ();
534f645668Schristos delete EAs;
544f645668Schristos }
554f645668Schristos
564f645668Schristos // get_addr() doesn't return an actual address for a DataObject
574f645668Schristos // but rather synthesises an address-like identifier tuple.
584f645668Schristos // XXXX since an aggregate and its first element have identical tuples
594f645668Schristos // may need to arrange for special-purpose sorting "by address"
604f645668Schristos uint64_t
get_addr()614f645668Schristos DataObject::get_addr ()
624f645668Schristos {
634f645668Schristos uint64_t addr;
644f645668Schristos if (parent && parent->get_typename ())
654f645668Schristos addr = MAKE_ADDRESS (parent->id, offset); // element
664f645668Schristos else if (parent)
674f645668Schristos addr = MAKE_ADDRESS (parent->id, id) | 0x8000000000000000ULL; // Scalar, Unknown
684f645668Schristos else if (id == dbeSession->get_Scalars_DataObject ()->id)
694f645668Schristos addr = MAKE_ADDRESS (id, 0) | 0x8000000000000000ULL; // Scalar aggregate
704f645668Schristos else if (id == dbeSession->get_Unknown_DataObject ()->id)
714f645668Schristos addr = MAKE_ADDRESS (id, 0) | 0x8000000000000000ULL; // Unknown aggregate
724f645668Schristos else
734f645668Schristos addr = MAKE_ADDRESS (id, 0); // aggregate
744f645668Schristos return addr;
754f645668Schristos }
764f645668Schristos
774f645668Schristos Histable *
convertto(Histable_type type,Histable *)784f645668Schristos DataObject::convertto (Histable_type type, Histable *)
794f645668Schristos {
804f645668Schristos return type == DOBJECT ? this : NULL;
814f645668Schristos }
824f645668Schristos
834f645668Schristos char
get_offset_mark()844f645668Schristos DataObject::get_offset_mark ()
854f645668Schristos {
864f645668Schristos enum
874f645668Schristos {
884f645668Schristos blocksize = 32
894f645668Schristos };
904f645668Schristos
914f645668Schristos if (size == 0 || offset == -1)
924f645668Schristos return '?'; // undefined
934f645668Schristos if (size > blocksize)
944f645668Schristos return '#'; // requires multiple blocks
954f645668Schristos if (size == blocksize && (offset % blocksize == 0))
964f645668Schristos return '<'; // fits block entirely
974f645668Schristos if (offset % blocksize == 0)
984f645668Schristos return '/'; // starts block
994f645668Schristos if ((offset + size) % blocksize == 0)
1004f645668Schristos return '\\'; // closes block
1014f645668Schristos if (offset / blocksize == ((offset + size) / blocksize))
1024f645668Schristos return '|'; // inside block
1034f645668Schristos return 'X'; // crosses blocks unnecessarily
1044f645668Schristos }
1054f645668Schristos
1064f645668Schristos char *
get_offset_name()1074f645668Schristos DataObject::get_offset_name ()
1084f645668Schristos {
1094f645668Schristos char *offset_name;
1104f645668Schristos if (parent && parent->get_typename ()) // element
1114f645668Schristos offset_name = dbe_sprintf (GTXT ("%c%+6lld .{%s %s}"),
1124f645668Schristos get_offset_mark (), (long long) offset,
1134f645668Schristos _typename ? _typename : GTXT ("NO_TYPE"),
1144f645668Schristos _instname ? _instname : GTXT ("-")); // "NO_NAME"
1154f645668Schristos else if ((offset != -1) && (offset > 0)) // filler
1164f645668Schristos offset_name = dbe_sprintf (GTXT ("%c%+6lld %s"), get_offset_mark (),
1174f645668Schristos (long long) offset, get_name ());
1184f645668Schristos else if (parent) // Scalar/Unknown element
1194f645668Schristos offset_name = dbe_sprintf (GTXT (" .%s"), get_unannotated_name ());
1204f645668Schristos else // aggregate
1214f645668Schristos offset_name = dbe_strdup (get_name ());
1224f645668Schristos return offset_name;
1234f645668Schristos }
1244f645668Schristos
1254f645668Schristos void
set_dobjname(char * type_name,char * inst_name)1264f645668Schristos DataObject::set_dobjname (char *type_name, char *inst_name)
1274f645668Schristos {
1284f645668Schristos _unannotated_name = _typename = _instname = NULL;
1294f645668Schristos if (inst_name)
1304f645668Schristos _instname = dbe_strdup (inst_name);
1314f645668Schristos
1324f645668Schristos char *buf;
1334f645668Schristos if (parent == dbeSession->get_Scalars_DataObject ())
1344f645668Schristos {
1354f645668Schristos if (type_name)
1364f645668Schristos _typename = dbe_strdup (type_name);
1374f645668Schristos _unannotated_name = dbe_sprintf (NTXT ("{%s %s}"), type_name,
1384f645668Schristos inst_name ? inst_name : NTXT ("-"));
1394f645668Schristos buf = dbe_sprintf (NTXT ("%s.%s"), parent->get_name (), _unannotated_name);
1404f645668Schristos }
1414f645668Schristos else if (parent == dbeSession->get_Unknown_DataObject ())
1424f645668Schristos {
1434f645668Schristos _unannotated_name = dbe_strdup (type_name);
1444f645668Schristos buf = dbe_sprintf (NTXT ("%s.%s"), parent->get_name (), _unannotated_name);
1454f645668Schristos }
1464f645668Schristos else
1474f645668Schristos {
1484f645668Schristos if (type_name)
1494f645668Schristos _typename = dbe_strdup (type_name);
1504f645668Schristos if (parent && parent->get_typename ())
1514f645668Schristos buf = dbe_sprintf (NTXT ("%s.{%s %s}"),
1524f645668Schristos parent->get_name () ? parent->get_name () : NTXT ("ORPHAN"),
1534f645668Schristos type_name ? type_name : NTXT ("NO_TYPE"),
1544f645668Schristos inst_name ? inst_name : NTXT ("-")); // "NO_NAME"
1554f645668Schristos else
1564f645668Schristos buf = dbe_sprintf (NTXT ("{%s %s}"),
1574f645668Schristos type_name ? type_name : NTXT ("NO_TYPE"),
1584f645668Schristos inst_name ? inst_name : NTXT ("-")); // "NO_NAME"
1594f645668Schristos }
1604f645668Schristos name = buf;
1614f645668Schristos dbeSession->dobj_updateHT (this);
1624f645668Schristos }
1634f645668Schristos
1644f645668Schristos void
set_name(char * string)1654f645668Schristos DataObject::set_name (char *string)
1664f645668Schristos {
1674f645668Schristos name = dbe_strdup (string);
1684f645668Schristos dbeSession->dobj_updateHT (this);
1694f645668Schristos }
1704f645668Schristos
1714f645668Schristos DbeEA *
find_dbeEA(Vaddr EA)1724f645668Schristos DataObject::find_dbeEA (Vaddr EA)
1734f645668Schristos {
1744f645668Schristos DbeEA *dbeEA;
1754f645668Schristos int left = 0;
1764f645668Schristos int right = EAs->size () - 1;
1774f645668Schristos while (left <= right)
1784f645668Schristos {
1794f645668Schristos int index = (left + right) / 2;
1804f645668Schristos dbeEA = EAs->fetch (index);
1814f645668Schristos if (EA < dbeEA->eaddr)
1824f645668Schristos right = index - 1;
1834f645668Schristos else if (EA > dbeEA->eaddr)
1844f645668Schristos left = index + 1;
1854f645668Schristos else
1864f645668Schristos return dbeEA;
1874f645668Schristos }
1884f645668Schristos
1894f645668Schristos // None found, create a new one
1904f645668Schristos dbeEA = new DbeEA (this, EA);
1914f645668Schristos EAs->insert (left, dbeEA);
1924f645668Schristos return dbeEA;
1934f645668Schristos }
194