diff options
Diffstat (limited to 'gprofng/src/Module.cc')
-rw-r--r-- | gprofng/src/Module.cc | 1840 |
1 files changed, 1840 insertions, 0 deletions
diff --git a/gprofng/src/Module.cc b/gprofng/src/Module.cc new file mode 100644 index 00000000000..1e61b429e95 --- /dev/null +++ b/gprofng/src/Module.cc @@ -0,0 +1,1840 @@ +/* Copyright (C) 2021 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 <unistd.h> +#include <ar.h> +#include <ctype.h> +#include <sys/param.h> + +#include "util.h" +#include "DbeSession.h" +#include "Experiment.h" +#include "DataObject.h" +#include "Function.h" +#include "DbeView.h" +#include "MetricList.h" +#include "Module.h" +#include "ClassFile.h" +#include "LoadObject.h" +#include "Disasm.h" +#include "CompCom.h" +#include "Dwarf.h" +#include "DbeFile.h" +#include "PathTree.h" +#include "Elf.h" + +Module::Module () +{ + lang_code = Sp_lang_unknown; + flags = 0; + status = AE_NOTREAD; + openSourceFlag = AE_NOTREAD; + hexVisible = false; + disPath = NULL; + stabsPath = NULL; + stabsTmp = NULL; + disName = NULL; + stabsName = NULL; + indexStabsLink = NULL; + file_name = NULL; + functions = new Vector<Function*>; + loadobject = NULL; + dot_o_file = NULL; + main_source = dbeSession->get_Unknown_Source (); + srcContext = main_source; + includes = new Vector<SourceFile*>; + includes->append (main_source); + curr_inc = NULL; + fragmented = 0; + hwcprof = 0; + hdrOffset = 0; + hasDwarf = false; + hasStabs = false; + readStabs = false; + comComs = NULL; + infoList = NULL; + datatypes = NULL; + objStabs = NULL; + disasm = NULL; + comp_flags = NULL; + comp_dir = NULL; + linkerStabName = NULL; + disMTime = (time_t) 0; + stabsMTime = (time_t) 0; + real_timestamp = 0; + curr_timestamp = 0; + src_items = NULL; + dis_items = NULL; + data_items = NULL; + cur_dbev = NULL; + maximum = NULL; + maximum_inc = NULL; + empty = NULL; + inlinedSubr = NULL; +} + +Module::~Module () +{ + removeStabsTmp (); + delete includes; + if (comComs != NULL) + { + comComs->destroy (); + delete comComs; + } + free (comp_flags); + free (comp_dir); + free (linkerStabName); + free (disPath); + free (stabsPath); + free (disName); + free (stabsName); + delete functions; + free (file_name); + if (indexStabsLink) + // Remove a link to the current module + indexStabsLink->indexStabsLink = NULL; + + if (dot_o_file) + { + delete dot_o_file->dbeFile; + delete dot_o_file; + } + delete src_items; + delete dis_items; + delete disasm; + free (inlinedSubr); + if (lang_code != Sp_lang_java) + delete dbeFile; + +} + +Stabs * +Module::openDebugInfo () +{ + setFile (); + objStabs = loadobject->openDebugInfo (disPath); + return objStabs; +} + +void +Module::removeStabsTmp () +{ + // Remove temporary *.o (got from *.a) after reading Stabs + if (stabsTmp != NULL) + { + unlink (stabsTmp); + free (stabsTmp); + stabsTmp = NULL; + } +} + +int64_t +Module::get_size () +{ + Function *fp; + int index; + int64_t result = 0; + Vec_loop (Function*, functions, index, fp) + { + result += fp->size; + } + return result; +} + +bool +Module::is_fortran () +{ + return Stabs::is_fortran (lang_code); +} + +SourceFile * +Module::findSource (const char *fname, bool create) +{ + SourceFile *sf = NULL; + if (loadobject && loadobject->firstExp) + sf = loadobject->firstExp->get_source (fname); + if (sf == NULL) + sf = dbeSession->createSourceFile (fname); + for (int i = 0, sz = includes ? includes->size () : 0; i < sz; i++) + { + SourceFile *sf1 = includes->fetch (i); + if (sf == sf1) + return sf; + } + if (create) + { + if (includes == NULL) + includes = new Vector<SourceFile*>; + includes->append (sf); + return sf; + } + return NULL; +} + +SourceFile * +Module::setIncludeFile (char *includeFile) +{ + curr_inc = NULL; + if (includeFile) + curr_inc = findSource (includeFile, true); + return curr_inc; +} + +char * +Module::anno_str (char *fnm) +{ + char timebuf1[26], timebuf2[26]; + const time_t real_time = (time_t) (unsigned int) real_timestamp; + const time_t curr_time = (time_t) (unsigned int) curr_timestamp; + + switch (status) + { + case AE_OK: + case AE_NOTREAD: + return NULL; + case AE_NOSRC: + return dbe_sprintf (GTXT ("Source file `%s' not readable"), + fnm ? fnm : file_name); + case AE_NOOBJ: + if (lang_code == Sp_lang_java) + { + Emsg *emsg = get_error (); + if (emsg) + { + char *s = dbe_strdup (emsg->get_msg ()); + remove_msg (emsg); + return s; + } + return dbe_sprintf (GTXT ("Object file `%s.class' not readable"), + name); + } + return dbe_sprintf (GTXT ("Object file `%s' not readable"), get_name ()); + case AE_NOLOBJ: + if (lang_code == Sp_lang_java) + return dbe_sprintf (GTXT ("Object file `%s' not readable"), + dbeFile ? dbeFile->get_name () : name); + return dbe_sprintf (GTXT ("Object file `%s' not readable"), loadobject->get_pathname ()); + case AE_NOSTABS: + return dbe_sprintf (GTXT ("Error reading line-number information in object `%s'; source annotation not available"), + stabsPath ? stabsPath : NTXT ("")); + case AE_NOSYMTAB: + return dbe_sprintf (GTXT ("Error reading symbol table in object `%s'; disassembly annotation not available"), + disPath ? disPath : NTXT ("")); + case AE_TIMESRC: + return dbe_sprintf (GTXT ("Warning! Source file `%s' is newer than the experiment data"), + main_source->dbeFile->getResolvedPath ()); + case AE_TIMEDIS: + return dbe_sprintf (GTXT ("Warning! Object file `%s' is newer than the experiment data"), + disName ? disName : NTXT ("")); + case AE_TIMESTABS: + return dbe_sprintf (GTXT ("Warning! Object file `%s' is newer than the experiment data"), + stabsName ? stabsName : NTXT ("")); + case AE_TIMESTABS_DIFF: + snprintf (timebuf1, sizeof (timebuf1), NTXT ("%s"), ctime (&curr_time)); + snprintf (timebuf2, sizeof (timebuf2), NTXT ("%s"), ctime (&real_time)); + timebuf1[24] = timebuf2[24] = '\0'; + return dbe_sprintf (GTXT ("Warning! Object file `%s' is not the same one that was linked into executable.\n" + "\tObject file: `%s'\n\tcompiled on: %s\n" + "\tExecutable contains object file compiled on: %s"), + getResolvedObjectPath (), getResolvedObjectPath (), + timebuf1, timebuf2); + case AE_OTHER: + default: + return dbe_strdup (GTXT ("Annotation computation error")); + } +}//anno_str + +LoadObject * +Module::createLoadObject (const char *lo_name) +{ + LoadObject *lo = new LoadObject (lo_name); + lo->dbeFile->filetype |= DbeFile::F_DOT_O; + return lo; +} + +static bool +tsIsNewer (time_t t1, time_t t2) +{ + return t1 != 0 && t2 != 0 && t1 < t2; +} + +Module::Anno_Errors +Module::checkTimeStamp (bool chkDis) +{ + /* Check the linked and the real object timestamps due to bug #4796329 */ + if (real_timestamp && curr_timestamp && real_timestamp != curr_timestamp) + return AE_TIMESTABS_DIFF; + + time_t srctime = main_source->getMTime (); + for (int index = 0; index < dbeSession->nexps (); index++) + { + time_t mtime = dbeSession->get_exp (index)->get_mtime (); + if (tsIsNewer (mtime, srctime)) + return AE_TIMESRC; + if (tsIsNewer (mtime, stabsMTime)) + return AE_TIMESTABS; + if (chkDis && tsIsNewer (mtime, disMTime)) + return AE_TIMEDIS; + } + return AE_OK; +}//checkTimeStamp + +static size_t +get_ar_size (char *s, size_t len) +{ + size_t sz = 0; + for (size_t i = 0; i < len; i++) + { + if (s[i] < '0' || s[i] > '9') + break; + sz = sz * 10 + (s[i] - '0'); + } + return sz; +} + +static void +dump_hdr_field (char *nm, char *s, size_t len) +{ + Dprintf (DEBUG_READ_AR, NTXT (" %s "), nm); + for (size_t i = 0; i < len; i++) + Dprintf (DEBUG_READ_AR, "%c", isprint (s[i]) ? s[i] : '?'); + Dprintf (DEBUG_READ_AR, NTXT (" ")); + for (size_t i = 0; i < len; i++) + Dprintf (DEBUG_READ_AR, NTXT (" %d"), s[i]); + Dprintf (DEBUG_READ_AR, NTXT (" \n")); +} + +static void +dump_ar_hdr (int lineNum, struct ar_hdr *hdr) +{ + if (DEBUG_READ_AR) + { + Dprintf (DEBUG_READ_AR, NTXT ("Module::read_ar %d\n"), lineNum); + dump_hdr_field (NTXT ("ar_name"), hdr->ar_name, sizeof (hdr->ar_name)); + dump_hdr_field (NTXT ("ar_date"), hdr->ar_date, sizeof (hdr->ar_date)); + dump_hdr_field (NTXT ("ar_uid"), hdr->ar_uid, sizeof (hdr->ar_uid)); + dump_hdr_field (NTXT ("ar_gid"), hdr->ar_gid, sizeof (hdr->ar_gid)); + dump_hdr_field (NTXT ("ar_mode"), hdr->ar_mode, sizeof (hdr->ar_mode)); + dump_hdr_field (NTXT ("ar_size"), hdr->ar_size, sizeof (hdr->ar_size)); + dump_hdr_field (NTXT ("ar_fmag"), hdr->ar_fmag, sizeof (hdr->ar_fmag)); + } +} + +bool +Module::read_ar (int ar, int obj, char *obj_base) +{ + struct ar_hdr hdr; // Archive header + char magic[SARMAG]; // Magic string from archive + Dprintf (DEBUG_READ_AR, "Module::read_ar %d %p %s %s \n", __LINE__, + this, STR (obj_base), STR (get_name ())); + // Check the magic string + if ((read_from_file (ar, magic, SARMAG) != SARMAG) + || strncmp (magic, ARMAG, SARMAG)) + return false; + + // Read and skip the first file in the archive (index file to ld) + if (read_from_file (ar, &hdr, sizeof (hdr)) != sizeof (hdr)) + return false; + DEBUG_CODE dump_ar_hdr (__LINE__, &hdr); + if (lseek (ar, get_ar_size (hdr.ar_size, sizeof (hdr.ar_size)), SEEK_CUR) + == -1) + return false; + + // Read the string file where it keeps long file names (if exist) + if (read_from_file (ar, &hdr, sizeof (hdr)) != sizeof (hdr)) + return false; + DEBUG_CODE dump_ar_hdr (__LINE__, &hdr); + char *longnames = NULL; // Area with names longer than ~13 + size_t longnames_size = 0; + if (!strncmp (hdr.ar_name, NTXT ("//"), 2)) + { + longnames_size = get_ar_size (hdr.ar_size, sizeof (hdr.ar_size)); + longnames = (char *) malloc (longnames_size + 1); + int64_t cnt = read_from_file (ar, longnames, longnames_size); + if (cnt != (int64_t) longnames_size) + { + free (longnames); + return false; + } + longnames[longnames_size] = 0; + } + else + // back out, no long file names + lseek (ar, -(sizeof (hdr)), SEEK_CUR); + + // Search the ar for the object file name + char ar_buf[sizeof (hdr.ar_name) + 1]; + ar_buf[sizeof (hdr.ar_name)] = 0; + while (1) + { + if (read_from_file (ar, &hdr, sizeof (hdr)) != sizeof (hdr)) + break; + DEBUG_CODE dump_ar_hdr (__LINE__, &hdr); + char *ar_name; + if (hdr.ar_name[0] != '/') + { // Name is in the header + for (size_t i = 0; i < sizeof (hdr.ar_name); i++) + { + if (hdr.ar_name[i] == '/') + { + ar_buf[i] = 0; + break; + } + ar_buf[i] = hdr.ar_name[i]; + } + ar_name = ar_buf; + } + else if (hdr.ar_name[1] == ' ') + { // Name is blank + ar_buf[0] = 0; + ar_name = ar_buf; + } + else + { // Name is in the string table + if (longnames == NULL) + break; + size_t offset = get_ar_size (hdr.ar_name + 1, + sizeof (hdr.ar_name) - 1); + if (offset >= longnames_size) + break; + for (size_t i = offset; i < longnames_size; i++) + { + if (longnames[i] == '/') + { + longnames[i] = 0; + break; + } + } + ar_name = longnames + offset; + } + Dprintf (DEBUG_READ_AR, "Module::read_ar %d ar_name=%s\n", __LINE__, + ar_name); + + if (streq (ar_name, obj_base)) + { // create object file + free (longnames); + for (size_t objsize = get_ar_size (hdr.ar_size, sizeof (hdr.ar_size)); + objsize > 0;) + { + char buf[MAXPATHLEN]; + size_t n = objsize < sizeof (buf) ? objsize : sizeof (buf); + int64_t cnt = read_from_file (ar, buf, n); + if (cnt != (int64_t) n) + return false; + cnt = write (obj, buf, n); + if (cnt != (int64_t) n) + return false; + objsize -= n; + } + return true; + } + if (lseek (ar, get_ar_size (hdr.ar_size, sizeof (hdr.ar_size)), + SEEK_CUR) == -1) + break; + } + free (longnames); + return false; +} + +static char * +get_obj_name_from_lib (char *nm) +{ + char *base = strrchr (nm, '('); + if (base) + { + size_t last = strlen (base) - 1; + if (base[last] == ')') + return base; + } + return NULL; +} + +bool +Module::setFile () +{ + if ((loadobject->flags & SEG_FLAG_DYNAMIC) != 0) + return true; + if ((loadobject->dbeFile->filetype & DbeFile::F_FICTION) != 0) + return false; + if ((flags & MOD_FLAG_UNKNOWN) != 0) + return true; + + if (lang_code == Sp_lang_java) + { + if (dbeFile->get_need_refind ()) + { + char *fnm = dbeFile->get_location (); + stabsPath = dbe_strdup (fnm); + stabsName = dbe_strdup (fnm); + disPath = dbe_strdup (fnm); + disName = dbe_strdup (fnm); + stabsMTime = dbeFile->sbuf.st_mtime; + } + return dbeFile->get_location () != NULL; + } + + if (dbeFile == NULL) + { + char *objname = get_obj_name_from_lib (name); + if (objname) + { + // in the format of libpath(obj) + objname = dbe_strdup (objname + 1); + size_t last = strlen (objname) - 1; + objname[last] = '\0'; + } + dbeFile = new DbeFile (objname ? objname : name); + free (objname); + dbeFile->filetype |= DbeFile::F_DOT_O; + } + if (dbeFile->get_need_refind ()) + { + disMTime = (time_t) 0; + stabsMTime = (time_t) 0; + free (disName); + free (stabsName); + disName = NULL; + stabsName = NULL; + + // Find the Executable/Shared-Object file of module + char *path = loadobject->dbeFile->get_location (); + if (path) + { + disPath = strdup (path); + disName = strdup (path); + disMTime = loadobject->dbeFile->sbuf.st_mtime; + } + + char *objname = get_obj_name_from_lib (name); + if (objname) + { + // in the format of libpath(obj) + char *namebuf = dbe_strdup (name); + char *base = namebuf + (objname - name); + *base = '\0'; + base++; + size_t last = strlen (base) - 1; + base[last] = '\0'; + stabsTmp = dbeSession->get_tmp_file_name (base, false); + dbeSession->tmp_files->append (strdup (stabsTmp)); + + DbeFile *dbf = dbeSession->getDbeFile (namebuf, + DbeFile::F_DOT_A_LIB | DbeFile::F_FILE); + path = dbf->get_location (); + int ar = -1, obj = -1; + if (path != NULL) + { + ar = open64 (path, O_RDONLY | O_LARGEFILE); + if (ar != -1) + obj = open64 (stabsTmp, O_CREAT | O_WRONLY | O_LARGEFILE, 0600); + } + if (ar != -1 && obj != -1 && read_ar (ar, obj, base)) + { + dbeFile->set_location (stabsTmp); + dbeFile->check_access (stabsTmp); // init 'sbuf' + dbeFile->sbuf.st_mtime = 0; // Don't check timestamps + dbeFile->container = dbf; + stabsPath = strdup (stabsTmp); + stabsName = strdup (path); + stabsMTime = dbeFile->sbuf.st_mtime; + } + else + { + removeStabsTmp (); + objname = NULL; + } + if (ar != -1) + close (ar); + if (obj != -1) + close (obj); + free (namebuf); + } + if (objname == NULL) + { + path = dbeFile->get_location (); + if (path != NULL) + { + stabsPath = strdup (path); + stabsName = strdup (path); + stabsMTime = hasDwarf ? 0 : dbeFile->sbuf.st_mtime; + } + } + + // First, try to access the symbol table of the module itself + // If failed, access the symbol table of the executable + if (stabsPath == NULL) + { + if (disPath == NULL) + return false; + stabsPath = strdup (disPath); + stabsName = strdup (disName); + stabsMTime = disMTime; + } + else if (disPath == NULL) + { + disPath = strdup (stabsPath); + disName = strdup (stabsName); + disMTime = stabsMTime; + } + } + return stabsPath != NULL; +} + +// openStabs -- open mappings from PCs to source lines +bool +Module::openStabs (bool all) +{ + if ((loadobject->flags & SEG_FLAG_DYNAMIC) != 0 + || (flags & MOD_FLAG_UNKNOWN) != 0) + return true; + if (loadobject->platform == Java) + { + setIncludeFile (NULL); + readFile (); + return ( status == AE_OK); + } + if (readStabs) + return true; + + // Read Stabs info. + int64_t Inode = main_source->getInode (); + char *fname = strrchr (file_name, (int) '/'); + char *mname = strrchr (main_source->get_name (), (int) '/'); + if (fname && mname && !streq (fname, mname)) + { + SourceFile *sf = findSource (file_name, false); + if (sf != NULL) + Inode = sf->getInode (); + } + + comComs = new Vector<ComC*>; + Stabs *stabs = openDebugInfo (); + if (stabs == NULL) + return false; + int st = stabs->read_stabs (Inode, this, comComs, true); + if (!hasDwarf && hasStabs && !streq (stabsPath, disPath)) + { + // Read stabs from .o file + if (dot_o_file == NULL) + { + if (dbeFile->get_location ()) + { + dot_o_file = createLoadObject (dbeFile->get_name ()); + dot_o_file->dbeFile->set_location (dbeFile->get_location ()); + dot_o_file->dbeFile->sbuf = dbeFile->sbuf; + dot_o_file->dbeFile->container = dbeFile->container; + } + } + if (dot_o_file + && dot_o_file->sync_read_stabs () == LoadObject::ARCHIVE_SUCCESS) + { + Stabs *stabs_o = dot_o_file->objStabs; + if (stabs_o) + { + st = stabs_o->read_stabs (Inode, this, + comComs->size () > 0 ? NULL : comComs); + Elf *elf_o = stabs_o->openElf (false); + if (elf_o->dwarf) + stabs->read_dwarf_from_dot_o (this); + } + } + } + if (all) + read_hwcprof_info (); + + readStabs = true; + return st == Stabs::DBGD_ERR_NONE; +} + +char * +Module::get_disasm (uint64_t inst_address, uint64_t end_address, + uint64_t start_address, uint64_t address, int64_t &inst_size) +{ + return disasm->get_disasm (inst_address, end_address, start_address, + address, inst_size); +} + +void +Module::read_stabs (bool all) +{ + if (openSourceFlag == AE_NOTREAD) + { + openSourceFlag = AE_OK; + if (lang_code == Sp_lang_java) + { + char *clpath = file_name; + if (clpath == NULL || strcmp (clpath, "<Unknown>") == 0) + clpath = ClassFile::get_java_file_name (name, false); + main_source = findSource (clpath, true); + main_source->dbeFile->filetype |= DbeFile::F_JAVA_SOURCE; + if (clpath != file_name) + free (clpath); + } + else + main_source = findSource (file_name, true); + if (setFile ()) + openStabs (all); + } +} + +bool +Module::openDisPC () +{ + if (disasm == NULL) + { + if (!(loadobject->flags & SEG_FLAG_DYNAMIC) && loadobject->platform != Java) + { + // Read Stabs & Symbol tables + if (openDebugInfo () == NULL) + return false; + if (!objStabs->read_symbols (functions)) + return false; + } + disasm = new Disasm (loadobject->platform, objStabs); + } + return true; +} + +static SourceFile *cmpSrcContext; // Use only for func_cmp + +static int +func_cmp (const void *a, const void *b) +{ + Function *fp1 = *((Function **) a); + Function *fp2 = *((Function **) b); + return fp1->func_cmp (fp2, cmpSrcContext); +} + +bool +Module::computeMetrics (DbeView *dbev, Function *func, MetricList *metrics, + Histable::Type type, bool src_metric, + bool func_scope, SourceFile *source) +{ + name_idx = metrics->get_listorder (NTXT ("name"), Metric::STATIC); + if (name_idx < 0) + { + metrics->print_metric_list (stderr, + GTXT ("Fatal: no name metric in Module::computeMetrics mlist:\n"), + 1); + abort (); + } + + // Now find the metrics for size and address, if present + size_index = metrics->get_listorder (NTXT ("size"), Metric::STATIC); + addr_index = metrics->get_listorder (NTXT ("address"), Metric::STATIC); + + // free the old cached data for both src and disassembly + // If it's disassembly with visible source metrics, we use both + if (dis_items) + { + delete dis_items; + dis_items = NULL; + } + if (src_items) + { + delete src_items; + src_items = NULL; + } + + // ask the DbeView to generate new data to be cached + if (src_metric || type == Histable::LINE) + { + Histable *obj = (func_scope) ? (Histable*) func : (Histable*)this; + if (lang_code == Sp_lang_java) + obj = func_scope ? (Histable *) func : + (source && source->get_type () == Histable::SOURCEFILE ? + (Histable *) source : (Histable *) this); + src_items = dbev->get_hist_data (metrics, Histable::LINE, 0, + Hist_data::MODL, obj, source); + } + if (type == Histable::INSTR) + dis_items = dbev->get_hist_data (metrics, Histable::INSTR, 0, + Hist_data::MODL, + func_scope ? (Histable*) func : (Histable*) this, + source); + + Hist_data *cur_hist_data; + if (type == Histable::INSTR) + cur_hist_data = dis_items; + else + cur_hist_data = src_items; + + Vector<Metric*> *items = cur_hist_data->get_metric_list ()->get_items (); + long sz = items->size (); + empty = new TValue[sz]; + memset (empty, 0, sizeof (TValue) * sz); + for (long i = 0; i < sz; i++) + empty[i].tag = items->get (i)->get_vtype (); + return true; +} + +// Method to get annotated source or disassembly for the module +// or a function within it +Hist_data * +Module::get_data (DbeView *dbev, MetricList *mlist, Histable::Type type, + TValue *ftotal, SourceFile *srcFile, Function *func, + Vector<int> *marks, int threshold, int vis_bits, + int src_visible, bool hex_vis, bool func_scope, + bool /*src_only*/, Vector<int_pair_t> *marks2d, + Vector<int_pair_t> *marks2d_inc) +{ + cur_dbev = dbev; + srcContext = srcFile ? srcFile : main_source; + read_stabs (); + status = AE_OK; + dbev->warning_msg = NULL; + dbev->error_msg = NULL; + if (type == Histable::LINE) + { + if (!srcContext->readSource ()) + { + status = AE_NOSRC; + dbev->error_msg = anno_str (srcContext->get_name ()); + return NULL; + } + if (!computeMetrics (dbev, func, mlist, type, false, func_scope, srcContext)) + { + status = AE_OTHER; + dbev->error_msg = anno_str (); + return NULL; + } + status = checkTimeStamp (false); + } + else + { // Histable::INSTR + Anno_Errors src_status = AE_OK; + if (!srcContext->readSource ()) + { + src_status = AE_NOSRC; + dbev->error_msg = anno_str (srcContext->get_name ()); + } + if (!setFile ()) + status = AE_NOLOBJ; + else + { + if (!openStabs ()) + src_status = AE_NOSTABS; + if (!openDisPC ()) + status = AE_NOSYMTAB; + } + if (status != AE_OK) + { + dbev->error_msg = anno_str (); + return NULL; + } + if (src_status != AE_OK && func != NULL) + { + if (loadobject->platform == Java && (func->flags & FUNC_FLAG_NATIVE) != 0) + { + append_msg (CMSG_ERROR, + GTXT ("`%s' is a native method; byte code not available\n"), + func->get_name ()); + status = AE_NOOBJ; + dbev->error_msg = anno_str (); + return NULL; + } + func_scope = true; + } + // get the disassembly-line metric data + if (!computeMetrics (dbev, func, mlist, type, + (src_visible & SRC_METRIC) != 0, + func_scope, srcContext)) + { + status = AE_OTHER; + dbev->error_msg = anno_str (); + return NULL; + } + status = checkTimeStamp (true); + } + total = ftotal; + + // initialize line number + init_line (); + + // initialize data -- get duplicate metric list for the line texts + // pick up the metric list from the computed data + MetricList *nmlist = NULL; + if (type == Histable::INSTR) + { + mlist = dis_items->get_metric_list (); + nmlist = new MetricList (mlist); + data_items = new Hist_data (nmlist, Histable::INSTR, Hist_data::MODL); + data_items->set_status (dis_items->get_status ()); + set_dis_data (func, vis_bits, dbev->get_cmpline_visible (), + src_visible, hex_vis, func_scope, + dbev->get_funcline_visible ()); + } + else + { + mlist = src_items->get_metric_list (); + nmlist = new MetricList (mlist); + data_items = new Hist_data (nmlist, Histable::LINE, Hist_data::MODL); + data_items->set_status (src_items->get_status ()); + set_src_data (func_scope ? func : NULL, vis_bits, + dbev->get_cmpline_visible (), + dbev->get_funcline_visible ()); + } + data_items->compute_minmax (); + + Metric *mitem; + int index; + Hist_data::HistItem *max_item; + TValue *value; + Hist_data::HistItem *max_item_inc; + TValue *value_inc; + double dthreshold = threshold / 100.0; + + int sz = data_items->get_metric_list ()->get_items ()->size (); + maximum = new TValue[sz]; + maximum_inc = new TValue[sz]; + memset (maximum, 0, sizeof (TValue) * sz); + memset (maximum_inc, 0, sizeof (TValue) * sz); + max_item = data_items->get_maximums (); + max_item_inc = data_items->get_maximums_inc (); + + Vec_loop (Metric*, data_items->get_metric_list ()->get_items (), index, mitem) + { + maximum_inc[index].tag = maximum[index].tag = mitem->get_vtype (); + + if (mitem->get_subtype () == Metric::STATIC) + continue; + if (!mitem->is_visible () && !mitem->is_tvisible () + && !mitem->is_pvisible ()) + continue; + + value = &max_item->value[index]; + value_inc = &max_item_inc->value[index]; + + double dthresh; + if (mitem->is_zeroThreshold () == true) + dthresh = 0; + else + dthresh = dthreshold; + switch (value->tag) + { + case VT_INT: + maximum[index].i = (int) (dthresh * (double) value->i); + maximum_inc[index].i = (int) (dthresh * (double) value_inc->i); + break; + case VT_DOUBLE: + maximum[index].d = dthresh * value->d; + maximum_inc[index].d = dthresh * value_inc->d; + break; + case VT_LLONG: + maximum[index].ll = (unsigned long long) (dthresh * (double) value->ll); + maximum_inc[index].ll = (unsigned long long) + (dthresh * (double) value_inc->ll); + break; + case VT_ULLONG: + maximum[index].ull = (unsigned long long) + (dthresh * (double) value->ull); + maximum_inc[index].ull = (unsigned long long) + (dthresh * (double) value_inc->ull); + break; + default: + // not needed for non-numerical metrics + break; + } + } + + // mark all high values + for (int index1 = 0; index1 < data_items->size (); index1++) + { + Hist_data::HistItem *hi = data_items->fetch (index1); + int index2; + Vec_loop (Metric*, nmlist->get_items (), index2, mitem) + { + bool mark = false; + if (mitem->get_subtype () == Metric::STATIC) + continue; + if (!mitem->is_visible () && !mitem->is_tvisible () + && !mitem->is_pvisible ()) + continue; + + switch (hi->value[index2].tag) + { + case VT_DOUBLE: + if (nmlist->get_type () == MET_SRCDIS + && data_items->get_callsite_mark ()->get (hi->obj)) + { + if (hi->value[index2].d > maximum_inc[index2].d) + mark = true; + break; + } + if (hi->value[index2].d > maximum[index2].d) + mark = true; + break; + case VT_INT: + if (nmlist->get_type () == MET_SRCDIS + && data_items->get_callsite_mark ()->get (hi->obj)) + { + if (hi->value[index2].i > maximum_inc[index2].i) + mark = true; + break; + } + if (hi->value[index2].i > maximum[index2].i) + mark = true; + break; + case VT_LLONG: + if (nmlist->get_type () == MET_SRCDIS + && data_items->get_callsite_mark ()->get (hi->obj)) + { + if (hi->value[index2].ll > maximum_inc[index2].ll) + mark = true; + break; + } + if (hi->value[index2].ll > maximum[index2].ll) + mark = true; + break; + case VT_ULLONG: + if (nmlist->get_type () == MET_SRCDIS + && data_items->get_callsite_mark ()->get (hi->obj)) + { + if (hi->value[index2].ull > maximum_inc[index2].ull) + mark = true; + break; + } + if (hi->value[index2].ull > maximum[index2].ull) + mark = true; + break; + // ignoring the following cases (why?) + case VT_SHORT: + case VT_FLOAT: + case VT_HRTIME: + case VT_LABEL: + case VT_ADDRESS: + case VT_OFFSET: + break; + } + if (mark) + { + marks->append (index1); + break; + } + } + } + + // mark all high values to marks2d + if (marks2d != NULL && marks2d_inc != NULL) + { + for (int index1 = 0; index1 < data_items->size (); index1++) + { + Hist_data::HistItem *hi = data_items->fetch (index1); + int index2; + Vec_loop (Metric*, nmlist->get_items (), index2, mitem) + { + Metric::SubType subType = mitem->get_subtype (); + if (subType == Metric::STATIC) + continue; + if (!mitem->is_visible () && !mitem->is_tvisible () + && !mitem->is_pvisible ()) + continue; + switch (hi->value[index2].tag) + { + case VT_DOUBLE: + if (nmlist->get_type () == MET_SRCDIS + && data_items->get_callsite_mark ()->get (hi->obj)) + { + if (hi->value[index2].d > maximum_inc[index2].d) + { + int_pair_t pair = {index1, index2}; + marks2d_inc->append (pair); + } + break; + } + if (hi->value[index2].d > maximum[index2].d) + { + int_pair_t pair = {index1, index2}; + marks2d->append (pair); + } + break; + case VT_INT: + if (nmlist->get_type () == MET_SRCDIS + && data_items->get_callsite_mark ()->get (hi->obj)) + { + if (hi->value[index2].i > maximum_inc[index2].i) + { + int_pair_t pair = {index1, index2}; + marks2d_inc->append (pair); + } + break; + } + if (hi->value[index2].i > maximum[index2].i) + { + int_pair_t pair = {index1, index2}; + marks2d->append (pair); + } + break; + case VT_LLONG: + if (nmlist->get_type () == MET_SRCDIS + && data_items->get_callsite_mark ()->get (hi->obj)) + { + if (hi->value[index2].ll > maximum_inc[index2].ll) + { + int_pair_t pair = {index1, index2}; + marks2d_inc->append (pair); + } + break; + } + if (hi->value[index2].ll > maximum[index2].ll) + { + int_pair_t pair = {index1, index2}; + marks2d->append (pair); + } + break; + case VT_ULLONG: + if (nmlist->get_type () == MET_SRCDIS + && data_items->get_callsite_mark ()->get (hi->obj)) + { + if (hi->value[index2].ull > maximum_inc[index2].ull) + { + int_pair_t pair = {index1, index2}; + marks2d_inc->append (pair); + } + break; + } + if (hi->value[index2].ull > maximum[index2].ull) + { + int_pair_t pair = {index1, index2}; + marks2d->append (pair); + } + break; + case VT_SHORT: + case VT_FLOAT: + case VT_HRTIME: + case VT_LABEL: + case VT_ADDRESS: + case VT_OFFSET: + break; + } + } + } + } + + // free memory used by Computing & Printing metrics + delete[] maximum; + delete[] maximum_inc; + delete[] empty; + maximum = NULL; + maximum_inc = NULL; + empty = NULL; + dbev->warning_msg = anno_str (); + return data_items; +} + +Vector<uint64_t> * +Module::getAddrs (Function *func) +{ + uint64_t start_address = func->img_offset; + uint64_t end_address = start_address + func->size; + int64_t inst_size = 0; + + // initialize "disasm" if necessary + if (!openDisPC ()) + return NULL; + + Vector<uint64_t> *addrs = new Vector<uint64_t>; + for (uint64_t inst_address = start_address; inst_address < end_address;) + { + char *s = disasm->get_disasm (inst_address, end_address, start_address, + func->img_offset, inst_size); + free (s); + addrs->append (inst_address - start_address); + inst_address += inst_size; + if (inst_size == 0) + break; + } + return addrs; +} + +void +Module::init_line () +{ + // initialize the compiler commentary data + cindex = 0; + if (comComs != NULL && comComs->size () > 0) + cline = comComs->fetch (cindex)->line; + else + cline = -1; + + sindex = 0; + if (src_items && src_items->size () > 0) + sline = ((DbeLine*) src_items->fetch (0)->obj)->lineno; + else + sline = -1; + + dindex = 0; + mindex = 0; + mline = -1; + if (dis_items && dis_items->size () > 0) + { + daddr = (DbeInstr*) dis_items->fetch (0)->obj; + + // After sorting all HistItems with PCLineFlag appear + // at the end of the list. Find the first one. + for (mindex = dis_items->size () - 1; mindex >= 0; mindex--) + { + Hist_data::HistItem *item = dis_items->fetch (mindex); + if (!(((DbeInstr*) item->obj)->flags & PCLineFlag)) + break; + mline = (unsigned) (((DbeInstr*) item->obj)->addr); + } + mindex++; + } + else + daddr = NULL; +} + +void +Module::set_src_data (Function *func, int vis_bits, int cmpline_visible, + int funcline_visible) +{ + Function *curr_func = NULL; + + // start at the top of the file, and loop over all lines in the file (source context) + for (curline = 1; curline <= srcContext->getLineCount (); curline++) + { + // Before writing the line, see if there's compiler commentary to insert + if (cline == curline) + set_ComCom (vis_bits); + + // Find out if we need to print zero metrics with the line + DbeLine *dbeline = srcContext->find_dbeline (NULL, curline); + Anno_Types type = AT_SRC_ONLY; + if (dbeline->dbeline_func_next) + { + if (func) + for (DbeLine *dl = dbeline->dbeline_func_next; dl; dl = dl->dbeline_func_next) + { + if (dl->func == func) + { + type = AT_SRC; + break; + } + } + else + type = AT_SRC; + } + + if (funcline_visible) + { // show red lines + // is there a function index line to insert? + Function *func_next = NULL; + for (DbeLine *dl = dbeline; dl; dl = dl->dbeline_func_next) + { + Function *f = dl->func; + if (f && f->line_first == curline + && f->getDefSrc () == srcContext) + { + if (lang_code == Sp_lang_java + && (f->flags & FUNC_FLAG_DYNAMIC)) + continue; + if (cur_dbev && cur_dbev->get_path_tree ()->get_func_nodeidx (f)) + { + func_next = f; + break; + } + else if (func_next == NULL) + func_next = f; + } + } + if (func_next && curr_func != func_next) + { + curr_func = func_next; + char *func_name = curr_func->get_name (); + if (is_fortran () && streq (func_name, NTXT ("MAIN_"))) + func_name = curr_func->get_match_name (); + Hist_data::HistItem *item = + src_items->new_hist_item (curr_func, AT_FUNC, empty); + item->value[name_idx].l = dbe_sprintf (GTXT ("<Function: %s>"), + func_name); + data_items->append_hist_item (item); + } + } // end of red line + set_src (type, dbeline); // add the source line + } // end of loop over source lines + + // See if compiler flags are set; if so, append them + if (cmpline_visible && comp_flags) + { + Hist_data::HistItem *item = src_items->new_hist_item (NULL, AT_EMPTY, + empty); + item->value[name_idx].l = strdup (NTXT ("")); + data_items->append_hist_item (item); + item = src_items->new_hist_item (NULL, AT_COM, empty); + item->value[name_idx].l = dbe_sprintf (GTXT ("Compile flags: %s"), + comp_flags); + data_items->append_hist_item (item); + } +} + +void +Module::set_dis_data (Function *func, int vis_bits, int cmpline_visible, + int src_visible, bool hex_vis, bool func_scope, + int funcline_visible) +{ + bool nextFile = false; + + // initialize the source output, if any + curline = (srcContext->getLineCount () > 0) ? 1 : -1; + if (func) + nextFile = srcContext != func->getDefSrc (); + curr_inc = srcContext; + + bool src_code = (src_visible & SRC_CODE); + Anno_Types src_type = (src_visible & SRC_METRIC) ? AT_SRC : AT_SRC_ONLY; + + char *img_fname = func ? func->img_fname : NULL; + + // Build a new Function list + Vector<Function*> *FuncLst = new Vector<Function*>; + if (func_scope) + { + if (func) + FuncLst->append (func); + } + else + { + for (int i = 0, sz = functions ? functions->size () : 0; i < sz; i++) + { + Function *fitem = functions->fetch (i); + if (fitem != fitem->cardinal ()) + continue; + if (img_fname == NULL) + img_fname = fitem->img_fname; + if (fitem->img_fname == NULL || strcmp (fitem->img_fname, img_fname)) + continue; + FuncLst->append (fitem); + } + } + if (FuncLst->size () == 0) + { // no function is good + delete FuncLst; + return; + } + cmpSrcContext = srcContext; + FuncLst->sort (func_cmp); + + disasm->set_hex_visible (hex_vis); + for (int index = 0, sz = FuncLst->size (); index < sz; index++) + { + Function *fitem = FuncLst->fetch (index); + uint64_t start_address, end_address; + int64_t inst_size; + if (fitem->getDefSrc () != srcContext && curline > 0) + { + // now flush the left source line, if available + for (; curline <= srcContext->getLineCount (); curline++) + { + // see if there's a compiler comment line to dump + if (cline == curline) + set_ComCom (vis_bits); + if (src_code) + set_src (src_type, srcContext->find_dbeline (curline)); + } + curline = -1; + } + + curr_inc = NULL; + // disassemble one function + start_address = objStabs ? + objStabs->mapOffsetToAddress (fitem->img_offset) : 0; + end_address = start_address + fitem->size; + inst_size = 0; + + disasm->set_addr_end (end_address); + if ((loadobject->flags & SEG_FLAG_DYNAMIC) + && loadobject->platform != Java) + disasm->set_img_name (img_fname); + + for (uint64_t inst_address = start_address; inst_address < end_address;) + { + uint64_t address = inst_address - start_address; + DbeInstr *instr = fitem->find_dbeinstr (0, address); + DbeLine *dbeline = (DbeLine *) (instr->convertto (Histable::LINE)); + if (instr->lineno == -1 && dbeline && dbeline->lineno > 0) + instr->lineno = dbeline->lineno; + + // now write the unannotated source line, if available + if (curline > 0) + { // source is present + int lineno = curline - 1; + if (instr->lineno != -1) + { + if (dbeline && streq (dbeline->sourceFile->get_name (), + srcContext->get_name ())) + lineno = instr->lineno; + } + else if (curr_inc == NULL && srcContext == fitem->def_source + && fitem->line_first > 0) + lineno = fitem->line_first; + + for (; curline <= lineno; curline++) + { + // see if there's a compiler comment line to dump + if (cline == curline) + set_ComCom (vis_bits); + if (mline == curline) + set_MPSlave (); + if (src_code) + set_src (src_type, srcContext->find_dbeline (curline)); + if (curline >= srcContext->getLineCount ()) + { + curline = -1; + break; + } + } + } + + if (funcline_visible) + { // show red lines + if (!curr_inc || (dbeline && curr_inc != dbeline->sourceFile)) + { + Hist_data::HistItem *item = dis_items->new_hist_item (dbeline, AT_FUNC, empty); + curr_inc = dbeline ? dbeline->sourceFile : srcContext; + char *str; + if (curr_inc != srcContext) + { + char *fileName = curr_inc->dbeFile->getResolvedPath (); + str = dbe_sprintf (GTXT ("<Function: %s, instructions from source file %s>"), + fitem->get_name (), fileName); + } + else + str = dbe_sprintf (GTXT ("<Function: %s>"), + fitem->get_name ()); + item->value[name_idx].l = str; + data_items->append_hist_item (item); + } + } + + char *dis_str = get_disasm (inst_address, end_address, start_address, + fitem->img_offset, inst_size); + if (inst_size == 0) + break; + else if (instr->size == 0) + instr->size = (unsigned int) inst_size; + inst_address += inst_size; + + // stomp out control characters + for (size_t i = 0, len = strlen (dis_str); i < len; i++) + { + if (dis_str[i] == '\t') + dis_str[i] = ' '; + } + + for (int i = 0; i < bTargets.size (); i++) + { + target_info_t *bTarget = bTargets.fetch (i); + if (bTarget->offset == fitem->img_offset + address) + { + // insert a new line for the bTarget + size_t colon = strcspn (dis_str, NTXT (":")); + char *msg = GTXT ("* <branch target>"); + size_t len = colon + strlen (msg); + len = (len < 50) ? (50 - len) : 1; + char *new_dis_str = dbe_sprintf ("%.*s%s%*c <===----<<<", + (int) colon, dis_str, msg, + (int) len, ' '); + DbeInstr *bt = fitem->find_dbeinstr (PCTrgtFlag, address); + bt->lineno = instr->lineno; + bt->size = 0; + set_dis (bt, AT_DIS, nextFile, new_dis_str); + break; + } + } + + // AnalyzerInfo/Datatype annotations + if (infoList != NULL) + { + inst_info_t *info = NULL; + int pinfo; + Vec_loop (inst_info_t*, infoList, pinfo, info) + { + if (info->offset == fitem->img_offset + address) break; + } + if (info != NULL) + { // got a matching memop + char typetag[400]; + typetag[0] = '\0'; + long t; + datatype_t *dtype = NULL; + Vec_loop (datatype_t*, datatypes, t, dtype) + { + if (dtype->datatype_id == info->memop->datatype_id) + break; + } + if (datatypes != NULL) + { + size_t len = strlen (typetag); + if (dtype == NULL || t == datatypes->size ()) + snprintf (typetag + len, sizeof (typetag) - len, "%s", + PTXT (DOBJ_UNSPECIFIED)); + else if (dtype->dobj == NULL) + snprintf (typetag + len, sizeof (typetag) - len, "%s", + PTXT (DOBJ_UNDETERMINED)); + else + snprintf (typetag + len, sizeof (typetag) - len, "%s", + dtype->dobj->get_name ()); + } + if (strlen (typetag) > 1) + { + char *new_dis_str; + new_dis_str = dbe_sprintf ("%-50s %s", dis_str, typetag); + free (dis_str); + dis_str = new_dis_str; + } + } + } + set_dis (instr, AT_DIS, nextFile, dis_str); + } + } + + // now flush the left source line, if available + if (curline > 0) + { // source is present + for (; curline <= srcContext->getLineCount (); curline++) + { + // see if there's a compiler comment line to dump + if (cline == curline) + set_ComCom (vis_bits); + + if (src_code) + set_src (src_type, srcContext->find_dbeline (curline)); + } + } + + // See if compiler flags are set; if so, append them + if (cmpline_visible && comp_flags) + { + Hist_data::HistItem *item = dis_items->new_hist_item (NULL, AT_EMPTY, + empty); + item->value[name_idx].l = dbe_strdup (NTXT ("")); + data_items->append_hist_item (item); + item = dis_items->new_hist_item (NULL, AT_COM, empty); + item->value[name_idx].l = dbe_sprintf (GTXT ("Compile flags: %s"), + comp_flags); + data_items->append_hist_item (item); + } + delete FuncLst; +} + +// set_src -- inserts one or more lines into the growing data list +void +Module::set_src (Anno_Types type, DbeLine *dbeline) +{ + Hist_data::HistItem *item; + + // Flush items that are not represented in source + while (sline >= 0 && sline < curline) + { + item = src_items->fetch (sindex); + if (((DbeLine*) item->obj)->lineno > 0) + set_one (item, AT_QUOTE, item->obj->get_name ()); + + if (++sindex < src_items->size ()) // get next line with metrics + sline = ((DbeLine*) src_items->fetch (sindex)->obj)->lineno; + else + sline = -1; + } + + // write values in the metric fields for the given source line + if (curline == sline) + { // got metrics for this line + item = src_items->fetch (sindex); + if (((DbeLine*) item->obj)->lineno > 0) + set_one (item, AT_SRC, srcContext->getLine (curline)); + + if (++sindex < src_items->size ()) // get next line metric index + sline = ((DbeLine*) src_items->fetch (sindex)->obj)->lineno; + else + sline = -1; + } + else + { + item = data_items->new_hist_item (dbeline, type, empty); + if (size_index != -1) + item->value[size_index].ll = dbeline->get_size (); + if (addr_index != -1) + item->value[addr_index].ll = dbeline->get_addr (); + item->value[name_idx].l = dbe_strdup (srcContext->getLine (curline)); + data_items->append_hist_item (item); + } +} + +void +Module::set_dis (DbeInstr *instr, Anno_Types type, bool nextFile, char *dis_str) +{ + // Flush items that are not represented in disassembly + while (daddr && daddr->pc_cmp (instr) < 0) + { + if (!nextFile) + set_one (dis_items->fetch (dindex), AT_QUOTE, daddr->get_name ()); + if (++dindex < dis_items->size ()) // get next line metric index + daddr = (DbeInstr*) dis_items->fetch (dindex)->obj; + else + daddr = NULL; + } + + // Write values in the metric fields for the given pc index value + if (instr->inlinedInd >= 0) + { + StringBuilder sb; + sb.append (dis_str); + instr->add_inlined_info (&sb); + free (dis_str); + dis_str = sb.toString (); + } + if (daddr && daddr->pc_cmp (instr) == 0) + { + Hist_data::HistItem *item = data_items->new_hist_item (instr, type, + dis_items->fetch (dindex)->value); + item->value[name_idx].tag = VT_LABEL; + item->value[name_idx].l = dis_str; + data_items->append_hist_item (item); + if (dis_items->get_callsite_mark ()->get (dis_items->fetch (dindex)->obj)) + data_items->get_callsite_mark ()->put (item->obj, 1); + + if (++dindex < dis_items->size ()) // get next line metric index + daddr = (DbeInstr*) dis_items->fetch (dindex)->obj; + else + daddr = NULL; + } + else + { + // create a new item for this PC + Hist_data::HistItem *item = dis_items->new_hist_item (instr, type, empty); + if (size_index != -1) + item->value[size_index].ll = instr->size; + if (addr_index != -1) + item->value[addr_index].ll = instr->get_addr (); + item->value[name_idx].tag = VT_LABEL; + item->value[name_idx].l = dis_str; + data_items->append_hist_item (item); + } +} + +void +Module::set_MPSlave () +{ + Hist_data::HistItem *item; + Function *fp; + int index; + + // write the inclusive metrics for slave threads + while (mline == curline) + { + item = dis_items->fetch (mindex); + DbeInstr *instr = (DbeInstr *) item->obj; + Vec_loop (Function*, functions, index, fp) + { + if (fp->derivedNode == instr) + { + set_one (item, AT_QUOTE, (fp->isOutlineFunction) ? + GTXT ("<inclusive metrics for outlined functions>") : + GTXT ("<inclusive metrics for slave threads>")); + break; + } + } + + mindex++; + if (mindex < dis_items->size ()) + mline = (unsigned) ((DbeInstr*) (dis_items->fetch (mindex)->obj))->addr; + else + mline = -1; + } +}//set_MPSlave + +void +Module::set_one (Hist_data::HistItem *org_item, Anno_Types type, + const char *text) +{ + if (org_item == NULL) + return; + Hist_data::HistItem *item = data_items->new_hist_item (org_item->obj, type, + org_item->value); + item->value[name_idx].tag = VT_LABEL; + item->value[name_idx].l = dbe_strdup (text); + data_items->append_hist_item (item); + if (org_item != NULL && src_items != NULL + && src_items->get_callsite_mark ()->get (org_item->obj)) + data_items->get_callsite_mark ()->put (item->obj, 1); +}//set_one + +void +Module::set_ComCom (int vis_bits) +{ + Hist_data::HistItem *item; + Function *func = dbeSession->get_Unknown_Function (); + + if (vis_bits) + { + // precede the compiler commentary with a blank line + item = data_items->new_hist_item (func, AT_EMPTY, empty); + item->value[name_idx].l = dbe_strdup (NTXT ("")); + data_items->append_hist_item (item); + } + while (cline == curline) + { + ComC *comm = comComs->fetch (cindex); + if (comm->visible & vis_bits) + { + // write the compiler commentary + item = data_items->new_hist_item (func, AT_COM, empty); + item->value[name_idx].l = dbe_strdup (comm->com_str); + data_items->append_hist_item (item); + } + if (++cindex < comComs->size ()) + cline = comComs->fetch (cindex)->line; + else + cline = -1; + } +} + +void +Module::dump_dataobjects (FILE *out) +{ + int index; + datatype_t *dtype; + Vec_loop (datatype_t*, datatypes, index, dtype) + { + fprintf (out, NTXT ("[0x%08X,%6lld] %4d %6d %s "), dtype->datatype_id, + dtype->dobj ? dtype->dobj->id : 0LL, + dtype->memop_refs, dtype->event_data, + (dtype->dobj != NULL ? (dtype->dobj->get_name () ? + dtype->dobj->get_name () : "<NULL>") : "<no object>")); +#if DEBUG + Histable* scope = dtype->dobj ? dtype->dobj->get_scope () : NULL; + if (scope != NULL) + { + switch (scope->get_type ()) + { + case Histable::LOADOBJECT: + case Histable::FUNCTION: + fprintf (out, NTXT ("%s"), scope->get_name ()); + break; + case Histable::MODULE: + { + char *filename = get_basename (scope->get_name ()); + fprintf (out, NTXT ("%s"), filename); + break; + } + default: + fprintf (out, NTXT ("\tUnexpected scope %d:%s"), + scope->get_type (), scope->get_name ()); + } + } +#endif + fprintf (out, NTXT ("\n")); + } +} + +void +Module::set_name (char *str) +{ + free (name); + name = str; +} + +void +Module::read_hwcprof_info () +{ + if (hwcprof == 0) + { + hwcprof = 1; + Stabs *stabs = openDebugInfo (); + if (stabs) + stabs->read_hwcprof_info (this); + } +} + +void +Module::reset_datatypes () +{ + for (int i = 0, sz = datatypes ? datatypes->size () : -1; i < sz; i++) + { + datatype_t *t = datatypes->fetch (i); + t->event_data = 0; + } +} + +DataObject * +Module::get_dobj (uint32_t dtype_id) +{ + read_hwcprof_info (); + for (int i = 0, sz = datatypes ? datatypes->size () : -1; i < sz; i++) + { + datatype_t *t = datatypes->fetch (i); + if (t->datatype_id == dtype_id) + { + t->event_data++; + return t->dobj; + } + } + return NULL; +} + +int +Module::readFile () +{ + return AE_OK; +} + +Vector<Histable*> * +Module::get_comparable_objs () +{ + update_comparable_objs (); + if (comparable_objs || dbeSession->expGroups->size () <= 1 || loadobject == NULL) + return comparable_objs; + Vector<Histable*> *comparableLoadObjs = loadobject->get_comparable_objs (); + if (comparableLoadObjs == NULL) + return NULL; + comparable_objs = new Vector<Histable*>(comparableLoadObjs->size ()); + for (int i = 0, sz = comparableLoadObjs->size (); i < sz; i++) + { + Module *mod = NULL; + LoadObject *lo = (LoadObject*) comparableLoadObjs->fetch (i); + if (lo) + { + mod = lo->get_comparable_Module (this); + if (mod) + mod->comparable_objs = comparable_objs; + } + comparable_objs->store (i, mod); + } + dump_comparable_objs (); + return comparable_objs; +} + +JMethod * +Module::find_jmethod (const char *nm, const char *sig) +{ + // Vladimir: Probably we should not use linear search + for (long i = 0, sz = VecSize (functions); i < sz; i++) + { + JMethod *jmthd = (JMethod*) functions->get (i); + char *jmt_name = jmthd->get_name (Histable::SHORT); + if (strcmp (jmt_name, nm) == 0 + && strcmp (jmthd->get_signature (), sig) == 0) + return jmthd; + } + return NULL; +} |