Exemple #1
0
/*
 * Given a symbol index, look up the corresponding symbol from the
 * given symbol table.
 *
 * This function allows the caller to treat the symbol table as a single
 * logical entity even though there may be 2 actual ELF symbol tables
 * involved. See the comments in Pcontrol.h for details.
 */
static GElf_Sym *
symtab_getsym(sym_tbl_t *symtab, int ndx, GElf_Sym *dst)
{
	/* If index is in range of primary symtab, look it up there */
	if (ndx >= symtab->st_symn_aux) {
		return (gelf_getsym(symtab->st_syms_pri,
		    ndx - symtab->st_symn_aux, dst));
	}

	/* Not in primary: Look it up in the auxiliary symtab */
	return (gelf_getsym(symtab->st_syms_aux, ndx, dst));
}
Exemple #2
0
void symtab_elf_foreach(library_info_t *lib, void (*callback)(const symbol_t *))
{
	for (int i = 0; i < lib->elf_symtab_count; ++i) {
		GElf_Sym sym;
		gelf_getsym(lib->elf_symtab_data, i, &sym);
		//if (ELF32_ST_TYPE(sym.st_info) != type) {
		//	continue;
		//}
		symbol_t entry = {
			.lib  = lib,
			.addr = sym.st_value,
			.size = sym.st_size,
			.name = elf_strptr(lib->elf,
				lib->elf_symtab_shdr.sh_link, sym.st_name),
			.name_demangled = try_demangle_noprefix(entry.name),
		};
		callback(&entry);
	}
}


bool symtab_elf_lookup_addr(library_info_t *lib, symbol_t *entry,
	uintptr_t addr)
{
	for (int i = 0; i < lib->elf_symtab_count; ++i) {
		GElf_Sym sym;
		gelf_getsym(lib->elf_symtab_data, i, &sym);
		
		//if (ELF32_ST_TYPE(sym.st_info) != type) {
		//	continue;
		//}
		
		if (sym.st_value == addr) {
			entry->lib  = lib;
			entry->addr = sym.st_value;
			entry->size = sym.st_size;
			entry->name = elf_strptr(lib->elf,
				lib->elf_symtab_shdr.sh_link, sym.st_name);
			entry->name_demangled = try_demangle_noprefix(entry->name);
			
			return true;
		}
		
		/*fprintf(stderr,
			"val %08x size %8x bind %2d type %2d name '%s'\n",
			val, size, bind, type,
			elf_strptr(lib->elf, shdr.sh_link, sym.st_name));*/
	}
	
	return false;
}
static void
_dwarf_elf_apply_reloc(Dwarf_Debug dbg, void *buf, Elf_Data *rel_data,
    Elf_Data *symtab_data, int endian)
{
	Dwarf_Unsigned type;
	GElf_Rela rela;
	GElf_Sym sym;
	size_t symndx;
	uint64_t offset;
	int size, j;

	j = 0;
	while (gelf_getrela(rel_data, j++, &rela) != NULL) {
		symndx = GELF_R_SYM(rela.r_info);
		type = GELF_R_TYPE(rela.r_info);

		if (gelf_getsym(symtab_data, symndx, &sym) == NULL)
			continue;

		offset = rela.r_offset;
		size = _dwarf_get_reloc_size(dbg, type);

		if (endian == ELFDATA2MSB)
			_dwarf_write_msb(buf, &offset, rela.r_addend, size);
		else
			_dwarf_write_lsb(buf, &offset, rela.r_addend, size);
	}
}
static void
_dwarf_elf_write_reloc(Dwarf_Debug dbg, Elf_Data *symtab_data, int endian,
    void *buf, uint64_t offset, GElf_Xword r_info, GElf_Sxword r_addend,
    int is_rel)
{
	GElf_Sym sym;
	int size;

	if (gelf_getsym(symtab_data, GELF_R_SYM(r_info), &sym) == NULL)
		return;
	if ((size = _dwarf_get_reloc_size(dbg, GELF_R_TYPE(r_info))) == 0)
		return; /* Unknown or non-absolute relocation. */
	if (is_rel) {
		uint64_t roffset = offset;

		if (endian == ELFDATA2MSB)
			r_addend = _dwarf_read_msb(buf, &roffset, size);
		else
			r_addend = _dwarf_read_lsb(buf, &roffset, size);
	}
	if (endian == ELFDATA2MSB)
		_dwarf_write_msb(buf, &offset, sym.st_value + r_addend, size);
	else
		_dwarf_write_lsb(buf, &offset, sym.st_value + r_addend, size);
}
Exemple #5
0
static arch_addr_t _find_solib_break(struct mt_elf *mte, Elf_Data *symtab, const char *strtab, size_t size)
{
	size_t i;
	unsigned int j;

	static const char * const solib_break_names[] =
	{
		"r_debug_state",
		"_r_debug_state",
		"_dl_debug_state",
		"rtld_db_dlactivity",
		"__dl_rtld_db_dlactivity",
		"_rtld_debug_state"
	};

	for (i = 0; i < size; ++i) {
		GElf_Sym sym;

		if (gelf_getsym(symtab, i, &sym) == NULL) {
			fprintf(stderr, "couldn't get symbol #%zd from %s: %s\n", i, mte->filename, elf_errmsg(-1));
			continue;
		}

		if (GELF_ST_TYPE(sym.st_info) != STT_FUNC || sym.st_value == 0 || sym.st_shndx == STN_UNDEF)
			continue;

		const char *name = strtab + sym.st_name;

		for(j = 0; j < ARRAY_SIZE(solib_break_names); j++) {
			if (!strcmp(name, solib_break_names[j]))
				return ARCH_ADDR_T(sym.st_value + mte->bias);
		}
	}
	return ARCH_ADDR_T(0);
}
/**
 * @brief Search a single, particular ELF symbol table for a named symbol
 *
 * @param elf The open ELF object
 * @param symtab The ELF symbol table section
 * @param name The symbol name to find
 *
 * @returns The address to which the symbol points, 0 otherwise.
 */
static GElf_Addr elf_scn_getsymaddr_byname(Elf *elf, Elf_Scn *symtab,
                                           const char * name) {
    GElf_Shdr shdr;
    Elf_Data *data;
    uint32_t syms, i;
    GElf_Sym sym;

    if (gelf_getshdr(symtab, &shdr) == NULL || shdr.sh_type != SHT_SYMTAB) {
        return 0;
    }

    data = elf_getdata(symtab, NULL);
    if (data == NULL) {
        return 0;
    }

    syms = shdr.sh_size / shdr.sh_entsize;

    for(i=0; i<syms; i++) {
        gelf_getsym(data, i, &sym);
        if (strcmp(elf_strptr(elf, shdr.sh_link, sym.st_name), name) == 0) {
            return sym.st_value;
        }
    }

    return 0;
}
Exemple #7
0
static void readSymbols(Elf *e, Elf_Scn *scn, const GElf_Shdr &shdr,
                        unsigned low, unsigned high,
                        std::auto_ptr<CoreSymbolInfo> &SI)
{
  Elf_Data *data = elf_getdata(scn, NULL);
  if (data == NULL) {
    return;
  }
  unsigned count = shdr.sh_size / shdr.sh_entsize;

  CoreSymbolInfoBuilder builder;

  for (unsigned i = 0; i < count; i++) {
    GElf_Sym sym;
    if (gelf_getsym(data, i, &sym) == NULL) {
      continue;
    }
    if (sym.st_shndx == SHN_ABS)
      continue;
    if (sym.st_value < low || sym.st_value >= high)
      continue;
    builder.addSymbol(elf_strptr(e, shdr.sh_link, sym.st_name),
                      sym.st_value,
                      sym.st_info);
  }
  SI = builder.getSymbolInfo();
}
Exemple #8
0
static void parse_relocs(Elf *elf, Elf_Data *relocs, Elf_Data *symbols,
			unsigned symbol_sh_link,
			struct radeon_shader_binary *binary)
{
	unsigned i;

