if (__builtin_expect (_dl_debug_mask & DL_DEBUG_RELOC, 0))
if (__builtin_expect (GL(dl_debug_mask) & DL_DEBUG_RELOC, 0))
_dl_relocate_object (struct link_map *l, struct r_scope_elem *scope[],		     int lazy, int consider_profiling){  struct textrels  {    caddr_t start;    size_t len;    int prot;    struct textrels *next;  } *textrels = NULL;  /* Initialize it to make the compiler happy.  */  const char *errstring = NULL;  if (l->l_relocated)    return;  /* If DT_BIND_NOW is set relocate all references in this object.  We     do not do this if we are profiling, of course.  */  if (!consider_profiling      && __builtin_expect (l->l_info[DT_BIND_NOW] != NULL, 0))    lazy = 0;  if (__builtin_expect (_dl_debug_mask & DL_DEBUG_RELOC, 0))    _dl_printf ("\nrelocation processing: %s%s\n",		l->l_name[0] ? l->l_name : _dl_argv[0], lazy ? " (lazy)" : "");  /* DT_TEXTREL is now in level 2 and might phase out at some time.     But we rewrite the DT_FLAGS entry to a DT_TEXTREL entry to make     testing easier and therefore it will be available at all time.  */  if (__builtin_expect (l->l_info[DT_TEXTREL] != NULL, 0))    {      /* Bletch.  We must make read-only segments writable	 long enough to relocate them.  */      const ElfW(Phdr) *ph;      for (ph = l->l_phdr; ph < &l->l_phdr[l->l_phnum]; ++ph)	if (ph->p_type == PT_LOAD && (ph->p_flags & PF_W) == 0)	  {	    struct textrels *newp;	    newp = (struct textrels *) alloca (sizeof (*newp));	    newp->len = (((ph->p_vaddr + ph->p_memsz + _dl_pagesize - 1)			  & ~(_dl_pagesize - 1))			 - (ph->p_vaddr & ~(_dl_pagesize - 1)));	    newp->start = ((ph->p_vaddr & ~(_dl_pagesize - 1))			   + (caddr_t) l->l_addr);	    if (__mprotect (newp->start, newp->len, PROT_READ|PROT_WRITE) < 0)	      {		errstring = N_("cannot make segment writable for relocation");	      call_error:		_dl_signal_error (errno, l->l_name, NULL, errstring);	      }#if (PF_R | PF_W | PF_X) == 7 && (PROT_READ | PROT_WRITE | PROT_EXEC) == 7	    newp->prot = (PF_TO_PROT			  >> ((ph->p_flags & (PF_R | PF_W | PF_X)) * 4)) & 0xf;#else	    newp->prot = 0;	    if (ph->p_flags & PF_R)	      newp->prot |= PROT_READ;	    if (ph->p_flags & PF_W)	      newp->prot |= PROT_WRITE;	    if (ph->p_flags & PF_X)	      newp->prot |= PROT_EXEC;#endif	    newp->next = textrels;	    textrels = newp;	  }    }  {    /* Do the actual relocation of the object's GOT and other data.  */    /* String table object symbols.  */    const char *strtab = (const void *) D_PTR (l, l_info[DT_STRTAB]);    /* This macro is used as a callback from the ELF_DYNAMIC_RELOCATE code.  */#define RESOLVE_MAP(ref, version, r_type) \    (ELFW(ST_BIND) ((*ref)->st_info) != STB_LOCAL			      \     ? ((__builtin_expect ((*ref) == l->l_lookup_cache.sym, 0)		      \	 && elf_machine_type_class (r_type) == l->l_lookup_cache.type_class)  \	? (bump_num_cache_relocations (),				      \	   (*ref) = l->l_lookup_cache.ret,				      \	   l->l_lookup_cache.value)					      \	: ({ lookup_t _lr;						      \	     int _tc = elf_machine_type_class (r_type);			      \	     l->l_lookup_cache.type_class = _tc;			      \	     l->l_lookup_cache.sym = (*ref);				      \	     _lr = ((version) != NULL && (version)->hash != 0		      \		    ? _dl_lookup_versioned_symbol (strtab + (*ref)->st_name,  \						   l, (ref), scope,	      \						   (version), _tc, 0)	      \		    : _dl_lookup_symbol (strtab + (*ref)->st_name, l, (ref),  \					 scope, _tc, 0));		      \	     l->l_lookup_cache.ret = (*ref);				      \	     l->l_lookup_cache.value = _lr; }))				      \     : l)#define RESOLVE(ref, version, r_type) \    (ELFW(ST_BIND) ((*ref)->st_info) != STB_LOCAL			      \     ? ((__builtin_expect ((*ref) == l->l_lookup_cache.sym, 0)		      \	 && elf_machine_type_class (r_type) == l->l_lookup_cache.type_class)  \		? (bump_num_cache_relocations (),				      \	   (*ref) = l->l_lookup_cache.ret,				      \	   l->l_lookup_cache.value)					      \	: ({ lookup_t _lr;						      \	     int _tc = elf_machine_type_class (r_type);			      \	     l->l_lookup_cache.type_class = _tc;			      \	     l->l_lookup_cache.sym = (*ref);				      \	     _lr = ((version) != NULL && (version)->hash != 0		      \		    ? _dl_lookup_versioned_symbol (strtab + (*ref)->st_name,  \						   l, (ref), scope,	      \						   (version), _tc, 0)	      \		    : _dl_lookup_symbol (strtab + (*ref)->st_name, l, (ref),  \					 scope, _tc, 0));		      \	     l->l_lookup_cache.ret = (*ref);				      \	     l->l_lookup_cache.value = _lr; }))				      \     : l->l_addr)#include "dynamic-link.h"    ELF_DYNAMIC_RELOCATE (l, lazy, consider_profiling);    if (__builtin_expect (consider_profiling, 0))      {	/* Allocate the array which will contain the already found	   relocations.  If the shared object lacks a PLT (for example	   if it only contains lead function) the l_info[DT_PLTRELSZ]	   will be NULL.  */	if (l->l_info[DT_PLTRELSZ] == NULL)	  {	    errstring = N_("%s: profiler found no PLTREL in object %s\n");	  fatal:	    _dl_fatal_printf (errstring,			      _dl_argv[0] ?: "<program name unknown>",			      l->l_name);	  }	l->l_reloc_result =	  (ElfW(Addr) *) calloc (sizeof (ElfW(Addr)),				 l->l_info[DT_PLTRELSZ]->d_un.d_val);	if (l->l_reloc_result == NULL)	  {	    errstring = N_("\%s: profiler out of memory shadowing PLTREL of %s\n");	    goto fatal;	  }      }  }  /* Mark the object so we know this work has been done.  */  l->l_relocated = 1;  /* Undo the segment protection changes.  */  while (__builtin_expect (textrels != NULL, 0))    {      if (__mprotect (textrels->start, textrels->len, textrels->prot) < 0)	{	  errstring = N_("cannot restore segment prot after reloc");	  goto call_error;	}      textrels = textrels->next;    }}