Ejemplo n.º 1
0
int
findelfsecidx(Elf *elf, const char *file, const char *tofind)
{
	Elf_Scn *scn = NULL;
	GElf_Ehdr ehdr;
	GElf_Shdr shdr;

	if (gelf_getehdr(elf, &ehdr) == NULL)
		elfterminate(file, "Couldn't read ehdr");

	while ((scn = elf_nextscn(elf, scn)) != NULL) {
		char *name;

		if (gelf_getshdr(scn, &shdr) == NULL) {
			elfterminate(file,
			    "Couldn't read header for section %d",
			    elf_ndxscn(scn));
		}

		if ((name = elf_strptr(elf, ehdr.e_shstrndx,
		    (size_t)shdr.sh_name)) == NULL) {
			elfterminate(file,
			    "Couldn't get name for section %d",
			    elf_ndxscn(scn));
		}

		if (strcmp(name, tofind) == 0)
			return (elf_ndxscn(scn));
	}

	return (-1);
}
Ejemplo n.º 2
0
int ElfWriter::newSection(LIBDWARF_CALLBACK_NAME_TYPE name,
  uint64_t size, uint32_t type, uint64_t flags,
  uint64_t addr/* = 0*/) {
  Elf_Scn *scn = elf_newscn(m_elf);
  if (!scn) {
    logError("Unable to create new section");
    return -1;
  }
  Elf64_Shdr *sectionHdr = elf64_getshdr(scn);
  if (!sectionHdr) {
    logError("Unable to create section header");
    return -1;
  }
  int nameOffset = addSectionString(name);
  sectionHdr->sh_name = nameOffset;
  sectionHdr->sh_type = type;
  sectionHdr->sh_flags = flags;
  sectionHdr->sh_size = size;
  sectionHdr->sh_addr = addr;
  sectionHdr->sh_offset = 0;
  sectionHdr->sh_link = 0;
  sectionHdr->sh_info = 0;
  sectionHdr->sh_addralign = 1;
  sectionHdr->sh_entsize = 0;

  return elf_ndxscn(scn);
}
Ejemplo n.º 3
0
int
internal_function
__libdwfl_find_build_id (Dwfl_Module *mod, bool set, Elf *elf)
{
  size_t shstrndx = SHN_UNDEF;
  int result = 0;

  Elf_Scn *scn = elf_nextscn (elf, NULL);

  if (scn == NULL)
    {
      /* No sections, have to look for phdrs.  */
      GElf_Ehdr ehdr_mem;
      GElf_Ehdr *ehdr = gelf_getehdr (elf, &ehdr_mem);
      size_t phnum;
      if (unlikely (ehdr == NULL)
	  || unlikely (elf_getphdrnum (elf, &phnum) != 0))
	{
	  __libdwfl_seterrno (DWFL_E_LIBELF);
	  return -1;
	}
      for (size_t i = 0; result == 0 && i < phnum; ++i)
	{
	  GElf_Phdr phdr_mem;
	  GElf_Phdr *phdr = gelf_getphdr (elf, i, &phdr_mem);
	  if (likely (phdr != NULL) && phdr->p_type == PT_NOTE)
	    result = check_notes (mod, set,
				  elf_getdata_rawchunk (elf,
							phdr->p_offset,
							phdr->p_filesz,
							ELF_T_NHDR),
				  phdr->p_vaddr + mod->main.bias);
	}
    }
  else
    do
      {
	GElf_Shdr shdr_mem;
	GElf_Shdr *shdr = gelf_getshdr (scn, &shdr_mem);
	if (likely (shdr != NULL) && shdr->sh_type == SHT_NOTE)
	  {
	    /* Determine the right sh_addr in this module.  */
	    GElf_Addr vaddr = 0;
	    if (!(shdr->sh_flags & SHF_ALLOC))
	      vaddr = NO_VADDR;
	    else if (mod->e_type != ET_REL)
	      vaddr = shdr->sh_addr + mod->main.bias;
	    else if (__libdwfl_relocate_value (mod, elf, &shstrndx,
					       elf_ndxscn (scn), &vaddr))
	      vaddr = NO_VADDR;
	    result = check_notes (mod, set, elf_getdata (scn, NULL), vaddr);
	  }
      }
    while (result == 0 && (scn = elf_nextscn (elf, scn)) != NULL);

  return result;
}
Ejemplo n.º 4
0
//---------------------------------------------------------------------
static int convElfHdr(Melf_Scn* mscn, Elf_Scn* escn)
{
  Elf32_Shdr *shdr; 
  if ((shdr = elf32_getshdr(escn)) == NULL){
    fprintf(stderr, "Error reading section header.\n");
    return -1;
  } 
  mscn->m_shdr.sh_id = (Melf_Half)elf_ndxscn(escn);
  mscn->m_shdr.sh_type = shdr->sh_type;
  mscn->m_shdr.sh_link = shdr->sh_link;
  mscn->m_shdr.sh_info = shdr->sh_info;
  return 0;
}
Ejemplo n.º 5
0
void *
drsym_obj_mod_init_pre(byte *map_base, size_t file_size)
{
    elf_info_t *mod;
    Elf_Scn *symtab_scn;
    Elf_Scn *strtab_scn;
    Elf_Shdr *symtab_shdr;

    mod = dr_global_alloc(sizeof(*mod));
    memset(mod, 0, sizeof(*mod));
    mod->map_base = map_base;

    mod->elf = elf_memory((char *)map_base, file_size);

    symtab_scn = find_elf_section_by_name(mod->elf, ".symtab");
    strtab_scn = find_elf_section_by_name(mod->elf, ".strtab");

    if (symtab_scn != NULL) {
        mod->debug_kind |= DRSYM_SYMBOLS | DRSYM_ELF_SYMTAB;

        if (strtab_scn != NULL) {
            symtab_shdr = elf_getshdr(symtab_scn);
            mod->strtab_idx = elf_ndxscn(strtab_scn);
            mod->num_syms = symtab_shdr->sh_size / symtab_shdr->sh_entsize;

            /* This assumes that the ELF file uses the same representation conventions
             * as the current machine, which is reasonable considering this module is
             * probably loaded in the current process.
             */
            mod->syms = (Elf_Sym*)(((char*) mod->map_base) + symtab_shdr->sh_offset);
        }
    } else {
        /* XXX i#672: there may still be dwarf2 or stabs sections even if the
         * symtable is stripped and we could do symbol lookup via dwarf2
         */
    }

    if (find_elf_section_by_name(mod->elf, ".debug_line") != NULL) {
        mod->debug_kind |= DRSYM_LINE_NUMS | DRSYM_DWARF_LINE;
    }

    return (void *) mod;
}
Ejemplo n.º 6
0
const char *
dwfl_module_relocation_info (Dwfl_Module *mod, unsigned int idx,
			     Elf32_Word *shndxp)
{
  if (mod == NULL)
    return NULL;

  switch (mod->e_type)
    {
    case ET_REL:
      break;

    case ET_DYN:
      if (idx != 0)
	return NULL;
      if (shndxp)
	*shndxp = SHN_ABS;
      return "";

    default:
      return NULL;
    }

  if (unlikely (mod->reloc_info == NULL) && cache_sections (mod) < 0)
    return NULL;

  struct dwfl_relocation *sections = mod->reloc_info;

  if (idx >= sections->count)
    return NULL;

  if (shndxp)
    *shndxp = elf_ndxscn (sections->refs[idx].scn);

  return sections->refs[idx].name;
}
Ejemplo n.º 7
0
/**
 * parse initial ELF file and collect essential section header information
 */
int
ElfInject::collectSHInfo() {
	Elf_Scn *scn = NULL;
	GElf_Shdr shdr;
	GElf_Shdr tmpShdr;
	char *symName = NULL;

	info("collect section header information");

	/* initialize important sections */

	elf_getshdrstrndx(bin.elf, &bin.shStrtabIndex);
	debug("° section .shstrtab: %d", bin.shStrtabIndex);

	while((scn = elf_nextscn(bin.elf, scn)) != NULL) {
		/* get section header */
		gelf_getshdr(scn, &shdr);

		switch(shdr.sh_type) {
		case SHT_SYMTAB:
			bin.shSymtabIndex = elf_ndxscn(scn);
			debug("° section .symtab: %d", bin.shSymtabIndex);
			break;
		case SHT_DYNAMIC:
			bin.shDynamicIndex = elf_ndxscn(scn);
			debug("° section .dyntab: %d", bin.shDynamicIndex);
			break;
		case SHT_STRTAB:
			gelf_getshdr(scn, &tmpShdr);
			symName = elf_strptr(bin.elf, bin.shStrtabIndex, tmpShdr.sh_name);

			if (!strcmp(symName, SH_NAME_DYNSTR)) {
				bin.shDynstrIndex = elf_ndxscn(scn);
				debug("° section .dynstr: %d", bin.shDynstrIndex);
			} else if (!strcmp(symName, SH_NAME_STRTAB)) {
				bin.shStrtabIndex = elf_ndxscn(scn);
				debug("° section .strtab: %d", bin.shStrtabIndex);
			}
			break;
		case SHT_DYNSYM:
			bin.shDynsymIndex = elf_ndxscn(scn);
			debug("° section .dynsym: %d", bin.shDynsymIndex);
			break;
		case SHT_PROGBITS:
			gelf_getshdr(scn, &tmpShdr);
			symName = elf_strptr(bin.elf, bin.shStrtabIndex, tmpShdr.sh_name);

			if (!strcmp(symName, SH_NAME_PLT)) {
				bin.shPltIndex = elf_ndxscn(scn);
				debug("° section .plt: %d", bin.shPltIndex);
			} else if (!strcmp(symName, SH_NAME_GOTPLT)) {
				bin.shGotPltIndex = elf_ndxscn(scn);
				bin.sizeGotPlt = tmpShdr.sh_size;
				debug("° section .got.plt: %d (size: %d)", bin.shGotPltIndex, bin.sizeGotPlt);
			} else if (!strcmp(symName, SH_NAME_GOT)) {
				bin.shGotIndex = elf_ndxscn(scn);
				bin.sizeGot = tmpShdr.sh_size;
				debug("° section .got: %d (size: %d)", bin.shGotIndex, bin.sizeGot);
			}
			break;
		case SHT_REL:
			gelf_getshdr(scn, &tmpShdr);
			symName = elf_strptr(bin.elf, bin.shStrtabIndex, tmpShdr.sh_name);

			if (!strcmp(symName, SH_NAME_RELPLT)) {
				bin.shRelPltIndex = elf_ndxscn(scn);
				debug("° section .rel.plt: %d", bin.shRelPltIndex);
			} else if (!strcmp(symName, SH_NAME_RELDYN)) {
				bin.shRelDynIndex = elf_ndxscn(scn);
				debug("° section .rel.dyn: %d", bin.shRelDynIndex);
			}
			break;
		default:
			/* do nothing */
			break;
		}
	}

	if(!bin.shSymtabIndex) {
		error("cannot find section .symtab");
		return -1;
	}

	return 0;
}
Ejemplo n.º 8
0
/*
 * Print the symbol table according to the flags that were
 * set, if any.  Input is an opened ELF file, the section name,
 * the section header, the section descriptor, and the filename.
 * First get the symbol table with a call to elf_getdata.
 * Then translate the symbol table data in memory by calling
 * readsyms().  This avoids duplication of function calls
 * and improves sorting efficiency.  qsort is used when sorting
 * is requested.
 */
