1 /* Loading dynamic objects for GNU Make.
2 Copyright (C) 2012 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 "_gmake_setup"
29 static void *global_dl
= NULL
;
36 init_symbol (const struct floc
*flocp
, const char *ldname
, load_func_t symp
)
40 int nmlen
= strlen (ldname
);
41 char *loaded
= allocated_variable_expand("$(.LOADED)");
43 /* If it's already been loaded don't do it again. */
44 p
= strstr (loaded
, ldname
);
45 r
= p
&& (p
==loaded
|| p
[-1]==' ') && (p
[nmlen
]=='\0' || p
[nmlen
]==' ');
50 /* Now invoke the symbol. */
53 /* If it succeeded, add the symbol to the loaded variable. */
55 do_variable_definition (flocp
, ".LOADED", ldname
, o_default
, f_append
, 0);
61 load_file (const struct floc
*flocp
, const char *ldname
, int noerror
)
66 char *new = alloca (strlen (ldname
) + CSTRLEN (SYMBOL_EXTENSION
) + 1);
70 global_dl
= dlopen (NULL
, RTLD_NOW
|RTLD_GLOBAL
);
72 fatal (flocp
, _("Failed to open global symbol table: %s"), dlerror());
75 /* If a symbol name was provided, use it. */
76 fp
= strchr (ldname
, '(');
81 /* If there's an open paren, see if there's a close paren: if so use
82 that as the symbol name. We can't have whitespace: it would have
83 been chopped up before this function is called. */
84 ep
= strchr (fp
+1, ')');
85 if (ep
&& ep
[1] == '\0')
91 fatal (flocp
, _("Empty symbol name for load: %s"), ldname
);
93 /* Make a copy of the ldname part. */
94 memcpy (new, ldname
, l
);
98 /* Make a copy of the symbol name part. */
99 symname
= new + l
+ 1;
100 memcpy (symname
, fp
, ep
- fp
);
101 symname
[ep
- fp
] = '\0';
105 /* If we didn't find a symbol name yet, construct it from the ldname. */
110 fp
= strrchr (ldname
, '/');
115 while (isalnum (*fp
) || *fp
== '_')
117 strcpy (p
, SYMBOL_EXTENSION
);
121 DB (DB_VERBOSE
, (_("Loading symbol %s from %s\n"), symname
, ldname
));
123 /* See if it's already defined. */
124 symp
= (load_func_t
) dlsym (global_dl
, symname
);
126 void *dlp
= dlopen (ldname
, RTLD_LAZY
|RTLD_GLOBAL
);
130 DB (DB_BASIC
, ("%s", dlerror()));
132 error (flocp
, "%s", dlerror());
136 symp
= dlsym (dlp
, symname
);
138 fatal (flocp
, _("Failed to load symbol %s from %s: %s"),
139 symname
, ldname
, dlerror());
142 /* Invoke the symbol to initialize the loaded object. */
143 return init_symbol(flocp
, ldname
, symp
);
149 load_file (const struct floc
*flocp
, const char *ldname
, int noerror
)
152 fatal (flocp
, _("The 'load' operation is not supported on this platform."));
157 #endif /* MAKE_LOAD */