Пример #1
0
size_t HIDDEN FindSymbol(Module *module, const char* symbolName, int index)
{
	int i;
	link_map *dlmap;
	struct stat dlstat;
	int dlfile;
	uintptr_t map_base;
	Elf32_Ehdr *file_hdr;
	Elf32_Shdr *sections, *shstrtab_hdr, *symtab_hdr, *strtab_hdr;
	Elf32_Sym *symtab;
	const char *shstrtab, *strtab;
	uint16_t section_count;
	uint32_t symbol_count;
	size_t address;

	// If index > 0 then we shouldn't use dlsym, cos it will give wrong result
	if (index == 0)
	{
		address = (size_t)dlsym((void *)module->handle, symbolName);
		if (address != NULL)
			return address;
	}

	dlmap = (struct link_map *)module->handle;
	symtab_hdr = NULL;
	strtab_hdr = NULL;

	dlfile = open(dlmap->l_name, O_RDONLY);
	if (dlfile == -1 || fstat(dlfile, &dlstat) == -1)
	{
		close(dlfile);
		return NULL;
	}

	// Map library file into memory
	file_hdr = (Elf32_Ehdr *)mmap(NULL, dlstat.st_size, PROT_READ, MAP_PRIVATE, dlfile, 0);
	map_base = (uintptr_t)file_hdr;
	close(dlfile);
	if (file_hdr == MAP_FAILED)
	{
		return NULL;
	}

	if (file_hdr->e_shoff == 0 || file_hdr->e_shstrndx == SHN_UNDEF)
	{
		munmap(file_hdr, dlstat.st_size);
		return NULL;
	}

	sections = (Elf32_Shdr *)(map_base + file_hdr->e_shoff);
	section_count = file_hdr->e_shnum;
	// Get ELF section header string table
	shstrtab_hdr = &sections[file_hdr->e_shstrndx];
	shstrtab = (const char *)(map_base + shstrtab_hdr->sh_offset);

	// Iterate sections while looking for ELF symbol table and string table
	for (uint16_t i = 0; i < section_count; i++)
	{
		Elf32_Shdr &hdr = sections[i];
		const char *section_name = shstrtab + hdr.sh_name;
		//printf("Seg[%d].name = '%s'\n", i, section_name);

		if (strcmp(section_name, ".symtab") == 0)
		{
			symtab_hdr = &hdr;
		}
		else if (strcmp(section_name, ".strtab") == 0)
		{
			strtab_hdr = &hdr;
		}
	}

	if (symtab_hdr == NULL || strtab_hdr == NULL)
	{
		munmap(file_hdr, dlstat.st_size);
		return NULL;
	}

	symtab = (Elf32_Sym *)(map_base + symtab_hdr->sh_offset);
	strtab = (const char *)(map_base + strtab_hdr->sh_offset);
	symbol_count = symtab_hdr->sh_size / symtab_hdr->sh_entsize;

	int mangleNameLength;
	int mangleNameLastLength = 1024;	// Is it enouph?

	// If index is 0 then we need to take first entry
	if (index == 0) index++;

	// Iterate symbol table
	int match = 1;
	for (uint32_t i = 0; i < symbol_count; i++)
	{
		Elf32_Sym &sym = symtab[i];
		unsigned char sym_type = ELF32_ST_TYPE(sym.st_info);
		const char *sym_name = strtab + sym.st_name;

		// Skip symbols that are undefined or do not refer to functions or objects
		if (sym.st_shndx == SHN_UNDEF || (sym_type != STT_FUNC && sym_type != STT_OBJECT))
		{
			continue;
		}

		if (strcmp(sym_name, symbolName) == 0)
		{
			if (match == index)
			{
				address = (size_t)(dlmap->l_addr + sym.st_value);
				break;
			}
			else
			{
				match++;
			}
		}
		// Try to find lowest length mangled name then
		if (sym_name[0] == '_' && sym_name[1] == 'Z' && strstr(sym_name + 2, symbolName) != NULL && (mangleNameLength = strlen(sym_name)) < mangleNameLastLength)
		{
			mangleNameLastLength = mangleNameLength;
			address = (size_t)(dlmap->l_addr + sym.st_value);
#ifdef _DEBUG
			printf("FindSymbol (mangled name): symbol: \"%s\", address: %lx\n", sym_name, address);
#endif
		}
	}

	munmap(file_hdr, dlstat.st_size);

#ifdef _DEBUG
	printf("FindSymbol (elf): symbol: \"%s\", address: %lx\n", symbolName, address);
#endif

	return address;
}
Пример #2
0
orl_return ElfCreateSymbolHandles( elf_sec_handle elf_sec_hnd )
{
    int                 loop;
    int                 num_syms;
    elf_symbol_handle   current;
    unsigned char       *current_sym;
    Elf32_Sym           *current_sym32;
    Elf64_Sym           *current_sym64;
    int                 st_name;

    num_syms = elf_sec_hnd->size / elf_sec_hnd->entsize;
    elf_sec_hnd->assoc.sym.symbols = (elf_symbol_handle)_ClientSecAlloc( elf_sec_hnd, sizeof( elf_symbol_handle_struct ) * num_syms );
    if( elf_sec_hnd->assoc.sym.symbols == NULL )
        return( ORL_OUT_OF_MEMORY );
    current = elf_sec_hnd->assoc.sym.symbols;
    current_sym = elf_sec_hnd->contents;
    for( loop = 0; loop < num_syms; loop++ ) {
        if( elf_sec_hnd->elf_file_hnd->flags & ORL_FILE_FLAG_64BIT_MACHINE ) {
            current_sym64 = (Elf64_Sym *)current_sym;
            fix_sym64_byte_order( elf_sec_hnd->elf_file_hnd, current_sym64 );
            st_name = current_sym64->st_name;
            current->value.u._32[I64LO32] = current_sym64->st_value.u._32[I64LO32];
            current->value.u._32[I64HI32] = current_sym64->st_value.u._32[I64HI32];
            current->info = current_sym64->st_info;
            current->shndx = current_sym64->st_shndx;
        } else {
            current_sym32 = (Elf32_Sym *)current_sym;
            fix_sym_byte_order( elf_sec_hnd->elf_file_hnd, current_sym32 );
            st_name = current_sym32->st_name;
            current->value.u._32[I64LO32] = current_sym32->st_value;
            current->value.u._32[I64HI32] = 0;
            current->info = current_sym32->st_info;
            current->shndx = current_sym32->st_shndx;
        }
        if( st_name == 0 ) {
            current->name = NULL;
        } else {
            current->name = (char *)( elf_sec_hnd->assoc.sym.string_table->contents + st_name );
        }
        current->file_format = ORL_ELF;
        current->elf_file_hnd = elf_sec_hnd->elf_file_hnd;
        switch( ELF32_ST_BIND( current->info ) ) {
        case STB_LOCAL:
            current->binding = ORL_SYM_BINDING_LOCAL;
            break;
        case STB_GLOBAL:
            current->binding = ORL_SYM_BINDING_GLOBAL;
            break;
        case STB_WEAK:
            current->binding = ORL_SYM_BINDING_WEAK;
            break;
        default:
            current->binding = ORL_SYM_BINDING_NONE; // other?
            break;
        }
        switch( ELF32_ST_TYPE( current->info ) ) {
        case STT_OBJECT:
            current->type = ORL_SYM_TYPE_OBJECT;
            break;
        case STT_FUNC:
            current->type = ORL_SYM_TYPE_FUNCTION;
            break;
        case STT_SECTION:
            current->type = ORL_SYM_TYPE_SECTION;
            break;
        case STT_FILE:
            current->type = ORL_SYM_TYPE_FILE;
            break;
        default:
            current->type = ORL_SYM_TYPE_NOTYPE;
            break;
        }
        switch( current->shndx ) {
        case SHN_ABS:
            current->type |= ORL_SYM_TYPE_ABSOLUTE;
            break;
        case SHN_COMMON:
            current->type |= ORL_SYM_TYPE_COMMON;
            break;
        case SHN_UNDEF:
            current->type |= ORL_SYM_TYPE_UNDEFINED;
            break;
        }
        current++;
        current_sym += elf_sec_hnd->entsize;
    }
    return( ORL_OKAY );
}
Пример #3
0
Sym_table *
elf_symbols(Environ *e, uByte *load, uInt loadlen)
{
	Elf32_Ehdr *hdr = (Elf32_Ehdr*)load;
	Elf32_Shdr *shdr;
	Elf32_Shdr *symtab = NULL;
	Elf32_Shdr *strhdr = NULL;
	char *strtab;
	int i = 0;
	int num, nsyms;
	char *strs;
	Elf32_Sym *syms, *s;
	Sym_table *tab;

	if (!elf_is_exec(e, load, loadlen))		/* sanity check */
		return NULL;

	shdr = (Elf32_Shdr*)(load + hdr->e_shoff);
	strtab = (char*)load + shdr[hdr->e_shstrndx].sh_offset;

	for (i = 0; i < hdr->e_shnum; i++)
	{
		if (strcmp(strtab + shdr[i].sh_name, ELF_SYMTAB) == 0)
			symtab = shdr + i;
		else if (strcmp(strtab + shdr[i].sh_name, ELF_STRTAB) == 0)
			strhdr = shdr + i;
	}

	if (symtab == NULL || strhdr == NULL)
		return NULL;

	if (symtab->sh_entsize != sizeof *syms)
		return NULL;

	strs = (char*)load + strhdr->sh_offset;
	s = syms = (Elf32_Sym*)(load + symtab->sh_offset);
	nsyms = symtab->sh_size / sizeof *syms;
	num = 0;

	/* first count the number of symbols we are interested in */
	for (i = 0; i < nsyms; i++, s++)
	{
		if ((ELF32_ST_BIND(s->st_info) == STB_GLOBAL ||
				ELF32_ST_BIND(s->st_info) == STB_LOCAL) &&
				(ELF32_ST_TYPE(s->st_info) == STT_OBJECT ||
				ELF32_ST_TYPE(s->st_info) == STT_FUNC))
			num++;
	}

	/* allocate space for the symbols */
	tab = (Sym_table*)malloc(sizeof *tab);

	if (tab == NULL)
		return NULL;

	memset(tab, 0, sizeof *tab);
	tab->list = (Sym_ent*)malloc(sizeof *tab->list * num);

	if (tab->list == NULL)
	{
		free(tab);
		return NULL;
	}

	tab->num = num;
	num = 0;
	s = syms = (Elf32_Sym*)(load + symtab->sh_offset);

	/* and load the table */
	for (i = 0; i < nsyms; i++, s++)
	{
		if ((ELF32_ST_BIND(s->st_info) == STB_GLOBAL ||
				ELF32_ST_BIND(s->st_info) == STB_LOCAL) &&
				(ELF32_ST_TYPE(s->st_info) == STT_OBJECT ||
				ELF32_ST_TYPE(s->st_info) == STT_FUNC))
		{
			tab->list[num].name = cstrdup(strs + s->st_name);
			tab->list[num].addr = s->st_value;
			tab->list[num].type = ELF32_ST_TYPE(s->st_info) == STT_FUNC ?
					SYM_TEXT : SYM_DATA;
			DPRINTF(("tab %d: name=%P addr=%#x type=%#x\n", num,
					tab->list[num].name,
					tab->list[num].addr, tab->list[num].type));
			num++;
		}
	}

	return tab;
}
Пример #4
0
void *MemoryUtils::ResolveSymbol(void *handle, const char *symbol)
{
#if defined(WIN32)

	return GetProcAddress((HMODULE)handle, symbol);
	
#elif defined(__linux__)

	void *address = dlsym(handle, symbol);
	
	if (address != NULL)
	{
		return address;
	}

	struct link_map *dlmap;
	struct stat dlstat;
	int dlfile;
	uintptr_t map_base;
	Elf32_Ehdr *file_hdr;
	Elf32_Shdr *sections, *shstrtab_hdr, *symtab_hdr, *strtab_hdr;
	Elf32_Sym *symtab;
	const char *shstrtab, *strtab;
	uint16_t section_count;
	uint32_t symbol_count;
	LibSymbolTable *libtable;
	SymbolTable *table;
	Symbol *symbol_entry;

	dlmap = (struct link_map *)handle;
	symtab_hdr = NULL;
	strtab_hdr = NULL;
	table = NULL;
	
	/* See if we already have a symbol table for this library */
	for (size_t i = 0; i < m_SymTables.length(); i++)
	{
		libtable = m_SymTables[i];
		if (libtable->lib_base == dlmap->l_addr)
		{
			table = &libtable->table;
			break;
		}
	}

	/* If we don't have a symbol table for this library, then create one */
	if (table == NULL)
	{
		libtable = new LibSymbolTable();
		libtable->table.Initialize();
		libtable->lib_base = dlmap->l_addr;
		libtable->last_pos = 0;
		table = &libtable->table;
		m_SymTables.append(libtable);
	}

	/* See if the symbol is already cached in our table */
	symbol_entry = table->FindSymbol(symbol, strlen(symbol));
	if (symbol_entry != NULL)
	{
		return symbol_entry->address;
	}

	/* If symbol isn't in our table, then we have open the actual library */
	dlfile = open(dlmap->l_name, O_RDONLY);
	if (dlfile == -1 || fstat(dlfile, &dlstat) == -1)
	{
		close(dlfile);
		return NULL;
	}

	/* Map library file into memory */
	file_hdr = (Elf32_Ehdr *)mmap(NULL, dlstat.st_size, PROT_READ, MAP_PRIVATE, dlfile, 0);
	map_base = (uintptr_t)file_hdr;
	if (file_hdr == MAP_FAILED)
	{
		close(dlfile);
		return NULL;
	}
	close(dlfile);

	if (file_hdr->e_shoff == 0 || file_hdr->e_shstrndx == SHN_UNDEF)
	{
		munmap(file_hdr, dlstat.st_size);
		return NULL;
	}

	sections = (Elf32_Shdr *)(map_base + file_hdr->e_shoff);
	section_count = file_hdr->e_shnum;
	/* Get ELF section header string table */
	shstrtab_hdr = &sections[file_hdr->e_shstrndx];
	shstrtab = (const char *)(map_base + shstrtab_hdr->sh_offset);

	/* Iterate sections while looking for ELF symbol table and string table */
	for (uint16_t i = 0; i < section_count; i++)
	{
		Elf32_Shdr &hdr = sections[i];
		const char *section_name = shstrtab + hdr.sh_name;

		if (strcmp(section_name, ".symtab") == 0)
		{
			symtab_hdr = &hdr;
		}
		else if (strcmp(section_name, ".strtab") == 0)
		{
			strtab_hdr = &hdr;
		}
	}

	/* Uh oh, we don't have a symbol table or a string table */
	if (symtab_hdr == NULL || strtab_hdr == NULL)
	{
		munmap(file_hdr, dlstat.st_size);
		return NULL;
	}

	symtab = (Elf32_Sym *)(map_base + symtab_hdr->sh_offset);
	strtab = (const char *)(map_base + strtab_hdr->sh_offset);
	symbol_count = symtab_hdr->sh_size / symtab_hdr->sh_entsize;

	/* Iterate symbol table starting from the position we were at last time */
	for (uint32_t i = libtable->last_pos; i < symbol_count; i++)
	{
		Elf32_Sym &sym = symtab[i];
		unsigned char sym_type = ELF32_ST_TYPE(sym.st_info);
		const char *sym_name = strtab + sym.st_name;
		Symbol *cur_sym;

		/* Skip symbols that are undefined or do not refer to functions or objects */
		if (sym.st_shndx == SHN_UNDEF || (sym_type != STT_FUNC && sym_type != STT_OBJECT))
		{
			continue;
		}

		/* Caching symbols as we go along */
		cur_sym = table->InternSymbol(sym_name, strlen(sym_name), (void *)(dlmap->l_addr + sym.st_value));
		if (strcmp(symbol, sym_name) == 0)
		{
			symbol_entry = cur_sym;
			libtable->last_pos = ++i;
			break;
		}
	}

	munmap(file_hdr, dlstat.st_size);
	return symbol_entry ? symbol_entry->address : NULL;

#elif defined(__APPLE__)
	
	uintptr_t dlbase, linkedit_addr;
	uint32_t image_count;
	struct mach_header *file_hdr;
	struct load_command *loadcmds;
	struct segment_command *linkedit_hdr;
	struct symtab_command *symtab_hdr;
	struct nlist *symtab;
	const char *strtab;
	uint32_t loadcmd_count;
	uint32_t symbol_count;
	LibSymbolTable *libtable;
	SymbolTable *table;
	Symbol *symbol_entry;
	
	dlbase = 0;
	image_count = m_ImageList->infoArrayCount;
	linkedit_hdr = NULL;
	symtab_hdr = NULL;
	table = NULL;
	
	/* Loop through mach-o images in process.
	 * We can skip index 0 since that is just the executable.
	 */
	for (uint32_t i = 1; i < image_count; i++)
	{
		const struct dyld_image_info &info = m_ImageList->infoArray[i];
		
		/* "Load" each one until we get a matching handle */
		void *h = dlopen(info.imageFilePath, RTLD_NOLOAD);
		if (h == handle)
		{
			dlbase = (uintptr_t)info.imageLoadAddress;
			dlclose(h);
			break;
		}
		
		dlclose(h);
	}
	
	if (!dlbase)
	{
		/* Uh oh, we couldn't find a matching handle */
		return NULL;
	}
	
	/* See if we already have a symbol table for this library */
	for (size_t i = 0; i < m_SymTables.length(); i++)
	{
		libtable = m_SymTables[i];
		if (libtable->lib_base == dlbase)
		{
			table = &libtable->table;
			break;
		}
	}
	
	/* If we don't have a symbol table for this library, then create one */
	if (table == NULL)
	{
		libtable = new LibSymbolTable();
		libtable->table.Initialize();
		libtable->lib_base = dlbase;
		libtable->last_pos = 0;
		table = &libtable->table;
		m_SymTables.append(libtable);
	}
	
	/* See if the symbol is already cached in our table */
	symbol_entry = table->FindSymbol(symbol, strlen(symbol));
	if (symbol_entry != NULL)
	{
		return symbol_entry->address;
	}
	
	/* If symbol isn't in our table, then we have to locate it in memory */
	
	file_hdr = (struct mach_header *)dlbase;
	loadcmds = (struct load_command *)(dlbase + sizeof(struct mach_header));
	loadcmd_count = file_hdr->ncmds;
	
	/* Loop through load commands until we find the ones for the symbol table */
	for (uint32_t i = 0; i < loadcmd_count; i++)
	{
		if (loadcmds->cmd == LC_SEGMENT && !linkedit_hdr)
		{
			struct segment_command *seg = (struct segment_command *)loadcmds;
			if (strcmp(seg->segname, "__LINKEDIT") == 0)
			{
				linkedit_hdr = seg;
				if (symtab_hdr)
				{
					break;
				}
			}
		}
		else if (loadcmds->cmd == LC_SYMTAB)
		{
			symtab_hdr = (struct symtab_command *)loadcmds;
			if (linkedit_hdr)
			{
				break;
			}
		}

		/* Load commands are not of a fixed size which is why we add the size */
		loadcmds = (struct load_command *)((uintptr_t)loadcmds + loadcmds->cmdsize);
	}
	
	if (!linkedit_hdr || !symtab_hdr || !symtab_hdr->symoff || !symtab_hdr->stroff)
	{
		/* Uh oh, no symbol table */
		return NULL;
	}

	linkedit_addr = dlbase + linkedit_hdr->vmaddr;
	symtab = (struct nlist *)(linkedit_addr + symtab_hdr->symoff - linkedit_hdr->fileoff);
	strtab = (const char *)(linkedit_addr + symtab_hdr->stroff - linkedit_hdr->fileoff);
	symbol_count = symtab_hdr->nsyms;
	
	/* Iterate symbol table starting from the position we were at last time */
	for (uint32_t i = libtable->last_pos; i < symbol_count; i++)
	{
		struct nlist &sym = symtab[i];
		/* Ignore the prepended underscore on all symbols, so +1 here */
		const char *sym_name = strtab + sym.n_un.n_strx + 1;
		Symbol *cur_sym;
		
		/* Skip symbols that are undefined */
		if (sym.n_sect == NO_SECT)
		{
			continue;
		}
		
		/* Caching symbols as we go along */
		cur_sym = table->InternSymbol(sym_name, strlen(sym_name), (void *)(dlbase + sym.n_value));
		if (strcmp(symbol, sym_name) == 0)
		{
			symbol_entry = cur_sym;
			libtable->last_pos = ++i;
			break;
		}
	}
	
	return symbol_entry ? symbol_entry->address : NULL;

#endif
}
Пример #5
0
GElf_Sym *
gelf_getsym(Elf_Data *ed, int ndx, GElf_Sym *dst)
{
	int ec;
	Elf *e;
	size_t msz;
	Elf_Scn *scn;
	uint32_t sh_type;
	Elf32_Sym *sym32;
	Elf64_Sym *sym64;
	struct _Libelf_Data *d;

	d = (struct _Libelf_Data *) ed;

	if (d == NULL || ndx < 0 || dst == NULL ||
	    (scn = d->d_scn) == NULL ||
	    (e = scn->s_elf) == NULL) {
		LIBELF_SET_ERROR(ARGUMENT, 0);
		return (NULL);
	}

	ec = e->e_class;
	assert(ec == ELFCLASS32 || ec == ELFCLASS64);

	if (ec == ELFCLASS32)
		sh_type = scn->s_shdr.s_shdr32.sh_type;
	else
		sh_type = scn->s_shdr.s_shdr64.sh_type;

	if (_libelf_xlate_shtype(sh_type) != ELF_T_SYM) {
		LIBELF_SET_ERROR(ARGUMENT, 0);
		return (NULL);
	}

	msz = _libelf_msize(ELF_T_SYM, ec, e->e_version);

	assert(msz > 0);

	if (msz * ndx >= d->d_data.d_size) {
		LIBELF_SET_ERROR(ARGUMENT, 0);
		return (NULL);
	}

	if (ec == ELFCLASS32) {

		sym32 = (Elf32_Sym *) d->d_data.d_buf + ndx;

		dst->st_name  = sym32->st_name;
		dst->st_value = (Elf64_Addr) sym32->st_value;
		dst->st_size  = (Elf64_Xword) sym32->st_size;
		dst->st_info  = ELF64_ST_INFO(ELF32_ST_BIND(sym32->st_info),
		    ELF32_ST_TYPE(sym32->st_info));
		dst->st_other = sym32->st_other;
		dst->st_shndx = sym32->st_shndx;
	} else {

		sym64 = (Elf64_Sym *) d->d_data.d_buf + ndx;

		*dst = *sym64;
	}

	return (dst);
}