Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit ee158fcd authored by Isaku Yamahata's avatar Isaku Yamahata Committed by Tony Luck
Browse files

ia64/pv_ops/bp/module: support binary patching for kernel module.



support binary patching for kernel module.

Signed-off-by: default avatarIsaku Yamahata <yamahata@valinux.co.jp>
Signed-off-by: default avatarTony Luck <tony.luck@intel.com>
parent 03f511dd
Loading
Loading
Loading
Loading
+6 −0
Original line number Diff line number Diff line
@@ -16,6 +16,12 @@ struct mod_arch_specific {
	struct elf64_shdr *got;		/* global offset table */
	struct elf64_shdr *opd;		/* official procedure descriptors */
	struct elf64_shdr *unwind;	/* unwind-table section */
#ifdef CONFIG_PARAVIRT
	struct elf64_shdr *paravirt_bundles;
					/* paravirt_alt_bundle_patch table */
	struct elf64_shdr *paravirt_insts;
					/* paravirt_alt_inst_patch table */
#endif
	unsigned long gp;		/* global-pointer for module */

	void *core_unw_table;		/* core unwind-table cookie returned by unwinder */
+32 −0
Original line number Diff line number Diff line
@@ -446,6 +446,14 @@ module_frob_arch_sections (Elf_Ehdr *ehdr, Elf_Shdr *sechdrs, char *secstrings,
			mod->arch.opd = s;
		else if (strcmp(".IA_64.unwind", secstrings + s->sh_name) == 0)
			mod->arch.unwind = s;
#ifdef CONFIG_PARAVIRT
		else if (strcmp(".paravirt_bundles",
				secstrings + s->sh_name) == 0)
			mod->arch.paravirt_bundles = s;
		else if (strcmp(".paravirt_insts",
				secstrings + s->sh_name) == 0)
			mod->arch.paravirt_insts = s;
#endif

	if (!mod->arch.core_plt || !mod->arch.init_plt || !mod->arch.got || !mod->arch.opd) {
		printk(KERN_ERR "%s: sections missing\n", mod->name);
@@ -921,6 +929,30 @@ module_finalize (const Elf_Ehdr *hdr, const Elf_Shdr *sechdrs, struct module *mo
	DEBUGP("%s: init: entry=%p\n", __func__, mod->init);
	if (mod->arch.unwind)
		register_unwind_table(mod);
#ifdef CONFIG_PARAVIRT
        if (mod->arch.paravirt_bundles) {
                struct paravirt_patch_site_bundle *start =
                        (struct paravirt_patch_site_bundle *)
                        mod->arch.paravirt_bundles->sh_addr;
                struct paravirt_patch_site_bundle *end =
                        (struct paravirt_patch_site_bundle *)
                        (mod->arch.paravirt_bundles->sh_addr +
                         mod->arch.paravirt_bundles->sh_size);

                paravirt_patch_apply_bundle(start, end);
        }
        if (mod->arch.paravirt_insts) {
                struct paravirt_patch_site_inst *start =
                        (struct paravirt_patch_site_inst *)
                        mod->arch.paravirt_insts->sh_addr;
                struct paravirt_patch_site_inst *end =
                        (struct paravirt_patch_site_inst *)
                        (mod->arch.paravirt_insts->sh_addr +
                         mod->arch.paravirt_insts->sh_size);

                paravirt_patch_apply_inst(start, end);
        }
#endif
	return 0;
}