Ejemplo n.º 1
0
BOOL DLSYM_canonical_lookup(DLOAD_HANDLE handle, int sym_index, 
                            DLIMP_Dynamic_Module *dyn_module, 
                            Elf32_Addr *sym_value)
{
   /*------------------------------------------------------------------------*/
   /* Lookup the symbol table to get the symbol characteristics.             */
   /*------------------------------------------------------------------------*/
   struct Elf32_Sym *sym = &dyn_module->symtab[sym_index];
   int32_t           st_bind = ELF32_ST_BIND(sym->st_info);
   int32_t           st_vis  = ELF32_ST_VISIBILITY(sym->st_other);
   BOOL              is_def  = (sym->st_shndx != SHN_UNDEF && 
                               (sym->st_shndx < SHN_LORESERVE || 
                                sym->st_shndx == SHN_ABS || 
                                sym->st_shndx == SHN_COMMON || 
                                sym->st_shndx == SHN_XINDEX));
   const char *sym_name = (char *)sym->st_name; 

#if LOADER_DEBUG
   if (debugging_on)
      DLIF_trace("DLSYM_canonical_lookup: %d, %s\n", sym_index, sym_name);
#endif

   /*------------------------------------------------------------------------*/
   /* Local symbols and symbol definitions that cannot be pre-empted         */
   /* are resolved by the definition in the same module.                     */
   /*------------------------------------------------------------------------*/
   if (st_bind == STB_LOCAL || st_vis != STV_DEFAULT)
   {
      /*---------------------------------------------------------------------*/
      /* If it is a local symbol or non-local that cannot be preempted,      */
      /* the definition should be found in the same module. If we don't      */
      /* find the definition it is an error.                                 */
      /*---------------------------------------------------------------------*/
      if (!is_def)
      {
         DLIF_error(DLET_SYMBOL, 
                    "Local/non-imported symbol %s definition is not found "
                    "in module %s!\n", sym_name, dyn_module->name);
         return FALSE;
      }
      else
      {
         if (sym_value) *sym_value = sym->st_value;
         return TRUE; 
      }
   }
   /*------------------------------------------------------------------------*/
   /* Else we have either pre-emptable defintion or undef symbol. We need    */
   /* to do global look up.                                                  */
   /*------------------------------------------------------------------------*/
   else 
   {
      return DLSYM_global_lookup(handle, sym_name, dyn_module->loaded_module, 
                                 sym_value);
   }
}
Ejemplo n.º 2
0
static const char *get_st_visibility(unsigned char val)
{
	static const char *const visibilities[] = {
		"DEFAULT",
		"INTERNAL",
		"HIDDEN",
		"PROTECTED"
	};
	return visibilities[ELF32_ST_VISIBILITY(val)];
}
Ejemplo n.º 3
0
static int
do_test (void)
{
  void *handle = dlopen ("modstatic2-nonexistent.so", RTLD_LAZY);
  if (handle == NULL)
    printf ("nonexistent: %s\n", dlerror ());
  else
    exit (1);

  handle = dlopen ("modstatic2.so", RTLD_LAZY);
  if (handle == NULL)
    {
      printf ("%s\n", dlerror ());
      exit (1);
    }

  int (*test) (FILE *, int);
  test = dlsym (handle, "test");
  if (test == NULL)
    {
      printf ("%s\n", dlerror ());
      exit (1);
    }

  Dl_info info;
  int res = dladdr (test, &info);
  if (res == 0)
    {
      puts ("dladdr returned 0");
      exit (1);
    }
  else
    {
      if (strstr (info.dli_fname, "modstatic2.so") == NULL
	  || strcmp (info.dli_sname, "test") != 0)
	{
	  printf ("fname %s sname %s\n", info.dli_fname, info.dli_sname);
	  exit (1);
	}
      if (info.dli_saddr != (void *) test)
	{
	  printf ("saddr %p != test %p\n", info.dli_saddr, test);
	  exit (1);
	}
    }

  ElfW(Sym) *sym;
  void *symp;
  res = dladdr1 (test, &info, &symp, RTLD_DL_SYMENT);
  if (res == 0)
    {
      puts ("dladdr1 returned 0");
      exit (1);
    }
  else
    {
      if (strstr (info.dli_fname, "modstatic2.so") == NULL
	  || strcmp (info.dli_sname, "test") != 0)
	{
	  printf ("fname %s sname %s\n", info.dli_fname, info.dli_sname);
	  exit (1);
	}
      if (info.dli_saddr != (void *) test)
	{
	  printf ("saddr %p != test %p\n", info.dli_saddr, test);
	  exit (1);
	}
      sym = symp;
      if (sym == NULL)
	{
	  puts ("sym == NULL\n");
	  exit (1);
	}
      if (ELF32_ST_BIND (sym->st_info) != STB_GLOBAL
	  || ELF32_ST_VISIBILITY (sym->st_other) != STV_DEFAULT)
	{
	  printf ("bind %d visibility %d\n",
		  (int) ELF32_ST_BIND (sym->st_info),
		  (int) ELF32_ST_VISIBILITY (sym->st_other));
	  exit (1);
	}
    }

  Lmid_t lmid;
  res = dlinfo (handle, RTLD_DI_LMID, &lmid);
  if (res != 0)
    {
      printf ("dlinfo returned %d %s\n", res, dlerror ());
      exit (1);
    }
  else if (lmid != LM_ID_BASE)
    {
      printf ("lmid %d != %d\n", (int) lmid, (int) LM_ID_BASE);
      exit (1);
    }

  res = test (stdout, 2);
  if (res != 4)
    {
      printf ("Got %i, expected 4\n", res);
      exit (1);
    }

  void *handle2 = dlopen (LIBDL_SO, RTLD_LAZY);
  if (handle2 == NULL)
    {
      printf ("libdl.so: %s\n", dlerror ());
      exit (1);
    }

  if (dlvsym (handle2, "_dlfcn_hook", "GLIBC_PRIVATE") == NULL)
    {
      printf ("dlvsym: %s\n", dlerror ());
      exit (1);
    }

  void *(*dlsymfn) (void *, const char *);
  dlsymfn = dlsym (handle2, "dlsym");
  if (dlsymfn == NULL)
    {
      printf ("dlsym \"dlsym\": %s\n", dlerror ());
      exit (1);
    }
  void *test2 = dlsymfn (handle, "test");
  if (test2 == NULL)
    {
      printf ("%s\n", dlerror ());
      exit (1);
    }
  else if (test2 != (void *) test)
    {
      printf ("test %p != test2 %p\n", test, test2);
      exit (1);
    }

  dlclose (handle2);
  dlclose (handle);

  handle = dlmopen (LM_ID_BASE, "modstatic2.so", RTLD_LAZY);
  if (handle == NULL)
    {
      printf ("%s\n", dlerror ());
      exit (1);
    }
  dlclose (handle);

  handle = dlmopen (LM_ID_NEWLM, "modstatic2.so", RTLD_LAZY);
  if (handle == NULL)
    printf ("LM_ID_NEWLM: %s\n", dlerror ());
  else
    {
      puts ("LM_ID_NEWLM unexpectedly succeeded");
      exit (1);
    }

  return 0;
}
Ejemplo n.º 4
0
Elf_Scn *symtab_write_elf(Elf *e, struct sect * sects,
						  struct buffer *strtab_buf, struct buffer *shstrtab_buf)
{
  unsigned i, k;
  struct sym_info *sym;
  Elf32_Sym esym;

