コード例 #1
0
ファイル: 20021120-1.c プロジェクト: pjump/gcc
void foo (int n)
{
    double DECLARE(d);
    float DECLARE(f);
    volatile double *pd;
    volatile float *pf;
    int i;

    pd = gd;
    COPYIN (d, pd);
    for (i = 0; i < n; i++)
    {
        pf = gf;
        COPYIN (f, pf);
        pd = gd;
        ADD (d, pd);
        pd = gd;
        ADD (d, pd);
        pd = gd;
        ADD (d, pd);
        pf = gf;
        COPYOUT (f, pf);
    }
    pd = gd;
    COPYOUT (d, pd);
}
コード例 #2
0
/*
 * Apply any intra-module relocations to the value. p is the load address
 * of the value and val/len is the value to be modified. This does NOT modify
 * the image in-place, because this is done by kern_linker later on.
 *
 * Returns EOPNOTSUPP if no relocation method is supplied.
 */
static int
__elfN(reloc_ptr)(struct preloaded_file *mp, elf_file_t ef,
    Elf_Addr p, void *val, size_t len)
{
	size_t n;
	Elf_Rela a;
	Elf_Rel r;
	int error;

	/*
	 * The kernel is already relocated, but we still want to apply
	 * offset adjustments.
	 */
	if (ef->kernel)
		return (EOPNOTSUPP);

	for (n = 0; n < ef->relsz / sizeof(r); n++) {
		COPYOUT(ef->rel + n, &r, sizeof(r));

		error = __elfN(reloc)(ef, __elfN(symaddr), &r, ELF_RELOC_REL,
		    ef->off, p, val, len);
		if (error != 0)
			return (error);
	}
	for (n = 0; n < ef->relasz / sizeof(a); n++) {
		COPYOUT(ef->rela + n, &a, sizeof(a));

		error = __elfN(reloc)(ef, __elfN(symaddr), &a, ELF_RELOC_RELA,
		    ef->off, p, val, len);
		if (error != 0)
			return (error);
	}

	return (0);
}
コード例 #3
0
/*
 * Apply any intra-module relocations to the value. p is the load address
 * of the value and val/len is the value to be modified. This does NOT modify
 * the image in-place, because this is done by kern_linker later on.
 */
