Пример #1
0
/**
 * @brief Search an elf for a named section
 *
 * @param elf The open elf object
 * @param name The section name to find
 *
 * @returns A pointer to the section if successful, NULL otherwise.
 */
static Elf_Scn * elf_getscn_byname(Elf *elf, const char * name) {
    Elf_Scn *scn = NULL;
    size_t shstrndx;
    GElf_Shdr shdr;
    char *section_name;

    if (elf_getshdrstrndx(elf, &shstrndx) != 0) {
        fprintf(stderr, "elf_getshdrstrndx() failed: %s\n", elf_errmsg(-1));
    } else {
        /**
         * Iterate over the sections in the ELF descriptor to get the indices
         * of the .text and .data descriptors
         */
        while ((scn = elf_nextscn(elf, scn)) != NULL) {
            if (gelf_getshdr(scn, &shdr) != &shdr) {
                fprintf(stderr, "getshdr() failed: %s\n",
                    elf_errmsg(-1));
            } else {
                section_name = elf_strptr(elf, shstrndx, shdr.sh_name);
                if (section_name == NULL) {
                    fprintf(stderr, "elf_strptr() failed: %s\n",
                        elf_errmsg(-1));
                } else if (strcmp(section_name, name) == 0) {
                    break;
                }
            }
        }
    }

    return scn;
}
Пример #2
0
int
find_injected_secaddr(elf_data_t *elf, inject_data_t *inject)
{
  Elf_Scn *scn;
  GElf_Shdr shdr;
  uint64_t max_inject_addr = 0;
  char* s;
  size_t shstrndx;

  if(elf_getshdrstrndx(elf->e, &shstrndx) < 0) {
    return -1;
  }

  scn = NULL;
  while((scn = elf_nextscn(elf->e, scn))) {
    if(!gelf_getshdr(scn, &shdr)) {
      return -1;
    }
    s = elf_strptr(elf->e, shstrndx, shdr.sh_name);
    if(!s) {
      return -1;
    }

    if(!strcmp(s, DYNINST_NAME))
		fprintf(finfo,"dyninst end=%lx\n",shdr.sh_addr + shdr.sh_size);
	if (shdr.sh_addr + shdr.sh_offset > max_inject_addr)
		max_inject_addr = shdr.sh_addr + shdr.sh_size;
  }
  inject->secaddr = max_inject_addr + inject->len + 0x4000;
  return 0;
}
Пример #3
0
Elf_Scn *elf_utils_new_scn_with_name(Elf *e, const char *scn_name)
{
	Elf_Scn *scn;
	GElf_Shdr shdr;
	size_t shstrndx, index, namelen;
	Elf_Data *shstrdata;
	void *ptr;

	ELF_ASSERT(elf_getshdrstrndx(e, &shstrndx) == 0);

	ELF_ASSERT(scn = elf_getscn(e, shstrndx));
	ELF_ASSERT(shstrdata = elf_getdata(scn, NULL));

	namelen = strlen(scn_name) + 1;
	ELF_ASSERT(gelf_getshdr(scn, &shdr));
	if (!elf_utils_shift_contents(e, shdr.sh_offset + shdr.sh_size, namelen))
		goto failure;
	ASSERT(ptr = realloc(shstrdata->d_buf, shstrdata->d_size + namelen));
	index = shstrdata->d_size;
	strcpy(ptr+index, scn_name);
	shstrdata->d_buf = ptr;
	shstrdata->d_size += namelen;
	shdr.sh_size += namelen;
	ELF_ASSERT(gelf_update_shdr(scn, &shdr));

	ELF_ASSERT(scn = elf_newscn(e));
	ELF_ASSERT(gelf_getshdr(scn, &shdr));
	shdr.sh_name = index;
	ELF_ASSERT(gelf_update_shdr(scn, &shdr));
	
	return scn;
failure:
	return NULL;
}
Пример #4
0
int
rewrite_section_name(elf_data_t *elf, inject_data_t *inject, char **err)
{
  Elf_Scn *scn;
  GElf_Shdr shdr;
  char *s;
  size_t shstrndx, stroff, strbase;

  if(strlen(inject->secname) > strlen(ABITAG_NAME)) {
    (*err) = "section name too long";
    return -1;
  }

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

  stroff = 0;
  strbase = 0;
  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;
    }

    if(!strcmp(s, ABITAG_NAME)) {
      stroff = shdr.sh_name;   /* offset into shstrtab */
    } else if(!strcmp(s, SHSTRTAB_NAME)) {
      strbase = shdr.sh_offset; /* offset to start of shstrtab */
    }
  }

  if(stroff == 0) {
    (*err) = "cannot find shstrtab entry for injected section";
    return -1;
  } else if(strbase == 0) {
    (*err) = "cannot find shstrtab";
    return -1;
  }

  inject->shstroff = strbase + stroff;

  verbose("renaming rewritten section to \"%s\"", inject->secname);
  verbose("writing section string table to file");

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

  return 0;
}
Пример #5
0
Файл: elves.c Проект: abrt/satyr
/**
 * Finds a section by its name in an ELF file.
 * @param elf
 *   A libelf handle representing the file.
 * @param section_name
 *   Name of section to be found.
 * @param data_dest
 *   Save the resulting elf data pointer here.  Cannot be NULL.
 * @param shdr_dest
 *   Save the section header here. Cannot be NULL.
 * @param error_message
 *   Will be filled by an error message if the function fails (returns
 *   zero).  Caller is responsible for calling free() on the string
 *   pointer.  If function succeeds, the pointer is not touched by the
 *   function.
 * @returns
 *   Zero on error, index of the section on success.
 */
static unsigned
find_elf_section_by_name(Elf *elf,
                         const char *section_name,
                         Elf_Data **data_dest,
                         GElf_Shdr *shdr_dest,
                         char **error_message)
{
    /* Find the string table index */
    size_t shdr_string_index;
    if (0 != elf_getshdrstrndx(elf, &shdr_string_index))
    {
        *error_message = sr_asprintf("elf_getshdrstrndx failed");
        return 0;
    }

    unsigned section_index = 0;
    Elf_Scn *section = NULL;
    while ((section = elf_nextscn(elf, section)) != NULL)
    {
        /* Starting index is 1. */
        ++section_index;

        GElf_Shdr shdr;
        if (gelf_getshdr(section, &shdr) != &shdr)
        {
            *error_message = sr_asprintf("gelf_getshdr failed");
            return 0;
        }

        const char *current_section_name = elf_strptr(elf,
                                                      shdr_string_index,
                                                      shdr.sh_name);

        if (!current_section_name)
        {
            *error_message = sr_asprintf("elf_strptr failed");
            return 0;
        }

        if (0 == strcmp(current_section_name, section_name))
        {
            /* We found the right section!  Save the data. */
            *data_dest = elf_getdata(section, NULL);
            if (!*data_dest)
            {
                *error_message = sr_asprintf("elf_getdata failed");
                return 0;
            }

            /* Save the section header. */
            *shdr_dest = shdr;
            return section_index;
        }
    }

    *error_message = sr_asprintf("Section %s not found", section_name);
    return 0;
}
Пример #6
0
/*
 * @param e         elf handle
 * @param name      name of section to be found
 * @param filename  filename for logging messages
 * @param dest      save the resulting elf data pointer here (can be NULL)
 * @param shdr_dest save the section header here (can be NULL)
 * @returns zero on error, index of the section on success
 */