  Elf_Scn *scn, *relscn, *tmpscn;
  Elf_Data *data, *reldata;
  Elf32_Shdr *shdr, *relshdr;

  struct buffer buf;
  struct buffer *relbuf;

  struct sect *s;

  buffer_init(&buf);

  esym.st_name = 0;
  esym.st_value = 0;
  esym.st_size = 0;
  esym.st_info = 0;
  esym.st_other = 0;
  esym.st_shndx = 0;
  buffer_writemem(&buf, &esym, sizeof(esym));

  relbuf = malloc(0);
  for (s = sects, k = 0; s != NULL; s = s->next, k++)
	{
	  relbuf = realloc(relbuf, (k+1)*sizeof(struct buffer));
	  buffer_init(&relbuf[k]);
	}

  for (i = 0; i < SYMTAB_SIZE; i++)
    {
      for (sym = symtab[i]; sym != NULL; sym = sym->next)
        {
          if (sym->symbol[0] != '.' || sym->relocs != NULL)
            {
			  struct reloc_info size;
			  int type = STT_NOTYPE;
			  int bind = STB_LOCAL;
			  if (!sym->defined || sym->bind == SYM_BIND_GLOBAL)
				{
				  bind = STB_GLOBAL;
				}

			  esym.st_name = strtab_buf->pos;
			  buffer_writestr(strtab_buf, sym->symbol);

			  esym.st_value = sym->addr;
			  
			  size = expr_evaluate(sym->size);
			  if (size.symbol != NULL) {
				eprintf("Cannot relocate symbol size");
				exit(EXIT_FAILURE);
			  }
			  esym.st_size = size.intval;

			  if (strcmp(sym->type, "@function") == 0)
				type = STT_FUNC;
			  if (strcmp(sym->type, "@object") == 0)
				type = STT_OBJECT;
			  esym.st_info = ELF32_ST_INFO(bind, type);

			  esym.st_other = ELF32_ST_VISIBILITY(STV_DEFAULT);

			  tmpscn = section_find(e, sym->section, shstrtab_buf);
			  if (tmpscn == NULL && sym->section != NULL)
				tmpscn = section_find(e, pile_name(pile_match(sym->section)), shstrtab_buf);
			  esym.st_shndx = tmpscn != NULL ? elf_ndxscn(tmpscn) : 0;

			  if (sym->relocs != NULL) {
				struct sym_reloc_info *r;
				for (r = sym->relocs; r != NULL; r = r->next) {
				  Elf32_Rela rel;
				  rel.r_offset = r->addr;
				  rel.r_info = ELF32_R_INFO(buf.pos/sizeof(esym), r->type);
				  rel.r_addend = r->addend;
				  for (s = sects, k = 0; s != NULL; s = s->next, k++)
					{
					  if (strcmp(s->name, r->sect) == 0)
						{
						  buffer_writemem(&relbuf[k], &rel, sizeof(rel));
						}
					}
				}
			  }

			  buffer_writemem(&buf, &esym, sizeof(esym));
			}
        }
    }

