]> git.ipfire.org Git - thirdparty/binutils-gdb.git/blame - gprofng/src/SourceFile.cc
Update year range in copyright notice of binutils files
[thirdparty/binutils-gdb.git] / gprofng / src / SourceFile.cc
CommitLineData
fd67aa11 1/* Copyright (C) 2021-2024 Free Software Foundation, Inc.
bb368aad
VM
2 Contributed by Oracle.
3
4 This file is part of GNU Binutils.
5
6 This program is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 3, or (at your option)
9 any later version.
10
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
15
16 You should have received a copy of the GNU General Public License
17 along with this program; if not, write to the Free Software
18 Foundation, 51 Franklin Street - Fifth Floor, Boston,
19 MA 02110-1301, USA. */
20
21#include "config.h"
22#include <unistd.h>
23
24#include "util.h"
25#include "DbeSession.h"
26#include "Function.h"
27#include "SourceFile.h"
28#include "DefaultMap.h"
29#include "DbeFile.h"
30#include "LoadObject.h"
31#include "Module.h"
32
33int SourceFile::curId = 0;
34
35SourceFile::SourceFile (const char *file_name)
36{
37 status = OS_NOTREAD;
38 srcLines = NULL;
39 srcInode = -1;
40 lines = NULL;
41 dbeLines = NULL;
42 functions = new DefaultMap<Function *, Function *>();
43 dbeFile = new DbeFile (file_name);
44 dbeFile->filetype |= DbeFile::F_SOURCE | DbeFile::F_FILE;
45 set_name ((char *) file_name);
46 srcMTime = (time_t) 0;
47 isTmpFile = false;
48 flags = 0;
49 read_stabs = false;
50 id = (uint64_t) ((Histable::SOURCEFILE << 24) + curId) << 32;
51 curId++;
52}
53
54SourceFile::~SourceFile ()
55{
56 destroy_map (DbeLine *, dbeLines);
57 delete functions;
58 delete dbeFile;
59 if (lines)
60 {
61 lines->destroy ();
62 delete lines;
63 }
64 if (srcLines)
65 {
66 free (srcLines->get (0));
67 delete srcLines;
68 }
69 if (isTmpFile)
70 unlink (name);
71}
72
73void
74SourceFile::set_name (char* _name)
75{
76 name = dbe_strdup (_name);
77}
78
79char*
80SourceFile::get_name (NameFormat)
81{
82 return name;
83}
84
85bool
86SourceFile::readSource ()
87{
88 if (srcLines)
89 return true;
90 status = OS_NOSRC;
91 char *location = dbeFile->get_location ();
92 if (location == NULL)
93 return false;
94 if (!isTmpFile)
95 srcMTime = dbeFile->sbuf.st_mtime;
96 srcInode = dbeFile->sbuf.st_ino;
97 size_t srcLen = dbeFile->sbuf.st_size;
98 int fd = open64 (location, O_RDONLY);
99 if (fd == -1)
100 {
101 status = OS_NOSRC;
102 return false;
103 }
104 char *srcMap = (char *) malloc (srcLen + 1);
105 int64_t sz = read_from_file (fd, srcMap, srcLen);
106 if (sz != (int64_t) srcLen)
107 append_msg (CMSG_ERROR, GTXT ("%s: Can read only %lld bytes instead %lld"),
108 location, (long long) sz, (long long) srcLen);
109 srcMap[sz] = 0;
110 close (fd);
111
112 // Count the number of lines in the file, converting <nl> to zero
113 srcLines = new Vector<char*>();
114 srcLines->append (srcMap);
115 for (int64_t i = 0; i < sz; i++)
116 {
117 if (srcMap[i] == '\r')
118 { // Window style
119 srcMap[i] = 0;
120 if (i + 1 < sz && srcMap[i + 1] != '\n')
121 srcLines->append (srcMap + i + 1);
122 }
123 else if (srcMap[i] == '\n')
124 {
125 srcMap[i] = '\0';
126 if (i + 1 < sz)
127 srcLines->append (srcMap + i + 1);
128 }
129 }
130 if (dbeLines)
131 {
132 Vector<DbeLine *> *v = dbeLines->values ();
133 for (long i = 0, sz1 = v ? v->size () : 0; i < sz1; i++)
134 {
135 DbeLine *p = v->get (i);
136 if (p->lineno >= srcLines->size ())
137 append_msg (CMSG_ERROR, GTXT ("Wrong line number %d. '%s' has only %d lines"),
53beac2e
VM
138 (int) p->lineno, dbeFile->get_location (),
139 (int) srcLines->size ());
bb368aad
VM
140 }
141 delete v;
142 }
143 status = OS_OK;
144 return true;
145}
146
147char *
148SourceFile::getLine (int lineno)
149{
150 assert (srcLines != NULL);
151 if (lineno > 0 && lineno <= srcLines->size ())
152 return srcLines->get (lineno - 1);
153 return NTXT ("");
154}
155
156DbeLine *
157SourceFile::find_dbeline (Function *func, int lineno)
158{
159 if (lineno < 0 || (lineno == 0 && func == NULL))
160 return NULL;
161 DbeLine *dbeLine = NULL;
162 if (lines)
163 { // the source is available
164 if (lineno > lines->size ())
165 {
166 if (dbeLines)
167 dbeLine = dbeLines->get (lineno);
168 if (dbeLine == NULL)
169 append_msg (CMSG_ERROR,
170 GTXT ("Wrong line number %d. '%s' has only %d lines"),
53beac2e
VM
171 (int) lineno, dbeFile->get_location (),
172 (int) lines->size ());
bb368aad
VM
173 }
174 else
175 {
176 dbeLine = lines->fetch (lineno);
177 if (dbeLine == NULL)
178 {
179 dbeLine = new DbeLine (NULL, this, lineno);
180 lines->store (lineno, dbeLine);
181 }
182 }
183 }
184 if (dbeLine == NULL)
185 { // the source is not yet read or lineno is wrong
186 if (dbeLines == NULL)
187 dbeLines = new DefaultMap<int, DbeLine *>();
188 dbeLine = dbeLines->get (lineno);
189 if (dbeLine == NULL)
190 {
191 dbeLine = new DbeLine (NULL, this, lineno);
192 dbeLines->put (lineno, dbeLine);
193 }
194 }
195
196 for (DbeLine *last = dbeLine;; last = last->dbeline_func_next)
197 {
198 if (last->func == func)
199 return last;
200 if (last->dbeline_func_next == NULL)
201 {
202 DbeLine *dl = new DbeLine (func, this, lineno);
203 if (functions->get (func) == NULL)
204 functions->put (func, func);
205 last->dbeline_func_next = dl;
206 dl->dbeline_base = dbeLine;
207 return dl;
208 }
209 }
210}
211
212Vector<Function *> *
213SourceFile::get_functions ()
214{
215 if (!read_stabs)
216 {
217 // Create all DbeLines for this Source
218 read_stabs = true;
219 Vector<LoadObject *> *lobjs = dbeSession->get_LoadObjects ();
220 for (long i = 0, sz = VecSize (lobjs); i < sz; i++)
221 {
222 LoadObject *lo = lobjs->get (i);
223 for (long i1 = 0, sz1 = VecSize (lo->seg_modules); i1 < sz1; i1++)
224 {
225 Module *mod = lo->seg_modules->get (i1);
226 mod->read_stabs ();
227 }
228 }
229 }
230 return functions->keySet ();
231}