	if (!relocs || !symbols || !binary->reloc_count) {
		return;
	}
	binary->relocs = CALLOC(binary->reloc_count,
			sizeof(struct radeon_shader_reloc));
	for (i = 0; i < binary->reloc_count; i++) {
		GElf_Sym symbol;
		GElf_Rel rel;
		char *symbol_name;
		struct radeon_shader_reloc *reloc = &binary->relocs[i];

		gelf_getrel(relocs, i, &rel);
		gelf_getsym(symbols, GELF_R_SYM(rel.r_info), &symbol);
		symbol_name = elf_strptr(elf, symbol_sh_link, symbol.st_name);

		reloc->offset = rel.r_offset;
		reloc->name = strdup(symbol_name);
	}
}
Exemple #9
0
/*
 * Given the current symbol index (-1 to start at the beginning of the symbol
 * table) and the type of symbol to match, this function returns the index of
 * the next matching symbol (if any), and places the name of that symbol in
 * *namep.  If no symbol is found, -1 is returned.
 */
static int
next_sym(const ctf_data_t *cd, const int symidx, const uchar_t matchtype,
    char **namep)
{
	int i;

	for (i = symidx + 1; i < cd->cd_nsyms; i++) {
		GElf_Sym sym;
		char *name;
		int type;

		if (gelf_getsym(cd->cd_symdata, i, &sym) == 0)
			return (-1);

		name = (char *)cd->cd_strdata->d_buf + sym.st_name;
		type = GELF_ST_TYPE(sym.st_info);

		/*
		 * Skip various types of symbol table entries.
		 */
		if (type != matchtype || ignore_symbol(&sym, name))
			continue;

		/* Found one */
		*namep = name;
		return (i);
	}

	return (-1);
}
Exemple #10
0
/*
 * MIPS doesn't have traditional got.plt entries with corresponding
 * relocations.
 *
 * sym_index is an offset into the external GOT entries. Filter out
 * stuff that are not functions.
 */
int
arch_get_sym_info(struct ltelf *lte, const char *filename,
		  size_t sym_index, GElf_Rela *rela, GElf_Sym *sym)
{
	const char *name;

	if (mips_elf_is_cpic(lte->ehdr.e_flags)) {
		return elf_get_sym_info(lte, filename, sym_index, rela, sym);
	}

	/* Fixup the offset.  */
	sym_index += lte->arch.mips_gotsym;

	if (gelf_getsym(lte->dynsym, sym_index, sym) == NULL){
		error(EXIT_FAILURE, 0,
			"Couldn't get relocation from \"%s\"", filename);
	}

	name = lte->dynstr + sym->st_name;
	if (ELF64_ST_TYPE(sym->st_info) != STT_FUNC) {
		debug(2, "sym %s not a function", name);
		return -1;
	}

	return 0;
}
Exemple #11
0
/*
 * Look up the symbol at addr, returning a copy of the symbol and its name.
 */
static int
lookup_addr(Elf *e, Elf_Scn *scn, u_long stridx, uintptr_t off, uintptr_t addr,
    const char **name, GElf_Sym *symcopy)
{
	GElf_Sym sym;
	Elf_Data *data;
	const char *s;
	uint64_t rsym;
	int i;

	if ((data = elf_getdata(scn, NULL)) == NULL) {
		DPRINTFX("ERROR: elf_getdata() failed: %s", elf_errmsg(-1));
		return (1);
	}
	for (i = 0; gelf_getsym(data, i, &sym) != NULL; i++) {
		rsym = off + sym.st_value;
		if (addr >= rsym && addr < rsym + sym.st_size) {
			s = elf_strptr(e, stridx, sym.st_name);
			if (s != NULL) {
				*name = s;
				memcpy(symcopy, &sym, sizeof(*symcopy));
				/*
				 * DTrace expects the st_value to contain
				 * only the address relative to the start of
				 * the function.
				 */
				symcopy->st_value = rsym;
				return (0);
			}
		}
	}
	return (1);
}
Exemple #12
0
/* Below code adapted from libelf tutorial example */
static u32 extract_functions_internal (const char *str, func_entry *func_list) {
    Elf *e;
    Elf_Kind ek;
    Elf_Scn *scn;
    Elf_Data *edata;
    u32 fd, i, symbol_count;
    GElf_Sym sym;
    GElf_Shdr shdr;
    u32 func_count = 0;

    if(elf_version(EV_CURRENT) == EV_NONE) {
        printf("Error initializing ELF: %s\n", elf_errmsg(-1));
        return -1;
    }

    if ((fd = open(str, O_RDONLY, 0)) < 0) {
        printf("Unable to open %s\n", str);
        return -1;
    }

    if ((e = elf_begin(fd, ELF_C_READ, NULL)) == NULL) {
        printf("elf_begin failed: %s\n", elf_errmsg(-1));
    }

    ek = elf_kind(e);
    if(ek != ELF_K_ELF) {
        printf("not an ELF object");
    } else {
        scn = NULL;
        edata = NULL;
        while((scn = elf_nextscn(e, scn)) != NULL) {
            gelf_getshdr(scn, &shdr);
            if(shdr.sh_type == SHT_SYMTAB) {
                edata = elf_getdata(scn, edata);
                symbol_count = shdr.sh_size / shdr.sh_entsize;
                for(i = 0; i < symbol_count; i++) {
                    gelf_getsym(edata, i, &sym);
                    if(ELF32_ST_TYPE(sym.st_info) != STT_FUNC) {
                        check_for_end_marker(elf_strptr(e, shdr.sh_link, sym.st_name), sym.st_value);
                        continue;
                    }
                    if(sym.st_size == 0) continue;

                    func_list[func_count].offset = sym.st_value;
                    func_list[func_count++].func_name = strdup(elf_strptr(e, shdr.sh_link, sym.st_name));

                    if(func_count >= MAXFNS) {
                        printf("Func limit (%"PRId32") reached, please increase MAXFNS & rebuild\n", MAXFNS);
                        raise(SIGABRT);
                    }
                    //                    printf("%08x %08x\t%s\n", sym.st_value, sym.st_size, elf_strptr(e, shdr.sh_link, sym.st_name));
                }
            }
        }
    }

    elf_end(e);
    close(fd);
    return func_count;
}
Exemple #13
0
static int parse_relo_and_apply(Elf_Data *data, Elf_Data *symbols,
				GElf_Shdr *shdr, struct bpf_insn *insn)
{
	int i, nrels;

	nrels = shdr->sh_size / shdr->sh_entsize;

	for (i = 0; i < nrels; i++) {
		GElf_Sym sym;
		GElf_Rel rel;
		unsigned int insn_idx;

		gelf_getrel(data, i, &rel);

		insn_idx = rel.r_offset / sizeof(struct bpf_insn);

		gelf_getsym(symbols, GELF_R_SYM(rel.r_info), &sym);

		if (insn[insn_idx].code != (BPF_LD | BPF_IMM | BPF_DW)) {
			printf("invalid relo for insn[%d].code 0x%x\n",
			       insn_idx, insn[insn_idx].code);
			return 1;
		}
		insn[insn_idx].src_reg = BPF_PSEUDO_MAP_FD;
		insn[insn_idx].imm = map_fd[sym.st_value / sizeof(struct bpf_map_def)];
	}

	return 0;
}
Exemple #14
0
map_s *elf_set_breakpoints(proc_s *proc)
{
    elf_info_s *elf = elf_symbols(proc->fd);
    map_s *brkp = map_init(32, cmp_addr);
    for (size_t i = 0; i < elf->replt_count; ++i) {
        void *ret;
        GElf_Rel rel;
        GElf_Rela rela;
        const char *name;
        GElf_Sym sym;
        GElf_Addr addr;
        /* local relocation entries */
        if (elf->replt->d_type == ELF_T_REL) {
            ret = gelf_getrel(elf->replt, i, &rel);
            rela.r_offset = rel.r_offset;
            rela.r_info = rel.r_info;
            rela.r_addend = 0;
        }
        /* external relocation entries */
        else
            ret = gelf_getrela(elf->replt, i, &rela);

        gelf_getsym(elf->dynsym, ELF64_R_SYM(rela.r_info), &sym);

        name = elf->dynstr + sym.st_name;
        addr = elf->plt_addr + (i + 1) * 16;
        breakpoint_create(brkp, addr, name, proc->pid);
    }
    return brkp;
}
Exemple #15
0
GElf_Sym *
gelf_getsymshndx(Elf_Data *d, Elf_Data *id, int ndx, GElf_Sym *dst,
    Elf32_Word *shindex)
{
	int ec;
	Elf *e;
	size_t msz;
	Elf_Scn *scn;
	uint32_t sh_type;
	struct _Libelf_Data *ld, *lid;

	ld = (struct _Libelf_Data *) d;
	lid = (struct _Libelf_Data *) id;

	if (gelf_getsym(d, ndx, dst) == 0)
		return (NULL);

	if (lid == NULL || (scn = lid->d_scn) == NULL ||
	    (e = scn->s_elf) == NULL || (e != ld->d_scn->s_elf) ||
	    shindex == 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_WORD ||
	   id->d_type != ELF_T_WORD) {
		LIBELF_SET_ERROR(ARGUMENT, 0);
		return (NULL);
	}

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

	assert(msz > 0);
	assert(ndx >= 0);

	if (msz * (size_t) ndx >= id->d_size) {
		LIBELF_SET_ERROR(ARGUMENT, 0);
		return (NULL);
	}

	*shindex = ((Elf32_Word *) id->d_buf)[ndx];

	return (dst);
}
Exemple #16
0
static int populate_this_symtab(struct mt_elf *mte, struct libref *libref, Elf_Data *symtab, const char *strtab, size_t size)
{
	size_t i;

	for (i = 0; i < size; ++i) {
		GElf_Sym sym;

		if (gelf_getsym(symtab, i, &sym) == NULL) {
			fprintf(stderr, "couldn't get symbol #%zd from %s: %s\n", i, mte->filename, elf_errmsg(-1));
			continue;
		}

		if (GELF_ST_TYPE(sym.st_info) != STT_FUNC || sym.st_value == 0 || sym.st_shndx == STN_UNDEF)
			continue;

		/* Find symbol name and snip version. */
		const char *orig_name = strtab + sym.st_name;
		const char *version = strchr(orig_name, '@');
		size_t len = version ? (size_t)(version - orig_name) : strlen(orig_name);
		char name[len + 1];

		memcpy(name, orig_name, len);
		name[len] = 0;

		/* If the symbol is not matched, skip it. */
		const struct function *func = flist_matches_symbol(name);
		if (!func)
			continue;

		arch_addr_t addr = ARCH_ADDR_T(sym.st_value + mte->bias);

		struct library_symbol *libsym = library_find_symbol(libref, addr);
		if (!libsym) {
			struct library_symbol *libsym = library_symbol_new(libref, addr, func);

			if (!libsym) {
				fprintf(stderr, "couldn't init symbol: %s%s\n", name, func->name);
				continue;
			}
		}
		else {
			/* handle symbol alias */
			if (libsym->func->level > func->level)
				libsym->func = func;
		}
		if (unlikely(options.verbose > 1))
			fprintf(stderr, "breakpoint for %s:%s at %#lx\n", libref->filename, func->demangled_name, addr);
	}

	return 0;
}
Exemple #17
0
static GElf_Sym FindSymbol(Elf *e, const char *name) {
    auto sym_scn = FindSectionByType(e, SHT_SYMTAB);
    auto sym_data = elf_getdata(sym_scn.first, nullptr);
    auto num_syms = sym_scn.second.sh_size / sym_scn.second.sh_entsize;
    for (size_t i = 0; i < num_syms; i++) {
        GElf_Sym sym;
        gelf_getsym(sym_data, i, &sym);
        auto sym_name = elf_strptr(e, sym_scn.second.sh_link, sym.st_name);
        if (strcmp(sym_name, name) == 0)
            return sym;
    }
    errx(EX_SOFTWARE, "Binary does not contain symbol:%s", name);
    return GElf_Sym();
}
Exemple #18
0
static void parse_symbol_table(Elf_Data *symbol_table_data,
				const GElf_Shdr *symbol_table_header,
				struct radeon_shader_binary *binary)
{
	GElf_Sym symbol;
	unsigned i = 0;
	unsigned symbol_count =
		symbol_table_header->sh_size / symbol_table_header->sh_entsize;

