]> git.ipfire.org Git - thirdparty/binutils-gdb.git/blob - gprofng/src/MachineModel.cc
Update year range in copyright notice of binutils files
[thirdparty/binutils-gdb.git] / gprofng / src / MachineModel.cc
1 /* Copyright (C) 2021-2024 Free Software Foundation, Inc.
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 <string.h>
23 #include <unistd.h>
24 #include <dirent.h>
25
26 #include "DbeSession.h"
27 #include "Command.h"
28 #include "Application.h"
29 #include "MemorySpace.h"
30 #include "i18n.h"
31
32 #define MAXARGS 20
33
34 static const char *LIBNAME = "../lib/analyzer/lib/machinemodels";
35
36 char *
37 DbeSession::find_mach_model (char *name)
38 {
39 // Read current working directory to see if it's there
40 if (name[0] == '/')
41 {
42 // Absolute path given
43 char *path = dbe_sprintf (NTXT ("%s.ermm"), name);
44 if (access (path, R_OK | F_OK) == 0)
45 return path;
46 free (path);
47 // Don't try anywhere else
48 return NULL;
49 }
50
51 char *path = dbe_sprintf (NTXT ("./%s.ermm"), name);
52 if (access (path, R_OK | F_OK) == 0)
53 return path;
54 free (path);
55
56
57 // Read the user's home directory to see if it's there
58 char *home = getenv (NTXT ("HOME"));
59 if (home != NULL)
60 {
61 path = dbe_sprintf (NTXT ("%s/%s.ermm"), home, name);
62 if (access (path, R_OK | F_OK) == 0)
63 return path;
64 free (path);
65 }
66 if (strchr (name, (int) '/') != NULL)
67 // name has a slash; don't look in system installation directory
68 return NULL;
69
70 // Read system installation directory to see if it's there
71 path = dbe_sprintf ("%s/%s/%s.ermm", theApplication->get_run_dir (),
72 LIBNAME, name);
73 if (access (path, R_OK | F_OK) == 0)
74 return path;
75 free (path);
76 return NULL;
77 }
78
79 // Handle the definitions from a machinemodel file
80 // Return value is NULL if it was OK, or an error message if not
81 char *
82 DbeSession::load_mach_model (char *_name)
83 {
84 CmdType cmd_type;
85 int arg_count, cparam;
86 char *cmd, *end_cmd;
87 char *arglist[MAXARGS];
88 char *ret = NULL;
89 char *path = NULL;
90 FILE *fptr = NULL;
91
92 // Does name have .ermm suffix? If so, strip it away
93 char *name = dbe_strdup (_name);
94 size_t len = strlen (name);
95 if (len > 5 && strcmp (name + len - 5, ".ermm") == 0)
96 name[len - 5] = 0;
97
98 if ((mach_model_loaded != NULL) && (strcmp (name, mach_model_loaded) == 0))
99 {
100 ret = dbe_sprintf (GTXT ("Machine model %s is already loaded\n"), name);
101 free (name);
102 return ret;
103 }
104 else if (mach_model_loaded == NULL && len == 0)
105 {
106 ret = dbe_sprintf (GTXT ("No Machine model is loaded\n"));
107 free (name);
108 return ret;
109 }
110
111 if (len != 0)
112 {
113 // zero-length just means unload any previously loaded model; only look if non-zero
114 path = find_mach_model (name);
115 if (path == NULL)
116 {
117 ret = dbe_sprintf (GTXT ("Machine model %s not found\n"), name);
118 free (name);
119 return ret;
120 }
121 fptr = fopen (path, NTXT ("r"));
122 if (fptr == NULL)
123 {
124 ret = dbe_sprintf (GTXT ("Open of Machine model %s, file %s failed\n"), name, path);
125 free (path);
126 free (name);
127 return ret;
128 }
129 }
130
131 // We are now committed to make the new machine model the loaded one;
132 // Delete any MemoryObjects from any previously loaded machinemodel
133 if (dbeSession->mach_model_loaded != NULL)
134 {
135 Vector <char *> *oldobjs = MemorySpace::getMachineModelMemObjs
136 (dbeSession->mach_model_loaded);
137 for (int i = 0; i < oldobjs->size (); i++)
138 MemorySpace::mobj_delete (oldobjs->fetch (i));
139 delete oldobjs;
140 free (mach_model_loaded);
141 }
142 if (len == 0)
143 {
144 mach_model_loaded = NULL;
145 free (name);
146 // and there's no "loading" to do; just return
147 return NULL;
148 }
149 else
150 mach_model_loaded = name;
151
152 int line_no = 0;
153 end_cmd = NULL;
154
155 while (!feof (fptr))
156 {
157 char *script = read_line (fptr);
158 if (script == NULL)
159 continue;
160
161 line_no++;
162 strtok (script, NTXT ("\n"));
163
164 // extract the command
165 cmd = strtok (script, NTXT (" \t"));
166 if (cmd == NULL || *cmd == '#' || *cmd == '\n')
167 {
168 free (script);
169 continue;
170 }
171
172 char *remainder = strtok (NULL, NTXT ("\n"));
173 // now extract the arguments
174 int nargs = 0;
175 for (;;)
176 {
177 if (nargs >= MAXARGS)
178 {
179 ret = dbe_sprintf (GTXT ("Warning: more than %d arguments to %s command, line %d\n"),
180 MAXARGS, cmd, line_no);
181 continue;
182 }
183
184 char *nextarg = strtok (remainder, NTXT ("\n"));
185
186 if (nextarg == NULL || *nextarg == '#')
187 // either the end of the line, or a comment indicator
188 break;
189 arglist[nargs++] = parse_qstring (nextarg, &end_cmd);
190 remainder = end_cmd;
191 if (remainder == NULL)
192 break;
193
194 // skip any blanks or tabs to get to next argument
195 while ((*remainder == ' ') || (*remainder == '\t'))
196 remainder++;
197 }
198
199 cmd_type = Command::get_command (cmd, arg_count, cparam);
200 // check for extra arguments
201 if (cmd_type != UNKNOWN_CMD && cmd_type != INDXOBJDEF && nargs > arg_count)
202 ret = dbe_sprintf (GTXT ("Warning: extra arguments to %s command, line %d\n"),
203 cmd, line_no);
204 if (nargs < arg_count)
205 {
206 ret = dbe_sprintf (GTXT ("Error: missing arguments to %s command, line %d\n"),
207 cmd, line_no);
208
209 // ignore this command
210 free (script);
211 continue;
212 }
213
214 switch (cmd_type)
215 {
216 case INDXOBJDEF:
217 {
218 char *err = dbeSession->indxobj_define (arglist[0], NULL,
219 arglist[1], (nargs >= 3) ? PTXT (arglist[2]) : NULL,
220 (nargs >= 4) ? PTXT (arglist[3]) : NULL);
221 if (err != NULL)
222 ret = dbe_sprintf (GTXT (" %s: line %d `%s %s %s'\n"),
223 err, line_no, cmd, arglist[0], arglist[1]);
224 break;
225 }
226 case COMMENT:
227 // ignore the line
228 break;
229 default:
230 {
231 // unexpected command in a machinemodel file
232 ret = dbe_sprintf (GTXT ("Unexpected command in machinemodel file %s on line %d: `%.64s'\n"),
233 path, line_no, cmd);
234 break;
235 }
236 }
237 free (script);
238 }
239 fclose (fptr);
240 return ret;
241 }
242
243 Vector<char*> *
244 DbeSession::list_mach_models ()
245 {
246 Vector<char*> *model_names = new Vector<char*>();
247
248 // Open the current directory to read the entries there
249 DIR *dir = opendir (NTXT ("."));
250 if (dir != NULL)
251 {
252 struct dirent *entry = NULL;
253 while ((entry = readdir (dir)) != NULL)
254 {
255 size_t len = strlen (entry->d_name);
256 if (len < 5 || strcmp (entry->d_name + len - 5, ".ermm") != 0)
257 continue;
258 char *model = dbe_strdup (entry->d_name);
259
260 // remove the .ermm suffix
261 model[len - 5] = 0;
262
263 // add to vector
264 model_names->append (dbe_strdup (model));
265 }
266 closedir (dir);
267 }
268
269 // Read the user's home directory to list the models there
270 char *home = getenv ("HOME");
271 if (home != NULL)
272 {
273 dir = opendir (home);
274 if (dir != NULL)
275 {
276 struct dirent *entry = NULL;
277 while ((entry = readdir (dir)) != NULL)
278 {
279 size_t len = strlen (entry->d_name);
280 if (len < 5 || strcmp (entry->d_name + len - 5, ".ermm") != 0)
281 continue;
282 char *model = dbe_strdup (entry->d_name);
283
284 // remove the .ermm suffix
285 model[len - 5] = 0;
286
287 // add to vector
288 model_names->append (dbe_strdup (model));
289 }
290 closedir (dir);
291 }
292 }
293
294 // Read system installation directory to list the models there
295 char *sysdir = dbe_sprintf ("%s/%s", theApplication->get_run_dir (), LIBNAME);
296
297 dir = opendir (sysdir);
298 if (dir != NULL)
299 {
300 struct dirent *entry = NULL;
301 while ((entry = readdir (dir)) != NULL)
302 {
303 size_t len = strlen (entry->d_name);
304 if (len < 5 || strcmp (entry->d_name + len - 5, ".ermm") != 0)
305 continue;
306 char *model = dbe_strdup (entry->d_name);
307
308 // remove the .ermm suffix
309 model[len - 5] = 0;
310
311 // add to vector
312 model_names->append (dbe_strdup (model));
313 }
314 closedir (dir);
315 }
316 return model_names;
317 }