Esempio n. 1
0
/*
 * A simple relocator for IA32/AMD64 EFI binaries.
 */
EFI_STATUS
_reloc(unsigned long ImageBase, ElfW_Dyn *dynamic, EFI_HANDLE image_handle,
    EFI_SYSTEM_TABLE *system_table)
{
	unsigned long relsz, relent;
	unsigned long *newaddr;
	ElfW_Rel *rel;
	ElfW_Dyn *dynp;

	/*
	 * Find the relocation address, its size and the relocation entry.
	 */
	relsz = 0;
	relent = 0;
	for (dynp = dynamic; dynp->d_tag != DT_NULL; dynp++) {
		switch (dynp->d_tag) {
		case DT_REL:
		case DT_RELA:
			rel = (ElfW_Rel *) ((unsigned long) dynp->d_un.d_ptr +
			    ImageBase);
			break;
		case DT_RELSZ:
		case DT_RELASZ:
			relsz = dynp->d_un.d_val;
			break;
		case DT_RELENT:
		case DT_RELAENT:
			relent = dynp->d_un.d_val;
			break;
		default:
			break;
		}
	}

	/*
	 * Perform the actual relocation.
	 * XXX: We are reusing code for the amd64 version of this, but
	 * we must make sure the relocation types are the same.
	 */
	CTASSERT(R_386_NONE == R_X86_64_NONE);
	CTASSERT(R_386_RELATIVE == R_X86_64_RELATIVE);
	for (; relsz > 0; relsz -= relent) {
		switch (ELFW_R_TYPE(rel->r_info)) {
		case R_386_NONE:
			/* No relocation needs be performed. */
			break;
		case R_386_RELATIVE:
			/* Address relative to the base address. */
			newaddr = (unsigned long *)(ImageBase + rel->r_offset);
			*newaddr += ImageBase;
			break;
		default:
			/* XXX: do we need other relocations ? */
			break;
		}
		rel = (ElfW_Rel *) ((caddr_t) rel + relent);
	}

	return (EFI_SUCCESS);
}
Esempio n. 2
0
/*
 * A simple elf relocator.
 */
void
self_reloc(Elf_Addr baseaddr, ElfW_Dyn *dynamic)
{
	Elf_Word relsz, relent;
	Elf_Addr *newaddr;
	ElfW_Rel *rel = 0;
	ElfW_Dyn *dynp;

	/*
	 * Find the relocation address, its size and the relocation entry.
	 */
	relsz = 0;
	relent = 0;
	for (dynp = dynamic; dynp->d_tag != DT_NULL; dynp++) {
		switch (dynp->d_tag) {
		case DT_REL:
		case DT_RELA:
			rel = (ElfW_Rel *)(dynp->d_un.d_ptr + baseaddr);
			break;
		case DT_RELSZ:
		case DT_RELASZ:
			relsz = dynp->d_un.d_val;
			break;
		case DT_RELENT:
		case DT_RELAENT:
			relent = dynp->d_un.d_val;
			break;
		default:
			break;
		}
	}

	/*
	 * Perform the actual relocation. We rely on the object having been
	 * linked at 0, so that the difference between the load and link
	 * address is the same as the load address.
	 */
	for (; relsz > 0; relsz -= relent) {
		switch (ELFW_R_TYPE(rel->r_info)) {
		case RELOC_TYPE_NONE:
			/* No relocation needs be performed. */
			break;

		case RELOC_TYPE_RELATIVE:
			newaddr = (Elf_Addr *)(rel->r_offset + baseaddr);
#ifdef ELF_RELA
			/* Addend relative to the base address. */
			*newaddr = baseaddr + rel->r_addend;
#else
			/* Address relative to the base address. */
			*newaddr += baseaddr;
#endif
			break;
		default:
			/* XXX: do we need other relocations ? */
			break;
		}
		rel = (ElfW_Rel *)(void *)((caddr_t) rel + relent);
	}
}
Esempio n. 3
0
/*
 * A simple elf relocator.
 */
void
self_reloc(Elf_Addr baseaddr, ElfW_Dyn *dynamic)
{
	Elf_Word relsz, relent;
	Elf_Addr *newaddr;
	ElfW_Rel *rel = 0;
	ElfW_Dyn *dynp;

	/*
	 * Find the relocation address, its size and the relocation entry.
	 */
	relsz = 0;
	relent = 0;
	for (dynp = dynamic; dynp->d_tag != DT_NULL; dynp++) {
		switch (dynp->d_tag) {
		case DT_REL:
		case DT_RELA:
			rel = (ElfW_Rel *)(dynp->d_un.d_ptr + baseaddr);
			break;
		case DT_RELSZ:
		case DT_RELASZ:
			relsz = dynp->d_un.d_val;
			break;
		case DT_RELENT:
		case DT_RELAENT:
			relent = dynp->d_un.d_val;
			break;
		default:
			break;
		}
	}

	/*
	 * Perform the actual relocation.
	 */
	for (; relsz > 0; relsz -= relent) {
		switch (ELFW_R_TYPE(rel->r_info)) {
		case RELOC_TYPE_NONE:
			/* No relocation needs be performed. */
			break;

		case RELOC_TYPE_RELATIVE:
			/* Address relative to the base address. */
			newaddr = (Elf_Addr *)(rel->r_offset + baseaddr);
			*newaddr += baseaddr;
			/* Add the addend when the ABI uses them */ 
#ifdef ELF_RELA
			*newaddr += rel->r_addend;
#endif
			break;
		default:
			/* XXX: do we need other relocations ? */
			break;
		}
		rel = (ElfW_Rel *)(void *)((caddr_t) rel + relent);
	}
}
Esempio n. 4
0
/*
 * A simple elf relocator.
 */
void
self_reloc(Elf_Addr baseaddr, ElfW_Dyn *dynamic)
{
	Elf_Word relsz, relent;
	Elf_Addr *newaddr;
	ElfW_Rel *rel;
	ElfW_Dyn *dynp;

	/*
	 * Find the relocation address, its size and the relocation entry.
	 */
	relsz = 0;
	relent = 0;
	for (dynp = dynamic; dynp->d_tag != DT_NULL; dynp++) {
		switch (dynp->d_tag) {
		case DT_REL:
		case DT_RELA:
			rel = (ElfW_Rel *)(dynp->d_un.d_ptr + baseaddr);
			break;
		case DT_RELSZ:
		case DT_RELASZ:
			relsz = dynp->d_un.d_val;
			break;
		case DT_RELENT:
		case DT_RELAENT:
			relent = dynp->d_un.d_val;
			break;
		default:
			break;
		}
	}

	/*
	 * Perform the actual relocation.
	 */
	for (; relsz > 0; relsz -= relent) {
		switch (ELFW_R_TYPE(rel->r_info)) {
		case RELOC_TYPE_NONE:
			/* No relocation needs be performed. */
			break;

		case RELOC_TYPE_RELATIVE:
			newaddr = (Elf_Addr *)(rel->r_offset + baseaddr);
#ifdef ELF_RELA
			/*
			 * For R_AARCH64_RELATIVE we need to calculate the
			 * delta between the address we are run from and the
			 * address we are linked at. As the latter is 0 we
			 * just use the address we are run from for this.
			 */
			*newaddr = baseaddr + rel->r_addend;
#else
			/* Address relative to the base address. */
			*newaddr += baseaddr;
#endif
			break;
		default:
			/* XXX: do we need other relocations ? */
			break;
		}
		rel = (ElfW_Rel *)(void *)((caddr_t) rel + relent);
	}
}