Exemple #1
0
main(int argc, char **argv)
{
    int fd;
    Elf *elf;
    Elf32_Ehdr *ehdr;
    Elf_Scn *scn;
    Elf_Data *data;
    Elf32_Half ndx;
    Elf32_Shdr *shdr;
    unsigned int *textdata;

    if (argc != 2)
	exit(2);

    assert(!nlist(argv[1], nl));
    assert(nl[0].n_value && !(nl[0].n_value & 0x3));
    assert(nl[1].n_value && !(nl[1].n_value & 0x3));
    assert(nl[2].n_value && !(nl[2].n_value & 0x3));

    if (elf_version(EV_CURRENT) == EV_NONE) {
	fprintf(stderr, "ELF punted! Recompile %s\n", argv[0]);
	exit(1);
    }

    fd = open(argv[1], O_RDWR);
    if (fd < 0) {
	perror("open");
	exit(1);
    }

    elf = elf_begin(fd, ELF_C_RDWR, NULL);

    ehdr = elf32_getehdr(elf);
    assert(ehdr);
    /* want SHT_PROGBITS section named .text */
    ndx = ehdr->e_shstrndx;
    scn = NULL;
    while ((scn = elf_nextscn(elf, scn))) {
	char *name = NULL;

	if ((shdr = elf32_getshdr(scn)))
	    name = elf_strptr(elf, ndx, (size_t) shdr->sh_name);
	if (!strcmp(name, ".text"))
	    break;
    }

    data = elf_getdata(scn, NULL);
    assert(data && data->d_size && !data->d_off);
    textdata = (unsigned int *) data->d_buf;

    /* process */
    assert(textdata[nl[0].n_value / 4] == 0x000B000D);
    textdata[nl[0].n_value / 4] = type_ReturnPcHeader;

    assert(textdata[nl[1].n_value / 4] == 0x000A000D);
    assert(textdata[nl[1].n_value / 4 + 1] == 0x000B000D);
    assert(textdata[nl[1].n_value / 4 + 2] == 0x000B000D);
    textdata[nl[1].n_value / 4 + 1] = 0x0417FECC;
    textdata[nl[1].n_value / 4 + 2] = 0x01000000;

    assert(textdata[nl[2].n_value / 4] == 0x000B000D);
    textdata[nl[2].n_value / 4] = type_ReturnPcHeader;

    elf_flagdata(data, ELF_C_SET, ELF_F_DIRTY);
    elf_update(elf, ELF_C_WRITE);
    elf_end(elf);
}
Exemple #2
0
int
_elf_nlist(int fd, struct nlist * list)
{
	Elf	   *elfdes;	/* ELF descriptor */
	GElf_Ehdr  ehdr;	/* ELF Ehdr */
	GElf_Shdr  s_buf;	/* buffer storing section header */
	Elf_Data   *symdata;	/* buffer points to symbol table */
	Elf_Scn    *secidx = 0;	/* index of the section header table */
	GElf_Sym   sym;		/* buffer storing one symbol information */
	unsigned   strtab;	/* index of symbol name in string table */
	long	   count;	/* number of symbols */
	long	   ii;		/* loop control */

	if (elf_version(EV_CURRENT) == EV_NONE) {
		(void) close(fd);
		return (-1);
	}
	elfdes = elf_begin(fd, ELF_C_READ, (Elf *)0);
	if (gelf_getehdr(elfdes, &ehdr) == 0)
		return (end_elf_job(fd, elfdes));

	while ((secidx = elf_nextscn(elfdes, secidx)) != 0) {
		if ((gelf_getshdr(secidx, &s_buf)) == 0)
			return (end_elf_job(fd, elfdes));
		if (s_buf.sh_type != SHT_SYMTAB) /* not symbol table */
			continue;
		symdata = elf_getdata(secidx, (Elf_Data *)0);
		if (symdata == 0)
			return (end_elf_job(fd, elfdes));
		if (symdata->d_size == 0)
			break;
		strtab = s_buf.sh_link;
		count = symdata->d_size / s_buf.sh_entsize;
		for (ii = 1; ii < count; ++ii) {
			struct nlist *p;
			register char *name;
			/* LINTED */
			(void) gelf_getsym(symdata, (int)ii, &sym);
			name = elf_strptr(elfdes, strtab, (size_t)sym.st_name);
			if (name == 0)
				continue;
			for (p = list; p->n_name && p->n_name[0]; ++p) {
				if (strcmp(p->n_name, name))
					continue;
				p->n_value = (long)sym.st_value;
				p->n_type = GELF_ST_TYPE(sym.st_info);
				p->n_scnum = sym.st_shndx;
				break;
			}
		}
		break;
		/*
		 * Currently there is only one symbol table section
		 * in an object file, but this restriction may be
		 * relaxed in the future.
		 */
	}
	(void) elf_end(elfdes);
	(void) close(fd);
	return (0);
}
Exemple #3
0
/**
 * Compile an LLVM module to machine code.
 *
 * @returns 0 for success, 1 for failure
 */