static unsigned xelf_section_by_name(Elf *e, const char *name, const char *filename, Elf_Data **dest, GElf_Shdr *shdr_dest)
{
    Elf_Scn *scn = NULL;
    GElf_Shdr shdr;
    unsigned section_index = 0;
    size_t shstrndx;

    /* Find the string table index */
    if (elf_getshdrstrndx(e, &shstrndx) != 0)
    {
        VERB1 log_elf_error("elf_getshdrstrndx", filename);
        return 0;
    }

    while ((scn = elf_nextscn(e, scn)) != NULL)
    {
        section_index++; /* starting index is 1 */

        if (gelf_getshdr(scn, &shdr) != &shdr)
        {
            VERB1 log_elf_error("gelf_getshdr", filename);
            continue;
        }

        const char *scnname = elf_strptr(e, shstrndx, shdr.sh_name);
        if (scnname == NULL)
        {
            VERB1 log_elf_error("elf_strptr", filename);
            continue;
        }

        if (strcmp(scnname, name) == 0)
        {
            /* Found, save data */
            if (dest)
            {
                *dest = elf_getdata(scn, NULL);
                if (*dest == NULL)
                {
                    VERB1 log_elf_error("elf_getdata", filename);
                    break;
                }
            }

            /* save shdr */
            if (shdr_dest)
            {
                *shdr_dest = shdr;
            }

            return section_index;
        }
    }

    VERB1 log("Section %s not found in %s\n", name, filename);
    return 0;
}
Пример #7
0
const char *get_scn_name(vita_elf_t *ve, Elf_Scn *scn)
{
	size_t shstrndx;
	GElf_Shdr shdr;

	elf_getshdrstrndx(ve->elf, &shstrndx);
	gelf_getshdr(scn, &shdr);
	return elf_strptr(ve->elf, shstrndx, shdr.sh_name);
}
Пример #8
0
uint8_t *dump_section_data(Elf *elf_object, int *size)
{
	uint8_t *buffer = NULL;
	Elf_Data *data = NULL;
	size_t shdr_num;
	size_t max_saddr = 0;
	GElf_Shdr shdr;
	size_t shstrndx;
	char *name = NULL;

	*size = 0;

	int ret = elf_getshdrnum(elf_object, &shdr_num);
	if (ret) {
		printf("Problem during ELF parsing\n");
		return NULL;
	}

	if (shdr_num == 0)
		return NULL;

	Elf_Scn *cur_section = NULL;
	ret = elf_getshdrstrndx(elf_object, &shstrndx);
	if (ret)
		printf("No string table found\n");

	while ((cur_section = elf_nextscn(elf_object, cur_section)) != NULL ) {
		if (gelf_getshdr(cur_section, &shdr) != &shdr) {
			printf("Problem during ELF parsing\n");
			return NULL;
		}

		if ((shdr.sh_type == SHT_PROGBITS) && (shdr.sh_flags & SHF_ALLOC) && shdr.sh_size != 0) {

			name = elf_strptr(elf_object, shstrndx , shdr.sh_name);
			printf("Loading section %s, size 0x%08X lma 0x%08X\n",
				name ? name : "??", (unsigned int)shdr.sh_size, (unsigned int)shdr.sh_addr);

			if (shdr.sh_addr + shdr.sh_size >= max_saddr) {
				max_saddr = shdr.sh_addr + shdr.sh_size;
				buffer = realloc(buffer, max_saddr);
			}

			data = elf_getdata(cur_section, data);
			if (data != NULL)
				memcpy(buffer + shdr.sh_addr, data->d_buf, data->d_size);
			else {
				printf("Couldn't load section data chunk\n");
				return NULL;
			}
		}
	}

	*size = max_saddr;
	return buffer;
}
Пример #9
0
int elf_utils_duplicate_shstrtab(Elf *e)
{
	size_t shstrndx;

	ELF_ASSERT(elf_getshdrstrndx(e, &shstrndx) == 0);

	return elf_utils_duplicate_scn_contents(e, shstrndx);
failure:
	return 0;
}
Пример #10
0
/*
 * Print the symbol table.  This function does not print the contents
 * of the symbol table but sets up the parameters and then calls
 * print_symtab to print the symbols.  This function does not assume
 * that there is only one section of type SYMTAB.  Input is an opened
 * ELF file, a pointer to the ELF header, and the filename.
 */
