summaryrefslogtreecommitdiff
path: root/gprofng/src/SourceFile.cc
diff options
context:
space:
mode:
Diffstat (limited to 'gprofng/src/SourceFile.cc')
-rw-r--r--gprofng/src/SourceFile.cc229
1 files changed, 229 insertions, 0 deletions
diff --git a/gprofng/src/SourceFile.cc b/gprofng/src/SourceFile.cc
new file mode 100644
index 00000000000..bd0a1f19556
--- /dev/null
+++ b/gprofng/src/SourceFile.cc
@@ -0,0 +1,229 @@
+/* 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 "util.h"
+#include "DbeSession.h"
+#include "Function.h"
+#include "SourceFile.h"
+#include "DefaultMap.h"
+#include "DbeFile.h"
+#include "LoadObject.h"
+#include "Module.h"
+
+int SourceFile::curId = 0;
+
+SourceFile::SourceFile (const char *file_name)
+{
+ status = OS_NOTREAD;
+ srcLines = NULL;
+ srcInode = -1;
+ lines = NULL;
+ dbeLines = NULL;
+ functions = new DefaultMap<Function *, Function *>();
+ dbeFile = new DbeFile (file_name);
+ dbeFile->filetype |= DbeFile::F_SOURCE | DbeFile::F_FILE;
+ set_name ((char *) file_name);
+ srcMTime = (time_t) 0;
+ isTmpFile = false;
+ flags = 0;
+ read_stabs = false;
+ id = (uint64_t) ((Histable::SOURCEFILE << 24) + curId) << 32;
+ curId++;
+}
+
+SourceFile::~SourceFile ()
+{
+ destroy_map (DbeLine *, dbeLines);
+ delete functions;
+ delete dbeFile;
+ if (lines)
+ {
+ lines->destroy ();
+ delete lines;
+ }
+ if (srcLines)
+ {
+ free (srcLines->get (0));
+ delete srcLines;
+ }
+ if (isTmpFile)
+ unlink (name);
+}
+
+void
+SourceFile::set_name (char* _name)
+{
+ name = dbe_strdup (_name);
+}
+
+char*
+SourceFile::get_name (NameFormat)
+{
+ return name;
+}
+
+bool
+SourceFile::readSource ()
+{
+ if (srcLines)
+ return true;
+ status = OS_NOSRC;
+ char *location = dbeFile->get_location ();
+ if (location == NULL)
+ return false;
+ if (!isTmpFile)
+ srcMTime = dbeFile->sbuf.st_mtime;
+ srcInode = dbeFile->sbuf.st_ino;
+ size_t srcLen = dbeFile->sbuf.st_size;
+ int fd = open64 (location, O_RDONLY);
+ if (fd == -1)
+ {
+ status = OS_NOSRC;
+ return false;
+ }
+ char *srcMap = (char *) malloc (srcLen + 1);
+ int64_t sz = read_from_file (fd, srcMap, srcLen);
+ if (sz != (int64_t) srcLen)
+ append_msg (CMSG_ERROR, GTXT ("%s: Can read only %lld bytes instead %lld"),
+ location, (long long) sz, (long long) srcLen);
+ srcMap[sz] = 0;
+ close (fd);
+
+ // Count the number of lines in the file, converting <nl> to zero
+ srcLines = new Vector<char*>();
+ srcLines->append (srcMap);
+ for (int64_t i = 0; i < sz; i++)
+ {
+ if (srcMap[i] == '\r')
+ { // Window style
+ srcMap[i] = 0;
+ if (i + 1 < sz && srcMap[i + 1] != '\n')
+ srcLines->append (srcMap + i + 1);
+ }
+ else if (srcMap[i] == '\n')
+ {
+ srcMap[i] = '\0';
+ if (i + 1 < sz)
+ srcLines->append (srcMap + i + 1);
+ }
+ }
+ if (dbeLines)
+ {
+ Vector<DbeLine *> *v = dbeLines->values ();
+ for (long i = 0, sz1 = v ? v->size () : 0; i < sz1; i++)
+ {
+ DbeLine *p = v->get (i);
+ if (p->lineno >= srcLines->size ())
+ append_msg (CMSG_ERROR, GTXT ("Wrong line number %d. '%s' has only %d lines"),
+ p->lineno, dbeFile->get_location (), srcLines->size ());
+ }
+ delete v;
+ }
+ status = OS_OK;
+ return true;
+}
+
+char *
+SourceFile::getLine (int lineno)
+{
+ assert (srcLines != NULL);
+ if (lineno > 0 && lineno <= srcLines->size ())
+ return srcLines->get (lineno - 1);
+ return NTXT ("");
+}
+
+DbeLine *
+SourceFile::find_dbeline (Function *func, int lineno)
+{
+ if (lineno < 0 || (lineno == 0 && func == NULL))
+ return NULL;
+ DbeLine *dbeLine = NULL;
+ if (lines)
+ { // the source is available
+ if (lineno > lines->size ())
+ {
+ if (dbeLines)
+ dbeLine = dbeLines->get (lineno);
+ if (dbeLine == NULL)
+ append_msg (CMSG_ERROR,
+ GTXT ("Wrong line number %d. '%s' has only %d lines"),
+ lineno, dbeFile->get_location (), lines->size ());
+ }
+ else
+ {
+ dbeLine = lines->fetch (lineno);
+ if (dbeLine == NULL)
+ {
+ dbeLine = new DbeLine (NULL, this, lineno);
+ lines->store (lineno, dbeLine);
+ }
+ }
+ }
+ if (dbeLine == NULL)
+ { // the source is not yet read or lineno is wrong
+ if (dbeLines == NULL)
+ dbeLines = new DefaultMap<int, DbeLine *>();
+ dbeLine = dbeLines->get (lineno);
+ if (dbeLine == NULL)
+ {
+ dbeLine = new DbeLine (NULL, this, lineno);
+ dbeLines->put (lineno, dbeLine);
+ }
+ }
+
+ for (DbeLine *last = dbeLine;; last = last->dbeline_func_next)
+ {
+ if (last->func == func)
+ return last;
+ if (last->dbeline_func_next == NULL)
+ {
+ DbeLine *dl = new DbeLine (func, this, lineno);
+ if (functions->get (func) == NULL)
+ functions->put (func, func);
+ last->dbeline_func_next = dl;
+ dl->dbeline_base = dbeLine;
+ return dl;
+ }
+ }
+}
+
+Vector<Function *> *
+SourceFile::get_functions ()
+{
+ if (!read_stabs)
+ {
+ // Create all DbeLines for this Source
+ read_stabs = true;
+ Vector<LoadObject *> *lobjs = dbeSession->get_LoadObjects ();
+ for (long i = 0, sz = VecSize (lobjs); i < sz; i++)
+ {
+ LoadObject *lo = lobjs->get (i);
+ for (long i1 = 0, sz1 = VecSize (lo->seg_modules); i1 < sz1; i1++)
+ {
+ Module *mod = lo->seg_modules->get (i1);
+ mod->read_stabs ();
+ }
+ }
+ }
+ return functions->keySet ();
+}