static int
__elfN(obj_reloc_ptr)(struct preloaded_file *mp, elf_file_t ef, Elf_Addr p,
    void *val, size_t len)
{
	Elf_Ehdr *hdr;
	Elf_Shdr *shdr;
	Elf_Addr off = p;
	Elf_Addr base;
	Elf_Rela a, *abase;
	Elf_Rel r, *rbase;
	int error, i, j, nrel, nrela;

	hdr = &ef->hdr;
	shdr = ef->e_shdr;

	for (i = 0; i < hdr->e_shnum; i++) {
		if (shdr[i].sh_type != SHT_RELA && shdr[i].sh_type != SHT_REL)
			continue;
		base = shdr[shdr[i].sh_info].sh_addr;
		if (base == 0 || shdr[i].sh_addr == 0)
			continue;
		if (off < base || off + len > base +
		    shdr[shdr[i].sh_info].sh_size)
			continue;

		switch (shdr[i].sh_type) {
		case SHT_RELA:
			abase = (Elf_Rela *)(intptr_t)shdr[i].sh_addr;

			nrela = shdr[i].sh_size / sizeof(Elf_Rela);
			for (j = 0; j < nrela; j++) {
				COPYOUT(abase + j, &a, sizeof(a));

				error = __elfN(reloc)(ef, __elfN(obj_symaddr),
				    &a, ELF_RELOC_RELA, base, off, val, len);
				if (error != 0)
					return (error);
			}
			break;
		case SHT_REL:
			rbase = (Elf_Rel *)(intptr_t)shdr[i].sh_addr;

			nrel = shdr[i].sh_size / sizeof(Elf_Rel);
			for (j = 0; j < nrel; j++) {
				COPYOUT(rbase + j, &r, sizeof(r));

				error = __elfN(reloc)(ef, __elfN(obj_symaddr),
				    &r, ELF_RELOC_REL, base, off, val, len);
				if (error != 0)
					return (error);
			}
			break;
		}
	}
	return (0);
}
コード例 #4
0
ファイル: fdt_loader_cmd.c プロジェクト: Lxg1582/freebsd
static int
fdt_load_dtb(vm_offset_t va)
{
	struct fdt_header header;
	int err;

	debugf("fdt_load_dtb(0x%08jx)\n", (uintmax_t)va);

	COPYOUT(va, &header, sizeof(header));
	err = fdt_check_header(&header);
	if (err < 0) {
		if (err == -FDT_ERR_BADVERSION)
			sprintf(command_errbuf,
			    "incompatible blob version: %d, should be: %d",
			    fdt_version(fdtp), FDT_LAST_SUPPORTED_VERSION);

		else
			sprintf(command_errbuf, "error validating blob: %s",
			    fdt_strerror(err));
		return (1);
	}

	/*
	 * Release previous blob
	 */
	if (fdtp)
		free(fdtp);

	fdtp_size = fdt_totalsize(&header);
	fdtp = malloc(fdtp_size);

	if (fdtp == NULL) {
		command_errmsg = "can't allocate memory for device tree copy";
		return (1);
	}

	fdtp_va = va;
	COPYOUT(va, fdtp, fdtp_size);
	debugf("DTB blob found at 0x%jx, size: 0x%jx\n", (uintmax_t)va, (uintmax_t)fdtp_size);

	return (0);
}
コード例 #5
0
int
__elfN(lookup_symbol)(struct preloaded_file *fp, elf_file_t ef, const char* name,
		  Elf_Sym *symp)
{
    Elf_Hashelt symnum;
    Elf_Sym sym;
    char *strp;
    unsigned long hash;

    hash = elf_hash(name);
    COPYOUT(&ef->buckets[hash % ef->nbuckets], &symnum, sizeof(symnum));

    while (symnum != STN_UNDEF) {
	if (symnum >= ef->nchains) {
	    printf(__elfN(bad_symtable));
	    return ENOENT;
	}

	COPYOUT(ef->symtab + symnum, &sym, sizeof(sym));
	if (sym.st_name == 0) {
	    printf(__elfN(bad_symtable));
	    return ENOENT;
	}

	strp = strdupout((vm_offset_t)(ef->strtab + sym.st_name));
	if (strcmp(name, strp) == 0) {
	    free(strp);
	    if (sym.st_shndx != SHN_UNDEF ||
		(sym.st_value != 0 &&
		 ELF_ST_TYPE(sym.st_info) == STT_FUNC)) {
		*symp = sym;
		return 0;
	    }
	    return ENOENT;
	}
	free(strp);
	COPYOUT(&ef->chains[symnum], &symnum, sizeof(symnum));
    }
    return ENOENT;
}
コード例 #6
0
ファイル: load_elf_obj.c プロジェクト: 2asoft/freebsd
/* Look up the address of a specified symbol. */
static Elf_Addr
__elfN(obj_symaddr)(struct elf_file *ef, Elf_Size symidx)
{
	Elf_Sym sym;
	Elf_Addr base;

	if (symidx >= ef->e_shdr[ef->symtabindex].sh_size / sizeof(Elf_Sym))
		return (0);
	COPYOUT(ef->e_shdr[ef->symtabindex].sh_addr + symidx * sizeof(Elf_Sym),
	    &sym, sizeof(sym));
	if (sym.st_shndx == SHN_UNDEF || sym.st_shndx >= ef->hdr.e_shnum)
		return (0);
	base = ef->e_shdr[sym.st_shndx].sh_addr;
	if (base == 0)
		return (0);
	return (base + sym.st_value);
}
コード例 #7
0
int
__elfN(obj_parse_modmetadata)(struct preloaded_file *fp, elf_file_t ef)
{
	struct mod_metadata md;
#if defined(__i386__) && __ELF_WORD_SIZE == 64
	struct mod_metadata64 md64;
#endif
	struct mod_depend *mdepend;
	struct mod_version mver;
	char *s;
	int error, modcnt, minfolen;
	Elf_Addr v, p, p_stop;

	if (__elfN(obj_lookup_set)(fp, ef, "modmetadata_set", &p, &p_stop,
	    &modcnt) != 0)
		return 0;

	modcnt = 0;
	while (p < p_stop) {
		COPYOUT(p, &v, sizeof(v));
		error = __elfN(obj_reloc_ptr)(fp, ef, p, &v, sizeof(v));
		if (error != 0)
			return (error);
#if defined(__i386__) && __ELF_WORD_SIZE == 64
		COPYOUT(v, &md64, sizeof(md64));
		error = __elfN(obj_reloc_ptr)(fp, ef, v, &md64, sizeof(md64));
		if (error != 0)
			return (error);
		md.md_version = md64.md_version;
		md.md_type = md64.md_type;
		md.md_cval = (const char *)(uintptr_t)md64.md_cval;
		md.md_data = (void *)(uintptr_t)md64.md_data;
#else
		COPYOUT(v, &md, sizeof(md));
		error = __elfN(obj_reloc_ptr)(fp, ef, v, &md, sizeof(md));
		if (error != 0)
			return (error);
#endif
		p += sizeof(Elf_Addr);
		switch(md.md_type) {
		case MDT_DEPEND:
			s = strdupout((vm_offset_t)md.md_cval);
			minfolen = sizeof(*mdepend) + strlen(s) + 1;
			mdepend = malloc(minfolen);
			if (mdepend == NULL)
				return ENOMEM;
			COPYOUT((vm_offset_t)md.md_data, mdepend,
			    sizeof(*mdepend));
			strcpy((char*)(mdepend + 1), s);
			free(s);
			file_addmetadata(fp, MODINFOMD_DEPLIST, minfolen,
			    mdepend);
			free(mdepend);
			break;
		case MDT_VERSION:
			s = strdupout((vm_offset_t)md.md_cval);
			COPYOUT((vm_offset_t)md.md_data, &mver, sizeof(mver));
			file_addmodule(fp, s, mver.mv_version, NULL);
			free(s);
			modcnt++;
			break;
		case MDT_MODULE:
			break;
		default:
			printf("unknown type %d\n", md.md_type);
			break;
		}
	}
	return 0;
}
コード例 #8
0
int
manage_link(int fd)
{
	char *p, *e, *cp;
	char ifname[IF_NAMESIZE];
	ssize_t bytes;
	struct rt_msghdr *rtm;
	struct if_announcemsghdr *ifan;
	struct if_msghdr *ifm;
	struct ifa_msghdr *ifam;
	struct rt rt;
	struct sockaddr *sa, *rti_info[RTAX_MAX];
	int len;
#ifdef RTM_CHGADDR
	struct sockaddr_dl sdl;
	unsigned char *hwaddr;
#endif

	for (;;) {
		if (ioctl(fd, FIONREAD, &len) == -1)
			return -1;
		if (link_buflen < len) {
			p = realloc(link_buf, len);
			if (p == NULL)
				return -1;
			link_buf = p;
			link_buflen = len;
		}
		bytes = read(fd, link_buf, link_buflen);
		if (bytes == -1) {
			if (errno == EAGAIN)
				return 0;
			if (errno == EINTR)
				continue;
			return -1;
		}
		e = link_buf + bytes;
		for (p = link_buf; p < e; p += rtm->rtm_msglen) {
			rtm = (struct rt_msghdr *)(void *)p;
			switch(rtm->rtm_type) {
#ifdef RTM_IFANNOUNCE
			case RTM_IFANNOUNCE:
				ifan = (struct if_announcemsghdr *)(void *)p;
				switch(ifan->ifan_what) {
				case IFAN_ARRIVAL:
					handle_interface(1, ifan->ifan_name);
					break;
				case IFAN_DEPARTURE:
					handle_interface(-1, ifan->ifan_name);
					break;
				}
				break;
#endif
			case RTM_IFINFO:
				ifm = (struct if_msghdr *)(void *)p;
				memset(ifname, 0, sizeof(ifname));
				if (if_indextoname(ifm->ifm_index, ifname))
					handle_interface(0, ifname);
				break;
			case RTM_DELETE:
				if (!(rtm->rtm_addrs & RTA_DST) ||
				    !(rtm->rtm_addrs & RTA_GATEWAY) ||
				    !(rtm->rtm_addrs & RTA_NETMASK))
					break;
				if (rtm->rtm_pid == getpid())
					break;
				cp = (char *)(void *)(rtm + 1);
				sa = (struct sockaddr *)(void *)cp;
				if (sa->sa_family != AF_INET)
					break;
				get_addrs(rtm->rtm_addrs, cp, rti_info);
				rt.iface = NULL;
				rt.next = NULL;
				COPYOUT(rt.dest, rti_info[RTAX_DST]);
				COPYOUT(rt.net, rti_info[RTAX_NETMASK]);
				COPYOUT(rt.gate, rti_info[RTAX_GATEWAY]);
				route_deleted(&rt);
				break;
#ifdef RTM_CHGADDR
			case RTM_CHGADDR:	/* FALLTHROUGH */
#endif
			case RTM_DELADDR:	/* FALLTHROUGH */
			case RTM_NEWADDR:
				ifam = (struct ifa_msghdr *)(void *)p;
				if (!if_indextoname(ifam->ifam_index, ifname))
					break;
				cp = (char *)(void *)(ifam + 1);
				get_addrs(ifam->ifam_addrs, cp, rti_info);
				if (rti_info[RTAX_IFA] == NULL)
					break;
				switch (rti_info[RTAX_IFA]->sa_family) {
#ifdef RTM_CHGADDR
				case AF_LINK:
					if (rtm->rtm_type != RTM_CHGADDR)
						break;
					memcpy(&sdl, rti_info[RTAX_IFA],
					    rti_info[RTAX_IFA]->sa_len);
					hwaddr = xmalloc(sdl.sdl_alen);
					memcpy(hwaddr, LLADDR(&sdl),
					    sdl.sdl_alen);
					handle_hwaddr(ifname, hwaddr,
					    sdl.sdl_alen);
					break;
#endif
				case AF_INET:
				case 255: /* FIXME: Why 255? */
					COPYOUT(rt.dest, rti_info[RTAX_IFA]);
					COPYOUT(rt.net, rti_info[RTAX_NETMASK]);
					COPYOUT(rt.gate, rti_info[RTAX_BRD]);
					handle_ifa(rtm->rtm_type, ifname,
					    &rt.dest, &rt.net, &rt.gate);
					break;
				}
				break;
			}
		}
	}
}
コード例 #9
0
static vm_offset_t
fdt_find_static_dtb(void)
{
	Elf_Sym sym;
	vm_offset_t dyntab, esym;
	uint64_t offs;
	struct preloaded_file *kfp;
	struct file_metadata *md;
	Elf_Sym *symtab;
	Elf_Dyn *dyn;
	char *strtab, *strp;
	int i, sym_count;

	symtab = NULL;
	dyntab = esym = 0;
	strtab = strp = NULL;

	offs = __elfN(relocation_offset);

	kfp = file_findfile(NULL, NULL);
	if (kfp == NULL)
		return (0);

	md = file_findmetadata(kfp, MODINFOMD_ESYM);
	if (md == NULL)
		return (0);
	COPYOUT(md->md_data, &esym, sizeof(esym));

	md = file_findmetadata(kfp, MODINFOMD_DYNAMIC);
	if (md == NULL)
		return (0);
	COPYOUT(md->md_data, &dyntab, sizeof(dyntab));

	dyntab += offs;

	/* Locate STRTAB and DYNTAB */
	for (dyn = (Elf_Dyn *)dyntab; dyn->d_tag != DT_NULL; dyn++) {
		if (dyn->d_tag == DT_STRTAB) {
			strtab = (char *)(uintptr_t)(dyn->d_un.d_ptr + offs);
			continue;
		} else if (dyn->d_tag == DT_SYMTAB) {
			symtab = (Elf_Sym *)(uintptr_t)
			    (dyn->d_un.d_ptr + offs);
			continue;
		}
	}

	if (symtab == NULL || strtab == NULL) {
		/*
		 * No symtab? No strtab? That should not happen here,
		 * and should have been verified during __elfN(loadimage).
		 * This must be some kind of a bug.
		 */
		return (0);
	}

	sym_count = (int)((Elf_Sym *)esym - symtab) / sizeof(Elf_Sym);

	/*
	 * The most efficent way to find a symbol would be to calculate a
	 * hash, find proper bucket and chain, and thus find a symbol.
	 * However, that would involve code duplication (e.g. for hash
	 * function). So we're using simpler and a bit slower way: we're
	 * iterating through symbols, searching for the one which name is
	 * 'equal' to 'fdt_static_dtb'. To speed up the process a little bit,
	 * we are eliminating symbols type of which is not STT_NOTYPE, or(and)
	 * those which binding attribute is not STB_GLOBAL.
	 */
	for (i = 0; i < sym_count; i++) {
		COPYOUT(symtab + i, &sym, sizeof(sym));
		if (ELF_ST_BIND(sym.st_info) != STB_GLOBAL ||
		    ELF_ST_TYPE(sym.st_info) != STT_NOTYPE)
			continue;

		strp = strdupout((vm_offset_t)(strtab + sym.st_name));
		if (strcmp(strp, FDT_STATIC_DTB_SYMBOL) == 0) {
			/* Found a match ! */
			free(strp);
			return ((vm_offset_t)(sym.st_value + offs));
		}
		free(strp);
	}
	return (0);
}
コード例 #10
0
ファイル: if-bsd.c プロジェクト: RTEMS/rtems-libbsd
int
manage_link(int fd)
{
	char *p, *e, *cp;
	char ifname[IF_NAMESIZE];
	ssize_t bytes;
	struct rt_msghdr *rtm;
	struct if_announcemsghdr *ifan;
	struct if_msghdr *ifm;
	struct ifa_msghdr *ifam;
	struct sockaddr *sa, *rti_info[RTAX_MAX];
	int len;
	struct sockaddr_dl sdl;
#ifdef INET
	struct rt rt;
#endif
#if defined(INET6) && !defined(LISTEN_DAD)
	struct in6_addr ia6;
	struct sockaddr_in6 *sin6;
	int ifa_flags;
#endif

	for (;;) {
		if (ioctl(fd, FIONREAD, &len) == -1)
			return -1;
		if (link_buflen < len) {
			p = realloc(link_buf, len);
			if (p == NULL)
				return -1;
			link_buf = p;
			link_buflen = len;
		}
		bytes = read(fd, link_buf, link_buflen);
		if (bytes == -1) {
			if (errno == EAGAIN)
				return 0;
			if (errno == EINTR)
				continue;
			return -1;
		}
		e = link_buf + bytes;
		for (p = link_buf; p < e; p += rtm->rtm_msglen) {
			rtm = (struct rt_msghdr *)(void *)p;
			// Ignore messages generated by us
			if (rtm->rtm_pid == getpid())
				break;
			switch(rtm->rtm_type) {
#ifdef RTM_IFANNOUNCE
			case RTM_IFANNOUNCE:
				ifan = (struct if_announcemsghdr *)(void *)p;
				switch(ifan->ifan_what) {
				case IFAN_ARRIVAL:
					handle_interface(1, ifan->ifan_name);
					break;
				case IFAN_DEPARTURE:
					handle_interface(-1, ifan->ifan_name);
					break;
				}
				break;
#endif
			case RTM_IFINFO:
				ifm = (struct if_msghdr *)(void *)p;
				memset(ifname, 0, sizeof(ifname));
				if (!(if_indextoname(ifm->ifm_index, ifname)))
					break;
				switch (ifm->ifm_data.ifi_link_state) {
				case LINK_STATE_DOWN:
					len = LINK_DOWN;
					break;
				case LINK_STATE_UP:
					len = LINK_UP;
					break;
				default:
					/* handle_carrier will re-load
					 * the interface flags and check for
					 * IFF_RUNNING as some drivers that
					 * don't handle link state also don't
					 * set IFF_RUNNING when this routing
					 * message is generated.
					 * As such, it is a race ...*/
					len = LINK_UNKNOWN;
					break;
				}
				handle_carrier(len, ifm->ifm_flags, ifname);
				break;
			case RTM_DELETE:
				if (~rtm->rtm_addrs &
				    (RTA_DST | RTA_GATEWAY | RTA_NETMASK))
					break;
				cp = (char *)(void *)(rtm + 1);
				sa = (struct sockaddr *)(void *)cp;
				if (sa->sa_family != AF_INET)
					break;
#ifdef INET
				get_addrs(rtm->rtm_addrs, cp, rti_info);
				memset(&rt, 0, sizeof(rt));
				rt.iface = NULL;
				COPYOUT(rt.dest, rti_info[RTAX_DST]);
				COPYOUT(rt.net, rti_info[RTAX_NETMASK]);
				COPYOUT(rt.gate, rti_info[RTAX_GATEWAY]);
				ipv4_routedeleted(&rt);
#endif
				break;
#ifdef RTM_CHGADDR
			case RTM_CHGADDR:	/* FALLTHROUGH */
#endif
			case RTM_DELADDR:	/* FALLTHROUGH */
			case RTM_NEWADDR:
				ifam = (struct ifa_msghdr *)(void *)p;
				if (!if_indextoname(ifam->ifam_index, ifname))
					break;
				cp = (char *)(void *)(ifam + 1);
				get_addrs(ifam->ifam_addrs, cp, rti_info);
				if (rti_info[RTAX_IFA] == NULL)
					break;
				switch (rti_info[RTAX_IFA]->sa_family) {
				case AF_LINK:
#ifdef RTM_CHGADDR
					if (rtm->rtm_type != RTM_CHGADDR)
						break;
#else
					if (rtm->rtm_type != RTM_NEWADDR)
						break;
#endif
					memcpy(&sdl, rti_info[RTAX_IFA],
					    rti_info[RTAX_IFA]->sa_len);
					handle_hwaddr(ifname,
					    (const unsigned char*)CLLADDR(&sdl),
					    sdl.sdl_alen);
					break;
#ifdef INET
				case AF_INET:
				case 255: /* FIXME: Why 255? */
					COPYOUT(rt.dest, rti_info[RTAX_IFA]);
					COPYOUT(rt.net, rti_info[RTAX_NETMASK]);
					COPYOUT(rt.gate, rti_info[RTAX_BRD]);
					ipv4_handleifa(rtm->rtm_type,
					    NULL, ifname,
					    &rt.dest, &rt.net, &rt.gate);
					break;
#endif
#if defined(INET6) && !defined(LISTEN_DAD)
				case AF_INET6:
					sin6 = (struct sockaddr_in6*)(void *)
					    rti_info[RTAX_IFA];
					memcpy(ia6.s6_addr,
					    sin6->sin6_addr.s6_addr,
					    sizeof(ia6.s6_addr));
					if (rtm->rtm_type == RTM_NEWADDR) {
						ifa_flags = in6_addr_flags(
								ifname,
								&ia6);
						if (ifa_flags == -1)
							break;
					} else
						ifa_flags = 0;
					ipv6_handleifa(rtm->rtm_type, NULL,
					    ifname, &ia6, ifa_flags);
					break;
#endif
				}
				break;
			}
		}
	}
}
コード例 #11
0
ファイル: load_elf.c プロジェクト: alek-p/openzfs
int
__elfN(parse_modmetadata)(struct preloaded_file *fp, elf_file_t ef,
    Elf_Addr p_start, Elf_Addr p_end)
{
    struct mod_metadata md;
#if (defined(__i386__) || defined(__powerpc__)) && __ELF_WORD_SIZE == 64
    struct mod_metadata64 md64;
#elif defined(__amd64__) && __ELF_WORD_SIZE == 32
    struct mod_metadata32 md32;
#endif
    struct mod_depend *mdepend;
    struct mod_version mver;
    char *s;
    int error, modcnt, minfolen;
    Elf_Addr v, p;

    modcnt = 0;
    p = p_start;
    while (p < p_end) {
	COPYOUT(p, &v, sizeof(v));
	error = __elfN(reloc_ptr)(fp, ef, p, &v, sizeof(v));
	if (error == EOPNOTSUPP)
	    v += ef->off;
	else if (error != 0)
	    return (error);
#if (defined(__i386__) || defined(__powerpc__)) && __ELF_WORD_SIZE == 64
	COPYOUT(v, &md64, sizeof(md64));
	error = __elfN(reloc_ptr)(fp, ef, v, &md64, sizeof(md64));
	if (error == EOPNOTSUPP) {
	    md64.md_cval += ef->off;
	    md64.md_data += ef->off;
	} else if (error != 0)
	    return (error);
	md.md_version = md64.md_version;
	md.md_type = md64.md_type;
	md.md_cval = (const char *)(uintptr_t)md64.md_cval;
	md.md_data = (void *)(uintptr_t)md64.md_data;
#elif defined(__amd64__) && __ELF_WORD_SIZE == 32
	COPYOUT(v, &md32, sizeof(md32));
	error = __elfN(reloc_ptr)(fp, ef, v, &md32, sizeof(md32));
	if (error == EOPNOTSUPP) {
	    md32.md_cval += ef->off;
	    md32.md_data += ef->off;
	} else if (error != 0)
	    return (error);
	md.md_version = md32.md_version;
	md.md_type = md32.md_type;
	md.md_cval = (const char *)(uintptr_t)md32.md_cval;
	md.md_data = (void *)(uintptr_t)md32.md_data;
#else
	COPYOUT(v, &md, sizeof(md));
	error = __elfN(reloc_ptr)(fp, ef, v, &md, sizeof(md));
	if (error == EOPNOTSUPP) {
	    md.md_cval += ef->off;
	    md.md_data = (void *)((uintptr_t)md.md_data + (uintptr_t)ef->off);
	} else if (error != 0)
	    return (error);
#endif
	p += sizeof(Elf_Addr);
	switch(md.md_type) {
	  case MDT_DEPEND:
	    if (ef->kernel)		/* kernel must not depend on anything */
	      break;
	    s = strdupout((vm_offset_t)md.md_cval);
	    minfolen = sizeof(*mdepend) + strlen(s) + 1;
	    mdepend = malloc(minfolen);
	    if (mdepend == NULL)
		return ENOMEM;
	    COPYOUT((vm_offset_t)md.md_data, mdepend, sizeof(*mdepend));
	    strcpy((char*)(mdepend + 1), s);
	    free(s);
	    file_addmetadata(fp, MODINFOMD_DEPLIST, minfolen, mdepend);
	    free(mdepend);
	    break;
	  case MDT_VERSION:
	    s = strdupout((vm_offset_t)md.md_cval);
	    COPYOUT((vm_offset_t)md.md_data, &mver, sizeof(mver));
	    file_addmodule(fp, s, mver.mv_version, NULL);
	    free(s);
	    modcnt++;
	    break;
	}
    }
    if (modcnt == 0) {
	s = fake_modname(fp->f_name);
	file_addmodule(fp, s, 1, NULL);
	free(s);
    }
    return 0;
}
コード例 #12
0
ファイル: load_elf.c プロジェクト: alek-p/openzfs
/*
 * With the file (fd) open on the image, and (ehdr) containing
 * the Elf header, load the image at (off)
 */