static void
get_symtab(Elf *elf_file, char *filename)
{
	Elf_Scn	*scn, *scnfd;
	Elf_Data *data;
	GElf_Word symtabtype;
	size_t shstrndx;

	if (elf_getshdrstrndx(elf_file, &shstrndx) == -1) {
		(void) fprintf(stderr, gettext(
		    "%s: %s: cannot get e_shstrndx\n"),
		    prog_name, filename);
		return;
	}

	/* get section header string table */
	scnfd = get_scnfd(elf_file, shstrndx, SHT_STRTAB);
	if (scnfd == NULL) {
		(void) fprintf(stderr, gettext(
		    "%s: %s: cannot get string table\n"),
		    prog_name, filename);
		return;
	}

	data = elf_getdata(scnfd, NULL);
	if (data->d_size == 0) {
		(void) fprintf(stderr, gettext(
		    "%s: %s: no data in string table\n"),
		    prog_name, filename);
		return;
	}

	if (D_flag)
		symtabtype = SHT_DYNSYM;
	else if (L_flag)
		symtabtype = SHT_SUNW_LDYNSYM;
	else
		symtabtype = SHT_SYMTAB;

	scn = 0;
	while ((scn = elf_nextscn(elf_file, scn)) != 0)	{
		GElf_Shdr shdr;

		if (gelf_getshdr(scn, &shdr) == NULL) {
			(void) fprintf(stderr, "%s: %s: %s:\n",
			    prog_name, filename, elf_errmsg(-1));
			return;
		}

		if (shdr.sh_type == symtabtype)	{
			print_symtab(elf_file, shstrndx, scn,
			    &shdr, filename);
		}
	} /* end while */
}
Пример #11
0
void radeon_elf_read(const char *elf_data, unsigned elf_size,
					struct radeon_shader_binary *binary,
					unsigned debug)
{
	char *elf_buffer;
	Elf *elf;
	Elf_Scn *section = NULL;
	size_t section_str_index;

	/* One of the libelf implementations
	 * (http://www.mr511.de/software/english.htm) requires calling
	 * elf_version() before elf_memory().
	 */
	elf_version(EV_CURRENT);
	elf_buffer = MALLOC(elf_size);
	memcpy(elf_buffer, elf_data, elf_size);

	elf = elf_memory(elf_buffer, elf_size);

	elf_getshdrstrndx(elf, &section_str_index);
	binary->disassembled = 0;

	while ((section = elf_nextscn(elf, section))) {
		const char *name;
		Elf_Data *section_data = NULL;
		GElf_Shdr section_header;
		if (gelf_getshdr(section, &section_header) != &section_header) {
			fprintf(stderr, "Failed to read ELF section header\n");
			return;
		}
		name = elf_strptr(elf, section_str_index, section_header.sh_name);
		if (!strcmp(name, ".text")) {
			section_data = elf_getdata(section, section_data);
			binary->code_size = section_data->d_size;
			binary->code = MALLOC(binary->code_size * sizeof(unsigned char));
			memcpy(binary->code, section_data->d_buf, binary->code_size);
		} else if (!strcmp(name, ".AMDGPU.config")) {
			section_data = elf_getdata(section, section_data);
			binary->config_size = section_data->d_size;
			binary->config = MALLOC(binary->config_size * sizeof(unsigned char));
			memcpy(binary->config, section_data->d_buf, binary->config_size);
		} else if (debug && !strcmp(name, ".AMDGPU.disasm")) {
			binary->disassembled = 1;
			section_data = elf_getdata(section, section_data);
			fprintf(stderr, "\nShader Disassembly:\n\n");
			fprintf(stderr, "%.*s\n", (int)section_data->d_size,
						  (char *)section_data->d_buf);
		}
	}

	if (elf){
		elf_end(elf);
	}
	FREE(elf_buffer);
}
Пример #12
0
Dwfl_Error
internal_function
__libdwfl_relocate_value (Dwfl_Module *mod, Elf *elf, size_t *shstrndx,
			  Elf32_Word shndx, GElf_Addr *value)
{
  assert (mod->e_type == ET_REL);

  Elf_Scn *refscn = elf_getscn (elf, shndx);
  GElf_Shdr refshdr_mem, *refshdr = gelf_getshdr (refscn, &refshdr_mem);
  if (refshdr == NULL)
    return DWFL_E_LIBELF;

  if (refshdr->sh_addr == 0 && (refshdr->sh_flags & SHF_ALLOC))
    {
      /* This is a loaded section.  Find its actual
	 address and update the section header.  */

      if (*shstrndx == SHN_UNDEF
	  && unlikely (elf_getshdrstrndx (elf, shstrndx) < 0))
	return DWFL_E_LIBELF;

      const char *name = elf_strptr (elf, *shstrndx, refshdr->sh_name);
      if (unlikely (name == NULL))
	return DWFL_E_LIBELF;

      if ((*mod->dwfl->callbacks->section_address) (MODCB_ARGS (mod),
						    name, shndx, refshdr,
						    &refshdr->sh_addr))
	return CBFAIL;

      if (refshdr->sh_addr == (Dwarf_Addr) -1l)
	/* The callback indicated this section wasn't really loaded but we
	   don't really care.  */
	refshdr->sh_addr = 0;	/* Make no adjustment below.  */

      /* Update the in-core file's section header to show the final
	 load address (or unloadedness).  This serves as a cache,
	 so we won't get here again for the same section.  */
      if (likely (refshdr->sh_addr != 0)
	  && unlikely (! gelf_update_shdr (refscn, refshdr)))
	return DWFL_E_LIBELF;
    }

  if (refshdr->sh_flags & SHF_ALLOC)
    /* Apply the adjustment.  */
    *value += dwfl_adjusted_address (mod, refshdr->sh_addr);

  return DWFL_E_NOERROR;
}
Пример #13
0
static int should_copy_scn(Elf *elf, GElf_Shdr *shdr, struct strlist *scns)
{
	char *name;
	size_t shstrndx;

	if (elf_getshdrstrndx(elf, &shstrndx) < 0)
		return 0;
	name = elf_strptr(elf, shstrndx, shdr->sh_name);
	if (name == NULL)
		return 0;

	if (strlist__has_entry(scns, name))
		return 1;
	return 0;
}
Пример #14
0
static ElfSectionInfo FindSectionByName(Elf *e, const char *name) {
    size_t shstrndx;
    elf_getshdrstrndx(e, &shstrndx);

    Elf_Scn *scn = nullptr;
    GElf_Shdr shdr;
    for (;;) {
        scn = elf_nextscn(e, scn);
        if (scn == nullptr)
            return std::make_pair(nullptr, shdr);
        gelf_getshdr(scn, &shdr);
        auto sec_name = elf_strptr(e, shstrndx, shdr.sh_name);
        if (strcmp(sec_name, name) == 0)
            return std::make_pair(scn, shdr);
    }
}
Пример #15
0
static int
dt_module_load_sect(dtrace_hdl_t *dtp, dt_module_t *dmp, ctf_sect_t *ctsp)
{
	const char *s;
	size_t shstrs;
	GElf_Shdr sh;
	Elf_Data *dp;
	Elf_Scn *sp;

	if (elf_getshdrstrndx(dmp->dm_elf, &shstrs) == -1)
		return (dt_set_errno(dtp, EDT_NOTLOADED));

	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 (sh.sh_type == ctsp->cts_type &&
		    sh.sh_entsize == ctsp->cts_entsize &&
		    strcmp(s, ctsp->cts_name) == 0)
			break; /* section matches specification */
	}

	/*
	 * If the section isn't found, return success but leave cts_data set
	 * to NULL and cts_size set to zero for our caller.
	 */
	if (sp == NULL || (dp = elf_getdata(sp, NULL)) == NULL)
		return (0);

#if defined(sun)
	ctsp->cts_data = dp->d_buf;
#else
	if ((ctsp->cts_data = malloc(dp->d_size)) == NULL)
		return (0);
	memcpy(ctsp->cts_data, dp->d_buf, dp->d_size);
