Ejemplo n.º 1
0
static ExportTrampolineVector FindExportTrampolines(Elf *e,
                                                    const ElfSectionInfo &xptramp_info) {
    auto sym_scn = FindSectionByType(e, SHT_DYNSYM);
    auto sym_data = elf_getdata(sym_scn.first, nullptr);
    auto syms = reinterpret_cast<Elf_Sym*>(sym_data->d_buf);

    ExportTrampolineVector res;
    // FIXME: this assumes that the whole section
    // is inside a single Elf_Data object
    auto xptramp_data = elf_getdata(xptramp_info.first, nullptr);
    auto xptramp_start = reinterpret_cast<uint8_t*>(xptramp_data->d_buf);
    auto xptramp_end = xptramp_start + xptramp_data->d_size;
    for (auto ptr = xptramp_start; ptr < xptramp_end;) {
        auto addr = xptramp_info.second.sh_addr   + xptramp_data->d_off + (ptr - xptramp_start);
        auto  ofs = xptramp_info.second.sh_offset + xptramp_data->d_off + (ptr - xptramp_start);
        auto arg = *reinterpret_cast<uint32_t*>(ptr + 1);
        switch(ptr[0]) {
        case 0x01:
            res.emplace_back(addr, ofs, syms[arg].st_value);
            break;
        case 0xE9:
            break;
        default:
            errx(EX_SOFTWARE, ".xptramp section has invalid byte: %hhd\n", ptr[0]);
        }
        ptr += 5;
    }
    return res;
}
Ejemplo n.º 2
0
unsigned char *
get_data_from_iterator (struct data_iterator *it, GElf_Addr size)
{
  unsigned char *ptr;

  /* If we're at the end of a data block, move onto the next.  */
  if (it->data && it->data->d_off + it->data->d_size == it->sec_offset)
    it->data = elf_getdata (it->dso->scn[it->sec], it->data);

  if (it->data == NULL)
    {
      /* Find out which section contains the next byte.  */
      it->sec = addr_to_sec (it->dso, it->addr);
      if (it->sec < 0)
	return NULL;

      /* Fast-forward to the block that contains ADDR, if any.  */
      it->sec_offset = it->addr - it->dso->shdr[it->sec].sh_addr;
      do
	it->data = elf_getdata (it->dso->scn[it->sec], it->data);
      while (it->data && it->data->d_off + it->data->d_size <= it->sec_offset);
    }

  /* Make sure that all the data we want is included in this block.  */
  if (it->data == NULL
      || it->data->d_off > it->sec_offset
      || it->data->d_off + it->data->d_size < it->sec_offset + size)
    return NULL;

  ptr = (unsigned char *) it->data->d_buf + (it->sec_offset - it->data->d_off);
  it->sec_offset += size;
  it->addr += size;
  return ptr;
}
Ejemplo n.º 3
0
static void handle_dynamic_section(elf_info_s *elf, Elf_Scn *scn, GElf_Shdr shdr)
{
    Elf_Data *data;
    GElf_Addr replt_addr;
    size_t replt_count;

    /* get data of .dynamic */
    data = elf_getdata(scn, NULL);

    /* iterate through .dynamic */
    for (size_t i = 0; i < shdr.sh_size / shdr.sh_entsize; ++i) {
        GElf_Dyn dyn;

        // get entries i
        gelf_getdyn(data, i, &dyn);
        // if replt
        if (dyn.d_tag == DT_JMPREL)
            replt_addr = dyn.d_un.d_ptr;
        // if replt_size
        if (dyn.d_tag == DT_PLTRELSZ)
            replt_count = dyn.d_un.d_val;
    }
    LOG(INFO, "Section relplt at 0x%lx (%zu)", replt_addr, replt_count);
    for (size_t i = 1; i < elf->hdr.e_shnum; ++i) {
        Elf_Scn *scn;
        GElf_Shdr shdr;
        scn = elf_getscn(elf->elf, i);
        gelf_getshdr(scn, &shdr);
        if (shdr.sh_addr == replt_addr && shdr.sh_size == replt_count) {
            elf->replt = elf_getdata(scn, NULL);
            elf->replt_count = shdr.sh_size / shdr.sh_entsize;
            break;
        }
    }
}
Ejemplo n.º 4
0
static void	resolve_relocations(sym_strtab **list)
{
  Elf_Scn	*scn;
  Elf64_Shdr	*shdr;

  scn = NULL;
  while ((scn = elf_nextscn(e, scn)))
    {
      if ((shdr = elf64_getshdr(scn)) == NULL)
      	exit_error("gelf_getshdr() fail");
      if (shdr->sh_type == SHT_DYNSYM)
	{
	  Elf_Data	*data;
	  data = elf_getdata(scn, NULL);
	  dynsym_tab = (Elf64_Sym*)data->d_buf;
	}
      if (shdr->sh_type == SHT_STRTAB && shdr->sh_flags == SHF_ALLOC)
	{
	  Elf_Data	*data;
	  data = elf_getdata(scn, NULL);
	  dynsym_strtab = (char*)data->d_buf;
	}
    }
  if (!dynsym_tab)
    return;
  scn = NULL;
  while ((scn = elf_nextscn(e, scn)))
    {
      if ((shdr = elf64_getshdr(scn)) == NULL)
      	exit_error("gelf_getshdr() fail");
      if (shdr->sh_type == SHT_RELA)
	reloc_treatment(scn, shdr, list);
    }
}
Ejemplo n.º 5
0
static Elf_Data *loaddata(Elf_Scn *scn, GElf_Shdr *shdr)
{
	Elf_Data *data = elf_getdata(scn, NULL);
	if (data == NULL || elf_getdata(scn, data) != NULL
	    || data->d_off || data->d_size != shdr->sh_size)
		return NULL;
	return data;
}
Ejemplo n.º 6
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);
}
Ejemplo n.º 7
0
struct trap_data_t read_trap_data(struct trap_file_t *file) {
    struct trap_data_t res = { TRAP_PLATFORM_UNKNOWN, 0, 0, NULL, 0 };
    Elf_Scn *txtrp_scn = find_section(file->elf, ".txtrp");
    if (txtrp_scn == NULL)
        return res;