static int
__elfN(loadimage)(struct preloaded_file *fp, elf_file_t ef, u_int64_t off)
{
    int 	i;
    u_int	j;
    Elf_Ehdr	*ehdr;
    Elf_Phdr	*phdr, *php;
    Elf_Shdr	*shdr;
    char	*shstr;
    int		ret;
    vm_offset_t firstaddr;
    vm_offset_t lastaddr;
    size_t	chunk;
    ssize_t	result;
    Elf_Addr	ssym, esym;
    Elf_Dyn	*dp;
    Elf_Addr	adp;
    Elf_Addr	ctors;
    int		ndp;
    int		symstrindex;
    int		symtabindex;
    Elf_Size	size;
    u_int	fpcopy;
    Elf_Sym	sym;
    Elf_Addr	p_start, p_end;

    dp = NULL;
    shdr = NULL;
    ret = 0;
    firstaddr = lastaddr = 0;
    ehdr = ef->ehdr;
    if (ehdr->e_type == ET_EXEC) {
#if defined(__i386__) || defined(__amd64__)
#if __ELF_WORD_SIZE == 64
	off = - (off & 0xffffffffff000000ull);/* x86_64 relocates after locore */
#else
	off = - (off & 0xff000000u);	/* i386 relocates after locore */
#endif
#elif defined(__powerpc__)
	/*
	 * On the purely virtual memory machines like e500, the kernel is
	 * linked against its final VA range, which is most often not
	 * available at the loader stage, but only after kernel initializes
	 * and completes its VM settings. In such cases we cannot use p_vaddr
	 * field directly to load ELF segments, but put them at some
	 * 'load-time' locations.
	 */
	if (off & 0xf0000000u) {
	    off = -(off & 0xf0000000u);
	    /*
	     * XXX the physical load address should not be hardcoded. Note
	     * that the Book-E kernel assumes that it's loaded at a 16MB
	     * boundary for now...
	     */
	    off += 0x01000000;
	    ehdr->e_entry += off;
#ifdef ELF_VERBOSE
	    printf("Converted entry 0x%08x\n", ehdr->e_entry);
#endif
	} else
	    off = 0;
#elif defined(__arm__) && !defined(EFI)
	/*
	 * The elf headers in arm kernels specify virtual addresses in all
	 * header fields, even the ones that should be physical addresses.
	 * We assume the entry point is in the first page, and masking the page
	 * offset will leave us with the virtual address the kernel was linked
	 * at.  We subtract that from the load offset, making 'off' into the
	 * value which, when added to a virtual address in an elf header,
	 * translates it to a physical address.  We do the va->pa conversion on
	 * the entry point address in the header now, so that later we can
	 * launch the kernel by just jumping to that address.
	 *
	 * When booting from UEFI the copyin and copyout functions handle
	 * adjusting the location relative to the first virtual address.
	 * Because of this there is no need to adjust the offset or entry
	 * point address as these will both be handled by the efi code.
	 */
	off -= ehdr->e_entry & ~PAGE_MASK;
	ehdr->e_entry += off;
#ifdef ELF_VERBOSE
	printf("ehdr->e_entry 0x%08x, va<->pa off %llx\n", ehdr->e_entry, off);
#endif
#else
	off = 0;		/* other archs use direct mapped kernels */
#endif
    }
    ef->off = off;

    if (ehdr->e_ident[EI_OSABI] == ELFOSABI_SOLARIS) {
	/* use entry address from header */
	fp->f_addr = ehdr->e_entry;
    }

    if (ef->kernel)
	__elfN(relocation_offset) = off;

    if ((ehdr->e_phoff + ehdr->e_phnum * sizeof(*phdr)) > ef->firstlen) {
	printf("elf" __XSTRING(__ELF_WORD_SIZE) "_loadimage: program header not within first page\n");
	goto out;
    }
    phdr = (Elf_Phdr *)(ef->firstpage + ehdr->e_phoff);

    for (i = 0; i < ehdr->e_phnum; i++) {
	/* We want to load PT_LOAD segments only.. */
	if (phdr[i].p_type != PT_LOAD)
	    continue;

#ifdef ELF_VERBOSE
	if (ehdr->e_ident[EI_OSABI] == ELFOSABI_SOLARIS) {
	    printf("Segment: 0x%lx@0x%lx -> 0x%lx-0x%lx",
		(long)phdr[i].p_filesz, (long)phdr[i].p_offset,
		(long)(phdr[i].p_paddr + off),
		(long)(phdr[i].p_paddr + off + phdr[i].p_memsz - 1));
	} else {
	    printf("Segment: 0x%lx@0x%lx -> 0x%lx-0x%lx",
		(long)phdr[i].p_filesz, (long)phdr[i].p_offset,
		(long)(phdr[i].p_vaddr + off),
		(long)(phdr[i].p_vaddr + off + phdr[i].p_memsz - 1));
	}
#else
	if ((phdr[i].p_flags & PF_W) == 0) {
	    printf("text=0x%lx ", (long)phdr[i].p_filesz);
	} else {
	    printf("data=0x%lx", (long)phdr[i].p_filesz);
	    if (phdr[i].p_filesz < phdr[i].p_memsz)
		printf("+0x%lx", (long)(phdr[i].p_memsz -phdr[i].p_filesz));
	    printf(" ");
	}
#endif
	fpcopy = 0;
	if (ef->firstlen > phdr[i].p_offset) {
	    fpcopy = ef->firstlen - phdr[i].p_offset;
	    if (ehdr->e_ident[EI_OSABI] == ELFOSABI_SOLARIS) {
		archsw.arch_copyin(ef->firstpage + phdr[i].p_offset,
		    phdr[i].p_paddr + off, fpcopy);
	    } else {
		archsw.arch_copyin(ef->firstpage + phdr[i].p_offset,
		    phdr[i].p_vaddr + off, fpcopy);
	    }
	}
	if (phdr[i].p_filesz > fpcopy) {
	    if (ehdr->e_ident[EI_OSABI] == ELFOSABI_SOLARIS) {
		if (kern_pread(ef->fd, phdr[i].p_paddr + off + fpcopy,
		    phdr[i].p_filesz - fpcopy,
		    phdr[i].p_offset + fpcopy) != 0) {
			printf("\nelf" __XSTRING(__ELF_WORD_SIZE)
			    "_loadimage: read failed\n");
			goto out;
		}
	    } else {
		if (kern_pread(ef->fd, phdr[i].p_vaddr + off + fpcopy,
		    phdr[i].p_filesz - fpcopy,
		    phdr[i].p_offset + fpcopy) != 0) {
			printf("\nelf" __XSTRING(__ELF_WORD_SIZE)
			    "_loadimage: read failed\n");
			goto out;
		}
	    }
	}
	/* clear space from oversized segments; eg: bss */
	if (phdr[i].p_filesz < phdr[i].p_memsz) {
#ifdef ELF_VERBOSE
	    if (ehdr->e_ident[EI_OSABI] == ELFOSABI_SOLARIS) {
		printf(" (bss: 0x%lx-0x%lx)",
		    (long)(phdr[i].p_paddr + off + phdr[i].p_filesz),
		    (long)(phdr[i].p_paddr + off + phdr[i].p_memsz - 1));
	    } else {
		printf(" (bss: 0x%lx-0x%lx)",
		    (long)(phdr[i].p_vaddr + off + phdr[i].p_filesz),
		    (long)(phdr[i].p_vaddr + off + phdr[i].p_memsz - 1));
	    }
#endif

	    if (ehdr->e_ident[EI_OSABI] == ELFOSABI_SOLARIS) {
		kern_bzero(phdr[i].p_paddr + off + phdr[i].p_filesz,
		    phdr[i].p_memsz - phdr[i].p_filesz);
	    } else {
		kern_bzero(phdr[i].p_vaddr + off + phdr[i].p_filesz,
		    phdr[i].p_memsz - phdr[i].p_filesz);
	    }
	}
#ifdef ELF_VERBOSE
	printf("\n");
#endif

	if (archsw.arch_loadseg != NULL)
	    archsw.arch_loadseg(ehdr, phdr + i, off);

	if (ehdr->e_ident[EI_OSABI] == ELFOSABI_SOLARIS) {
		if (firstaddr == 0 || firstaddr > (phdr[i].p_paddr + off))
		    firstaddr = phdr[i].p_paddr + off;
		if (lastaddr == 0 ||
		    lastaddr < (phdr[i].p_paddr + off + phdr[i].p_memsz))
		    lastaddr = phdr[i].p_paddr + off + phdr[i].p_memsz;
	} else {
		if (firstaddr == 0 || firstaddr > (phdr[i].p_vaddr + off))
		    firstaddr = phdr[i].p_vaddr + off;
		if (lastaddr == 0 ||
		    lastaddr < (phdr[i].p_vaddr + off + phdr[i].p_memsz))
		    lastaddr = phdr[i].p_vaddr + off + phdr[i].p_memsz;
	}
    }
    lastaddr = roundup(lastaddr, sizeof(long));

    /*
     * Get the section headers.  We need this for finding the .ctors
     * section as well as for loading any symbols.  Both may be hard
     * to do if reading from a .gz file as it involves seeking.  I
     * think the rule is going to have to be that you must strip a
     * file to remove symbols before gzipping it.
     */
    chunk = ehdr->e_shnum * ehdr->e_shentsize;
    if (chunk == 0 || ehdr->e_shoff == 0)
	goto nosyms;
    shdr = alloc_pread(ef->fd, ehdr->e_shoff, chunk);
    if (shdr == NULL) {
	printf("\nelf" __XSTRING(__ELF_WORD_SIZE)
	    "_loadimage: failed to read section headers");
	goto nosyms;
    }
    file_addmetadata(fp, MODINFOMD_SHDR, chunk, shdr);

    /*
     * Read the section string table and look for the .ctors section.
     * We need to tell the kernel where it is so that it can call the
     * ctors.
     */
    chunk = shdr[ehdr->e_shstrndx].sh_size;
    if (chunk) {
	shstr = alloc_pread(ef->fd, shdr[ehdr->e_shstrndx].sh_offset, chunk);
	if (shstr) {
	    for (i = 0; i < ehdr->e_shnum; i++) {
		if (strcmp(shstr + shdr[i].sh_name, ".ctors") != 0)
		    continue;
		ctors = shdr[i].sh_addr;
		file_addmetadata(fp, MODINFOMD_CTORS_ADDR, sizeof(ctors),
		    &ctors);
		size = shdr[i].sh_size;
		file_addmetadata(fp, MODINFOMD_CTORS_SIZE, sizeof(size),
		    &size);
		break;
	    }
	    free(shstr);
	}
    }

    /*
     * Now load any symbols.
     */
    symtabindex = -1;
    symstrindex = -1;
    for (i = 0; i < ehdr->e_shnum; i++) {
	if (shdr[i].sh_type != SHT_SYMTAB)
	    continue;
	for (j = 0; j < ehdr->e_phnum; j++) {
	    if (phdr[j].p_type != PT_LOAD)
		continue;
	    if (shdr[i].sh_offset >= phdr[j].p_offset &&
		(shdr[i].sh_offset + shdr[i].sh_size <=
		 phdr[j].p_offset + phdr[j].p_filesz)) {
		shdr[i].sh_offset = 0;
		shdr[i].sh_size = 0;
		break;
	    }
	}
	if (shdr[i].sh_offset == 0 || shdr[i].sh_size == 0)
	    continue;		/* alread loaded in a PT_LOAD above */
	/* Save it for loading below */
	symtabindex = i;
	symstrindex = shdr[i].sh_link;
    }
    if (symtabindex < 0 || symstrindex < 0)
	goto nosyms;

    /* Ok, committed to a load. */
#ifndef ELF_VERBOSE
    printf("syms=[");
#endif
    ssym = lastaddr;
    for (i = symtabindex; i >= 0; i = symstrindex) {
#ifdef ELF_VERBOSE
	char	*secname;

	switch(shdr[i].sh_type) {
	    case SHT_SYMTAB:		/* Symbol table */
		secname = "symtab";
		break;
	    case SHT_STRTAB:		/* String table */
		secname = "strtab";
		break;
	    default:
		secname = "WHOA!!";
		break;
	}
#endif

	size = shdr[i].sh_size;
	archsw.arch_copyin(&size, lastaddr, sizeof(size));
	lastaddr += sizeof(size);

#ifdef ELF_VERBOSE
	printf("\n%s: 0x%jx@0x%jx -> 0x%jx-0x%jx", secname,
	    (uintmax_t)shdr[i].sh_size, (uintmax_t)shdr[i].sh_offset,
	    (uintmax_t)lastaddr, (uintmax_t)(lastaddr + shdr[i].sh_size));
#else
	if (i == symstrindex)
	    printf("+");
	printf("0x%lx+0x%lx", (long)sizeof(size), (long)size);
#endif

	if (lseek(ef->fd, (off_t)shdr[i].sh_offset, SEEK_SET) == -1) {
	    printf("\nelf" __XSTRING(__ELF_WORD_SIZE) "_loadimage: could not seek for symbols - skipped!");
	    lastaddr = ssym;
	    ssym = 0;
	    goto nosyms;
	}
	result = archsw.arch_readin(ef->fd, lastaddr, shdr[i].sh_size);
	if (result < 0 || (size_t)result != shdr[i].sh_size) {
	    printf("\nelf" __XSTRING(__ELF_WORD_SIZE) "_loadimage: could not read symbols - skipped! (%ju != %ju)", (uintmax_t)result,
		(uintmax_t)shdr[i].sh_size);
	    lastaddr = ssym;
	    ssym = 0;
	    goto nosyms;
	}
	/* Reset offsets relative to ssym */
	lastaddr += shdr[i].sh_size;
	lastaddr = roundup(lastaddr, sizeof(size));
	if (i == symtabindex)
	    symtabindex = -1;
	else if (i == symstrindex)
	    symstrindex = -1;
    }
    esym = lastaddr;
#ifndef ELF_VERBOSE
    printf("]");
#endif

    file_addmetadata(fp, MODINFOMD_SSYM, sizeof(ssym), &ssym);
    file_addmetadata(fp, MODINFOMD_ESYM, sizeof(esym), &esym);

nosyms:
    printf("\n");

    ret = lastaddr - firstaddr;
    if (ehdr->e_ident[EI_OSABI] != ELFOSABI_SOLARIS)
	fp->f_addr = firstaddr;

    php = NULL;
    for (i = 0; i < ehdr->e_phnum; i++) {
	if (phdr[i].p_type == PT_DYNAMIC) {
	    php = phdr + i;
	    adp = php->p_vaddr;
	    file_addmetadata(fp, MODINFOMD_DYNAMIC, sizeof(adp), &adp);
	    break;
	}
    }

    if (php == NULL)	/* this is bad, we cannot get to symbols or _DYNAMIC */
	goto out;

    ndp = php->p_filesz / sizeof(Elf_Dyn);
    if (ndp == 0)
	goto out;
    dp = malloc(php->p_filesz);
    if (dp == NULL)
	goto out;
    if (ehdr->e_ident[EI_OSABI] == ELFOSABI_SOLARIS)
	archsw.arch_copyout(php->p_paddr + off, dp, php->p_filesz);
    else
	archsw.arch_copyout(php->p_vaddr + off, dp, php->p_filesz);

    ef->strsz = 0;
    for (i = 0; i < ndp; i++) {
	if (dp[i].d_tag == 0)
	    break;
	switch (dp[i].d_tag) {
	case DT_HASH:
	    ef->hashtab = (Elf_Hashelt*)(uintptr_t)(dp[i].d_un.d_ptr + off);
	    break;
	case DT_STRTAB:
	    ef->strtab = (char *)(uintptr_t)(dp[i].d_un.d_ptr + off);
	    break;
	case DT_STRSZ:
	    ef->strsz = dp[i].d_un.d_val;
	    break;
	case DT_SYMTAB:
	    ef->symtab = (Elf_Sym*)(uintptr_t)(dp[i].d_un.d_ptr + off);
	    break;
	case DT_REL:
	    ef->rel = (Elf_Rel *)(uintptr_t)(dp[i].d_un.d_ptr + off);
	    break;
	case DT_RELSZ:
	    ef->relsz = dp[i].d_un.d_val;
	    break;
	case DT_RELA:
	    ef->rela = (Elf_Rela *)(uintptr_t)(dp[i].d_un.d_ptr + off);
	    break;
	case DT_RELASZ:
	    ef->relasz = dp[i].d_un.d_val;
	    break;
	default:
	    break;
	}
    }
    if (ef->hashtab == NULL || ef->symtab == NULL ||
	ef->strtab == NULL || ef->strsz == 0)
	goto out;
    COPYOUT(ef->hashtab, &ef->nbuckets, sizeof(ef->nbuckets));
    COPYOUT(ef->hashtab + 1, &ef->nchains, sizeof(ef->nchains));
    ef->buckets = ef->hashtab + 2;
    ef->chains = ef->buckets + ef->nbuckets;

    if (__elfN(lookup_symbol)(fp, ef, "__start_set_modmetadata_set", &sym) != 0)
	return 0;
    p_start = sym.st_value + ef->off;
    if (__elfN(lookup_symbol)(fp, ef, "__stop_set_modmetadata_set", &sym) != 0)
	return ENOENT;
    p_end = sym.st_value + ef->off;

    if (__elfN(parse_modmetadata)(fp, ef, p_start, p_end) == 0)
	goto out;

    if (ef->kernel)			/* kernel must not depend on anything */
	goto out;

out:
    if (dp)
	free(dp);
    if (shdr)
	free(shdr);
    return ret;
}
コード例 #13
0
ファイル: fdt_loader_cmd.c プロジェクト: Lxg1582/freebsd
static vm_offset_t
fdt_find_static_dtb()
{
	Elf_Ehdr *ehdr;
	Elf_Shdr *shdr;
	Elf_Sym sym;
	vm_offset_t strtab, symtab, fdt_start;
	uint64_t offs;
	struct preloaded_file *kfp;
	struct file_metadata *md;
	char *strp;
	int i, sym_count;

	debugf("fdt_find_static_dtb()\n");

	sym_count = symtab = strtab = 0;
	strp = NULL;

	offs = __elfN(relocation_offset);

	kfp = file_findfile(NULL, NULL);
	if (kfp == NULL)
		return (0);

	/* Locate the dynamic symbols and strtab. */
	md = file_findmetadata(kfp, MODINFOMD_ELFHDR);
	if (md == NULL)
		return (0);
	ehdr = (Elf_Ehdr *)md->md_data;

	md = file_findmetadata(kfp, MODINFOMD_SHDR);
	if (md == NULL)
		return (0);
	shdr = (Elf_Shdr *)md->md_data;

	for (i = 0; i < ehdr->e_shnum; ++i) {
		if (shdr[i].sh_type == SHT_DYNSYM && symtab == 0) {
			symtab = shdr[i].sh_addr + offs;
			sym_count = shdr[i].sh_size / sizeof(Elf_Sym);
		} else if (shdr[i].sh_type == SHT_STRTAB && strtab == 0) {
			strtab = shdr[i].sh_addr + offs;
		}
	}

	/*
	 * The most efficent way to find a symbol would be to calculate a
	 * hash, find proper bucket and chain, and thus find a symbol.
	 * However, that would involve code duplication (e.g. for hash
	 * function). So we're using simpler and a bit slower way: we're
	 * iterating through symbols, searching for the one which name is
	 * 'equal' to 'fdt_static_dtb'. To speed up the process a little bit,
	 * we are eliminating symbols type of which is not STT_NOTYPE, or(and)
	 * those which binding attribute is not STB_GLOBAL.
	 */
	fdt_start = 0;
	while (sym_count > 0 && fdt_start == 0) {
		COPYOUT(symtab, &sym, sizeof(sym));
		symtab += sizeof(sym);
		--sym_count;
		if (ELF_ST_BIND(sym.st_info) != STB_GLOBAL ||
		    ELF_ST_TYPE(sym.st_info) != STT_NOTYPE)
			continue;
		strp = strdupout(strtab + sym.st_name);
		if (strcmp(strp, FDT_STATIC_DTB_SYMBOL) == 0)
			fdt_start = (vm_offset_t)sym.st_value + offs;
		free(strp);
	}
	return (fdt_start);
}
コード例 #14
0
/*
 * With the file (fd) open on the image, and (ehdr) containing
 * the Elf header, load the image at (off)
 */
