This is the mail archive of the
gcc@gcc.gnu.org
mailing list for the GCC project.
Re: Shared library annoyance with gcc-3_0-branch
On 20-Feb-2001, Andreas Schwab <schwab@suse.de> wrote:
>
> Not even that. Only one copy of the code must be _active_ during
> runtime. There can well be multiple copies, as long as the other copies
> are never called. That's because every copy of the code would use its own
> private list of unwind info, and none of them whould have the whole list
> (look for `static struct object *objects' in frame-dwarf2.c).
Hmm... this is such an ugly hack, I feel embarrassed to say it...
but how about using putenv() to communicate the address of the
static data between the different copies? Would that work?
I have in mind something along the lines of the following
#define MAGIC_NUMBER 0xCC31D
struct static_data {
unsigned long magic_number;
struct static_data *self_pointer;
static struct object *objects;
};
/* Check to see if the static data has already been allocated,
If so, return non-zero and set *SD to point to it.
We do this by checking if the environment variable
__LIBGCC_pid__ matches our process id, and the environment
variable __LIBGCC_addr__ is set. If so, it must have been
set by an invocation of another copy of this function which
has somehow been linked into the executable (or at least so
we assume). For security we do a little bit of sanity checking. */
int
get_static_data_from_env (sd)
struct static_data **sd;
{
char *pid_string;
char *addr_string;
void *addr;
pid_string = getenv ("__LIBGCC_pid__");
if (!pid_string || atol(pid_string) != getpid())
return 0;
addr_string = getenv ("__LIBGCC_addr__");
if (!addr_string || sscanf(addr_string, "%p", &addr) != 1)
return 0;
*sd = (struct static_data *) addr;
if (sd->magic_number != MAGIC_NUMBER
|| sd->self_pointer != sd)
/* __LIBGCC_addr__ must have been invalid. */
abort();
return 1;
}
/* Check to see if the static data has already been allocated,
If so, return non-zero and set *SD to point to it.
If not, allocate it, and set the environment variables
appropriately so that any other allocations from this
process will use the data we've allocated rather than
allocating it again. */
struct static_data *
get_static_data ()
{
struct static_data *sd;
if (!get_static_data_from_env (&sd))
{
static char env1[40], env2[40];
sd = (struct static_data *) malloc (sizeof struct static_data);
sd->magic_number = MAGIC_NUMBER;
sd->self_pointer = sd;
sprintf(env1, "__LIBGCC_pid__=%ld\n", (long) getpid());
sprintf(env2, "__LIBGCC_addr__=%p\n", (void *) *sd);
if (putenv(env2) == 0)
(void) putenv(env1);
}
return sd;
}
Is this a good idea, or just the product of too many late nights
(and a sick and twisted mind ;-) ?
--
Fergus Henderson <fjh@cs.mu.oz.au> | "I have always known that the pursuit
| of excellence is a lethal habit"
WWW: <http://www.cs.mu.oz.au/~fjh> | -- the last words of T. S. Garp.