/* Copyright (C) 2021-2024 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 #include #include #include "DbeSession.h" #include "Command.h" #include "Application.h" #include "MemorySpace.h" #include "i18n.h" #define MAXARGS 20 static const char *LIBNAME = "../lib/analyzer/lib/machinemodels"; char * DbeSession::find_mach_model (char *name) { // Read current working directory to see if it's there if (name[0] == '/') { // Absolute path given char *path = dbe_sprintf (NTXT ("%s.ermm"), name); if (access (path, R_OK | F_OK) == 0) return path; free (path); // Don't try anywhere else return NULL; } char *path = dbe_sprintf (NTXT ("./%s.ermm"), name); if (access (path, R_OK | F_OK) == 0) return path; free (path); // Read the user's home directory to see if it's there char *home = getenv (NTXT ("HOME")); if (home != NULL) { path = dbe_sprintf (NTXT ("%s/%s.ermm"), home, name); if (access (path, R_OK | F_OK) == 0) return path; free (path); } if (strchr (name, (int) '/') != NULL) // name has a slash; don't look in system installation directory return NULL; // Read system installation directory to see if it's there path = dbe_sprintf ("%s/%s/%s.ermm", theApplication->get_run_dir (), LIBNAME, name); if (access (path, R_OK | F_OK) == 0) return path; free (path); return NULL; } // Handle the definitions from a machinemodel file // Return value is NULL if it was OK, or an error message if not char * DbeSession::load_mach_model (char *_name) { CmdType cmd_type; int arg_count, cparam; char *cmd, *end_cmd; char *arglist[MAXARGS]; char *ret = NULL; char *path = NULL; FILE *fptr = NULL; // Does name have .ermm suffix? If so, strip it away char *name = dbe_strdup (_name); size_t len = strlen (name); if (len > 5 && strcmp (name + len - 5, ".ermm") == 0) name[len - 5] = 0; if ((mach_model_loaded != NULL) && (strcmp (name, mach_model_loaded) == 0)) { ret = dbe_sprintf (GTXT ("Machine model %s is already loaded\n"), name); free (name); return ret; } else if (mach_model_loaded == NULL && len == 0) { ret = dbe_sprintf (GTXT ("No Machine model is loaded\n")); free (name); return ret; } if (len != 0) { // zero-length just means unload any previously loaded model; only look if non-zero path = find_mach_model (name); if (path == NULL) { ret = dbe_sprintf (GTXT ("Machine model %s not found\n"), name); free (name); return ret; } fptr = fopen (path, NTXT ("r")); if (fptr == NULL) { ret = dbe_sprintf (GTXT ("Open of Machine model %s, file %s failed\n"), name, path); free (path); free (name); return ret; } } // We are now committed to make the new machine model the loaded one; // Delete any MemoryObjects from any previously loaded machinemodel if (dbeSession->mach_model_loaded != NULL) { Vector *oldobjs = MemorySpace::getMachineModelMemObjs (dbeSession->mach_model_loaded); for (int i = 0; i < oldobjs->size (); i++) MemorySpace::mobj_delete (oldobjs->fetch (i)); delete oldobjs; free (mach_model_loaded); } if (len == 0) { mach_model_loaded = NULL; free (name); // and there's no "loading" to do; just return return NULL; } else mach_model_loaded = name; int line_no = 0; end_cmd = NULL; while (!feof (fptr)) { char *script = read_line (fptr); if (script == NULL) continue; line_no++; strtok (script, NTXT ("\n")); // extract the command cmd = strtok (script, NTXT (" \t")); if (cmd == NULL || *cmd == '#' || *cmd == '\n') { free (script); continue; } char *remainder = strtok (NULL, NTXT ("\n")); // now extract the arguments int nargs = 0; for (;;) { if (nargs >= MAXARGS) { ret = dbe_sprintf (GTXT ("Warning: more than %d arguments to %s command, line %d\n"), MAXARGS, cmd, line_no); continue; } char *nextarg = strtok (remainder, NTXT ("\n")); if (nextarg == NULL || *nextarg == '#') // either the end of the line, or a comment indicator break; arglist[nargs++] = parse_qstring (nextarg, &end_cmd); remainder = end_cmd; if (remainder == NULL) break; // skip any blanks or tabs to get to next argument while ((*remainder == ' ') || (*remainder == '\t')) remainder++; } cmd_type = Command::get_command (cmd, arg_count, cparam); // check for extra arguments if (cmd_type != UNKNOWN_CMD && cmd_type != INDXOBJDEF && nargs > arg_count) ret = dbe_sprintf (GTXT ("Warning: extra arguments to %s command, line %d\n"), cmd, line_no); if (nargs < arg_count) { ret = dbe_sprintf (GTXT ("Error: missing arguments to %s command, line %d\n"), cmd, line_no); // ignore this command free (script); continue; } switch (cmd_type) { case INDXOBJDEF: { char *err = dbeSession->indxobj_define (arglist[0], NULL, arglist[1], (nargs >= 3) ? PTXT (arglist[2]) : NULL, (nargs >= 4) ? PTXT (arglist[3]) : NULL); if (err != NULL) ret = dbe_sprintf (GTXT (" %s: line %d `%s %s %s'\n"), err, line_no, cmd, arglist[0], arglist[1]); break; } case COMMENT: // ignore the line break; default: { // unexpected command in a machinemodel file ret = dbe_sprintf (GTXT ("Unexpected command in machinemodel file %s on line %d: `%.64s'\n"), path, line_no, cmd); break; } } free (script); } fclose (fptr); return ret; } Vector * DbeSession::list_mach_models () { Vector *model_names = new Vector(); // Open the current directory to read the entries there DIR *dir = opendir (NTXT (".")); if (dir != NULL) { struct dirent *entry = NULL; while ((entry = readdir (dir)) != NULL) { size_t len = strlen (entry->d_name); if (len < 5 || strcmp (entry->d_name + len - 5, ".ermm") != 0) continue; char *model = dbe_strdup (entry->d_name); // remove the .ermm suffix model[len - 5] = 0; // add to vector model_names->append (dbe_strdup (model)); } closedir (dir); } // Read the user's home directory to list the models there char *home = getenv ("HOME"); if (home != NULL) { dir = opendir (home); if (dir != NULL) { struct dirent *entry = NULL; while ((entry = readdir (dir)) != NULL) { size_t len = strlen (entry->d_name); if (len < 5 || strcmp (entry->d_name + len - 5, ".ermm") != 0) continue; char *model = dbe_strdup (entry->d_name); // remove the .ermm suffix model[len - 5] = 0; // add to vector model_names->append (dbe_strdup (model)); } closedir (dir); } } // Read system installation directory to list the models there char *sysdir = dbe_sprintf ("%s/%s", theApplication->get_run_dir (), LIBNAME); dir = opendir (sysdir); if (dir != NULL) { struct dirent *entry = NULL; while ((entry = readdir (dir)) != NULL) { size_t len = strlen (entry->d_name); if (len < 5 || strcmp (entry->d_name + len - 5, ".ermm") != 0) continue; char *model = dbe_strdup (entry->d_name); // remove the .ermm suffix model[len - 5] = 0; // add to vector model_names->append (dbe_strdup (model)); } closedir (dir); } return model_names; }