This is the mail archive of the gcc@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]

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.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]