Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

objtool: Refactor prefix symbol creation code

The prefix symbol creation code currently ignores all errors, presumably
because some functions don't have the leading NOPs.

Shuffle the code around a bit, improve the error handling and document
why some errors are ignored.

Acked-by: Petr Mladek <pmladek@suse.com>
Tested-by: Joe Lawrence <joe.lawrence@redhat.com>
Signed-off-by: Josh Poimboeuf <jpoimboe@kernel.org>

+46 -32
+46 -13
tools/objtool/check.c
··· 15 15 #include <objtool/special.h> 16 16 #include <objtool/warn.h> 17 17 #include <objtool/checksum.h> 18 + #include <objtool/util.h> 18 19 19 20 #include <linux/objtool_types.h> 20 21 #include <linux/hashtable.h> ··· 4234 4233 return false; 4235 4234 } 4236 4235 4237 - static int add_prefix_symbol(struct objtool_file *file, struct symbol *func) 4236 + /* 4237 + * For FineIBT or kCFI, a certain number of bytes preceding the function may be 4238 + * NOPs. Those NOPs may be rewritten at runtime and executed, so give them a 4239 + * proper function name: __pfx_<func>. 4240 + * 4241 + * The NOPs may not exist for the following cases: 4242 + * 4243 + * - compiler cloned functions (*.cold, *.part0, etc) 4244 + * - asm functions created with inline asm or without SYM_FUNC_START() 4245 + * 4246 + * So return 0 if the NOPs are missing or the function already has a prefix 4247 + * symbol. 4248 + */ 4249 + static int create_prefix_symbol(struct objtool_file *file, struct symbol *func) 4238 4250 { 4239 4251 struct instruction *insn, *prev; 4252 + char name[SYM_NAME_LEN]; 4240 4253 struct cfi_state *cfi; 4241 4254 4242 - insn = find_insn(file, func->sec, func->offset); 4243 - if (!insn) 4255 + if (!is_func_sym(func) || is_prefix_func(func) || 4256 + func->cold || func->static_call_tramp) 4257 + return 0; 4258 + 4259 + if ((strlen(func->name) + sizeof("__pfx_") > SYM_NAME_LEN)) { 4260 + WARN("%s: symbol name too long, can't create __pfx_ symbol", 4261 + func->name); 4262 + return 0; 4263 + } 4264 + 4265 + if (snprintf_check(name, SYM_NAME_LEN, "__pfx_%s", func->name)) 4244 4266 return -1; 4267 + 4268 + insn = find_insn(file, func->sec, func->offset); 4269 + if (!insn) { 4270 + WARN("%s: can't find starting instruction", func->name); 4271 + return -1; 4272 + } 4245 4273 4246 4274 for (prev = prev_insn_same_sec(file, insn); 4247 4275 prev; ··· 4278 4248 u64 offset; 4279 4249 4280 4250 if (prev->type != INSN_NOP) 4281 - return -1; 4251 + return 0; 4282 4252 4283 4253 offset = func->offset - prev->offset; 4284 4254 4285 4255 if (offset > opts.prefix) 4286 - return -1; 4256 + return 0; 4287 4257 4288 4258 if (offset < opts.prefix) 4289 4259 continue; 4290 4260 4291 - elf_create_prefix_symbol(file->elf, func, opts.prefix); 4261 + if (!elf_create_symbol(file->elf, name, func->sec, 4262 + GELF_ST_BIND(func->sym.st_info), 4263 + GELF_ST_TYPE(func->sym.st_info), 4264 + prev->offset, opts.prefix)) 4265 + return -1; 4266 + 4292 4267 break; 4293 4268 } 4294 4269 4295 4270 if (!prev) 4296 - return -1; 4271 + return 0; 4297 4272 4298 4273 if (!insn->cfi) { 4299 4274 /* ··· 4316 4281 return 0; 4317 4282 } 4318 4283 4319 - static int add_prefix_symbols(struct objtool_file *file) 4284 + static int create_prefix_symbols(struct objtool_file *file) 4320 4285 { 4321 4286 struct section *sec; 4322 4287 struct symbol *func; ··· 4326 4291 continue; 4327 4292 4328 4293 sec_for_each_sym(sec, func) { 4329 - if (!is_func_sym(func)) 4330 - continue; 4331 - 4332 - add_prefix_symbol(file, func); 4294 + if (create_prefix_symbol(file, func)) 4295 + return -1; 4333 4296 } 4334 4297 } 4335 4298 ··· 4954 4921 } 4955 4922 4956 4923 if (opts.prefix) { 4957 - ret = add_prefix_symbols(file); 4924 + ret = create_prefix_symbols(file); 4958 4925 if (ret) 4959 4926 goto out; 4960 4927 }
-17
tools/objtool/elf.c
··· 942 942 return sym; 943 943 } 944 944 945 - struct symbol * 946 - elf_create_prefix_symbol(struct elf *elf, struct symbol *orig, size_t size) 947 - { 948 - size_t namelen = strlen(orig->name) + sizeof("__pfx_"); 949 - char name[SYM_NAME_LEN]; 950 - unsigned long offset; 951 - 952 - snprintf(name, namelen, "__pfx_%s", orig->name); 953 - 954 - offset = orig->sym.st_value - size; 955 - 956 - return elf_create_symbol(elf, name, orig->sec, 957 - GELF_ST_BIND(orig->sym.st_info), 958 - GELF_ST_TYPE(orig->sym.st_info), 959 - offset, size); 960 - } 961 - 962 945 struct reloc *elf_init_reloc(struct elf *elf, struct section *rsec, 963 946 unsigned int reloc_idx, unsigned long offset, 964 947 struct symbol *sym, s64 addend, unsigned int type)
-2
tools/objtool/include/objtool/elf.h
··· 148 148 unsigned int type, unsigned long offset, 149 149 size_t size); 150 150 struct symbol *elf_create_section_symbol(struct elf *elf, struct section *sec); 151 - struct symbol *elf_create_prefix_symbol(struct elf *elf, struct symbol *orig, 152 - size_t size); 153 151 154 152 void *elf_add_data(struct elf *elf, struct section *sec, const void *data, 155 153 size_t size);