unsigned radeon_llvm_compile(LLVMModuleRef M, struct radeon_llvm_binary *binary,
					  const char * gpu_family, unsigned dump) {

	LLVMTargetRef target;
	LLVMTargetMachineRef tm;
	char cpu[CPU_STRING_LEN];
	char fs[FS_STRING_LEN];
	char *err;
	LLVMMemoryBufferRef out_buffer;
	unsigned buffer_size;
	const char *buffer_data;
	char triple[TRIPLE_STRING_LEN];
	char *elf_buffer;
	Elf *elf;
	Elf_Scn *section = NULL;
	size_t section_str_index;
	LLVMBool r;

	init_r600_target();

	target = get_r600_target();
	if (!target) {
		return 1;
	}

	strncpy(cpu, gpu_family, CPU_STRING_LEN);
	memset(fs, 0, sizeof(fs));
	if (dump) {
		LLVMDumpModule(M);
		strncpy(fs, "+DumpCode", FS_STRING_LEN);
	}
	strncpy(triple, "r600--", TRIPLE_STRING_LEN);
	tm = LLVMCreateTargetMachine(target, triple, cpu, fs,
				  LLVMCodeGenLevelDefault, LLVMRelocDefault,
						  LLVMCodeModelDefault);

	r = LLVMTargetMachineEmitToMemoryBuffer(tm, M, LLVMObjectFile, &err,
								 &out_buffer);
	if (r) {
		fprintf(stderr, "%s", err);
		FREE(err);
		return 1;
	}

	buffer_size = LLVMGetBufferSize(out_buffer);
	buffer_data = LLVMGetBufferStart(out_buffer);

	/* 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(buffer_size);
	memcpy(elf_buffer, buffer_data, buffer_size);

	elf = elf_memory(elf_buffer, buffer_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 1;
		}
		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 (dump && !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);
		}
	}

	LLVMDisposeMemoryBuffer(out_buffer);
	LLVMDisposeTargetMachine(tm);
	return 0;
}
Exemple #4
0
static int
pkg_get_myabi(char *dest, size_t sz)
{
	Elf *elf;
	Elf_Data *data;
	Elf_Note note;
	Elf_Scn *scn;
	char *src, *osname;
	const char *abi;
	GElf_Ehdr elfhdr;
	GElf_Shdr shdr;
	int fd, i, ret;
	uint32_t version;

	version = 0;
	ret = -1;
	scn = NULL;
	abi = NULL;

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

	if ((fd = open("/bin/sh", O_RDONLY)) < 0) {
		warn("open()");
		return (-1);
	}

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

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

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

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

	if (scn == NULL) {
		ret = -1;
		warn("failed to get the note section");
		goto cleanup;
	}

	data = elf_getdata(scn, NULL);
	src = data->d_buf;
	for (;;) {
		memcpy(&note, src, sizeof(Elf_Note));
		src += sizeof(Elf_Note);
		if (note.n_type == NT_VERSION)
			break;
		src += note.n_namesz + note.n_descsz;
	}
	osname = src;
	src += note.n_namesz;
	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]);

	snprintf(dest, sz, "%s:%d:%s:%s",
	    osname, version / 100000,
	    elf_corres_to_string(mach_corres, (int)elfhdr.e_machine),
	    elf_corres_to_string(wordsize_corres,
	    (int)elfhdr.e_ident[EI_CLASS]));

	ret = 0;

	switch (elfhdr.e_machine) {
	case EM_ARM:
		snprintf(dest + strlen(dest), sz - strlen(dest),
		    ":%s:%s:%s", elf_corres_to_string(endian_corres,
		    (int)elfhdr.e_ident[EI_DATA]),
		    (elfhdr.e_flags & EF_ARM_NEW_ABI) > 0 ?
		    "eabi" : "oabi",
		    (elfhdr.e_flags & EF_ARM_VFP_FLOAT) > 0 ?
		    "softfp" : "vfp");
		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";
			break;
		}
		snprintf(dest + strlen(dest), sz - strlen(dest),
		    ":%s:%s", elf_corres_to_string(endian_corres,
		    (int)elfhdr.e_ident[EI_DATA]), abi);
		break;
	}

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

	close(fd);
	return (ret);
}
Exemple #5
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 *abi, *endian_corres_str, *wordsize_corres_str;

	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("fail to get the note section");
		goto cleanup;
	}

	data = elf_getdata(scn, NULL);
	src = data->d_buf;
	while (1) {
		memcpy(&note, src, sizeof(Elf_Note));
		src += sizeof(Elf_Note);
		if (note.n_type == NT_VERSION)
			break;
		src += note.n_namesz + note.n_descsz;
	}
	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]);

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

	switch (elfhdr.e_machine) {
	case EM_ARM:
		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",
		    endian_corres_str,
		    (elfhdr.e_flags & EF_ARM_NEW_ABI) > 0 ? "eabi" : "oabi",
		    (elfhdr.e_flags & EF_ARM_VFP_FLOAT) > 0 ? "softfp" : "vfp");
		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",
		    endian_corres_str, abi);
		break;
	default:
		break;
	}

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

	close(fd);
	return (ret);
}
Exemple #6
0
/*
 * scan the ELF image to build table of global symbold and the image
 * regions where they can be found (BSS and DATA)
 */
static inline int
table_init_helper (void)
{
    Elf *e = NULL;
    GElf_Ehdr ehdr;
    char *shstr_name = NULL;
    size_t shstrndx;
    Elf_Scn *scn = NULL;
    GElf_Shdr shdr;
    int ret = -1;
#if 0
    int (*getsi) ();            /* look up name of elf_get... routine */
#endif

    /* unrecognized format */
    if (elf_version (EV_CURRENT) == EV_NONE) {
        goto bail;
    }

    /* get the ELF object from already opened state */
    e = elf_begin (GET_STATE (exe_fd), ELF_C_READ, NULL);
    if (e == NULL) {
        goto bail;
    }

    /* do some sanity checks */
    if (elf_kind (e) != ELF_K_ELF) {
        goto bail;
    }
    if (gelf_getehdr (e, &ehdr) == NULL) {
        goto bail;
    }
    if (gelf_getclass (e) == ELFCLASSNONE) {
        goto bail;
    }

    /*
     * There are various elf_get* routines with different return values
     * in differnt libraries/versions - name of routine does not tell us
     * all we ned to know.  So let it go here, and we'll mop up any
     * problems later on.
     */

    /*
     * This routine is either "elf_getshdrstrndx" in newer ELF
     * libraries, or "elf_getshstrndx" in older ones.  Hard-code older
     * one for now since it is in the newer libraries, although marked as
     * deprecated.  This will be detected by autoconf later
     *
     * DEPRECATED
     */
    (void) elf_getshstrndx (e, &shstrndx);

    /* walk sections, look for RO/BSS/DATA and symbol table */
    scn = NULL;

    while ((scn = elf_nextscn (e, scn)) != NULL) {

        if (gelf_getshdr (scn, &shdr) != &shdr) {
            goto bail;
        }
        shstr_name = elf_strptr (e, shstrndx, shdr.sh_name);
        if (shstr_name == NULL) {
            goto bail;
        }

        /* found the read-only data */
        if (shdr.sh_type == SHT_PROGBITS && strcmp (shstr_name, ".rodata") == 0) {

            elfro.start = shdr.sh_addr;
            elfro.end = elfro.start + shdr.sh_size;

            shmemi_trace (SHMEM_LOG_SYMBOLS,
                          "ELF section .rodata for global variables = 0x%lX -> 0x%lX",
                          elfro.start, elfro.end);
            continue;           /* move to next scan */
        }

        /* found the uninitialized globals */
        if (shdr.sh_type == SHT_NOBITS && strcmp (shstr_name, ".bss") == 0) {

            elfbss.start = shdr.sh_addr;
            elfbss.end = elfbss.start + shdr.sh_size;

            shmemi_trace (SHMEM_LOG_SYMBOLS,
                          "ELF section .bss for global variables = 0x%lX -> 0x%lX",
                          elfbss.start, elfbss.end);
            continue;           /* move to next scan */
        }

        /* found the initialized globals */
        if (shdr.sh_type == SHT_PROGBITS && strcmp (shstr_name, ".data") == 0) {

            elfdata.start = shdr.sh_addr;
            elfdata.end = elfdata.start + shdr.sh_size;

            shmemi_trace (SHMEM_LOG_SYMBOLS,
                          "ELF section .data for global variables = 0x%lX -> 0x%lX",
                          elfdata.start, elfdata.end);
            continue;           /* move to next scan */
        }

        /* keep looking until we find the symbol table */
        if (shdr.sh_type == SHT_SYMTAB) {
            Elf_Data *data = NULL;
            while ((data = elf_getdata (scn, data)) != NULL) {
                GElf_Sym *es;
                GElf_Sym *last_es;

                es = (GElf_Sym *) data->d_buf;
                if (es == NULL) {
                    continue;
                }

                /* find out how many entries to look for */
                last_es = (GElf_Sym *) ((char *) data->d_buf + data->d_size);

                for (; es < last_es; es += 1) {
                    char *name;

                    /*
                     * need visible global or local (Fortran save) object with
                     * some kind of content
                     */
                    if (es->st_value == 0 || es->st_size == 0) {
                        continue;
                    }
                    /*
                     * this macro handles a symbol that is present
                     * in one libelf implementation but isn't in another
                     * (elfutils vs. libelf)
                     */
#ifndef GELF_ST_VISIBILITY
#define GELF_ST_VISIBILITY(o) ELF64_ST_VISIBILITY(o)
#endif
                    if (GELF_ST_TYPE (es->st_info) != STT_OBJECT &&
                        GELF_ST_VISIBILITY (es->st_info) != STV_DEFAULT) {
                        continue;
                    }
                    name = elf_strptr (e, shdr.sh_link, (size_t) es->st_name);
                    if (name == NULL || *name == '\0') {
                        continue;
                    }
                    /* put the symbol and info into the symbol hash table */
                    {
                        globalvar_t *gv = (globalvar_t *) malloc (sizeof (*gv));
                        if (gv == NULL) {
                            goto bail;
                        }
                        gv->name = strdup (name);
                        if (gv->name == NULL) {
                            free (gv);
                            goto bail;
                        }
                        gv->addr = (void *) es->st_value;
                        gv->size = es->st_size;
                        HASH_ADD_PTR (gvp, addr, gv);
                    }
                }
            }
            /*
             * pulled out all the global symbols => success,
             * don't need to scan further
             */
            ret = 0;
            break;
        }
    }

  bail:

    if (elf_end (e) != 0) {
        ret = -1;
    }

    return ret;
}
Exemple #7
0
static int
pkg_get_myabi(char *dest, size_t sz)
{
	Elf *elf;
	Elf_Data *data;
	Elf_Note note;
	Elf_Scn *scn;
	char *src, *osname;
	const char *arch, *abi, *fpu, *endian_corres_str;
	const char *wordsize_corres_str;
	GElf_Ehdr elfhdr;
	GElf_Shdr shdr;
	int fd, i, ret;
	uint32_t version;

	version = 0;
	ret = -1;
	scn = NULL;
	abi = NULL;

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

	if ((fd = open(_PATH_BSHELL, O_RDONLY)) < 0) {
		warn("open()");
		return (-1);
	}

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

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

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

	if (scn == NULL) {
		ret = -1;
		warn("failed to get the note section");
		goto cleanup;
	}

	data = elf_getdata(scn, NULL);
	src = data->d_buf;
	for (;;) {
		memcpy(&note, src, sizeof(Elf_Note));
		src += sizeof(Elf_Note);
		if (note.n_type == NT_VERSION)
			break;
		src += note.n_namesz + note.n_descsz;
	}
	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);

	snprintf(dest, sz, "%s:%d",
	    osname, version / 100000);

	ret = 0;

	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 = 1;
						warn("unknown ARM ARCH");
						goto cleanup;
					}
				}
			} else {
				ret = 1;
				warn("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 {
			ret = 1;
			warn("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";
			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);
	}

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

	close(fd);
	return (ret);
}
Exemple #8
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;
}
Exemple #9
0
static int
analyse_elf(struct pkgdb *db, struct pkg *pkg, const char *fpath)
{
	struct pkg_dep *dep = NULL;
	struct pkg *p = NULL;
	struct pkgdb_it *it = NULL;
	Elf *e;
	Elf_Scn *scn = NULL;
	GElf_Shdr shdr;
	Elf_Data *data;
	GElf_Dyn *dyn, dyn_mem;
	size_t numdyn;
	size_t dynidx;
	void *handle;
	Link_map *map;
	char *name;
	bool found=false;

	int fd;

	if ((fd = open(fpath, O_RDONLY, 0)) < 0)
		return (EPKG_FATAL);

	if (( e = elf_begin(fd, ELF_C_READ, NULL)) == NULL)
		return (EPKG_FATAL);

	if (elf_kind(e) != ELF_K_ELF)
		return (EPKG_FATAL);

	while (( scn = elf_nextscn(e, scn)) != NULL) {
		if (gelf_getshdr(scn, &shdr) != &shdr)
			return (EPKG_FATAL);

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

	if  (scn == NULL)
		return (EPKG_OK);

	data = elf_getdata(scn, NULL);
	numdyn = shdr.sh_size / shdr.sh_entsize;

	for (dynidx = 0; dynidx < numdyn; dynidx++) {
		if ((dyn = gelf_getdyn(data, dynidx, &dyn_mem)) == NULL)
			return (EPKG_FATAL);

		if (dyn->d_tag != DT_NEEDED)
			continue;

		name = elf_strptr(e, shdr.sh_link, dyn->d_un.d_val);
		handle = dlopen(name, RTLD_LAZY);

		if (handle != NULL) {
			dlinfo(handle, RTLD_DI_LINKMAP, &map);
			if ((it = pkgdb_query_which(db, map->l_name)) == NULL)
				return (EPKG_FATAL);

			if (pkgdb_it_next(it, &p, PKG_LOAD_BASIC) == EPKG_OK) {
				found = false;
				while (pkg_deps(pkg, &dep) == EPKG_OK) {
					if (strcmp(pkg_dep_origin(dep), pkg_get(p, PKG_ORIGIN)) == 0)
						found = true;
				}
				if (!found) {
					pkg_emit_error("adding forgotten depends (%s): %s-%s",
								   map->l_name, pkg_get(p, PKG_NAME),
								   pkg_get(p, PKG_VERSION));
					pkg_adddep(pkg, pkg_get(p, PKG_NAME), pkg_get(p, PKG_ORIGIN), pkg_get(p, PKG_VERSION));
				}
			}
			dlclose(handle);
		}
		pkgdb_it_free(it);
	}
	pkg_free(p);
	close(fd);

	return (EPKG_OK);

}
static uint32_t* ExtractIsaBinaryFromElfBinary(uint64_t    isaOffset,
                                               const void* pBinary,
                                               size_t      binarySize)
{
    if (nullptr == pBinary || 0 == binarySize)
    {
        return nullptr;
    }

    // get isa binary from .hsatext section with a relative byte offset (isaOffset)

    // Determine the ELF type:
    bool isELF = false;
    bool isELF32 = false;
    bool isELF64 = false;

    // The ELF executable header is 16 bytes:
    if (16 < binarySize)
    {
        // Check for the ELF header start:
        const unsigned char* pBinaryAsUBytes = (const unsigned char*)pBinary;
        isELF = ((0x7f == pBinaryAsUBytes[0]) &&
                 ('E'  == pBinaryAsUBytes[1]) &&
                 ('L'  == pBinaryAsUBytes[2]) &&
                 ('F'  == pBinaryAsUBytes[3]));
        isELF32 = isELF && (0x01 == pBinaryAsUBytes[4]);
        isELF64 = isELF && (0x02 == pBinaryAsUBytes[4]);
    }

    // Validate:
    if (!isELF)
    {
        return nullptr;
    }

    if (!isELF32 && !isELF64)
    {
        assert(!"Unsupported ELF sub-format!");
        return nullptr;
    }

    // Set the version of elf:
    elf_version(EV_CURRENT);

    // Initialize the binary as ELF from memory:
    Elf* pContainerElf = elf_memory((char*)pBinary, binarySize);

    if (nullptr == pContainerElf)
    {
        return nullptr;
    }

    // First get the .hsatext section:
    static const std::string isaSectionName = ".hsatext";

    // Get the shared strings section:
    size_t sectionHeaderStringSectionIndex = 0;
    int rcShrstr = elf_getshdrstrndx(pContainerElf, &sectionHeaderStringSectionIndex);

    if ((0 != rcShrstr) || (0 == sectionHeaderStringSectionIndex))
    {
        return nullptr;
    }

    // Iterate the sections to find the isa section
    Elf_Scn* pCurrentSection = elf_nextscn(pContainerElf, nullptr);

    while (nullptr != pCurrentSection)
    {
        size_t strOffset = 0;

        if (isELF32)
        {
            // Get the section header:
            Elf32_Shdr* pCurrentSectionHeader = elf32_getshdr(pCurrentSection);

            if (nullptr != pCurrentSectionHeader)
            {
                // Get the name and link:
                strOffset = pCurrentSectionHeader->sh_name;
            }
        }
        else if (isELF64)
        {
            // Get the section header:
            Elf64_Shdr* pCurrentSectionHeader = elf64_getshdr(pCurrentSection);

            if (nullptr != pCurrentSectionHeader)
            {
                // Get the name and link:
                strOffset = pCurrentSectionHeader->sh_name;
            }
        }

        // Get the current section's name:
        char* pCurrentSectionName = elf_strptr(pContainerElf, sectionHeaderStringSectionIndex, strOffset);

        if (nullptr != pCurrentSectionName)
        {
            if (isaSectionName == pCurrentSectionName)
            {
                // Get the section's data:
                Elf_Data* pSectionData = elf_getdata(pCurrentSection, nullptr);

                if (nullptr != pSectionData)
                {
                    // Found the section, no need to continue:
                    // the isa binary is prefixed with an amd_kernel_code_t structure
                    uint64_t buffer = reinterpret_cast<uint64_t>(pSectionData->d_buf) + isaOffset + sizeof(amd_kernel_code_t);
                    return reinterpret_cast<uint32_t*>(buffer);
                }
            }
        }

        // Get the next section:
        pCurrentSection = elf_nextscn(pContainerElf, pCurrentSection);
    }

    return nullptr;
}
static int
cache_sections (Dwfl_Module *mod)
{
  if (likely (mod->reloc_info != NULL))
    return mod->reloc_info->count;

  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;
}
Exemple #12
0
unsigned int ElfSymbolResolver::createElfSymbolResolver(ElfSymbolResolver **resolver, const char *filename) {
	int			elf_fd;
	Elf 			*elf_handle;
	Elf_Scn			*elf_scn 	= NULL;
	GElf_Shdr		elf_shdr;
	Elf_Data		*elf_data	= NULL;
	GElf_Sym 		elf_symbol;
	ElfSymbolResolver 	*instance;
	int			symbol_count	= 0;
	int			i 		= 0;
	
	if (elf_version(EV_CURRENT) == EV_NONE) {
		return 1; // failed to initialize libelf
	}

	elf_fd = open(filename, O_RDONLY);
	if (elf_fd == -1) {
		return 2; // failed to open file
	}

	elf_handle = elf_begin(elf_fd, ELF_C_READ, NULL);
	if (elf_handle == 0) {
		close(elf_fd);
		return 3; // failed to elf_begin
	}

	instance = new ElfSymbolResolver();
	if (instance == 0) {
		elf_end(elf_handle);
		close(elf_fd);
		return 4; // failed to allocate instance
	}

	while ((elf_scn = elf_nextscn(elf_handle, elf_scn)) != NULL) {
		if (gelf_getshdr(elf_scn, &elf_shdr) != &elf_shdr) {
			delete instance;
			elf_end(elf_handle);
			close(elf_fd);
			return 5; // gelf_getshdr failed
		}

		if (elf_shdr.sh_type == SHT_SYMTAB) {
			elf_data = elf_getdata(elf_scn, elf_data);
			if (elf_data != NULL) {
				symbol_count = elf_shdr.sh_size / elf_shdr.sh_entsize;

				for (i = 0; i < symbol_count; i++) {
					if (gelf_getsym(elf_data, i, &elf_symbol) == 0) {
						delete instance;
						elf_end(elf_handle);
						close(elf_fd);
						return 6; // gelf_getsym failed
					}

					if (ELF32_ST_BIND(elf_symbol.st_info) == STB_GLOBAL && elf_symbol.st_size > 0) {
						if (ELF32_ST_TYPE(elf_symbol.st_info) == STT_OBJECT) {
							const char *variable_name = elf_strptr(elf_handle, elf_shdr.sh_link, elf_symbol.st_name);
							if (variable_name != 0) {
								printf("variable: %s (%lu)\n", variable_name, (unsigned long int) elf_symbol.st_size);
							}

							ElfVariableSymbol* v = new ElfVariableSymbol(variable_name, (void *) elf_symbol.st_value, (size_t) elf_symbol.st_size);
							instance->addVariable(v);
						} else if (ELF32_ST_TYPE(elf_symbol.st_info) == STT_FUNC) {
							const char *function_name = elf_strptr(elf_handle, elf_shdr.sh_link, elf_symbol.st_name);
							if (function_name != 0) {
								printf("function: %s (%#x - %#x)\n", function_name, (unsigned int) elf_symbol.st_value, (unsigned int) elf_symbol.st_size);
							}

							ElfFunctionSymbol* f = new ElfFunctionSymbol(function_name, (void *) elf_symbol.st_value, (size_t) elf_symbol.st_size);
							instance->addFunction(f);
						}
					}
				}
			}
		}
	}

	if (resolver != 0) {
		*resolver = instance;
	} else {
		delete instance;
	}

	elf_end(elf_handle);
	close(elf_fd);

	return 0;
}
Exemple #13
0
int
main (int argc, char *argv[])
{
  if (argc < 3)
    error (EXIT_FAILURE, 0, "usage: %s FROMNAME TONAME", argv[0]);

  elf_version (EV_CURRENT);

  int infd = open (argv[1], O_RDONLY);
  if (infd == -1)
    error (EXIT_FAILURE, errno, "cannot open input file '%s'", argv[1]);

  Elf *inelf = elf_begin (infd, ELF_C_READ, NULL);
  if (inelf == NULL)
    error (EXIT_FAILURE, 0, "problems opening '%s' as ELF file: %s",
	   argv[1], elf_errmsg (-1));

  int outfd = creat (argv[2], 0666);
  if (outfd == -1)
    error (EXIT_FAILURE, errno, "cannot open output file '%s'", argv[2]);

  Elf *outelf = elf_begin (outfd, ELF_C_WRITE, NULL);
  if (outelf == NULL)
    error (EXIT_FAILURE, 0, "problems opening '%s' as ELF file: %s",
	   argv[2], elf_errmsg (-1));

  gelf_newehdr (outelf, gelf_getclass (inelf));

  GElf_Ehdr ehdr_mem;
  GElf_Ehdr *ehdr;
  gelf_update_ehdr (outelf, (ehdr = gelf_getehdr (inelf, &ehdr_mem)));

  if (ehdr->e_phnum > 0)
    {
      int cnt;

      if (gelf_newphdr (outelf, ehdr->e_phnum) == 0)
	error (EXIT_FAILURE, 0, "cannot create program header: %s",
	       elf_errmsg (-1));

      for (cnt = 0; cnt < ehdr->e_phnum; ++cnt)
	{
	  GElf_Phdr phdr_mem;

	  gelf_update_phdr (outelf, cnt, gelf_getphdr (inelf, cnt, &phdr_mem));
	}
    }

  Elf_Scn *scn = NULL;
  while ((scn = elf_nextscn (inelf, scn)) != NULL)
    {
      Elf_Scn *newscn = elf_newscn (outelf);

      GElf_Shdr shdr_mem;
      gelf_update_shdr (newscn, gelf_getshdr (scn, &shdr_mem));

      *elf_newdata (newscn) = *elf_getdata (scn, NULL);
    }

  elf_flagelf (outelf, ELF_C_SET, ELF_F_LAYOUT);

  if (elf_update (outelf, ELF_C_WRITE) == -1)
    error (EXIT_FAILURE, 0, "elf_update failed: %s", elf_errmsg (-1));

  close (outfd);

  return 0;
}
/* Search an ELF file for a ".gnu_debuglink" section.  */
static const char *
find_debuglink (Elf *elf, GElf_Word *crc)
{
  size_t shstrndx;
  if (elf_getshdrstrndx (elf, &shstrndx) < 0)
    return NULL;

  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)
	return NULL;

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

      if (!strcmp (name, ".gnu_debuglink"))
	break;
    }

  if (scn == NULL)
    return NULL;

  /* Found the .gnu_debuglink section.  Extract its contents.  */
  Elf_Data *rawdata = elf_rawdata (scn, NULL);
  if (rawdata == NULL)
    return NULL;

  Elf_Data crcdata =
    {
      .d_type = ELF_T_WORD,
      .d_buf = crc,
      .d_size = sizeof *crc,
      .d_version = EV_CURRENT,
    };
  Elf_Data conv =
    {
      .d_type = ELF_T_WORD,
      .d_buf = rawdata->d_buf + rawdata->d_size - sizeof *crc,
      .d_size = sizeof *crc,
      .d_version = EV_CURRENT,
    };

  GElf_Ehdr ehdr_mem;
  GElf_Ehdr *ehdr = gelf_getehdr (elf, &ehdr_mem);
  if (ehdr == NULL)
    return NULL;

  Elf_Data *d = gelf_xlatetom (elf, &crcdata, &conv, ehdr->e_ident[EI_DATA]);
  if (d == NULL)
    return NULL;
  assert (d == &crcdata);

  return rawdata->d_buf;
}