#endif
	ctsp->cts_size = dp->d_size;

	dt_dprintf("loaded %s [%s] (%lu bytes)\n",
	    dmp->dm_name, ctsp->cts_name, (ulong_t)ctsp->cts_size);

	return (0);
}
Пример #16
0
Dwfl_Error
internal_function
__libdwfl_relocate (Dwfl_Module *mod, Elf *debugfile, bool debug)
{
  assert (mod->e_type == ET_REL);

  GElf_Ehdr ehdr_mem;
  const GElf_Ehdr *ehdr = gelf_getehdr (debugfile, &ehdr_mem);
  if (ehdr == NULL)
    return DWFL_E_LIBELF;

  size_t d_shstrndx;
  if (elf_getshdrstrndx (debugfile, &d_shstrndx) < 0)
    return DWFL_E_LIBELF;

  RELOC_SYMTAB_CACHE (reloc_symtab);

  /* Look at each section in the debuginfo file, and process the
     relocation sections for debugging sections.  */
  Dwfl_Error result = DWFL_E_NOERROR;
  Elf_Scn *scn = NULL;
  while (result == DWFL_E_NOERROR
	 && (scn = elf_nextscn (debugfile, scn)) != NULL)
    {
      GElf_Shdr shdr_mem;
      GElf_Shdr *shdr = gelf_getshdr (scn, &shdr_mem);

      if ((shdr->sh_type == SHT_REL || shdr->sh_type == SHT_RELA)
	  && shdr->sh_size != 0)
	{
	  /* It's a relocation section.  */

	  Elf_Scn *tscn = elf_getscn (debugfile, shdr->sh_info);
	  if (unlikely (tscn == NULL))
	    result = DWFL_E_LIBELF;
	  else
	    result = relocate_section (mod, debugfile, ehdr, d_shstrndx,
				       &reloc_symtab, scn, shdr, tscn,
				       debug, !debug);
	}
    }

  return result;
}
Пример #17
0
static Elf_Scn *find_section(Elf *elf, const char *needle) {
    size_t shstrndx;
    if (elf_getshdrstrndx(elf, &shstrndx) != 0)
        errx(EXIT_FAILURE, "Could not find string section in file");

    Elf_Scn *scn;
    GElf_Shdr shdr;
    for (scn = elf_nextscn(elf, NULL);
         scn != NULL;
         scn = elf_nextscn(elf, scn)) {
        if (gelf_getshdr(scn, &shdr) == NULL)
            errx(EXIT_FAILURE, "Cannot get section header");

        const char *scn_name = elf_strptr(elf, shstrndx, shdr.sh_name);
        if (strcmp(scn_name, needle) == 0)
            return scn;
    }
    return NULL;
}
Пример #18
0
/* Search for the sections named ".eh_frame" and ".eh_frame_hdr".  */
static Dwarf_CFI *
getcfi_shdr (Elf *elf, const GElf_Ehdr *ehdr)
{
  size_t shstrndx;
  if (elf_getshdrstrndx (elf, &shstrndx) != 0)
    {
      __libdw_seterrno (DWARF_E_GETEHDR_ERROR);
      return NULL;
    }

  if (shstrndx != 0)
    {
      Elf_Scn *hdr_scn = NULL;
      GElf_Addr hdr_vaddr = 0;
      Elf_Scn *scn = NULL;
      while ((scn = elf_nextscn (elf, scn)) != NULL)
	{
	  GElf_Shdr shdr_mem;
	  GElf_Shdr *shdr = gelf_getshdr (scn, &shdr_mem);
	  if (shdr == NULL)
	    continue;
	  const char *name = elf_strptr (elf, shstrndx, shdr->sh_name);
	  if (name == NULL)
	    continue;
	  if (!strcmp (name, ".eh_frame_hdr"))
	    {
	      hdr_scn = scn;
	      hdr_vaddr = shdr->sh_addr;
	    }
	  else if (!strcmp (name, ".eh_frame"))
	    {
	      if (shdr->sh_type == SHT_PROGBITS)
		return getcfi_scn_eh_frame (elf, ehdr, scn, shdr,
					    hdr_scn, hdr_vaddr);
	      else
		return NULL;
	    }
	}
    }

  return (void *) -1l;
}
Пример #19
0
Dwfl_Error
internal_function
__libdwfl_relocate_section (Dwfl_Module *mod, Elf *relocated,
			    Elf_Scn *relocscn, Elf_Scn *tscn, bool partial)
{
  GElf_Ehdr ehdr_mem;
  GElf_Shdr shdr_mem;

  RELOC_SYMTAB_CACHE (reloc_symtab);

  size_t shstrndx;
  if (elf_getshdrstrndx (relocated, &shstrndx) < 0)
    return DWFL_E_LIBELF;

  return (__libdwfl_module_getebl (mod)
	  ?: relocate_section (mod, relocated,
			       gelf_getehdr (relocated, &ehdr_mem), shstrndx,
			       &reloc_symtab,
			       relocscn, gelf_getshdr (relocscn, &shdr_mem),
			       tscn, false, partial));
}
Пример #20
0
static void
elf_foreach_resource_section (Elf             *elf,
                              SectionCallback  callback,
                              gpointer         data)
{
  size_t shstrndx, shnum;
  size_t scnidx;
  Elf_Scn *scn;
  GElf_Shdr *shdr, shdr_mem;
  const gchar *section_name;

  elf_getshdrstrndx (elf, &shstrndx);
  g_assert (shstrndx >= 0);

  elf_getshdrnum (elf, &shnum);
  g_assert (shnum >= 0);

  for (scnidx = 1; scnidx < shnum; scnidx++)
    {
      scn = elf_getscn (elf, scnidx);
      if (scn == NULL)
        continue;

      shdr = gelf_getshdr (scn, &shdr_mem);
      if (shdr == NULL)
        continue;

      if (shdr->sh_type != SHT_PROGBITS)
        continue;

      section_name = elf_strptr (elf, shstrndx, shdr->sh_name);
      if (section_name == NULL ||
          !g_str_has_prefix (section_name, ".gresource."))
        continue;

      if (!callback (shdr, section_name + strlen (".gresource."), data))
        break;
    }
}
Пример #21
0
static Elf_Scn *
get_scn_named(Elf *elf, char *goal, GElf_Shdr *shdrp_out)
{
    int rc;
    size_t shstrndx = -1;
    int scn_no = 0;
    Elf_Scn *scn = NULL;
    GElf_Shdr shdr_data, *shdrp;

    shdrp = shdrp_out ? shdrp_out : &shdr_data;

    rc = elf_getshdrstrndx(elf, &shstrndx);
    if (rc < 0)
	return NULL;

    do {
	GElf_Shdr *shdr;
	char *name;

	scn = elf_getscn(elf, ++scn_no);
	if (!scn)
	    break;

	shdr = gelf_getshdr(scn, shdrp);
	if (!shdr)
	    /*
	     * the binary is malformed, but hey, maybe the next one is fine,
	     * why not...
	     */
	    continue;

	name = elf_strptr(elf, shstrndx, shdr->sh_name);
	if (name && !strcmp(name, goal))
	    return scn;
    } while (scn != NULL);
    return NULL;
}
Пример #22
0
/* Looks for a section with real data, not just a section with a header */
static Elf_Scn *
find_elf_section_by_name(Elf *elf, const char *match_name)
{
    Elf_Scn *scn;
    size_t shstrndx;  /* Means "section header string table section index" */

    if (elf_getshdrstrndx(elf, &shstrndx) != 0) {
        NOTIFY_ELF();
        return NULL;
    }

    for (scn = elf_getscn(elf, 0); scn != NULL; scn = elf_nextscn(elf, scn)) {
        Elf_Shdr *section_header = elf_getshdr(scn);
        const char *sec_name;
        if (section_header == NULL) {
            NOTIFY_ELF();
            continue;
        }
        sec_name = elf_strptr(elf, shstrndx, section_header->sh_name);
        if (sec_name == NULL) {
            NOTIFY_ELF();
        }
        if (strcmp(sec_name, match_name) == 0) {
            /* For our purposes, we want to treat a no-data section
             * type as if it didn't exist.  This happens sometimes in
             * debuglink files where some sections like .symtab are
             * present b/c the headers mirror the original ELF file, but
             * there's no data there.  Xref i#642.
             */
            if (TEST(SHT_NOBITS, section_header->sh_type))
                return NULL;
            return scn;
        }
    }
    return NULL;
}
Пример #23
0
int
pkg_get_myarch(char *dest, size_t sz)
{
	Elf *elf = NULL;
	GElf_Ehdr elfhdr;
	GElf_Shdr shdr;
	Elf_Data *data;
	Elf_Note note;
	Elf_Scn *scn = NULL;
	int fd;
	char *src = NULL;
	char *osname;
	uint32_t version = 0;
	int ret = EPKG_OK;
	int i;
	const char *arch, *abi, *endian_corres_str, *wordsize_corres_str, *fpu;

	if (elf_version(EV_CURRENT) == EV_NONE) {
		pkg_emit_error("ELF library initialization failed: %s",
		    elf_errmsg(-1));
		return (EPKG_FATAL);
	}

	if ((fd = open(_PATH_BSHELL, O_RDONLY)) < 0) {
		pkg_emit_errno("open", _PATH_BSHELL);
		snprintf(dest, sz, "%s", "unknown");
		return (EPKG_FATAL);
	}

	if ((elf = elf_begin(fd, ELF_C_READ, NULL)) == NULL) {
		ret = EPKG_FATAL;
		pkg_emit_error("elf_begin() failed: %s.", elf_errmsg(-1));
		goto cleanup;
	}

	if (gelf_getehdr(elf, &elfhdr) == NULL) {
		ret = EPKG_FATAL;
		pkg_emit_error("getehdr() failed: %s.", elf_errmsg(-1));
		goto cleanup;
	}

	while ((scn = elf_nextscn(elf, scn)) != NULL) {
		if (gelf_getshdr(scn, &shdr) != &shdr) {
			ret = EPKG_FATAL;
			pkg_emit_error("getshdr() failed: %s.", elf_errmsg(-1));
			goto cleanup;
		}

		if (shdr.sh_type == SHT_NOTE)
			break;
	}

	if (scn == NULL) {
		ret = EPKG_FATAL;
		pkg_emit_error("failed to get the note section");
		goto cleanup;
	}

	data = elf_getdata(scn, NULL);
	src = data->d_buf;
	while ((uintptr_t)src < ((uintptr_t)data->d_buf + data->d_size)) {
		memcpy(&note, src, sizeof(Elf_Note));
		src += sizeof(Elf_Note);
		if (note.n_type == NT_VERSION)
			break;
		src += note.n_namesz + note.n_descsz;
	}
	if ((uintptr_t)src >= ((uintptr_t)data->d_buf + data->d_size)) {
		ret = EPKG_FATAL;
		pkg_emit_error("failed to find the version elf note");
		goto cleanup;
	}
	osname = src;
	src += roundup2(note.n_namesz, 4);
	if (elfhdr.e_ident[EI_DATA] == ELFDATA2MSB)
		version = be32dec(src);
	else
		version = le32dec(src);

	for (i = 0; osname[i] != '\0'; i++)
		osname[i] = (char)tolower(osname[i]);

	wordsize_corres_str = elf_corres_to_string(wordsize_corres,
	    (int)elfhdr.e_ident[EI_CLASS]);

	arch = elf_corres_to_string(mach_corres, (int) elfhdr.e_machine);
#if defined(__DragonFly__)
	snprintf(dest, sz, "%s:%d.%d",
	    osname, version / 100000, (((version / 100 % 1000)+1)/2)*2);
#else
	snprintf(dest, sz, "%s:%d", osname, version / 100000);
#endif

	switch (elfhdr.e_machine) {
	case EM_ARM:
		endian_corres_str = elf_corres_to_string(endian_corres,
		    (int)elfhdr.e_ident[EI_DATA]);

		/* FreeBSD doesn't support the hard-float ABI yet */
		fpu = "softfp";
		if ((elfhdr.e_flags & 0xFF000000) != 0) {
			const char *sh_name = NULL;
			size_t shstrndx;

			/* This is an EABI file, the conformance level is set */
			abi = "eabi";

			/* Find which TARGET_ARCH we are building for. */
			elf_getshdrstrndx(elf, &shstrndx);
			while ((scn = elf_nextscn(elf, scn)) != NULL) {
				sh_name = NULL;
				if (gelf_getshdr(scn, &shdr) != &shdr) {
					scn = NULL;
					break;
				}

				sh_name = elf_strptr(elf, shstrndx,
				    shdr.sh_name);
				if (sh_name == NULL)
					continue;
				if (strcmp(".ARM.attributes", sh_name) == 0)
					break;
			}
			if (scn != NULL && sh_name != NULL) {
				data = elf_getdata(scn, NULL);
				/*
				 * Prior to FreeBSD 10.0 libelf would return
				 * NULL from elf_getdata on the .ARM.attributes
				 * section. As this was the first release to
				 * get armv6 support assume a NULL value means
				 * arm.
				 *
				 * This assumption can be removed when 9.x
				 * is unsupported.
				 */
				if (data != NULL) {
					arch = aeabi_parse_arm_attributes(
					    data->d_buf, data->d_size);
					if (arch == NULL) {
						ret = EPKG_FATAL;
						pkg_emit_error(
						    "unknown ARM ARCH");
						goto cleanup;
					}
				}
			} else {
				ret = EPKG_FATAL;
				pkg_emit_error("Unable to find the "
				    ".ARM.attributes section");
				goto cleanup;
			}

		} else if (elfhdr.e_ident[EI_OSABI] != ELFOSABI_NONE) {
			/*
			 * EABI executables all have this field set to
			 * ELFOSABI_NONE, therefore it must be an oabi file.
			 */
			abi = "oabi";
                } else {
			/*
			 * We may have failed to positively detect the ABI,
			 * set the ABI to unknown. If we end up here one of
			 * the above cases should be fixed for the binary.
			 */
			ret = EPKG_FATAL;
			pkg_emit_error("unknown ARM ABI");
			goto cleanup;
		}
		snprintf(dest + strlen(dest), sz - strlen(dest),
		    ":%s:%s:%s:%s:%s", arch, wordsize_corres_str,
		    endian_corres_str, abi, fpu);
		break;
	case EM_MIPS:
		/*
		 * this is taken from binutils sources:
		 * include/elf/mips.h
		 * mapping is figured out from binutils:
		 * gas/config/tc-mips.c
		 */
		switch (elfhdr.e_flags & EF_MIPS_ABI) {
			case E_MIPS_ABI_O32:
				abi = "o32";
				break;
			case E_MIPS_ABI_N32:
				abi = "n32";
				break;
			default:
				if (elfhdr.e_ident[EI_DATA] == ELFCLASS32)
					abi = "o32";
				else if (elfhdr.e_ident[EI_DATA] == ELFCLASS64)
					abi = "n64";
				else
					abi = "unknown";
				break;
		}
		endian_corres_str = elf_corres_to_string(endian_corres,
		    (int)elfhdr.e_ident[EI_DATA]);

		snprintf(dest + strlen(dest), sz - strlen(dest), ":%s:%s:%s:%s",
		    arch, wordsize_corres_str, endian_corres_str, abi);
		break;
	default:
		snprintf(dest + strlen(dest), sz - strlen(dest), ":%s:%s",
		    arch, wordsize_corres_str);
		break;
	}

cleanup:
	if (elf != NULL)
		elf_end(elf);

	close(fd);
	return (ret);
}
Пример #24
0
/**
 * Look for a magic "flowlib" elf section and read it out, if it exists. Most of
 * this code adapted from hphp/util/embedded-data.cpp.
 */
