Example #1
0
static int
add_section(struct elf_writer *ew, struct buffer *data, const char *name,
            Elf64_Addr addr, Elf64_Word size)
{
	Elf64_Shdr shdr;
	int ret;

	memset(&shdr, 0, sizeof(shdr));
	if (data != NULL) {
		shdr.sh_type = SHT_PROGBITS;
		shdr.sh_flags = SHF_ALLOC | SHF_WRITE | SHF_EXECINSTR;
	} else {
		shdr.sh_type = SHT_NOBITS;
		shdr.sh_flags = SHF_ALLOC;
	}
	shdr.sh_addr = addr;
	shdr.sh_offset = addr;
	shdr.sh_size = size;

	ret = elf_writer_add_section(ew, &shdr, data, name);

	if (ret)
		ERROR("Could not add '%s' section.\n", name);

	return ret;
}
Example #2
0
struct elf_writer *elf_writer_init(const Elf64_Ehdr *ehdr)
{
	struct elf_writer *ew;
	Elf64_Shdr shdr;
	struct buffer empty_buffer;

	if (!iself(ehdr))
		return NULL;

	ew = calloc(1, sizeof(*ew));

	memcpy(&ew->ehdr, ehdr, sizeof(ew->ehdr));

	ew->bit64 = ew->ehdr.e_ident[EI_CLASS] == ELFCLASS64;

	/* Set the endinan ops. */
	if (ew->ehdr.e_ident[EI_DATA] == ELFDATA2MSB)
		ew->xdr = &xdr_be;
	else
		ew->xdr = &xdr_le;

	/* Reset count and offsets */
	ew->ehdr.e_phoff = 0;
	ew->ehdr.e_shoff = 0;
	ew->ehdr.e_shnum = 0;
	ew->ehdr.e_phnum = 0;

	memset(&empty_buffer, 0, sizeof(empty_buffer));
	memset(&shdr, 0, sizeof(shdr));

	/* Add SHT_NULL section header. */
	shdr.sh_type = SHT_NULL;
	elf_writer_add_section(ew, &shdr, &empty_buffer, NULL);

	/* Add section header string table and maintain reference to it.  */
	shdr.sh_type = SHT_STRTAB;
	elf_writer_add_section(ew, &shdr, &empty_buffer, ".shstrtab");
	ew->ehdr.e_shstrndx = ew->num_secs - 1;
	ew->shstrtab = &ew->sections[ew->ehdr.e_shstrndx];