/* 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 = find_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);
  return open_elf (mod, &mod->debug);
}


/* Try to find a symbol table in FILE.
   Returns DWFL_E_NOERROR if a proper one is found.
   Returns DWFL_E_NO_SYMTAB if not, but still sets results for SHT_DYNSYM.  */
static Dwfl_Error
load_symtab (struct dwfl_file *file, struct dwfl_file **symfile,
	     Elf_Scn **symscn, Elf_Scn **xndxscn,
	     size_t *syments, GElf_Word *strshndx)
{
  bool symtab = false;
  Elf_Scn *scn = NULL;
  while ((scn = elf_nextscn (file->elf, scn)) != NULL)
    {
      GElf_Shdr shdr_mem, *shdr = gelf_getshdr (scn, &shdr_mem);
      if (shdr != NULL)
	switch (shdr->sh_type)
	  {
	  case SHT_SYMTAB:
	    symtab = true;
	    *symscn = scn;
	    *symfile = file;
	    *strshndx = shdr->sh_link;
	    *syments = shdr->sh_size / shdr->sh_entsize;
	    if (*xndxscn != NULL)
	      return DWFL_E_NOERROR;
	    break;

	  case SHT_DYNSYM:
	    if (symtab)
	      break;
	    /* Use this if need be, but keep looking for SHT_SYMTAB.  */
	    *symscn = scn;
	    *symfile = file;
	    *strshndx = shdr->sh_link;
	    *syments = shdr->sh_size / shdr->sh_entsize;
	    break;

	  case SHT_SYMTAB_SHNDX:
	    *xndxscn = scn;
	    if (symtab)
	      return DWFL_E_NOERROR;
	    break;

	  default:
	    break;
	  }
    }

  if (symtab)
    /* We found one, though no SHT_SYMTAB_SHNDX to go with it.  */
    return DWFL_E_NOERROR;

  /* We found no SHT_SYMTAB, so any SHT_SYMTAB_SHNDX was bogus.
     We might have found an SHT_DYNSYM and set *SYMSCN et al though.  */
  *xndxscn = NULL;
  return DWFL_E_NO_SYMTAB;
}


/* Translate addresses into file offsets.
   OFFS[*] start out zero and remain zero if unresolved.  */