	/* We are over allocating this list, because symbol_count gives the
 	 * total number of symbols, and we will only be filling the list
 	 * with offsets of global symbols.  The memory savings from
 	 * allocating the correct size of this list will be small, and
 	 * I don't think it is worth the cost of pre-computing the number
 	 * of global symbols.
 	 */
	binary->global_symbol_offsets = CALLOC(symbol_count, sizeof(uint64_t));

	while (gelf_getsym(symbol_table_data, i++, &symbol)) {
		unsigned i;
		if (GELF_ST_BIND(symbol.st_info) != STB_GLOBAL ||
		    symbol.st_shndx == 0 /* Undefined symbol */) {
			continue;
		}

		binary->global_symbol_offsets[binary->global_symbol_count] =
					symbol.st_value;

		/* Sort the list using bubble sort.  This list will usually
		 * be small. */
		for (i = binary->global_symbol_count; i > 0; --i) {
			uint64_t lhs = binary->global_symbol_offsets[i - 1];
			uint64_t rhs = binary->global_symbol_offsets[i];
			if (lhs < rhs) {
				break;
			}
			binary->global_symbol_offsets[i] = lhs;
			binary->global_symbol_offsets[i - 1] = rhs;
		}
		++binary->global_symbol_count;
	}
}
Exemple #19
0
static int
symbol_matches(struct ltelf *lte, size_t lte_i, GElf_Sym *sym,
	       size_t symidx, const char *name)
{
	GElf_Sym tmp_sym;
	GElf_Sym *tmp;

	tmp = (sym) ? (sym) : (&tmp_sym);

	if (gelf_getsym(lte[lte_i].dynsym, symidx, tmp) == NULL)
		error(EXIT_FAILURE, 0, "Couldn't get symbol from .dynsym");
	else {
		tmp->st_value += lte[lte_i].base_addr;
		debug(2, "symbol found: %s, %zd, %#" PRIx64,
		      name, lte_i, tmp->st_value);
	}
	return tmp->st_value != 0
		&& tmp->st_shndx != SHN_UNDEF
		&& strcmp(name, lte[lte_i].dynstr + tmp->st_name) == 0;
}
Exemple #20
0
static int
bpf_object__init_maps_name(struct bpf_object *obj)
{
	int i;
	Elf_Data *symbols = obj->efile.symbols;

	if (!symbols || obj->efile.maps_shndx < 0)
		return -EINVAL;

	for (i = 0; i < symbols->d_size / sizeof(GElf_Sym); i++) {
		GElf_Sym sym;
		size_t map_idx;
		const char *map_name;

		if (!gelf_getsym(symbols, i, &sym))
			continue;
		if (sym.st_shndx != obj->efile.maps_shndx)
			continue;

		map_name = elf_strptr(obj->efile.elf,
				      obj->efile.strtabidx,
				      sym.st_name);
		map_idx = sym.st_value / sizeof(struct bpf_map_def);
		if (map_idx >= obj->nr_maps) {
			pr_warning("index of map \"%s\" is buggy: %zu > %zu\n",
				   map_name, map_idx, obj->nr_maps);
			continue;
		}
		obj->maps[map_idx].name = strdup(map_name);
		if (!obj->maps[map_idx].name) {
			pr_warning("failed to alloc map name\n");
			return -ENOMEM;
		}
		pr_debug("map %zu is \"%s\"\n", map_idx,
			 obj->maps[map_idx].name);
	}
	return 0;
}
Exemple #21
0
/* Given Elf header, Elf_Scn, and Elf32_Shdr 
 * print out the symbol table 
 */