	return ew;
}
Example #3
0
int rmodule_stage_to_elf(Elf64_Ehdr *ehdr, struct buffer *buff)
{
	struct buffer reader;
	struct buffer elf_out;
	struct rmodule_header rmod;
	struct xdr *xdr;
	struct elf_writer *ew;
	Elf64_Shdr shdr;
	int bit64;
	size_t payload_sz;
	const char *section_name = ".program";
	const size_t input_sz = buffer_size(buff);

	buffer_clone(&reader, buff);

	xdr = (ehdr->e_ident[EI_DATA] == ELFDATA2MSB) ? &xdr_be : &xdr_le;
	bit64 = ehdr->e_ident[EI_CLASS] == ELFCLASS64;

	rmod_deserialize(&rmod, &reader, xdr);

	/* Indicate that file is not an rmodule if initial checks fail. */
	if (rmod.magic != RMODULE_MAGIC)
		return 1;
	if (rmod.version != RMODULE_VERSION_1)
		return 1;

	if (rmod.payload_begin_offset > input_sz ||
	    rmod.payload_end_offset > input_sz ||
	    rmod.relocations_begin_offset > input_sz ||
	    rmod.relocations_end_offset > input_sz) {
		ERROR("Rmodule fields out of bounds.\n");
		return -1;
	}

	ehdr->e_entry = rmod.module_entry_point;
	ew = elf_writer_init(ehdr);

	if (ew == NULL)
		return -1;

	payload_sz = rmod.payload_end_offset - rmod.payload_begin_offset;
	memset(&shdr, 0, sizeof(shdr));
	shdr.sh_type = SHT_PROGBITS;
	shdr.sh_flags = SHF_WRITE | SHF_ALLOC | SHF_EXECINSTR;
	shdr.sh_addr = rmod.module_link_start_address;
	shdr.sh_size = payload_sz;
	buffer_splice(&reader, buff, rmod.payload_begin_offset, payload_sz);

	if (elf_writer_add_section(ew, &shdr, &reader, section_name)) {
		ERROR("Unable to add ELF section: %s\n", section_name);
		elf_writer_destroy(ew);
		return -1;
	}

	if (payload_sz != rmod.module_program_size) {
		struct buffer b;

		buffer_init(&b, NULL, NULL, 0);
		memset(&shdr, 0, sizeof(shdr));
		shdr.sh_type = SHT_NOBITS;
		shdr.sh_flags = SHF_WRITE | SHF_ALLOC;
		shdr.sh_addr = rmod.module_link_start_address + payload_sz;
		shdr.sh_size = rmod.module_program_size - payload_sz;
		if (elf_writer_add_section(ew, &shdr, &b, ".empty")) {
			ERROR("Unable to add ELF section: .empty\n");
			elf_writer_destroy(ew);
			return -1;
		}
	}

	/* Provide a section symbol so the relcoations can reference that. */
	if (elf_writer_add_symbol(ew, section_name, section_name, shdr.sh_addr,
					0, STB_LOCAL, STT_SECTION)) {
		ERROR("Unable to add section symbol to ELF.\n");
		elf_writer_destroy(ew);
		return -1;
	}

	/* Add symbols for the parameters if they are non-zero. */
	if (rmod.parameters_begin != rmod.parameters_end) {
		int ret = 0;

		ret |= elf_writer_add_symbol(ew, "_rmodule_params",
						section_name,
						rmod.parameters_begin, 0,
						STB_GLOBAL, STT_NOTYPE);
		ret |= elf_writer_add_symbol(ew, "_ermodule_params",
						section_name,
						rmod.parameters_end, 0,
						STB_GLOBAL, STT_NOTYPE);

		if (ret != 0) {
			ERROR("Unable to add module params symbols to ELF\n");
			elf_writer_destroy(ew);
			return -1;
		}
	}

	if (elf_writer_add_symbol(ew, "_bss", section_name, rmod.bss_begin, 0,
					STB_GLOBAL, STT_NOTYPE) ||
	    elf_writer_add_symbol(ew, "_ebss", section_name, rmod.bss_end, 0,
					STB_GLOBAL, STT_NOTYPE)) {
		ERROR("Unable to add bss symbols to ELF\n");
		elf_writer_destroy(ew);
		return -1;
	}

	ssize_t relocs_sz = rmod.relocations_end_offset;
	relocs_sz -= rmod.relocations_begin_offset;
	buffer_splice(&reader, buff, rmod.relocations_begin_offset, relocs_sz);
	while (relocs_sz > 0) {
		Elf64_Addr addr;

		if (bit64) {
			relocs_sz -= sizeof(Elf64_Addr);
			addr = xdr->get64(&reader);
		} else {
			relocs_sz -= sizeof(Elf32_Addr);
			addr = xdr->get32(&reader);
		}

		/* Skip any relocations that are below the link address. */
		if (addr < rmod.module_link_start_address)
			continue;

		if (elf_writer_add_rel(ew, section_name, addr)) {
			ERROR("Relocation addition failure.\n");
			elf_writer_destroy(ew);
			return -1;
		}
	}

	if (elf_writer_serialize(ew, &elf_out)) {
		ERROR("ELF writer serialize failure.\n");
		elf_writer_destroy(ew);
		return -1;
	}

	elf_writer_destroy(ew);

	/* Flip buffer with the created ELF one. */
	buffer_delete(buff);
	*buff = elf_out;

	return 0;
}