ElfW(Addr) retaddr, const void *regs, long int *framesizep)
ElfW(Addr) retaddr, void *regs, long int *framesizep)
_dl_profile_fixup (#ifdef ELF_MACHINE_RUNTIME_FIXUP_ARGS		   ELF_MACHINE_RUNTIME_FIXUP_ARGS,#endif		   struct link_map *l, ElfW(Word) reloc_offset,		   ElfW(Addr) retaddr, const void *regs, long int *framesizep){  void (*mcount_fct) (ElfW(Addr), ElfW(Addr)) = INTUSE(_dl_mcount);  /* This is the address in the array where we store the result of previous     relocations.  */  struct reloc_result *reloc_result    = &l->l_reloc_result[reloc_offset / sizeof (PLTREL)];  ElfW(Addr) *resultp = &reloc_result->addr;  ElfW(Addr) value = *resultp;  if (value == 0)    {      /* This is the first time we have to relocate this object.  */      const ElfW(Sym) *const symtab	= (const void *) D_PTR (l, l_info[DT_SYMTAB]);      const char *strtab = (const char *) D_PTR (l, l_info[DT_STRTAB]);      const PLTREL *const reloc	= (const void *) (D_PTR (l, l_info[DT_JMPREL]) + reloc_offset);      const ElfW(Sym) *refsym = &symtab[ELFW(R_SYM) (reloc->r_info)];      const ElfW(Sym) *defsym = refsym;      lookup_t result;      /* Sanity check that we're really looking at a PLT relocation.  */      assert (ELFW(R_TYPE)(reloc->r_info) == ELF_MACHINE_JMP_SLOT);      /* Look up the target symbol.  If the symbol is marked STV_PROTECTED	 don't look in the global scope.  */      if (__builtin_expect (ELFW(ST_VISIBILITY) (refsym->st_other), 0) == 0)	{	  const struct r_found_version *version = NULL;	  if (l->l_info[VERSYMIDX (DT_VERSYM)] != NULL)	    {	      const ElfW(Half) *vernum =		(const void *) D_PTR (l, l_info[VERSYMIDX (DT_VERSYM)]);	      ElfW(Half) ndx = vernum[ELFW(R_SYM) (reloc->r_info)] & 0x7fff;	      version = &l->l_versions[ndx];	      if (version->hash == 0)		version = NULL;	    }	  result = _dl_lookup_symbol_x (strtab + refsym->st_name, l, &defsym,					l->l_scope, version,					ELF_RTYPE_CLASS_PLT,					DL_LOOKUP_ADD_DEPENDENCY, NULL);	  /* Currently result contains the base load address (or link map)	     of the object that defines sym.  Now add in the symbol	     offset.  */	  value = (defsym != NULL		   ? LOOKUP_VALUE_ADDRESS (result) + defsym->st_value : 0);	}      else	{	  /* We already found the symbol.  The module (and therefore its load	     address) is also known.  */	  value = l->l_addr + refsym->st_value;	  result = l;	}      /* And now perhaps the relocation addend.  */      value = elf_machine_plt_value (l, reloc, value);#ifdef SHARED      /* Auditing checkpoint: we have a new binding.  Provide the	 auditing libraries the possibility to change the value and	 tell us whether further auditing is wanted.  */      if (defsym != NULL && GLRO(dl_naudit) > 0)	{	  reloc_result->bound = result;	  /* Compute index of the symbol entry in the symbol table of	     the DSO with the definition.  */	  reloc_result->boundndx = (defsym				    - (ElfW(Sym) *) D_PTR (result,							   l_info[DT_SYMTAB]));	  /* Determine whether any of the two participating DSOs is	     interested in auditing.  */	  if ((l->l_audit_any_plt | result->l_audit_any_plt) != 0)	    {	      unsigned int altvalue = 0;	      struct audit_ifaces *afct = GLRO(dl_audit);	      /* Synthesize a symbol record where the st_value field is		 the result.  */	      ElfW(Sym) sym = *defsym;	      sym.st_value = value;	      /* Keep track whether there is any interest in tracing		 the call in the lower two bits.  */	      assert (DL_NNS * 2 <= sizeof (reloc_result->flags) * 8);	      assert ((LA_SYMB_NOPLTENTER | LA_SYMB_NOPLTEXIT) == 3);	      reloc_result->enterexit = LA_SYMB_NOPLTENTER | LA_SYMB_NOPLTEXIT;	      const char *strtab2 = (const void *) D_PTR (result,							  l_info[DT_STRTAB]);	      for (unsigned int cnt = 0; cnt < GLRO(dl_naudit); ++cnt)		{		  /* XXX Check whether both DSOs must request action or		     only one */		  if ((l->l_audit[cnt].bindflags & LA_FLG_BINDFROM) != 0		      && (result->l_audit[cnt].bindflags & LA_FLG_BINDTO) != 0)		    {		      unsigned int flags = altvalue;		      if (afct->symbind != NULL)			{			  uintptr_t new_value			    = afct->symbind (&sym, reloc_result->boundndx,					     &l->l_audit[cnt].cookie,					     &result->l_audit[cnt].cookie,					     &flags,					     strtab2 + defsym->st_name);			  if (new_value != (uintptr_t) sym.st_value)			    {			      altvalue = LA_SYMB_ALTVALUE;			      sym.st_value = new_value;			    }			}		      /* Remember the results for every audit library and			 store a summary in the first two bits.  */		      reloc_result->enterexit			&= flags & (LA_SYMB_NOPLTENTER | LA_SYMB_NOPLTEXIT);		      reloc_result->enterexit			|= ((flags & (LA_SYMB_NOPLTENTER | LA_SYMB_NOPLTEXIT))			    << ((cnt + 1) * 2));		    }		  else		    /* If the bind flags say this auditor is not interested,		       set the bits manually.  */		    reloc_result->enterexit		      |= ((LA_SYMB_NOPLTENTER | LA_SYMB_NOPLTEXIT)			  << ((cnt + 1) * 2));		  afct = afct->next;		}	      reloc_result->flags = altvalue;	      value = sym.st_value;	    }	  else	    /* Set all bits since this symbol binding is not interesting.  */	    reloc_result->enterexit = (1u << DL_NNS) - 1;	}#endif      /* Store the result for later runs.  */      if (__builtin_expect (! GLRO(dl_bind_not), 1))	*resultp = value;    }  /* By default we do not call the pltexit function.  */  long int framesize = -1;#ifdef SHARED  /* Auditing checkpoint: report the PLT entering and allow the     auditors to change the value.  */  if (value != 0 && GLRO(dl_naudit) > 0      /* Don't do anything if no auditor wants to intercept this call.  */      && (reloc_result->enterexit & LA_SYMB_NOPLTENTER) == 0)    {      ElfW(Sym) *defsym = ((ElfW(Sym) *) D_PTR (reloc_result->bound,						l_info[DT_SYMTAB])			   + reloc_result->boundndx);      /* Set up the sym parameter.  */      ElfW(Sym) sym = *defsym;      sym.st_value = value;      /* Get the symbol name.  */      const char *strtab = (const void *) D_PTR (reloc_result->bound,						 l_info[DT_STRTAB]);      const char *symname = strtab + sym.st_name;      /* Keep track of overwritten addresses.  */      unsigned int altvalue = reloc_result->flags;      struct audit_ifaces *afct = GLRO(dl_audit);      for (unsigned int cnt = 0; cnt < GLRO(dl_naudit); ++cnt)	{ 	  if (afct->ARCH_LA_PLTENTER != NULL	      && (reloc_result->enterexit		  & (LA_SYMB_NOPLTENTER << (2 * (cnt + 1)))) == 0)	    {	      unsigned int flags = altvalue;	      long int new_framesize = -1;	      uintptr_t new_value		= afct->ARCH_LA_PLTENTER (&sym, reloc_result->boundndx,					  &l->l_audit[cnt].cookie,					  &reloc_result->bound->l_audit[cnt].cookie,					  regs, &flags, symname,					  &new_framesize);	      if (new_value != (uintptr_t) sym.st_value)		{		  altvalue = LA_SYMB_ALTVALUE;		  sym.st_value = new_value;		}	      /* Remember the results for every audit library and		 store a summary in the first two bits.  */	      reloc_result->enterexit		|= ((flags & (LA_SYMB_NOPLTENTER | LA_SYMB_NOPLTEXIT))		    << (2 * (cnt + 1)));	      if ((reloc_result->enterexit & (LA_SYMB_NOPLTEXIT					      << (2 * (cnt + 1))))		  == 0 && new_framesize != -1 && framesize != -2)		{		  /* If this is the first call providing information,		     use it.  */		  if (framesize == -1)		    framesize = new_framesize;		  /* If two pltenter calls provide conflicting information,		     use the larger value.  */		  else if (new_framesize != framesize)		    framesize = MAX (new_framesize, framesize);		}	    }	  afct = afct->next;	}      value = sym.st_value;    }#endif  /* Store the frame size information.  */  *framesizep = framesize;  (*mcount_fct) (retaddr, value);  return value;}