コード例 #1
0
int
__elf_fdnlist(int fd, struct nlist *list)
{
	struct nlist *p;
	caddr_t strtab;
	Elf_Off symoff = 0, symstroff = 0;
	Elf_Word symsize = 0, symstrsize = 0;
	Elf_Sword nent, cc, i;
	Elf_Sym sbuf[1024];
	Elf_Sym *s;
	Elf_Ehdr ehdr;
	Elf_Shdr *shdr = NULL;
	Elf_Word shdr_size;
	struct stat st;
	int usemalloc = 0;

	/* Make sure obj is OK */
	if (pread(fd, &ehdr, sizeof(Elf_Ehdr), (off_t)0) != sizeof(Elf_Ehdr) ||
	    !__elf_is_okay__(&ehdr) || fstat(fd, &st) < 0)
		return (-1);

	/* calculate section header table size */
	shdr_size = ehdr.e_shentsize * ehdr.e_shnum;

	/* Make sure it's not too big to mmap */
	if (shdr_size > SIZE_T_MAX) {
		errno = EFBIG;
		return (-1);
	}

	/* mmap section header table */
	shdr = (Elf_Shdr *)mmap(NULL, (size_t)shdr_size, PROT_READ,
	    MAP_SHARED|MAP_FILE, fd, (off_t) ehdr.e_shoff);
	if (shdr == MAP_FAILED) {
		usemalloc = 1;
		if ((shdr = malloc(shdr_size)) == NULL)
			return (-1);

		if (pread(fd, shdr, shdr_size, (off_t)ehdr.e_shoff) != shdr_size) {
			free(shdr);
			return (-1);
		}
	}

	/*
	 * Find the symbol table entry and its corresponding
	 * string table entry.	Version 1.1 of the ABI states
	 * that there is only one symbol table but that this
	 * could change in the future.
	 */
	for (i = 0; i < ehdr.e_shnum; i++) {
		if (shdr[i].sh_type == SHT_SYMTAB) {
			symoff = shdr[i].sh_offset;
			symsize = shdr[i].sh_size;
			symstroff = shdr[shdr[i].sh_link].sh_offset;
			symstrsize = shdr[shdr[i].sh_link].sh_size;
			break;
		}
	}

	/* Flush the section header table */
	if (usemalloc)
		free(shdr);
	else
		munmap((caddr_t)shdr, shdr_size);

	/* Check for files too large to mmap. */
	/* XXX is this really possible? */
	if (symstrsize > SIZE_T_MAX) {
		errno = EFBIG;
		return (-1);
	}
	/*
	 * Map string table into our address space.  This gives us
	 * an easy way to randomly access all the strings, without
	 * making the memory allocation permanent as with malloc/free
	 * (i.e., munmap will return it to the system).
	 */
	if (usemalloc) {
		if ((strtab = malloc(symstrsize)) == NULL)
			return (-1);
		if (pread(fd, strtab, symstrsize, (off_t)symstroff) != symstrsize) {
			free(strtab);
			return (-1);
		}
	} else {
		strtab = mmap(NULL, (size_t)symstrsize, PROT_READ,
		    MAP_SHARED|MAP_FILE, fd, (off_t) symstroff);
		if (strtab == MAP_FAILED)
			return (-1);
	}
	/*
	 * clean out any left-over information for all valid entries.
	 * Type and value defined to be 0 if not found; historical
	 * versions cleared other and desc as well.  Also figure out
	 * the largest string length so don't read any more of the
	 * string table than we have to.
	 *
	 * 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;
	}

	/* Don't process any further if object is stripped. */
	/* ELFism - dunno if stripped by looking at header */
	if (symoff == 0)
		goto elf_done;

	while (symsize > 0) {
		cc = MIN(symsize, sizeof(sbuf));
		if (pread(fd, sbuf, cc, (off_t)symoff) != cc)
			break;
		symsize -= cc;
		symoff += cc;
		for (s = sbuf; cc > 0; ++s, cc -= sizeof(*s)) {
			int soff = s->st_name;

			if (soff == 0)
				continue;
			for (p = list; !ISLAST(p); p++) {
				char *sym;

				/*
				 * First we check for the symbol as it was
				 * provided by the user. If that fails
				 * and the first char is an '_', skip over
				 * the '_' and try again.
				 * XXX - What do we do when the user really
				 *       wants '_foo' and the are symbols
				 *       for both 'foo' and '_foo' in the
				 *	 table and 'foo' is first?
				 */
				sym = p->n_un.n_name;
				if (strcmp(&strtab[soff], sym) != 0 &&
				    (sym[0] != '_' ||
				     strcmp(&strtab[soff], sym + 1) != 0))
					continue;

				p->n_value = s->st_value;

				/* XXX - type conversion */
				/*	 is pretty rude. */
				switch(ELF_ST_TYPE(s->st_info)) {
				case STT_NOTYPE:
					switch (s->st_shndx) {
					case SHN_UNDEF:
						p->n_type = N_UNDF;
						break;
					case SHN_ABS:
						p->n_type = N_ABS;
						break;
					case SHN_COMMON:
						p->n_type = N_COMM;
						break;
					default:
						p->n_type = N_COMM | N_EXT;
						break;
					}
					break;
				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;
				}
				if (ELF_ST_BIND(s->st_info) ==
				    STB_LOCAL)
					p->n_type = N_EXT;
				p->n_desc = 0;
				p->n_other = 0;
				if (--nent <= 0)
					break;
			}
		}
	}
elf_done:
	if (usemalloc)
		free(strtab);
	else
		munmap(strtab, symstrsize);
	return (nent);
}
コード例 #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;
}
コード例 #3
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);
}
コード例 #4
0
ファイル: nlist.c プロジェクト: 2asoft/freebsd
int
__elf_fdnlist(int fd, struct nlist *list)
{
	struct nlist *p;
	Elf_Off symoff = 0, symstroff = 0;
	Elf_Size symsize = 0, symstrsize = 0;
	Elf_Ssize cc, i;
	int nent = -1;
	int errsave;
	Elf_Sym sbuf[1024];
	Elf_Sym *s;
	Elf_Ehdr ehdr;
	char *strtab = NULL;
	Elf_Shdr *shdr = NULL;
	Elf_Size shdr_size;
	void *base;
	struct stat st;

	/* Make sure obj is OK */
	if (lseek(fd, (off_t)0, SEEK_SET) == -1 ||
	    _read(fd, &ehdr, sizeof(Elf_Ehdr)) != sizeof(Elf_Ehdr) ||
	    !__elf_is_okay__(&ehdr) ||
	    _fstat(fd, &st) < 0)
		return (-1);

	/* calculate section header table size */
	shdr_size = ehdr.e_shentsize * ehdr.e_shnum;

	/* Make sure it's not too big to mmap */
	if (shdr_size > SIZE_T_MAX) {
		errno = EFBIG;
		return (-1);
	}

	/* mmap section header table */
	base = mmap(NULL, (size_t)shdr_size, PROT_READ, MAP_PRIVATE, fd,
	    (off_t)ehdr.e_shoff);
	if (base == MAP_FAILED)
		return (-1);
	shdr = (Elf_Shdr *)base;

	/*
	 * Find the symbol table entry and it's corresponding
	 * string table entry.	Version 1.1 of the ABI states
	 * that there is only one symbol table but that this
	 * could change in the future.
	 */
	for (i = 0; i < ehdr.e_shnum; i++) {
		if (shdr[i].sh_type == SHT_SYMTAB) {
			symoff = shdr[i].sh_offset;
			symsize = shdr[i].sh_size;
			symstroff = shdr[shdr[i].sh_link].sh_offset;
			symstrsize = shdr[shdr[i].sh_link].sh_size;
			break;
		}
	}

	/* Check for files too large to mmap. */
	if (symstrsize > SIZE_T_MAX) {
		errno = EFBIG;
		goto done;
	}
	/*
	 * Map string table into our address space.  This gives us
	 * an easy way to randomly access all the strings, without
	 * making the memory allocation permanent as with malloc/free
	 * (i.e., munmap will return it to the system).
	 */
	base = mmap(NULL, (size_t)symstrsize, PROT_READ, MAP_PRIVATE, fd,
	    (off_t)symstroff);
	if (base == MAP_FAILED)
		goto done;
	strtab = (char *)base;

	/*
	 * clean out any left-over information for all valid entries.
	 * Type and value defined to be 0 if not found; historical
	 * versions cleared other and desc as well.  Also figure out
	 * the largest string length so don't read any more of the
	 * string table than we have to.
	 *
	 * 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;
	}

	/* Don't process any further if object is stripped. */
	if (symoff == 0)
		goto done;
		
	if (lseek(fd, (off_t) symoff, SEEK_SET) == -1) {
		nent = -1;
		goto done;
	}

	while (symsize > 0 && nent > 0) {
		cc = MIN(symsize, sizeof(sbuf));
		if (_read(fd, sbuf, cc) != cc)
			break;
		symsize -= cc;
		for (s = sbuf; cc > 0 && nent > 0; ++s, cc -= sizeof(*s)) {
			char *name;
			struct nlist *p;

			name = strtab + s->st_name;
			if (name[0] == '\0')
				continue;
			for (p = list; !ISLAST(p); p++) {
				if ((p->n_un.n_name[0] == '_' &&
				    strcmp(name, p->n_un.n_name+1) == 0)
				    || strcmp(name, p->n_un.n_name) == 0) {
					elf_sym_to_nlist(p, s, shdr,
					    ehdr.e_shnum);
					if (--nent <= 0)
						break;
				}
			}
		}
	}
  done:
	errsave = errno;
	if (strtab != NULL)
		munmap(strtab, symstrsize);
	if (shdr != NULL)
		munmap(shdr, shdr_size);
	errno = errsave;
	return (nent);
}
コード例 #5
0
ファイル: nlist.c プロジェクト: 2asoft/freebsd
int
__aout_fdnlist(int fd, struct nlist *list)
{
	struct nlist *p, *symtab;
	caddr_t strtab, a_out_mmap;
	off_t stroff, symoff;
	u_long symsize;
	int nent;
	struct exec * exec;
	struct stat st;

	/* check that file is at least as large as struct exec! */
	if ((_fstat(fd, &st) < 0) || (st.st_size < sizeof(struct exec)))
		return (-1);

	/* Check for files too large to mmap. */
	if (st.st_size > SIZE_T_MAX) {
		errno = EFBIG;
		return (-1);
	}

	/*
	 * Map the whole a.out file into our address space.
	 * We then find the string table withing this area.
	 * We do not just mmap the string table, as it probably
	 * does not start at a page boundary - we save ourselves a
	 * lot of nastiness by mmapping the whole file.
	 *
	 * This gives us an easy way to randomly access all the strings,
	 * without making the memory allocation permanent as with
	 * malloc/free (i.e., munmap will return it to the system).
	 */
	a_out_mmap = mmap(NULL, (size_t)st.st_size, PROT_READ, MAP_PRIVATE, fd, (off_t)0);
	if (a_out_mmap == MAP_FAILED)
		return (-1);

	exec = (struct exec *)a_out_mmap;
	if (N_BADMAG(*exec)) {
		munmap(a_out_mmap, (size_t)st.st_size);
		return (-1);
	}

	symoff = N_SYMOFF(*exec);
	symsize = exec->a_syms;
	stroff = symoff + symsize;

	/* find the string table in our mmapped area */
	strtab = a_out_mmap + stroff;
	symtab = (struct nlist *)(a_out_mmap + symoff);

	/*
	 * clean out any left-over information for all valid entries.
	 * Type and value defined to be 0 if not found; historical
	 * versions cleared other and desc as well.  Also figure out
	 * the largest string length so don't read any more of the
	 * string table than we have to.
	 *
	 * 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;
	}

	while (symsize > 0) {
		int soff;

		symsize-= sizeof(struct nlist);
		soff = symtab->n_un.n_strx;


		if (soff != 0 && (symtab->n_type & N_STAB) == 0)
			for (p = list; !ISLAST(p); p++)
				if (!strcmp(&strtab[soff], p->n_un.n_name)) {
					p->n_value = symtab->n_value;
					p->n_type = symtab->n_type;
					p->n_desc = symtab->n_desc;
					p->n_other = symtab->n_other;
					if (--nent <= 0)
						break;
				}
		symtab++;
	}
	munmap(a_out_mmap, (size_t)st.st_size);
	return (nent);
}
コード例 #6
0
ファイル: nlist.c プロジェクト: mzp/frama-c-sample
int
__aout_fdnlist(int fd, struct nlist *list)
{
	struct nlist *p, *s;
	char *strtab;
	off_t symoff, stroff;
	u_long symsize;
	int nent, cc;
	int strsize, usemalloc = 0;
	struct nlist nbuf[1024];
	struct exec exec;

	if (pread(fd, &exec, sizeof(exec), (off_t)0) != sizeof(exec) ||
	    N_BADMAG(exec) || exec.a_syms == NULL)
		return (-1);

	stroff = N_STROFF(exec);
	symoff = N_SYMOFF(exec);
	symsize = exec.a_syms;

	/* Read in the size of the string table. */
	if (pread(fd, (void *)&strsize, sizeof(strsize), stroff) !=
	    sizeof(strsize))
		return (-1);
	else
		stroff += sizeof(strsize);

	/*
	 * Read in the string table.  We try mmap, but that will fail
	 * for /dev/ksyms so fall back on malloc.  Since OpenBSD's malloc(3)
	 * returns memory to the system on free this does not cause bloat.
	 */
	strsize -= sizeof(strsize);
	strtab = mmap(NULL, (size_t)strsize, PROT_READ, MAP_SHARED|MAP_FILE,
	    fd, stroff);
	if (strtab == MAP_FAILED) {
		usemalloc = 1;
		if ((strtab = (char *)malloc(strsize)) == NULL)
			return (-1);
		errno = EIO;
		if (pread(fd, strtab, strsize, stroff) != strsize) {
			nent = -1;
			goto aout_done;
		}
	}

	/*
	 * clean out any left-over information for all valid entries.
	 * Type and value defined to be 0 if not found; historical
	 * versions cleared other and desc as well.  Also figure out
	 * the largest string length so don't read any more of the
	 * string table than we have to.
	 *
	 * 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;
	}

	while (symsize > 0) {
		cc = MIN(symsize, sizeof(nbuf));
		if (pread(fd, nbuf, cc, symoff) != cc)
			break;
		symsize -= cc;
		symoff += cc;
		for (s = nbuf; cc > 0; ++s, cc -= sizeof(*s)) {
			char *sname = strtab + s->n_un.n_strx - sizeof(int);

			if (s->n_un.n_strx == 0 || (s->n_type & N_STAB) != 0)
				continue;
			for (p = list; !ISLAST(p); p++) {
				char *pname = p->n_un.n_name;

				if (*sname != '_' && *pname == '_')
					pname++;
				if (!strcmp(sname, pname)) {
					p->n_value = s->n_value;
					p->n_type = s->n_type;
					p->n_desc = s->n_desc;
					p->n_other = s->n_other;
					if (--nent <= 0)
						break;
				}
			}
		}
	}
aout_done:
	if (usemalloc)
		free(strtab);
	else
		munmap(strtab, strsize);
	return (nent);
}
コード例 #7
0
ファイル: nlist.c プロジェクト: mzp/frama-c-sample
int
__ecoff_fdnlist(int fd, struct nlist *list)
{
	struct nlist *p;
	struct ecoff_exechdr *exechdrp;
	struct ecoff_symhdr *symhdrp;
	struct ecoff_extsym *esyms;
	struct stat st;
	char *mappedfile;
	size_t mappedsize;
	u_long symhdroff, extstroff;
	u_int symhdrsize;
	int rv, nent;
	long i, nesyms;

	rv = -3;

	if (fstat(fd, &st) < 0)
		BAD;
	if (st.st_size > SIZE_T_MAX) {
		errno = EFBIG;
		BAD;
	}
	mappedsize = st.st_size;
	mappedfile = mmap(NULL, mappedsize, PROT_READ, MAP_SHARED|MAP_FILE,
	    fd, 0);
	if (mappedfile == MAP_FAILED)
		BAD;

	if (check(0, sizeof *exechdrp))
		BADUNMAP;
	exechdrp = (struct ecoff_exechdr *)&mappedfile[0];

	if (ECOFF_BADMAG(exechdrp))
		BADUNMAP;

	symhdroff = exechdrp->f.f_symptr;
	symhdrsize = exechdrp->f.f_nsyms;

	if (check(symhdroff, sizeof *symhdrp) ||
	    sizeof *symhdrp != symhdrsize)
		BADUNMAP;
	symhdrp = (struct ecoff_symhdr *)&mappedfile[symhdroff];

	nesyms = symhdrp->esymMax;
	if (check(symhdrp->cbExtOffset, nesyms * sizeof *esyms))
		BADUNMAP;
	esyms = (struct ecoff_extsym *)&mappedfile[symhdrp->cbExtOffset];
	extstroff = symhdrp->cbSsExtOffset;

	/*
	 * clean out any left-over information for all valid entries.
	 * Type and value 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 < nesyms; i++) {
		for (p = list; !ISLAST(p); p++) {
			char *nlistname;
			char *symtabname;

			nlistname = p->n_un.n_name;
			if (*nlistname == '_')
				nlistname++;
			symtabname =
			    &mappedfile[extstroff + esyms[i].es_strindex];

			if (!strcmp(symtabname, nlistname)) {
				p->n_value = esyms[i].es_value;
				p->n_type = N_EXT;		/* XXX */
				p->n_desc = 0;			/* XXX */
				p->n_other = 0;			/* XXX */
				if (--nent <= 0)
					break;
			}
		}
	}
	rv = nent;

