for (l = GL(dl_loaded); l; l = l->l_next) { ElfW(Addr) mapstart, mapend; mapstart = l->l_map_start & ~(GLRO(dl_pagesize) - 1); mapend = l->l_map_end | (GLRO(dl_pagesize) - 1); assert (mapend > mapstart);
for (nsid = 0; nsid < DL_NNS; ++nsid) for (l = GL(dl_ns)[nsid]._ns_loaded; l; l = l->l_next) { ElfW(Addr) mapstart, mapend; mapstart = l->l_map_start & ~(GLRO(dl_pagesize) - 1); mapend = l->l_map_end | (GLRO(dl_pagesize) - 1); assert (mapend > mapstart);
weak_extern (__cache_line_size)/* Because ld.so is now versioned, these functions can be in their own file;   no relocations need to be done to call them.   Of course, if ld.so is not versioned...  */#if defined SHARED && !(DO_VERSIONING - 0)#error This will not work with versioning turned off, sorry.#endif/* Stuff for the PLT.  */#define PLT_INITIAL_ENTRY_WORDS 18#define PLT_LONGBRANCH_ENTRY_WORDS 0#define PLT_TRAMPOLINE_ENTRY_WORDS 6#define PLT_DOUBLE_SIZE (1<<13)#define PLT_ENTRY_START_WORDS(entry_number) \  (PLT_INITIAL_ENTRY_WORDS + (entry_number)*2				\   + ((entry_number) > PLT_DOUBLE_SIZE					\      ? ((entry_number) - PLT_DOUBLE_SIZE)*2				\      : 0))#define PLT_DATA_START_WORDS(num_entries) PLT_ENTRY_START_WORDS(num_entries)/* Macros to build PowerPC opcode words.  */#define OPCODE_ADDI(rd,ra,simm) \  (0x38000000 | (rd) << 21 | (ra) << 16 | ((simm) & 0xffff))#define OPCODE_ADDIS(rd,ra,simm) \  (0x3c000000 | (rd) << 21 | (ra) << 16 | ((simm) & 0xffff))#define OPCODE_ADD(rd,ra,rb) \  (0x7c000214 | (rd) << 21 | (ra) << 16 | (rb) << 11)#define OPCODE_B(target) (0x48000000 | ((target) & 0x03fffffc))#define OPCODE_BA(target) (0x48000002 | ((target) & 0x03fffffc))#define OPCODE_BCTR() 0x4e800420#define OPCODE_LWZ(rd,d,ra) \  (0x80000000 | (rd) << 21 | (ra) << 16 | ((d) & 0xffff))#define OPCODE_LWZU(rd,d,ra) \  (0x84000000 | (rd) << 21 | (ra) << 16 | ((d) & 0xffff))#define OPCODE_MTCTR(rd) (0x7C0903A6 | (rd) << 21)#define OPCODE_RLWINM(ra,rs,sh,mb,me) \  (0x54000000 | (rs) << 21 | (ra) << 16 | (sh) << 11 | (mb) << 6 | (me) << 1)#define OPCODE_LI(rd,simm)    OPCODE_ADDI(rd,0,simm)#define OPCODE_ADDIS_HI(rd,ra,value) \  OPCODE_ADDIS(rd,ra,((value) + 0x8000) >> 16)#define OPCODE_LIS_HI(rd,value) OPCODE_ADDIS_HI(rd,0,value)#define OPCODE_SLWI(ra,rs,sh) OPCODE_RLWINM(ra,rs,sh,0,31-sh)#define PPC_DCBST(where) asm volatile ("dcbst 0,%0" : : "r"(where) : "memory")#define PPC_SYNC asm volatile ("sync" : : : "memory")#define PPC_ISYNC asm volatile ("sync; isync" : : : "memory")#define PPC_ICBI(where) asm volatile ("icbi 0,%0" : : "r"(where) : "memory")#define PPC_DIE asm volatile ("tweq 0,0")/* Use this when you've modified some code, but it won't be in the   instruction fetch queue (or when it doesn't matter if it is). */#define MODIFIED_CODE_NOQUEUE(where) \     do { PPC_DCBST(where); PPC_SYNC; PPC_ICBI(where); } while (0)/* Use this when it might be in the instruction queue. */#define MODIFIED_CODE(where) \     do { PPC_DCBST(where); PPC_SYNC; PPC_ICBI(where); PPC_ISYNC; } while (0)/* The idea here is that to conform to the ABI, we are supposed to try   to load dynamic objects between 0x10000 (we actually use 0x40000 as   the lower bound, to increase the chance of a memory reference from   a null pointer giving a segfault) and the program's load address;   this may allow us to use a branch instruction in the PLT rather   than a computed jump.  The address is only used as a preference for   mmap, so if we get it wrong the worst that happens is that it gets   mapped somewhere else.  */ElfW(Addr)__elf_preferred_address(struct link_map *loader, size_t maplength,			ElfW(Addr) mapstartpref){  ElfW(Addr) low, high;  struct link_map *l;  /* If the object has a preference, load it there!  */  if (mapstartpref != 0)    return mapstartpref;  /* Otherwise, quickly look for a suitable gap between 0x3FFFF and     0x70000000.  0x3FFFF is so that references off NULL pointers will     cause a segfault, 0x70000000 is just paranoia (it should always     be superceded by the program's load address).  */  low =  0x0003FFFF;  high = 0x70000000;  for (l = GL(dl_loaded); l; l = l->l_next)    {      ElfW(Addr) mapstart, mapend;      mapstart = l->l_map_start & ~(GLRO(dl_pagesize) - 1);      mapend = l->l_map_end | (GLRO(dl_pagesize) - 1);      assert (mapend > mapstart);      /* Prefer gaps below the main executable, note that l ==	 _dl_loaded does not work for static binaries loading	 e.g. libnss_*.so.  */      if ((mapend >= high || l->l_type == lt_executable)	  && high >= mapstart)	high = mapstart;      else if (mapend >= low && low >= mapstart)	low = mapend;      else if (high >= mapend && mapstart >= low)	{	  if (high - mapend >= mapstart - low)	    low = mapend;	  else	    high = mapstart;	}    }  high -= 0x10000; /* Allow some room between objects.  */  maplength = (maplength | (GLRO(dl_pagesize) - 1)) + 1;  if (high <= low || high - low < maplength )    return 0;  return high - maplength;  /* Both high and maplength are page-aligned.  */}