static void
find_offsets (Elf *elf, const GElf_Ehdr *ehdr, size_t n,
	      GElf_Addr addrs[n], GElf_Off offs[n])
{
  size_t unsolved = n;
  for (uint_fast16_t i = 0; i < ehdr->e_phnum; ++i)
    {
      GElf_Phdr phdr_mem;
      GElf_Phdr *phdr = gelf_getphdr (elf, i, &phdr_mem);
      if (phdr != NULL && phdr->p_type == PT_LOAD && phdr->p_memsz > 0)
	for (size_t j = 0; j < n; ++j)
	  if (offs[j] == 0
	      && addrs[j] >= phdr->p_vaddr
	      && addrs[j] - phdr->p_vaddr < phdr->p_filesz)
	    {
	      offs[j] = addrs[j] - phdr->p_vaddr + phdr->p_offset;
	      if (--unsolved == 0)
		break;
	    }
    }
}
Exemple #15
0
/* Method to test if a file is non stripped binary. Uses libelf*/
bool rm_util_is_nonstripped(_U const char *path, _U RmStat *statp) {
    bool is_ns = false;

#if HAVE_LIBELF
    g_return_val_if_fail(path, false);

    if(statp && (statp->st_mode & (S_IXUSR | S_IXGRP | S_IXOTH)) == 0) {
        return false;
    }

    /* inspired by "jschmier"'s answer at http://stackoverflow.com/a/5159890 */
    int fd;

    /* ELF handle */
    Elf *elf;

    /* section descriptor pointer */
    Elf_Scn *scn;

    /* section header */
    GElf_Shdr shdr;

    /* Open ELF file to obtain file descriptor */
    if((fd = rm_sys_open(path, O_RDONLY)) == -1) {
        rm_log_warning_line(_("cannot open file '%s' for nonstripped test: "), path);
        rm_log_perror("");
        return 0;
    }

    /* Protect program from using an older library */
    if(elf_version(EV_CURRENT) == EV_NONE) {
        rm_log_error_line(_("ELF Library is out of date!"));
        return false;
    }

    /* Initialize elf pointer for examining contents of file */
    elf = elf_begin(fd, ELF_C_READ, NULL);

    /* Initialize section descriptor pointer so that elf_nextscn()
     * returns a pointer to the section descriptor at index 1.
     * */
    scn = NULL;

    /* Iterate through ELF sections */
    while((scn = elf_nextscn(elf, scn)) != NULL) {
        /* Retrieve section header */
        gelf_getshdr(scn, &shdr);

        /* If a section header holding a symbol table (.symtab)
         * is found, this ELF file has not been stripped. */
        if(shdr.sh_type == SHT_SYMTAB) {
            is_ns = true;
            break;
        }
    }
    elf_end(elf);
    rm_sys_close(fd);
#endif

    return is_ns;
}
int get_VTables(char* file, vtable_info*** vtables)
{
    int fd;
    struct stat elf_stats;
    
    int symbol_count;
    int num;
    int i;
    char *sname, *ssname;
    vtable_info* vt;
    
    Elf *elf = NULL;
    Elf_Scn *scn = NULL;
    GElf_Shdr shdr;
    Elf_Data *edata = NULL;
    GElf_Sym sym;
    
    if ((fd = open(file, O_RDONLY))==-1)
    {
        printf("Failed to open %s\n", file);
        return ERR;
    }
    
    if ((fstat(fd, &elf_stats)))
    {
        printf("Failed to fstat %s\n", file);
        close(fd);
        return ERR;
    }
    
    if (elf_version(EV_CURRENT) == EV_NONE)
    {
        printf("WARNING Elf Library is out of date!\n");
    }
    
    elf = elf_begin(fd, ELF_C_READ, NULL);
    
    while ((scn = elf_nextscn(elf, scn)) != NULL)
    {
        gelf_getshdr(scn, &shdr);
        
        if (shdr.sh_type == SHT_DYNSYM)
        {
            edata = elf_getdata(scn, edata);
            
            symbol_count = shdr.sh_size / shdr.sh_entsize;
            *vtables = (vtable_info**)malloc(sizeof(vtable_info*) * symbol_count);
            
            num = 0;
            for (i = 0; i < symbol_count; i++)
            {
                gelf_getsym(edata, i, &sym);
                
                if (sym.st_value==0)
                { // UND
                    continue;
                }
                
                sname = elf_strptr(elf, shdr.sh_link, sym.st_name);
                ssname = (char*)malloc(1 + strlen(sname));
                strcpy(ssname, sname);
                
                if (strstr(ssname, "_ZTV"))
                {
                    vt = (vtable_info*)malloc(sizeof(vtable_info));
                    vt->name = ssname;
                    vt->size = sym.st_size;
                    
                    (*vtables)[num] = vt;
                    num += 1;
                }
                else
                {
                    free(ssname);
                }
            }
            (*vtables)[num] = NULL;
        }
    }
    
    if (*vtables == NULL)
    {
        return ERR;
    }
    
    elf_end(elf);
    close(fd);
    
    return 0;
}
Exemple #17
0
static void
fetch_symtab(Elf *elf, char *filename, mod_info_t *module)
{
	Elf_Scn		*scn = NULL, *sym = NULL;
	GElf_Word	strndx = 0;
	size_t		i, nsyms, nfuncs;
	Elf_Data	*symdata;
	nltype		*nl, *npe;

	while ((scn = elf_nextscn(elf, scn)) != NULL) {

		GElf_Shdr shdr;

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

		if (shdr.sh_type == SHT_SYMTAB ||
					shdr.sh_type == SHT_DYNSYM) {
			GElf_Xword chk = shdr.sh_size / shdr.sh_entsize;

			nsyms = (size_t)(shdr.sh_size / shdr.sh_entsize);

			if (chk != (GElf_Xword) nsyms) {
				(void) fprintf(stderr, "%s: can't handle"
					"more than 2^32 symbols", cmdname);
				exit(ERR_INPUT);
			}

			strndx = shdr.sh_link;
			sym = scn;
		}

		/*
		 * If we've found a real symbol table, we're done.
		 */
		if (shdr.sh_type == SHT_SYMTAB)
			break;
	}

	if (sym == NULL || strndx == 0) {
		(void) fprintf(stderr, "%s: missing symbol table in %s\n",
						    cmdname, filename);
		exit(ERR_ELF);
	}

	if ((symdata = elf_getdata(scn, NULL)) == NULL) {
		(void) fprintf(stderr, "%s: can't read symbol data from %s\n",
						    cmdname, filename);
		exit(ERR_ELF);
	}

	if ((npe = nl = (nltype *) calloc(nsyms, sizeof (nltype))) == NULL) {
		(void) fprintf(stderr, "%s: can't alloc %x bytes for symbols\n",
					cmdname, nsyms * sizeof (nltype));
		exit(ERR_ELF);
	}

	/*
	 * Now we need to cruise through the symbol table eliminating
	 * all non-functions from consideration, and making strings
	 * real.
	 */
	nfuncs = 0;

	for (i = 1; i < nsyms; i++) {
		GElf_Sym	gsym;
		char		*name;

		(void) gelf_getsym(symdata, i, &gsym);

		name = elf_strptr(elf, strndx, gsym.st_name);

		/*
		 * We're interested in this symbol if it's a function
		 */
		if (is_function(elf, &gsym)) {

			npe->name = name;
			npe->value = gsym.st_value;
			npe->size = gsym.st_size;
			npe->info = gsym.st_info;

			npe++;
			nfuncs++;
		}

		if (strcmp(name, PRF_END) == 0)
			module->data_end = gsym.st_value;
	}

	if (npe == nl) {
		(void) fprintf(stderr, "%s: no valid functions in %s\n",
						    cmdname, filename);
		exit(ERR_INPUT);
	}

	/*
	 * And finally, sort the symbols by increasing address
	 * and remove the duplicates.
	 */
	qsort(nl, nfuncs, sizeof (nltype), cmp_by_address);
	rm_dups(nl, &nfuncs);

	module->nl = nl;
	module->nfuncs = nfuncs;
}
Exemple #18
0
/*
 * Translate symbol table data particularly for sorting.
 * Input is the symbol table data structure, number of symbols,
 * opened ELF file, and the string table link offset.
 */
