1 /* Loading dynamic objects for GNU Make.
2 Copyright (C) 2012-2016 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 <http://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", err));
89 OS (error, flocp, "%s", err);
93 /* Assert that the GPL license symbol is defined. */
94 symp = (load_func_t) dlsym (dlp, "plugin_is_GPL_compatible");
97 _("Loaded object %s is not declared to be GPL compatible"),
100 symp = (load_func_t) dlsym (dlp, symname);
103 const char *err = dlerror ();
104 OSSS (fatal, flocp, _("Failed to load symbol %s from %s: %s"),
105 symname, ldname, err);
108 /* Add this symbol to a trivial lookup table. This is not efficient but
109 it's highly unlikely we'll be loading lots of objects, and we only
110 need it to look them up on unload, if we rebuild them. */
111 new = xmalloc (sizeof (struct load_list));
112 new->name = xstrdup (ldname);
114 new->next = loaded_syms;
122 load_file (const floc *flocp, const char **ldname, int noerror)
124 int nmlen = strlen (*ldname);
125 char *new = alloca (nmlen + CSTRLEN (SYMBOL_EXTENSION) + 1);
126 char *symname = NULL;
132 /* Break the input into an object file name and a symbol name. If no symbol
133 name was provided, compute one from the object file name. */
134 fp = strchr (*ldname, '(');
139 /* There's an open paren, so see if there's a close paren: if so use
140 that as the symbol name. We can't have whitespace: it would have
141 been chopped up before this function is called. */
142 ep = strchr (fp+1, ')');
143 if (ep && ep[1] == '\0')
145 int l = fp - *ldname;;
149 OS (fatal, flocp, _("Empty symbol name for load: %s"), *ldname);
151 /* Make a copy of the ldname part. */
152 memcpy (new, *ldname, l);
157 /* Make a copy of the symbol name part. */
158 symname = new + l + 1;
159 memcpy (symname, fp, ep - fp);
160 symname[ep - fp] = '\0';
164 /* Add this name to the string cache so it can be reused later. */
165 *ldname = strcache_add (*ldname);
167 /* If this object has been loaded, we're done. */
168 loaded = allocated_variable_expand ("$(.LOADED)");
169 fp = strstr (loaded, *ldname);
170 r = fp && (fp==loaded || fp[-1]==' ') && (fp[nmlen]=='\0' || fp[nmlen]==' ');
174 /* If we didn't find a symbol name yet, construct it from the ldname. */
179 fp = strrchr (*ldname, '/');
180 #ifdef HAVE_DOS_PATHS
183 const char *fp2 = strchr (fp, '\\');
189 fp = strrchr (*ldname, '\\');
190 /* The (improbable) case of d:foo. */
191 if (fp && *fp && fp[1] == ':')
198 while (isalnum (*fp) || *fp == '_')
200 strcpy (p, SYMBOL_EXTENSION);
204 DB (DB_VERBOSE, (_("Loading symbol %s from %s\n"), symname, *ldname));
207 symp = load_object (flocp, noerror, *ldname, symname);
211 /* Invoke the symbol. */
214 /* If it succeeded, add the load file to the loaded variable. */
217 size_t loadlen = strlen (loaded);
218 char *newval = alloca (loadlen + strlen (*ldname) + 2);
219 /* Don't add a space if it's empty. */
222 memcpy (newval, loaded, loadlen);
223 newval[loadlen++] = ' ';
225 strcpy (&newval[loadlen], *ldname);
226 do_variable_definition (flocp, ".LOADED", newval, o_default, f_simple, 0);
235 unload_file (const char *name)
239 for (d = loaded_syms; d != NULL; d = d->next)
240 if (streq (d->name, name) && d->dlp)
242 if (dlclose (d->dlp))
243 perror_with_name ("dlclose", d->name);
252 load_file (const floc *flocp, const char **ldname UNUSED, int noerror)
256 _("The 'load' operation is not supported on this platform."));
262 unload_file (const char *name UNUSED)
264 O (fatal, NILF, "INTERNAL: Cannot unload when load is not supported!");
267 #endif /* MAKE_LOAD */