Exemplo n.º 1
0
static int symb_synthesize_plt_symbols(struct symb_arr *arr, Elf *elf) {
   uint32_t nr_rel_entries, idx;
   GElf_Sym sym;
   uint64_t plt_offset;
   GElf_Shdr shdr_plt;
   GElf_Shdr shdr_rel_plt, shdr_dynsym;
   Elf_Data *reldata, *syms, *symstrs;
   Elf_Scn *scn_plt_rel, *scn_symstrs, *scn_dynsym;
   size_t dynsym_idx;
   GElf_Ehdr ehdr;
   char sympltname[1024];
   int nr = 0, symidx, err = 0;

   if (gelf_getehdr(elf, &ehdr) == NULL)
      goto out_elf_end;

   scn_dynsym
            = elf_section_by_name(elf, &ehdr, &shdr_dynsym, ".dynsym", &dynsym_idx);
   if (scn_dynsym == NULL)
      goto out_elf_end;

   scn_plt_rel
            = elf_section_by_name(elf, &ehdr, &shdr_rel_plt, ".rela.plt", NULL);
   if (scn_plt_rel == NULL) {
      scn_plt_rel
               = elf_section_by_name(elf, &ehdr, &shdr_rel_plt, ".rel.plt", NULL);
      if (scn_plt_rel == NULL)
         goto out_elf_end;
   }

   err = -1;

   if (shdr_rel_plt.sh_link != dynsym_idx)
      goto out_elf_end;

   if (elf_section_by_name(elf, &ehdr, &shdr_plt, ".plt", NULL) == NULL)
      goto out_elf_end;

   /*
    * Fetch the relocation section to find the idxes to the GOT
    * and the symbols in the .dynsym they refer to.
    */
   reldata = elf_getdata(scn_plt_rel, NULL);
   if (reldata == NULL)
      goto out_elf_end;

   syms = elf_getdata(scn_dynsym, NULL);
   if (syms == NULL)
      goto out_elf_end;

   scn_symstrs = elf_getscn(elf, shdr_dynsym.sh_link);
   if (scn_symstrs == NULL)
      goto out_elf_end;

   symstrs = elf_getdata(scn_symstrs, NULL);
   if (symstrs == NULL)
      goto out_elf_end;

   nr_rel_entries = shdr_rel_plt.sh_size / shdr_rel_plt.sh_entsize;
   plt_offset = shdr_plt.sh_offset;

   if (shdr_rel_plt.sh_type == SHT_RELA) {
      GElf_Rela pos_mem, *pos;

      elf_section__for_each_rela(reldata, pos, pos_mem, idx,
               nr_rel_entries) {
         symidx = GELF_R_SYM(pos->r_info);
         plt_offset += shdr_plt.sh_entsize;
         gelf_getsym(syms, symidx, &sym);
         snprintf(sympltname, sizeof(sympltname), "%s@plt", elf_sym__name(&sym, symstrs));
         struct symb *s = symb_new();
         s->hex = plt_offset;
         s->name = strdup(sympltname);
         symb_insert(s, arr);
         ++nr;
      }
Exemplo n.º 2
0
/*
 * We need to check if we have a .dynsym, so that we can handle the
 * .plt, synthesizing its symbols, that aren't on the symtabs (be it
 * .dynsym or .symtab).
 * And always look at the original dso, not at debuginfo packages, that
 * have the PLT data stripped out (shdr_rel_plt.sh_type == SHT_NOBITS).
 */
int dso__synthesize_plt_symbols(struct dso *dso, struct symsrc *ss, struct map *map,
				symbol_filter_t filter)
{
	uint32_t nr_rel_entries, idx;
	GElf_Sym sym;
	u64 plt_offset;
	GElf_Shdr shdr_plt;
	struct symbol *f;
	GElf_Shdr shdr_rel_plt, shdr_dynsym;
	Elf_Data *reldata, *syms, *symstrs;
	Elf_Scn *scn_plt_rel, *scn_symstrs, *scn_dynsym;
	size_t dynsym_idx;
	GElf_Ehdr ehdr;
	char sympltname[1024];
	Elf *elf;
	int nr = 0, symidx, err = 0;

	if (!ss->dynsym)
		return 0;

	elf = ss->elf;
	ehdr = ss->ehdr;

	scn_dynsym = ss->dynsym;
	shdr_dynsym = ss->dynshdr;
	dynsym_idx = ss->dynsym_idx;

	if (scn_dynsym == NULL)
		goto out_elf_end;

	scn_plt_rel = elf_section_by_name(elf, &ehdr, &shdr_rel_plt,
					  ".rela.plt", NULL);
	if (scn_plt_rel == NULL) {
		scn_plt_rel = elf_section_by_name(elf, &ehdr, &shdr_rel_plt,
						  ".rel.plt", NULL);
		if (scn_plt_rel == NULL)
			goto out_elf_end;
	}

	err = -1;

	if (shdr_rel_plt.sh_link != dynsym_idx)
		goto out_elf_end;

	if (elf_section_by_name(elf, &ehdr, &shdr_plt, ".plt", NULL) == NULL)
		goto out_elf_end;

	/*
	 * Fetch the relocation section to find the idxes to the GOT
	 * and the symbols in the .dynsym they refer to.
	 */
	reldata = elf_getdata(scn_plt_rel, NULL);
	if (reldata == NULL)
		goto out_elf_end;

	syms = elf_getdata(scn_dynsym, NULL);
	if (syms == NULL)
		goto out_elf_end;

	scn_symstrs = elf_getscn(elf, shdr_dynsym.sh_link);
	if (scn_symstrs == NULL)
		goto out_elf_end;

	symstrs = elf_getdata(scn_symstrs, NULL);
	if (symstrs == NULL)
		goto out_elf_end;

	if (symstrs->d_size == 0)
		goto out_elf_end;

	nr_rel_entries = shdr_rel_plt.sh_size / shdr_rel_plt.sh_entsize;
	plt_offset = shdr_plt.sh_offset;

	if (shdr_rel_plt.sh_type == SHT_RELA) {
		GElf_Rela pos_mem, *pos;

		elf_section__for_each_rela(reldata, pos, pos_mem, idx,
					   nr_rel_entries) {
			symidx = GELF_R_SYM(pos->r_info);
			plt_offset += shdr_plt.sh_entsize;
			gelf_getsym(syms, symidx, &sym);
			snprintf(sympltname, sizeof(sympltname),
				 "%s@plt", elf_sym__name(&sym, symstrs));

			f = symbol__new(plt_offset, shdr_plt.sh_entsize,
					STB_GLOBAL, sympltname);
			if (!f)
				goto out_elf_end;

			if (filter && filter(map, f))
				symbol__delete(f);
			else {
				symbols__insert(&dso->symbols[map->type], f);
				++nr;
			}
		}
Exemplo n.º 3
0
/*
 * We need to check if we have a .dynsym, so that we can handle the
 * .plt, synthesizing its symbols, that aren't on the symtabs (be it
 * .dynsym or .symtab).
 * And always look at the original dso, not at debuginfo packages, that
 * have the PLT data stripped out (shdr_rel_plt.sh_type == SHT_NOBITS).
 */
static int dso__synthesize_plt_symbols(struct  dso *self, int verbose)
{
	uint32_t nr_rel_entries, idx;
	GElf_Sym sym;
	u64 plt_offset;
	GElf_Shdr shdr_plt;
	struct symbol *f;
	GElf_Shdr shdr_rel_plt, shdr_dynsym;
	Elf_Data *reldata, *syms, *symstrs;
	Elf_Scn *scn_plt_rel, *scn_symstrs, *scn_dynsym;
	size_t dynsym_idx;
	GElf_Ehdr ehdr;
	char sympltname[1024];
	Elf *elf;
	int nr = 0, symidx, fd, err = 0;

	fd = open(self->name, O_RDONLY);
	if (fd < 0)
		goto out;

	elf = elf_begin(fd, ELF_C_READ_MMAP, NULL);
	if (elf == NULL)
		goto out_close;

	if (gelf_getehdr(elf, &ehdr) == NULL)
		goto out_elf_end;

	scn_dynsym = elf_section_by_name(elf, &ehdr, &shdr_dynsym,
					 ".dynsym", &dynsym_idx);
	if (scn_dynsym == NULL)
		goto out_elf_end;

	scn_plt_rel = elf_section_by_name(elf, &ehdr, &shdr_rel_plt,
					  ".rela.plt", NULL);
	if (scn_plt_rel == NULL) {
		scn_plt_rel = elf_section_by_name(elf, &ehdr, &shdr_rel_plt,
						  ".rel.plt", NULL);
		if (scn_plt_rel == NULL)
			goto out_elf_end;
	}

	err = -1;

	if (shdr_rel_plt.sh_link != dynsym_idx)
		goto out_elf_end;

	if (elf_section_by_name(elf, &ehdr, &shdr_plt, ".plt", NULL) == NULL)
		goto out_elf_end;

	/*
	 * Fetch the relocation section to find the indexes to the GOT
	 * and the symbols in the .dynsym they refer to.
	 */
	reldata = elf_getdata(scn_plt_rel, NULL);
	if (reldata == NULL)
		goto out_elf_end;

	syms = elf_getdata(scn_dynsym, NULL);
	if (syms == NULL)
		goto out_elf_end;

	scn_symstrs = elf_getscn(elf, shdr_dynsym.sh_link);
	if (scn_symstrs == NULL)
		goto out_elf_end;

	symstrs = elf_getdata(scn_symstrs, NULL);
	if (symstrs == NULL)
		goto out_elf_end;

	nr_rel_entries = shdr_rel_plt.sh_size / shdr_rel_plt.sh_entsize;
	plt_offset = shdr_plt.sh_offset;

	if (shdr_rel_plt.sh_type == SHT_RELA) {
		GElf_Rela pos_mem, *pos;

		elf_section__for_each_rela(reldata, pos, pos_mem, idx,
					   nr_rel_entries) {
			symidx = GELF_R_SYM(pos->r_info);
			plt_offset += shdr_plt.sh_entsize;
			gelf_getsym(syms, symidx, &sym);
			snprintf(sympltname, sizeof(sympltname),
				 "%s@plt", elf_sym__name(&sym, symstrs));

			f = symbol__new(plt_offset, shdr_plt.sh_entsize,
					sympltname, self->sym_priv_size, 0, verbose);
			if (!f)
				goto out_elf_end;

			dso__insert_symbol(self, f);
			++nr;
		}