CAMLprim value get_embedded_flowlib_data(value filename) {
  CAMLparam1(filename);
  CAMLlocal1(result);

  if (elf_version(EV_CURRENT) == EV_NONE) {
    goto fail_early;
  }

  int fd = open(String_val(filename), O_RDONLY);
  if (fd < 0) {
    goto fail_early;
  }

  Elf* e = elf_begin(fd, ELF_C_READ, 0);
  if (!e || elf_kind(e) != ELF_K_ELF) {
    goto fail_after_open;
  }

  size_t shstrndx = 0;
#ifdef HAVE_ELF_GETSHDRSTRNDX
  int stat = elf_getshdrstrndx(e, &shstrndx);
#else
  int stat = elf_getshstrndx(e, &shstrndx);
#endif
  if (stat < 0 || shstrndx == 0) {
    goto fail_after_elf_begin;
  }

  Elf_Scn *scn = NULL;
  while ((scn = elf_nextscn(e, scn))) {
    GElf_Shdr shdr;
    if (gelf_getshdr(scn, &shdr) != &shdr) {
      goto fail_after_elf_begin;
    }

    char *name = elf_strptr(e, shstrndx, shdr.sh_name);
    if (!name) {
      goto fail_after_elf_begin;
    }

    if (!strcmp("flowlib", name)) {
      GElf_Shdr ghdr;
      if (gelf_getshdr(scn, &ghdr) != &ghdr) {
        goto fail_after_elf_begin;
      }

      size_t offset = ghdr.sh_offset;
      size_t size = ghdr.sh_size;

      elf_end(e);

      lseek(fd, offset, SEEK_SET);
      result = caml_alloc_string(size);
      ssize_t ret = read(fd, String_val(result), size);
      if (ret != (ssize_t)size) {
        goto fail_after_elf_begin;
      }

      close(fd);
      CAMLreturn(SOME(result));
    }
  }

fail_after_elf_begin:
  elf_end(e);
fail_after_open:
  close(fd);
fail_early:
  CAMLreturn(NONE);
}
Пример #25
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;
}
Пример #26
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);
}
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;
}
Пример #28
0
/* If the main file might have been prelinked, then we need to
   discover the correct synchronization address between the main and
   debug files.  Because of prelink's section juggling, we cannot rely
   on the address_sync computed from PT_LOAD segments (see open_elf).

   We will attempt to discover a synchronization address based on the
   section headers instead.  But finding a section address that is
   safe to use requires identifying which sections are SHT_PROGBITS.
   We can do that in the main file, but in the debug file all the
   allocated sections have been transformed into SHT_NOBITS so we have
   lost the means to match them up correctly.

   The only method left to us is to decode the .gnu.prelink_undo
   section in the prelinked main file.  This shows what the sections
   looked like before prelink juggled them--when they still had a
   direct correspondence to the debug file.  */