static SYM *
readsyms(Elf_Data * data, GElf_Sxword num, Elf *elf,
	unsigned int link, unsigned int symscnndx)
{
	SYM		*s, *buf;
	GElf_Sym	sym;
	Elf32_Word	*symshndx = 0;
	unsigned int	nosymshndx = 0;
	int		i;

	if ((buf = calloc(num, sizeof (SYM))) == NULL) {
		(void) fprintf(stderr, gettext("%s: cannot allocate memory\n"),
		    prog_name);
		return (NULL);
	}

	s = buf;	/* save pointer to head of array */

	for (i = 1; i < num; i++, buf++) {
		(void) gelf_getsym(data, i, &sym);

		buf->indx = i;
		/* allow to work on machines where NULL-derefs dump core */
		if (sym.st_name == 0)
			buf->name = "";
		else if (C_flag) {
			const char *dn;
			char *name = (char *)elf_strptr(elf, link, sym.st_name);
			dn = conv_demangle_name(name);
			if (strcmp(dn, name) == 0) {	/* Not demangled */
				if (exotic(name)) {
					name = FormatName(name, d_buf);
				}
			} else {  /* name demangled */
				name = FormatName(name, dn);
			}
			buf->name = name;
		}
		else
			buf->name = (char *)elf_strptr(elf, link, sym.st_name);

		buf->value	= sym.st_value;
		buf->size	= sym.st_size;
		buf->type	= GELF_ST_TYPE(sym.st_info);
		buf->bind	= GELF_ST_BIND(sym.st_info);
		buf->other	= sym.st_other;
		if ((sym.st_shndx == SHN_XINDEX) &&
		    (symshndx == 0) && (nosymshndx == 0)) {
			Elf_Scn		*_scn;
			GElf_Shdr	_shdr;
			_scn = 0;
			while ((_scn = elf_nextscn(elf, _scn)) != 0) {
				if (gelf_getshdr(_scn, &_shdr) == 0)
					break;
				if ((_shdr.sh_type == SHT_SYMTAB_SHNDX) &&
				    (_shdr.sh_link == symscnndx)) {
					Elf_Data	*_data;
					if ((_data = elf_getdata(_scn,
					    0)) != 0) {
						symshndx =
						    (Elf32_Word *)_data->d_buf;
						break;
					}
				}
			}
			nosymshndx = 1;
		}
		if ((symshndx) && (sym.st_shndx == SHN_XINDEX)) {
			buf->shndx = symshndx[i];
		} else {
			buf->shndx	= sym.st_shndx;
			if (sym.st_shndx >= SHN_LORESERVE)
				buf->flags |= FLG_SYM_SPECSEC;
		}
	}	/* end for loop */
	return (s);
}
Exemple #19
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;
}
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;
}
Exemple #21
0
static void
dtrace_dof_init(void)
{
#if defined(sun)
	dof_hdr_t *dof = &__SUNW_dof;
#else
	dof_hdr_t *dof = NULL;
#endif
#ifdef _LP64
	Elf64_Ehdr *elf;
#else
	Elf32_Ehdr *elf;
#endif
	dof_helper_t dh;
	Link_map *lmp;
#if defined(sun)
	Lmid_t lmid;
#else
	u_long lmid = 0;
#endif
	int fd;
	const char *p;
#if !defined(sun)
	Elf *e;
	Elf_Scn *scn = NULL;
	Elf_Data *symtabdata = NULL, *dynsymdata = NULL, *dofdata = NULL;
	dof_hdr_t *dof_next = NULL;
	GElf_Shdr shdr;
	int efd;
	char *s;
	size_t shstridx, symtabidx = 0, dynsymidx = 0;
#endif

	if (getenv("DTRACE_DOF_INIT_DISABLE") != NULL)
		return;

	if (getenv("DTRACE_DOF_INIT_DEBUG") != NULL)
		dof_init_debug = B_TRUE;

	if (dlinfo(RTLD_SELF, RTLD_DI_LINKMAP, &lmp) == -1 || lmp == NULL) {
		dprintf(1, "couldn't discover module name or address\n");
		return;
	}

#if defined(sun)
	if (dlinfo(RTLD_SELF, RTLD_DI_LMID, &lmid) == -1) {
		dprintf(1, "couldn't discover link map ID\n");
		return;
	}
#endif

	if ((modname = strrchr(lmp->l_name, '/')) == NULL)
		modname = lmp->l_name;
	else
		modname++;
#if !defined(sun)
	elf_version(EV_CURRENT);
	if ((efd = open(lmp->l_name, O_RDONLY, 0)) < 0) {
		dprintf(1, "couldn't open file for reading\n");
		return;
	}
	if ((e = elf_begin(efd, ELF_C_READ, NULL)) == NULL) {
		dprintf(1, "elf_begin failed\n");
		close(efd);
		return;
	}
	elf_getshdrstrndx(e, &shstridx);
	dof = NULL;
	while ((scn = elf_nextscn(e, scn)) != NULL) {
		gelf_getshdr(scn, &shdr);
		if (shdr.sh_type == SHT_SYMTAB) {
			symtabidx = shdr.sh_link;
			symtabdata = elf_getdata(scn, NULL);
		} else if (shdr.sh_type == SHT_DYNSYM) {
			dynsymidx = shdr.sh_link;
			dynsymdata = elf_getdata(scn, NULL);
		} else if (shdr.sh_type == SHT_SUNW_dof) {
			s = elf_strptr(e, shstridx, shdr.sh_name);
			if  (s != NULL && strcmp(s, ".SUNW_dof") == 0) {
				dofdata = elf_getdata(scn, NULL);
				dof = dofdata->d_buf;
			}
		}
	}
	if (dof == NULL) {
		dprintf(1, "SUNW_dof section not found\n");
		elf_end(e);
		close(efd);
		return;
	}

	while ((char *) dof < (char *) dofdata->d_buf + dofdata->d_size) {
		dof_next = (void *) ((char *) dof + dof->dofh_filesz);
#endif

	if (dof->dofh_ident[DOF_ID_MAG0] != DOF_MAG_MAG0 ||
	    dof->dofh_ident[DOF_ID_MAG1] != DOF_MAG_MAG1 ||
	    dof->dofh_ident[DOF_ID_MAG2] != DOF_MAG_MAG2 ||
	    dof->dofh_ident[DOF_ID_MAG3] != DOF_MAG_MAG3) {
		dprintf(0, ".SUNW_dof section corrupt\n");
		return;
	}

	elf = (void *)lmp->l_addr;

	dh.dofhp_dof = (uintptr_t)dof;
	dh.dofhp_addr = elf->e_type == ET_DYN ? (uintptr_t) lmp->l_addr : 0;

	if (lmid == 0) {
		(void) snprintf(dh.dofhp_mod, sizeof (dh.dofhp_mod),
		    "%s", modname);
	} else {
		(void) snprintf(dh.dofhp_mod, sizeof (dh.dofhp_mod),
		    "LM%lu`%s", lmid, modname);
	}

	if ((p = getenv("DTRACE_DOF_INIT_DEVNAME")) != NULL)
		devnamep = p;

	if ((fd = open64(devnamep, O_RDWR)) < 0) {
		dprintf(1, "failed to open helper device %s", devnamep);
#if defined(sun)
		/*
		 * If the device path wasn't explicitly set, try again with
		 * the old device path.
		 */
		if (p != NULL)
			return;

		devnamep = olddevname;

		if ((fd = open64(devnamep, O_RDWR)) < 0) {
			dprintf(1, "failed to open helper device %s", devnamep);
			return;
		}
#else
		return;
#endif
	}
	if ((gen = ioctl(fd, DTRACEHIOC_ADDDOF, &dh)) == -1)
		dprintf(1, "DTrace ioctl failed for DOF at %p", dof);
	else {
		dprintf(1, "DTrace ioctl succeeded for DOF at %p\n", dof);
#if !defined(sun)
		gen = dh.gen;
#endif
	}

	(void) close(fd);

#if !defined(sun)
		/* End of while loop */
		dof = dof_next;
	}

	elf_end(e);
	(void) close(efd);
#endif
}
Exemple #22
0
int
symtab_init(void)
{
	Elf		*elf;
	Elf_Scn		*scn = NULL;
	Sym		*symtab, *symp, *lastsym;
	char		*strtab;
	uint_t		cnt;
	int		fd;
	int		i;
	int		strindex = -1;

	if ((fd = open("/dev/ksyms", O_RDONLY)) == -1)
		return (-1);

	(void) elf_version(EV_CURRENT);

	elf = elf_begin(fd, ELF_C_READ, NULL);

	for (cnt = 1; (scn = elf_nextscn(elf, scn)) != NULL; cnt++) {
		Shdr *shdr = elf_getshdr(scn);
		if (shdr->sh_type == SHT_SYMTAB) {
			symtab = (Sym *)elf_getdata(scn, NULL)->d_buf;
			nsyms = shdr->sh_size / shdr->sh_entsize;
			strindex = shdr->sh_link;
		}
	}

	for (cnt = 1; (scn = elf_nextscn(elf, scn)) != NULL; cnt++) {
		if (cnt == strindex)
			strtab = (char *)elf_getdata(scn, NULL)->d_buf;
	}

	lastsym = symtab + nsyms;
	nsyms = 0;
	for (symp = symtab; symp < lastsym; symp++)
		if ((uint_t)ELF32_ST_TYPE(symp->st_info) <= STT_FUNC &&
		    symp->st_size != 0)
			add_symbol(symp->st_name + strtab,
			    (uintptr_t)symp->st_value, (size_t)symp->st_size);

	fake_up_certain_popular_kernel_symbols();
	(void) sprintf(maxsymname, "0x%lx", ULONG_MAX);
	add_symbol(maxsymname, ULONG_MAX, 1);

	qsort(symbol_table, nsyms, sizeof (syment_t), symcmp);

	/*
	 * Destroy all duplicate symbols, then sort it again.
	 */
	for (i = 0; i < nsyms - 1; i++)
		if (symbol_table[i].addr == symbol_table[i + 1].addr)
			symbol_table[i].addr = 0;

	qsort(symbol_table, nsyms, sizeof (syment_t), symcmp);

	while (symbol_table[1].addr == 0) {
		symbol_table++;
		nsyms--;
	}
	symbol_table[0].name = "(usermode)";
	symbol_table[0].addr = 0;
	symbol_table[0].size = 1;

	return (0);
}
Exemple #23
0
static int
analyse_elf(struct pkg *pkg, const char *fpath,
	int (action)(void *, struct pkg *, const char *, const char *, bool),
	void *actdata)
{
	Elf *e = NULL;
	GElf_Ehdr elfhdr;
	Elf_Scn *scn = NULL;
	Elf_Scn *note = NULL;
	Elf_Scn *dynamic = NULL;
	GElf_Shdr shdr;
	Elf_Data *data;
	GElf_Dyn *dyn, dyn_mem;
	struct stat sb;
	int ret = EPKG_OK;

	size_t numdyn = 0;
	size_t sh_link = 0;
	size_t dynidx;
	const char *osname;
	const char *shlib;

	bool shlibs = false;
	bool autodeps = false;
	bool developer = false;
	bool is_shlib = false;

	pkg_config_bool(PKG_CONFIG_AUTODEPS, &autodeps);
	pkg_config_bool(PKG_CONFIG_SHLIBS, &shlibs);
	pkg_config_bool(PKG_CONFIG_DEVELOPER_MODE, &developer);

	int fd;

	if (lstat(fpath, &sb) != 0)
		pkg_emit_errno("fstat() failed for %s", fpath);
	/* ignore empty files and non regular files */
	if (sb.st_size == 0 || !S_ISREG(sb.st_mode))
		return (EPKG_END); /* Empty file or sym-link: no results */

	if ((fd = open(fpath, O_RDONLY, 0)) < 0) {
		return (EPKG_FATAL);
	}

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

	if (elf_kind(e) != ELF_K_ELF) {
		close(fd);
		return (EPKG_END); /* Not an elf file: no results */
	}

	if (developer)
		pkg->flags |= PKG_CONTAINS_ELF_OBJECTS;

	if (!autodeps && !shlibs) {
	   ret = EPKG_OK;
	   goto cleanup;
	}

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

	while ((scn = elf_nextscn(e, scn)) != NULL) {
		if (gelf_getshdr(scn, &shdr) != &shdr) {
			ret = EPKG_FATAL;
			pkg_emit_error("getshdr() for %s failed: %s", fpath,
			    elf_errmsg(-1));
			goto cleanup;
		}
		switch (shdr.sh_type) {
		case SHT_NOTE:
			note = scn;
			break;
		case SHT_DYNAMIC:
			dynamic = scn;
			sh_link = shdr.sh_link;
			numdyn = shdr.sh_size / shdr.sh_entsize;
			break;
		}

		if (note != NULL && dynamic != NULL)
			break;
	}

	/*
	 * note == NULL usually means a shared object for use with dlopen(3)
	 * dynamic == NULL means not a dynamically linked elf
	 */
	if (dynamic == NULL) {
		ret = EPKG_END;
		goto cleanup; /* not a dynamically linked elf: no results */
	}

	if (note != NULL) {
		data = elf_getdata(note, NULL);
		osname = (const char *) data->d_buf + sizeof(Elf_Note);
		if (strncasecmp(osname, "freebsd", sizeof("freebsd")) != 0 &&
		    strncasecmp(osname, "dragonfly", sizeof("dragonfly")) != 0) {
			ret = EPKG_END;	/* Foreign (probably linux) ELF object */
			goto cleanup;
		}
	} else {
		if (elfhdr.e_ident[EI_OSABI] != ELFOSABI_FREEBSD) {
			ret = EPKG_END;
			goto cleanup;
		}
	}

	data = elf_getdata(dynamic, NULL);

	/* First, scan through the data from the .dynamic section to
	   find any RPATH or RUNPATH settings.  These are colon
	   separated paths to prepend to the ld.so search paths from
	   the ELF hints file.  These always seem to come right after
	   the NEEDED shared library entries.

	   NEEDED entries should resolve to a filename for installed
	   executables, but need not resolve for installed shared
	   libraries -- additional info from the apps that link
	   against them would be required.  Shared libraries are
	   distinguished by a DT_SONAME tag */

	rpath_list_init();
	for (dynidx = 0; dynidx < numdyn; dynidx++) {
		if ((dyn = gelf_getdyn(data, dynidx, &dyn_mem)) == NULL) {
			ret = EPKG_FATAL;
			pkg_emit_error("getdyn() failed for %s: %s", fpath,
			    elf_errmsg(-1));
			goto cleanup;
		}

		if (dyn->d_tag == DT_SONAME) {
			is_shlib = true;

			/* The file being scanned is a shared library
			   *provided* by the package. Record this if
			   appropriate */

			if (shlibs)
				pkg_addshlib_provided(pkg, basename(fpath));
		}

		if (dyn->d_tag != DT_RPATH && dyn->d_tag != DT_RUNPATH)
			continue;
		
		shlib_list_from_rpath(elf_strptr(e, sh_link, dyn->d_un.d_val), 
				      dirname(fpath));
		break;
	}

	/* Now find all of the NEEDED shared libraries. */

	for (dynidx = 0; dynidx < numdyn; dynidx++) {
		if ((dyn = gelf_getdyn(data, dynidx, &dyn_mem)) == NULL) {
			ret = EPKG_FATAL;
			pkg_emit_error("getdyn() failed for %s: %s", fpath,
			    elf_errmsg(-1));
			goto cleanup;
		}

		if (dyn->d_tag != DT_NEEDED)
			continue;

		shlib = elf_strptr(e, sh_link, dyn->d_un.d_val);

		/* When running in DEVELOPER_MODE check that shlib
		   names conform to the correct pattern.  Only issue a
		   warning on mismatch -- shlibs may belong to a
		   different package. */

		if (developer)
			warn_about_name_format(pkg, fpath, shlib);

		action(actdata, pkg, fpath, shlib, is_shlib);
	}

cleanup:
	rpath_list_free();

	if (e != NULL)
		elf_end(e);
	close(fd);

	return (ret);
}
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;
}
Exemple #25
0
void leaky::readSymbols(const char *fileName)
{
    int fd = ::open(fileName, O_RDONLY);
    if (fd < 0) {
	fprintf(stderr, "%s: unable to open \"%s\"\n", applicationName,
		fileName);
	exit(-1);
    }

    elf_version(EV_CURRENT);
    Elf *elf = elf_begin(fd, ELF_C_READ, 0);
    if (!elf) {
	fprintf(stderr, "%s: \"%s\": has no symbol table\n", applicationName,
		fileName);
	exit(-1);
    }

    long alloced = 10000;
    Symbol* syms = (Symbol*) malloc(sizeof(Symbol) * 10000);
    Symbol* sp = syms;
    Symbol* last = syms + alloced;

    // Get each of the relevant sections and add them to the list of
    // symbols.
    Elf32_Ehdr *ehdr = elf32_getehdr(elf);
    if (!ehdr) {
	fprintf(stderr, "%s: elf library lossage\n", applicationName);
	exit(-1);
    }
#if 0
    Elf32_Half ndx = ehdr->e_shstrndx;
#endif

    Elf_Scn *scn = 0;
    int strtabndx = -1;
    for (int i = 1; (scn = elf_nextscn(elf, scn)) != 0; i++) {
	Elf32_Shdr *shdr = elf32_getshdr(scn);
#if 0
	char *name = elf_strptr(elf, ndx, (size_t) shdr->sh_name);
	printf("Section %s (%d 0x%x)\n", name ? name : "(null)",
	       shdr->sh_type, shdr->sh_type);
#endif
	if (shdr->sh_type == SHT_STRTAB) {
	    /* We assume here that string tables preceed symbol tables... */
	    strtabndx = i;
	    continue;
	}
#if 0
	if (shdr->sh_type == SHT_DYNAMIC) {
	    /* Dynamic */
	    Elf_Data *data = elf_getdata(scn, 0);
	    if (!data || !data->d_size) {
		printf("No data...");
		continue;
	    }

	    Elf32_Dyn *dyn = (Elf32_Dyn*) data->d_buf;
	    Elf32_Dyn *lastdyn =
		(Elf32_Dyn*) ((char*) data->d_buf + data->d_size);
	    for (; dyn < lastdyn; dyn++) {
		printf("tag=%d value=0x%x\n", dyn->d_tag, dyn->d_un.d_val);
	    }
	} else
#endif
	if ((shdr->sh_type == SHT_SYMTAB) ||
	    (shdr->sh_type == SHT_DYNSYM)) {
	    /* Symbol table */
	    Elf_Data *data = elf_getdata(scn, 0);
	    if (!data || !data->d_size) {
		printf("No data...");
		continue;
	    }

	    /* In theory we now have the symbols... */
	    Elf32_Sym *esym = (Elf32_Sym*) data->d_buf;
	    Elf32_Sym *lastsym =
		(Elf32_Sym*) ((char*) data->d_buf + data->d_size);
	    for (; esym < lastsym; esym++) {
#if 0
		char *nm = elf_strptr(elf, strtabndx, (size_t)esym->st_name);
		printf("%20s 0x%08x %02x %02x\n",
		       nm, esym->st_value, ELF32_ST_BIND(esym->st_info),
		       ELF32_ST_TYPE(esym->st_info));
#endif
		if ((esym->st_value == 0) ||
		    (ELF32_ST_BIND(esym->st_info) == STB_WEAK) ||
		    (ELF32_ST_BIND(esym->st_info) == STB_NUM) ||
		    (ELF32_ST_TYPE(esym->st_info) != STT_FUNC)) {
		    continue;
		}
#if 1
		char *nm = elf_strptr(elf, strtabndx, (size_t)esym->st_name);
#endif
		sp->name = nm ? strdup(nm) : "(no name)";
		sp->address = esym->st_value;
		sp++;
		if (sp >= last) {
		    long n = alloced + 10000;
		    syms = (Symbol*)
			realloc(syms, (size_t) (sizeof(Symbol) * n));
		    last = syms + n;
		    sp = syms + alloced;
		    alloced = n;
		}
	    }
	}
    }

    int interesting = sp - syms;
    if (!quiet) {
	printf("Total of %d symbols\n", interesting);
    }
    usefulSymbols = interesting;
    externalSymbols = syms;
}
Exemple #26
0
/**
 * Loads all the lua scripts present in the program file
 * @param scripts in output, contains an allocated array, containing all the
 * scripts loaded, ending with a {NULL, NULL} script. The array must be freed
 * with free_scripts() after usage.
 * @return total number of scripts loaded
 */