static int
__elfN(loadimage)(struct preloaded_file *fp, elf_file_t ef, u_int64_t off)
{
    int 	i;
    u_int	j;
    Elf_Ehdr	*ehdr;
    Elf_Phdr	*phdr, *php;
    Elf_Shdr	*shdr;
    int		ret;
    vm_offset_t firstaddr;
    vm_offset_t lastaddr;
    size_t	chunk;
    ssize_t	result;
    Elf_Addr	ssym, esym;
    Elf_Dyn	*dp;
    Elf_Addr	adp;
    int		ndp;
    int		symstrindex;
    int		symtabindex;
    Elf_Size	size;
    u_int	fpcopy;

    dp = NULL;
    shdr = NULL;
    ret = 0;
    firstaddr = lastaddr = 0;
    ehdr = ef->ehdr;
    if (ef->kernel) {
#if defined(__i386__) || defined(__amd64__)
#if __ELF_WORD_SIZE == 64
	off = - (off & 0xffffffffff000000ull);/* x86_64 relocates after locore */
#else
	off = - (off & 0xff000000u);	/* i386 relocates after locore */
#endif
#elif defined(__powerpc__)
	/*
	 * On the purely virtual memory machines like e500, the kernel is
	 * linked against its final VA range, which is most often not
	 * available at the loader stage, but only after kernel initializes
	 * and completes its VM settings. In such cases we cannot use p_vaddr
	 * field directly to load ELF segments, but put them at some
	 * 'load-time' locations.
	 */
	if (off & 0xf0000000u) {
	    off = -(off & 0xf0000000u);
	    /*
	     * XXX the physical load address should not be hardcoded. Note
	     * that the Book-E kernel assumes that it's loaded at a 16MB
	     * boundary for now...
	     */
	    off += 0x01000000;
	    ehdr->e_entry += off;
#ifdef ELF_VERBOSE
	    printf("Converted entry 0x%08x\n", ehdr->e_entry);
#endif
	} else
	    off = 0;
#elif defined(__arm__)
	/*
	 * The elf headers in some kernels specify virtual addresses in all
	 * header fields.  More recently, the e_entry and p_paddr fields are the
	 * proper physical addresses.  Even when the p_paddr fields are correct,
	 * the MI code below uses the p_vaddr fields with an offset added for
	 * loading (doing so is arguably wrong).  To make loading work, we need
	 * an offset that represents the difference between physical and virtual
	 * addressing.  ARM kernels are always linked at 0xCnnnnnnn.  Depending
	 * on the headers, the offset value passed in may be physical or virtual
	 * (because it typically comes from e_entry), but we always replace
	 * whatever is passed in with the va<->pa offset.  On the other hand, we
	 * always remove the high-order part of the entry address whether it's
	 * physical or virtual, because it will be adjusted later for the actual
	 * physical entry point based on where the image gets loaded.
	 */
	off = -0xc0000000;
	ehdr->e_entry &= ~0xf0000000;
#ifdef ELF_VERBOSE
	printf("ehdr->e_entry 0x%08x, va<->pa off %llx\n", ehdr->e_entry, off);
#endif
#else
	off = 0;		/* other archs use direct mapped kernels */
#endif
	__elfN(relocation_offset) = off;
    }
    ef->off = off;

    if ((ehdr->e_phoff + ehdr->e_phnum * sizeof(*phdr)) > ef->firstlen) {
	printf("elf" __XSTRING(__ELF_WORD_SIZE) "_loadimage: program header not within first page\n");
	goto out;
    }
    phdr = (Elf_Phdr *)(ef->firstpage + ehdr->e_phoff);

    for (i = 0; i < ehdr->e_phnum; i++) {
	/* We want to load PT_LOAD segments only.. */
	if (phdr[i].p_type != PT_LOAD)
	    continue;

#ifdef ELF_VERBOSE
	printf("Segment: 0x%lx@0x%lx -> 0x%lx-0x%lx",
	    (long)phdr[i].p_filesz, (long)phdr[i].p_offset,
	    (long)(phdr[i].p_vaddr + off),
	    (long)(phdr[i].p_vaddr + off + phdr[i].p_memsz - 1));
#else
	if ((phdr[i].p_flags & PF_W) == 0) {
	    printf("text=0x%lx ", (long)phdr[i].p_filesz);
	} else {
	    printf("data=0x%lx", (long)phdr[i].p_filesz);
	    if (phdr[i].p_filesz < phdr[i].p_memsz)
		printf("+0x%lx", (long)(phdr[i].p_memsz -phdr[i].p_filesz));
	    printf(" ");
	}
#endif
	fpcopy = 0;
	if (ef->firstlen > phdr[i].p_offset) {
	    fpcopy = ef->firstlen - phdr[i].p_offset;
	    archsw.arch_copyin(ef->firstpage + phdr[i].p_offset,
			       phdr[i].p_vaddr + off, fpcopy);
	}
	if (phdr[i].p_filesz > fpcopy) {
	    if (kern_pread(ef->fd, phdr[i].p_vaddr + off + fpcopy,
		phdr[i].p_filesz - fpcopy, phdr[i].p_offset + fpcopy) != 0) {
		printf("\nelf" __XSTRING(__ELF_WORD_SIZE)
		    "_loadimage: read failed\n");
		goto out;
	    }
	}
	/* clear space from oversized segments; eg: bss */
	if (phdr[i].p_filesz < phdr[i].p_memsz) {
#ifdef ELF_VERBOSE
	    printf(" (bss: 0x%lx-0x%lx)",
		(long)(phdr[i].p_vaddr + off + phdr[i].p_filesz),
		(long)(phdr[i].p_vaddr + off + phdr[i].p_memsz - 1));
#endif

	    kern_bzero(phdr[i].p_vaddr + off + phdr[i].p_filesz,
		phdr[i].p_memsz - phdr[i].p_filesz);
	}
#ifdef ELF_VERBOSE
	printf("\n");
#endif

	if (archsw.arch_loadseg != NULL)
	    archsw.arch_loadseg(ehdr, phdr + i, off);

	if (firstaddr == 0 || firstaddr > (phdr[i].p_vaddr + off))
	    firstaddr = phdr[i].p_vaddr + off;
	if (lastaddr == 0 || lastaddr < (phdr[i].p_vaddr + off + phdr[i].p_memsz))
	    lastaddr = phdr[i].p_vaddr + off + phdr[i].p_memsz;
    }
    lastaddr = roundup(lastaddr, sizeof(long));

    /*
     * Now grab the symbol tables.  This isn't easy if we're reading a
     * .gz file.  I think the rule is going to have to be that you must
     * strip a file to remove symbols before gzipping it so that we do not
     * try to lseek() on it.
     */
    chunk = ehdr->e_shnum * ehdr->e_shentsize;
    if (chunk == 0 || ehdr->e_shoff == 0)
	goto nosyms;
    shdr = alloc_pread(ef->fd, ehdr->e_shoff, chunk);
    if (shdr == NULL) {
	printf("\nelf" __XSTRING(__ELF_WORD_SIZE)
	    "_loadimage: failed to read section headers");
	goto nosyms;
    }
    file_addmetadata(fp, MODINFOMD_SHDR, chunk, shdr);

    symtabindex = -1;
    symstrindex = -1;
    for (i = 0; i < ehdr->e_shnum; i++) {
	if (shdr[i].sh_type != SHT_SYMTAB)
	    continue;
	for (j = 0; j < ehdr->e_phnum; j++) {
	    if (phdr[j].p_type != PT_LOAD)
		continue;
	    if (shdr[i].sh_offset >= phdr[j].p_offset &&
		(shdr[i].sh_offset + shdr[i].sh_size <=
		 phdr[j].p_offset + phdr[j].p_filesz)) {
		shdr[i].sh_offset = 0;
		shdr[i].sh_size = 0;
		break;
	    }
	}
	if (shdr[i].sh_offset == 0 || shdr[i].sh_size == 0)
	    continue;		/* alread loaded in a PT_LOAD above */
	/* Save it for loading below */
	symtabindex = i;
	symstrindex = shdr[i].sh_link;
    }
    if (symtabindex < 0 || symstrindex < 0)
	goto nosyms;

    /* Ok, committed to a load. */
#ifndef ELF_VERBOSE
    printf("syms=[");
#endif
    ssym = lastaddr;
    for (i = symtabindex; i >= 0; i = symstrindex) {
#ifdef ELF_VERBOSE
	char	*secname;

	switch(shdr[i].sh_type) {
	    case SHT_SYMTAB:		/* Symbol table */
		secname = "symtab";
		break;
	    case SHT_STRTAB:		/* String table */
		secname = "strtab";
		break;
	    default:
		secname = "WHOA!!";
		break;
	}
#endif

	size = shdr[i].sh_size;
	archsw.arch_copyin(&size, lastaddr, sizeof(size));
	lastaddr += sizeof(size);

#ifdef ELF_VERBOSE
	printf("\n%s: 0x%jx@0x%jx -> 0x%jx-0x%jx", secname,
	    (uintmax_t)shdr[i].sh_size, (uintmax_t)shdr[i].sh_offset,
	    (uintmax_t)lastaddr, (uintmax_t)(lastaddr + shdr[i].sh_size));
#else
	if (i == symstrindex)
	    printf("+");
	printf("0x%lx+0x%lx", (long)sizeof(size), (long)size);
#endif

	if (lseek(ef->fd, (off_t)shdr[i].sh_offset, SEEK_SET) == -1) {
	    printf("\nelf" __XSTRING(__ELF_WORD_SIZE) "_loadimage: could not seek for symbols - skipped!");
	    lastaddr = ssym;
	    ssym = 0;
	    goto nosyms;
	}
	result = archsw.arch_readin(ef->fd, lastaddr, shdr[i].sh_size);
	if (result < 0 || (size_t)result != shdr[i].sh_size) {
	    printf("\nelf" __XSTRING(__ELF_WORD_SIZE) "_loadimage: could not read symbols - skipped! (%ju != %ju)", (uintmax_t)result,
		(uintmax_t)shdr[i].sh_size);
	    lastaddr = ssym;
	    ssym = 0;
	    goto nosyms;
	}
	/* Reset offsets relative to ssym */
	lastaddr += shdr[i].sh_size;
	lastaddr = roundup(lastaddr, sizeof(size));
	if (i == symtabindex)
	    symtabindex = -1;
	else if (i == symstrindex)
	    symstrindex = -1;
    }
    esym = lastaddr;
#ifndef ELF_VERBOSE
    printf("]");
#endif

    file_addmetadata(fp, MODINFOMD_SSYM, sizeof(ssym), &ssym);
    file_addmetadata(fp, MODINFOMD_ESYM, sizeof(esym), &esym);

nosyms:
    printf("\n");

    ret = lastaddr - firstaddr;
    fp->f_addr = firstaddr;

    php = NULL;
    for (i = 0; i < ehdr->e_phnum; i++) {
	if (phdr[i].p_type == PT_DYNAMIC) {
	    php = phdr + i;
	    adp = php->p_vaddr;
	    file_addmetadata(fp, MODINFOMD_DYNAMIC, sizeof(adp), &adp);
	    break;
	}
    }

    if (php == NULL)	/* this is bad, we cannot get to symbols or _DYNAMIC */
	goto out;

    ndp = php->p_filesz / sizeof(Elf_Dyn);
    if (ndp == 0)
	goto out;
    dp = malloc(php->p_filesz);
    if (dp == NULL)
	goto out;
    archsw.arch_copyout(php->p_vaddr + off, dp, php->p_filesz);

    ef->strsz = 0;
    for (i = 0; i < ndp; i++) {
	if (dp[i].d_tag == 0)
	    break;
	switch (dp[i].d_tag) {
	case DT_HASH:
	    ef->hashtab = (Elf_Hashelt*)(uintptr_t)(dp[i].d_un.d_ptr + off);
	    break;
	case DT_STRTAB:
	    ef->strtab = (char *)(uintptr_t)(dp[i].d_un.d_ptr + off);
	    break;
	case DT_STRSZ:
	    ef->strsz = dp[i].d_un.d_val;
	    break;
	case DT_SYMTAB:
	    ef->symtab = (Elf_Sym*)(uintptr_t)(dp[i].d_un.d_ptr + off);
	    break;
	case DT_REL:
	    ef->rel = (Elf_Rel *)(uintptr_t)(dp[i].d_un.d_ptr + off);
	    break;
	case DT_RELSZ:
	    ef->relsz = dp[i].d_un.d_val;
	    break;
	case DT_RELA:
	    ef->rela = (Elf_Rela *)(uintptr_t)(dp[i].d_un.d_ptr + off);
	    break;
	case DT_RELASZ:
	    ef->relasz = dp[i].d_un.d_val;
	    break;
	default:
	    break;
	}
    }
    if (ef->hashtab == NULL || ef->symtab == NULL ||
	ef->strtab == NULL || ef->strsz == 0)
	goto out;
    COPYOUT(ef->hashtab, &ef->nbuckets, sizeof(ef->nbuckets));
    COPYOUT(ef->hashtab + 1, &ef->nchains, sizeof(ef->nchains));
    ef->buckets = ef->hashtab + 2;
    ef->chains = ef->buckets + ef->nbuckets;
    if (__elfN(parse_modmetadata)(fp, ef) == 0)
	goto out;

    if (ef->kernel)			/* kernel must not depend on anything */
	goto out;

out:
    if (dp)
	free(dp);
    if (shdr)
	free(shdr);
    return ret;
}
コード例 #15
0
ファイル: if-bsd.c プロジェクト: RsrchBoy/dpkg-dhcpcd5
int
if_managelink(struct dhcpcd_ctx *ctx)
{
	/* route and ifwatchd like a msg buf size of 2048 */
	char msg[2048], *p, *e, *cp;
	ssize_t bytes;
	struct rt_msghdr *rtm;
	struct if_announcemsghdr *ifan;
	struct if_msghdr *ifm;
	struct ifa_msghdr *ifam;
	struct sockaddr *sa, *rti_info[RTAX_MAX];
	int len;
	struct sockaddr_dl sdl;
	struct interface *ifp;
#ifdef INET
	struct rt rt;
#endif
#ifdef INET6
	struct rt6 rt6;
	struct in6_addr ia6;
	struct sockaddr_in6 *sin6;
	int ifa_flags;
#endif

	bytes = read(ctx->link_fd, msg, sizeof(msg));
	if (bytes == -1)
		return -1;
	if (bytes == 0)
		return 0;
	e = msg + bytes;
	for (p = msg; p < e; p += rtm->rtm_msglen) {
		rtm = (struct rt_msghdr *)(void *)p;
		// Ignore messages generated by us
		if (rtm->rtm_pid == getpid())
			break;
		switch(rtm->rtm_type) {
#ifdef RTM_IFANNOUNCE
		case RTM_IFANNOUNCE:
			ifan = (struct if_announcemsghdr *)(void *)p;
			switch(ifan->ifan_what) {
			case IFAN_ARRIVAL:
				dhcpcd_handleinterface(ctx, 1,
				    ifan->ifan_name);
				break;
			case IFAN_DEPARTURE:
				dhcpcd_handleinterface(ctx, -1,
				    ifan->ifan_name);
				break;
			}
			break;
#endif
		case RTM_IFINFO:
			ifm = (struct if_msghdr *)(void *)p;
			if ((ifp = if_findindex(ctx, ifm->ifm_index)) == NULL)
				break;
			switch (ifm->ifm_data.ifi_link_state) {
			case LINK_STATE_DOWN:
				len = LINK_DOWN;
				break;
			case LINK_STATE_UP:
				len = LINK_UP;
				break;
			default:
				/* handle_carrier will re-load
				 * the interface flags and check for
				 * IFF_RUNNING as some drivers that
				 * don't handle link state also don't
				 * set IFF_RUNNING when this routing
				 * message is generated.
				 * As such, it is a race ...*/
				len = LINK_UNKNOWN;
				break;
			}
			dhcpcd_handlecarrier(ctx, len,
			    (unsigned int)ifm->ifm_flags, ifp->name);
			break;
		case RTM_DELETE:
			if (~rtm->rtm_addrs &
			    (RTA_DST | RTA_GATEWAY | RTA_NETMASK))
				break;
			cp = (char *)(void *)(rtm + 1);
			sa = (struct sockaddr *)(void *)cp;
			get_addrs(rtm->rtm_addrs, cp, rti_info);
			switch (sa->sa_family) {
#ifdef INET
			case AF_INET:
				memset(&rt, 0, sizeof(rt));
				rt.iface = NULL;
				COPYOUT(rt.dest, rti_info[RTAX_DST]);
				COPYOUT(rt.net, rti_info[RTAX_NETMASK]);
				COPYOUT(rt.gate, rti_info[RTAX_GATEWAY]);
				ipv4_routedeleted(ctx, &rt);
				break;
#endif
#ifdef INET6
			case AF_INET6:
				memset(&rt6, 0, sizeof(rt6));
				rt6.iface = NULL;
				COPYOUT6(rt6.dest, rti_info[RTAX_DST]);
				COPYOUT6(rt6.net, rti_info[RTAX_NETMASK]);
				COPYOUT6(rt6.gate, rti_info[RTAX_GATEWAY]);
				ipv6_routedeleted(ctx, &rt6);
				break;
#endif
			}
#ifdef RTM_CHGADDR
		case RTM_CHGADDR:	/* FALLTHROUGH */
#endif
		case RTM_DELADDR:	/* FALLTHROUGH */
		case RTM_NEWADDR:
			ifam = (struct ifa_msghdr *)(void *)p;
			if ((ifp = if_findindex(ctx, ifam->ifam_index)) == NULL)
				break;
			cp = (char *)(void *)(ifam + 1);
			get_addrs(ifam->ifam_addrs, cp, rti_info);
			if (rti_info[RTAX_IFA] == NULL)
				break;
			switch (rti_info[RTAX_IFA]->sa_family) {
			case AF_LINK:
#ifdef RTM_CHGADDR
				if (rtm->rtm_type != RTM_CHGADDR)
					break;
#else
				if (rtm->rtm_type != RTM_NEWADDR)
					break;
#endif
				memcpy(&sdl, rti_info[RTAX_IFA],
				    rti_info[RTAX_IFA]->sa_len);
				dhcpcd_handlehwaddr(ctx, ifp->name,
				    (const unsigned char*)CLLADDR(&sdl),
				    sdl.sdl_alen);
				break;
#ifdef INET
			case AF_INET:
			case 255: /* FIXME: Why 255? */
				COPYOUT(rt.dest, rti_info[RTAX_IFA]);
				COPYOUT(rt.net, rti_info[RTAX_NETMASK]);
				COPYOUT(rt.gate, rti_info[RTAX_BRD]);
				ipv4_handleifa(ctx, rtm->rtm_type,
				    NULL, ifp->name,
				    &rt.dest, &rt.net, &rt.gate);
				break;
#endif
#ifdef INET6
			case AF_INET6:
				sin6 = (struct sockaddr_in6*)(void *)
				    rti_info[RTAX_IFA];
				ia6 = sin6->sin6_addr;
#ifdef __KAME__
				if (IN6_IS_ADDR_LINKLOCAL(&ia6))
					ia6.s6_addr[2] = ia6.s6_addr[3] = '\0';
#endif
				if (rtm->rtm_type == RTM_NEWADDR) {
					ifa_flags = if_addrflags6(&ia6, ifp);
					if (ifa_flags == -1)
						break;
				} else
					ifa_flags = 0;
				ipv6_handleifa(ctx, rtm->rtm_type, NULL,
				    ifp->name, &ia6, ifa_flags);
				break;
#endif
			}
			break;
		}
	}

	return 0;
}
コード例 #16
0
ファイル: mem_refcnt.c プロジェクト: dot-Sean/linux_kernels
/* ARGSUSED */
int
mem_refcnt_ioctl(devfs_handle_t dev,
                 int cmd,
                 void *arg,
                 int mode,
                 cred_t *cred_p,
                 int *rvalp)
{
        cnodeid_t node;
        int errcode;
	extern int numnodes;
        
        ASSERT( (hubspc_subdevice_t)(ulong)device_info_get(dev) == HUBSPC_REFCOUNTERS );

        node = master_node_get(dev);

        ASSERT( (node >= 0) && (node < numnodes) );

        ASSERT( NODEPDA(node)->migr_refcnt_counterbuffer != NULL);
        ASSERT( NODEPDA(node)->migr_refcnt_counterbase != NULL );
        ASSERT( NODEPDA(node)->migr_refcnt_cbsize != 0 );

        errcode = 0;
        
        switch (cmd) {
        case RCB_INFO_GET:
        {
                rcb_info_t rcb;
                
                rcb.rcb_len = NODEPDA(node)->migr_refcnt_cbsize;
                
                rcb.rcb_sw_sets = NODEPDA(node)->migr_refcnt_numsets;
                rcb.rcb_sw_counters_per_set = numnodes;
                rcb.rcb_sw_counter_size = sizeof(refcnt_t);

                rcb.rcb_base_pages = NODEPDA(node)->migr_refcnt_numsets /
                                     NUM_OF_HW_PAGES_PER_SW_PAGE();  
                rcb.rcb_base_page_size = NBPP;
                rcb.rcb_base_paddr = ctob(slot_getbasepfn(node, 0));
                
                rcb.rcb_cnodeid = node;
                rcb.rcb_granularity = MD_PAGE_SIZE;
#ifdef notyet
                rcb.rcb_hw_counter_max = MIGR_COUNTER_MAX_GET(node);
                rcb.rcb_diff_threshold = MIGR_THRESHOLD_DIFF_GET(node);
#endif
                rcb.rcb_abs_threshold = MIGR_THRESHOLD_ABS_GET(node);
                rcb.rcb_num_slots = node_getnumslots(node);

                if (COPYOUT(&rcb, arg, sizeof(rcb_info_t))) {
                        errcode = EFAULT;
                }

                break;
        }
        case RCB_SLOT_GET:
        {
                rcb_slot_t slot[MAX_MEM_SLOTS];
                int s;
                int nslots;

                nslots = node_getnumslots(node);
                ASSERT(nslots <= MAX_MEM_SLOTS);
                for (s = 0; s < nslots; s++) {
                        slot[s].base = (uint64_t)ctob(slot_getbasepfn(node, s));
#ifdef notyet
                        slot[s].size  = (uint64_t)ctob(slot_getsize(node, s));
#else
                        slot[s].size  = (uint64_t)1;
#endif
                }
                if (COPYOUT(&slot[0], arg, nslots * sizeof(rcb_slot_t))) {
                        errcode = EFAULT;
                }
                
                *rvalp = nslots;
                break;
        }
                
        default:
                errcode = EINVAL;
                break;

        }
        
        return errcode;
}