static _Bool print_symbols(Elf *elf, Elf_Scn *scn, GElf_Shdr *shdr)
{
	Elf_Data *data;
	char *name;
	char *stringName;
	data = 0;
	int number = 0;
	if ((data = elf_getdata(scn, data)) == 0 || data->d_size == 0)
	{
		/* error or no data */
		fprintf(stderr, "Section had no data!\n");
			exit(-1);
	}
	/*now print the symbols*/
	unsigned count = symtab_shdr.sh_size / symtab_shdr.sh_entsize;
	//fprintf(stderr, "Total symbols count: %u\n", count);
	/* now loop through the symbol table and print it*/
	for (unsigned i = 0; i < count; ++i)
	{
		//fprintf(stderr, "Index is %u\n", i);
		GElf_Sym esym;
		GElf_Sym *ret = gelf_getsym(data, i, &esym);
		if (ret == 0) { fprintf(stderr, "Error!\n"); return FALSE; }
		if ((esym.st_value == 0) ||
			(GELF_ST_BIND(esym.st_info)== STB_WEAK) ||
			(GELF_ST_BIND(esym.st_info)== STB_NUM)) 
				continue;
		//fprintf(stderr, "Symbol has strtab offset %zu\n", (size_t)esym.st_name);
		name = elf_strptr(elf, shdr->sh_link, (size_t)esym.st_name);
		if(!name)
		{
			fprintf(stderr,"%s\n",elf_errmsg(elf_errno()));
			exit(-1);
		}
		printf("%d: %s\n", number++, name);
	}
	return TRUE;
}
Exemple #22
0
/*
 * Look up the symbol with the given name and return a copy of it.
 */