static int load_scripts(struct lua_script **scripts)
{
	unsigned ev;
	int fd;
	Elf *e;
	Elf_Kind ek;
	size_t shstrndx;
	Elf_Scn *scn;
	GElf_Shdr shdr;
	const char *name;
	uint32_t nb_scripts = 0;
	struct lua_script *script;

	ev = elf_version(EV_CURRENT);
	if (ev == EV_NONE)
		exit(103);

	fd = open(SELF_EXE, O_RDONLY, 0);
	if (fd < 0)
		exit(104);

	e = elf_begin(fd, ELF_C_READ, NULL);
	if (e == NULL)
		exit(105);

	ek = elf_kind(e);
	if (ek != ELF_K_ELF)
		exit(106);

	if (elf_getshdrstrndx(e, &shstrndx) != 0)
		exit(107);

	*scripts = NULL;
	for (scn = elf_nextscn(e, NULL);
			scn != NULL;
			scn = elf_nextscn(e, scn)) {
		if (gelf_getshdr(scn, &shdr) != &shdr)
			exit(108);

		name = elf_strptr(e, shstrndx, shdr.sh_name);
		if (name == NULL)
			exit(109);
		if (strncmp(name, LUA_WRAPPER_SECTION_PREFIX,
				strlen(LUA_WRAPPER_SECTION_PREFIX)) == 0) {
			/* store the section */
			if (debug)
				printf("store section %s\n", name);
			nb_scripts++;
			*scripts = realloc(*scripts,
					(nb_scripts + 1) *
					sizeof(struct lua_script));
			if (*scripts == NULL)
				exit(110);
			script = *scripts + (nb_scripts - 1);

			load_script(script, scn, &shdr, name);
		}
	}

	elf_end(e);
	close(fd);

	/* NULL guard */
	if (nb_scripts != 0)
		(*scripts)[nb_scripts].code = (*scripts)[nb_scripts].name =
				NULL;

	return nb_scripts;
}
Exemple #27
0
int
xlate_named_init_elf(Elf * elf, const char *section_name,
	xlate_table_con * ret_tab_ptr)
{
   int retstatus  = XLATE_TB_STATUS_NO_ERROR;
   xlate_table_con newtab = 0;
   Elf_Scn *scn = 0;
   int is64bit = 0;
   char *ident;
   size_t identsize;
   Elf_Scn *xlscn = 0;
   Elf64_Shdr *shdr64 = 0;
   Elf32_Shdr *shdr32 = 0;
   Elf32_Ehdr *ehdr32 = 0;
   Elf64_Ehdr *ehdr64 = 0;
   Elf_Data   *xlatedata = 0;
   int stringindex = 0;
   char * sec_name;

   if(elf_kind(elf) != ELF_K_ELF) {
	return XLATE_TB_STATUS_NOT_ELF;
   }
   ident = elf_getident(elf,&identsize);

   if(ident == 0 || identsize < EI_NIDENT) {
     return  XLATE_TB_STATUS_ELF_IDENT_BAD;
   }
   if(ident[EI_CLASS] ==  ELFCLASS64) {
	is64bit = 1;
   }
   if(is64bit) {
	ehdr64 = elf64_getehdr(elf);
	if(ehdr64 == 0 ) {
	  return XLATE_TB_STATUS_ELF_EHDR_BAD;
	}
	stringindex = ehdr64->e_shstrndx;
   } else {
	ehdr32 = elf32_getehdr(elf);
	if(ehdr32 == 0 ) {
	  return XLATE_TB_STATUS_ELF_EHDR_BAD;
	}
	stringindex = ehdr32->e_shstrndx;
   }

   for(scn = elf_nextscn(elf,scn);  
	scn != 0 && xlscn == 0
		; scn = elf_nextscn(elf,scn)) {
	if(is64bit) {
	  shdr64 = elf64_getshdr(scn);
	  if(shdr64 == 0) {
	    return XLATE_TB_STATUS_ELF_SHDR_BAD;
	  }
	  sec_name = elf_strptr(elf,stringindex,shdr64->sh_name);
	  if(sec_name == 0) {
	    return XLATE_TB_STATUS_ELF_STRPTR_BAD;
	  }
	  if(shdr64->sh_type    != SHT_MIPS_XLATE &&
		shdr64->sh_type != SHT_MIPS_XLATE_DEBUG &&
		shdr64->sh_type != SHT_MIPS_XLATE_OLD ) {
		continue;
	  }
	  if(!streq(section_name,sec_name)) {
		continue;
	  }
	  xlscn = scn;
	  break;
	} else {
	  shdr32 = elf32_getshdr(scn);
	  if(shdr32 == 0) {
	    return XLATE_TB_STATUS_ELF_SHDR_BAD;
	  }
	  sec_name = elf_strptr(elf,stringindex,shdr32->sh_name);
	  if(sec_name == 0) {
	    return XLATE_TB_STATUS_ELF_STRPTR_BAD;
	  }
	  if(shdr32->sh_type    != SHT_MIPS_XLATE  &&
		shdr32->sh_type != SHT_MIPS_XLATE_DEBUG &&
		shdr32->sh_type != SHT_MIPS_XLATE_OLD ) {
		continue;
	  }
	  if(!streq(section_name,sec_name)) {
		continue;
	  }
	  xlscn = scn;
	  break;
	}
   }
   if(xlscn == 0) {
	return XLATE_TB_STATUS_NO_XLATE;
   }

   xlatedata = elf_getdata(xlscn,NULL);
   if(xlatedata == NULL || xlatedata->d_size == 0) {
	return XLATE_TB_STATUS_NO_XLATE_DATA;
   }
   
   newtab = (xlate_table_con)malloc(sizeof(struct xlate_table_con_s));
   if(newtab == NULL) {
	return XLATE_TB_STATUS_ALLOC_FAIL;
   }
   bzero(newtab,sizeof(struct xlate_table_con_s));


   newtab->xc_elf = elf;


   newtab->xc_section_data = xlatedata->d_buf;
   newtab->xc_data_size = xlatedata->d_size;
   if(newtab->xc_data_size != xlatedata->d_size) {
	/* we have a gigantic section and are compiled only 32 bit.
	** we simply cannot handle and I don't think the
        ** mmap would have worked anyway so we cannot really
	** get here.
	*/
     free(newtab);
     return XLATE_TB_STATUS_SECTION_TOO_BIG;
   }

   retstatus = _xlate_fill_in_table_data(newtab,is64bit);
   if(retstatus != XLATE_TB_STATUS_NO_ERROR) {
     free(newtab);
     return retstatus;
   }

   newtab->xc_valid_table         = VALID_TABLE_MAGIC;
   *ret_tab_ptr = newtab;
   return retstatus;
}
Exemple #28
0
unsigned int *NWMouse_findcookie(char *filename)
{
	Elf			*elf_ptr; 
	int			fd; 
	Elf32_Ehdr		*ehdr; 
	Elf_Scn			*section; 
	Elf32_Shdr		*section_header;
	Elf32_Shdr		*code_header;
	unsigned char		*buffer, *entry; 
	unsigned char		*buffer_ptr; 
	unsigned char		*cookie_address; 
	struct		stat	statbuf; 

	static	unsigned int	calls[7]; 			/* Return things in this array */
	unsigned int		*ptr_calls; 
	int			instruction_size;
	struct 		instr 	instruction;

	int			i, j; 
	unsigned int		*table_ptr;
	int			done; 

	/* Dynamic Linking, we only use this stuff if we need it */

	void			*dlhandle; 

	dlhandle = dlopen("nwmouse/libdis/libdisasm.so", RTLD_NOW); 
	if( !dlhandle ) { 
		fprintf(stderr, "ERROR: NWMouse: (cookie) dlopen of libdisasm.so failed: %s\n", dlerror()); 
		abort(); 
	}

	NWMouse_disassemble_init_ptr = (int (*)())dlsym(dlhandle, "disassemble_init"); 
	if( NWMouse_disassemble_init_ptr == NULL ) { 
		fprintf(stderr, "ERROR: NWMouse: (cookie) dlsym(disassemble_init) failed: %s\n", dlerror()); 
		abort(); 
	}
	NWMouse_disassemble_address_ptr = (int (*)())dlsym(dlhandle, "disassemble_address"); 
	if( NWMouse_disassemble_address_ptr == NULL ) { 
		fprintf(stderr, "ERROR: NWMouse: (cookie) dlsym(disassemble_address) failed: %s\n", dlerror()); 
		abort(); 
	}
	NWMouse_disassemble_cleanup_ptr = (int (*)())dlsym(dlhandle, "disassemble_cleanup"); 
	if( NWMouse_disassemble_cleanup_ptr == NULL ) { 
		fprintf(stderr, "ERROR: NWMouse: (cookie) dlsym(disassemble_cleanup) failed: %s\n", dlerror()); 
		abort(); 
	}
	NWMouse_disassemble_init_ptr(0, INTEL_SYNTAX); 
		
/* Initialize the elves. */

	if (elf_version(EV_CURRENT) == EV_NONE) {
		fprintf(stderr, "ERROR: NWMouse: (cookie) libelf version mismatch.\n"); 
		abort(); 
	}

/* open library */ 	

	fd = open(filename, O_RDONLY); 
	if( fd < 0 ) { 
		fprintf(stderr, "ERROR: NWMouse: (cookie) Unable to open shared library: %s (%d)\n", filename, errno); 
		abort(); 
	}
	if( fstat(fd, &statbuf) < 0 ) { 
		fprintf(stderr, "ERROR: NWMouse: (cookie) Unable to stat shared library: %s (%d) Howd that happen?\n", filename, errno); 
		abort(); 
	}
	buffer = mmap(0, statbuf.st_size, PROT_READ, MAP_SHARED, fd, 0);
	if( buffer == NULL ) { 
		fprintf(stderr, "ERROR: NWMouse: (cookie) Unable to mmap executable: %s (%d)\n", filename, errno); 
		abort(); 
	}
	elf_ptr = elf_begin(fd, ELF_C_READ, (Elf *)0);
	if( elf_ptr == NULL) { 
		fprintf(stderr, "ERROR: NWMouse: (cookie) elf_begin failed: %s.\n", elf_errmsg(elf_errno())); 
		abort(); 
	} 

	/* Get the Header */
	if ( (ehdr = elf32_getehdr(elf_ptr)) == NULL) { 
		fprintf(stderr, "ERROR: NWMouse: (cookie) Unable to get Elf header: %s\n",  elf_errmsg(elf_errno()) ); 
		abort(); 
	}
	section = 0; 
	code_header = NULL; 
	while( (section = elf_nextscn( elf_ptr, section )) ) { 
		section_header = elf32_getshdr(section); 
		if( 	ehdr->e_entry >= section_header->sh_addr &&
			ehdr->e_entry < (section_header->sh_addr + section_header->sh_size)) {
				code_header = section_header; 
				break; 
		}
	}
	if( code_header == NULL ) { 
		fprintf(stderr, "ERROR: NWMouse: (cookie) Unable to locate appropriate code section.\n"); 
		abort(); 
	}

	/* Found start of program */
	entry = (unsigned char *)ehdr->e_entry - (code_header->sh_addr - code_header->sh_offset);
	fprintf(stderr, "NOTICE: NWMouse: (cookie) Entry point determined: %p\n", entry); 
	buffer_ptr = (unsigned char *) (int)entry + (int)buffer; 

	calls[0] = (NWMouse_search(buffer_ptr, (unsigned char *)ehdr->e_entry, code_header->sh_size, NWMouse_cookie0, 0, -1, 1))[0]; 
	fprintf(stderr, "NOTICE: NWMouse: (cookie) Cookie0 location: 0x%08x\n", (unsigned int)calls[0] + (unsigned int)code_header->sh_addr);

	ptr_calls = NWMouse_search(buffer_ptr, (unsigned char *)ehdr->e_entry, code_header->sh_size, NWMouse_cookie1, 0, 1, 1);

	calls[1] = ptr_calls[0]; 
	calls[2] = ptr_calls[1]; 

	instruction_size = NWMouse_disassemble_address_ptr((char *)buffer_ptr + calls[2], &instruction ); 
	if( ! instruction_size ) { 
		fprintf(stderr, "ERROR: NWMouse: (cookie) Curious: Invalid instruction disassembled: %08x\n", calls[2]); 
		fprintf(stderr, "ERROR: NWMouse: (cookie) This really shouldn't happen.\n"); 
		fprintf(stderr, "ERROR: NWMouse: (cookie)    Please contact David Holland ([email protected])\n"); 
		abort();
	}
	if( strcmp(instruction.mnemonic, "mov") || strtol( instruction.src, (char **)NULL, 16) < code_header->sh_addr ) { 
		fprintf(stderr, "ERROR: NWMouse: (cookie) Unexpected opcode found: %s %s\n", instruction.mnemonic, instruction.src); 
		fprintf(stderr, "ERROR: NWMouse: (cookie)    Please contact David Holland ([email protected])\n"); 
		abort();
	}
	calls[2] = strtol( instruction.src, (char **)NULL, 16);
	fprintf(stderr, "NOTICE: NWMouse: (cookie) Cookie1 location: 0x%08x\n", (unsigned int)calls[1] + (unsigned int)code_header->sh_addr);
	fprintf(stderr, "NOTICE: NWMouse: (cookie) Cookie2 location: 0x%08x\n", (unsigned int)calls[2]); 

	calls[3] = (NWMouse_search(buffer_ptr, (unsigned char *)ehdr->e_entry, code_header->sh_size, NWMouse_cookie2, 0, 1, 1))[0]; 
	fprintf(stderr, "NOTICE: NWMouse: (cookie) Cookie3 location: 0x%08x\n", (unsigned int)calls[3] + (unsigned int)code_header->sh_addr);

	calls[4] = (NWMouse_search(buffer_ptr, (unsigned char *)ehdr->e_entry, code_header->sh_size, NWMouse_cookie3, 0, 1, 1))[0]; 
	fprintf(stderr, "NOTICE: NWMouse: (cookie) Cookie4 location: 0x%08x\n", (unsigned int)calls[4] + (unsigned int)code_header->sh_addr);

	calls[5] = (NWMouse_search(buffer_ptr, (unsigned char *)ehdr->e_entry, code_header->sh_size, NWMouse_cookie4, 0, 1, 1))[1]; 
	fprintf(stderr, "NOTICE: NWMouse: (cookie) Cookie5 location: 0x%08x\n", (unsigned int)calls[5] + (unsigned int)code_header->sh_addr);

/* Calls "loaded".  Correct into virtual addresses */

	calls[0] = calls[0] + code_header->sh_addr; 		/* Function outside of end of table */
	calls[1] = calls[1] + code_header->sh_addr; 		/* Constructor */
	// calls[2] = calls[2] + code_header->sh_addr;  - Do not add to this one - Already corrected. /* Table Start */
	calls[3] = calls[3] + code_header->sh_addr; 		/* Render */
	calls[4] = calls[4] + code_header->sh_addr; 		/* Texture */
	calls[5] = calls[5] + code_header->sh_addr; 		/* Constructed object */

/* Find the Orientation function, ugh... */
	fprintf(stderr, "NOTICE: NWMouse: (cookie) Searching for proper Orientation function, this may take a while...\n"); 

/* Partially cloned from nwmouse.c */ 
	table_ptr = (void *)calls[2];
        i = 1; done = 0;
        while( table_ptr[i] != 0x0 && table_ptr[i] != calls[0] && !done ) {
		calls[6] = 
			(NWMouse_search(buffer_ptr, 			/* Secondary in memory copy 		*/
				(unsigned char *)ehdr->e_entry,		/* Kinda useless, unless _NOTDEF_ defd	*/
				table_ptr[i] - code_header->sh_addr + NWMouse_cookie5_size,	/* routine length. - hardcoded - blah 	*/
				NWMouse_cookie5, 			/* Search cookie			*/
				table_ptr[i] - code_header->sh_addr, 	/* start position 			*/
				1,					/* First occurance 			*/
				0					/* Abort if not found? 			*/
			))[0]; 
		if( calls[6] != 0 ) { 
			j = 0; 
			while( j < NWMouse_cookie5_size ) { 
				memset(&instruction, 0, sizeof(struct code));
				instruction_size = NWMouse_disassemble_address_ptr((char *)buffer_ptr + calls[6] + j, &instruction );
				if( !instruction_size ) { 

			fprintf(stderr, "ERROR: NWMouse: (cookie) Huh...: Invalid instruction disassembled: %08x\n", calls[2]); 
			fprintf(stderr, "ERROR: NWMouse: (cookie) This really shouldn't happen.\n"); 
			fprintf(stderr, "ERROR: NWMouse: (cookie)    Please contact David Holland ([email protected])\n"); 

					abort();

				}
				if( !strcmp(instruction.mnemonic, "mov") && 
					strtol( instruction.src, (char **)NULL, 16) == 0x4 &&
					!strcmp(instruction.dest, "ecx") ) { 
					done = 1; 
					j = NWMouse_cookie5_size; 
				}
				j += instruction_size; 
			}
		}
		i++; 
        }
	fprintf(stderr, "NOTICE: NWMouse: (cookie) Cookie6 location: 0x%08x\n", (unsigned int)calls[6] + (unsigned int)code_header->sh_addr);
	calls[6] = calls[6] + code_header->sh_addr; 		/* Set Orientation */

	elf_end(elf_ptr); 
	munmap(buffer, statbuf.st_size ); 
	close(fd); 
	dlclose(dlhandle); 
	return(calls); 
}
Exemple #29
0
__tgt_target_table *__tgt_rtl_load_binary(int32_t device_id,
                                          __tgt_device_image *image) {

  DP("Dev %d: load binary from " DPxMOD " image\n", device_id,
     DPxPTR(image->ImageStart));

  assert(device_id >= 0 && device_id < NUMBER_OF_DEVICES && "bad dev id");

  size_t ImageSize = (size_t)image->ImageEnd - (size_t)image->ImageStart;
  size_t NumEntries = (size_t)(image->EntriesEnd - image->EntriesBegin);
  DP("Expecting to have %zd entries defined.\n", NumEntries);

  // Is the library version incompatible with the header file?
  if (elf_version(EV_CURRENT) == EV_NONE) {
    DP("Incompatible ELF library!\n");
    return NULL;
  }

  // Obtain elf handler
  Elf *e = elf_memory((char *)image->ImageStart, ImageSize);
  if (!e) {
    DP("Unable to get ELF handle: %s!\n", elf_errmsg(-1));
    return NULL;
  }

  if (elf_kind(e) != ELF_K_ELF) {
    DP("Invalid Elf kind!\n");
    elf_end(e);
    return NULL;
  }

  // Find the entries section offset
  Elf_Scn *section = 0;
  Elf64_Off entries_offset = 0;

  size_t shstrndx;

  if (elf_getshdrstrndx(e, &shstrndx)) {
    DP("Unable to get ELF strings index!\n");
    elf_end(e);
    return NULL;
  }

  while ((section = elf_nextscn(e, section))) {
    GElf_Shdr hdr;
    gelf_getshdr(section, &hdr);

    if (!strcmp(elf_strptr(e, shstrndx, hdr.sh_name), OFFLOADSECTIONNAME)) {
      entries_offset = hdr.sh_addr;
      break;
    }
  }

  if (!entries_offset) {
    DP("Entries Section Offset Not Found\n");
    elf_end(e);
    return NULL;
  }

  DP("Offset of entries section is (" DPxMOD ").\n", DPxPTR(entries_offset));

  // load dynamic library and get the entry points. We use the dl library
  // to do the loading of the library, but we could do it directly to avoid the
  // dump to the temporary file.
  //
  // 1) Create tmp file with the library contents.
  // 2) Use dlopen to load the file and dlsym to retrieve the symbols.
  char tmp_name[] = "/tmp/tmpfile_XXXXXX";
  int tmp_fd = mkstemp(tmp_name);

  if (tmp_fd == -1) {
    elf_end(e);
    return NULL;
  }

  FILE *ftmp = fdopen(tmp_fd, "wb");

  if (!ftmp) {
    elf_end(e);
    return NULL;
  }

  fwrite(image->ImageStart, ImageSize, 1, ftmp);
  fclose(ftmp);

  DynLibTy Lib = {tmp_name, dlopen(tmp_name, RTLD_LAZY)};

  if (!Lib.Handle) {
    DP("Target library loading error: %s\n", dlerror());
    elf_end(e);
    return NULL;
  }

  DeviceInfo.DynLibs.push_back(Lib);

  struct link_map *libInfo = (struct link_map *)Lib.Handle;

  // The place where the entries info is loaded is the library base address
  // plus the offset determined from the ELF file.
  Elf64_Addr entries_addr = libInfo->l_addr + entries_offset;

  DP("Pointer to first entry to be loaded is (" DPxMOD ").\n",
      DPxPTR(entries_addr));

  // Table of pointers to all the entries in the target.
  __tgt_offload_entry *entries_table = (__tgt_offload_entry *)entries_addr;

  __tgt_offload_entry *entries_begin = &entries_table[0];
  __tgt_offload_entry *entries_end = entries_begin + NumEntries;

  if (!entries_begin) {
    DP("Can't obtain entries begin\n");
    elf_end(e);
    return NULL;
  }

  DP("Entries table range is (" DPxMOD ")->(" DPxMOD ")\n",
      DPxPTR(entries_begin), DPxPTR(entries_end));
  DeviceInfo.createOffloadTable(device_id, entries_begin, entries_end);

  elf_end(e);

  return DeviceInfo.getOffloadEntriesTable(device_id);
}
/* Search an ELF file for a ".gnu_debuglink" section.  */
static const char *
find_debuglink (Elf *elf, GElf_Word *crc)
{
  size_t shstrndx;
  if (elf_getshdrstrndx (elf, &shstrndx) < 0)
    return NULL;

  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)
	return NULL;

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

      if (!strcmp (name, ".gnu_debuglink"))
	break;
    }

  if (scn == NULL)
    return NULL;

  /* Found the .gnu_debuglink section.  Extract its contents.  */
  Elf_Data *rawdata = elf_rawdata (scn, NULL);
  if (rawdata == NULL)
    return NULL;

  Elf_Data crcdata =
    {
      .d_type = ELF_T_WORD,
      .d_buf = crc,
      .d_size = sizeof *crc,
      .d_version = EV_CURRENT,
    };
  Elf_Data conv =
    {
      .d_type = ELF_T_WORD,
      .d_buf = rawdata->d_buf + rawdata->d_size - sizeof *crc,
      .d_size = sizeof *crc,
      .d_version = EV_CURRENT,
    };

  GElf_Ehdr ehdr_mem;
  GElf_Ehdr *ehdr = gelf_getehdr (elf, &ehdr_mem);
  if (ehdr == NULL)
    return NULL;

  Elf_Data *d = gelf_xlatetom (elf, &crcdata, &conv, ehdr->e_ident[EI_DATA]);
  if (d == NULL)
    return NULL;
  assert (d == &crcdata);

  return rawdata->d_buf;
}