static Dwfl_Error
find_prelink_address_sync (Dwfl_Module *mod, struct dwfl_file *file)
{
  /* The magic section is only identified by name.  */
  size_t shstrndx;
  if (elf_getshdrstrndx (mod->main.elf, &shstrndx) < 0)
    return DWFL_E_LIBELF;

  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 (unlikely (shdr == NULL))
	return DWFL_E_LIBELF;
      if (shdr->sh_type == SHT_PROGBITS
	  && !(shdr->sh_flags & SHF_ALLOC)
	  && shdr->sh_name != 0)
	{
	  const char *secname = elf_strptr (mod->main.elf, shstrndx,
					    shdr->sh_name);
	  if (unlikely (secname == NULL))
	    return DWFL_E_LIBELF;
	  if (!strcmp (secname, ".gnu.prelink_undo"))
	    break;
	}
    }

  if (scn == NULL)
    /* There was no .gnu.prelink_undo section.  */
    return DWFL_E_NOERROR;

  Elf_Data *undodata = elf_rawdata (scn, NULL);
  if (unlikely (undodata == NULL))
    return DWFL_E_LIBELF;

  /* Decode the section.  It consists of the original ehdr, phdrs,
     and shdrs (but omits section 0).  */

  union
  {
    Elf32_Ehdr e32;
    Elf64_Ehdr e64;
  } ehdr;
  Elf_Data dst =
    {
      .d_buf = &ehdr,
      .d_size = sizeof ehdr,
      .d_type = ELF_T_EHDR,
      .d_version = EV_CURRENT
    };
  Elf_Data src = *undodata;
  src.d_size = gelf_fsize (mod->main.elf, ELF_T_EHDR, 1, EV_CURRENT);
  src.d_type = ELF_T_EHDR;
  if (unlikely (gelf_xlatetom (mod->main.elf, &dst, &src,
			       elf_getident (mod->main.elf, NULL)[EI_DATA])
		== NULL))
    return DWFL_E_LIBELF;

  size_t shentsize = gelf_fsize (mod->main.elf, ELF_T_SHDR, 1, EV_CURRENT);
  size_t phentsize = gelf_fsize (mod->main.elf, ELF_T_PHDR, 1, EV_CURRENT);

  uint_fast16_t phnum;
  uint_fast16_t shnum;
  if (ehdr.e32.e_ident[EI_CLASS] == ELFCLASS32)
    {
      if (ehdr.e32.e_shentsize != shentsize
	  || ehdr.e32.e_phentsize != phentsize)
	return DWFL_E_BAD_PRELINK;
      phnum = ehdr.e32.e_phnum;
      shnum = ehdr.e32.e_shnum;
    }
  else
    {
      if (ehdr.e64.e_shentsize != shentsize
	  || ehdr.e64.e_phentsize != phentsize)
	return DWFL_E_BAD_PRELINK;
      phnum = ehdr.e64.e_phnum;
      shnum = ehdr.e64.e_shnum;
    }

  /* Since prelink does not store the zeroth section header in the undo
     section, it cannot support SHN_XINDEX encoding.  */
  if (unlikely (shnum >= SHN_LORESERVE)
      || unlikely (undodata->d_size != (src.d_size
					+ phnum * phentsize
					+ (shnum - 1) * shentsize)))
    return DWFL_E_BAD_PRELINK;

  /* We look at the allocated SHT_PROGBITS (or SHT_NOBITS) sections.  (Most
     every file will have some SHT_PROGBITS sections, but it's possible to
     have one with nothing but .bss, i.e. SHT_NOBITS.)  The special sections
     that can be moved around have different sh_type values--except for
     .interp, the section that became the PT_INTERP segment.  So we exclude
     the SHT_PROGBITS section whose address matches the PT_INTERP p_vaddr.
     For this reason, we must examine the phdrs first to find PT_INTERP.  */

  GElf_Addr main_interp = 0;
  {
    size_t main_phnum;
    if (unlikely (elf_getphdrnum (mod->main.elf, &main_phnum)))
      return DWFL_E_LIBELF;
    for (size_t i = 0; i < main_phnum; ++i)
      {
	GElf_Phdr phdr;
	if (unlikely (gelf_getphdr (mod->main.elf, i, &phdr) == NULL))
	  return DWFL_E_LIBELF;
	if (phdr.p_type == PT_INTERP)
	  {
	    main_interp = phdr.p_vaddr;
	    break;
	  }
      }
  }

  src.d_buf += src.d_size;
  src.d_type = ELF_T_PHDR;
  src.d_size = phnum * phentsize;

  GElf_Addr undo_interp = 0;
  bool class32 = ehdr.e32.e_ident[EI_CLASS] == ELFCLASS32;
  {
    size_t phdr_size = class32 ? sizeof (Elf32_Phdr) : sizeof (Elf64_Phdr);
    if (unlikely (phnum > SIZE_MAX / phdr_size))
      return DWFL_E_NOMEM;
    const size_t phdrs_bytes = phnum * phdr_size;
    void *phdrs = malloc (phdrs_bytes);
    if (unlikely (phdrs == NULL))
      return DWFL_E_NOMEM;
    dst.d_buf = phdrs;
    dst.d_size = phdrs_bytes;
    if (unlikely (gelf_xlatetom (mod->main.elf, &dst, &src,
				 ehdr.e32.e_ident[EI_DATA]) == NULL))
      {
	free (phdrs);
	return DWFL_E_LIBELF;
      }
    if (class32)
      {
	Elf32_Phdr (*p32)[phnum] = phdrs;
	for (uint_fast16_t i = 0; i < phnum; ++i)
	  if ((*p32)[i].p_type == PT_INTERP)
	    {
	      undo_interp = (*p32)[i].p_vaddr;
	      break;
	    }
      }
    else
      {
	Elf64_Phdr (*p64)[phnum] = phdrs;
	for (uint_fast16_t i = 0; i < phnum; ++i)
	  if ((*p64)[i].p_type == PT_INTERP)
	    {
	      undo_interp = (*p64)[i].p_vaddr;
	      break;
	    }
      }
    free (phdrs);
  }

  if (unlikely ((main_interp == 0) != (undo_interp == 0)))
    return DWFL_E_BAD_PRELINK;

  src.d_buf += src.d_size;
  src.d_type = ELF_T_SHDR;
  src.d_size = gelf_fsize (mod->main.elf, ELF_T_SHDR, shnum - 1, EV_CURRENT);

  size_t shdr_size = class32 ? sizeof (Elf32_Shdr) : sizeof (Elf64_Shdr);
  if (unlikely (shnum - 1  > SIZE_MAX / shdr_size))
    return DWFL_E_NOMEM;
  const size_t shdrs_bytes = (shnum - 1) * shdr_size;
  void *shdrs = malloc (shdrs_bytes);
  if (unlikely (shdrs == NULL))
    return DWFL_E_NOMEM;
  dst.d_buf = shdrs;
  dst.d_size = shdrs_bytes;
  if (unlikely (gelf_xlatetom (mod->main.elf, &dst, &src,
			       ehdr.e32.e_ident[EI_DATA]) == NULL))
    {
      free (shdrs);
      return DWFL_E_LIBELF;
    }

  /* Now we can look at the original section headers of the main file
     before it was prelinked.  First we'll apply our method to the main
     file sections as they are after prelinking, to calculate the
     synchronization address of the main file.  Then we'll apply that
     same method to the saved section headers, to calculate the matching
     synchronization address of the debug file.

     The method is to consider SHF_ALLOC sections that are either
     SHT_PROGBITS or SHT_NOBITS, excluding the section whose sh_addr
     matches the PT_INTERP p_vaddr.  The special sections that can be
     moved by prelink have other types, except for .interp (which
     becomes PT_INTERP).  The "real" sections cannot move as such, but
     .bss can be split into .dynbss and .bss, with the total memory
     image remaining the same but being spread across the two sections.
     So we consider the highest section end, which still matches up.  */

  GElf_Addr highest;

  inline void consider_shdr (GElf_Addr interp,
			     GElf_Word sh_type,
			     GElf_Xword sh_flags,
			     GElf_Addr sh_addr,
			     GElf_Xword sh_size)
  {
    if ((sh_flags & SHF_ALLOC)
	&& ((sh_type == SHT_PROGBITS && sh_addr != interp)
	    || sh_type == SHT_NOBITS))
      {
	const GElf_Addr sh_end = sh_addr + sh_size;
	if (sh_end > highest)
	  highest = sh_end;
      }
  }

  highest = 0;
  scn = NULL;
  while ((scn = elf_nextscn (mod->main.elf, scn)) != NULL)
    {
      GElf_Shdr sh_mem;
      GElf_Shdr *sh = gelf_getshdr (scn, &sh_mem);
      if (unlikely (sh == NULL))
	{
	  free (shdrs);
	  return DWFL_E_LIBELF;
	}
      consider_shdr (main_interp, sh->sh_type, sh->sh_flags,
		     sh->sh_addr, sh->sh_size);
    }
  if (highest > mod->main.vaddr)
    {
      mod->main.address_sync = highest;

      highest = 0;
      if (class32)
	{
	  Elf32_Shdr (*s32)[shnum - 1] = shdrs;
	  for (size_t i = 0; i < shnum - 1; ++i)
	    consider_shdr (undo_interp, (*s32)[i].sh_type,
			   (*s32)[i].sh_flags, (*s32)[i].sh_addr,
			   (*s32)[i].sh_size);
	}
      else
	{
	  Elf64_Shdr (*s64)[shnum - 1] = shdrs;
	  for (size_t i = 0; i < shnum - 1; ++i)
	    consider_shdr (undo_interp, (*s64)[i].sh_type,
			   (*s64)[i].sh_flags, (*s64)[i].sh_addr,
			   (*s64)[i].sh_size);
	}

      if (highest > file->vaddr)
	file->address_sync = highest;
      else
	{
	  free (shdrs);
	  return DWFL_E_BAD_PRELINK;
	}
    }

  free (shdrs);

  return DWFL_E_NOERROR;
}

