Exemple #1
0
static int
find_matching_file (struct dl_phdr_info *info, size_t size, void *data)
{
    struct file_match *match = data;
    /* This code is modeled from Gfind_proc_info-lsb.c:callback() from libunwind */
    long n;
    const ElfW(Phdr) *phdr;
    ElfW(Addr) load_base = info->dlpi_addr;

    phdr = info->dlpi_phdr;
    for (n = info->dlpi_phnum; --n >= 0; phdr++) {
	if (phdr->p_type == PT_LOAD) {
	    ElfW(Addr) vaddr = phdr->p_vaddr + load_base;
	    if (match->address >= vaddr &&
		match->address < vaddr + phdr->p_memsz)
	    {
		/* we found a match */
		match->file = info->dlpi_name;
		match->base = info->dlpi_addr;
		return 1;
	    }
	}
    }

    return 0;
}
Exemple #2
0
static void
_dl_unprotect_relro (struct link_map *l)
{
  ElfW(Addr) start = ((l->l_addr + l->l_relro_addr)
		      & ~(GLRO(dl_pagesize) - 1));
  ElfW(Addr) end = ((l->l_addr + l->l_relro_addr + l->l_relro_size)
		    & ~(GLRO(dl_pagesize) - 1));

  if (start != end)
    __mprotect ((void *) start, end - start, PROT_READ | PROT_WRITE);
}
Exemple #3
0
void
_dl_protect_relro (struct elf_resolve *l)
{
	ElfW(Addr) base = (ElfW(Addr)) DL_RELOC_ADDR(l->loadaddr, l->relro_addr);
	ElfW(Addr) start = (base & PAGE_ALIGN);
	ElfW(Addr) end = ((base + l->relro_size) & PAGE_ALIGN);
	_dl_if_debug_dprint("RELRO protecting %s:  start:%x, end:%x\n", l->libname, start, end);
	if (start != end &&
	    _dl_mprotect ((void *) start, end - start, PROT_READ) < 0) {
		_dl_dprintf(2, "%s: cannot apply additional memory protection after relocation", l->libname);
		_dl_exit(0);
	}
}
Exemple #4
0
bool
CrashInfo::GetDSOInfo()
{
    Phdr* phdrAddr = reinterpret_cast<Phdr*>(m_auxvValues[AT_PHDR]);
    int phnum = m_auxvValues[AT_PHNUM];
    assert(m_auxvValues[AT_PHENT] == sizeof(Phdr));

    if (phnum <= 0 || phdrAddr == nullptr) {
        return false;
    }
    TRACE("DSO: phdr %p phnum %d\n", phdrAddr, phnum);

    // Search for the program PT_DYNAMIC header 
    ElfW(Dyn)* dynamicAddr = nullptr;
    for (int i = 0; i < phnum; i++, phdrAddr++)
    {
        Phdr ph;
        if (!ReadMemory(phdrAddr, &ph, sizeof(ph))) {
            return false;
        }
        TRACE("DSO: phdr %p type %d (%x) vaddr %016lx memsz %016lx offset %016lx\n", 
            phdrAddr, ph.p_type, ph.p_type, ph.p_vaddr, ph.p_memsz, ph.p_offset);

        if (ph.p_type == PT_DYNAMIC) 
        {
            dynamicAddr = reinterpret_cast<ElfW(Dyn)*>(ph.p_vaddr);
        }
        else if (ph.p_type == PT_GNU_EH_FRAME)
Exemple #5
0
static const char *
elf_platform (void)
{
  int fd;

  fd = open ("/proc/self/auxv", O_RDONLY);

  if (fd != -1)
    {
      char buf[1024];
      ElfW(auxv_t) *av;
      ssize_t n;

      n = read (fd, buf, sizeof (buf));
      close (fd);

      if (n > 0)
	{
	  for (av = (ElfW(auxv_t) *) buf; av->a_type != AT_NULL; ++av)
	    switch (av->a_type)
	      {
	      case AT_PLATFORM:
		return (const char *) av->a_un.a_val;

	      default:
		break;
	      }
	}
    }
void
attribute_hidden
_dl_tlsdesc_lazy_resolver_fixup (struct tlsdesc volatile *td,
				 Elf32_Addr *got)
{
  struct link_map *l = (struct link_map *)got[1];
  lookup_t result;
  unsigned long value;

  if (_dl_tlsdesc_resolve_early_return_p
      (td, (void*)(D_PTR (l, l_info[ADDRIDX (DT_TLSDESC_PLT)]) + l->l_addr)))
    return;

  if (td->argument.value & 0x80000000)
    {
      /* A global symbol, this is the symbol index.  */
      /* The code below was borrowed from _dl_fixup().  */
      const Elf_Symndx symndx = td->argument.value ^ 0x80000000;
      const ElfW(Sym) *const symtab
	= (const void *) D_PTR (l, l_info[DT_SYMTAB]);
      const char *strtab = (const void *) D_PTR (l, l_info[DT_STRTAB]);
      const ElfW(Sym) *sym = &symtab[symndx];

      /* Look up the target symbol.  If the normal lookup rules are not
	 used don't look in the global scope.  */
      if (ELFW(ST_BIND) (sym->st_info) != STB_LOCAL
	  && __builtin_expect (ELFW(ST_VISIBILITY) (sym->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[symndx] & 0x7fff;
	      version = &l->l_versions[ndx];
	      if (version->hash == 0)
		version = NULL;
	    }

	  result = _dl_lookup_symbol_x
	    (strtab + sym->st_name, l, &sym,
	     l->l_scope, version, ELF_RTYPE_CLASS_PLT,
	     DL_LOOKUP_ADD_DEPENDENCY, NULL);
	  if (sym)
	    value = sym->st_value;
	  else
	    {
	      td->entry = _dl_tlsdesc_undefweak;
	      goto done;
	    }
	}
      else
	{
	  /* We already found the symbol.  The module (and therefore its load
	     address) is also known.  */
	  result = l;
	  value = sym->st_value;
	}
    }
Exemple #7
0
static int
find_dynamic_entry_addr(Process *proc, void *pvAddr, int d_tag, void **addr) {
	int i = 0, done = 0;
	ElfW(Dyn) entry;

	debug(DEBUG_FUNCTION, "find_dynamic_entry()");

	if (addr ==	NULL || pvAddr == NULL || d_tag < 0 || d_tag > DT_NUM) {
		return -1;
	}

	while ((!done) && (i < ELF_MAX_SEGMENTS) &&
		(sizeof(entry) == umovebytes(proc, pvAddr, &entry, sizeof(entry))) &&
		(entry.d_tag != DT_NULL)) {
		if (entry.d_tag == d_tag) {
			done = 1;
			*addr = (void *)entry.d_un.d_val;
		}
		pvAddr += sizeof(entry);
		i++;
	}

	if (done) {
		debug(2, "found address: 0x%p in dtag %d\n", *addr, d_tag);
		return 0;
	}
	else {
		debug(2, "Couldn't address for dtag!\n");
		return -1;
	}
}
Exemple #8
0
static void
hook_libdl_cb(void *data) {
	struct cb_data *hook_data = data;
	const char *lib_name = NULL;
	ElfW(Addr) addr;
	struct ltelf *lte = NULL;

	debug(DEBUG_FUNCTION, "add_library_cb");

	if (!data) {
		debug(2, "No callback data");
		return;
	}

	lib_name = hook_data->lib_name;
	addr = hook_data->addr;
	lte = hook_data->lte;

	if (library_num < MAX_LIBRARIES) {
		lte[library_num].base_addr = addr;
		library[library_num++] = strdup(lib_name);
	}
	else {
		fprintf (stderr, "MAX LIBS REACHED\n");
		exit(EXIT_FAILURE);
	}
}
Exemple #9
0
static telf_status
headerfs_release_ident(void *obj_hdl)
{
        telf_obj *obj = obj_hdl;
        telf_status ret;
        telf_default_content *content = NULL;
        ElfW(Ehdr) *ehdr = obj->ctx->ehdr;

        DEBUG("name:%s data=%p", obj->name, obj->data);

        content = obj->data;
        if (content) {
                int i;

                for (i = 0; i < EI_NIDENT; i++) {
                        char tmp[3] = {
                          content->buf[2*i],
                          content->buf[2*i+1],
                          0
                        };
                        ehdr->e_ident[i] = (uint8_t) strtoul(tmp, NULL, 16);
                }
        }

        ret = ELF_SUCCESS;

        return ret;
}
void __libc_init_AT_SECURE(KernelArgumentBlock& args) {
  __libc_auxv = args.auxv;

  // Check that the kernel provided a value for AT_SECURE.
  bool found_AT_SECURE = false;
  for (ElfW(auxv_t)* v = __libc_auxv; v->a_type != AT_NULL; ++v) {
    if (v->a_type == AT_SECURE) {
      found_AT_SECURE = true;
      break;
    }
  }
  if (!found_AT_SECURE) __early_abort(__LINE__);

  if (getauxval(AT_SECURE)) {
    // If this is a setuid/setgid program, close the security hole described in
    // https://www.freebsd.org/security/advisories/FreeBSD-SA-02:23.stdio.asc
    __nullify_closed_stdio();

    __sanitize_environment_variables(args.envp);
  }

  // Now the environment has been sanitized, make it available.
  environ = args.envp;

  __initialize_personality();
}
Exemple #11
0
static telf_status
symentryfs_read_info(void *obj_hdl,
                     char **bufp,
                     size_t *buf_lenp)
{
        telf_obj *obj = obj_hdl;
        char *symname = NULL;
        char *buf = NULL;
        size_t buf_len = 0;
        telf_status ret;
        FILE *out = NULL;
        ElfW(Sym) *sym = obj->parent->data;

        /* default value */
        symname = "NONAME";

        if (sym->st_name) {
                symname = ((ELF_SECTION_SYMTAB == obj->parent->type) ?
                           elf_getsymname :
                           elf_getdsymname)(obj->ctx, sym);

                if (! symname || ! *symname)
                        symname = "UNRESOLVED";
        }

        out = open_memstream(&buf, &buf_len);
        if (! out) {
                ERR("open_memstream: %s", strerror(errno));
                ret = ELF_ENOMEM;
                goto end;
        }

        fprintf(out,
                "value: %p\n"
                "size: %zu\n"
                "type: %s\n"
                "bind: %s\n"
                "name: %s\n",
                (void *) sym->st_value,
                sym->st_size,
                sym_type_to_str(sym),
                sym_bind_to_str(sym),
                symname);

        ret = ELF_SUCCESS;
  end:
        if (out)
                fclose(out);

        if (bufp)
                *bufp = buf;
        else
                free(buf);

        if (buf_lenp)
                *buf_lenp = buf_len;

        return ret;
}
extern "C" unsigned long int getauxval(unsigned long int type) {
  for (ElfW(auxv_t)* v = __libc_auxv; v->a_type != AT_NULL; ++v) {
    if (v->a_type == type) {
      return v->a_un.a_val;
    }
  }
  return 0;
}
Exemple #13
0
_dl_linux_resolver (struct elf_resolve *tpnt, int reloc_entry)
{
	ELF_RELOC *this_reloc;
	char *strtab;
	ElfW(Sym) *symtab;
	int symtab_index;
	char *rel_addr;
	struct elf_resolve *new_tpnt;
	char *new_addr;
	struct funcdesc_value funcval;
	struct funcdesc_value volatile *got_entry;
	char *symname;

	rel_addr = (char *)tpnt->dynamic_info[DT_JMPREL];

	this_reloc = (ELF_RELOC *)(intptr_t)(rel_addr + reloc_entry);
	symtab_index = ELF_R_SYM(this_reloc->r_info);

	symtab = (Elf32_Sym *) tpnt->dynamic_info[DT_SYMTAB];
	strtab = (char *) tpnt->dynamic_info[DT_STRTAB];
	symname= strtab + symtab[symtab_index].st_name;

	/* Address of GOT entry fix up */
	got_entry = (struct funcdesc_value *) DL_RELOC_ADDR(tpnt->loadaddr, this_reloc->r_offset);

	/* Get the address to be used to fill in the GOT entry.  */
	new_addr = _dl_lookup_hash(symname, tpnt->symbol_scope, NULL, 0, &new_tpnt);
	if (!new_addr) {
		new_addr = _dl_lookup_hash(symname, NULL, NULL, 0, &new_tpnt);
		if (!new_addr) {
			_dl_dprintf(2, "%s: can't resolve symbol '%s'\n",
				    _dl_progname, symname);
			_dl_exit(1);
		}
	}

	funcval.entry_point = new_addr;
	funcval.got_value = new_tpnt->loadaddr.got_value;

#if defined (__SUPPORT_LD_DEBUG__)
	if (_dl_debug_bindings) {
		_dl_dprintf(_dl_debug_file, "\nresolve function: %s", symname);
		if (_dl_debug_detail)
			_dl_dprintf(_dl_debug_file,
				    "\n\tpatched (%x,%x) ==> (%x,%x) @ %x\n",
				    got_entry->entry_point, got_entry->got_value,
				    funcval.entry_point, funcval.got_value,
				    got_entry);
	}
	if (1 || !_dl_debug_nofixups) {
		*got_entry = funcval;
	}
#else
	*got_entry = funcval;
#endif

	return got_entry;
}
// Returns elf_header.e_type if the file pointed by fd is an ELF binary.
static int FileGetElfType(const int fd) {
  ElfW(Ehdr) elf_header;
  if (!ReadFromOffsetExact(fd, &elf_header, sizeof(elf_header), 0)) {
    return -1;
  }
  if (memcmp(elf_header.e_ident, ELFMAG, SELFMAG) != 0) {
    return -1;
  }
  return elf_header.e_type;
}
Exemple #15
0
int main(int argc, char *argv[]){
	long i;
	ElfW(Addr) a_type;
	ElfW(Addr) a_val;
	
	if(argc == 1){
		printf("No arguments specified.\n\n");
		print_help();
		return 0;
	}
	
	for(i = 1; i < argc; i++){
		if(!strcasecmp("--help", argv[i]) || !strcasecmp("-help", argv[i])){
			print_help();
			return 0;
		}
		if(!strcasecmp("--info", argv[i]) || !strcasecmp("-info", argv[i])){
			print_info();
			return 0;
		}
		if(!strcasecmp("--list", argv[i]) || !strcasecmp("-list", argv[i])){
			print_list();
			return 0;
		}
		if(!strcasecmp("--hwcap", argv[i]) || !strcasecmp("-hwcap", argv[i])){
			print_hwcap();
			return 0;
		}

	}

	for(i = 1; i < argc; i++){
		a_type = translate_a_type(argv[i]);
		a_val = query_auxv(a_type);
#ifdef __powerpc64__
 		 printf("%lu\n", a_val);
#else
		printf("%u\n", a_val);
#endif
	}

	return 0;
}
Exemple #16
0
static telf_status
headerfs_release_entrypoint(void *obj_hdl)
{
        telf_obj *obj = obj_hdl;
        telf_status ret;
        telf_default_content *content = NULL;

        DEBUG("name:%s data=%p", obj->name, obj->data);

        content = obj->data;
        if (content) {
                ElfW(Addr) addr = (ElfW(Addr)) strtoull(content->buf, NULL, 0);
                DEBUG("new entry point: %p", (void *) addr);
                obj->ctx->ehdr->e_entry = addr;
        }

        ret = ELF_SUCCESS;

        return ret;
}
Exemple #17
0
int init_elf_headers(HIJACK *hijack)
{
    hijack->ehdr.raw = read_data(hijack, (unsigned long)(hijack->baseaddr), sizeof(ElfW(Ehdr)));
    if (!(hijack->ehdr.raw))
        return -1;
    
    hijack->phdr.raw = read_data(hijack, ((unsigned long)(hijack->baseaddr) + hijack->ehdr.ehdr->e_phoff), hijack->ehdr.ehdr->e_phentsize * hijack->ehdr.ehdr->e_phnum);
    if (!(hijack->phdr.raw))
        return -1;

    return 0;
}
Exemple #18
0
/*
 * This is the entry point for the linker wrapper, which finds
 * the real linker, then bootstraps into it.
 */
extern "C" ElfW(Addr) __linker_init(void* raw_args) {
  KernelArgumentBlock args(raw_args);

  static uintptr_t linker_offset = reinterpret_cast<uintptr_t>(&linker_code_start);
  static uintptr_t linktime_addr = reinterpret_cast<uintptr_t>(&linktime_addr);
  ElfW(Addr) my_addr = reinterpret_cast<uintptr_t>(&linktime_addr) - linktime_addr;

  // Set AT_ENTRY to the proper entry point
  for (ElfW(auxv_t)* v = args.auxv; v->a_type != AT_NULL; ++v) {
    if (v->a_type == AT_BASE) {
      v->a_un.a_val = my_addr + linker_offset;
    }
    if (v->a_type == AT_ENTRY) {
      v->a_un.a_val = my_addr + reinterpret_cast<uintptr_t>(&original_start);
    }
  }

  // Return address of linker entry point -- may need to ensure that raw_args
  // was saved.
  return my_addr + linker_offset + reinterpret_cast<uintptr_t>(&linker_entry);
}
Exemple #19
0
int
iconv_real_init(
  void
) {
  static pthread_mutex_t iconv_real_lock = PTHREAD_MUTEX_INITIALIZER;
  static int iconv_real_initialized = 0;
  static int iconv_real_status = -1;
  struct link_map *map = _r_debug.r_map;

  if (iconv_real_initialized) {
    return iconv_real_status;
  }

  pthread_mutex_lock(&iconv_real_lock);

  if (!map) {
    goto out;
  }

  for (; map; map = map->l_next) {
    if (!strstr(map->l_name, "/libc.so")) {
      continue;
    }

    ElfW(Dyn) *dyn;
    ElfW(Sym) *symtab = NULL;
    char const *strtab = NULL;
    unsigned int symnum = 0;

    for (dyn = map->l_ld; dyn->d_tag != DT_NULL; ++dyn) {
      if (dyn->d_tag == DT_SYMTAB) {
	symtab = (ElfW(Sym) *)OFFSET(map, dyn->d_un.d_ptr);
      }
      else if (dyn->d_tag == DT_STRTAB) {
	strtab = (char const *)OFFSET(map, dyn->d_un.d_ptr);
      }
      else if (dyn->d_tag == DT_HASH) {
	symnum = ((unsigned int *)OFFSET(map, dyn->d_un.d_ptr))[1];
      }
    }
void dynLibImplLinux::GetImportAndExportData( 
	const char* dllName )
{
	if( std::string(dllName).empty())
	{
		return;
	}

	Elf* mainElf;
	struct link_map* mainLm;
	std::string csPath_o;
	OpenDynamicLibrary( dllName, mainElf, mainLm, csPath_o );
	if ( mainLm == NULL )
	{
		return;
	}

	Elf_Scn* section = 0;
	ElfW(Shdr) *shdr;
	FindSection( mainElf, SHT_DYNAMIC, section, shdr );

	std::list<std::string> dependencies;
	ExtractDynSymbols( mainElf, section, shdr, STT_NOTYPE, dependencies );

	std::list<std::string>::iterator it;
	for(it = dependencies.begin( ); it != dependencies.end( ) ; it++) {

		AddString( it->c_str() );

		if ( GetDllEntry( it->c_str()  ) == NULL )
		{
			DLL_ENTRY stImpExport;

			std::string csPath_o;
			if ( GetExportData( it->c_str(), stImpExport.ArrayExport, csPath_o ) )
			{
				stImpExport.m_bIsStable = true;
				stImpExport.m_csFullPath = csPath_o;

				// Add data to static internal map
				MakeUpper( *it );
				m_DataEntry[ *it ] = stImpExport;

			}

		}

		DeleteString( it->c_str() );
	}

	dlclose( mainLm );
}
Exemple #21
0
/* Returns 0 if everything is ok, != 0 in case of error.  */
int
process_elf_file (const char *file_name, const char *lib, int *flag,
		  unsigned int *osversion, char **soname, void *file_contents,
		  size_t file_length)
{
  union
    {
      Elf64_Ehdr *eh64;
      Elf32_Ehdr *eh32;
      ElfW(Ehdr) *eh;
    }
  elf_header;
  int ret;

  elf_header.eh = file_contents;
  if (elf_header.eh->e_ident [EI_CLASS] == ELFCLASS32)
    {
      ret = process_elf32_file (file_name, lib, flag, osversion, soname,
				file_contents, file_length);
      if (!ret)
	{
	  Elf32_Word flags = elf_header.eh32->e_flags;
	  int nan2008 = (flags & EF_MIPS_NAN2008) != 0;

	  /* n32 libraries are always libc.so.6+, o32 only if 2008 NaN.  */
	  if ((flags & EF_MIPS_ABI2) != 0)
	    *flag = (nan2008 ? FLAG_MIPS64_LIBN32_NAN2008
		     : FLAG_MIPS64_LIBN32) | FLAG_ELF_LIBC6;
	  else if (nan2008)
	    *flag = FLAG_MIPS_LIB32_NAN2008 | FLAG_ELF_LIBC6;
	}
    }
  else
    {
      ret = process_elf64_file (file_name, lib, flag, osversion, soname,
				file_contents, file_length);
      /* n64 libraries are always libc.so.6+.  */
      if (!ret)
	{
	  Elf64_Word flags = elf_header.eh64->e_flags;
	  int nan2008 = (flags & EF_MIPS_NAN2008) != 0;

	  *flag = (nan2008 ? FLAG_MIPS64_LIBN64_NAN2008
		   : FLAG_MIPS64_LIBN64) | FLAG_ELF_LIBC6;
	}
    }

  return ret;
}
Exemple #22
0
internal_function
_dl_vdso_vsym (const char *name, const struct r_found_version *vers)
{
#ifndef __ZRT_SO
  struct link_map *map = GLRO (dl_sysinfo_map);
  void *value = NULL;


  if (map != NULL)
    {
      /* Use a WEAK REF so we don't error out if the symbol is not found.  */
      ElfW (Sym) wsym;
      memset (&wsym, 0, sizeof (ElfW (Sym)));
      wsym.st_info = (unsigned char) ELFW (ST_INFO (STB_WEAK, STT_NOTYPE));

      /* Search the scope of the vdso map.  */
      const ElfW (Sym) *ref = &wsym;
      lookup_t result = GLRO (dl_lookup_symbol_x) (name, map, &ref,
						   map->l_local_scope,
						   vers, 0, 0, NULL);

      if (ref != NULL)
	value = DL_SYMBOL_ADDRESS (result, ref);
    }
Exemple #23
0
unsigned la_objopen(struct link_map *map, Lmid_t lmid, uintptr_t *cookie) {
#ifdef GLGRAB_APPLY_ELF_HACK
	ElfW(Dyn) *last, *pltrelsz = NULL;
	for (last = map->l_ld; last->d_tag != DT_NULL; ++last) {
		if (last->d_tag == DT_PLTRELSZ)
			pltrelsz = last;
	}

	if (pltrelsz == NULL) {
		pltrelsz = last++;
		last->d_tag = DT_NULL;
		pltrelsz->d_tag = DT_PLTRELSZ;
		pltrelsz->d_un.d_val = 0;

		ElfW(Dyn) **p = &map->l_ld + 1;
		while (*p < map->l_ld || *p > last)
			++p;

		p[DT_PLTRELSZ - map->l_ld->d_tag] = pltrelsz;
	}
#endif

	return LA_FLG_BINDTO | LA_FLG_BINDFROM;
}
Exemple #24
0
void *get_func_end(void *func)
{
	int r;
	Dl_info dl_info;
	ElfW(Sym) *elf_info;

	r = dladdr1(func, &dl_info, (void **) &elf_info, RTLD_DL_SYMENT);
	if (r == 0)
		return NULL;
	if (elf_info == NULL)
		return NULL;
	if (dl_info.dli_saddr == NULL)
		return NULL;

	return ((unsigned char *) func) + elf_info->st_size;
}
Exemple #25
0
unsigned long int
__getauxval (unsigned long int type)
{
  ElfW(auxv_t) *p;

  if (type == AT_HWCAP)
    return GLRO(dl_hwcap);
  else if (type == AT_HWCAP2)
    return GLRO(dl_hwcap2);

  for (p = GLRO(dl_auxv); p->a_type != AT_NULL; p++)
    if (p->a_type == type)
      return p->a_un.a_val;

  __set_errno (ENOENT);
  return 0;
}
void* dlsym(void* handle, const char* symbol) {
  ScopedPthreadMutexLocker locker(&g_dl_mutex);

#if !defined(__LP64__)
  if (handle == NULL) {
    __bionic_format_dlerror("dlsym library handle is null", NULL);
    return NULL;
  }
#endif

  if (symbol == NULL) {
    __bionic_format_dlerror("dlsym symbol name is null", NULL);
    return NULL;
  }

  soinfo* found = NULL;
  ElfW(Sym)* sym = NULL;
  if (handle == RTLD_DEFAULT) {
    sym = dlsym_linear_lookup(symbol, &found, NULL);
  } else if (handle == RTLD_NEXT) {
    void* caller_addr = __builtin_return_address(0);
    soinfo* si = find_containing_library(caller_addr);

    sym = NULL;
    if (si && si->next) {
      sym = dlsym_linear_lookup(symbol, &found, si->next);
    }
  } else {
    found = reinterpret_cast<soinfo*>(handle);
    sym = dlsym_handle_lookup(found, symbol);
  }

  if (sym != NULL) {
    unsigned bind = ELF_ST_BIND(sym->st_info);

    if ((bind == STB_GLOBAL || bind == STB_WEAK) && sym->st_shndx != 0) {
      return reinterpret_cast<void*>(sym->st_value + found->load_bias);
    }

    __bionic_format_dlerror("symbol found but not global", symbol);
    return NULL;
  } else {
    __bionic_format_dlerror("undefined symbol", symbol);
    return NULL;
  }
}
Exemple #27
0
void
attribute_hidden
_dl_tlsdesc_resolve_rela_fixup (struct tlsdesc *td, struct link_map *l)
{
  const ElfW(Rela) *reloc = atomic_load_relaxed (&td->arg);

  /* After GL(dl_load_lock) is grabbed only one caller can see td->entry in
     initial state in _dl_tlsdesc_resolve_early_return_p, other concurrent
     callers will return and retry calling td->entry.  The updated td->entry
     synchronizes with the single writer so all read accesses here can use
     relaxed order.  */
  if (_dl_tlsdesc_resolve_early_return_p
      (td, (void*)(D_PTR (l, l_info[ADDRIDX (DT_TLSDESC_PLT)]) + l->l_addr)))
    return;

  /* The code below was borrowed from _dl_fixup(),
     except for checking for STB_LOCAL.  */
  const ElfW(Sym) *const symtab
    = (const void *) D_PTR (l, l_info[DT_SYMTAB]);
  const char *strtab = (const void *) D_PTR (l, l_info[DT_STRTAB]);
  const ElfW(Sym) *sym = &symtab[ELFW(R_SYM) (reloc->r_info)];
  lookup_t result;

   /* Look up the target symbol.  If the normal lookup rules are not
      used don't look in the global scope.  */
  if (ELFW(ST_BIND) (sym->st_info) != STB_LOCAL
      && __builtin_expect (ELFW(ST_VISIBILITY) (sym->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 + sym->st_name, l, &sym,
				    l->l_scope, version, ELF_RTYPE_CLASS_PLT,
				    DL_LOOKUP_ADD_DEPENDENCY, NULL);
    }
  else
    {
Exemple #28
0
/* Find the list of shared objects */
static struct link_map *
loaded (void)
{
  ElfW(Dyn) *d;

  if (&_DYNAMIC == 0)		/* statically linked */
    return 0;

  for (d = _DYNAMIC; d->d_tag != DT_NULL; ++d)
    if (d->d_tag == DT_DEBUG)
      {
	struct r_debug *r = (void *) d->d_un.d_ptr;
	return r->r_map;
      }

  return 0;			/* ld broken */
}
Exemple #29
0
unsigned long find_pltgot(HIJACK *hijack)
{
	unsigned int i;
	ElfW(Dyn) *dyn=NULL;
	
	SetError(hijack, ERROR_NONE);
	
	if (IsFlagSet(hijack, F_DEBUG))
		fprintf(stderr, "[*] Attempting to find PLT/GOT\n");
	
	for (i=0; i<hijack->ehdr.ehdr->e_phnum; i++)
	{
		if (hijack->phdr.phdr[i].p_type == PT_DYNAMIC)
		{
			dyn = (ElfW(Dyn) *)read_data(hijack, (unsigned long)(hijack->phdr.phdr[i].p_vaddr), hijack->phdr.phdr[i].p_memsz);
			break;
		}
	}
Exemple #30
0
void
get_proc_tables (proc_tables * ptabs)
{
#ifdef HAVE_ELF_H
# if (defined(HAVE_ELF32_DYN_D_TAG) || defined(HAVE_ELF64_DYN_D_TAG)) && HAVE_DECL_ELFW
	ElfW (Dyn) * dyn;

	memset (ptabs, 0x00, sizeof (proc_tables));
	for (dyn = _DYNAMIC; dyn != NULL && dyn->d_tag != DT_NULL; ++dyn)
		switch (dyn->d_tag)
		{
			 /* symbols */
		 case DT_SYMTAB:
			 ptabs->symbols = (Elf32_Sym *) dyn->d_un.d_ptr;
			 break;
		 case DT_HASH:
			 ptabs->sym_hash = (Elf32_Word *) dyn->d_un.d_ptr;
			 break;
		 case DT_SYMENT:
			 ptabs->sym_ent_size = dyn->d_un.d_val;
			 break;
			 /* strings */
		 case DT_STRTAB:
			 ptabs->strings = (char *)dyn->d_un.d_ptr;
			 break;
		 case DT_STRSZ:
			 ptabs->str_tabl_size = dyn->d_un.d_val;
			 break;
			 /* debug info */
		 case DT_DEBUG:
#  ifdef HAVE_LINK_H
			 ptabs->debug = (struct r_debug *)dyn->d_un.d_ptr;
#  endif			 
			 break;
			 /* GOT/PLT */
		 case DT_PLTGOT:
			 ptabs->pltgot = (void *)dyn->d_un.d_ptr;
			 break;
		}
	if (ptabs->sym_hash != NULL)
		ptabs->sym_ent_num = *(ptabs->sym_hash + 1);
# endif
#endif /* HAVE_ELF_H */
}