arch/mips/kernel/elf.c

Source file repositories/reference/linux-study-clean/arch/mips/kernel/elf.c

File Facts

System
Linux kernel
Corpus path
arch/mips/kernel/elf.c
Extension
.c
Size
9876 bytes
Lines
348
Domain
Architecture Layer
Bucket
arch/mips
Inferred role
Architecture Layer: exported/initcall integration point
Status
integration implementation candidate

Why This File Exists

CPU and platform-specific kernel glue: boot entry, traps, syscall entry, interrupts, page tables, context switch, and low-level barriers.

Dependency Surface

Detected Declarations

Annotated Snippet

struct mode_req {
	bool single;
	bool soft;
	bool fr1;
	bool frdefault;
	bool fre;
};

static const struct mode_req fpu_reqs[] = {
	[MIPS_ABI_FP_ANY]    = { true,  true,  true,  true,  true  },
	[MIPS_ABI_FP_DOUBLE] = { false, false, false, true,  true  },
	[MIPS_ABI_FP_SINGLE] = { true,  false, false, false, false },
	[MIPS_ABI_FP_SOFT]   = { false, true,  false, false, false },
	[MIPS_ABI_FP_OLD_64] = { false, false, false, false, false },
	[MIPS_ABI_FP_XX]     = { false, false, true,  true,  true  },
	[MIPS_ABI_FP_64]     = { false, false, true,  false, false },
	[MIPS_ABI_FP_64A]    = { false, false, true,  false, true  }
};

/*
 * Mode requirements when .MIPS.abiflags is not present in the ELF.
 * Not present means that everything is acceptable except FR1.
 */
static struct mode_req none_req = { true, true, false, true, true };

int arch_elf_pt_proc(void *_ehdr, void *_phdr, struct file *elf,
		     bool is_interp, struct arch_elf_state *state)
{
	union {
		struct elf32_hdr e32;
		struct elf64_hdr e64;
	} *ehdr = _ehdr;
	struct elf32_phdr *phdr32 = _phdr;
	struct elf64_phdr *phdr64 = _phdr;
	struct mips_elf_abiflags_v0 abiflags;
	bool elf32;
	u32 flags;
	int ret;
	loff_t pos;

	elf32 = ehdr->e32.e_ident[EI_CLASS] == ELFCLASS32;
	flags = elf32 ? ehdr->e32.e_flags : ehdr->e64.e_flags;

	/* Let's see if this is an O32 ELF */
	if (elf32) {
		if (flags & EF_MIPS_FP64) {
			/*
			 * Set MIPS_ABI_FP_OLD_64 for EF_MIPS_FP64. We will override it
			 * later if needed
			 */
			if (is_interp)
				state->interp_fp_abi = MIPS_ABI_FP_OLD_64;
			else
				state->fp_abi = MIPS_ABI_FP_OLD_64;
		}
		if (phdr32->p_type != PT_MIPS_ABIFLAGS)
			return 0;

		if (phdr32->p_filesz < sizeof(abiflags))
			return -EINVAL;
		pos = phdr32->p_offset;
	} else {
		if (phdr64->p_type != PT_MIPS_ABIFLAGS)
			return 0;
		if (phdr64->p_filesz < sizeof(abiflags))
			return -EINVAL;
		pos = phdr64->p_offset;
	}

	ret = kernel_read(elf, &abiflags, sizeof(abiflags), &pos);
	if (ret < 0)
		return ret;
	if (ret != sizeof(abiflags))
		return -EIO;

	/* Record the required FP ABIs for use by mips_check_elf */
	if (is_interp)
		state->interp_fp_abi = abiflags.fp_abi;
	else
		state->fp_abi = abiflags.fp_abi;

	return 0;
}

int arch_check_elf(void *_ehdr, bool has_interpreter, void *_interp_ehdr,
		   struct arch_elf_state *state)
{
	union {
		struct elf32_hdr e32;
		struct elf64_hdr e64;

Annotation

Implementation Notes