diff options
Diffstat (limited to 'gprofng/src/SourceFile.cc')
-rw-r--r-- | gprofng/src/SourceFile.cc | 229 |
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 (); +} |