1 /* Loading dynamic objects for GNU Make.
2 Copyright (C) 2012-2022 Free Software Foundation, Inc.
3 This file is part of GNU Make.
5 GNU Make is free software; you can redistribute it and/or modify it under the
6 terms of the GNU General Public License as published by the Free Software
7 Foundation; either version 3 of the License, or (at your option) any later
10 GNU Make is distributed in the hope that it will be useful, but WITHOUT ANY
11 WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
12 A PARTICULAR PURPOSE. See the GNU General Public License for more details.
14 You should have received a copy of the GNU General Public License along with
15 this program. If not, see <https://www.gnu.org/licenses/>. */
27 #define SYMBOL_EXTENSION "_gmk_setup"
33 /* Tru64 V4.0 does not have this flag */
35 # define RTLD_GLOBAL 0
40 struct load_list *next;
45 static struct load_list *loaded_syms = NULL;
48 load_object (const floc *flocp, int noerror, const char *ldname,
51 static void *global_dl = NULL;
56 global_dl = dlopen (NULL, RTLD_NOW|RTLD_GLOBAL);
59 const char *err = dlerror ();
60 OS (fatal, flocp, _("Failed to open global symbol table: %s"), err);
64 symp = (load_func_t) dlsym (global_dl, symname);
67 struct load_list *new;
70 /* If the path has no "/", try the current directory first. */
71 if (! strchr (ldname, '/')
73 && ! strchr (ldname, '\\')
76 dlp = dlopen (concat (2, "./", ldname), RTLD_LAZY|RTLD_GLOBAL);
78 /* If we haven't opened it yet, try the default search path. */
80 dlp = dlopen (ldname, RTLD_LAZY|RTLD_GLOBAL);
82 /* Still no? Then fail. */
85 const char *err = dlerror ();
87 DB (DB_BASIC, ("%s\n", err));
89 OS (error, flocp, "%s", err);
93 DB (DB_VERBOSE, (_("Loaded shared object %s\n"), ldname));
95 /* Assert that the GPL license symbol is defined. */
96 symp = (load_func_t) dlsym (dlp, "plugin_is_GPL_compatible");
99 _("Loaded object %s is not declared to be GPL compatible"),
102 symp = (load_func_t) dlsym (dlp, symname);
105 const char *err = dlerror ();
106 OSSS (fatal, flocp, _("Failed to load symbol %s from %s: %s"),
107 symname, ldname, err);
110 /* Add this symbol to a trivial lookup table. This is not efficient but
111 it's highly unlikely we'll be loading lots of objects, and we only
112 need it to look them up on unload, if we rebuild them. */
113 new = xmalloc (sizeof (struct load_list));
114 new->name = xstrdup (ldname);
116 new->next = loaded_syms;
124 load_file (const floc *flocp, struct file *file, int noerror)
126 const char *ldname = file->name;
127 size_t nmlen = strlen (ldname);
128 char *new = alloca (nmlen + CSTRLEN (SYMBOL_EXTENSION) + 1);
129 char *symname = NULL;
134 /* Break the input into an object file name and a symbol name. If no symbol
135 name was provided, compute one from the object file name. */
136 fp = strchr (ldname, '(');
141 /* There's an open paren, so see if there's a close paren: if so use
142 that as the symbol name. We can't have whitespace: it would have
143 been chopped up before this function is called. */
144 ep = strchr (fp+1, ')');
145 if (ep && ep[1] == '\0')
147 size_t l = fp - ldname;
151 OS (fatal, flocp, _("Empty symbol name for load: %s"), ldname);
153 /* Make a copy of the ldname part. */
154 memcpy (new, ldname, l);
159 /* Make a copy of the symbol name part. */
160 symname = new + l + 1;
161 memcpy (symname, fp, ep - fp);
162 symname[ep - fp] = '\0';
166 /* Make sure this name is in the string cache. */
167 ldname = file->name = strcache_add (ldname);
169 /* If this object has been loaded, we're done: return -1 to ensure make does
170 not rebuild again. If a rebuild is allowed it was set up when this
171 object was initially loaded. */
172 file = lookup_file (ldname);
173 if (file && file->loaded)
176 /* If we didn't find a symbol name yet, construct it from the ldname. */
181 fp = strrchr (ldname, '/');
182 #ifdef HAVE_DOS_PATHS
185 const char *fp2 = strchr (fp, '\\');
191 fp = strrchr (ldname, '\\');
192 /* The (improbable) case of d:foo. */
193 if (fp && *fp && fp[1] == ':')
200 while (isalnum ((unsigned char) *fp) || *fp == '_')
202 strcpy (p, SYMBOL_EXTENSION);
206 DB (DB_VERBOSE, (_("Loading symbol %s from %s\n"), symname, ldname));
209 symp = load_object (flocp, noerror, ldname, symname);
213 /* Invoke the symbol. */
216 /* If the load didn't fail, add the file to the .LOADED variable. */
218 do_variable_definition(flocp, ".LOADED", ldname, o_file, f_append_value, 0);
224 unload_file (const char *name)
229 for (d = loaded_syms; d != NULL; d = d->next)
230 if (streq (d->name, name) && d->dlp)
232 DB (DB_VERBOSE, (_("Unloading shared object %s\n"), name));
233 rc = dlclose (d->dlp);
235 perror_with_name ("dlclose: ", d->name);
247 load_file (const floc *flocp, struct file *file UNUSED, int noerror)
251 _("The 'load' operation is not supported on this platform"));
257 unload_file (const char *name UNUSED)
259 O (fatal, NILF, "INTERNAL: Cannot unload when load is not supported");
262 #endif /* MAKE_LOAD */