  scn = xelf_newscn(e);

  shdr = xelf32_getshdr(scn);
  shdr->sh_name = shstrtab_buf->pos;
  buffer_writestr(shstrtab_buf, ".symtab");
  shdr->sh_type = SHT_SYMTAB;
  shdr->sh_flags = 0;

  data = xelf_newdata(scn);
  data->d_align = 4;
  data->d_off = 0;
  data->d_type = ELF_T_SYM;
  data->d_version = EV_CURRENT;
  data->d_buf = buf.data;
  data->d_size = buf.pos;

  for (s = sects, k = 0; s != NULL; s = s->next, k++)
	{
	  if (relbuf[k].pos > 0)
		{
		  char *relname;

		  relscn = xelf_newscn(e);
	  
		  relshdr = xelf32_getshdr(relscn);
		  relshdr->sh_name = shstrtab_buf->pos;
		  relname = malloc(strlen(s->name)+6);
		  strcpy(relname, ".rela");
		  strcat(relname, s->name);
		  buffer_writestr(shstrtab_buf, relname);

		  relshdr->sh_type = SHT_RELA;
		  shdr->sh_flags = 0;

		  reldata = xelf_newdata(relscn);
		  reldata->d_align = 4;
		  reldata->d_off = 0;
		  reldata->d_type = ELF_T_RELA;
		  reldata->d_version = EV_CURRENT;
		  reldata->d_buf = relbuf[k].data;
		  reldata->d_size = relbuf[k].pos;

		  relshdr->sh_link = elf_ndxscn(scn);
		  
		  tmpscn = section_find(e, s->name, shstrtab_buf);
		  relshdr->sh_info = tmpscn != NULL ? elf_ndxscn(tmpscn) : 0;
		}
	}