/* Find the separate debuginfo file for this module and open libelf on it.
   When we return success, MOD->debug is set up.  */
static Dwfl_Error
find_debuginfo (Dwfl_Module *mod)
{
  if (mod->debug.elf != NULL)
    return DWFL_E_NOERROR;

  GElf_Word debuglink_crc = 0;
  const char *debuglink_file;
  debuglink_file = INTUSE(dwelf_elf_gnu_debuglink) (mod->main.elf,
						    &debuglink_crc);

  mod->debug.fd = (*mod->dwfl->callbacks->find_debuginfo) (MODCB_ARGS (mod),
							   mod->main.name,
							   debuglink_file,
							   debuglink_crc,
							   &mod->debug.name);
  Dwfl_Error result = open_elf (mod, &mod->debug);
  if (result == DWFL_E_NOERROR && mod->debug.address_sync != 0)
    result = find_prelink_address_sync (mod, &mod->debug);
  return result;
}

/* Try to find the alternative debug link for the given DWARF and set
   it if found.  Only called when mod->dw is already setup but still
   might need an alternative (dwz multi) debug file.  filename is either
   the main or debug name from which the Dwarf was created. */
static void
find_debug_altlink (Dwfl_Module *mod, const char *filename)
{
  assert (mod->dw != NULL);

  const char *altname;
  const void *build_id;
  ssize_t build_id_len = INTUSE(dwelf_dwarf_gnu_debugaltlink) (mod->dw,
							       &altname,
							       &build_id);

  if (build_id_len > 0)
    {
      /* We could store altfile in the module, but don't really need it.  */
      char *altfile = NULL;
      mod->alt_fd = (*mod->dwfl->callbacks->find_debuginfo) (MODCB_ARGS (mod),
							     filename,
							     altname,
							     0,
							     &altfile);

      /* The (internal) callbacks might just set mod->alt_elf directly
	 because they open the Elf anyway for sanity checking.
	 Otherwise open either the given file name or use the fd
	 returned.  */
      Dwfl_Error error = open_elf_file (&mod->alt_elf, &mod->alt_fd,
					&altfile);
      if (error == DWFL_E_NOERROR)
	{
	  mod->alt = INTUSE(dwarf_begin_elf) (mod->alt_elf,
					      DWARF_C_READ, NULL);
	  if (mod->alt == NULL)
	    {
	      elf_end (mod->alt_elf);
	      mod->alt_elf = NULL;
	      close (mod->alt_fd);
	      mod->alt_fd = -1;
	    }
	  else
	    dwarf_setalt (mod->dw, mod->alt);
	}

      free (altfile); /* See above, we don't really need it.  */
    }
}
Пример #29
0
void radeon_elf_read(const char *elf_data, unsigned elf_size,
					struct radeon_shader_binary *binary,
					unsigned debug)
{
	char *elf_buffer;
	Elf *elf;
	Elf_Scn *section = NULL;
	Elf_Data *symbols = NULL, *relocs = NULL;
	size_t section_str_index;
	unsigned symbol_sh_link;

	/* One of the libelf implementations
	 * (http://www.mr511.de/software/english.htm) requires calling
	 * elf_version() before elf_memory().
	 */
	elf_version(EV_CURRENT);
	elf_buffer = MALLOC(elf_size);
	memcpy(elf_buffer, elf_data, elf_size);

	elf = elf_memory(elf_buffer, elf_size);

	elf_getshdrstrndx(elf, &section_str_index);
	binary->disassembled = 0;

	while ((section = elf_nextscn(elf, section))) {
		const char *name;
		Elf_Data *section_data = NULL;
		GElf_Shdr section_header;
		if (gelf_getshdr(section, &section_header) != &section_header) {
			fprintf(stderr, "Failed to read ELF section header\n");
			return;
		}
		name = elf_strptr(elf, section_str_index, section_header.sh_name);
		if (!strcmp(name, ".text")) {
			section_data = elf_getdata(section, section_data);
			binary->code_size = section_data->d_size;
			binary->code = MALLOC(binary->code_size * sizeof(unsigned char));
			memcpy(binary->code, section_data->d_buf, binary->code_size);
		} else if (!strcmp(name, ".AMDGPU.config")) {
			section_data = elf_getdata(section, section_data);
			binary->config_size = section_data->d_size;
			binary->config = MALLOC(binary->config_size * sizeof(unsigned char));
			memcpy(binary->config, section_data->d_buf, binary->config_size);
		} else if (debug && !strcmp(name, ".AMDGPU.disasm")) {
			binary->disassembled = 1;
			section_data = elf_getdata(section, section_data);
			fprintf(stderr, "\nShader Disassembly:\n\n");
			fprintf(stderr, "%.*s\n", (int)section_data->d_size,
						  (char *)section_data->d_buf);
		} else if (!strncmp(name, ".rodata", 7)) {
			section_data = elf_getdata(section, section_data);
			binary->rodata_size = section_data->d_size;
			binary->rodata = MALLOC(binary->rodata_size * sizeof(unsigned char));
			memcpy(binary->rodata, section_data->d_buf, binary->rodata_size);
		} else if (!strncmp(name, ".symtab", 7)) {
			symbols = elf_getdata(section, section_data);
			symbol_sh_link = section_header.sh_link;
			parse_symbol_table(symbols, &section_header, binary);
		} else if (!strcmp(name, ".rel.text")) {
			relocs = elf_getdata(section, section_data);
			binary->reloc_count = section_header.sh_size /
					section_header.sh_entsize;
		}
	}

	parse_relocs(elf, relocs, symbols, symbol_sh_link, binary);

	if (elf){
		elf_end(elf);
	}
	FREE(elf_buffer);

	/* Cache the config size per symbol */
	if (binary->global_symbol_count) {
		binary->config_size_per_symbol =
			binary->config_size / binary->global_symbol_count;
	} else {
		binary->global_symbol_count = 1;
		binary->config_size_per_symbol = binary->config_size;
	}
}
Пример #30
0
int init(char* fname)
{
	char *id, bytes[5];

	if (elf_version (EV_CURRENT) == EV_NONE) {
		errx (EXIT_FAILURE, " ELF  library   initialization  "
		      " failed : %s", elf_errmsg (-1));
		return -1;
	}

	int fd;
	if ((fd = open (fname, O_RDONLY, 0)) < 0) {
		err (EXIT_FAILURE, " open  \"%s\"  failed ", fname);
		return -1;
	}
	g.fd = fd;

	Elf *e;
	if ((e = elf_begin (fd, ELF_C_READ, NULL)) == NULL) {
		errx (EXIT_FAILURE, " elf_begin ()  failed : %s.",
		      elf_errmsg (-1));
		return -1;
	}

	if (elf_kind (e) != ELF_K_ELF) {
		errx (EXIT_FAILURE, " \"%s\" is  not an  ELF  object .",
		      fname);
		return -1;
	}
	g.e = e;

	GElf_Ehdr ehdr;
	if (gelf_getehdr (e, &ehdr) == NULL) {
		errx (EXIT_FAILURE, " getehdr ()  failed : %s.",
		      elf_errmsg (-1));
		return -1;
	}
	g.ehdr = ehdr;

	int i;
	if ((i = gelf_getclass (e)) == ELFCLASSNONE) {
		errx (EXIT_FAILURE, " getclass ()  failed : %s.",
		      elf_errmsg (-1));
		return -1;
	}

	if ((id = elf_getident (e, NULL)) == NULL) {
		errx (EXIT_FAILURE, " getident ()  failed : %s.",
		      elf_errmsg (-1));
		return -1;
	}

	size_t n;
	if (elf_getshdrnum (e, &n) != 0) {
		errx (EXIT_FAILURE, " getshdrnum ()  failed : %s.",
		      elf_errmsg (-1));
		return -1;
	}
	g.shdrnum = n;

	if (elf_getshdrstrndx (e, &n) != 0) {
		errx (EXIT_FAILURE, " getshdrstrndx ()  failed : %s.",
		      elf_errmsg (-1));
		return -1;
	}
	g.shstrndx = n;

	if (elf_getphdrnum (e, &n) != 0) {
		errx (EXIT_FAILURE, " getphdrnum ()  failed : %s.",
		      elf_errmsg (-1));
		return -1;
	}
	g.phdrnum = n;

	init_scns();
	init_phdrs();

	return 0;
}