static int
lookup_name(Elf *e, Elf_Scn *scn, u_long stridx, const char *symbol,
    GElf_Sym *symcopy, prsyminfo_t *si)
{
	GElf_Sym sym;
	Elf_Data *data;
	char *s;
	int i;

	if ((data = elf_getdata(scn, NULL)) == NULL) {
		DPRINTFX("ERROR: elf_getdata() failed: %s", elf_errmsg(-1));
		return (1);
	}
	for (i = 0; gelf_getsym(data, i, &sym) != NULL; i++) {
		s = elf_strptr(e, stridx, sym.st_name);
		if (s != NULL && strcmp(s, symbol) == 0) {
			memcpy(symcopy, &sym, sizeof(*symcopy));
			if (si != NULL)
				si->prs_id = i;
			return (0);
		}
	}
	return (1);
}
Exemple #23
0
static void
walk_symtab(Elf *elf, char *fname, ctf_file_t *fp,
    void (*callback)(ctf_file_t *, symtab_sym_t *))
{
	Elf_Scn *stab = NULL;
	Elf_Scn *text = NULL;
	Elf_Data *stabdata = NULL;
	Elf_Data *textdata = NULL;
	GElf_Ehdr ehdr;
	GElf_Shdr stabshdr;
	GElf_Shdr textshdr;
	int foundtext = 0, foundstab = 0;
	symtab_sym_t ss;

	if ((gelf_getehdr(elf, &ehdr)) == NULL)
		errx(1, "could not read ELF header from %s\n",
		    fname);

	while ((stab = elf_nextscn(elf, stab)) != NULL) {
		(void) gelf_getshdr(stab, &stabshdr);

		if (stabshdr.sh_type == SHT_SYMTAB) {
			foundstab = 1;
			break;
		}
	}

	while ((text = elf_nextscn(elf, text)) != NULL) {
		(void) gelf_getshdr(text, &textshdr);

		if (strcmp(".text", elf_strptr(elf,
		    ehdr.e_shstrndx, (size_t)textshdr.sh_name)) == 0) {
			foundtext = 1;
			break;
		}
	}

	if (!foundstab || !foundtext)
		return;

	stabdata = elf_getdata(stab, NULL);
	textdata = elf_rawdata(text,  NULL);
	for (unsigned symdx = 0;
	    symdx < (stabshdr.sh_size / stabshdr.sh_entsize);
	    symdx++) {
		(void) gelf_getsym(stabdata, symdx, &ss.ss_sym);

		if ((GELF_ST_TYPE(ss.ss_sym.st_info) != STT_FUNC) ||
		    (ss.ss_sym.st_shndx == SHN_UNDEF))
			continue;

		ss.ss_name = elf_strptr(elf, stabshdr.sh_link,
		    ss.ss_sym.st_name);
		ss.ss_data = ((uint8_t *)(textdata->d_buf)) +
		    (ss.ss_sym.st_value - textshdr.sh_addr);

		if (ctf_func_info(fp, symdx, &ss.ss_finfo) == CTF_ERR) {
			fprintf(stderr, "failed to get funcinfo for: %s\n",
			    ss.ss_name);
			continue;
		}

		(void) callback(fp, &ss);
	}
}
Exemple #24
0
int
proc_name2sym(struct proc_handle *p, const char *object, const char *symbol,
    GElf_Sym *symcopy)
{
	Elf *e;
	Elf_Scn *scn, *dynsymscn = NULL, *symtabscn = NULL;
	Elf_Data *data;
	GElf_Shdr shdr;
	GElf_Sym sym;
	GElf_Ehdr ehdr;
	int fd, error = -1;
	size_t i;
	prmap_t *map;
	char *s;
	unsigned long symtabstridx = 0, dynsymstridx = 0;

	if ((map = proc_name2map(p, object)) == NULL) {
		DPRINTF("ERROR: couldn't find object %s", object);
		goto err0;
	}
	if ((fd = open(map->pr_mapname, O_RDONLY, 0)) < 0) {
		DPRINTF("ERROR: open %s failed", map->pr_mapname);
		goto err0;
	}
	if ((e = elf_begin(fd, ELF_C_READ, NULL)) == NULL) {
		warn("ERROR: elf_begin() failed");
		goto err1;
	}
	if (gelf_getehdr(e, &ehdr) == NULL) {
		warn("ERROR: gelf_getehdr() failed");
		goto err2;
	}
	/*
	 * Find the index of the STRTAB and SYMTAB sections to locate
	 * symbol names.
	 */
	scn = NULL;
	while ((scn = elf_nextscn(e, scn)) != NULL) {
		gelf_getshdr(scn, &shdr);
		switch (shdr.sh_type) {
		case SHT_SYMTAB:
			symtabscn = scn;
			symtabstridx = shdr.sh_link;
			break;
		case SHT_DYNSYM:
			dynsymscn = scn;
			dynsymstridx = shdr.sh_link;
			break;
		default:
			break;
		}
	}
	/*
	 * Iterate over the Dynamic Symbols table to find the symbol.
	 * Then look up the string name in STRTAB (.dynstr)
	 */
	if ((data = elf_getdata(dynsymscn, NULL))) {
		DPRINTF("ERROR: elf_getdata() failed");
		i = 0;
		while (gelf_getsym(data, i++, &sym) != NULL) {
			s = elf_strptr(e, dynsymstridx, sym.st_name);
			if (s && strcmp(s, symbol) == 0) {
				memcpy(symcopy, &sym, sizeof(sym));
				symcopy->st_value = map->pr_vaddr + sym.st_value;
				error = 0;
				goto out;
			}
		}
	}
	/*
	 * Iterate over the Symbols Table to find the symbol.
	 * Then look up the string name in STRTAB (.dynstr)
	 */
	if (symtabscn == NULL)
		goto err2;
	if ((data = elf_getdata(symtabscn, NULL))) {
		i = 0;
		while (gelf_getsym(data, i++, &sym) != NULL) {
			s = elf_strptr(e, symtabstridx, sym.st_name);
			if (s && strcmp(s, symbol) == 0) {
				memcpy(symcopy, &sym, sizeof(sym));
				error = 0;
				goto out;
			}
		}
	}
out:
err2:
	elf_end(e);
err1:
	close(fd);
err0:
	free(map);

	return (error);
}
Exemple #25
0
int
proc_iter_symbyaddr(struct proc_handle *p, const char *object, int which,
    int mask, proc_sym_f *func, void *cd)
{
	Elf *e;
	int i, fd;
	prmap_t *map;
	Elf_Scn *scn, *foundscn = NULL;
	Elf_Data *data;
	GElf_Shdr shdr;
	GElf_Sym sym;
	unsigned long stridx = -1;
	char *s;
	int error = -1;

	if ((map = proc_name2map(p, object)) == NULL)
		return (-1);
	if ((fd = open(map->pr_mapname, O_RDONLY)) < 0) {
		warn("ERROR: open %s failed", map->pr_mapname);
		goto err0;
	}
	if ((e = elf_begin(fd, ELF_C_READ, NULL)) == NULL) {
		warn("ERROR: elf_begin() failed");
		goto err1;
	}
	/*
	 * Find the section we are looking for.
	 */
	scn = NULL;
	while ((scn = elf_nextscn(e, scn)) != NULL) {
		gelf_getshdr(scn, &shdr);
		if (which == PR_SYMTAB && 
		    shdr.sh_type == SHT_SYMTAB) {
			foundscn = scn;
			break;
		} else if (which == PR_DYNSYM &&
		    shdr.sh_type == SHT_DYNSYM) {
			foundscn = scn;
			break;
		}
	}
	if (!foundscn)
		return (-1);
	stridx = shdr.sh_link;
	if ((data = elf_getdata(foundscn, NULL)) == NULL) {
		DPRINTF("ERROR: elf_getdata() failed");
		goto err2;
	}
	i = 0;
	while (gelf_getsym(data, i++, &sym) != NULL) {
		if (GELF_ST_BIND(sym.st_info) == STB_LOCAL &&
		    (mask & BIND_LOCAL) == 0)
			continue;
		if (GELF_ST_BIND(sym.st_info) == STB_GLOBAL &&
		    (mask & BIND_GLOBAL) == 0)
			continue;
		if (GELF_ST_BIND(sym.st_info) == STB_WEAK &&
		    (mask & BIND_WEAK) == 0)
			continue;
		if (GELF_ST_TYPE(sym.st_info) == STT_NOTYPE &&
		    (mask & TYPE_NOTYPE) == 0)
			continue;
		if (GELF_ST_TYPE(sym.st_info) == STT_OBJECT &&
		    (mask & TYPE_OBJECT) == 0)
			continue;
		if (GELF_ST_TYPE(sym.st_info) == STT_FUNC &&
		    (mask & TYPE_FUNC) == 0)
			continue;
		if (GELF_ST_TYPE(sym.st_info) == STT_SECTION &&
		    (mask & TYPE_SECTION) == 0)
			continue;
		if (GELF_ST_TYPE(sym.st_info) == STT_FILE &&
		    (mask & TYPE_FILE) == 0)
			continue;
		s = elf_strptr(e, stridx, sym.st_name);
		sym.st_value += map->pr_vaddr;
		(*func)(cd, &sym, s);
	}
	error = 0;
err2:
	elf_end(e);
err1:
	close(fd);
err0:
	free(map);
	return (error);
}
Exemple #26
0
int
proc_addr2sym(struct proc_handle *p, uintptr_t addr, char *name,
    size_t namesz, GElf_Sym *symcopy)
{
	Elf *e;
	Elf_Scn *scn, *dynsymscn = NULL, *symtabscn = NULL;
	Elf_Data *data;
	GElf_Shdr shdr;
	GElf_Sym sym;
	GElf_Ehdr ehdr;
	int fd, error = -1;
	size_t i;
	uint64_t rsym;
	prmap_t *map;
	char *s;
	unsigned long symtabstridx = 0, dynsymstridx = 0;

	if ((map = proc_addr2map(p, addr)) == NULL)
		return (-1);
	if (!map->pr_mapname || (fd = open(map->pr_mapname, O_RDONLY, 0)) < 0) {
		warn("ERROR: open %s failed", map->pr_mapname);
		goto err0;
	}
	if ((e = elf_begin(fd, ELF_C_READ, NULL)) == NULL) {
		warn("ERROR: elf_begin() failed");
		goto err1;
	}
	if (gelf_getehdr(e, &ehdr) == NULL) {
		warn("ERROR: gelf_getehdr() failed");
		goto err2;
	}
	/*
	 * Find the index of the STRTAB and SYMTAB sections to locate
	 * symbol names.
	 */
	scn = NULL;
	while ((scn = elf_nextscn(e, scn)) != NULL) {
		gelf_getshdr(scn, &shdr);
		switch (shdr.sh_type) {
		case SHT_SYMTAB:
			symtabscn = scn;
			symtabstridx = shdr.sh_link;
			break;
		case SHT_DYNSYM:
			dynsymscn = scn;
			dynsymstridx = shdr.sh_link;
			break;
		default:
			break;
		}
	}
	/*
	 * Iterate over the Dynamic Symbols table to find the symbol.
	 * Then look up the string name in STRTAB (.dynstr)
	 */
	if ((data = elf_getdata(dynsymscn, NULL)) == NULL) {
		DPRINTF("ERROR: elf_getdata() failed");
		goto symtab;
	}
	i = 0;
	while (gelf_getsym(data, i++, &sym) != NULL) {
		/*
		 * Calculate the address mapped to the virtual memory
		 * by rtld.
		 */
		rsym = map->pr_vaddr + sym.st_value;
		if (addr >= rsym && addr <= (rsym + sym.st_size)) {
			s = elf_strptr(e, dynsymstridx, sym.st_name);
			if (s) {
				if (s[0] == '_' && s[1] == 'Z' && s[2])
					demangle(s, name, namesz);
				else
					strlcpy(name, s, namesz);
				memcpy(symcopy, &sym, sizeof(sym));
				/*
				 * DTrace expects the st_value to contain
				 * only the address relative to the start of
				 * the function.
				 */
				symcopy->st_value = rsym;
				error = 0;
				goto out;
			}
		}
	}
symtab:
	/*
	 * Iterate over the Symbols Table to find the symbol.
	 * Then look up the string name in STRTAB (.dynstr)
	 */
	if (symtabscn == NULL)
		goto err2;
	if ((data = elf_getdata(symtabscn, NULL)) == NULL) {
		DPRINTF("ERROR: elf_getdata() failed");
		goto err2;
	}
	i = 0;
	while (gelf_getsym(data, i++, &sym) != NULL) {
		/*
		 * Calculate the address mapped to the virtual memory
		 * by rtld.
		 */
		if (ehdr.e_type != ET_EXEC)
			rsym = map->pr_vaddr + sym.st_value;
		else
			rsym = sym.st_value;
		if (addr >= rsym && addr <= (rsym + sym.st_size)) {
			s = elf_strptr(e, symtabstridx, sym.st_name);
			if (s) {
				if (s[0] == '_' && s[1] == 'Z' && s[2])
					demangle(s, name, namesz);
				else
					strlcpy(name, s, namesz);
				memcpy(symcopy, &sym, sizeof(sym));
				/*
				 * DTrace expects the st_value to contain
				 * only the address relative to the start of
				 * the function.
				 */
				symcopy->st_value = rsym;
				error = 0;
				goto out;
			}
		}
	}
out:
err2:
	elf_end(e);
err1:
	close(fd);
err0:
	free(map);
	return (error);
}
int main(int argc, char *argv[])
{

    int fd; 		// File Descriptor
    char *base_ptr;		// ptr to our object in memory
    char *file = argv[1];	// filename
    struct stat elf_stats;	// fstat struct

    if((fd = open(file, O_RDWR)) == ERR)
    {
        printf("couldnt open %s\n", file);
        return ERR;
    }

    if((fstat(fd, &elf_stats)))
    {
        printf("could not fstat %s\n", file);
        close(fd);
        return ERR;
    }

    if((base_ptr = (char *) malloc(elf_stats.st_size)) == NULL)
    {
        printf("could not malloc\n");
        close(fd);
        return ERR;
    }

    if((read(fd, base_ptr, elf_stats.st_size)) < elf_stats.st_size)
    {
        printf("could not read %s\n", file);
        free(base_ptr);
        close(fd);
        return ERR;
    }

    /* Check libelf version first */
    if(elf_version(EV_CURRENT) == EV_NONE)
    {
        printf("WARNING Elf Library is out of date!\n");
    }
    printf("Doing great! \n");
    elf_header = (Elf32_Ehdr *) base_ptr;	// point elf_header at our object in memory
    elf = elf_begin(fd, ELF_C_READ, NULL);	// Initialize 'elf' pointer to our file descriptor

    printf("%p, \n", elf_header);
    printf("%p, \n", elf);

    /* Iterate through section headers */
    while((scn = elf_nextscn(elf, scn)) != 0)
    {
        // point shdr at this section header entry
        printf("%p, ....... \n", elf);
        gelf_getshdr(scn, &shdr);
        printf("%p, AAAAAAAAA \n", elf);
        // print the section header type
        printf("%p, AAAAAAAAA \n", elf);
        printf("Type: ");

        switch(shdr.sh_type)
        {
        case SHT_NULL:
            printf( "SHT_NULL\t");
            break;
        case SHT_PROGBITS:
            printf( "SHT_PROGBITS");
            break;
        case SHT_SYMTAB:
            printf( "SHT_SYMTAB");
            break;
        case SHT_STRTAB:
            printf( "SHT_STRTAB");
            break;
        case SHT_RELA:
            printf( "SHT_RELA\t");
            break;
        case SHT_HASH:
            printf( "SHT_HASH\t");
            break;
        case SHT_DYNAMIC:
            printf( "SHT_DYNAMIC");
            break;
        case SHT_NOTE:
            printf( "SHT_NOTE\t");
            break;
        case SHT_NOBITS:
            printf( "SHT_NOBITS");
            break;
        case SHT_REL:
            printf( "SHT_REL\t");
            break;
        case SHT_SHLIB:
            printf( "SHT_SHLIB");
            break;
        case SHT_DYNSYM:
            printf( "SHT_DYNSYM");
            break;
        case SHT_INIT_ARRAY:
            printf( "SHT_INIT_ARRAY");
            break;
        case SHT_FINI_ARRAY:
            printf( "SHT_FINI_ARRAY");
            break;
        case SHT_PREINIT_ARRAY:
            printf( "SHT_PREINIT_ARRAY");
            break;
        case SHT_GROUP:
            printf( "SHT_GROUP");
            break;
        case SHT_SYMTAB_SHNDX:
            printf( "SHT_SYMTAB_SHNDX");
            break;
        case SHT_NUM:
            printf( "SHT_NUM\t");
            break;
        case SHT_LOOS:
            printf( "SHT_LOOS\t");
            break;
        case SHT_GNU_verdef:
            printf( "SHT_GNU_verdef");
            break;
        case SHT_GNU_verneed:
            printf( "SHT_VERNEED");
            break;
        case SHT_GNU_versym:
            printf( "SHT_GNU_versym");
            break;
        default:
            printf( "(none) ");
            break;
        }

        // print the section header flags
        printf("\t(");
        if(shdr.sh_flags & SHF_WRITE)
        {
            printf("W");
        }
        if(shdr.sh_flags & SHF_ALLOC)
        {
            printf("A");
        }
        if(shdr.sh_flags & SHF_EXECINSTR)
        {
            printf("X");
        }
        if(shdr.sh_flags & SHF_STRINGS)
        {
            printf("S");
        }
        printf(")\t");

        // the shdr name is in a string table, libelf uses elf_strptr() to find it
        // using the e_shstrndx value from the elf_header
        printf("%s\n", elf_strptr(elf, elf_header->e_shstrndx, shdr.sh_name));
    }

// Iterate through section headers again this time well stop when we find symbols
    elf = elf_begin(fd, ELF_C_READ, NULL);

    int symbol_count;
    int i;

    while((scn = elf_nextscn(elf, scn)) != NULL)
    {
        gelf_getshdr(scn, &shdr);

        // When we find a section header marked SHT_SYMTAB stop and get symbols
        if(shdr.sh_type == SHT_SYMTAB)
        {
            // edata points to our symbol table
            edata = elf_getdata(scn, edata);

            // how many symbols are there? this number comes from the size of
            // the section divided by the entry size
            symbol_count = shdr.sh_size / shdr.sh_entsize;

            // loop through to grab all symbols
            for(i = 0; i < symbol_count; i++)
            {
                // libelf grabs the symbol data using gelf_getsym()
                gelf_getsym(edata, i, &sym);

                // print out the value and size
                printf("%08x %08d ", sym.st_value, sym.st_size);

                // type of symbol binding
                switch(ELF32_ST_BIND(sym.st_info))
                {
                case STB_LOCAL:
                    printf("LOCAL");
                    break;
                case STB_GLOBAL:
                    printf("GLOBAL");
                    break;
                case STB_WEAK:
                    printf("WEAK");
                    break;
                case STB_NUM:
                    printf("NUM");
                    break;
                case STB_LOOS:
                    printf("LOOS");
                    break;
                case STB_HIOS:
                    printf("HIOS");
                    break;
                case STB_LOPROC:
                    printf("LOPROC");
                    break;
                case STB_HIPROC:
                    printf("HIPROC");
                    break;
                default:
                    printf("UNKNOWN");
                    break;
                }

                printf("\t");

                // type of symbol
                switch(ELF32_ST_TYPE(sym.st_info))
                {
                case STT_NOTYPE:
                    printf("NOTYPE");
                    break;
                case STT_OBJECT:
                    printf("OBJECT");
                    break;
                case STT_FUNC:
                    printf("FUNC");
                    break;
                case STT_SECTION:
                    printf("SECTION");
                    break;
                case STT_FILE:
                    printf("FILE");
                    break;
                case STT_COMMON:
                    printf("COMMON");
                    break;
                case STT_TLS:
                    printf("TLS");
                    break;
                case STT_NUM:
                    printf("NUM");
                    break;
                case STT_LOOS:
                    printf("LOOS");
                    break;
                case STT_HIOS:
                    printf("HIOS");
                    break;
                case STT_LOPROC:
                    printf("LOPROC");
                    break;
                case STT_HIPROC:
                    printf("HIPROC");
                    break;
                default:
                    printf("UNKNOWN");
                    break;
                }

                printf("\t");

                // the name of the symbol is somewhere in a string table
                // we know which one using the shdr.sh_link member
                // libelf grabs the string using elf_strptr()
                printf("%s\n", elf_strptr(elf, shdr.sh_link, sym.st_name));
            }

        }
    }

    return 0;
}
int
main (void)
{
  int result = 0;
  size_t cnt;
  AsmCtx_t *ctx;
  Elf *elf;
  int fd;

  elf_version (EV_CURRENT);

  Ebl *ebl = ebl_openbackend_machine (EM_386);
  if (ebl == NULL)
    {
      puts ("cannot open backend library");
      return 1;
    }

  ctx = asm_begin (fname, ebl, false);
  if (ctx == NULL)
    {
      printf ("cannot create assembler context: %s\n", asm_errmsg (-1));
      return 1;
    }

  if (asm_newcomsym (ctx, "commsym", 4, 16) == NULL)
    {
      printf ("cannot create common symbol: %s\n", asm_errmsg (-1));
      asm_abort (ctx);
      return 1;
    }

  /* Create the output file.  */
  if (asm_end (ctx) != 0)
    {
      printf ("cannot create output file: %s\n", asm_errmsg (-1));
      asm_abort (ctx);
      return 1;
    }

  /* Check the file.  */
  fd = open (fname, O_RDONLY);
  if (fd == -1)
    {
      printf ("cannot open generated file: %m\n");
      result = 1;
      goto out;
    }

  elf = elf_begin (fd, ELF_C_READ, NULL);
  if (elf == NULL)
    {
      printf ("cannot create ELF descriptor: %s\n", elf_errmsg (-1));
      result = 1;
      goto out_close;
    }
  if (elf_kind (elf) != ELF_K_ELF)
    {
      puts ("not a valid ELF file");
      result = 1;
      goto out_close2;
    }

  for (cnt = 1; 1; ++cnt)
    {
      Elf_Scn *scn;
      GElf_Shdr shdr_mem;
      GElf_Shdr *shdr;

      scn = elf_getscn (elf, cnt);
      if (scn == NULL)
	{
	  printf ("cannot get section %Zd: %s\n", cnt, elf_errmsg (-1));
	  result = 1;
	  continue;
	}

      shdr = gelf_getshdr (scn, &shdr_mem);
      if (shdr == NULL)
	{
	  printf ("cannot get section header for section %Zd: %s\n",
		  cnt, elf_errmsg (-1));
	  result = 1;
	  continue;
	}
      /* We are looking for the symbol table.  */
      if (shdr->sh_type != SHT_SYMTAB)
	continue;

      for (cnt = 1; cnt< (shdr->sh_size
			  / gelf_fsize (elf, ELF_T_SYM, 1, EV_CURRENT));
	   ++cnt)
	{
	  GElf_Sym sym_mem;
	  GElf_Sym *sym;

	  if (cnt > 1)
	    {
	      puts ("too many symbol");
	      result = 1;
	      break;
	    }

	  sym = gelf_getsym (elf_getdata (scn, NULL), cnt, &sym_mem);
	  if (sym == NULL)
	    {
	      printf ("cannot get symbol %zu: %s\n", cnt, elf_errmsg (-1));
	      result = 1;
	    }
	  else
	    {
	      if (sym->st_shndx != SHN_COMMON)
		{
		  printf ("expected common symbol, got section %u\n",
			  (unsigned int) sym->st_shndx);
		  result = 1;
		}

	      if (sym->st_value != 16)
		{
		  printf ("requested alignment 16, is %" PRIuMAX "\n",
			  (uintmax_t) sym->st_value);
		  result = 1;
		}

	      if (sym->st_size != 4)
		{
		  printf ("requested size 4, is %" PRIuMAX "\n",
			  (uintmax_t) sym->st_value);
		  result = 1;
		}
	    }
	}

      break;
    }

 out_close2:
  elf_end (elf);
 out_close:
  close (fd);
 out:
  /* We don't need the file anymore.  */
  unlink (fname);

  ebl_closebackend (ebl);

  return result;
}
static GHashTable* parse_plt(Elf *e, const char *filename)
{
    GElf_Shdr shdr;

    Elf_Data *plt_data;
    uintptr_t plt_base;
    size_t plt_section_index = xelf_section_by_name(e, ".plt", filename, &plt_data, &shdr);
    if (plt_section_index == 0)
    {
        VERB1 log("No .plt section found for %s", filename);
        return NULL;
    }
    plt_base = shdr.sh_addr;

    /* Find the relocation section for .plt (typically .rela.plt), together
     * with its symbol and string table
     */
    Elf_Data *rela_plt_data = NULL;
    Elf_Data *plt_symbols = NULL;
    size_t stringtable = 0;
    Elf_Scn *scn = NULL;
    while ((scn = elf_nextscn(e, scn)) != NULL)
    {
        if (gelf_getshdr(scn, &shdr) != &shdr)
        {
            VERB1 log_elf_error("gelf_getshdr", filename);
            continue;
        }

        if (shdr.sh_type == SHT_RELA && shdr.sh_info == plt_section_index)
        {
            rela_plt_data = elf_getdata(scn, NULL);
            if (rela_plt_data == NULL)
            {
                VERB1 log_elf_error("elf_getdata", filename);
                break;
            }

            /* Get symbol section for .rela.plt */
            Elf_Scn *symscn = elf_getscn(e, shdr.sh_link);
            if (symscn == NULL)
            {
                VERB1 log_elf_error("elf_getscn", filename);
                break;
            }

            plt_symbols = elf_getdata(symscn, NULL);
            if (plt_symbols == NULL)
            {
                VERB1 log_elf_error("elf_getdata", filename);
                break;
            }

            /* Get string table for the symbol table. */
            if (gelf_getshdr(symscn, &shdr) != &shdr)
            {
                VERB1 log_elf_error("gelf_getshdr", filename);
                break;
            }

            stringtable = shdr.sh_link;
            break;
        }
    }

    if (stringtable == 0)
    {
        VERB1 log("Unable to read symbol table for .plt for file %s", filename);
        return NULL;
    }

    /* Init hash table
     * keys are pointers to integers which we allocate with malloc
     * values are owned by libelf, so we don't need to free them */
    GHashTable *hash = g_hash_table_new_full(g_int64_hash, g_int64_equal, free, NULL);

    /* PLT looks like this (see also AMD64 ABI, page 78):
     *
     * Disassembly of section .plt:
     *
     * 0000003463e01010 <attr_removef@plt-0x10>:
     *   3463e01010:   ff 35 2a 2c 20 00       pushq  0x202c2a(%rip)         <-- here is plt_base
     *   3463e01016:   ff 25 2c 2c 20 00       jmpq   *0x202c2c(%rip)            each "slot" is 16B wide
     *   3463e0101c:   0f 1f 40 00             nopl   0x0(%rax)                  0-th slot is skipped
     *
     * 0000003463e01020 <attr_removef@plt>:
     *   3463e01020:   ff 25 2a 2c 20 00       jmpq   *0x202c2a(%rip)
     *   3463e01026:   68 00 00 00 00          pushq  $0x0                   <-- this is the number we want
     *   3463e0102b:   e9 e0 ff ff ff          jmpq   3463e01010 <_init+0x18>
     *
     * 0000003463e01030 <fgetxattr@plt>:
     *   3463e01030:   ff 25 22 2c 20 00       jmpq   *0x202c22(%rip)
     *   3463e01036:   68 01 00 00 00          pushq  $0x1
     *   3463e0103b:   e9 d0 ff ff ff          jmpq   3463e01010 <_init+0x18>
     */

    unsigned plt_offset;
    uint32_t *plt_index;
    GElf_Rela rela;
    GElf_Sym symb;
    for (plt_offset = 16; plt_offset < plt_data->d_size; plt_offset += 16)
    {
        plt_index = (uint32_t*)(plt_data->d_buf + plt_offset + 7);

        if(gelf_getrela(rela_plt_data, *plt_index, &rela) != &rela)
        {
            VERB1 log_elf_error("gelf_getrela", filename);
            continue;
        }

        if(gelf_getsym(plt_symbols, GELF_R_SYM(rela.r_info), &symb) != &symb)
        {
            VERB1 log_elf_error("gelf_getsym", filename);
            continue;
        }

        char *symbol = elf_strptr(e, stringtable, symb.st_name);
        uintptr_t *addr = addr_alloc((uintptr_t)(plt_base + plt_offset));

        VERB3 log("[%02x] %jx: %s", *plt_index, (uintptr_t)(*addr), symbol);
        g_hash_table_insert(hash, addr, symbol);
    }

    return hash;
}
Exemple #30
0
static gboolean
handle_dwarf2_section (DebuginfoData *data, GHashTable *files, GError **error)
{
  Elf_Data *e_data;
  int i;
  debug_section_t *debug_sections;

  ptr_size = 0;

  if (data->ehdr.e_ident[EI_DATA] == ELFDATA2LSB)
    {
      do_read_16 = buf_read_ule16;
      do_read_32 = buf_read_ule32;
    }
  else if (data->ehdr.e_ident[EI_DATA] == ELFDATA2MSB)
    {
      do_read_16 = buf_read_ube16;
      do_read_32 = buf_read_ube32;
    }
  else
    {
      return flatpak_fail (error, "%s: Wrong ELF data encoding", data->filename);
    }

  debug_sections = data->debug_sections;

  if (debug_sections[DEBUG_INFO].data != NULL)
    {
      unsigned char *ptr, *endcu, *endsec;
      uint32_t value;
      struct abbrev_tag *t;
      g_autofree REL *relbuf = NULL;

      if (debug_sections[DEBUG_INFO].relsec)
        {
          Elf_Scn *scn;
          int ndx, maxndx;
          GElf_Rel rel;
          GElf_Rela rela;
          GElf_Sym sym;
          GElf_Addr base = data->shdr[debug_sections[DEBUG_INFO].sec].sh_addr;
          Elf_Data *symdata = NULL;
          int rtype;

          i = debug_sections[DEBUG_INFO].relsec;
          scn = data->scns[i];
          e_data = elf_getdata (scn, NULL);
          g_assert (e_data != NULL && e_data->d_buf != NULL);
          g_assert (elf_getdata (scn, e_data) == NULL);
          g_assert (e_data->d_off == 0);
          g_assert (e_data->d_size == data->shdr[i].sh_size);
          maxndx = data->shdr[i].sh_size / data->shdr[i].sh_entsize;
          relbuf = g_malloc (maxndx * sizeof (REL));
          reltype = data->shdr[i].sh_type;

          symdata = elf_getdata (data->scns[data->shdr[i].sh_link], NULL);
          g_assert (symdata != NULL && symdata->d_buf != NULL);
          g_assert (elf_getdata (data->scns[data->shdr[i].sh_link], symdata) == NULL);
          g_assert (symdata->d_off == 0);
          g_assert (symdata->d_size == data->shdr[data->shdr[i].sh_link].sh_size);

          for (ndx = 0, relend = relbuf; ndx < maxndx; ++ndx)
            {
              if (data->shdr[i].sh_type == SHT_REL)
                {
                  gelf_getrel (e_data, ndx, &rel);
                  rela.r_offset = rel.r_offset;
                  rela.r_info = rel.r_info;
                  rela.r_addend = 0;
                }
              else
                {
                  gelf_getrela (e_data, ndx, &rela);
                }
              gelf_getsym (symdata, ELF64_R_SYM (rela.r_info), &sym);
              /* Relocations against section symbols are uninteresting
                 in REL.  */
              if (data->shdr[i].sh_type == SHT_REL && sym.st_value == 0)
                continue;
              /* Only consider relocations against .debug_str, .debug_line
                 and .debug_abbrev.  */
              if (sym.st_shndx != debug_sections[DEBUG_STR].sec &&
                  sym.st_shndx != debug_sections[DEBUG_LINE].sec &&
                  sym.st_shndx != debug_sections[DEBUG_ABBREV].sec)
                continue;
              rela.r_addend += sym.st_value;
              rtype = ELF64_R_TYPE (rela.r_info);
              switch (data->ehdr.e_machine)
                {
                case EM_SPARC:
                case EM_SPARC32PLUS:
                case EM_SPARCV9:
                  if (rtype != R_SPARC_32 && rtype != R_SPARC_UA32)
                    goto fail;
                  break;

                case EM_386:
                  if (rtype != R_386_32)
                    goto fail;
                  break;

                case EM_PPC:
                case EM_PPC64:
                  if (rtype != R_PPC_ADDR32 && rtype != R_PPC_UADDR32)
                    goto fail;
                  break;

                case EM_S390:
                  if (rtype != R_390_32)
                    goto fail;
                  break;

                case EM_IA_64:
                  if (rtype != R_IA64_SECREL32LSB)
                    goto fail;
                  break;

                case EM_X86_64:
                  if (rtype != R_X86_64_32)
                    goto fail;
                  break;

                case EM_ALPHA:
                  if (rtype != R_ALPHA_REFLONG)
                    goto fail;
                  break;

#if defined(EM_AARCH64) && defined(R_AARCH64_ABS32)
                case EM_AARCH64:
                  if (rtype != R_AARCH64_ABS32)
                    goto fail;
                  break;

#endif
                case EM_68K:
                  if (rtype != R_68K_32)
                    goto fail;
                  break;

                default:
fail:
                  return flatpak_fail (error, "%s: Unhandled relocation %d in .debug_info section",
                                       data->filename, rtype);
                }
              relend->ptr = debug_sections[DEBUG_INFO].data
                            + (rela.r_offset - base);
              relend->addend = rela.r_addend;
              ++relend;
            }
          if (relbuf == relend)
            {
              g_free (relbuf);
              relbuf = NULL;
              relend = NULL;
            }
          else
            {
              qsort (relbuf, relend - relbuf, sizeof (REL), rel_cmp);
            }
        }

      ptr = debug_sections[DEBUG_INFO].data;
      relptr = relbuf;
      endsec = ptr + debug_sections[DEBUG_INFO].size;
      while (ptr != NULL && ptr < endsec)
        {
          g_autoptr(GHashTable) abbrev = NULL;

          if (ptr + 11 > endsec)
            return flatpak_fail (error, "%s: .debug_info CU header too small", data->filename);

          endcu = ptr + 4;
          endcu += read_32 (ptr);
          if (endcu == ptr + 0xffffffff)
            return flatpak_fail (error, "%s: 64-bit DWARF not supported", data->filename);

          if (endcu > endsec)
            return flatpak_fail (error, "%s: .debug_info too small", data->filename);

          cu_version = read_16 (ptr);
          if (cu_version != 2 && cu_version != 3 && cu_version != 4)
            return flatpak_fail (error, "%s: DWARF version %d unhandled", data->filename, cu_version);

          value = read_32_relocated (ptr);
          if (value >= debug_sections[DEBUG_ABBREV].size)
            {
              if (debug_sections[DEBUG_ABBREV].data == NULL)
                return flatpak_fail (error, "%s: .debug_abbrev not present", data->filename);
              else
                return flatpak_fail (error, "%s: DWARF CU abbrev offset too large", data->filename);
            }

          if (ptr_size == 0)
            {
              ptr_size = read_1 (ptr);
              if (ptr_size != 4 && ptr_size != 8)
                return flatpak_fail (error, "%s: Invalid DWARF pointer size %d", data->filename, ptr_size);
            }
          else if (read_1 (ptr) != ptr_size)
            {
              return flatpak_fail (error, "%s: DWARF pointer size differs between CUs", data->filename);
            }

          abbrev = read_abbrev (data,
                                debug_sections[DEBUG_ABBREV].data + value);

          while (ptr < endcu)
            {
              guint entry = read_uleb128 (ptr);
              if (entry == 0)
                continue;
              t = g_hash_table_lookup (abbrev, GINT_TO_POINTER (entry));
              if (t == NULL)
                {
                  g_warning ("%s: Could not find DWARF abbreviation %d", data->filename, entry);
                }
              else
                {
                  ptr = handle_attributes (data, ptr, t, files, error);
                  if (ptr == NULL)
                    return FALSE;
                }
            }
        }
    }

  return TRUE;
}