static void
print_symtab(Elf *elf_file, unsigned int shstrndx,
	Elf_Scn *p_sd, GElf_Shdr *shdr, char *filename)
{

	Elf_Data * sd;
	SYM	*sym_data;
	SYM	*s;
	GElf_Sxword	count = 0;
	const int ndigits_arr[] = {
		10,		/* FMT_T_DEC */
		8,		/* FMT_T_HEX */
		11,		/* FMT_T_OCT */
	};
	int ndigits;

	/*
	 * Determine # of digits to use for each numeric value.
	 */
	ndigits = ndigits_arr[fmt_flag];
	if (gelf_getclass(elf_file) == ELFCLASS64)
		ndigits *= 2;

	/*
	 * print header
	 */
	print_header(ndigits);

	/*
	 * get symbol table data
	 */
	if (((sd = elf_getdata(p_sd, NULL)) == NULL) || (sd->d_size == 0)) {
		(void) fprintf(stderr,
		    gettext("%s: %s: no symbol table data\n"),
		    prog_name, filename);
		return;
	}
	count = shdr->sh_size / shdr->sh_entsize;

	/*
	 * translate symbol table data
	 */
	sym_data = readsyms(sd, count, elf_file, shdr->sh_link,
	    (unsigned int)elf_ndxscn(p_sd));
	if (sym_data == NULL) {
		(void) fprintf(stderr, gettext(
		    "%s: %s: problem reading symbol data\n"),
		    prog_name, filename);
		return;
	}
	qsort((char *)sym_data, count-1, sizeof (SYM),
	    (int (*)(const void *, const void *))compare);
	s = sym_data;
	while (count > 1) {
#ifndef XPG4
		if (u_flag) {
			/*
			 * U_flag specified
			 */
			print_with_uflag(sym_data, filename);
		} else if (p_flag)
#else
		if (p_flag)
#endif
			print_with_pflag(ndigits, elf_file, shstrndx,
			    sym_data, filename);
		else if (P_flag)
			print_with_Pflag(ndigits, elf_file, shstrndx,
			    sym_data);
		else
			print_with_otherflags(ndigits, elf_file,
			    shstrndx, sym_data, filename);
		sym_data++;
		count--;
	}

	free(s);		/* allocated in readsym() */
}
Ejemplo n.º 9
0
dt_module_update(dtrace_hdl_t *dtp, struct kld_file_stat *k_stat)
#endif
{
	char fname[MAXPATHLEN];
	struct stat64 st;
	int fd, err, bits;

	dt_module_t *dmp;
	const char *s;
	size_t shstrs;
	GElf_Shdr sh;
	Elf_Data *dp;
	Elf_Scn *sp;

#if defined(sun)
	(void) snprintf(fname, sizeof (fname),
	    "%s/%s/object", OBJFS_ROOT, name);
#else
	GElf_Ehdr ehdr;
	GElf_Phdr ph;
	char name[MAXPATHLEN];
	uintptr_t mapbase, alignmask;
	int i = 0;
	int is_elf_obj;

	(void) strlcpy(name, k_stat->name, sizeof(name));
	(void) strlcpy(fname, k_stat->pathname, sizeof(fname));
#endif

	if ((fd = open(fname, O_RDONLY)) == -1 || fstat64(fd, &st) == -1 ||
	    (dmp = dt_module_create(dtp, name)) == NULL) {
		dt_dprintf("failed to open %s: %s\n", fname, strerror(errno));
		(void) close(fd);
		return;
	}

	/*
	 * Since the module can unload out from under us (and /system/object
	 * will return ENOENT), tell libelf to cook the entire file now and
	 * then close the underlying file descriptor immediately.  If this
	 * succeeds, we know that we can continue safely using dmp->dm_elf.
	 */
	dmp->dm_elf = elf_begin(fd, ELF_C_READ, NULL);
	err = elf_cntl(dmp->dm_elf, ELF_C_FDREAD);
	(void) close(fd);

	if (dmp->dm_elf == NULL || err == -1 ||
	    elf_getshdrstrndx(dmp->dm_elf, &shstrs) == -1) {
		dt_dprintf("failed to load %s: %s\n",
		    fname, elf_errmsg(elf_errno()));
		dt_module_destroy(dtp, dmp);
		return;
	}

	switch (gelf_getclass(dmp->dm_elf)) {
	case ELFCLASS32:
		dmp->dm_ops = &dt_modops_32;
		bits = 32;
		break;
	case ELFCLASS64:
		dmp->dm_ops = &dt_modops_64;
		bits = 64;
		break;
	default:
		dt_dprintf("failed to load %s: unknown ELF class\n", fname);
		dt_module_destroy(dtp, dmp);
		return;
	}
#if defined(__FreeBSD__)
	mapbase = (uintptr_t)k_stat->address;
	gelf_getehdr(dmp->dm_elf, &ehdr);
	is_elf_obj = (ehdr.e_type == ET_REL);
	if (is_elf_obj) {
		dmp->dm_sec_offsets =
		    malloc(ehdr.e_shnum * sizeof(*dmp->dm_sec_offsets));
		if (dmp->dm_sec_offsets == NULL) {
			dt_dprintf("failed to allocate memory\n");
			dt_module_destroy(dtp, dmp);
			return;
		}
	}
#endif
	/*
	 * Iterate over the section headers locating various sections of
	 * interest and use their attributes to flesh out the dt_module_t.
	 */
	for (sp = NULL; (sp = elf_nextscn(dmp->dm_elf, sp)) != NULL; ) {
		if (gelf_getshdr(sp, &sh) == NULL || sh.sh_type == SHT_NULL ||
		    (s = elf_strptr(dmp->dm_elf, shstrs, sh.sh_name)) == NULL)
			continue; /* skip any malformed sections */
#if defined(__FreeBSD__)
		if (sh.sh_size == 0)
			continue;
		if (sh.sh_type == SHT_PROGBITS || sh.sh_type == SHT_NOBITS) {
			alignmask = sh.sh_addralign - 1;
			mapbase += alignmask;
			mapbase &= ~alignmask;
			sh.sh_addr = mapbase;
			if (is_elf_obj)
				dmp->dm_sec_offsets[elf_ndxscn(sp)] = sh.sh_addr;
			mapbase += sh.sh_size;
		}
#endif
		if (strcmp(s, ".text") == 0) {
			dmp->dm_text_size = sh.sh_size;
			dmp->dm_text_va = sh.sh_addr;
		} else if (strcmp(s, ".data") == 0) {
			dmp->dm_data_size = sh.sh_size;
			dmp->dm_data_va = sh.sh_addr;
		} else if (strcmp(s, ".bss") == 0) {
			dmp->dm_bss_size = sh.sh_size;
			dmp->dm_bss_va = sh.sh_addr;
		} else if (strcmp(s, ".info") == 0 &&
		    (dp = elf_getdata(sp, NULL)) != NULL) {
			bcopy(dp->d_buf, &dmp->dm_info,
			    MIN(sh.sh_size, sizeof (dmp->dm_info)));
		} else if (strcmp(s, ".filename") == 0 &&
		    (dp = elf_getdata(sp, NULL)) != NULL) {
			(void) strlcpy(dmp->dm_file,
			    dp->d_buf, sizeof (dmp->dm_file));
		}
	}

	dmp->dm_flags |= DT_DM_KERNEL;
#if defined(sun)
	dmp->dm_modid = (int)OBJFS_MODID(st.st_ino);
#else
	/*
	 * Include .rodata and special sections into .text.
	 * This depends on default section layout produced by GNU ld
	 * for ELF objects and libraries:
	 * [Text][R/O data][R/W data][Dynamic][BSS][Non loadable]
	 */
	dmp->dm_text_size = dmp->dm_data_va - dmp->dm_text_va;
#if defined(__i386__)
	/*
	 * Find the first load section and figure out the relocation
	 * offset for the symbols. The kernel module will not need
	 * relocation, but the kernel linker modules will.
	 */
	for (i = 0; gelf_getphdr(dmp->dm_elf, i, &ph) != NULL; i++) {
		if (ph.p_type == PT_LOAD) {
			dmp->dm_reloc_offset = k_stat->address - ph.p_vaddr;
			break;
		}
	}
#endif
#endif

	if (dmp->dm_info.objfs_info_primary)
		dmp->dm_flags |= DT_DM_PRIMARY;

	dt_dprintf("opened %d-bit module %s (%s) [%d]\n",
	    bits, dmp->dm_name, dmp->dm_file, dmp->dm_modid);
}
Ejemplo n.º 10
0
  // Extract the strings associated with the provided `DynamicTag`
  // from the DYNAMIC section of the ELF binary.
  Try<std::vector<std::string>> GetDynamicStrings(DynamicTag tag) const
  {
    if (sections.count(SectionType::DYNAMIC) == 0) {
      return Error("No DYNAMIC sections found in ELF");
    }

    if (sections.count(SectionType::DYNAMIC) != 1) {
      return Error("Multiple DYNAMIC sections found in ELF");
    }

    Elf_Scn* dynamic_section = sections.at(SectionType::DYNAMIC)[0];

    // Walk through the entries in the dynamic section and look for
    // entries with the provided tag. These entries contain offsets to
    // strings in the dynamic section's string table. Consequently, we
    // also have to look for an entry containing a pointer to the
    // dynamic section's string table so we can resolve the strings
    // associated with the provided tag later on.
    Elf_Data* dynamic_data = elf_getdata(dynamic_section, NULL);
    if (dynamic_data == NULL) {
      return Error("elf_getdata() failed: " + stringify(elf_errmsg(-1)));
    }

    Option<uintptr_t> strtab_pointer = None();
    std::vector<uintptr_t> strtab_offsets;

    for (size_t i = 0; i < dynamic_data->d_size / sizeof(GElf_Dyn); i++) {
      GElf_Dyn entry;
      if (gelf_getdyn(dynamic_data, i, &entry) == NULL) {
          return Error("gelf_getdyn() failed: " + stringify(elf_errmsg(-1)));
      }

      if ((DynamicTag)entry.d_tag == DynamicTag::STRTAB) {
        strtab_pointer = entry.d_un.d_ptr;
      }

      if ((DynamicTag)entry.d_tag == tag) {
        strtab_offsets.push_back(entry.d_un.d_ptr);
      }
    }

    if (strtab_offsets.empty()) {
      return std::vector<std::string>();
    }

    if (strtab_pointer.isNone()) {
      return Error("Failed to find string table");
    }

    // Get a reference to the actual string table so we can index into it.
    Elf_Scn* string_table_section = gelf_offscn(elf, strtab_pointer.get());
    if (string_table_section == NULL) {
      return Error("gelf_offscn() failed: " + stringify(elf_errmsg(-1)));
    }

    size_t strtab_index = elf_ndxscn(string_table_section);
    if (strtab_index == SHN_UNDEF) {
      return Error("elf_ndxscn() failed: " + stringify(elf_errmsg(-1)));
    }

    // Find the strings in the string table from their offsets and return them.
    std::vector<std::string> strings;
    foreach (uintptr_t offset, strtab_offsets) {
      char* string = elf_strptr(elf, strtab_index, offset);
      if (string == NULL) {
        return Error("elf_strptr() failed: " + stringify(elf_errmsg(-1)));
      }

      strings.push_back(string);
    }
Ejemplo n.º 11
0
int
main (int argc, char *argv[])
{
    int result = 0;
    int cnt;

    elf_version (EV_CURRENT);

    for (cnt = 1; cnt < argc; ++cnt)
    {
        int fd = open (argv[cnt], O_RDONLY);

        Elf *elf = elf_begin (fd, ELF_C_READ, NULL);
        if (elf == NULL)
        {
            printf ("%s not usable %s\n", argv[cnt], elf_errmsg (-1));
            result = 1;
            close (fd);
            continue;
        }

        size_t shdrstrndx;
        if (elf_getshdrstrndx (elf, &shdrstrndx) == -1)
        {
            printf ("elf_getshdrstrnd failed %s\n", elf_errmsg (-1));
            result = 1;
            close (fd);
            continue;
        }

        Elf_Scn *scn = NULL;
        while ((scn = elf_nextscn (elf, scn)) != NULL)
        {
            int idx = elf_ndxscn (scn);
            GElf_Shdr shdr;
            if (gelf_getshdr (scn, &shdr) == NULL)
            {
                printf ("gelf_getshdr failed: %s\n", elf_errmsg (-1));
                result = 1;
                break;
            }

            if ((shdr.sh_flags & SHF_COMPRESSED) != 0)
            {
                GElf_Chdr chdr;
                if (gelf_getchdr (scn, &chdr) == NULL)
                {
                    printf ("gelf_getchdr failed: %s\n", elf_errmsg (-1));
                    result = 1;
                    break;
                }

                printf ("section %d: ELF Compressed ch_type: %" PRId32
                        ", ch_size: %" PRIx64 ", ch_addralign: %" PRIx64 "\n",
                        idx, chdr.ch_type, chdr.ch_size, chdr.ch_addralign);
            }
            else
            {
                const char *sname = elf_strptr (elf, shdrstrndx, shdr.sh_name);
                if (sname == NULL)
                {
                    printf ("couldn't get section name: %s\n", elf_errmsg (-1));
                    result = 1;
                    break;
                }

                /* This duplicates what the dwelfgnucompressed testcase does.  */
                if (strncmp(".zdebug", sname, strlen (".zdebug")) == 0)
                {
                    ssize_t size;
                    if ((size = dwelf_scn_gnu_compressed_size (scn)) == -1)
                    {
                        printf ("dwelf_scn_gnu_compressed_size failed: %s\n",
                                elf_errmsg (-1));
                        result = 1;
                        break;
                    }
                    printf ("section %d: GNU Compressed size: %zx\n", idx, size);
                }
                else
                    printf ("section %d: NOT Compressed\n", idx);
            }
        }

        elf_end (elf);
        close (fd);
    }

    return result;
}
Ejemplo n.º 12
0
//--------------------------------------------------------------------------------
static int convElfToMiniFile(char* elffilename, char* melffilename)
{
  int fdelf, fdmelf, modhdrsymndx;
  Elf* elf;
  Elf32_Ehdr *ehdr;
  Elf_Scn *relatextscn, *textscn, *symtabscn, *strtabscn;
  
  Melf_Scn *m_relatextscn, *m_textscn, *m_symtabscn;
  Melf* melf;
  symbol_map_t* symmap;
  Melf_Data *relatextdata, *symtabdata, *textdata;
  symbol_map_t symmap_storage;

  printf("ELF File: %s\n", elffilename);
  printf("Mini-ELF File: %s\n", melffilename);
  
  symmap = &symmap_storage;
  // Open ELF file for reading
  if ((fdelf = open(elffilename, O_RDONLY)) < 0){
    fprintf(stderr, "%s: ", elffilename);
    perror("convElfToMini -> fopen: ");
    exit(EXIT_FAILURE);
  }

  // Open Mini-ELF file for writing
  if ((fdmelf = open(melffilename, (O_RDWR | O_CREAT | O_EXCL), (S_IRWXU | S_IRWXG | S_IRWXO))) < 0){
    fprintf(stderr, "%s: ", melffilename);
    perror("convElfToMini -> fopen: ");
    exit(EXIT_FAILURE);
  }

  // Check version of ELF Library
  if (elf_version(EV_CURRENT) == EV_NONE){
    fprintf(stderr, "Library version is out of date.\n");
    exit(EXIT_FAILURE);
  }

  // Get the ELF descriptor
  elf = elf_begin(fdelf, ELF_C_READ, NULL);
  if (NULL == elf){
    fprintf(stderr, "elf_begin: Error getting elf descriptor\n");
    exit(EXIT_FAILURE);
  }

  // Ensure that it is an ELF format file
  if (elf_kind(elf) != ELF_K_ELF){
    fprintf(stderr, "This program can only read ELF format files.\n");
    exit(EXIT_FAILURE);
  }

  // Get the ELF Header
  ehdr = elf32_getehdr(elf);
  if (NULL == ehdr){
    fprintf(stderr, "Error reading ELF header\n");
    exit(EXIT_FAILURE);
  }

  // Verify if the ELF is AVR specific
  if (ehdr->e_machine != EM_AVR && ehdr->e_machine != EM_MSP430){
    fprintf(stderr, "This ELF binary is not supported.\n");
    exit(EXIT_FAILURE);
  }
  e_machine = ehdr->e_machine;
                                                         
  // Create a new Mini-ELF (MELF) descriptor
  if ((melf = melf_new(fdmelf)) == NULL){
    fprintf(stderr, "Error creating a new MELF descriptor\n");
    exit(EXIT_FAILURE);
  }

  // Get the pointer to .symtab section
  if ((symtabscn = getELFSectionByName(elf, ".symtab")) == NULL){
    fprintf(stderr, "Error getting .symtab section.\n");
    exit(EXIT_FAILURE);
  }

  // Get the pointer to .rela.text section
  /*
  if ((relatextscn = getELFSectionByName(elf, ".rela.text")) == NULL){
    fprintf(stderr, "Error getting .rela.text section.\n");
    exit(EXIT_FAILURE);
  }
  */
  relatextscn = getELFSectionByName(elf, ".rela.text");

  // Get the pointer to .text section
  if ((textscn = getELFSectionByName(elf, ".text")) == NULL){
    fprintf(stderr, "Error getting .text section.\n");
    exit(EXIT_FAILURE);
  }
  
  if ((strtabscn = getELFSectionByName(elf, ".strtab")) == NULL ) {
	fprintf(stderr, "Error getting .strtab section. \n");
	exit(EXIT_FAILURE);
  }

  // DEBUG info. to verify we have the correct sections
  DEBUG("Section Number (.text): %d\n", (int)elf_ndxscn(textscn));
  if( relatextscn != NULL ) {
	  DEBUG("Section Number (.rela.text): %d\n", (int)elf_ndxscn(relatextscn));
  }
  DEBUG("Section Number (.symtab): %d\n", (int)elf_ndxscn(symtabscn));

  // Initialize Symbol Map
  if (initSymbolMap(symmap, symtabscn) < 0){
    fprintf(stderr, "Error initializing symbol map.\n");
    exit(EXIT_FAILURE);
  }
  
  //
  // Set string table to symbol map
  //
  addStrTabToSymbolMap( symmap, strtabscn );
  addTxtScnToSymbolMap( symmap, textscn );
  

  // Convert Relocation Table
  // Simon: convert relocation before text section
  //        because some symbols will be patched in .text section
  if( relatextscn != NULL ) {
  if ((relatextdata = convRelaScn(relatextscn, symmap)) == NULL){
    fprintf(stderr, "Error converting Rela table.\n");
    exit(EXIT_FAILURE);
  }
  }

  // Convert Text Section
  if ((textdata = convProgbitsScn(textscn)) == NULL){
    fprintf(stderr, "Error converting text section.\n");
    exit(EXIT_FAILURE);
  }

  // Add mod_header symbol
  if ((modhdrsymndx = getELFSymbolTableNdx(elf, "mod_header")) == -1){
    fprintf(stderr, "Could not locate symbol: mod_header. Not a valid SOS module\n");
    exit(EXIT_FAILURE);
  }
  addMelfSymbol(symmap, modhdrsymndx);
  melf_setModHdrSymNdx(melf, symmap->etommap[modhdrsymndx]);

  // Convert Symbol Table
  if ((symtabdata = convSymScn(symmap)) == NULL){
    fprintf(stderr, "Error convering symbol table.\n");
    exit(EXIT_FAILURE);
  }
  
  // Create a new MELF Symbol table section
  if ((m_symtabscn = melf_new_scn(melf)) == NULL){
    fprintf(stderr, "Error creating symbol table MELF section.\n");
    exit(EXIT_FAILURE);
  }
  convElfHdr(m_symtabscn, symtabscn);
  melf_add_data_to_scn(m_symtabscn, symtabdata);

  // Create a new MELF Relocation table section
  if( relatextscn != NULL ) {
  if ((m_relatextscn = melf_new_scn(melf)) == NULL){
    fprintf(stderr, "Error creating relocation table MELF section.\n");
    exit(EXIT_FAILURE);
  }
  convElfHdr(m_relatextscn, relatextscn);
  melf_add_data_to_scn(m_relatextscn, relatextdata);
  }

  // Create a new MELF Symbol table section
  if ((m_textscn = melf_new_scn(melf)) == NULL){
    fprintf(stderr, "Error creating .text MELF section.\n");
    exit(EXIT_FAILURE);
  }
  convElfHdr(m_textscn, textscn);
  melf_add_data_to_scn(m_textscn, textdata);
  
  // Sort the MELF Sections (Enable single pass writing on the nodes)
  melf_sortScn(melf);

  // Set the section offsets
  melf_setScnOffsets(melf);

  // Write the MELF File
  melf_write(melf);

#ifdef DBGMODE
  prettyPrintMELF(melf);
#endif

  // Close ELF Descriptor
  elf_end(elf);
  // Close ELF File
  close(fdelf);
  // Close MELF File
  close(fdmelf);
  return 0;
}
Ejemplo n.º 13
0
int
_dwarf_elf_init(Dwarf_Debug dbg, Elf *elf, Dwarf_Error *error)
{
	Dwarf_Obj_Access_Interface *iface;
	Dwarf_Elf_Object *e;
	const char *name;
	GElf_Shdr sh;
	Elf_Scn *scn;
	Elf_Data *symtab_data;
	size_t symtab_ndx;
	int elferr, i, j, n, ret;

	ret = DW_DLE_NONE;

	if ((iface = calloc(1, sizeof(*iface))) == NULL) {
		DWARF_SET_ERROR(dbg, error, DW_DLE_MEMORY);
		return (DW_DLE_MEMORY);
	}

	if ((e = calloc(1, sizeof(*e))) == NULL) {
		free(iface);
		DWARF_SET_ERROR(dbg, error, DW_DLE_MEMORY);
		return (DW_DLE_MEMORY);
	}

	e->eo_elf = elf;
	e->eo_methods.get_section_info = _dwarf_elf_get_section_info;
	e->eo_methods.get_byte_order = _dwarf_elf_get_byte_order;
	e->eo_methods.get_length_size = _dwarf_elf_get_length_size;
	e->eo_methods.get_pointer_size = _dwarf_elf_get_pointer_size;
	e->eo_methods.get_section_count = _dwarf_elf_get_section_count;
	e->eo_methods.load_section = _dwarf_elf_load_section;

	iface->object = e;
	iface->methods = &e->eo_methods;

	dbg->dbg_iface = iface;

	if (gelf_getehdr(elf, &e->eo_ehdr) == NULL) {
		DWARF_SET_ELF_ERROR(dbg, error);
		ret = DW_DLE_ELF;
		goto fail_cleanup;
	}

	dbg->dbg_machine = e->eo_ehdr.e_machine;

	if (!elf_getshstrndx(elf, &e->eo_strndx)) {
		DWARF_SET_ELF_ERROR(dbg, error);
		ret = DW_DLE_ELF;
		goto fail_cleanup;
	}

	n = 0;
	symtab_ndx = 0;
	symtab_data = NULL;
	scn = NULL;
	(void) elf_errno();
	while ((scn = elf_nextscn(elf, scn)) != NULL) {
		if (gelf_getshdr(scn, &sh) == NULL) {
			DWARF_SET_ELF_ERROR(dbg, error);
			ret = DW_DLE_ELF;
			goto fail_cleanup;
		}

		if ((name = elf_strptr(elf, e->eo_strndx, sh.sh_name)) ==
		    NULL) {
			DWARF_SET_ELF_ERROR(dbg, error);
			ret = DW_DLE_ELF;
			goto fail_cleanup;
		}

		if (!strcmp(name, ".symtab")) {
			symtab_ndx = elf_ndxscn(scn);
			if ((symtab_data = elf_getdata(scn, NULL)) == NULL) {
				elferr = elf_errno();
				if (elferr != 0) {
					_DWARF_SET_ERROR(NULL, error,
					    DW_DLE_ELF, elferr);
					ret = DW_DLE_ELF;
					goto fail_cleanup;
				}
			}
			continue;
		}

		for (i = 0; debug_name[i] != NULL; i++) {
			if (!strcmp(name, debug_name[i]))
				n++;
		}
	}
	elferr = elf_errno();
	if (elferr != 0) {
		DWARF_SET_ELF_ERROR(dbg, error);
		return (DW_DLE_ELF);
	}

	e->eo_seccnt = n;

	if (n == 0)
		return (DW_DLE_NONE);

	if ((e->eo_data = calloc(n, sizeof(Dwarf_Elf_Data))) == NULL ||
	    (e->eo_shdr = calloc(n, sizeof(GElf_Shdr))) == NULL) {
		DWARF_SET_ERROR(NULL, error, DW_DLE_MEMORY);
		ret = DW_DLE_MEMORY;
		goto fail_cleanup;
	}

	scn = NULL;
	j = 0;
	while ((scn = elf_nextscn(elf, scn)) != NULL && j < n) {
		if (gelf_getshdr(scn, &sh) == NULL) {
			DWARF_SET_ELF_ERROR(dbg, error);
			ret = DW_DLE_ELF;
			goto fail_cleanup;
		}

		memcpy(&e->eo_shdr[j], &sh, sizeof(sh));

		if ((name = elf_strptr(elf, e->eo_strndx, sh.sh_name)) ==
		    NULL) {
			DWARF_SET_ELF_ERROR(dbg, error);
			ret = DW_DLE_ELF;
			goto fail_cleanup;
		}

		for (i = 0; debug_name[i] != NULL; i++) {
			if (strcmp(name, debug_name[i]))
				continue;

			(void) elf_errno();
			if ((e->eo_data[j].ed_data = elf_getdata(scn, NULL)) ==
			    NULL) {
				elferr = elf_errno();
				if (elferr != 0) {
					_DWARF_SET_ERROR(dbg, error,
					    DW_DLE_ELF, elferr);
					ret = DW_DLE_ELF;
					goto fail_cleanup;
				}
			}

			if (_libdwarf.applyrela) {
				if (_dwarf_elf_relocate(dbg, elf,
				    &e->eo_data[j], elf_ndxscn(scn), symtab_ndx,
				    symtab_data, error) != DW_DLE_NONE)
					goto fail_cleanup;
			}

			j++;
		}
	}

	assert(j == n);

	return (DW_DLE_NONE);

fail_cleanup:

	_dwarf_elf_deinit(dbg);

	return (ret);
}
Ejemplo n.º 14
0
static void
print_symtab(Elf *elf, const char *file)
{
	Elf_Scn		*scn = NULL;
	GElf_Shdr	shdr;
	GElf_Ehdr	ehdr;
	size_t		shstrndx;


	if (gelf_getehdr(elf, &ehdr) == NULL) {
		(void) fprintf(stderr, "%s: elf_getehdr() failed: %s\n",
		    file, elf_errmsg(0));
		return;
	}

	if (elf_getshdrstrndx(elf, &shstrndx) == -1) {
		(void) fprintf(stderr, "%s: elf_getshdrstrndx() failed: %s\n",
		    file, elf_errmsg(0));
		return;
	}

	while ((scn = elf_nextscn(elf, scn)) != NULL) {
		uint_t		symcnt, ndx, nosymshndx;
		Elf_Data	*symdata, *shndxdata;

		if (gelf_getshdr(scn, &shdr) == NULL) {
			(void) fprintf(stderr,
			    "%s: elf_getshdr() failed: %s\n",
			    file, elf_errmsg(0));
			return;
		}
		if ((shdr.sh_type != SHT_SYMTAB) &&
		    (shdr.sh_type != SHT_DYNSYM) &&
		    (shdr.sh_type != SHT_SUNW_LDYNSYM))
			continue;

		/*
		 * Get the data associated with the Symbol
		 * section.
		 */
		if ((symdata = elf_getdata(scn, NULL)) == NULL) {
			(void) fprintf(stderr,
			    "%s: elf_getdata() failed: %s\n",
			    file, elf_errmsg(0));
			return;
		}

		/*
		 * Print symbol table title and header for symbol display
		 */
		(void) printf("\nSymTab: %s:%s\n", file,
		    elf_strptr(elf, shstrndx, shdr.sh_name));
		(void) printf("  index   value    size     type "
		    "bind  oth shndx name\n");

		/*
		 * We now iterate over the full symbol table printing
		 * the symbols as we go.
		 */
		shndxdata = 0;
		nosymshndx = 0;
		symcnt = shdr.sh_size / shdr.sh_entsize;
		for (ndx = 0; ndx < symcnt; ndx++) {
			GElf_Sym	sym;
			Elf32_Word	shndx;
			uint_t		type, bind, specshndx;
			char		bindbuf[INTSTRLEN];
			char		typebuf[INTSTRLEN];
			char		shndxbuf[INTSTRLEN];
			const char	*bindstr, *typestr, *shndxstr;

			/*
			 * Get a symbol entry
			 */
			if (gelf_getsymshndx(symdata, shndxdata, ndx,
			    &sym, &shndx) == NULL) {
				(void) fprintf(stderr,
				    "%s: gelf_getsymshndx() failed: %s\n",
				    file, elf_errmsg(0));
				return;
			}
			/*
			 * Check to see if this symbol's st_shndx is using
			 * the 'Extended SHNDX table' for a SYMTAB.
			 *
			 * If it is - and we haven't searched before, go
			 * find the associated SHT_SYMTAB_SHNDX section.
			 */
			if ((sym.st_shndx == SHN_XINDEX) &&
			    (shndxdata == 0) && (nosymshndx == 0)) {
				Elf_Scn		*_scn = NULL;
				GElf_Shdr	_shdr;
				GElf_Word	symscnndx;

				specshndx = 0;
				symscnndx = elf_ndxscn(scn);

				while ((_scn =
				    elf_nextscn(elf, _scn)) != NULL) {
					if (gelf_getshdr(_scn, &_shdr) == NULL)
						break;

					/*
					 * We've found the Symtab SHNDX table
					 * if it's of type SHT_SYMTAB_SHNDX
					 * and it's shdr.sh_link points to the
					 * section index for the current symbol
					 * table.
					 */
					if ((_shdr.sh_type ==
					    SHT_SYMTAB_SHNDX) &&
					    (_shdr.sh_link == symscnndx) &&
					    ((shndxdata = elf_getdata(_scn,
					    NULL)) != NULL))
						break;
				}
				/*
				 * Get a symbol entry
				 */
				if (shndxdata &&
				    (gelf_getsymshndx(symdata, shndxdata, ndx,
				    &sym, &shndx) == NULL)) {
					(void) fprintf(stderr,
					    "%s: gelf_getsymshndx() "
					    "failed: %s\n",
					    file, elf_errmsg(0));
					return;
				}
				/*
				 * No Symtab SHNDX table was found.  We could
				 * give a fatal error here - instead we'll
				 * just mark that fact and display as much of
				 * the symbol table as we can.  Any symbol
				 * displayed with a XINDX section index has
				 * a bogus value.
				 */
				if (shndxdata == 0)
					nosymshndx = 1;
			}

			/*
			 * Decode the type & binding information
			 */
			type = GELF_ST_TYPE(sym.st_info);
			bind = GELF_ST_BIND(sym.st_info);

			if (type < STT_NUM)
				typestr = symtype[type];
			else {
				(void) snprintf(typebuf, INTSTRLEN,
				    "%d", type);
				typestr = typebuf;
			}

			if (bind < STB_NUM)
				bindstr = symbind[bind];
			else {
				(void) snprintf(bindbuf, INTSTRLEN,
				    "%d", bind);
				bindstr = bindbuf;
			}


			specshndx = 0;
			if (sym.st_shndx <  SHN_LORESERVE)
				shndx = sym.st_shndx;
			else if ((sym.st_shndx != SHN_XINDEX) ||
			    (shndxdata == NULL)) {
				shndx = sym.st_shndx;
				specshndx = 1;
			}

			if (shndx == SHN_UNDEF) {
				shndxstr = (const char *)"UNDEF";

			} else if (specshndx) {
				if (shndx == SHN_ABS)
					shndxstr = (const char *)"ABS";
				else if (shndx == SHN_COMMON)
					shndxstr = (const char *)"COMM";
				else if (shndx == SHN_XINDEX)
					shndxstr = (const char *)"XIND";
				else {
					(void) snprintf(shndxbuf, INTSTRLEN,
					    "%ld", shndx);
					shndxstr = shndxbuf;
				}
			} else {
				(void) snprintf(shndxbuf, INTSTRLEN,
				    "%ld", shndx);
				shndxstr = shndxbuf;
			}

			/*
			 * Display the symbol entry.
			 */
			(void) printf("[%3d] 0x%08llx 0x%08llx %-4s "
			    "%-6s %2d %5s %s\n",
			    ndx, sym.st_value, sym.st_size,
			    typestr, bindstr, sym.st_other, shndxstr,
			    elf_strptr(elf, shdr.sh_link, sym.st_name));
		}
	}
}
Ejemplo n.º 15
0
Elf_Scn *symtab_write_elf(Elf *e, struct sect * sects,
						  struct buffer *strtab_buf, struct buffer *shstrtab_buf)
{
  unsigned i, k;
  struct sym_info *sym;
  Elf32_Sym esym;

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

  struct buffer buf;
  struct buffer *relbuf;

  struct sect *s;

  buffer_init(&buf);

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

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

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

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

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

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

			  esym.st_other = ELF32_ST_VISIBILITY(STV_DEFAULT);

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

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

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

  scn = xelf_newscn(e);

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

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

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

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

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

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

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

  return scn;
}
Ejemplo n.º 16
0
int main()
{
    Dwarf_Error error = 0;
    Dwarf_P_Debug dw = dwarf_producer_init_c(DW_DLC_WRITE | DW_DLC_SIZE_64,
                       createSectionCallback,
                       /* error handler */0,
                       /* error arg */0,
                       /* user data */0,
                       &error);
    if (error != 0)
        die("dwarf_producer_init_c failed");

    Dwarf_Unsigned cie = dwarf_add_frame_cie(dw,
                         "",
                         /* code alignment factor */QT_POINTER_SIZE,
                         /* data alignment factor */-QT_POINTER_SIZE,
                         /* return address reg*/InstructionPointerRegister,
                         cie_init_instructions,
                         sizeof(cie_init_instructions),
                         &error);
    if (error != 0)
        die("dwarf_add_frame_cie failed");

    Dwarf_P_Fde fde = dwarf_new_fde(dw, &error);
    if (error != 0)
        die("dwarf_new_fde failed");

    /* New entry in state machine for code offset 1 after push rbp instruction */
    dwarf_add_fde_inst(fde,
                       DW_CFA_advance_loc,
                       /*offset in code alignment units*/ 1,
                       /* unused*/ 0,
                       &error);

    /* After "push rbp" the offset to the CFA is now 2 instead of 1 */
    dwarf_add_fde_inst(fde,
                       DW_CFA_def_cfa_offset_sf,
                       /*offset in code alignment units*/ -2,
                       /* unused*/ 0,
                       &error);

    /* After "push rbp" the value of rbp is now stored at offset 1 from CFA */
    dwarf_add_fde_inst(fde,
                       DW_CFA_offset,
                       StackFrameRegister,
                       2,
                       &error);

    /* New entry in state machine for code offset 3 for mov rbp, rsp instruction */
    dwarf_add_fde_inst(fde,
                       DW_CFA_advance_loc,
                       /*offset in code alignment units*/ 3,
                       /* unused */ 0,
                       &error);

    /* After "mov rbp, rsp" the cfa is reachable via rbp */
    dwarf_add_fde_inst(fde,
                       DW_CFA_def_cfa_register,
                       StackFrameRegister,
                       /* unused */0,
                       &error);

    /* Callee saved registers */
    for (int i = 0; i < calleeSavedRegisterCount; ++i) {
        dwarf_add_fde_inst(fde,
                           DW_CFA_offset,
                           calleeSavedRegisters[i],
                           i + 3,
                           &error);
    }

    dwarf_add_frame_fde(dw, fde,
                        /* die */0,
                        cie,
                        /*virt addr */0,
                        /* length of code */0,
                        /* symbol index */0,
                        &error);
    if (error != 0)
        die("dwarf_add_frame_fde failed");

    dwarf_transform_to_disk_form(dw, &error);
    if (error != 0)
        die("dwarf_transform_to_disk_form failed");

    Dwarf_Unsigned len = 0;
    Dwarf_Signed elfIdx = 0;
    unsigned char *bytes = (unsigned char *)dwarf_get_section_bytes(dw, /* section */1,
                           &elfIdx, &len, &error);
    if (error != 0)
        die("dwarf_get_section_bytes failed");

    // libdwarf doesn't add a terminating FDE with zero length, so let's add one
    // ourselves.
    unsigned char *newBytes = (unsigned char *)alloca(len + 4);
    memcpy(newBytes, bytes, len);
    newBytes[len] = 0;
    newBytes[len + 1] = 0;
    newBytes[len + 2] = 0;
    newBytes[len + 3] = 0;
    newBytes[len + 4] = 0;
    bytes = newBytes;
    len += 4;

    // Reset CIE-ID back to 0 as expected for .eh_frames
    bytes[4] = 0;
    bytes[5] = 0;
    bytes[6] = 0;
    bytes[7] = 0;

    unsigned fde_offset = bytes[0] + 4;

    bytes[fde_offset + 4] = fde_offset + 4;

    printf("static const unsigned char cie_fde_data[] = {\n");
    int i = 0;
    while (i < len) {
        printf("    ");
        for (int j = 0; i < len && j < 8; ++j, ++i)
            printf("0x%x, ", bytes[i]);
        printf("\n");
    }
    printf("};\n");

    printf("static const int fde_offset = %d;\n", fde_offset);
    printf("static const int initial_location_offset = %d;\n", fde_offset + 8);
    printf("static const int address_range_offset = %d;\n", fde_offset + 8 + QT_POINTER_SIZE);

#ifdef DEBUG
    {
        if (elf_version(EV_CURRENT) == EV_NONE)
            die("wrong elf version");
        int fd = open("debug.o", O_WRONLY | O_CREAT, 0777);
        if (fd < 0)
            die("cannot create debug.o");

        Elf *e = elf_begin(fd, ELF_C_WRITE, 0);
        if (!e)
            die("elf_begin failed");

        Elf_Ehdr *ehdr = elf_newehdr(e);
        if (!ehdr)
            die(elf_errmsg(-1));

        ehdr->e_ident[EI_DATA] = ELFDATA2LSB;
#if defined(Q_PROCESSOR_X86_64)
        ehdr->e_machine = EM_X86_64;
#elif defined(Q_PROCESSOR_X86)
        ehdr->e_machine = EM_386;
#else
#error port me :)
#endif
        ehdr->e_type = ET_EXEC;
        ehdr->e_version = EV_CURRENT;

        Elf_Scn *section = elf_newscn(e);
        if (!section)
            die("elf_newscn failed");

        Elf_Data *data = elf_newdata(section);
        if (!data)
            die(elf_errmsg(-1));
        data->d_align = 4;
        data->d_off = 0;
        data->d_buf = bytes;
        data->d_size = len;
        data->d_type = ELF_T_BYTE;
        data->d_version = EV_CURRENT;

        Elf_Shdr *shdr = elf_getshdr(section);
        if (!shdr)
            die(elf_errmsg(-1));

        shdr->sh_name = 1;
        shdr->sh_type = SHT_PROGBITS;
        shdr->sh_entsize = 0;

        char stringTable[] = {
            0,
            '.', 'e', 'h', '_', 'f', 'r', 'a', 'm', 'e', 0,
            '.', 's', 'h', 's', 't', 'r', 't', 'a', 'b', 0
        };

        section = elf_newscn(e);
        if (!section)
            die("elf_newscn failed");

        data = elf_newdata(section);
        if (!data)
            die(elf_errmsg(-1));
        data->d_align = 1;
        data->d_off = 0;
        data->d_buf = stringTable;
        data->d_size = sizeof(stringTable);
        data->d_type = ELF_T_BYTE;
        data->d_version = EV_CURRENT;

        shdr = elf_getshdr(section);
        if (!shdr)
            die(elf_errmsg(-1));

        shdr->sh_name = 11;
        shdr->sh_type = SHT_STRTAB;
        shdr->sh_flags = SHF_STRINGS | SHF_ALLOC;
        shdr->sh_entsize = 0;

        ehdr->e_shstrndx = elf_ndxscn(section);

        if (elf_update(e, ELF_C_WRITE) < 0)
            die(elf_errmsg(-1));

        elf_end(e);
        close(fd);
    }
#endif

    dwarf_producer_finish(dw, &error);
    if (error != 0)
        die("dwarf_producer_finish failed");
    return 0;
}
Ejemplo n.º 17
0
int
rewrite_code_section(elf_data_t *elf, inject_data_t *inject, char **err)
{
  Elf_Scn *scn;
  GElf_Shdr shdr;
  char *s;
  size_t shstrndx;

  if(elf_getshdrstrndx(elf->e, &shstrndx) < 0) {
    (*err) = "failed to get string table section index";
    return -1;
  }

  printf("shstrndx : %d\n",shstrndx);

  scn = NULL;
  while((scn = elf_nextscn(elf->e, scn))) {
    if(!gelf_getshdr(scn, &shdr)) {
      (*err) = "failed to get section header";
      return -1;
    }

    s = elf_strptr(elf->e, shstrndx, shdr.sh_name);
    if(!s) {
      (*err) = "failed to get section name";
      return -1;
    }
  	printf("section : %s\n",s);

    if(!strcmp(s, ABITAG_NAME)) {
      shdr.sh_name      = shdr.sh_name;              /* offset into string table */
      shdr.sh_type      = SHT_PROGBITS;              /* type */
      shdr.sh_flags     = SHF_ALLOC | SHF_EXECINSTR; /* flags */
      shdr.sh_addr      = inject->secaddr;           /* address to load section at */
      shdr.sh_offset    = inject->off;               /* file offset to start of section */
      shdr.sh_size      = inject->len;               /* size in bytes */
      shdr.sh_link      = 0;                         /* not used for code section */
      shdr.sh_info      = 0;                         /* not used for code section */
      shdr.sh_addralign = 16;                        /* memory alignment */
      shdr.sh_entsize   = 0;                         /* not used for code section */

      verbose("rewriting section header %lu:", elf_ndxscn(scn));
      verbose("  sh_name      = %u", shdr.sh_name);
      verbose("  sh_type      = SHT_PROGBITS");
      verbose("  sh_flags     = SHF_ALLOC | SHF_EXECINSTR"); 
      verbose("  sh_addr      = 0x%x", shdr.sh_addr);
      verbose("  sh_offset    = %lu", shdr.sh_offset);
      verbose("  sh_size      = %lu", shdr.sh_size);
      verbose("  sh_link      = 0");
      verbose("  sh_info      = 0");
      verbose("  sh_addralign = 0x%x", shdr.sh_addralign);
      verbose("  sh_entsize   = 0");

      inject->sidx = elf_ndxscn(scn);
      inject->scn = scn;
      memcpy(&inject->shdr, &shdr, sizeof(shdr));

      verbose("writing section header to file");

      if(write_shdr(elf, scn, &shdr, elf_ndxscn(scn), err) < 0) {
        return -1;
      }

      if(reorder_shdrs(elf, inject, err) < 0) {
        return -1;
      }

      break;
    }
  }

  if(!scn) {
    (*err) = "cannot find section to rewrite";
    return -1;
  }

  return 0;
}
Ejemplo n.º 18
0
int
reorder_shdrs(elf_data_t *elf, inject_data_t *inject, char **err)
{
  int direction, skip;
  size_t i;
  Elf_Scn *scn;
  GElf_Shdr shdr;

  direction = 0;

  scn = elf_getscn(elf->e, inject->sidx - 1);
  if(scn && !gelf_getshdr(scn, &shdr)) {
    (*err) = "failed to get section header";
    return -1;
  }
  if(scn && shdr.sh_addr > inject->shdr.sh_addr) {
    /* Injected section header must be moved left */
    direction = -1;
  }

  scn = elf_getscn(elf->e, inject->sidx + 1);
  if(scn && !gelf_getshdr(scn, &shdr)) {
    (*err) = "failed to get section header";
    return -1;
  }
  if(scn && shdr.sh_addr < inject->shdr.sh_addr) {
    /* Injected section header must be moved right */
    direction = 1;
  }

  if(direction == 0) {
    /* Section headers are already in order */
    return 0;
  }

  i = inject->sidx;

  /* Order section headers by increasing address */
  skip = 0;
  for(scn = elf_getscn(elf->e, inject->sidx + direction); 
      scn != NULL;
      scn = elf_getscn(elf->e, inject->sidx + direction + skip)) {
    if(!gelf_getshdr(scn, &shdr)) {
      (*err) = "failed to get section header";
      return -1;
    }

    if((direction < 0 && shdr.sh_addr <= inject->shdr.sh_addr)
       || (direction > 0 && shdr.sh_addr >= inject->shdr.sh_addr)) {
      /* The order is okay from this point on */
      break;
    }

    /* Only reorder code section headers */
    if(shdr.sh_type != SHT_PROGBITS) {
      skip += direction;
      continue;
    }

    /* Swap the injected shdr with its neighbor progbits header */
    if(write_shdr(elf, scn, &inject->shdr, elf_ndxscn(scn), err) < 0) {
      return -1;
    }
    if(write_shdr(elf, inject->scn, &shdr, inject->sidx, err) < 0) {
      return -1;
    }

    inject->sidx += direction + skip;
    inject->scn = elf_getscn(elf->e, inject->sidx);
    skip = 0;
  }

  verbose("reordered sections %lu - %lu", i, inject->sidx);

  return 0;
}
Ejemplo n.º 19
0
static int
cache_sections (Dwfl_Module *mod)
{
  struct secref *refs = NULL;
  size_t nrefs = 0;

  size_t shstrndx;
  if (unlikely (elf_getshdrstrndx (mod->main.elf, &shstrndx) < 0))
    {
    elf_error:
      __libdwfl_seterrno (DWFL_E_LIBELF);
      return -1;
    }

  bool check_reloc_sections = false;
  Elf_Scn *scn = NULL;
  while ((scn = elf_nextscn (mod->main.elf, scn)) != NULL)
    {
      GElf_Shdr shdr_mem;
      GElf_Shdr *shdr = gelf_getshdr (scn, &shdr_mem);
      if (shdr == NULL)
	goto elf_error;

      if ((shdr->sh_flags & SHF_ALLOC) && shdr->sh_addr == 0
	  && mod->e_type == ET_REL)
	{
	  /* This section might not yet have been looked at.  */
	  if (__libdwfl_relocate_value (mod, mod->main.elf, &shstrndx,
					elf_ndxscn (scn),
					&shdr->sh_addr) != DWFL_E_NOERROR)
	    continue;
	  shdr = gelf_getshdr (scn, &shdr_mem);
	  if (unlikely (shdr == NULL))
	    goto elf_error;
	}

      if (shdr->sh_flags & SHF_ALLOC)
	{
	  const char *name = elf_strptr (mod->main.elf, shstrndx,
					 shdr->sh_name);
	  if (unlikely (name == NULL))
	    goto elf_error;

	  struct secref *newref = alloca (sizeof *newref);
	  newref->scn = scn;
	  newref->relocs = NULL;
	  newref->name = name;
	  newref->start = dwfl_adjusted_address (mod, shdr->sh_addr);
	  newref->end = newref->start + shdr->sh_size;
	  newref->next = refs;
	  refs = newref;
	  ++nrefs;
	}

      if (mod->e_type == ET_REL
	  && shdr->sh_size != 0
	  && (shdr->sh_type == SHT_REL || shdr->sh_type == SHT_RELA)
	  && mod->dwfl->callbacks->section_address != NULL)
	{
	  if (shdr->sh_info < elf_ndxscn (scn))
	    {
	      /* We've already looked at the section these relocs apply to.  */
	      Elf_Scn *tscn = elf_getscn (mod->main.elf, shdr->sh_info);
	      if (likely (tscn != NULL))
		for (struct secref *sec = refs; sec != NULL; sec = sec->next)
		  if (sec->scn == tscn)
		    {
		      sec->relocs = scn;
		      break;
		    }
	    }
	  else
	    /* We'll have to do a second pass.  */
	    check_reloc_sections = true;
	}
    }

  mod->reloc_info = malloc (offsetof (struct dwfl_relocation, refs[nrefs]));
  if (mod->reloc_info == NULL)
    {
      __libdwfl_seterrno (DWFL_E_NOMEM);
      return -1;
    }

  struct secref **sortrefs = alloca (nrefs * sizeof sortrefs[0]);
  for (size_t i = nrefs; i-- > 0; refs = refs->next)
    sortrefs[i] = refs;
  assert (refs == NULL);

  qsort (sortrefs, nrefs, sizeof sortrefs[0], &compare_secrefs);

  mod->reloc_info->count = nrefs;
  for (size_t i = 0; i < nrefs; ++i)
    {
      mod->reloc_info->refs[i].name = sortrefs[i]->name;
      mod->reloc_info->refs[i].scn = sortrefs[i]->scn;
      mod->reloc_info->refs[i].relocs = sortrefs[i]->relocs;
      mod->reloc_info->refs[i].start = sortrefs[i]->start;
      mod->reloc_info->refs[i].end = sortrefs[i]->end;
    }

  if (unlikely (check_reloc_sections))
    {
      /* There was a reloc section that preceded its target section.
	 So we have to scan again now that we have cached all the
	 possible target sections we care about.  */

      scn = NULL;
      while ((scn = elf_nextscn (mod->main.elf, scn)) != NULL)
	{
	  GElf_Shdr shdr_mem;
	  GElf_Shdr *shdr = gelf_getshdr (scn, &shdr_mem);
	  if (shdr == NULL)
	    goto elf_error;

      	  if (shdr->sh_size != 0
	      && (shdr->sh_type == SHT_REL || shdr->sh_type == SHT_RELA))
	    {
	      Elf_Scn *tscn = elf_getscn (mod->main.elf, shdr->sh_info);
	      if (likely (tscn != NULL))
		for (size_t i = 0; i < nrefs; ++i)
		  if (mod->reloc_info->refs[i].scn == tscn)
		    {
		      mod->reloc_info->refs[i].relocs = scn;
		      break;
		    }
	    }
	}
    }

  return nrefs;
}
Ejemplo n.º 20
0
int main(int argc, const char *argv[]) {
    ssize_t bytes_written; // only used to silence compiler warnings 
    if (argc < 2)
        errx(EX_USAGE, "Usage: PatchEntry <binary>");

    if (elf_version(EV_CURRENT) == EV_NONE)
        errx(EX_SOFTWARE, "Invalid ELF version: %s", elf_errmsg(-1));

    int fd = open(argv[1], O_RDWR);
    if (fd == -1)
        err(EX_NOINPUT, "open() failed");

    Elf *e;
    e = elf_begin(fd, ELF_C_RDWR, NULL);
    if (e == nullptr)
        errx(EX_SOFTWARE, "Failed to read from ELF file: %s", elf_errmsg(-1));

    if (elf_kind(e) != ELF_K_ELF)
        errx(EX_SOFTWARE, "File is not an ELF object");

    // Read the ELF header to find the entry point
    // FIXME: check the class/architecture, make sure it's the same as ours
    GElf_Ehdr elf_hdr;
    if (gelf_getehdr(e, &elf_hdr) == NULL)
        errx(EX_SOFTWARE, "Failed to read ELF header: %s", elf_errmsg(-1));

    auto dt_init = FindDynamicInit(e);
    auto dt_init_ofs = 0;
    if (dt_init) {
        dt_init_ofs = dt_init->info.second.sh_offset +
                      dt_init->data->d_off +
                      dt_init->index * sizeof(Elf_Dyn) +
                      offsetof(Elf_Dyn, d_un);
    }

    auto pit_sym = FindSymbol(e, kProgramInfoTableName);
    auto pit_info = FindSectionDataByAddr(e, pit_sym.st_value);
    auto pit_ofs = std::get<0>(pit_info).second.sh_offset + // Section file offset
                   std::get<1>(pit_info)->d_off +           // Elf_Data offset
                   std::get<2>(pit_info);                   // Offset relative to Elf_Data
#if 1
    if (dt_init)
        printf("Old ELF entry:%p DT_INIT:%p@%x PIT:%p@%lx\n",
               (void*) elf_hdr.e_entry,
               (void*) dt_init->dyn_section.d_un.d_ptr,
               dt_init_ofs,
               (void*) pit_sym.st_value,
               pit_ofs);
    else
        printf("Old ELF entry:%p DT_INIT:NULL PIT:%p@%lx\n",
               (void*) elf_hdr.e_entry,
               (void*) pit_sym.st_value,
               pit_ofs);
#endif

    // Replace the ProgramInfoTable values
    auto pit_data = std::get<1>(pit_info);
    auto orig_pit = reinterpret_cast<TrapProgramInfoTable*>(
        reinterpret_cast<uint8_t*>(pit_data->d_buf) + std::get<2>(pit_info));
    TrapProgramInfoTable pit = *orig_pit; // Need to copy it here, since elf_end releases it
    if (pit.num_sections != 0)
       errx(EX_USAGE, "Binary already contains full ProgramInfoTable structure");
    if (dt_init)
        pit.orig_dt_init = dt_init->dyn_section.d_un.d_ptr;
    else
        pit.orig_dt_init = 0;
    pit.orig_entry = elf_hdr.e_entry;

    // Find executable sections in the binary (.text/.plt/others)
    // then copy them over to the PIT
    pit.num_sections = TRAP_NUM_SECTIONS;
    for (size_t i = 0; i < TRAP_NUM_SECTIONS; i++) {
        auto sec_info = FindSectionByName(e, kExecSections[i][0]);
        if (sec_info.first != nullptr) {
            pit.sections[i].start = sec_info.second.sh_addr;
            pit.sections[i].size = sec_info.second.sh_size;
        }
        auto trap_sec_info = FindSectionByName(e, kExecSections[i][1]);
        if (trap_sec_info.first != nullptr) {
            pit.sections[i].trap = trap_sec_info.second.sh_addr;
            pit.sections[i].trap_size = trap_sec_info.second.sh_size;
        }
    }

    // Set the new entry point addresses
    auto entry_trampoline_sym = FindSymbol(e, kEntryTrampolineName);
    auto init_trampoline_sym  = FindSymbol(e, kInitTrampolineName);
    elf_hdr.e_entry = entry_trampoline_sym.st_value;
    auto new_dt_init = static_cast<ArchPointer>(init_trampoline_sym.st_value);

    // Find export trampolines
    auto xptramp_info = FindSectionByName(e, ".xptramp");
    DynamicSymbolMap dyn_sym_map;
    ExportTrampolineVector xptramp_vec;
    size_t xptramp_shndx = 0;
    if (xptramp_info.first != nullptr) {
        pit.xptramp_start = xptramp_info.second.sh_addr;
        pit.xptramp_size  = xptramp_info.second.sh_size;
        dyn_sym_map = FindDynamicSymbols(e);
        xptramp_vec = FindExportTrampolines(e, xptramp_info);
        xptramp_shndx = elf_ndxscn(xptramp_info.first);
    }

    // Update the ELF header, then write it out
    // There's some pretty ugly behavior from libelf here:
    // if we let it handle the layout, it mis-aligns the data sections
    // It also doesn't seem to update the contents correctly,
    // so we do that manually
    elf_flagelf(e, ELF_C_SET, ELF_F_LAYOUT);
    gelf_update_ehdr(e, &elf_hdr);
    if (elf_update(e, ELF_C_WRITE) <= 0)
        errx(EX_SOFTWARE, "Couldn't update ELF file: %s", elf_errmsg(-1));
    elf_end(e);

    // FIXME: libelf shenanigans force us to
    // write data out to the file manually
    // 1) DT_INIT inside .dynamic
    if (dt_init) {
        printf("writing new DT_INIT: 0x%lu\n", new_dt_init);
        lseek(fd, dt_init_ofs, SEEK_SET);
        bytes_written = write(fd, &new_dt_init, sizeof(new_dt_init));
    }
    // 2) The ProgramInfoTable
    lseek(fd, pit_ofs, SEEK_SET);
    bytes_written = write(fd, &pit, sizeof(pit));
    // 3) Exported symbols
    WriteExportSymbols(fd, xptramp_info, xptramp_vec, xptramp_shndx, dyn_sym_map);
    close(fd);
    return 0;
}
const char *
dwfl_module_addrsym (Dwfl_Module *mod, GElf_Addr addr,
		     GElf_Sym *closest_sym, GElf_Word *shndxp)
{
  int syments = INTUSE(dwfl_module_getsymtab) (mod);
  if (syments < 0)
    return NULL;

  /* Return true iff we consider ADDR to lie in the same section as SYM.  */
  GElf_Word addr_shndx = SHN_UNDEF;
  inline bool same_section (const GElf_Sym *sym, GElf_Word shndx)
    {
      /* For absolute symbols and the like, only match exactly.  */
      if (shndx >= SHN_LORESERVE)
	return sym->st_value == addr;

      /* Figure out what section ADDR lies in.  */
      if (addr_shndx == SHN_UNDEF)
	{
	  GElf_Addr mod_addr = dwfl_deadjust_st_value (mod, addr);
	  Elf_Scn *scn = NULL;
	  addr_shndx = SHN_ABS;
	  while ((scn = elf_nextscn (mod->symfile->elf, scn)) != NULL)
	    {
	      GElf_Shdr shdr_mem;
	      GElf_Shdr *shdr = gelf_getshdr (scn, &shdr_mem);
	      if (likely (shdr != NULL)
		  && mod_addr >= shdr->sh_addr
		  && mod_addr < shdr->sh_addr + shdr->sh_size)
		{
		  addr_shndx = elf_ndxscn (scn);
		  break;
		}
	    }
	}

      return shndx == addr_shndx;
    }

  /* Keep track of the closest symbol we have seen so far.
     Here we store only symbols with nonzero st_size.  */
  const char *closest_name = NULL;
  GElf_Word closest_shndx = SHN_UNDEF;

  /* Keep track of an eligible symbol with st_size == 0 as a fallback.  */
  const char *sizeless_name = NULL;
  GElf_Sym sizeless_sym = { 0, 0, 0, 0, 0, SHN_UNDEF };
  GElf_Word sizeless_shndx = SHN_UNDEF;

  /* Keep track of the lowest address a relevant sizeless symbol could have.  */
  GElf_Addr min_label = 0;

  /* Look through the symbol table for a matching symbol.  */
  inline void search_table (int start, int end)
    {
      for (int i = start; i < end; ++i)
	{
	  GElf_Sym sym;
	  GElf_Word shndx;
	  const char *name = INTUSE(dwfl_module_getsym) (mod, i, &sym, &shndx);
	  if (name != NULL && name[0] != '\0'
	      && sym.st_shndx != SHN_UNDEF
	      && sym.st_value <= addr
	      && GELF_ST_TYPE (sym.st_info) != STT_SECTION
	      && GELF_ST_TYPE (sym.st_info) != STT_FILE
	      && GELF_ST_TYPE (sym.st_info) != STT_TLS)
	    {
	      /* Even if we don't choose this symbol, its existence excludes
		 any sizeless symbol (assembly label) that is below its upper
		 bound.  */
	      if (sym.st_value + sym.st_size > min_label)
		min_label = sym.st_value + sym.st_size;

	      if (sym.st_size == 0 || addr - sym.st_value < sym.st_size)
		{
		  /* This symbol is a better candidate than the current one
		     if it's closer to ADDR or is global when it was local.  */
		  if (closest_name == NULL
		      || closest_sym->st_value < sym.st_value
		      || (GELF_ST_BIND (closest_sym->st_info)
			  < GELF_ST_BIND (sym.st_info)))
		    {
		      if (sym.st_size != 0)
			{
			  *closest_sym = sym;
			  closest_shndx = shndx;
			  closest_name = name;
			}
		      else if (closest_name == NULL
			       && sym.st_value >= min_label
			       && same_section (&sym, shndx))
			{
			  /* Handwritten assembly symbols sometimes have no
			     st_size.  If no symbol with proper size includes
			     the address, we'll use the closest one that is in
			     the same section as ADDR.  */
			  sizeless_sym = sym;
			  sizeless_shndx = shndx;
			  sizeless_name = name;
			}
		    }
		  /* When the beginning of its range is no closer,
		     the end of its range might be.  But do not
		     replace a global symbol with a local!  */
		  else if (sym.st_size != 0
			   && closest_sym->st_value == sym.st_value
			   && closest_sym->st_size > sym.st_size
			   && (GELF_ST_BIND (closest_sym->st_info)
			       <= GELF_ST_BIND (sym.st_info)))
		    {
		      *closest_sym = sym;
		      closest_shndx = shndx;
		      closest_name = name;
		    }
		}
	    }
	}
    }

  /* First go through global symbols.  mod->first_global is setup by
     dwfl_module_getsymtab to the index of the first global symbol in
     the module's symbol table, or -1 when unknown.  All symbols with
     local binding come first in the symbol table, then all globals.  */
  search_table (mod->first_global < 0 ? 1 : mod->first_global, syments);

  /* If we found nothing searching the global symbols, then try the locals.
     Unless we have a global sizeless symbol that matches exactly.  */
  if (closest_name == NULL && mod->first_global > 1
      && (sizeless_name == NULL || sizeless_sym.st_value != addr))
    search_table (1, mod->first_global);

  /* If we found no proper sized symbol to use, fall back to the best
     candidate sizeless symbol we found, if any.  */
  if (closest_name == NULL
      && sizeless_name != NULL && sizeless_sym.st_value >= min_label)
    {
      *closest_sym = sizeless_sym;
      closest_shndx = sizeless_shndx;
      closest_name = sizeless_name;
    }

  if (shndxp != NULL)
    *shndxp = closest_shndx;
  return closest_name;
}
int
main (int argc, char *argv[])
{
  int result = 0;
  int cnt;

  elf_version (EV_CURRENT);

  for (cnt = 1; cnt < argc; ++cnt)
    {
      int fd = open (argv[cnt], O_RDONLY);

      Elf *elf = elf_begin (fd, ELF_C_READ, NULL);
      if (elf == NULL)
	{
	  printf ("%s not usable %s\n", argv[cnt], elf_errmsg (-1));
	  result = 1;
	  close (fd);
	  continue;
	}

      size_t shdrstrndx;
      if (elf_getshdrstrndx (elf, &shdrstrndx) == -1)
	{
	  printf ("elf_getshdrstrnd failed %s\n", elf_errmsg (-1));
	  result = 1;
	  close (fd);
	  continue;
	}

      Elf_Scn *scn = NULL;
      while ((scn = elf_nextscn (elf, scn)) != NULL)
	{
	  int idx = elf_ndxscn (scn);
	  GElf_Shdr shdr;
	  if (gelf_getshdr (scn, &shdr) == NULL)
	    {
	      printf ("gelf_getshdr failed: %s\n", elf_errmsg (-1));
	      result = 1;
	      break;
	    }

	  const char *sname = elf_strptr (elf, shdrstrndx, shdr.sh_name);
	  if (sname == NULL)
	    {
	      printf ("couldn't get section name: %s\n", elf_errmsg (-1));
	      result = 1;
	      break;
	    }

	  if (strncmp(".zdebug", sname, strlen (".zdebug")) == 0)
	    {
	      ssize_t size;
	      if ((size = dwelf_scn_gnu_compressed_size (scn)) == -1)
		{
		  printf ("dwelf_scn_gnu_compressed_size failed: %s\n",
			  elf_errmsg (-1));
		  result = 1;
		  break;
		}
	      printf ("section %d: GNU Compressed size: %zx\n", idx, size);
	    }
	}

      elf_end (elf);
      close (fd);
    }

  return result;
}
Ejemplo n.º 23
0
void clone_elf(Elf *elf, Elf *newelf,
               const char *elf_name,
               const char *newelf_name,
               bool *sym_filter, int num_symbols,
               int shady
#ifdef SUPPORT_ANDROID_PRELINK_TAGS
               , int *prelinked,
               int *elf_little,
               long *prelink_addr
#endif
               , bool rebuild_shstrtab,
               bool strip_debug,
               bool dry_run)
{
	GElf_Ehdr ehdr_mem, *ehdr; /* store ELF header of original library */
	size_t shstrndx; /* section-strings-section index */
	size_t shnum; /* number of sections in the original file */
	/* string table for section headers in new file */
	struct Ebl_Strtab *shst = NULL;
    int dynamic_idx = -1; /* index in shdr_info[] of .dynamic section */
    int dynsym_idx = -1; /* index in shdr_info[] of dynamic symbol table
                            section */

    unsigned int cnt;	  /* general-purpose counter */
    /* This flag is true when at least one section is dropped or when the
       relative order of sections has changed, so that section indices in
       the resulting file will be different from those in the original. */
    bool sections_dropped_or_rearranged;
	Elf_Scn *scn; /* general-purpose section */
	size_t idx;	  /* general-purporse section index */

	shdr_info_t *shdr_info = NULL;
    unsigned int shdr_info_len = 0;
    GElf_Phdr *phdr_info = NULL;

	/* Get the information from the old file. */
	ehdr = gelf_getehdr (elf, &ehdr_mem);
	FAILIF_LIBELF(NULL == ehdr, gelf_getehdr);

	/* Create new program header for the elf file */
	FAILIF(gelf_newehdr (newelf, gelf_getclass (elf)) == 0 ||
		   (ehdr->e_type != ET_REL && gelf_newphdr (newelf,
													ehdr->e_phnum) == 0),
		   "Cannot create new file: %s", elf_errmsg (-1));

#ifdef SUPPORT_ANDROID_PRELINK_TAGS
    ASSERT(prelinked);
    ASSERT(prelink_addr);
    ASSERT(elf_little);
    *elf_little = (ehdr->e_ident[EI_DATA] == ELFDATA2LSB);
    *prelinked = check_prelinked(elf_name, *elf_little, prelink_addr);
#endif

    INFO("\n\nCALCULATING MODIFICATIONS\n\n");

	/* Copy out the old program header: notice that if the ELF file does not
	   have a program header, this loop won't execute.
	*/
	INFO("Copying ELF program header...\n");
    phdr_info = (GElf_Phdr *)CALLOC(ehdr->e_phnum, sizeof(GElf_Phdr));
	for (cnt = 0; cnt < ehdr->e_phnum; ++cnt) {
		INFO("\tRetrieving entry %d\n", cnt);
		FAILIF_LIBELF(NULL == gelf_getphdr(elf, cnt, phdr_info + cnt),
                      gelf_getphdr);
        /* -- we update the header at the end
        FAILIF_LIBELF(gelf_update_phdr (newelf, cnt, phdr_info + cnt) == 0,
                      gelf_update_phdr);
        */
	}

    /* Get the section-header strings section.  This section contains the
	   strings used to name the other sections. */
	FAILIF_LIBELF(elf_getshstrndx(elf, &shstrndx) < 0, elf_getshstrndx);

	/* Get the number of sections. */
	FAILIF_LIBELF(elf_getshnum (elf, &shnum) < 0, elf_getshnum);
	INFO("Original ELF file has %zd sections.\n", shnum);

	/* Allocate the section-header-info buffer.  We allocate one more entry
       for the section-strings section because we regenerate that one and
       place it at the very end of the file.  Note that just because we create
       an extra entry in the shdr_info array, it does not mean that we create
       one more section the header.  We just mark the old section for removal
       and create one as the last section.
    */
	INFO("Allocating section-header info structure (%zd) bytes...\n",
		 shnum*sizeof (shdr_info_t));
    shdr_info_len = rebuild_shstrtab ? shnum + 1 : shnum;
	shdr_info = (shdr_info_t *)CALLOC(shdr_info_len, sizeof (shdr_info_t));

	/* Iterate over all the sections and initialize the internal section-info
	   array...
	*/
	INFO("Initializing section-header info structure...\n");
	/* Gather information about the sections in this file. */
	scn = NULL;
	cnt = 1;
	while ((scn = elf_nextscn (elf, scn)) != NULL) {
		ASSERT(elf_ndxscn(scn) == cnt);
		shdr_info[cnt].scn = scn;
		FAILIF_LIBELF(NULL == gelf_getshdr(scn, &shdr_info[cnt].shdr),
					  gelf_getshdr);

		/* Get the name of the section. */
		shdr_info[cnt].name = elf_strptr (elf, shstrndx,
										  shdr_info[cnt].shdr.sh_name);

		INFO("\tname: %s\n", shdr_info[cnt].name);
		FAILIF(shdr_info[cnt].name == NULL,
			   "Malformed file: section %d name is null\n",
			   cnt);

		/* Mark them as present but not yet investigated.  By "investigating"
		   sections, we mean that we check to see if by stripping other
		   sections, the sections under investigation will be compromised.  For
		   example, if we are removing a section of code, then we want to make
		   sure that the symbol table does not contain symbols that refer to
		   this code, so we investigate the symbol table.  If we do find such
		   symbols, we will not strip the code section.
		*/
		shdr_info[cnt].idx = 1;

		/* Remember the shdr.sh_link value.  We need to remember this value
		   for those sections that refer to other sections.  For example,
		   we need to remember it for relocation-entry sections, because if
		   we modify the symbol table that a relocation-entry section is
		   relative to, then we need to patch the relocation section.  By the
		   time we get to deciding whether we need to patch the relocation
		   section, we will have overwritten its header's sh_link field with
		   a new value.
		*/
		shdr_info[cnt].old_shdr = shdr_info[cnt].shdr;
        INFO("\t\toriginal sh_link: %08d\n", shdr_info[cnt].old_shdr.sh_link);
        INFO("\t\toriginal sh_addr: %lld\n", shdr_info[cnt].old_shdr.sh_addr);
        INFO("\t\toriginal sh_offset: %lld\n",
             shdr_info[cnt].old_shdr.sh_offset);
        INFO("\t\toriginal sh_size: %lld\n", shdr_info[cnt].old_shdr.sh_size);

        if (shdr_info[cnt].shdr.sh_type == SHT_DYNAMIC) {
            INFO("\t\tthis is the SHT_DYNAMIC section [%s] at index %d\n",
                 shdr_info[cnt].name,
                 cnt);
            dynamic_idx = cnt;
        }
        else if (shdr_info[cnt].shdr.sh_type == SHT_DYNSYM) {
            INFO("\t\tthis is the SHT_DYNSYM section [%s] at index %d\n",
                 shdr_info[cnt].name,
                 cnt);
            dynsym_idx = cnt;
        }

		FAILIF(shdr_info[cnt].shdr.sh_type == SHT_SYMTAB_SHNDX,
			   "Cannot handle sh_type SHT_SYMTAB_SHNDX!\n");
		FAILIF(shdr_info[cnt].shdr.sh_type == SHT_GROUP,
			   "Cannot handle sh_type SHT_GROUP!\n");
		FAILIF(shdr_info[cnt].shdr.sh_type == SHT_GNU_versym,
			   "Cannot handle sh_type SHT_GNU_versym!\n");

		/* Increment the counter. */
		++cnt;
	} /* while */

	/* Get the EBL handling. */
	Ebl *ebl = ebl_openbackend (elf);
	FAILIF_LIBELF(NULL == ebl, ebl_openbackend);
    FAILIF_LIBELF(0 != arm_init(elf, ehdr->e_machine, ebl, sizeof(Ebl)),
                  arm_init);

    if (strip_debug) {

      /* This will actually strip more than just sections.  It will strip
         anything not essential to running the image.
      */

      INFO("Finding debug sections to strip.\n");

      /* Now determine which sections can go away.  The general rule is that
         all sections which are not used at runtime are stripped out.  But
         there are a few exceptions:

         - special sections named ".comment" and ".note" are kept
         - OS or architecture specific sections are kept since we might not
		 know how to handle them
         - if a section is referred to from a section which is not removed
		 in the sh_link or sh_info element it cannot be removed either
      */
      for (cnt = 1; cnt < shnum; ++cnt) {
		/* Check whether the section can be removed.  */
		if (SECTION_STRIP_P (ebl, elf, ehdr, &shdr_info[cnt].shdr,
							 shdr_info[cnt].name,
							 1,	 /* remove .comment sections */
							 1	 /* remove all debug sections */) ||
            /* The macro above is broken--check for .comment explicitly */
            !strcmp(".comment", shdr_info[cnt].name)
#ifdef ARM_SPECIFIC_HACKS
            ||
            /* We ignore this section, that's why we can remove it. */
            !strcmp(".stack", shdr_info[cnt].name)
#endif
            )
        {
          /* For now assume this section will be removed.  */
          INFO("Section [%s] will be stripped from image.\n",
               shdr_info[cnt].name);
          shdr_info[cnt].idx = 0;
		}
#ifdef STRIP_STATIC_SYMBOLS
		else if (shdr_info[cnt].shdr.sh_type == SHT_SYMTAB) {
          /* Mark the static symbol table for removal */
          INFO("Section [%s] (static symbol table) will be stripped from image.\n",
               shdr_info[cnt].name);
          shdr_info[cnt].idx = 0;
          if (shdr_info[shdr_info[cnt].shdr.sh_link].shdr.sh_type ==
              SHT_STRTAB)
          {
            /* Mark the symbol table's string table for removal. */
            INFO("Section [%s] (static symbol-string table) will be stripped from image.\n",
                 shdr_info[shdr_info[cnt].shdr.sh_link].name);
            shdr_info[shdr_info[cnt].shdr.sh_link].idx = 0;
          }
          else {
            ERROR("Expecting the sh_link field of a symbol table to point to"
                  " associated symbol-strings table!  This is not mandated by"
                  " the standard, but is a common practice and the only way "
                  " to know for sure which strings table corresponds to which"
                  " symbol table!\n");
          }
		}
#endif
      }

      /* Mark the SHT_NULL section as handled. */
      shdr_info[0].idx = 2;

      /* Handle exceptions: section groups and cross-references.  We might have
         to repeat this a few times since the resetting of the flag might
         propagate.
      */
      int exceptions_pass = 0;
      bool changes;
      do {
        changes = false;
		INFO("\nHandling exceptions, pass %d\n\n", exceptions_pass++);
		for (cnt = 1; cnt < shnum; ++cnt) {
          if (shdr_info[cnt].idx == 0) {
            /* If a relocation section is marked as being removed but the
               section it is relocating is not, then do not remove the
               relocation section.
            */
            if ((shdr_info[cnt].shdr.sh_type == SHT_REL
                 || shdr_info[cnt].shdr.sh_type == SHT_RELA)
                && shdr_info[shdr_info[cnt].shdr.sh_info].idx != 0) {
              PRINT("\tSection [%s] will not be removed because the "
                    "section it is relocating (%s) stays.\n",
                    shdr_info[cnt].name,
                    shdr_info[shdr_info[cnt].shdr.sh_info].name);
            }
          }
          if (shdr_info[cnt].idx == 1) {
            INFO("Processing section [%s]...\n", shdr_info[cnt].name);

            /* The content of symbol tables we don't remove must not
               reference any section which we do remove.  Otherwise
               we cannot remove the referred section.
            */
            if (shdr_info[cnt].shdr.sh_type == SHT_DYNSYM ||
                shdr_info[cnt].shdr.sh_type == SHT_SYMTAB)
            {
              Elf_Data *symdata;
              size_t elsize;

              INFO("\tSection [%s] is a symbol table that's not being"
                   " removed.\n\tChecking to make sure that no symbols"
                   " refer to sections that are being removed.\n",
                   shdr_info[cnt].name);

              /* Make sure the data is loaded.  */
              symdata = elf_getdata (shdr_info[cnt].scn, NULL);
              FAILIF_LIBELF(NULL == symdata, elf_getdata);

              /* Go through all symbols and make sure the section they
                 reference is not removed.  */
              elsize = gelf_fsize (elf, ELF_T_SYM, 1, ehdr->e_version);

              /* Check the length of the dynamic-symbol filter. */
              FAILIF(sym_filter != NULL &&
                     (size_t)num_symbols != symdata->d_size / elsize,
                     "Length of dynsym filter (%d) must equal the number"
                     " of dynamic symbols (%zd)!\n",
                     num_symbols,
                     symdata->d_size / elsize);

              size_t inner;
              for (inner = 0;
                   inner < symdata->d_size / elsize;
                   ++inner)
              {
                GElf_Sym sym_mem;
                GElf_Sym *sym;
                size_t scnidx;

                sym = gelf_getsymshndx (symdata, NULL,
                                        inner, &sym_mem, NULL);
                FAILIF_LIBELF(sym == NULL, gelf_getsymshndx);

                scnidx = sym->st_shndx;
                FAILIF(scnidx == SHN_XINDEX,
                       "Can't handle SHN_XINDEX!\n");
                if (scnidx == SHN_UNDEF ||
                    scnidx >= shnum ||
                    (scnidx >= SHN_LORESERVE &&
                     scnidx <= SHN_HIRESERVE) ||
                    GELF_ST_TYPE (sym->st_info) == STT_SECTION)
                {
                  continue;
                }

                /* If the symbol is going to be thrown and it is a
                   global or weak symbol that is defined (not imported),
                   then continue.  Since the symbol is going away, we
                   do not care  whether it refers to a section that is
                   also going away.
                */
                if (sym_filter && !sym_filter[inner])
                {
                  bool global_or_weak =
                      ELF32_ST_BIND(sym->st_info) == STB_GLOBAL ||
                      ELF32_ST_BIND(sym->st_info) == STB_WEAK;
                  if (!global_or_weak && sym->st_shndx != SHN_UNDEF)
                    continue;
                }

                /* -- far too much output
                   INFO("\t\t\tSymbol [%s] (%d)\n",
                   elf_strptr(elf,
                   shdr_info[cnt].shdr.sh_link,
                   sym->st_name),
                   shdr_info[cnt].shdr.sh_info);
                */

                if (shdr_info[scnidx].idx == 0)
                {
                  PRINT("\t\t\tSymbol [%s] refers to section [%s], "
                        "which is being removed.  Will keep that "
                        "section.\n",
                        elf_strptr(elf,
                                   shdr_info[cnt].shdr.sh_link,
                                   sym->st_name),
                        shdr_info[scnidx].name);
                  /* Mark this section as used.  */
                  shdr_info[scnidx].idx = 1;
                  changes |= scnidx < cnt;
                }
              } /* for each symbol */
            } /* section type is SHT_DYNSYM or SHT_SYMTAB */
            /* Cross referencing happens:
			   - for the cases the ELF specification says.  That are
			   + SHT_DYNAMIC in sh_link to string table
			   + SHT_HASH in sh_link to symbol table
			   + SHT_REL and SHT_RELA in sh_link to symbol table
			   + SHT_SYMTAB and SHT_DYNSYM in sh_link to string table
			   + SHT_GROUP in sh_link to symbol table
			   + SHT_SYMTAB_SHNDX in sh_link to symbol table
			   Other (OS or architecture-specific) sections might as
			   well use this field so we process it unconditionally.
			   - references inside section groups
			   - specially marked references in sh_info if the SHF_INFO_LINK
			   flag is set
            */

            if (shdr_info[shdr_info[cnt].shdr.sh_link].idx == 0) {
              shdr_info[shdr_info[cnt].shdr.sh_link].idx = 1;
              changes |= shdr_info[cnt].shdr.sh_link < cnt;
            }

            /* Handle references through sh_info.  */
            if (SH_INFO_LINK_P (&shdr_info[cnt].shdr) &&
                shdr_info[shdr_info[cnt].shdr.sh_info].idx == 0) {
              PRINT("\tSection [%s] links to section [%s], which was "
                    "marked for removal--it will not be removed.\n",
                    shdr_info[cnt].name,
                    shdr_info[shdr_info[cnt].shdr.sh_info].name);

              shdr_info[shdr_info[cnt].shdr.sh_info].idx = 1;
              changes |= shdr_info[cnt].shdr.sh_info < cnt;
            }

            /* Mark the section as investigated.  */
            shdr_info[cnt].idx = 2;
          } /* if (shdr_info[cnt].idx == 1) */
		} /* for (cnt = 1; cnt < shnum; ++cnt) */
      } while (changes);
    }
    else {
      INFO("Not stripping sections.\n");
      /* Mark the SHT_NULL section as handled. */
      shdr_info[0].idx = 2;
    }

	/* Mark the section header string table as unused, we will create
	   a new one as the very last section in the new ELF file.
	*/
	shdr_info[shstrndx].idx = rebuild_shstrtab ? 0 : 2;

	/* We need a string table for the section headers. */
	FAILIF_LIBELF((shst = ebl_strtabinit (1	/* null-terminated */)) == NULL,
				  ebl_strtabinit);

	/* Assign new section numbers. */
	INFO("Creating new sections...\n");
	//shdr_info[0].idx = 0;
	for (cnt = idx = 1; cnt < shnum; ++cnt) {
		if (shdr_info[cnt].idx > 0) {
			shdr_info[cnt].idx = idx++;

			/* Create a new section. */
			FAILIF_LIBELF((shdr_info[cnt].newscn =
						   elf_newscn(newelf)) == NULL, elf_newscn);
			ASSERT(elf_ndxscn (shdr_info[cnt].newscn) == shdr_info[cnt].idx);

			/* Add this name to the section header string table. */
			shdr_info[cnt].se = ebl_strtabadd (shst, shdr_info[cnt].name, 0);

			INFO("\tsection [%s]  (old offset %lld, old size %lld) will have index %d "
				 "(was %zd).\n",
				 shdr_info[cnt].name,
				 shdr_info[cnt].old_shdr.sh_offset,
				 shdr_info[cnt].old_shdr.sh_size,
				 shdr_info[cnt].idx,
				 elf_ndxscn(shdr_info[cnt].scn));
		} else {
			INFO("\tIgnoring section [%s] (offset %lld, size %lld, index %zd), "
				 "it will be discarded.\n",
				 shdr_info[cnt].name,
				 shdr_info[cnt].shdr.sh_offset,
				 shdr_info[cnt].shdr.sh_size,
				 elf_ndxscn(shdr_info[cnt].scn));
		}
	} /* for */

    sections_dropped_or_rearranged = idx != cnt;

    Elf_Data *shstrtab_data = NULL;

#if 0
    /* Fail if sections are being dropped or rearranged (except for moving shstrtab) or the
       symbol filter is not empty, AND the file is an executable.
    */
    FAILIF(((idx != cnt && !(cnt - idx == 1 && rebuild_shstrtab)) || sym_filter != NULL) &&
           ehdr->e_type != ET_DYN,
           "You may not rearrange sections or strip symbols on an executable file!\n");
#endif

    INFO("\n\nADJUSTING ELF FILE\n\n");

    adjust_elf(elf, elf_name,
               newelf, newelf_name,
               ebl,
               ehdr, /* store ELF header of original library */
               sym_filter, num_symbols,
               shdr_info, shdr_info_len,
               phdr_info,
               idx, /* highest_scn_num */
               shnum,
               shstrndx,
               shst,
               sections_dropped_or_rearranged,
               dynamic_idx, /* index in shdr_info[] of .dynamic section */
               dynsym_idx, /* index in shdr_info[] of dynamic symbol table */
               shady,
               &shstrtab_data,
               ehdr->e_type == ET_DYN, /* adjust section ofsets only when the file is a shared library */
               rebuild_shstrtab);

    /* We have everything from the old file. */
	FAILIF_LIBELF(elf_cntl(elf, ELF_C_FDDONE) != 0, elf_cntl);

	/* The ELF library better follows our layout when this is not a
	   relocatable object file. */
	elf_flagelf (newelf,
				 ELF_C_SET,
				 (ehdr->e_type != ET_REL ? ELF_F_LAYOUT : 0));

	/* Finally write the file. */
    FAILIF_LIBELF(!dry_run && elf_update(newelf, ELF_C_WRITE) == -1, elf_update);

	if (shdr_info != NULL) {
		/* For some sections we might have created an table to map symbol
           table indices. */
       for (cnt = 1; cnt < shdr_info_len; ++cnt) {
            FREEIF(shdr_info[cnt].newsymidx);
            FREEIF(shdr_info[cnt].symse);
            if(shdr_info[cnt].dynsymst != NULL)
                ebl_strtabfree (shdr_info[cnt].dynsymst);
        }
		/* Free the memory. */
		FREE (shdr_info);
	}
    FREEIF(phdr_info);

    ebl_closebackend(ebl);

	/* Free other resources. */
	if (shst != NULL) ebl_strtabfree (shst);
    if (shstrtab_data != NULL)
        FREEIF(shstrtab_data->d_buf);
}
Ejemplo n.º 24
0
static int replaceAMDILSection(Elf* e, int nStream, MWCALtargetEnum target)
{
    Elf_Scn* scn = NULL;
    size_t shstrndx = 0;
    static const int verbose = 0;
    static const int verboseDebug = 0;

    /* Get section index of section containing the string table of section names */
    if (elf_getshdrstrndx(e, &shstrndx) != 0)
    {
        mw_printf("elf_getshdrstrndx failed: %s\n", elf_errmsg(-1));
        return 1;
    }

    /* Iterate through all the sections */
    while ((scn = elf_nextscn(e, scn)))
    {
        Elf32_Shdr* shdr;
        const char* name;

        /* Get the header for this section */
        shdr = elf32_getshdr(scn);
        if (!shdr)
        {
            mw_printf("elf32_getshdr() failed: %s\n", elf_errmsg(-1));
            return 1;
        }

        /* Look up the name of the section in the string table */
        name = elf_strptr(e, shstrndx, shdr->sh_name);
        if (!name)
        {
            mw_printf("elf_strptr() failed: %s\n", elf_errmsg(-1));
            return 1;
        }

        /*
        if (strstr(name, ".rodata") != NULL)
        {
            Elf_Data* data = elf_getdata(scn, NULL);


            FILE* f = fopen("rodata_section.bin", "wb");
            if (f)
            {
                fwrite(data->d_buf, 1, data->d_size, f);
                fclose(f);
            }
            else
            {
                perror("Failed to open file");
            }

            size_t roSize;
            char* r770RO = mwReadFileWithSize("rodata_section_RV770.bin", &roSize);
            assert(r770RO);

            data->d_buf = r770RO;
            data->d_size = roSize;


            if (!elf_flagdata(data, ELF_C_SET, ELF_F_DIRTY))
            {
                mw_printf("elf_flagdata() failed: %s\n", elf_errmsg(-1));
                return 1;
            }

            if (!elf_flagscn(scn, ELF_C_SET, ELF_F_DIRTY))
            {
                mw_printf("elf_flagscn() failed: %s\n", elf_errmsg(-1));
                return 1;
            }

            if (elf_update(e, ELF_C_NULL) < 0)
            {
                mw_printf("elf_update(NULL) failed: %s\n", elf_errmsg(-1));
                return 1;
            }
        }
        */

        if (strstr(name, ".amdil") != NULL)
        {
            int uavId;
            const char* uavComment;
            Elf_Data* data;

            data = elf_getdata(scn, NULL);
            if (!data)
            {
                mw_printf("Failed to get data for .amdil section: %s\n", elf_errmsg(-1));
                return 1;
            }

            if (verbose)
            {
                mw_printf("Replacing section data of type %d, off %d align "ZU"\n",
                          data->d_type,
                          (int) data->d_off,
                          data->d_align);
            }


            /* Before we overwrite it, there is information we would like to extract */
            uavComment = strstr((const char*) data->d_buf, ";uavid:");
            if (!uavComment || (sscanf(uavComment, ";uavid:%d\n", &uavId) != 1))
            {
                mw_printf("Error reading uavid from IL comment\n");
                uavId = -1;
            }

            ilSrc = getILSrc(nStream, target, uavId, &ilSrcLen);
            if (!ilSrc || (ilSrcLen == 0))
            {
                mw_printf("Failed to get IL source\n");
                return 1;
            }

            data->d_buf = (void*) ilSrc;
            data->d_size = ilSrcLen;

            if (!elf_flagdata(data, ELF_C_SET, ELF_F_DIRTY))
            {
                mw_printf("elf_flagdata() failed: %s\n", elf_errmsg(-1));
                return 1;
            }

            if (!elf_flagscn(scn, ELF_C_SET, ELF_F_DIRTY))
            {
                mw_printf("elf_flagscn() failed: %s\n", elf_errmsg(-1));
                return 1;
            }

            /* Don't let libelf rearrange the sections when writing.

               clBuildProgram() crashes on Windows if you don't do
               this with some(?) Catalyst versions
             */
            if (!elf_flagelf(e, ELF_C_SET, ELF_F_LAYOUT))
            {
                mw_printf("elf_flagelf() failed: %s\n", elf_errmsg(-1));
                return 1;
            }

            if (elf_update(e, ELF_C_NULL) < 0)
            {
                mw_printf("elf_update(NULL) failed: %s\n", elf_errmsg(-1));
                return 1;
            }
        }

        if (verboseDebug)
        {
            printf("Section %u %s\n", (unsigned int) elf_ndxscn(scn), name);
        }
    }

    if (elf_update(e, ELF_C_WRITE) < 0)
    {
        mw_printf("elf_update(ELF_C_WRITE) failed: %s\n", elf_errmsg(-1));
        return 1;
    }

    return 0;
}