if (WARN_ON(!klp_is_object_loaded(obj)))
return -EINVAL;
-- if (WARN_ON(!obj->relocs))
-- return -EINVAL;
++ objname = klp_is_module(obj) ? obj->name : "vmlinux";
module_disable_ro(pmod);
- for (reloc = obj->relocs; reloc->name; reloc++) {
- /* discover the address of the referenced symbol */
- if (reloc->external) {
- if (reloc->sympos > 0) {
- pr_err("non-zero sympos for external reloc symbol '%s' is not supported\n",
- reloc->name);
- ret = -EINVAL;
- goto out;
- }
- ret = klp_find_external_symbol(pmod, reloc->name, &val);
- } else
- ret = klp_find_object_symbol(obj->name,
- reloc->name,
- reloc->sympos,
- &val);
++ /* 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;
+
- for (reloc = obj->relocs; reloc->name; reloc++) {
- /* discover the address of the referenced symbol */
- if (reloc->external) {
- if (reloc->sympos > 0) {
- pr_err("non-zero sympos for external reloc symbol '%s' is not supported\n",
- reloc->name);
- ret = -EINVAL;
- goto out;
- }
- ret = klp_find_external_symbol(pmod, reloc->name, &val);
- } else
- ret = klp_find_object_symbol(obj->name,
- reloc->name,
- reloc->sympos,
- &val);
++ /*
++ * Format: .klp.rela.sec_objname.section_name
++ * See comment in klp_resolve_symbols() for an explanation
++ * of the selected field width value.
++ */
++ cnt = sscanf(secname, ".klp.rela.%55[^.]", sec_objname);
++ if (cnt != 1) {
++ pr_err("section %s has an incorrectly formatted name",
++ secname);
++ ret = -EINVAL;
++ break;
++ }
+
++ if (strcmp(objname, sec_objname))
++ continue;
++
++ ret = klp_resolve_symbols(sec, pmod);
if (ret)
-- goto out;
++ break;
-- ret = klp_write_module_reloc(pmod, reloc->type, reloc->loc,
-- val + reloc->addend);
-- if (ret) {
-- pr_err("relocation failed for symbol '%s' at 0x%016lx (%d)\n",
-- reloc->name, val, ret);
-- goto out;
-- }
++ ret = apply_relocate_add(pmod->klp_info->sechdrs,
++ pmod->core_kallsyms.strtab,
++ pmod->klp_info->symndx, i, pmod);
++ if (ret)
++ break;
}
-- out:
module_enable_ro(pmod);
return ret;
}