/* 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;
  {
    union
    {
      Elf32_Phdr p32[phnum];
      Elf64_Phdr p64[phnum];
    } phdr;
    dst.d_buf = &phdr;
    dst.d_size = sizeof phdr;
    if (unlikely (gelf_xlatetom (mod->main.elf, &dst, &src,
				 ehdr.e32.e_ident[EI_DATA]) == NULL))
      return DWFL_E_LIBELF;
    if (ehdr.e32.e_ident[EI_CLASS] == ELFCLASS32)
      {
	for (uint_fast16_t i = 0; i < phnum; ++i)
	  if (phdr.p32[i].p_type == PT_INTERP)
	    {
	      undo_interp = phdr.p32[i].p_vaddr;
	      break;
	    }
      }
    else
      {
	for (uint_fast16_t i = 0; i < phnum; ++i)
	  if (phdr.p64[i].p_type == PT_INTERP)
	    {
	      undo_interp = phdr.p64[i].p_vaddr;
	      break;
	    }
      }
  }

  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);

  union
  {
    Elf32_Shdr s32[shnum - 1];
    Elf64_Shdr s64[shnum - 1];
  } shdr;
  dst.d_buf = &shdr;
  dst.d_size = sizeof shdr;
  if (unlikely (gelf_xlatetom (mod->main.elf, &dst, &src,
			       ehdr.e32.e_ident[EI_DATA]) == NULL))
    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))
	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 (ehdr.e32.e_ident[EI_CLASS] == ELFCLASS32)
	for (size_t i = 0; i < shnum - 1; ++i)
	  consider_shdr (undo_interp, shdr.s32[i].sh_type, shdr.s32[i].sh_flags,
			 shdr.s32[i].sh_addr, shdr.s32[i].sh_size);
      else
	for (size_t i = 0; i < shnum - 1; ++i)
	  consider_shdr (undo_interp, shdr.s64[i].sh_type, shdr.s64[i].sh_flags,
			 shdr.s64[i].sh_addr, shdr.s64[i].sh_size);

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

  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 = find_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 a symbol table in FILE.
   Returns DWFL_E_NOERROR if a proper one is found.
   Returns DWFL_E_NO_SYMTAB if not, but still sets results for SHT_DYNSYM.  */