    GElf_Shdr shdr;
    if (gelf_getshdr(txtrp_scn, &shdr) == NULL)
        errx(EXIT_FAILURE, "Cannot get section header");
    res.txtrp_address = shdr.sh_addr;

    // Get the platform
    GElf_Ehdr ehdr;
    if (gelf_getehdr(file->elf, &ehdr) == NULL)
        errx(EXIT_FAILURE, "Cannot get ELF header");
    switch (ehdr.e_machine) {
    case EM_386:
        res.trap_platform = TRAP_PLATFORM_POSIX_X86;
        break;

    case EM_X86_64:
        res.trap_platform = TRAP_PLATFORM_POSIX_X86_64;
        break;

    case EM_ARM:
        res.trap_platform = TRAP_PLATFORM_POSIX_ARM;
        break;

    case 183: // EM_AARCH64
        res.trap_platform = TRAP_PLATFORM_POSIX_ARM64;
        break;

    default:
        errx(EXIT_FAILURE, "Unknown ELF machine");
        break;
    }

    Elf_Data *data = elf_getdata(txtrp_scn, NULL);
    for (data = elf_getdata(txtrp_scn, NULL);
         data != NULL;
         data = elf_getdata(txtrp_scn, data))
        res.size += data->d_size;

    res.data = malloc(res.size);
    uint8_t *ptr = res.data;
    for (data = elf_getdata(txtrp_scn, NULL);
         data != NULL;
         data = elf_getdata(txtrp_scn, data)) {
        memcpy(ptr, data->d_buf, data->d_size);
        ptr += data->d_size;
    }
    return res;
}
Ejemplo n.º 8
0
static void handle_dynsym_section(elf_info_s *elf, Elf_Scn *scn, GElf_Shdr shdr)
{
    Elf_Data *data;
    /* get .dynsym data and size */
    elf->dynsym = elf_getdata(scn, NULL);
    elf->dynsym_count = shdr.sh_size / shdr.sh_entsize;

    /* retrieve the header table index link which point to .dynstr */
    scn = elf_getscn(elf->elf, shdr.sh_link);
    gelf_getshdr(scn, &shdr);
    /* get the data of .dynstr */
    data = elf_getdata(scn, NULL);
    elf->dynstr = data->d_buf;
}
Ejemplo n.º 9
0
/* Below code adapted from libelf tutorial example */
static u32 extract_functions_internal (const char *str, func_entry *func_list) {
    Elf *e;
    Elf_Kind ek;
    Elf_Scn *scn;
    Elf_Data *edata;
    u32 fd, i, symbol_count;
    GElf_Sym sym;
    GElf_Shdr shdr;
    u32 func_count = 0;

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

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

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

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

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

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

    elf_end(e);
    close(fd);
    return func_count;
}
Ejemplo n.º 10
0
/* if this function encounters an error it never returns */
static Elf_Data *exec_getdata( Elf_Scn *scn, int line )
#define exec_getdata(a) \
    exec_getdata(a,__LINE__)
{
    Elf_Data *data;
    char *location;

    location = NULL;
    data = elf_getdata(scn, NULL);
    if ( data != NULL )
    {
        if ( data->d_buf != NULL )
        {
            return data;
        }
        else
        {
            location = "d_buf";
        }
    }
    else
    {
        location = "elf_data";
    }
    fprintf( stderr, "exec_getdata: %s@%d - %s\n", location, line,
             elf_errmsg( -1 ) );
    exit( 1 );
}
Ejemplo n.º 11
0
int find_symbol(char *fn, struct lsym *lsym, unsigned long baseaddr)
{
	struct lsym *ls;
	int num = 0;
	for (ls = lsym; ls->name; ls++)
		num++;

	elf_version(EV_CURRENT);
	int fd = open(fn, O_RDONLY);
	if (fd < 0)
		return -1;

	long ret = -1;
	Elf *elf = elf_begin(fd, ELF_C_READ, NULL);
	if (elf == NULL)
		goto out;

	GElf_Ehdr header;
	if (!gelf_getehdr(elf, &header))
		goto out_elf;

	Elf_Scn *section = NULL;
	int found = 0;
	while (found < num && (section = elf_nextscn(elf, section)) != 0) {
		GElf_Shdr shdr, *sh;
		sh = gelf_getshdr(section, &shdr);

		if (sh->sh_type == SHT_SYMTAB || sh->sh_type == SHT_DYNSYM) {
			Elf_Data *data = elf_getdata(section, NULL);
			GElf_Sym *sym, symbol;
			int j;

			unsigned numsym = sh->sh_size / sh->sh_entsize;
			for (j = 0; j < numsym; j++) {
				sym = gelf_getsymshndx(data, NULL, j, &symbol, NULL);
				char *symname = elf_strptr(elf, shdr.sh_link, sym->st_name);
				for (ls = lsym; ls->name; ls++) {
					if (!strcmp(symname, ls->name)) {
						Elf_Scn *oscn = elf_getscn(elf, sym->st_shndx);
						GElf_Shdr oshdr, *osh;
						osh = gelf_getshdr(oscn, &oshdr);
						ls->addr = (sym->st_value - osh->sh_addr) + osh->sh_offset + baseaddr;
						found++;
						if (found == num)
							break;
					}
				}
			}
		}
	}
	if (found == num)
		ret = 0;

out_elf:
	elf_end(elf);

out:
	close(fd);
	return ret;
}
Ejemplo n.º 12
0
static int dump_dynamic(struct file_state *f, Elf_Scn *scn, GElf_Shdr *shdr)
{
	struct dyn_state d;
	GElf_Dyn needed_dyn;
	char *needed_name;
	int i;

	d.f = f;
	d.dyn_data = elf_getdata(scn, NULL);
	if (!d.dyn_data) {
		elf_err("elf_getdata failed");
		return -1;
	}
	d.count = shdr->sh_size / shdr->sh_entsize;

	for (i = 0; i < d.count; i++) {
		if (!gelf_getdyn(d.dyn_data, i, &needed_dyn))
			continue;

		if (needed_dyn.d_tag != DT_NEEDED)
			continue;

		needed_name = (char *)f->strtab_data->d_buf
			      + needed_dyn.d_un.d_val;

		dump_needed(f->t, needed_name);
	}

	return 0;
}
Ejemplo n.º 13
0
Elf_Scn *
get_scnbyname(Elf *elf, char *name, int *num)
{
	Elf32_Ehdr	* ehdr;
	Elf_Scn		* scn;
	Elf32_Shdr	* shdr;
	Elf_Data	* data;
	int		  cnt,
			  tmp;

	if (!num)
		num = &tmp;
	
	*num = 0;

	if ((ehdr = elf32_getehdr(elf))==NULL)
		return NULL;

	if (((scn = elf_getscn(elf, ehdr->e_shstrndx)) == NULL) ||
	    ((data = elf_getdata(scn, NULL)) == NULL))
		return NULL;

	for (cnt = 1, scn = NULL; (scn = elf_nextscn(elf, scn)); cnt++) {
		if ((shdr = elf32_getshdr(scn)) == NULL)
			return NULL;

		if (! strcmp(name, (char *)data->d_buf + shdr->sh_name)) {
			*num = cnt;
			return scn;
		}
	}
	return NULL;
}
Ejemplo n.º 14
0
/**
 * Read a script from it's elf section and store it
 * @param script In output, contains the lua script loaded
 * @param scn section containing the script
 * @param shdr section header
 * @param name name of the script
 */
