コード例 #1
0
ファイル: nlist_elf32.c プロジェクト: marklee77/frankenlibc
int
ELFNAMEEND(__fdnlist)(int fd, struct nlist *list)
{
    struct stat st;
    Elf_Ehdr ehdr;
#if defined(_LP64) || ELFSIZE == 32 || defined(ELF64_MACHDEP_ID)
#if (ELFSIZE == 32)
    Elf32_Half nshdr;
#elif (ELFSIZE == 64)
    Elf64_Word nshdr;
#endif
    /* Only support 64+32 mode on LP64 and those that have defined */
    /* ELF64_MACHDEP_ID, otherwise no support for 64 mode on ILP32 */
    Elf_Ehdr *ehdrp;
    Elf_Shdr *shdrp, *symshdrp, *symstrshdrp;
    Elf_Sym *symp;
    Elf_Off shdr_off;
    Elf_Word shdr_size;
    struct nlist *p;
    char *mappedfile, *strtab;
    size_t mappedsize, nsyms;
    int nent;
#endif
    int rv;
    size_t i;

    _DIAGASSERT(fd != -1);
    _DIAGASSERT(list != NULL);

    rv = -1;

    /*
     * If we can't fstat() the file, something bad is going on.
     */
    if (fstat(fd, &st) < 0)
        BAD;

    /*
     * Map the file in its entirety.
     */
    if ((uintmax_t)st.st_size > (uintmax_t)SIZE_T_MAX) {
        errno = EFBIG;
        BAD;
    }

    /*
     * Read the elf header of the file.
     */
    if ((ssize_t)(i = pread(fd, &ehdr, sizeof(Elf_Ehdr), (off_t)0)) == -1)
        BAD;

    /*
     * Check that the elf header is correct.
     */
    if (i != sizeof(Elf_Ehdr))
        BAD;
    if (memcmp(ehdr.e_ident, ELFMAG, SELFMAG) != 0 ||
            ehdr.e_ident[EI_CLASS] != ELFCLASS)
        BAD;

    switch (ehdr.e_machine) {
        ELFDEFNNAME(MACHDEP_ID_CASES)

    default:
        BAD;
    }
#if defined(_LP64) || ELFSIZE == 32 || defined(ELF64_MACHDEP_ID)
    symshdrp = symstrshdrp = NULL;

    /* Only support 64+32 mode on LP64 and those that have defined */
    /* ELF64_MACHDEP_ID, otherwise no support for 64 mode on ILP32 */
    if (S_ISCHR(st.st_mode)) {
        const char *nlistname;
        Elf_Sym sym;

        /*
         * Character device; assume /dev/ksyms.
         */
        nent = 0;
        for (p = list; !ISLAST(p); ++p) {
            struct ksyms_gsymbol kg;
            int error;

            p->n_other = 0;
            p->n_desc = 0;
            nlistname = N_NAME(p);
            if (*nlistname == '_')
                nlistname++;

            memset(&kg, 0, sizeof(kg));
            kg.kg_name = nlistname;
#ifdef OKIOCGSYMBOL
            struct ksyms_ogsymbol okg;
            error = ioctl(fd, KIOCGSYMBOL, &kg);
            if (error == 0) {
                sym = kg.kg_sym;
            } else if (error && errno == ENOTTY) {
                memset(&okg, 0, sizeof(okg));
                okg.kg_name = nlistname;
                okg.kg_sym = &sym;
                error = ioctl(fd, OKIOCGSYMBOL, &okg);
            }
#else
            kg.kg_sym = &sym;
            error = ioctl(fd, KIOCGSYMBOL, &kg);
#endif
            if (error == 0
#if !defined(_LP64) && ELFSIZE == 64
#if __mips__
                    && (intptr_t)sym.st_value == (intmax_t)sym.st_value
#else
                    && (uintptr_t)sym.st_value == sym.st_value
#endif
#endif
                    && 1) {
                p->n_value = (uintptr_t)sym.st_value;
                switch (ELF_ST_TYPE(sym.st_info)) {
                case STT_NOTYPE:
                    p->n_type = N_UNDF;
                    break;
                case STT_COMMON:
                case STT_OBJECT:
                    p->n_type = N_DATA;
                    break;
                case STT_FUNC:
                    p->n_type = N_TEXT;
                    break;
                case STT_FILE:
                    p->n_type = N_FN;
                    break;
                default:
                    p->n_type = 0;
                    /* catch other enumerations for gcc */
                    break;
                }
                if (ELF_ST_BIND(sym.st_info) != STB_LOCAL)
                    p->n_type |= N_EXT;
            } else {
                nent++;
                p->n_value = 0;
                p->n_type = 0;
            }
        }
        return nent;
    }

    mappedsize = (size_t)st.st_size;
    mappedfile = mmap(NULL, mappedsize, PROT_READ, MAP_PRIVATE|MAP_FILE,
                      fd, (off_t)0);
    if (mappedfile == (char *)-1)
        BAD;

    /*
     * Make sure we can access the executable's header
     * directly, and make sure the recognize the executable
     * as an ELF binary.
     */
    if (check(0, sizeof *ehdrp))
        BADUNMAP;
    ehdrp = (Elf_Ehdr *)(void *)&mappedfile[0];

    /*
     * Find the symbol list and string table.
     */
    nshdr = ehdrp->e_shnum;
    shdr_off = ehdrp->e_shoff;
    shdr_size = ehdrp->e_shentsize * nshdr;

    if (check(shdr_off, shdr_size) ||
            (sizeof *shdrp != ehdrp->e_shentsize))
        BADUNMAP;
    shdrp = (void *)&mappedfile[(size_t)shdr_off];

    for (i = 0; i < nshdr; i++) {
        if (shdrp[i].sh_type == SHT_SYMTAB) {
            symshdrp = &shdrp[i];
            symstrshdrp = &shdrp[shdrp[i].sh_link];
        }
    }

    /* Make sure we're not stripped. */
    if (symshdrp == NULL || symshdrp->sh_offset == 0)
        BADUNMAP;

    /* Make sure the symbols and strings are safely mapped. */
    if (check(symshdrp->sh_offset, symshdrp->sh_size))
        BADUNMAP;
    if (check(symstrshdrp->sh_offset, symstrshdrp->sh_size))
        BADUNMAP;

    symp = (void *)&mappedfile[(size_t)symshdrp->sh_offset];
    nsyms = (size_t)(symshdrp->sh_size / sizeof(*symp));
    strtab = &mappedfile[(size_t)symstrshdrp->sh_offset];

    /*
     * Clean out any left-over information for all valid entries.
     * Type and value are defined to be 0 if not found; historical
     * versions cleared other and desc as well.
     *
     * XXX Clearing anything other than n_type and n_value violates
     * the semantics given in the man page.
     */
    nent = 0;
    for (p = list; !ISLAST(p); ++p) {
        p->n_type = 0;
        p->n_other = 0;
        p->n_desc = 0;
        p->n_value = 0;
        ++nent;
    }

    for (i = 0; i < nsyms; i++) {
        for (p = list; !ISLAST(p); ++p) {
            const char *nlistname;
            char *symtabname;

            /* This may be incorrect */
            nlistname = N_NAME(p);
            if (*nlistname == '_')
                nlistname++;

            symtabname = &strtab[symp[i].st_name];

            if (!strcmp(symtabname, nlistname)) {
                /*
                 * Translate (roughly) from ELF to nlist
                 */
                p->n_value = (uintptr_t)symp[i].st_value;
                switch (ELF_ST_TYPE(symp[i].st_info)) {
                case STT_NOTYPE:
                    p->n_type = N_UNDF;
                    break;
                case STT_OBJECT:
                case STT_COMMON:
                    p->n_type = N_DATA;
                    break;
                case STT_FUNC:
                    p->n_type = N_TEXT;
                    break;
                case STT_FILE:
                    p->n_type = N_FN;
                    break;
                default:
                    /* catch other enumerations for gcc */
                    break;
                }
                if (ELF_ST_BIND(symp[i].st_info) != STB_LOCAL)
                    p->n_type |= N_EXT;
                p->n_desc = 0;			/* XXX */
                p->n_other = 0;			/* XXX */

                if (--nent <= 0)
                    goto done;
                break;	/* into next run of outer loop */
            }
        }
    }

done:
    rv = nent;
unmap:
    munmap(mappedfile, mappedsize);
#endif /* _LP64 || ELFSIZE == 32 || ELF64_MACHDEP_ID */
out:
    return (rv);
}
コード例 #2
0
ファイル: nlist_coff.c プロジェクト: AgamAgarwal/minix
int
__fdnlist_coff(int fd, struct nlist *list)
{
	struct nlist *p;
	struct coff_filehdr *filehdrp;
	struct stat st;
	char *mappedfile;
	size_t mappedsize;
	u_long symoff, extstroff;
	int rv, nent;
	long i, nesyms;

	_DIAGASSERT(fd != -1);
	_DIAGASSERT(list != NULL);

	rv = -1;

	/*
	 * If we can't fstat() the file, something bad is going on.
	 */
	if (fstat(fd, &st) < 0)
		goto out;

	/*
	 * Map the file in its entirety.
	 */
	if ((uintmax_t)st.st_size > (uintmax_t)SIZE_T_MAX) {
		errno = EFBIG;
		goto out;
	}
	mappedsize = (size_t)st.st_size;
	mappedfile = mmap(NULL, mappedsize, PROT_READ, MAP_PRIVATE|MAP_FILE,
	    fd, 0);
	if (mappedfile == MAP_FAILED)
		goto out;

	/*
	 * Make sure we can access the executable's header
	 * directly, and make sure we recognize the executable
	 * as an COFF binary.
	 */
	if (mappedsize < sizeof (struct coff_filehdr))
		goto unmap;
	filehdrp = (void *)&mappedfile[0];

	if (COFF_BADMAG(filehdrp))
		goto unmap;

	/*
	 * Find the symbol list.
	 */
	symoff = filehdrp->f_symptr;
	nesyms = filehdrp->f_nsyms;

	if (symoff + ES_LEN * nesyms > mappedsize)
		goto unmap;
	extstroff = symoff + ES_LEN * nesyms;

	nent = 0;
	for (p = list; !ISLAST(p); ++p) {
		p->n_type = 0;
		p->n_other = 0;
		p->n_desc = 0;
		p->n_value = 0;
		++nent;
	}

	for (i = 0; i < nesyms; i++) {
		char *symtabname;
		const char *nlistname;
		struct coff_extsym esym;
		char name[10];

		memcpy(&esym, &mappedfile[symoff + ES_LEN * i], ES_LEN);
		if (esym.es_numaux != 0) {
			i += esym.es_numaux;	/* XXX Skip aux entry */
			continue;
		}
			
		if (esym.es_zero != 0) {
			memcpy(name, esym.es_name, 8);
			name[8] = 0;
			symtabname = name;
		} else if (esym.es_offset != 0)
			symtabname = &mappedfile[extstroff + esym.es_offset];
		else
			continue;

		for (p = list; !ISLAST(p); p++) {
			nlistname = N_NAME(p);
			if (!strcmp(symtabname, nlistname)) {
				/*
				 * Translate (roughly) from COFF to nlist
				 */
				p->n_value = esym.es_value;
				p->n_type = N_EXT;		/* XXX */
				p->n_desc = 0;			/* XXX */
				p->n_other = 0;			/* XXX */

				if (--nent <= 0)
					goto done;
				break;	/* into next run of outer loop */
			}
		}
	}

done:
	rv = nent;
unmap:
	munmap(mappedfile, mappedsize);
out:
	return rv;
}