error (EXIT_FAILURE, errno, _("Reopening shared object `%s' failed"));
error (EXIT_FAILURE, errno, _("Reopening shared object `%s' failed"), map->l_name);
load_shobj (const char *name){  struct link_map *map = NULL;  struct shobj *result;  ElfW(Addr) mapstart = ~((ElfW(Addr)) 0);  ElfW(Addr) mapend = 0;  const ElfW(Phdr) *ph;  size_t textsize;  unsigned int log_hashfraction;  ElfW(Ehdr) *ehdr;  int fd;  ElfW(Shdr) *shdr;  void *ptr;  size_t pagesize = getpagesize ();  const char *shstrtab;  int idx;  ElfW(Shdr) *symtab_entry;  /* Since we use dlopen() we must be prepared to work around the sometimes     strange lookup rules for the shared objects.  If we have a file foo.so     in the current directory and the user specfies foo.so on the command     line (without specifying a directory) we should load the file in the     current directory even if a normal dlopen() call would read the other     file.  We do this by adding a directory portion to the name.  */  if (strchr (name, '/') == NULL)    {      char *load_name = (char *) alloca (strlen (name) + 3);      stpcpy (stpcpy (load_name, "./"), name);      map = (struct link_map *) dlopen (load_name, RTLD_LAZY);    }  if (map == NULL)    {      map = (struct link_map *) dlopen (name, RTLD_LAZY);      if (map == NULL)	{	  error (0, errno, _("failed to load shared object `%s'"), name);	  return NULL;	}    }  /* Prepare the result.  */  result = (struct shobj *) calloc (1, sizeof (struct shobj));  if (result == NULL)    {      error (0, errno, _("cannot create internal descriptors"));      dlclose (map);      return NULL;    }  result->name = name;  result->map = map;  /* Compute the size of the sections which contain program code.     This must match the code in dl-profile.c (_dl_start_profile).  */  for (ph = map->l_phdr; ph < &map->l_phdr[map->l_phnum]; ++ph)    if (ph->p_type == PT_LOAD && (ph->p_flags & PF_X))      {	ElfW(Addr) start = (ph->p_vaddr & ~(pagesize - 1));	ElfW(Addr) end = ((ph->p_vaddr + ph->p_memsz + pagesize - 1)			  & ~(pagesize - 1));	if (start < mapstart)	  mapstart = start;	if (end > mapend)	  mapend = end;      }  result->lowpc = ROUNDDOWN ((uintptr_t) (mapstart + map->l_addr),			     HISTFRACTION * sizeof (HISTCOUNTER));  result->highpc = ROUNDUP ((uintptr_t) (mapend + map->l_addr),			    HISTFRACTION * sizeof (HISTCOUNTER));  if (do_test)    printf ("load addr: %0#*" PRIxPTR "\n"	    "lower bound PC: %0#*" PRIxPTR "\n"	    "upper bound PC: %0#*" PRIxPTR "\n",	    __ELF_NATIVE_CLASS == 32 ? 10 : 18, map->l_addr,	    __ELF_NATIVE_CLASS == 32 ? 10 : 18, result->lowpc,	    __ELF_NATIVE_CLASS == 32 ? 10 : 18, result->highpc);  textsize = result->highpc - result->lowpc;  result->kcountsize = textsize / HISTFRACTION;  result->hashfraction = HASHFRACTION;  if ((HASHFRACTION & (HASHFRACTION - 1)) == 0)    /* If HASHFRACTION is a power of two, mcount can use shifting       instead of integer division.  Precompute shift amount.  */    log_hashfraction = __builtin_ffs (result->hashfraction				      * sizeof (struct here_fromstruct)) - 1;  else    log_hashfraction = -1;  if (do_test)    printf ("hashfraction = %d\ndivider = %Zu\n",	    result->hashfraction,	    result->hashfraction * sizeof (struct here_fromstruct));  result->tossize = textsize / HASHFRACTION;  result->fromlimit = textsize * ARCDENSITY / 100;  if (result->fromlimit < MINARCS)    result->fromlimit = MINARCS;  if (result->fromlimit > MAXARCS)    result->fromlimit = MAXARCS;  result->fromssize = result->fromlimit * sizeof (struct here_fromstruct);  result->expected_size = (sizeof (struct gmon_hdr)			   + 4 + sizeof (struct gmon_hist_hdr)			   + result->kcountsize			   + 4 + 4			   + (result->fromssize			      * sizeof (struct here_cg_arc_record)));  if (do_test)    printf ("expected size: %Zd\n", result->expected_size);#define SCALE_1_TO_1	0x10000L  if (result->kcountsize < result->highpc - result->lowpc)    {      size_t range = result->highpc - result->lowpc;      size_t quot = range / result->kcountsize;      if (quot >= SCALE_1_TO_1)	result->s_scale = 1;      else if (quot >= SCALE_1_TO_1 / 256)	result->s_scale = SCALE_1_TO_1 / quot;      else if (range > ULONG_MAX / 256)	result->s_scale = ((SCALE_1_TO_1 * 256)			   / (range / (result->kcountsize / 256)));      else	result->s_scale = ((SCALE_1_TO_1 * 256)			   / ((range * 256) / result->kcountsize));    }  else    result->s_scale = SCALE_1_TO_1;  if (do_test)    printf ("s_scale: %d\n", result->s_scale);  /* Determine the dynamic string table.  */  if (map->l_info[DT_STRTAB] == NULL)    result->dynstrtab = NULL;  else    result->dynstrtab = (const char *) (map->l_addr					+ map->l_info[DT_STRTAB]->d_un.d_ptr);  if (do_test)    printf ("string table: %p\n", result->dynstrtab);  /* Determine the soname.  */  if (map->l_info[DT_SONAME] == NULL)    result->soname = NULL;  else    result->soname = result->dynstrtab + map->l_info[DT_SONAME]->d_un.d_val;  if (do_test)    printf ("soname: %s\n", result->soname);  /* Now we have to load the symbol table.     First load the section header table.  */  ehdr = (ElfW(Ehdr) *) map->l_addr;  /* Make sure we are on the right party.  */  if (ehdr->e_shentsize != sizeof (ElfW(Shdr)))    abort ();  /* And we need the shared object file descriptor again.  */  fd = open (map->l_name, O_RDONLY);  if (fd == -1)    /* Dooh, this really shouldn't happen.  We know the file is available.  */    error (EXIT_FAILURE, errno, _("Reopening shared object `%s' failed"));  /* Now map the section header.  */  ptr = mmap (NULL, (ehdr->e_shnum * sizeof (ElfW(Shdr))		     + (ehdr->e_shoff & (pagesize - 1))), PROT_READ,	      MAP_SHARED|MAP_FILE, fd, ehdr->e_shoff & ~(pagesize - 1));  if (ptr == MAP_FAILED)    error (EXIT_FAILURE, errno, _("mapping of section headers failed"));  shdr = (ElfW(Shdr) *) ((char *) ptr + (ehdr->e_shoff & (pagesize - 1)));  /* Get the section header string table.  */  ptr = mmap (NULL, (shdr[ehdr->e_shstrndx].sh_size		     + (shdr[ehdr->e_shstrndx].sh_offset & (pagesize - 1))),	      PROT_READ, MAP_SHARED|MAP_FILE, fd,	      shdr[ehdr->e_shstrndx].sh_offset & ~(pagesize - 1));  if (ptr == MAP_FAILED)    error (EXIT_FAILURE, errno,	   _("mapping of section header string table failed"));  shstrtab = ((const char *) ptr	      + (shdr[ehdr->e_shstrndx].sh_offset & (pagesize - 1)));  /* Search for the ".symtab" section.  */  symtab_entry = NULL;  for (idx = 0; idx < ehdr->e_shnum; ++idx)    if (shdr[idx].sh_type == SHT_SYMTAB	&& strcmp (shstrtab + shdr[idx].sh_name, ".symtab") == 0)      {	symtab_entry = &shdr[idx];	break;      }  /* We don't need the section header string table anymore.  */  munmap (ptr, (shdr[ehdr->e_shstrndx].sh_size		+ (shdr[ehdr->e_shstrndx].sh_offset & (pagesize - 1))));  if (symtab_entry == NULL)    {      fprintf (stderr, _("\*** The file `%s' is stripped: no detailed analysis possible\n"),	      name);      result->symtab = NULL;      result->strtab = NULL;    }  else    {      ElfW(Off) min_offset, max_offset;      ElfW(Shdr) *strtab_entry;      strtab_entry = &shdr[symtab_entry->sh_link];      /* Find the minimum and maximum offsets that include both the symbol	 table and the string table.  */      if (symtab_entry->sh_offset < strtab_entry->sh_offset)	{	  min_offset = symtab_entry->sh_offset & ~(pagesize - 1);	  max_offset = strtab_entry->sh_offset + strtab_entry->sh_size;	}      else	{	  min_offset = strtab_entry->sh_offset & ~(pagesize - 1);	  max_offset = symtab_entry->sh_offset + symtab_entry->sh_size;	}      result->symbol_map = mmap (NULL, max_offset - min_offset,				 PROT_READ, MAP_SHARED|MAP_FILE, fd,				 min_offset);      if (result->symbol_map == NULL)	error (EXIT_FAILURE, errno, _("failed to load symbol data"));      result->symtab	= (const ElfW(Sym) *) ((const char *) result->symbol_map			       + (symtab_entry->sh_offset - min_offset));      result->symtab_size = symtab_entry->sh_size;      result->strtab = ((const char *) result->symbol_map			+ (strtab_entry->sh_offset - min_offset));      result->symbol_mapsize = max_offset - min_offset;    }  /* Now we also don't need the section header table anymore.  */  munmap ((char *) shdr - (ehdr->e_shoff & (pagesize - 1)),	  (ehdr->e_phnum * sizeof (ElfW(Shdr))	   + (ehdr->e_shoff & (pagesize - 1))));  /* Free the descriptor for the shared object.  */  close (fd);  return result;}