On Fri, Nov 18, 2022 at 8:24 AM Petr Mladek <pmladek@xxxxxxxx> wrote: > [...] > > > > +#ifdef CONFIG_LIVEPATCH > > +void clear_relocate_add(Elf64_Shdr *sechdrs, > > + const char *strtab, > > + unsigned int symindex, > > + unsigned int relsec, > > + struct module *me) > > +{ > > + unsigned int i; > > + Elf64_Rela *rela = (void *)sechdrs[relsec].sh_addr; > > + Elf64_Sym *sym; > > + unsigned long *location; > > + const char *symname; > > + u32 *instruction; > > + > > + pr_debug("Clearing ADD relocate section %u to %u\n", relsec, > > + sechdrs[relsec].sh_info); > > + > > + for (i = 0; i < sechdrs[relsec].sh_size / sizeof(*rela); i++) { > > + location = (void *)sechdrs[sechdrs[relsec].sh_info].sh_addr > > + + rela[i].r_offset; > > + sym = (Elf64_Sym *)sechdrs[symindex].sh_addr > > + + ELF64_R_SYM(rela[i].r_info); > > + symname = me->core_kallsyms.strtab > > + + sym->st_name; > > + > > + if (ELF64_R_TYPE(rela[i].r_info) != R_PPC_REL24) > > + continue; > > + /* > > + * reverse the operations in apply_relocate_add() for case > > + * R_PPC_REL24. > > + */ > > + if (sym->st_shndx != SHN_UNDEF && > > + sym->st_shndx != SHN_LIVEPATCH) > > + continue; > > + > > + instruction = (u32 *)location; > > + if (is_mprofile_ftrace_call(symname)) > > + continue; > > + > > + if (!instr_is_relative_link_branch(ppc_inst(*instruction))) > > + continue; > > + > > + instruction += 1; > > + patch_instruction(instruction, ppc_inst(PPC_RAW_NOP())); > > + } > > + > > +} > > This looks like a lot of duplicated code. Isn't it? TBH, I think the duplicated code is not really bad. apply_relocate_add() is a much more complicated function, I would rather not mess it up to make this function a little simpler. [...] > > This duplicates a lot of code. Please, rename apply_relocate_add() the > same way as __apply_clear_relocate_add() and add the "apply" parameter. > Then add the wrappers for this: > > int write_relocate_add(Elf64_Shdr *sechdrs, > const char *strtab, > unsigned int symindex, > unsigned int relsec, > struct module *me, > bool apply) > { > int ret; > bool early = me->state == MODULE_STATE_UNFORMED; > void *(*write)(void *, const void *, size_t) = memcpy; > > if (!early) { > write = text_poke; > mutex_lock(&text_mutex); > } How about we move the "early" logic into __write_relocate_add()? > > ret = __write_relocate_add(sechdrs, strtab, symindex, relsec, me, > write, apply); > > if (!early) { > text_poke_sync(); > mutex_unlock(&text_mutex); > } > > return ret; > } > > int apply_relocate_add(Elf64_Shdr *sechdrs, > const char *strtab, > unsigned int symindex, > unsigned int relsec, > struct module *me) > { > return write_relocate_add(sechdrs, strtab, symindex, relsec, me, true); Then we just call __write_relocate_add() from here... > } > > #ifdef CONFIG_LIVEPATCH > void apply_relocate_add(Elf64_Shdr *sechdrs, > const char *strtab, > unsigned int symindex, > unsigned int relsec, > struct module *me) > { > write_relocate_add(sechdrs, strtab, symindex, relsec, me, false); and here. > } > #endif > > > > +#endif > > + > > #endif > > > > int module_finalize(const Elf_Ehdr *hdr, > > --- a/kernel/livepatch/core.c > > +++ b/kernel/livepatch/core.c > > @@ -316,6 +316,45 @@ int klp_apply_section_relocs(struct module *pmod, Elf_Shdr *sechdrs, > > return apply_relocate_add(sechdrs, strtab, symndx, secndx, pmod); > > } > > > > +static void klp_clear_object_relocations(struct module *pmod, > > + struct klp_object *obj) > > +{ > > + int i, cnt; > > + const char *objname, *secname; > > + char sec_objname[MODULE_NAME_LEN]; > > + Elf_Shdr *sec; > > + > > + objname = klp_is_module(obj) ? obj->name : "vmlinux"; > > + > > + /* For each klp relocation section */ > > + for (i = 1; i < pmod->klp_info->hdr.e_shnum; i++) { > > + sec = pmod->klp_info->sechdrs + i; > > + secname = pmod->klp_info->secstrings + sec->sh_name; > > + if (!(sec->sh_flags & SHF_RELA_LIVEPATCH)) > > + continue; > > + > > + /* > > + * Format: .klp.rela.sec_objname.section_name > > + * See comment in klp_resolve_symbols() for an explanation > > + * of the selected field width value. > > + */ > > + secname = pmod->klp_info->secstrings + sec->sh_name; > > + cnt = sscanf(secname, ".klp.rela.%55[^.]", sec_objname); > > + if (cnt != 1) { > > + pr_err("section %s has an incorrectly formatted name\n", > > + secname); > > + continue; > > + } Actually, I think we don't need the cnt check here. Once it is removed, there isn't much duplicated logic. > > + > > + if (strcmp(objname, sec_objname)) > > + continue; > > + > > + clear_relocate_add(pmod->klp_info->sechdrs, > > + pmod->core_kallsyms.strtab, > > + pmod->klp_info->symndx, i, pmod); > > + } > > +} > > Huh, this duplicates a lot of tricky code. > > It is even worse because this squashed code from two functions > klp_apply_section_relocs() and klp_apply_object_relocs() > into a single function. As a result, the code duplication is not > even obvious. > > Also the suffix "_reloacations() does not match the suffix of > the related funciton: > > + klp_apply_object_relocs() (existing) > + klp_clear_object_relocations() (new) > > This all would complicate maintenance of the code. > > Please, implement a common: > > int klp_write_section_relocs(struct module *pmod, Elf_Shdr *sechdrs, > const char *shstrtab, const char *strtab, > unsigned int symndx, unsigned int secndx, > const char *objname, bool apply); > > and > > int klp_write_object_relocs(struct klp_patch *patch, > struct klp_object *obj, > bool apply); > > and add the respective wrappers: > > int klp_apply_section_relocs(); /* also needed in module/main.c */ > int klp_apply_object_relocs(); > void klp_clear_object_relocs(); With the above simplification (removing cnt check), do we still need all these wrappers? Personally, I think they will make the code more difficult to follow.. Thanks, Song