  return scn;
}
Ejemplo n.º 5
0
int
test (FILE *out, int a)
{
  fputs ("in modstatic2.c (test)\n", out);

  void *handle = dlopen ("modstatic2-nonexistent.so", RTLD_LAZY);
  if (handle == NULL)
    fprintf (out, "nonexistent: %s\n", dlerror ());
  else
    exit (1);

  handle = dlopen ("modstatic2.so", RTLD_LAZY);
  if (handle == NULL)
    {
      fprintf (out, "%s\n", dlerror ());
      exit (1);
    }

  int (*test2) (FILE *, int);
  test2 = dlsym (handle, "test");
  if (test2 == NULL)
    {
      fprintf (out, "%s\n", dlerror ());
      exit (1);
    }
  if (test2 != test)
    {
      fprintf (out, "test %p != test2 %p\n", test, test2);
      exit (1);
    }

  Dl_info info;
  int res = dladdr (test2, &info);
  if (res == 0)
    {
      fputs ("dladdr returned 0\n", out);
      exit (1);
    }
  else
    {
      if (strstr (info.dli_fname, "modstatic2.so") == NULL
	  || strcmp (info.dli_sname, "test") != 0)
	{
	  fprintf (out, "fname %s sname %s\n", info.dli_fname, info.dli_sname);
	  exit (1);
	}
      if (info.dli_saddr != (void *) test2)
	{
	  fprintf (out, "saddr %p != test %p\n", info.dli_saddr, test2);
	  exit (1);
	}
    }

  ElfW(Sym) *sym;
  void *symp;
  res = dladdr1 (test2, &info, &symp, RTLD_DL_SYMENT);
  if (res == 0)
    {
      fputs ("dladdr1 returned 0\n", out);
      exit (1);
    }
  else
    {
      if (strstr (info.dli_fname, "modstatic2.so") == NULL
	  || strcmp (info.dli_sname, "test") != 0)
	{
	  fprintf (out, "fname %s sname %s\n", info.dli_fname, info.dli_sname);
	  exit (1);
	}
      if (info.dli_saddr != (void *) test2)
	{
	  fprintf (out, "saddr %p != test %p\n", info.dli_saddr, test2);
	  exit (1);
	}
      sym = symp;
      if (sym == NULL)
	{
	  fputs ("sym == NULL\n", out);
	  exit (1);
	}
      if (ELF32_ST_BIND (sym->st_info) != STB_GLOBAL
	  || ELF32_ST_VISIBILITY (sym->st_other) != STV_DEFAULT)
	{
	  fprintf (out, "bind %d visibility %d\n",
		   (int) ELF32_ST_BIND (sym->st_info),
		   (int) ELF32_ST_VISIBILITY (sym->st_other));
	  exit (1);
	}
    }

  Lmid_t lmid;
  res = dlinfo (handle, RTLD_DI_LMID, &lmid);
  if (res != 0)
    {
      fprintf (out, "dlinfo returned %d %s\n", res, dlerror ());
      exit (1);
    }
  else if (lmid != LM_ID_BASE)
    {
      fprintf (out, "lmid %d != %d\n", (int) lmid, (int) LM_ID_BASE);
      exit (1);
    }

  void *handle2 = dlopen (LIBDL_SO, RTLD_LAZY);
  if (handle2 == NULL)
    {
      fprintf (out, "libdl.so: %s\n", dlerror ());
      exit (1);
    }

#ifdef DO_VERSIONING
  if (dlvsym (handle2, "_dlfcn_hook", "GLIBC_PRIVATE") == NULL)
    {
      fprintf (out, "dlvsym: %s\n", dlerror ());
      exit (1);
    }
#endif

  void *(*dlsymfn) (void *, const char *);
  dlsymfn = dlsym (handle2, "dlsym");
  if (dlsymfn == NULL)
    {
      fprintf (out, "dlsym \"dlsym\": %s\n", dlerror ());
      exit (1);
    }
  void *test3 = dlsymfn (handle, "test");
  if (test3 == NULL)
    {
      fprintf (out, "%s\n", dlerror ());
      exit (1);
    }
  else if (test3 != (void *) test2)
    {
      fprintf (out, "test2 %p != test3 %p\n", test2, test3);
      exit (1);
    }

  dlclose (handle2);
  dlclose (handle);

  handle = dlmopen (LM_ID_BASE, "modstatic2.so", RTLD_LAZY);
  if (handle == NULL)
    {
      fprintf (out, "%s\n", dlerror ());
      exit (1);
    }
  dlclose (handle);

  handle = dlmopen (LM_ID_NEWLM, "modstatic2.so", RTLD_LAZY);
  if (handle == NULL)
    fprintf (out, "LM_ID_NEWLM: %s\n", dlerror ());
  else
    {
      fputs ("LM_ID_NEWLM unexpectedly succeeded\n", out);
      exit (1);
    }

  handle = dlopen ("modstatic.so", RTLD_LAZY);
  if (handle == NULL)
    {
      fprintf (out, "%s\n", dlerror ());
      exit (1);
    }

  int (*test4) (int);
  test4 = dlsym (handle, "test");
  if (test4 == NULL)
    {
      fprintf (out, "%s\n", dlerror ());
      exit (1);
    }

  res = test4 (16);
  if (res != 16 + 16)
    {
      fprintf (out, "modstatic.so (test) returned %d\n", res);
      exit (1);
    }

  res = dladdr1 (test4, &info, &symp, RTLD_DL_SYMENT);
  if (res == 0)
    {
      fputs ("dladdr1 returned 0\n", out);
      exit (1);
    }
  else
    {
      if (strstr (info.dli_fname, "modstatic.so") == NULL
	  || strcmp (info.dli_sname, "test") != 0)
	{
	  fprintf (out, "fname %s sname %s\n", info.dli_fname, info.dli_sname);
	  exit (1);
	}
      if (info.dli_saddr != (void *) test4)
	{
	  fprintf (out, "saddr %p != test %p\n", info.dli_saddr, test4);
	  exit (1);
	}
      sym = symp;
      if (sym == NULL)
	{
	  fputs ("sym == NULL\n", out);
	  exit (1);
	}
      if (ELF32_ST_BIND (sym->st_info) != STB_GLOBAL
	  || ELF32_ST_VISIBILITY (sym->st_other) != STV_DEFAULT)
	{
	  fprintf (out, "bind %d visibility %d\n",
		   (int) ELF32_ST_BIND (sym->st_info),
		   (int) ELF32_ST_VISIBILITY (sym->st_other));
	  exit (1);
	}
    }

  dlclose (handle);

  fputs ("leaving modstatic2.c (test)\n", out);
  return a + a;
}