static void load_script(struct lua_script *script, Elf_Scn *scn,
		GElf_Shdr *shdr, const char *name)
{
	unsigned i;
	Elf_Data *data;
	char *p;

	script->name = strdup(name + strlen(LUA_WRAPPER_SECTION_PREFIX));
	if (script->name == NULL)
	        exit(101);
	script->code = calloc(shdr->sh_size + 1, 1);
	if (script->name == NULL)
		exit(102);

	script->code[shdr->sh_size] = '\0';
	data = NULL;
	i = 0;
	while (i < shdr->sh_size && (data = elf_getdata(scn, data)) != NULL) {
		p = data->d_buf;
		while (p < (char *)data->d_buf + data->d_size) {
			script->code[i] = *p;
			i++;
			p++;
		}
	}
	remove_shebang(script->code);
}
Ejemplo n.º 15
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;
}
Ejemplo n.º 16
0
/**
 * @brief Search a single, particular ELF symbol table for a named symbol
 *
 * @param elf The open ELF object
 * @param symtab The ELF symbol table section
 * @param name The symbol name to find
 *
 * @returns The address to which the symbol points, 0 otherwise.
 */
static GElf_Addr elf_scn_getsymaddr_byname(Elf *elf, Elf_Scn *symtab,
                                           const char * name) {
    GElf_Shdr shdr;
    Elf_Data *data;
    uint32_t syms, i;
    GElf_Sym sym;

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

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

    syms = shdr.sh_size / shdr.sh_entsize;

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

    return 0;
}
Ejemplo n.º 17
0
/* Extract section and copy into HsaBrig */
static status_t extract_section_and_copy (Elf *elfP,
                                       Elf_Data *secHdr, 
                                       const SectionDesc* desc,
                                       hsa_ext_brig_module_t* brig_module,
                                       hsa_ext_brig_section_id_t section_id) {
    Elf_Scn* scn = NULL;
    Elf_Data* data = NULL;
    void* address_to_copy;
    size_t section_size=0;

    scn = extract_elf_section(elfP, secHdr, desc);

    if (scn) {
        if ((data = elf_getdata(scn, NULL)) == NULL) {
            return STATUS_UNKNOWN;
        }
        section_size = data->d_size;
        if (section_size > 0) {
          address_to_copy = malloc(section_size);
          memcpy(address_to_copy, data->d_buf, section_size);
        }
    }

    if ((!scn ||  section_size == 0))  {
        return STATUS_UNKNOWN;
    }

    /* Create a section header */
    brig_module->section[section_id] = (hsa_ext_brig_section_header_t*) address_to_copy; 

    return STATUS_SUCCESS;
} 
Ejemplo n.º 18
0
char*
elf_strptr(Elf *elf, size_t section, size_t offset) {
    Elf_Scn *scn;
    Elf_Data *sd;

    if (!elf) {
	return NULL;
    }
    elf_assert(elf->e_magic == ELF_MAGIC);
    if (!(scn = elf_getscn(elf, section))) {
	return NULL;
    }
    if (scn->s_type != SHT_STRTAB) {
	seterr(ERROR_NOSTRTAB);
	return NULL;
    }
    if (offset >= 0 && offset < scn->s_size) {
	sd = NULL;
	while ((sd = elf_getdata(scn, sd))) {
	    if (sd->d_buf
	     && offset >= (size_t)sd->d_off
	     && offset < (size_t)sd->d_off + sd->d_size) {
		return (char*)sd->d_buf + (offset - sd->d_off);
	    }
	}
    }
    seterr(ERROR_BADSTROFF);
    return NULL;
}
Ejemplo n.º 19
0
//---------------------------------------------------------------------
int getELFSymbolTableNdx(Elf* elf, char* symName)
{
  Elf_Scn *scn;
  Elf32_Shdr *shdr;
  Elf_Data *edata;
  Elf32_Sym *esym;


  scn = NULL;
  while ((scn = elf_nextscn(elf, scn)) != NULL){
    if ((shdr = elf32_getshdr(scn)) != NULL){
      if (SHT_SYMTAB == shdr->sh_type){
	edata = NULL;
	while ((edata = elf_getdata(scn, edata)) != NULL){
  	  if (ELF_T_SYM == edata->d_type){
	    int numSymbols, i;
	    char* symNameRead;
	    esym = (Elf32_Sym*)(edata->d_buf);
	    numSymbols = (int)(edata->d_size/shdr->sh_entsize);
	    for (i = 0; i < numSymbols; i++){
	      symNameRead = elf_strptr(elf, shdr->sh_link, esym[i].st_name);
	      if (strcmp(symNameRead, symName) == 0){
		return i;
	      }
	    }
	  }
	}
      }
    }
  }
  fprintf(stderr, "getElfSymbolTableNdx: Could not locate symbol in the symbol table.\n");
  return -1;
}
Ejemplo n.º 20
0
static Dwarf *
scngrp_read (Dwarf *result, Elf *elf, GElf_Ehdr *ehdr, Dwarf_Cmd cmd,
	     Elf_Scn *scngrp)
{
  /* SCNGRP is the section descriptor for a section group which might
     contain debug sections.  */
  Elf_Data *data = elf_getdata (scngrp, NULL);
  if (data == NULL)
    {
      /* We cannot read the section content.  Fail!  */
      free (result);
      return NULL;
    }

  /* The content of the section is a number of 32-bit words which
     represent section indices.  The first word is a flag word.  */
  Elf32_Word *scnidx = (Elf32_Word *) data->d_buf;
  size_t cnt;
  for (cnt = 1; cnt * sizeof (Elf32_Word) <= data->d_size; ++cnt)
    {
      Elf_Scn *scn = elf_getscn (elf, scnidx[cnt]);
      if (scn == NULL)
	{
	  /* A section group refers to a non-existing section.  Should
	     never happen.  */
	  __libdw_seterrno (DWARF_E_INVALID_ELF);
	  free (result);
	  return NULL;
	}

      check_section (result, ehdr, scn, true);
    }

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

	if ((data = elf_getdata(scn, NULL)) == NULL) {
		DPRINTFX("ERROR: elf_getdata() failed: %s", elf_errmsg(-1));
		return (1);
	}
	for (i = 0; gelf_getsym(data, i, &sym) != NULL; i++) {
		rsym = off + sym.st_value;
		if (addr >= rsym && addr < rsym + sym.st_size) {
			s = elf_strptr(e, stridx, sym.st_name);
			if (s != NULL) {
				*name = s;
				memcpy(symcopy, &sym, sizeof(*symcopy));
				/*
				 * DTrace expects the st_value to contain
				 * only the address relative to the start of
				 * the function.
				 */
				symcopy->st_value = rsym;
				return (0);
			}
		}
	}
	return (1);
}
Ejemplo n.º 22
0
scn_hdr_t* get_scn_hdr(int idx)
{
	Elf_Scn* scn = g.scns[idx];
	GElf_Shdr shdr = g.shdrs[idx];

	Elf_Data* data;
	size_t n;
	
	// if ( gelf_getshdr(scn , &shdr) != &shdr ) {
	// 	errx ( EXIT_FAILURE,
	// 	       " getshdr( shstrndx ) failed : %s.",
	// 	       elf_errmsg ( -1));
	// 	return NULL;
	// }

	// data = NULL; size_t buf_sz = 0;
	// while ((data=elf_getdata(scn, data)) != NULL) {
	// 	printf("+%d", data->d_size);
	// 	buf_sz += data->d_size;
	// }

	uint8_t* buf = (uint8_t*) malloc(shdr.sh_size);
	if (buf == NULL) {		
		errx (EXIT_FAILURE, "malloc failed");
		return NULL;
	}

	data = NULL; n = 0;
	while (n < shdr.sh_size &&
	       (data = elf_getdata(scn, data)) != NULL) {
		uint8_t* p = (uint8_t*)data->d_buf;
		size_t dsize = data->d_size;
		if(p != NULL)
			memcpy(buf+n, p, dsize);
		else //FIXME: seems some sections are empty in file
			memset(buf+n, 0, dsize);
		n += dsize;
	}

	// get the name string
	char* name;
	if ((name = elf_strptr(g.e, g.shstrndx, shdr.sh_name)) == NULL)
	  errx(EXIT_FAILURE , " elf_strptr()  failed : %s.",
	       elf_errmsg (-1));
	

	scn_hdr_t* scn_hdr_p = (scn_hdr_t*)malloc(sizeof(scn_hdr_t));
	if (scn_hdr_p == NULL) {
		errx (EXIT_FAILURE , "scn_hdr_t malloc failed");
		return NULL;
	}

	scn_hdr_p->sh_idx = idx;
	scn_hdr_p->name = name;
	scn_hdr_p->sh_addr = shdr.sh_addr;
	scn_hdr_p->sh_size = n;
	scn_hdr_p->data = buf;

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

  CoreSymbolInfoBuilder builder;

  for (unsigned i = 0; i < count; i++) {
    GElf_Sym sym;
    if (gelf_getsym(data, i, &sym) == NULL) {
      continue;
    }
    if (sym.st_shndx == SHN_ABS)
      continue;
    if (sym.st_value < low || sym.st_value >= high)
      continue;
    builder.addSymbol(elf_strptr(e, shdr.sh_link, sym.st_name),
                      sym.st_value,
                      sym.st_info);
  }
  SI = builder.getSymbolInfo();
}
Ejemplo n.º 24
0
Archivo: elves.c Proyecto: 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;
}
Ejemplo n.º 25
0
static void
check_section (Dwarf *result, GElf_Ehdr *ehdr, Elf_Scn *scn, bool inscngrp)
{
  GElf_Shdr shdr_mem;
  GElf_Shdr *shdr;

  /* Get the section header data.  */
  shdr = gelf_getshdr (scn, &shdr_mem);
  if (shdr == NULL)
    /* This should never happen.  If it does something is
       wrong in the libelf library.  */
    abort ();


  /* Make sure the section is part of a section group only iff we
     really need it.  If we are looking for the global (= non-section
     group debug info) we have to ignore all the info in section
     groups.  If we are looking into a section group we cannot look at
     a section which isn't part of the section group.  */
  if (! inscngrp && (shdr->sh_flags & SHF_GROUP) != 0)
    /* Ignore the section.  */
    return;


  /* We recognize the DWARF section by their names.  This is not very
     safe and stable but the best we can do.  */
  const char *scnname = elf_strptr (result->elf, ehdr->e_shstrndx,
				    shdr->sh_name);
  if (scnname == NULL)
    {
      /* The section name must be valid.  Otherwise is the ELF file
	 invalid.  */
      __libdw_seterrno (DWARF_E_INVALID_ELF);
      free (result);
      return;
    }


  /* Recognize the various sections.  Most names start with .debug_.  */
  size_t cnt;
  for (cnt = 0; cnt < ndwarf_scnnames; ++cnt)
    if (strcmp (scnname, dwarf_scnnames[cnt]) == 0)
      {
	/* Found it.  Remember where the data is.  */
	if (unlikely (result->sectiondata[cnt] != NULL))
	  /* A section appears twice.  That's bad.  We ignore the section.  */
	  break;

	/* Get the section data.  */
	Elf_Data *data = elf_getdata (scn, NULL);
	if (data != NULL && data->d_size != 0)
	  /* Yep, there is actually data available.  */
	  result->sectiondata[cnt] = data;

	break;
      }
}
Ejemplo n.º 26
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;
}
Ejemplo n.º 27
0
static void update_dyn_cache(ElfCreator *ctor)
{
	ctor->dynscn = get_scn_by_type(ctor, SHT_DYNAMIC);
	if (ctor->dynscn == NULL)
		return;

	ctor->dynshdr = gelf_getshdr(ctor->dynscn, &ctor->dynshdr_mem);
	ctor->dyndata = elf_getdata(ctor->dynscn, NULL);
}
Ejemplo n.º 28
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.º 29
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;
}
Ejemplo n.º 30
0
static void
set_flag(char *ifile, ulong_t flval)
{
	Elf *elf;
	Elf_Scn *scn;
	Elf_Data *data;
	GElf_Shdr shdr;
	GElf_Dyn dyn;
	int fd, secidx, nent, i;

	(void) elf_version(EV_CURRENT);

	if ((fd = open(ifile, O_RDWR)) < 0)
		die("Can't open %s", ifile);

	if ((elf = elf_begin(fd, ELF_C_RDWR, NULL)) == NULL)
		elfdie("Can't start ELF for %s", ifile);

	if ((secidx = findelfsecidx(elf, ".dynamic")) == -1)
		die("Can't find .dynamic section in %s\n", ifile);

	if ((scn = elf_getscn(elf, secidx)) == NULL)
		elfdie("elf_getscn (%d)", secidx);

	if (gelf_getshdr(scn, &shdr) == NULL)
		elfdie("gelf_shdr");

	if ((data = elf_getdata(scn, NULL)) == NULL)
		elfdie("elf_getdata");

	nent = shdr.sh_size / shdr.sh_entsize;
	for (i = 0; i < nent; i++) {
		if (gelf_getdyn(data, i, &dyn) == NULL)
			elfdie("gelf_getdyn");

		if (dyn.d_tag == DT_FLAGS_1) {
			dyn.d_un.d_val |= (Elf64_Xword)flval;

			if (gelf_update_dyn(data, i, &dyn) == 0)
				elfdie("gelf_update_dyn");

			break;
		}
	}

	if (i == nent) {
		die("%s's .dynamic section doesn't have a DT_FLAGS_1 "
		    "field\n", ifile);
	}

	if (elf_update(elf, ELF_C_WRITE) == -1)
		elfdie("Couldn't update %s with changes", ifile);

	(void) elf_end(elf);
	(void) close(fd);
}