static Dwfl_Error
load_symtab (struct dwfl_file *file, struct dwfl_file **symfile,
	     Elf_Scn **symscn, Elf_Scn **xndxscn,
	     size_t *syments, int *first_global, GElf_Word *strshndx)
{
  bool symtab = false;
  Elf_Scn *scn = NULL;
  while ((scn = elf_nextscn (file->elf, scn)) != NULL)
    {
      GElf_Shdr shdr_mem, *shdr = gelf_getshdr (scn, &shdr_mem);
      if (shdr != NULL)
	switch (shdr->sh_type)
	  {
	  case SHT_SYMTAB:
	    symtab = true;
	    *symscn = scn;
	    *symfile = file;
	    *strshndx = shdr->sh_link;
	    *syments = shdr->sh_size / shdr->sh_entsize;
	    *first_global = shdr->sh_info;
	    if (*xndxscn != NULL)
	      return DWFL_E_NOERROR;
	    break;

	  case SHT_DYNSYM:
	    if (symtab)
	      break;
	    /* Use this if need be, but keep looking for SHT_SYMTAB.  */
	    *symscn = scn;
	    *symfile = file;
	    *strshndx = shdr->sh_link;
	    *syments = shdr->sh_size / shdr->sh_entsize;
	    *first_global = shdr->sh_info;
	    break;

	  case SHT_SYMTAB_SHNDX:
	    *xndxscn = scn;
	    if (symtab)
	      return DWFL_E_NOERROR;
	    break;

	  default:
	    break;
	  }
    }

  if (symtab)
    /* We found one, though no SHT_SYMTAB_SHNDX to go with it.  */
    return DWFL_E_NOERROR;

  /* We found no SHT_SYMTAB, so any SHT_SYMTAB_SHNDX was bogus.
     We might have found an SHT_DYNSYM and set *SYMSCN et al though.  */
  *xndxscn = NULL;
  return DWFL_E_NO_SYMTAB;
}


/* Translate addresses into file offsets.
   OFFS[*] start out zero and remain zero if unresolved.  */
static void
find_offsets (Elf *elf, size_t phnum, size_t n,
	      GElf_Addr addrs[n], GElf_Off offs[n])
{
  size_t unsolved = n;
  for (size_t i = 0; i < phnum; ++i)
    {
      GElf_Phdr phdr_mem;
      GElf_Phdr *phdr = gelf_getphdr (elf, i, &phdr_mem);
      if (phdr != NULL && phdr->p_type == PT_LOAD && phdr->p_memsz > 0)
	for (size_t j = 0; j < n; ++j)
	  if (offs[j] == 0
	      && addrs[j] >= phdr->p_vaddr
	      && addrs[j] - phdr->p_vaddr < phdr->p_filesz)
	    {
	      offs[j] = addrs[j] - phdr->p_vaddr + phdr->p_offset;
	      if (--unsolved == 0)
		break;
	    }
    }
}