unmap:
	munmap(mappedfile, mappedsize);
out:
	return (rv);
}
コード例 #8
0
ファイル: nlist_aout.c プロジェクト: AgamAgarwal/minix
int
__fdnlist_aout(int fd, struct nlist *list)
{
	struct nlist *p, *s;
	char *strtab;
	off_t stroff, symoff;
	int nent;
	size_t strsize, symsize, cc;
	struct nlist nbuf[1024];
	struct exec exec;
	struct stat st;
	char *scoreboard, *scored;

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

	if (pread(fd, &exec, sizeof(exec), (off_t)0) != sizeof(exec) ||
	    N_BADMAG(exec) || fstat(fd, &st) < 0)
		return (-1);

	symoff = N_SYMOFF(exec);
	symsize = (size_t)exec.a_syms;
	stroff = symoff + symsize;

	/* Check for files too large to mmap. */
	if ((uintmax_t)(st.st_size - stroff) > (uintmax_t)SIZE_T_MAX) {
		errno = EFBIG;
		return (-1);
	}
	/*
	 * Map string table into our address space.  This gives us
	 * an easy way to randomly access all the strings, without
	 * making the memory allocation permanent as with malloc/free
	 * (i.e., munmap will return it to the system).
	 */
	strsize = (size_t)(st.st_size - stroff);
	strtab = mmap(NULL, strsize, PROT_READ, MAP_PRIVATE|MAP_FILE,
	    fd, stroff);
	if (strtab == (char *)-1)
		return (-1);
	/*
	 * clean out any left-over information for all valid entries.
	 * Type and value defined to be 0 if not found; historical
	 * versions cleared other and desc as well.  Also figure out
	 * the largest string length so don't read any more of the
	 * string table than we have to.
	 *
	 * 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;
	}
	if (lseek(fd, symoff, SEEK_SET) == -1)
		return (-1);
#if defined(__SSP__) || defined(__SSP_ALL__)
	scoreboard = malloc((size_t)nent);
#else
	scoreboard = alloca((size_t)nent);
#endif
	if (scoreboard == NULL)
		return (-1);
	(void)memset(scoreboard, 0, (size_t)nent);

	while (symsize > 0) {
		cc = MIN(symsize, sizeof(nbuf));
		if (read(fd, nbuf, cc) != (ssize_t) cc)
			break;
		symsize -= cc;
		for (s = nbuf; cc > 0; ++s, cc -= sizeof(*s)) {
			long soff = s->n_un.n_strx;

			if (soff == 0 || (s->n_type & N_STAB) != 0)
				continue;
			for (p = list, scored = scoreboard; !ISLAST(p);
			    p++, scored++)
				if (*scored == 0 &&
				    !strcmp(&strtab[(size_t)soff],
				    p->n_un.n_name)) {
					p->n_value = s->n_value;
					p->n_type = s->n_type;
					p->n_desc = s->n_desc;
					p->n_other = s->n_other;
					*scored = 1;
					if (--nent <= 0)
						break;
				}
		}
	}
	munmap(strtab, strsize);
#if defined(__SSP__) || defined(__SSP_ALL__)
	free(scoreboard);
#endif
	return (nent);
}