mirror of
				https://github.com/torvalds/linux.git
				synced 2025-11-04 10:40:15 +02:00 
			
		
		
		
	objtool: Improve error handling
Fix some error handling issues, improve error messages, properly distinguish betwee errors and warnings, and generally try to make all the error handling more consistent. Signed-off-by: Josh Poimboeuf <jpoimboe@kernel.org> Signed-off-by: Ingo Molnar <mingo@kernel.org> Cc: Linus Torvalds <torvalds@linux-foundation.org> Link: https://lore.kernel.org/r/3094bb4463dad29b6bd1bea03848d1571ace771c.1742852846.git.jpoimboe@kernel.org
This commit is contained in:
		
							parent
							
								
									e1a9dda74d
								
							
						
					
					
						commit
						c5995abe15
					
				
					 6 changed files with 232 additions and 221 deletions
				
			
		| 
						 | 
					@ -8,15 +8,12 @@
 | 
				
			||||||
#include <stdlib.h>
 | 
					#include <stdlib.h>
 | 
				
			||||||
#include <fcntl.h>
 | 
					#include <fcntl.h>
 | 
				
			||||||
#include <unistd.h>
 | 
					#include <unistd.h>
 | 
				
			||||||
 | 
					#include <errno.h>
 | 
				
			||||||
#include <sys/stat.h>
 | 
					#include <sys/stat.h>
 | 
				
			||||||
#include <sys/sendfile.h>
 | 
					#include <sys/sendfile.h>
 | 
				
			||||||
#include <objtool/builtin.h>
 | 
					#include <objtool/builtin.h>
 | 
				
			||||||
#include <objtool/objtool.h>
 | 
					#include <objtool/objtool.h>
 | 
				
			||||||
 | 
					#include <objtool/warn.h>
 | 
				
			||||||
#define ERROR(format, ...)				\
 | 
					 | 
				
			||||||
	fprintf(stderr,					\
 | 
					 | 
				
			||||||
		"error: objtool: " format "\n",		\
 | 
					 | 
				
			||||||
		##__VA_ARGS__)
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
const char *objname;
 | 
					const char *objname;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -139,22 +136,22 @@ int cmd_parse_options(int argc, const char **argv, const char * const usage[])
 | 
				
			||||||
static bool opts_valid(void)
 | 
					static bool opts_valid(void)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	if (opts.mnop && !opts.mcount) {
 | 
						if (opts.mnop && !opts.mcount) {
 | 
				
			||||||
		ERROR("--mnop requires --mcount");
 | 
							WARN("--mnop requires --mcount");
 | 
				
			||||||
		return false;
 | 
							return false;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (opts.noinstr && !opts.link) {
 | 
						if (opts.noinstr && !opts.link) {
 | 
				
			||||||
		ERROR("--noinstr requires --link");
 | 
							WARN("--noinstr requires --link");
 | 
				
			||||||
		return false;
 | 
							return false;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (opts.ibt && !opts.link) {
 | 
						if (opts.ibt && !opts.link) {
 | 
				
			||||||
		ERROR("--ibt requires --link");
 | 
							WARN("--ibt requires --link");
 | 
				
			||||||
		return false;
 | 
							return false;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (opts.unret && !opts.link) {
 | 
						if (opts.unret && !opts.link) {
 | 
				
			||||||
		ERROR("--unret requires --link");
 | 
							WARN("--unret requires --link");
 | 
				
			||||||
		return false;
 | 
							return false;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -171,7 +168,7 @@ static bool opts_valid(void)
 | 
				
			||||||
	    opts.static_call		||
 | 
						    opts.static_call		||
 | 
				
			||||||
	    opts.uaccess) {
 | 
						    opts.uaccess) {
 | 
				
			||||||
		if (opts.dump_orc) {
 | 
							if (opts.dump_orc) {
 | 
				
			||||||
			ERROR("--dump can't be combined with other actions");
 | 
								WARN("--dump can't be combined with other actions");
 | 
				
			||||||
			return false;
 | 
								return false;
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -181,7 +178,7 @@ static bool opts_valid(void)
 | 
				
			||||||
	if (opts.dump_orc)
 | 
						if (opts.dump_orc)
 | 
				
			||||||
		return true;
 | 
							return true;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	ERROR("At least one action required");
 | 
						WARN("At least one action required");
 | 
				
			||||||
	return false;
 | 
						return false;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -194,30 +191,30 @@ static int copy_file(const char *src, const char *dst)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	src_fd = open(src, O_RDONLY);
 | 
						src_fd = open(src, O_RDONLY);
 | 
				
			||||||
	if (src_fd == -1) {
 | 
						if (src_fd == -1) {
 | 
				
			||||||
		ERROR("can't open '%s' for reading", src);
 | 
							WARN("can't open %s for reading: %s", src, strerror(errno));
 | 
				
			||||||
		return 1;
 | 
							return 1;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	dst_fd = open(dst, O_WRONLY | O_CREAT | O_TRUNC, 0400);
 | 
						dst_fd = open(dst, O_WRONLY | O_CREAT | O_TRUNC, 0400);
 | 
				
			||||||
	if (dst_fd == -1) {
 | 
						if (dst_fd == -1) {
 | 
				
			||||||
		ERROR("can't open '%s' for writing", dst);
 | 
							WARN("can't open %s for writing: %s", dst, strerror(errno));
 | 
				
			||||||
		return 1;
 | 
							return 1;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (fstat(src_fd, &stat) == -1) {
 | 
						if (fstat(src_fd, &stat) == -1) {
 | 
				
			||||||
		perror("fstat");
 | 
							WARN_GLIBC("fstat");
 | 
				
			||||||
		return 1;
 | 
							return 1;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (fchmod(dst_fd, stat.st_mode) == -1) {
 | 
						if (fchmod(dst_fd, stat.st_mode) == -1) {
 | 
				
			||||||
		perror("fchmod");
 | 
							WARN_GLIBC("fchmod");
 | 
				
			||||||
		return 1;
 | 
							return 1;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	for (to_copy = stat.st_size; to_copy > 0; to_copy -= copied) {
 | 
						for (to_copy = stat.st_size; to_copy > 0; to_copy -= copied) {
 | 
				
			||||||
		copied = sendfile(dst_fd, src_fd, &offset, to_copy);
 | 
							copied = sendfile(dst_fd, src_fd, &offset, to_copy);
 | 
				
			||||||
		if (copied == -1) {
 | 
							if (copied == -1) {
 | 
				
			||||||
			perror("sendfile");
 | 
								WARN_GLIBC("sendfile");
 | 
				
			||||||
			return 1;
 | 
								return 1;
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
| 
						 | 
					@ -233,14 +230,14 @@ static char **save_argv(int argc, const char **argv)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	orig_argv = calloc(argc, sizeof(char *));
 | 
						orig_argv = calloc(argc, sizeof(char *));
 | 
				
			||||||
	if (!orig_argv) {
 | 
						if (!orig_argv) {
 | 
				
			||||||
		perror("calloc");
 | 
							WARN_GLIBC("calloc");
 | 
				
			||||||
		return NULL;
 | 
							return NULL;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	for (int i = 0; i < argc; i++) {
 | 
						for (int i = 0; i < argc; i++) {
 | 
				
			||||||
		orig_argv[i] = strdup(argv[i]);
 | 
							orig_argv[i] = strdup(argv[i]);
 | 
				
			||||||
		if (!orig_argv[i]) {
 | 
							if (!orig_argv[i]) {
 | 
				
			||||||
			perror("strdup");
 | 
								WARN_GLIBC("strdup(%s)", orig_argv[i]);
 | 
				
			||||||
			return NULL;
 | 
								return NULL;
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
	};
 | 
						};
 | 
				
			||||||
| 
						 | 
					@ -285,7 +282,7 @@ int objtool_run(int argc, const char **argv)
 | 
				
			||||||
		goto err;
 | 
							goto err;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (!opts.link && has_multiple_files(file->elf)) {
 | 
						if (!opts.link && has_multiple_files(file->elf)) {
 | 
				
			||||||
		ERROR("Linked object requires --link");
 | 
							WARN("Linked object requires --link");
 | 
				
			||||||
		goto err;
 | 
							goto err;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -313,7 +310,7 @@ int objtool_run(int argc, const char **argv)
 | 
				
			||||||
	 */
 | 
						 */
 | 
				
			||||||
	backup = malloc(strlen(objname) + strlen(ORIG_SUFFIX) + 1);
 | 
						backup = malloc(strlen(objname) + strlen(ORIG_SUFFIX) + 1);
 | 
				
			||||||
	if (!backup) {
 | 
						if (!backup) {
 | 
				
			||||||
		perror("malloc");
 | 
							WARN_GLIBC("malloc");
 | 
				
			||||||
		return 1;
 | 
							return 1;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -353,7 +353,7 @@ static struct cfi_state *cfi_alloc(void)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	struct cfi_state *cfi = calloc(1, sizeof(struct cfi_state));
 | 
						struct cfi_state *cfi = calloc(1, sizeof(struct cfi_state));
 | 
				
			||||||
	if (!cfi) {
 | 
						if (!cfi) {
 | 
				
			||||||
		WARN("calloc failed");
 | 
							WARN_GLIBC("calloc");
 | 
				
			||||||
		exit(1);
 | 
							exit(1);
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	nr_cfi++;
 | 
						nr_cfi++;
 | 
				
			||||||
| 
						 | 
					@ -409,7 +409,7 @@ static void *cfi_hash_alloc(unsigned long size)
 | 
				
			||||||
			PROT_READ|PROT_WRITE,
 | 
								PROT_READ|PROT_WRITE,
 | 
				
			||||||
			MAP_PRIVATE|MAP_ANON, -1, 0);
 | 
								MAP_PRIVATE|MAP_ANON, -1, 0);
 | 
				
			||||||
	if (cfi_hash == (void *)-1L) {
 | 
						if (cfi_hash == (void *)-1L) {
 | 
				
			||||||
		WARN("mmap fail cfi_hash");
 | 
							WARN_GLIBC("mmap fail cfi_hash");
 | 
				
			||||||
		cfi_hash = NULL;
 | 
							cfi_hash = NULL;
 | 
				
			||||||
	}  else if (opts.stats) {
 | 
						}  else if (opts.stats) {
 | 
				
			||||||
		printf("cfi_bits: %d\n", cfi_bits);
 | 
							printf("cfi_bits: %d\n", cfi_bits);
 | 
				
			||||||
| 
						 | 
					@ -465,7 +465,7 @@ static int decode_instructions(struct objtool_file *file)
 | 
				
			||||||
			if (!insns || idx == INSN_CHUNK_MAX) {
 | 
								if (!insns || idx == INSN_CHUNK_MAX) {
 | 
				
			||||||
				insns = calloc(sizeof(*insn), INSN_CHUNK_SIZE);
 | 
									insns = calloc(sizeof(*insn), INSN_CHUNK_SIZE);
 | 
				
			||||||
				if (!insns) {
 | 
									if (!insns) {
 | 
				
			||||||
					WARN("malloc failed");
 | 
										WARN_GLIBC("calloc");
 | 
				
			||||||
					return -1;
 | 
										return -1;
 | 
				
			||||||
				}
 | 
									}
 | 
				
			||||||
				idx = 0;
 | 
									idx = 0;
 | 
				
			||||||
| 
						 | 
					@ -567,14 +567,21 @@ static int add_pv_ops(struct objtool_file *file, const char *symname)
 | 
				
			||||||
		if (!reloc)
 | 
							if (!reloc)
 | 
				
			||||||
			break;
 | 
								break;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							idx = (reloc_offset(reloc) - sym->offset) / sizeof(unsigned long);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		func = reloc->sym;
 | 
							func = reloc->sym;
 | 
				
			||||||
		if (func->type == STT_SECTION)
 | 
							if (func->type == STT_SECTION)
 | 
				
			||||||
			func = find_symbol_by_offset(reloc->sym->sec,
 | 
								func = find_symbol_by_offset(reloc->sym->sec,
 | 
				
			||||||
						     reloc_addend(reloc));
 | 
											     reloc_addend(reloc));
 | 
				
			||||||
 | 
							if (!func) {
 | 
				
			||||||
 | 
								WARN_FUNC("can't find func at %s[%d]",
 | 
				
			||||||
 | 
									  reloc->sym->sec, reloc_addend(reloc),
 | 
				
			||||||
 | 
									  symname, idx);
 | 
				
			||||||
 | 
								return -1;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		idx = (reloc_offset(reloc) - sym->offset) / sizeof(unsigned long);
 | 
							if (objtool_pv_add(file, idx, func))
 | 
				
			||||||
 | 
								return -1;
 | 
				
			||||||
		objtool_pv_add(file, idx, func);
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
		off = reloc_offset(reloc) + 1;
 | 
							off = reloc_offset(reloc) + 1;
 | 
				
			||||||
		if (off > end)
 | 
							if (off > end)
 | 
				
			||||||
| 
						 | 
					@ -598,7 +605,7 @@ static int init_pv_ops(struct objtool_file *file)
 | 
				
			||||||
	};
 | 
						};
 | 
				
			||||||
	const char *pv_ops;
 | 
						const char *pv_ops;
 | 
				
			||||||
	struct symbol *sym;
 | 
						struct symbol *sym;
 | 
				
			||||||
	int idx, nr;
 | 
						int idx, nr, ret;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (!opts.noinstr)
 | 
						if (!opts.noinstr)
 | 
				
			||||||
		return 0;
 | 
							return 0;
 | 
				
			||||||
| 
						 | 
					@ -611,14 +618,19 @@ static int init_pv_ops(struct objtool_file *file)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	nr = sym->len / sizeof(unsigned long);
 | 
						nr = sym->len / sizeof(unsigned long);
 | 
				
			||||||
	file->pv_ops = calloc(sizeof(struct pv_state), nr);
 | 
						file->pv_ops = calloc(sizeof(struct pv_state), nr);
 | 
				
			||||||
	if (!file->pv_ops)
 | 
						if (!file->pv_ops) {
 | 
				
			||||||
 | 
							WARN_GLIBC("calloc");
 | 
				
			||||||
		return -1;
 | 
							return -1;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	for (idx = 0; idx < nr; idx++)
 | 
						for (idx = 0; idx < nr; idx++)
 | 
				
			||||||
		INIT_LIST_HEAD(&file->pv_ops[idx].targets);
 | 
							INIT_LIST_HEAD(&file->pv_ops[idx].targets);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	for (idx = 0; (pv_ops = pv_ops_tables[idx]); idx++)
 | 
						for (idx = 0; (pv_ops = pv_ops_tables[idx]); idx++) {
 | 
				
			||||||
		add_pv_ops(file, pv_ops);
 | 
							ret = add_pv_ops(file, pv_ops);
 | 
				
			||||||
 | 
							if (ret)
 | 
				
			||||||
 | 
								return ret;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	return 0;
 | 
						return 0;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					@ -666,13 +678,12 @@ static int create_static_call_sections(struct objtool_file *file)
 | 
				
			||||||
		/* find key symbol */
 | 
							/* find key symbol */
 | 
				
			||||||
		key_name = strdup(insn_call_dest(insn)->name);
 | 
							key_name = strdup(insn_call_dest(insn)->name);
 | 
				
			||||||
		if (!key_name) {
 | 
							if (!key_name) {
 | 
				
			||||||
			perror("strdup");
 | 
								WARN_GLIBC("strdup");
 | 
				
			||||||
			return -1;
 | 
								return -1;
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		if (strncmp(key_name, STATIC_CALL_TRAMP_PREFIX_STR,
 | 
							if (strncmp(key_name, STATIC_CALL_TRAMP_PREFIX_STR,
 | 
				
			||||||
			    STATIC_CALL_TRAMP_PREFIX_LEN)) {
 | 
								    STATIC_CALL_TRAMP_PREFIX_LEN)) {
 | 
				
			||||||
			WARN("static_call: trampoline name malformed: %s", key_name);
 | 
								WARN("static_call: trampoline name malformed: %s", key_name);
 | 
				
			||||||
			free(key_name);
 | 
					 | 
				
			||||||
			return -1;
 | 
								return -1;
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		tmp = key_name + STATIC_CALL_TRAMP_PREFIX_LEN - STATIC_CALL_KEY_PREFIX_LEN;
 | 
							tmp = key_name + STATIC_CALL_TRAMP_PREFIX_LEN - STATIC_CALL_KEY_PREFIX_LEN;
 | 
				
			||||||
| 
						 | 
					@ -682,7 +693,6 @@ static int create_static_call_sections(struct objtool_file *file)
 | 
				
			||||||
		if (!key_sym) {
 | 
							if (!key_sym) {
 | 
				
			||||||
			if (!opts.module) {
 | 
								if (!opts.module) {
 | 
				
			||||||
				WARN("static_call: can't find static_call_key symbol: %s", tmp);
 | 
									WARN("static_call: can't find static_call_key symbol: %s", tmp);
 | 
				
			||||||
				free(key_name);
 | 
					 | 
				
			||||||
				return -1;
 | 
									return -1;
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -697,7 +707,6 @@ static int create_static_call_sections(struct objtool_file *file)
 | 
				
			||||||
			 */
 | 
								 */
 | 
				
			||||||
			key_sym = insn_call_dest(insn);
 | 
								key_sym = insn_call_dest(insn);
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		free(key_name);
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
		/* populate reloc for 'key' */
 | 
							/* populate reloc for 'key' */
 | 
				
			||||||
		if (!elf_init_reloc_data_sym(file->elf, sec,
 | 
							if (!elf_init_reloc_data_sym(file->elf, sec,
 | 
				
			||||||
| 
						 | 
					@ -981,7 +990,7 @@ static int create_direct_call_sections(struct objtool_file *file)
 | 
				
			||||||
/*
 | 
					/*
 | 
				
			||||||
 * Warnings shouldn't be reported for ignored functions.
 | 
					 * Warnings shouldn't be reported for ignored functions.
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
static void add_ignores(struct objtool_file *file)
 | 
					static int add_ignores(struct objtool_file *file)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	struct section *rsec;
 | 
						struct section *rsec;
 | 
				
			||||||
	struct symbol *func;
 | 
						struct symbol *func;
 | 
				
			||||||
| 
						 | 
					@ -989,7 +998,7 @@ static void add_ignores(struct objtool_file *file)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	rsec = find_section_by_name(file->elf, ".rela.discard.func_stack_frame_non_standard");
 | 
						rsec = find_section_by_name(file->elf, ".rela.discard.func_stack_frame_non_standard");
 | 
				
			||||||
	if (!rsec)
 | 
						if (!rsec)
 | 
				
			||||||
		return;
 | 
							return 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	for_each_reloc(rsec, reloc) {
 | 
						for_each_reloc(rsec, reloc) {
 | 
				
			||||||
		switch (reloc->sym->type) {
 | 
							switch (reloc->sym->type) {
 | 
				
			||||||
| 
						 | 
					@ -1006,11 +1015,13 @@ static void add_ignores(struct objtool_file *file)
 | 
				
			||||||
		default:
 | 
							default:
 | 
				
			||||||
			WARN("unexpected relocation symbol type in %s: %d",
 | 
								WARN("unexpected relocation symbol type in %s: %d",
 | 
				
			||||||
			     rsec->name, reloc->sym->type);
 | 
								     rsec->name, reloc->sym->type);
 | 
				
			||||||
			continue;
 | 
								return -1;
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		func->ignore = true;
 | 
							func->ignore = true;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return 0;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/*
 | 
					/*
 | 
				
			||||||
| 
						 | 
					@ -1275,7 +1286,7 @@ static void remove_insn_ops(struct instruction *insn)
 | 
				
			||||||
	insn->stack_ops = NULL;
 | 
						insn->stack_ops = NULL;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static void annotate_call_site(struct objtool_file *file,
 | 
					static int annotate_call_site(struct objtool_file *file,
 | 
				
			||||||
			       struct instruction *insn, bool sibling)
 | 
								       struct instruction *insn, bool sibling)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	struct reloc *reloc = insn_reloc(file, insn);
 | 
						struct reloc *reloc = insn_reloc(file, insn);
 | 
				
			||||||
| 
						 | 
					@ -1286,12 +1297,12 @@ static void annotate_call_site(struct objtool_file *file,
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (sym->static_call_tramp) {
 | 
						if (sym->static_call_tramp) {
 | 
				
			||||||
		list_add_tail(&insn->call_node, &file->static_call_list);
 | 
							list_add_tail(&insn->call_node, &file->static_call_list);
 | 
				
			||||||
		return;
 | 
							return 0;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (sym->retpoline_thunk) {
 | 
						if (sym->retpoline_thunk) {
 | 
				
			||||||
		list_add_tail(&insn->call_node, &file->retpoline_call_list);
 | 
							list_add_tail(&insn->call_node, &file->retpoline_call_list);
 | 
				
			||||||
		return;
 | 
							return 0;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/*
 | 
						/*
 | 
				
			||||||
| 
						 | 
					@ -1303,10 +1314,12 @@ static void annotate_call_site(struct objtool_file *file,
 | 
				
			||||||
		if (reloc)
 | 
							if (reloc)
 | 
				
			||||||
			set_reloc_type(file->elf, reloc, R_NONE);
 | 
								set_reloc_type(file->elf, reloc, R_NONE);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		elf_write_insn(file->elf, insn->sec,
 | 
							if (elf_write_insn(file->elf, insn->sec,
 | 
				
			||||||
			       insn->offset, insn->len,
 | 
									   insn->offset, insn->len,
 | 
				
			||||||
			       sibling ? arch_ret_insn(insn->len)
 | 
									   sibling ? arch_ret_insn(insn->len)
 | 
				
			||||||
			               : arch_nop_insn(insn->len));
 | 
										   : arch_nop_insn(insn->len))) {
 | 
				
			||||||
 | 
								return -1;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		insn->type = sibling ? INSN_RETURN : INSN_NOP;
 | 
							insn->type = sibling ? INSN_RETURN : INSN_NOP;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1320,7 +1333,7 @@ static void annotate_call_site(struct objtool_file *file,
 | 
				
			||||||
			insn->retpoline_safe = true;
 | 
								insn->retpoline_safe = true;
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		return;
 | 
							return 0;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (opts.mcount && sym->fentry) {
 | 
						if (opts.mcount && sym->fentry) {
 | 
				
			||||||
| 
						 | 
					@ -1330,15 +1343,17 @@ static void annotate_call_site(struct objtool_file *file,
 | 
				
			||||||
			if (reloc)
 | 
								if (reloc)
 | 
				
			||||||
				set_reloc_type(file->elf, reloc, R_NONE);
 | 
									set_reloc_type(file->elf, reloc, R_NONE);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			elf_write_insn(file->elf, insn->sec,
 | 
								if (elf_write_insn(file->elf, insn->sec,
 | 
				
			||||||
				       insn->offset, insn->len,
 | 
										   insn->offset, insn->len,
 | 
				
			||||||
				       arch_nop_insn(insn->len));
 | 
										   arch_nop_insn(insn->len))) {
 | 
				
			||||||
 | 
									return -1;
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			insn->type = INSN_NOP;
 | 
								insn->type = INSN_NOP;
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		list_add_tail(&insn->call_node, &file->mcount_loc_list);
 | 
							list_add_tail(&insn->call_node, &file->mcount_loc_list);
 | 
				
			||||||
		return;
 | 
							return 0;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (insn->type == INSN_CALL && !insn->sec->init &&
 | 
						if (insn->type == INSN_CALL && !insn->sec->init &&
 | 
				
			||||||
| 
						 | 
					@ -1347,14 +1362,16 @@ static void annotate_call_site(struct objtool_file *file,
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (!sibling && dead_end_function(file, sym))
 | 
						if (!sibling && dead_end_function(file, sym))
 | 
				
			||||||
		insn->dead_end = true;
 | 
							insn->dead_end = true;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return 0;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static void add_call_dest(struct objtool_file *file, struct instruction *insn,
 | 
					static int add_call_dest(struct objtool_file *file, struct instruction *insn,
 | 
				
			||||||
			  struct symbol *dest, bool sibling)
 | 
								  struct symbol *dest, bool sibling)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	insn->_call_dest = dest;
 | 
						insn->_call_dest = dest;
 | 
				
			||||||
	if (!dest)
 | 
						if (!dest)
 | 
				
			||||||
		return;
 | 
							return 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/*
 | 
						/*
 | 
				
			||||||
	 * Whatever stack impact regular CALLs have, should be undone
 | 
						 * Whatever stack impact regular CALLs have, should be undone
 | 
				
			||||||
| 
						 | 
					@ -1365,10 +1382,10 @@ static void add_call_dest(struct objtool_file *file, struct instruction *insn,
 | 
				
			||||||
	 */
 | 
						 */
 | 
				
			||||||
	remove_insn_ops(insn);
 | 
						remove_insn_ops(insn);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	annotate_call_site(file, insn, sibling);
 | 
						return annotate_call_site(file, insn, sibling);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static void add_retpoline_call(struct objtool_file *file, struct instruction *insn)
 | 
					static int add_retpoline_call(struct objtool_file *file, struct instruction *insn)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	/*
 | 
						/*
 | 
				
			||||||
	 * Retpoline calls/jumps are really dynamic calls/jumps in disguise,
 | 
						 * Retpoline calls/jumps are really dynamic calls/jumps in disguise,
 | 
				
			||||||
| 
						 | 
					@ -1385,7 +1402,7 @@ static void add_retpoline_call(struct objtool_file *file, struct instruction *in
 | 
				
			||||||
		insn->type = INSN_JUMP_DYNAMIC_CONDITIONAL;
 | 
							insn->type = INSN_JUMP_DYNAMIC_CONDITIONAL;
 | 
				
			||||||
		break;
 | 
							break;
 | 
				
			||||||
	default:
 | 
						default:
 | 
				
			||||||
		return;
 | 
							return 0;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	insn->retpoline_safe = true;
 | 
						insn->retpoline_safe = true;
 | 
				
			||||||
| 
						 | 
					@ -1399,7 +1416,7 @@ static void add_retpoline_call(struct objtool_file *file, struct instruction *in
 | 
				
			||||||
	 */
 | 
						 */
 | 
				
			||||||
	remove_insn_ops(insn);
 | 
						remove_insn_ops(insn);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	annotate_call_site(file, insn, false);
 | 
						return annotate_call_site(file, insn, false);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static void add_return_call(struct objtool_file *file, struct instruction *insn, bool add)
 | 
					static void add_return_call(struct objtool_file *file, struct instruction *insn, bool add)
 | 
				
			||||||
| 
						 | 
					@ -1468,6 +1485,7 @@ static int add_jump_destinations(struct objtool_file *file)
 | 
				
			||||||
	struct reloc *reloc;
 | 
						struct reloc *reloc;
 | 
				
			||||||
	struct section *dest_sec;
 | 
						struct section *dest_sec;
 | 
				
			||||||
	unsigned long dest_off;
 | 
						unsigned long dest_off;
 | 
				
			||||||
 | 
						int ret;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	for_each_insn(file, insn) {
 | 
						for_each_insn(file, insn) {
 | 
				
			||||||
		if (insn->jump_dest) {
 | 
							if (insn->jump_dest) {
 | 
				
			||||||
| 
						 | 
					@ -1488,7 +1506,9 @@ static int add_jump_destinations(struct objtool_file *file)
 | 
				
			||||||
			dest_sec = reloc->sym->sec;
 | 
								dest_sec = reloc->sym->sec;
 | 
				
			||||||
			dest_off = arch_dest_reloc_offset(reloc_addend(reloc));
 | 
								dest_off = arch_dest_reloc_offset(reloc_addend(reloc));
 | 
				
			||||||
		} else if (reloc->sym->retpoline_thunk) {
 | 
							} else if (reloc->sym->retpoline_thunk) {
 | 
				
			||||||
			add_retpoline_call(file, insn);
 | 
								ret = add_retpoline_call(file, insn);
 | 
				
			||||||
 | 
								if (ret)
 | 
				
			||||||
 | 
									return ret;
 | 
				
			||||||
			continue;
 | 
								continue;
 | 
				
			||||||
		} else if (reloc->sym->return_thunk) {
 | 
							} else if (reloc->sym->return_thunk) {
 | 
				
			||||||
			add_return_call(file, insn, true);
 | 
								add_return_call(file, insn, true);
 | 
				
			||||||
| 
						 | 
					@ -1498,7 +1518,9 @@ static int add_jump_destinations(struct objtool_file *file)
 | 
				
			||||||
			 * External sibling call or internal sibling call with
 | 
								 * External sibling call or internal sibling call with
 | 
				
			||||||
			 * STT_FUNC reloc.
 | 
								 * STT_FUNC reloc.
 | 
				
			||||||
			 */
 | 
								 */
 | 
				
			||||||
			add_call_dest(file, insn, reloc->sym, true);
 | 
								ret = add_call_dest(file, insn, reloc->sym, true);
 | 
				
			||||||
 | 
								if (ret)
 | 
				
			||||||
 | 
									return ret;
 | 
				
			||||||
			continue;
 | 
								continue;
 | 
				
			||||||
		} else if (reloc->sym->sec->idx) {
 | 
							} else if (reloc->sym->sec->idx) {
 | 
				
			||||||
			dest_sec = reloc->sym->sec;
 | 
								dest_sec = reloc->sym->sec;
 | 
				
			||||||
| 
						 | 
					@ -1538,7 +1560,9 @@ static int add_jump_destinations(struct objtool_file *file)
 | 
				
			||||||
		 */
 | 
							 */
 | 
				
			||||||
		if (jump_dest->sym && jump_dest->offset == jump_dest->sym->offset) {
 | 
							if (jump_dest->sym && jump_dest->offset == jump_dest->sym->offset) {
 | 
				
			||||||
			if (jump_dest->sym->retpoline_thunk) {
 | 
								if (jump_dest->sym->retpoline_thunk) {
 | 
				
			||||||
				add_retpoline_call(file, insn);
 | 
									ret = add_retpoline_call(file, insn);
 | 
				
			||||||
 | 
									if (ret)
 | 
				
			||||||
 | 
										return ret;
 | 
				
			||||||
				continue;
 | 
									continue;
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
			if (jump_dest->sym->return_thunk) {
 | 
								if (jump_dest->sym->return_thunk) {
 | 
				
			||||||
| 
						 | 
					@ -1580,7 +1604,9 @@ static int add_jump_destinations(struct objtool_file *file)
 | 
				
			||||||
			 * Internal sibling call without reloc or with
 | 
								 * Internal sibling call without reloc or with
 | 
				
			||||||
			 * STT_SECTION reloc.
 | 
								 * STT_SECTION reloc.
 | 
				
			||||||
			 */
 | 
								 */
 | 
				
			||||||
			add_call_dest(file, insn, insn_func(jump_dest), true);
 | 
								ret = add_call_dest(file, insn, insn_func(jump_dest), true);
 | 
				
			||||||
 | 
								if (ret)
 | 
				
			||||||
 | 
									return ret;
 | 
				
			||||||
			continue;
 | 
								continue;
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1610,6 +1636,7 @@ static int add_call_destinations(struct objtool_file *file)
 | 
				
			||||||
	unsigned long dest_off;
 | 
						unsigned long dest_off;
 | 
				
			||||||
	struct symbol *dest;
 | 
						struct symbol *dest;
 | 
				
			||||||
	struct reloc *reloc;
 | 
						struct reloc *reloc;
 | 
				
			||||||
 | 
						int ret;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	for_each_insn(file, insn) {
 | 
						for_each_insn(file, insn) {
 | 
				
			||||||
		struct symbol *func = insn_func(insn);
 | 
							struct symbol *func = insn_func(insn);
 | 
				
			||||||
| 
						 | 
					@ -1621,7 +1648,9 @@ static int add_call_destinations(struct objtool_file *file)
 | 
				
			||||||
			dest_off = arch_jump_destination(insn);
 | 
								dest_off = arch_jump_destination(insn);
 | 
				
			||||||
			dest = find_call_destination(insn->sec, dest_off);
 | 
								dest = find_call_destination(insn->sec, dest_off);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			add_call_dest(file, insn, dest, false);
 | 
								ret = add_call_dest(file, insn, dest, false);
 | 
				
			||||||
 | 
								if (ret)
 | 
				
			||||||
 | 
									return ret;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			if (func && func->ignore)
 | 
								if (func && func->ignore)
 | 
				
			||||||
				continue;
 | 
									continue;
 | 
				
			||||||
| 
						 | 
					@ -1645,13 +1674,20 @@ static int add_call_destinations(struct objtool_file *file)
 | 
				
			||||||
				return -1;
 | 
									return -1;
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			add_call_dest(file, insn, dest, false);
 | 
								ret = add_call_dest(file, insn, dest, false);
 | 
				
			||||||
 | 
								if (ret)
 | 
				
			||||||
 | 
									return ret;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		} else if (reloc->sym->retpoline_thunk) {
 | 
							} else if (reloc->sym->retpoline_thunk) {
 | 
				
			||||||
			add_retpoline_call(file, insn);
 | 
								ret = add_retpoline_call(file, insn);
 | 
				
			||||||
 | 
								if (ret)
 | 
				
			||||||
 | 
									return ret;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		} else
 | 
							} else {
 | 
				
			||||||
			add_call_dest(file, insn, reloc->sym, false);
 | 
								ret = add_call_dest(file, insn, reloc->sym, false);
 | 
				
			||||||
 | 
								if (ret)
 | 
				
			||||||
 | 
									return ret;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	return 0;
 | 
						return 0;
 | 
				
			||||||
| 
						 | 
					@ -1674,15 +1710,15 @@ static int handle_group_alt(struct objtool_file *file,
 | 
				
			||||||
	if (!orig_alt_group) {
 | 
						if (!orig_alt_group) {
 | 
				
			||||||
		struct instruction *last_orig_insn = NULL;
 | 
							struct instruction *last_orig_insn = NULL;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		orig_alt_group = malloc(sizeof(*orig_alt_group));
 | 
							orig_alt_group = calloc(1, sizeof(*orig_alt_group));
 | 
				
			||||||
		if (!orig_alt_group) {
 | 
							if (!orig_alt_group) {
 | 
				
			||||||
			WARN("malloc failed");
 | 
								WARN_GLIBC("calloc");
 | 
				
			||||||
			return -1;
 | 
								return -1;
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		orig_alt_group->cfi = calloc(special_alt->orig_len,
 | 
							orig_alt_group->cfi = calloc(special_alt->orig_len,
 | 
				
			||||||
					     sizeof(struct cfi_state *));
 | 
										     sizeof(struct cfi_state *));
 | 
				
			||||||
		if (!orig_alt_group->cfi) {
 | 
							if (!orig_alt_group->cfi) {
 | 
				
			||||||
			WARN("calloc failed");
 | 
								WARN_GLIBC("calloc");
 | 
				
			||||||
			return -1;
 | 
								return -1;
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1711,9 +1747,9 @@ static int handle_group_alt(struct objtool_file *file,
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	new_alt_group = malloc(sizeof(*new_alt_group));
 | 
						new_alt_group = calloc(1, sizeof(*new_alt_group));
 | 
				
			||||||
	if (!new_alt_group) {
 | 
						if (!new_alt_group) {
 | 
				
			||||||
		WARN("malloc failed");
 | 
							WARN_GLIBC("calloc");
 | 
				
			||||||
		return -1;
 | 
							return -1;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1725,9 +1761,9 @@ static int handle_group_alt(struct objtool_file *file,
 | 
				
			||||||
		 * instruction affects the stack, the instruction after it (the
 | 
							 * instruction affects the stack, the instruction after it (the
 | 
				
			||||||
		 * nop) will propagate the new state to the shared CFI array.
 | 
							 * nop) will propagate the new state to the shared CFI array.
 | 
				
			||||||
		 */
 | 
							 */
 | 
				
			||||||
		nop = malloc(sizeof(*nop));
 | 
							nop = calloc(1, sizeof(*nop));
 | 
				
			||||||
		if (!nop) {
 | 
							if (!nop) {
 | 
				
			||||||
			WARN("malloc failed");
 | 
								WARN_GLIBC("calloc");
 | 
				
			||||||
			return -1;
 | 
								return -1;
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		memset(nop, 0, sizeof(*nop));
 | 
							memset(nop, 0, sizeof(*nop));
 | 
				
			||||||
| 
						 | 
					@ -1827,9 +1863,13 @@ static int handle_jump_alt(struct objtool_file *file,
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		if (reloc)
 | 
							if (reloc)
 | 
				
			||||||
			set_reloc_type(file->elf, reloc, R_NONE);
 | 
								set_reloc_type(file->elf, reloc, R_NONE);
 | 
				
			||||||
		elf_write_insn(file->elf, orig_insn->sec,
 | 
					
 | 
				
			||||||
			       orig_insn->offset, orig_insn->len,
 | 
							if (elf_write_insn(file->elf, orig_insn->sec,
 | 
				
			||||||
			       arch_nop_insn(orig_insn->len));
 | 
									   orig_insn->offset, orig_insn->len,
 | 
				
			||||||
 | 
									   arch_nop_insn(orig_insn->len))) {
 | 
				
			||||||
 | 
								return -1;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		orig_insn->type = INSN_NOP;
 | 
							orig_insn->type = INSN_NOP;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1865,9 +1905,8 @@ static int add_special_section_alts(struct objtool_file *file)
 | 
				
			||||||
	struct alternative *alt;
 | 
						struct alternative *alt;
 | 
				
			||||||
	int ret;
 | 
						int ret;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	ret = special_get_alts(file->elf, &special_alts);
 | 
						if (special_get_alts(file->elf, &special_alts))
 | 
				
			||||||
	if (ret)
 | 
							return -1;
 | 
				
			||||||
		return ret;
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
	list_for_each_entry_safe(special_alt, tmp, &special_alts, list) {
 | 
						list_for_each_entry_safe(special_alt, tmp, &special_alts, list) {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1876,8 +1915,7 @@ static int add_special_section_alts(struct objtool_file *file)
 | 
				
			||||||
		if (!orig_insn) {
 | 
							if (!orig_insn) {
 | 
				
			||||||
			WARN_FUNC("special: can't find orig instruction",
 | 
								WARN_FUNC("special: can't find orig instruction",
 | 
				
			||||||
				  special_alt->orig_sec, special_alt->orig_off);
 | 
									  special_alt->orig_sec, special_alt->orig_off);
 | 
				
			||||||
			ret = -1;
 | 
								return -1;
 | 
				
			||||||
			goto out;
 | 
					 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		new_insn = NULL;
 | 
							new_insn = NULL;
 | 
				
			||||||
| 
						 | 
					@ -1888,8 +1926,7 @@ static int add_special_section_alts(struct objtool_file *file)
 | 
				
			||||||
				WARN_FUNC("special: can't find new instruction",
 | 
									WARN_FUNC("special: can't find new instruction",
 | 
				
			||||||
					  special_alt->new_sec,
 | 
										  special_alt->new_sec,
 | 
				
			||||||
					  special_alt->new_off);
 | 
										  special_alt->new_off);
 | 
				
			||||||
				ret = -1;
 | 
									return -1;
 | 
				
			||||||
				goto out;
 | 
					 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1902,19 +1939,19 @@ static int add_special_section_alts(struct objtool_file *file)
 | 
				
			||||||
			ret = handle_group_alt(file, special_alt, orig_insn,
 | 
								ret = handle_group_alt(file, special_alt, orig_insn,
 | 
				
			||||||
					       &new_insn);
 | 
										       &new_insn);
 | 
				
			||||||
			if (ret)
 | 
								if (ret)
 | 
				
			||||||
				goto out;
 | 
									return ret;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		} else if (special_alt->jump_or_nop) {
 | 
							} else if (special_alt->jump_or_nop) {
 | 
				
			||||||
			ret = handle_jump_alt(file, special_alt, orig_insn,
 | 
								ret = handle_jump_alt(file, special_alt, orig_insn,
 | 
				
			||||||
					      &new_insn);
 | 
										      &new_insn);
 | 
				
			||||||
			if (ret)
 | 
								if (ret)
 | 
				
			||||||
				goto out;
 | 
									return ret;
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		alt = malloc(sizeof(*alt));
 | 
							alt = calloc(1, sizeof(*alt));
 | 
				
			||||||
		if (!alt) {
 | 
							if (!alt) {
 | 
				
			||||||
			WARN("malloc failed");
 | 
								WARN_GLIBC("calloc");
 | 
				
			||||||
			ret = -1;
 | 
								return -1;
 | 
				
			||||||
			goto out;
 | 
					 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		alt->insn = new_insn;
 | 
							alt->insn = new_insn;
 | 
				
			||||||
| 
						 | 
					@ -1931,8 +1968,7 @@ static int add_special_section_alts(struct objtool_file *file)
 | 
				
			||||||
		printf("long:\t%ld\t%ld\n", file->jl_nop_long, file->jl_long);
 | 
							printf("long:\t%ld\t%ld\n", file->jl_nop_long, file->jl_long);
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
out:
 | 
						return 0;
 | 
				
			||||||
	return ret;
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
__weak unsigned long arch_jump_table_sym_offset(struct reloc *reloc, struct reloc *table)
 | 
					__weak unsigned long arch_jump_table_sym_offset(struct reloc *reloc, struct reloc *table)
 | 
				
			||||||
| 
						 | 
					@ -1989,9 +2025,9 @@ static int add_jump_table(struct objtool_file *file, struct instruction *insn)
 | 
				
			||||||
		if (!insn_func(dest_insn) || insn_func(dest_insn)->pfunc != pfunc)
 | 
							if (!insn_func(dest_insn) || insn_func(dest_insn)->pfunc != pfunc)
 | 
				
			||||||
			break;
 | 
								break;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		alt = malloc(sizeof(*alt));
 | 
							alt = calloc(1, sizeof(*alt));
 | 
				
			||||||
		if (!alt) {
 | 
							if (!alt) {
 | 
				
			||||||
			WARN("malloc failed");
 | 
								WARN_GLIBC("calloc");
 | 
				
			||||||
			return -1;
 | 
								return -1;
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -2039,7 +2075,7 @@ static void find_jump_table(struct objtool_file *file, struct symbol *func,
 | 
				
			||||||
		    insn->jump_dest &&
 | 
							    insn->jump_dest &&
 | 
				
			||||||
		    (insn->jump_dest->offset <= insn->offset ||
 | 
							    (insn->jump_dest->offset <= insn->offset ||
 | 
				
			||||||
		     insn->jump_dest->offset > orig_insn->offset))
 | 
							     insn->jump_dest->offset > orig_insn->offset))
 | 
				
			||||||
		    break;
 | 
								break;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		table_reloc = arch_find_switch_table(file, insn, &table_size);
 | 
							table_reloc = arch_find_switch_table(file, insn, &table_size);
 | 
				
			||||||
		if (!table_reloc)
 | 
							if (!table_reloc)
 | 
				
			||||||
| 
						 | 
					@ -2103,7 +2139,6 @@ static int add_func_jump_tables(struct objtool_file *file,
 | 
				
			||||||
		if (!insn_jump_table(insn))
 | 
							if (!insn_jump_table(insn))
 | 
				
			||||||
			continue;
 | 
								continue;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					 | 
				
			||||||
		ret = add_jump_table(file, insn);
 | 
							ret = add_jump_table(file, insn);
 | 
				
			||||||
		if (ret)
 | 
							if (ret)
 | 
				
			||||||
			return ret;
 | 
								return ret;
 | 
				
			||||||
| 
						 | 
					@ -2221,6 +2256,7 @@ static int read_unwind_hints(struct objtool_file *file)
 | 
				
			||||||
			if (sym && sym->bind == STB_GLOBAL) {
 | 
								if (sym && sym->bind == STB_GLOBAL) {
 | 
				
			||||||
				if (opts.ibt && insn->type != INSN_ENDBR && !insn->noendbr) {
 | 
									if (opts.ibt && insn->type != INSN_ENDBR && !insn->noendbr) {
 | 
				
			||||||
					WARN_INSN(insn, "UNWIND_HINT_IRET_REGS without ENDBR");
 | 
										WARN_INSN(insn, "UNWIND_HINT_IRET_REGS without ENDBR");
 | 
				
			||||||
 | 
										return -1;
 | 
				
			||||||
				}
 | 
									}
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
| 
						 | 
					@ -2390,7 +2426,7 @@ static int __annotate_late(struct objtool_file *file, int type, struct instructi
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	default:
 | 
						default:
 | 
				
			||||||
		WARN_INSN(insn, "Unknown annotation type: %d", type);
 | 
							WARN_INSN(insn, "Unknown annotation type: %d", type);
 | 
				
			||||||
		break;
 | 
							return -1;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	return 0;
 | 
						return 0;
 | 
				
			||||||
| 
						 | 
					@ -2503,7 +2539,10 @@ static int decode_sections(struct objtool_file *file)
 | 
				
			||||||
	if (ret)
 | 
						if (ret)
 | 
				
			||||||
		return ret;
 | 
							return ret;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	add_ignores(file);
 | 
						ret = add_ignores(file);
 | 
				
			||||||
 | 
						if (ret)
 | 
				
			||||||
 | 
							return ret;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	add_uaccess_safe(file);
 | 
						add_uaccess_safe(file);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	ret = read_annotate(file, __annotate_early);
 | 
						ret = read_annotate(file, __annotate_early);
 | 
				
			||||||
| 
						 | 
					@ -2723,7 +2762,7 @@ static int update_cfi_state(struct instruction *insn,
 | 
				
			||||||
	if (cfa->base == CFI_UNDEFINED) {
 | 
						if (cfa->base == CFI_UNDEFINED) {
 | 
				
			||||||
		if (insn_func(insn)) {
 | 
							if (insn_func(insn)) {
 | 
				
			||||||
			WARN_INSN(insn, "undefined stack state");
 | 
								WARN_INSN(insn, "undefined stack state");
 | 
				
			||||||
			return -1;
 | 
								return 1;
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		return 0;
 | 
							return 0;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
| 
						 | 
					@ -3166,9 +3205,8 @@ static int propagate_alt_cfi(struct objtool_file *file, struct instruction *insn
 | 
				
			||||||
		if (cficmp(alt_cfi[group_off], insn->cfi)) {
 | 
							if (cficmp(alt_cfi[group_off], insn->cfi)) {
 | 
				
			||||||
			struct alt_group *orig_group = insn->alt_group->orig_group ?: insn->alt_group;
 | 
								struct alt_group *orig_group = insn->alt_group->orig_group ?: insn->alt_group;
 | 
				
			||||||
			struct instruction *orig = orig_group->first_insn;
 | 
								struct instruction *orig = orig_group->first_insn;
 | 
				
			||||||
			char *where = offstr(insn->sec, insn->offset);
 | 
								WARN_INSN(orig, "stack layout conflict in alternatives: %s",
 | 
				
			||||||
			WARN_INSN(orig, "stack layout conflict in alternatives: %s", where);
 | 
									  offstr(insn->sec, insn->offset));
 | 
				
			||||||
			free(where);
 | 
					 | 
				
			||||||
			return -1;
 | 
								return -1;
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
| 
						 | 
					@ -3181,11 +3219,13 @@ static int handle_insn_ops(struct instruction *insn,
 | 
				
			||||||
			   struct insn_state *state)
 | 
								   struct insn_state *state)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	struct stack_op *op;
 | 
						struct stack_op *op;
 | 
				
			||||||
 | 
						int ret;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	for (op = insn->stack_ops; op; op = op->next) {
 | 
						for (op = insn->stack_ops; op; op = op->next) {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		if (update_cfi_state(insn, next_insn, &state->cfi, op))
 | 
							ret = update_cfi_state(insn, next_insn, &state->cfi, op);
 | 
				
			||||||
			return 1;
 | 
							if (ret)
 | 
				
			||||||
 | 
								return ret;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		if (!opts.uaccess || !insn->alt_group)
 | 
							if (!opts.uaccess || !insn->alt_group)
 | 
				
			||||||
			continue;
 | 
								continue;
 | 
				
			||||||
| 
						 | 
					@ -3229,36 +3269,41 @@ static bool insn_cfi_match(struct instruction *insn, struct cfi_state *cfi2)
 | 
				
			||||||
		WARN_INSN(insn, "stack state mismatch: cfa1=%d%+d cfa2=%d%+d",
 | 
							WARN_INSN(insn, "stack state mismatch: cfa1=%d%+d cfa2=%d%+d",
 | 
				
			||||||
			  cfi1->cfa.base, cfi1->cfa.offset,
 | 
								  cfi1->cfa.base, cfi1->cfa.offset,
 | 
				
			||||||
			  cfi2->cfa.base, cfi2->cfa.offset);
 | 
								  cfi2->cfa.base, cfi2->cfa.offset);
 | 
				
			||||||
 | 
							return false;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	} else if (memcmp(&cfi1->regs, &cfi2->regs, sizeof(cfi1->regs))) {
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (memcmp(&cfi1->regs, &cfi2->regs, sizeof(cfi1->regs))) {
 | 
				
			||||||
		for (i = 0; i < CFI_NUM_REGS; i++) {
 | 
							for (i = 0; i < CFI_NUM_REGS; i++) {
 | 
				
			||||||
			if (!memcmp(&cfi1->regs[i], &cfi2->regs[i],
 | 
					
 | 
				
			||||||
				    sizeof(struct cfi_reg)))
 | 
								if (!memcmp(&cfi1->regs[i], &cfi2->regs[i], sizeof(struct cfi_reg)))
 | 
				
			||||||
				continue;
 | 
									continue;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			WARN_INSN(insn, "stack state mismatch: reg1[%d]=%d%+d reg2[%d]=%d%+d",
 | 
								WARN_INSN(insn, "stack state mismatch: reg1[%d]=%d%+d reg2[%d]=%d%+d",
 | 
				
			||||||
				  i, cfi1->regs[i].base, cfi1->regs[i].offset,
 | 
									  i, cfi1->regs[i].base, cfi1->regs[i].offset,
 | 
				
			||||||
				  i, cfi2->regs[i].base, cfi2->regs[i].offset);
 | 
									  i, cfi2->regs[i].base, cfi2->regs[i].offset);
 | 
				
			||||||
			break;
 | 
					 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
							return false;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	} else if (cfi1->type != cfi2->type) {
 | 
						if (cfi1->type != cfi2->type) {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		WARN_INSN(insn, "stack state mismatch: type1=%d type2=%d",
 | 
							WARN_INSN(insn, "stack state mismatch: type1=%d type2=%d",
 | 
				
			||||||
			  cfi1->type, cfi2->type);
 | 
								  cfi1->type, cfi2->type);
 | 
				
			||||||
 | 
							return false;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	} else if (cfi1->drap != cfi2->drap ||
 | 
						if (cfi1->drap != cfi2->drap ||
 | 
				
			||||||
		   (cfi1->drap && cfi1->drap_reg != cfi2->drap_reg) ||
 | 
							   (cfi1->drap && cfi1->drap_reg != cfi2->drap_reg) ||
 | 
				
			||||||
		   (cfi1->drap && cfi1->drap_offset != cfi2->drap_offset)) {
 | 
							   (cfi1->drap && cfi1->drap_offset != cfi2->drap_offset)) {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		WARN_INSN(insn, "stack state mismatch: drap1=%d(%d,%d) drap2=%d(%d,%d)",
 | 
							WARN_INSN(insn, "stack state mismatch: drap1=%d(%d,%d) drap2=%d(%d,%d)",
 | 
				
			||||||
			  cfi1->drap, cfi1->drap_reg, cfi1->drap_offset,
 | 
								  cfi1->drap, cfi1->drap_reg, cfi1->drap_offset,
 | 
				
			||||||
			  cfi2->drap, cfi2->drap_reg, cfi2->drap_offset);
 | 
								  cfi2->drap, cfi2->drap_reg, cfi2->drap_offset);
 | 
				
			||||||
 | 
							return false;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	} else
 | 
						return true;
 | 
				
			||||||
		return true;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	return false;
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static inline bool func_uaccess_safe(struct symbol *func)
 | 
					static inline bool func_uaccess_safe(struct symbol *func)
 | 
				
			||||||
| 
						 | 
					@ -3490,6 +3535,8 @@ static int validate_branch(struct objtool_file *file, struct symbol *func,
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			WARN("%s() falls through to next function %s()",
 | 
								WARN("%s() falls through to next function %s()",
 | 
				
			||||||
			     func->name, insn_func(insn)->name);
 | 
								     func->name, insn_func(insn)->name);
 | 
				
			||||||
 | 
								func->warnings++;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			return 1;
 | 
								return 1;
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -3597,9 +3644,6 @@ static int validate_branch(struct objtool_file *file, struct symbol *func,
 | 
				
			||||||
				return 1;
 | 
									return 1;
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			if (insn->dead_end)
 | 
					 | 
				
			||||||
				return 0;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
			break;
 | 
								break;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		case INSN_JUMP_CONDITIONAL:
 | 
							case INSN_JUMP_CONDITIONAL:
 | 
				
			||||||
| 
						 | 
					@ -3706,7 +3750,9 @@ static int validate_branch(struct objtool_file *file, struct symbol *func,
 | 
				
			||||||
			if (file->ignore_unreachables)
 | 
								if (file->ignore_unreachables)
 | 
				
			||||||
				return 0;
 | 
									return 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			WARN("%s: unexpected end of section", sec->name);
 | 
								WARN("%s%sunexpected end of section %s",
 | 
				
			||||||
 | 
								     func ? func->name : "", func ? ": " : "",
 | 
				
			||||||
 | 
								     sec->name);
 | 
				
			||||||
			return 1;
 | 
								return 1;
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -3796,7 +3842,7 @@ static int validate_unret(struct objtool_file *file, struct instruction *insn)
 | 
				
			||||||
			if (!is_sibling_call(insn)) {
 | 
								if (!is_sibling_call(insn)) {
 | 
				
			||||||
				if (!insn->jump_dest) {
 | 
									if (!insn->jump_dest) {
 | 
				
			||||||
					WARN_INSN(insn, "unresolved jump target after linking?!?");
 | 
										WARN_INSN(insn, "unresolved jump target after linking?!?");
 | 
				
			||||||
					return -1;
 | 
										return 1;
 | 
				
			||||||
				}
 | 
									}
 | 
				
			||||||
				ret = validate_unret(file, insn->jump_dest);
 | 
									ret = validate_unret(file, insn->jump_dest);
 | 
				
			||||||
				if (ret) {
 | 
									if (ret) {
 | 
				
			||||||
| 
						 | 
					@ -3818,7 +3864,7 @@ static int validate_unret(struct objtool_file *file, struct instruction *insn)
 | 
				
			||||||
			if (!dest) {
 | 
								if (!dest) {
 | 
				
			||||||
				WARN("Unresolved function after linking!?: %s",
 | 
									WARN("Unresolved function after linking!?: %s",
 | 
				
			||||||
				     insn_call_dest(insn)->name);
 | 
									     insn_call_dest(insn)->name);
 | 
				
			||||||
				return -1;
 | 
									return 1;
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			ret = validate_unret(file, dest);
 | 
								ret = validate_unret(file, dest);
 | 
				
			||||||
| 
						 | 
					@ -3847,7 +3893,7 @@ static int validate_unret(struct objtool_file *file, struct instruction *insn)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		if (!next) {
 | 
							if (!next) {
 | 
				
			||||||
			WARN_INSN(insn, "teh end!");
 | 
								WARN_INSN(insn, "teh end!");
 | 
				
			||||||
			return -1;
 | 
								return 1;
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		insn = next;
 | 
							insn = next;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
| 
						 | 
					@ -3862,18 +3908,13 @@ static int validate_unret(struct objtool_file *file, struct instruction *insn)
 | 
				
			||||||
static int validate_unrets(struct objtool_file *file)
 | 
					static int validate_unrets(struct objtool_file *file)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	struct instruction *insn;
 | 
						struct instruction *insn;
 | 
				
			||||||
	int ret, warnings = 0;
 | 
						int warnings = 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	for_each_insn(file, insn) {
 | 
						for_each_insn(file, insn) {
 | 
				
			||||||
		if (!insn->unret)
 | 
							if (!insn->unret)
 | 
				
			||||||
			continue;
 | 
								continue;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		ret = validate_unret(file, insn);
 | 
							warnings += validate_unret(file, insn);
 | 
				
			||||||
		if (ret < 0) {
 | 
					 | 
				
			||||||
			WARN_INSN(insn, "Failed UNRET validation");
 | 
					 | 
				
			||||||
			return ret;
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
		warnings += ret;
 | 
					 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	return warnings;
 | 
						return warnings;
 | 
				
			||||||
| 
						 | 
					@ -3899,13 +3940,13 @@ static int validate_retpoline(struct objtool_file *file)
 | 
				
			||||||
		if (insn->type == INSN_RETURN) {
 | 
							if (insn->type == INSN_RETURN) {
 | 
				
			||||||
			if (opts.rethunk) {
 | 
								if (opts.rethunk) {
 | 
				
			||||||
				WARN_INSN(insn, "'naked' return found in MITIGATION_RETHUNK build");
 | 
									WARN_INSN(insn, "'naked' return found in MITIGATION_RETHUNK build");
 | 
				
			||||||
			} else
 | 
									warnings++;
 | 
				
			||||||
				continue;
 | 
								}
 | 
				
			||||||
		} else {
 | 
								continue;
 | 
				
			||||||
			WARN_INSN(insn, "indirect %s found in MITIGATION_RETPOLINE build",
 | 
					 | 
				
			||||||
				  insn->type == INSN_JUMP_DYNAMIC ? "jump" : "call");
 | 
					 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							WARN_INSN(insn, "indirect %s found in MITIGATION_RETPOLINE build",
 | 
				
			||||||
 | 
								  insn->type == INSN_JUMP_DYNAMIC ? "jump" : "call");
 | 
				
			||||||
		warnings++;
 | 
							warnings++;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -4472,7 +4513,7 @@ static int validate_reachable_instructions(struct objtool_file *file)
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/* 'funcs' is a space-separated list of function names */
 | 
					/* 'funcs' is a space-separated list of function names */
 | 
				
			||||||
static int disas_funcs(const char *funcs)
 | 
					static void disas_funcs(const char *funcs)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	const char *objdump_str, *cross_compile;
 | 
						const char *objdump_str, *cross_compile;
 | 
				
			||||||
	int size, ret;
 | 
						int size, ret;
 | 
				
			||||||
| 
						 | 
					@ -4505,7 +4546,7 @@ static int disas_funcs(const char *funcs)
 | 
				
			||||||
	size = snprintf(NULL, 0, objdump_str, cross_compile, objname, funcs) + 1;
 | 
						size = snprintf(NULL, 0, objdump_str, cross_compile, objname, funcs) + 1;
 | 
				
			||||||
	if (size <= 0) {
 | 
						if (size <= 0) {
 | 
				
			||||||
		WARN("objdump string size calculation failed");
 | 
							WARN("objdump string size calculation failed");
 | 
				
			||||||
		return -1;
 | 
							return;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	cmd = malloc(size);
 | 
						cmd = malloc(size);
 | 
				
			||||||
| 
						 | 
					@ -4515,13 +4556,11 @@ static int disas_funcs(const char *funcs)
 | 
				
			||||||
	ret = system(cmd);
 | 
						ret = system(cmd);
 | 
				
			||||||
	if (ret) {
 | 
						if (ret) {
 | 
				
			||||||
		WARN("disassembly failed: %d", ret);
 | 
							WARN("disassembly failed: %d", ret);
 | 
				
			||||||
		return -1;
 | 
							return;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					 | 
				
			||||||
	return 0;
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static int disas_warned_funcs(struct objtool_file *file)
 | 
					static void disas_warned_funcs(struct objtool_file *file)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	struct symbol *sym;
 | 
						struct symbol *sym;
 | 
				
			||||||
	char *funcs = NULL, *tmp;
 | 
						char *funcs = NULL, *tmp;
 | 
				
			||||||
| 
						 | 
					@ -4530,9 +4569,17 @@ static int disas_warned_funcs(struct objtool_file *file)
 | 
				
			||||||
		if (sym->warnings) {
 | 
							if (sym->warnings) {
 | 
				
			||||||
			if (!funcs) {
 | 
								if (!funcs) {
 | 
				
			||||||
				funcs = malloc(strlen(sym->name) + 1);
 | 
									funcs = malloc(strlen(sym->name) + 1);
 | 
				
			||||||
 | 
									if (!funcs) {
 | 
				
			||||||
 | 
										WARN_GLIBC("malloc");
 | 
				
			||||||
 | 
										return;
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
				strcpy(funcs, sym->name);
 | 
									strcpy(funcs, sym->name);
 | 
				
			||||||
			} else {
 | 
								} else {
 | 
				
			||||||
				tmp = malloc(strlen(funcs) + strlen(sym->name) + 2);
 | 
									tmp = malloc(strlen(funcs) + strlen(sym->name) + 2);
 | 
				
			||||||
 | 
									if (!tmp) {
 | 
				
			||||||
 | 
										WARN_GLIBC("malloc");
 | 
				
			||||||
 | 
										return;
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
				sprintf(tmp, "%s %s", funcs, sym->name);
 | 
									sprintf(tmp, "%s %s", funcs, sym->name);
 | 
				
			||||||
				free(funcs);
 | 
									free(funcs);
 | 
				
			||||||
				funcs = tmp;
 | 
									funcs = tmp;
 | 
				
			||||||
| 
						 | 
					@ -4542,8 +4589,6 @@ static int disas_warned_funcs(struct objtool_file *file)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (funcs)
 | 
						if (funcs)
 | 
				
			||||||
		disas_funcs(funcs);
 | 
							disas_funcs(funcs);
 | 
				
			||||||
 | 
					 | 
				
			||||||
	return 0;
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
struct insn_chunk {
 | 
					struct insn_chunk {
 | 
				
			||||||
| 
						 | 
					@ -4576,7 +4621,7 @@ static void free_insns(struct objtool_file *file)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
int check(struct objtool_file *file)
 | 
					int check(struct objtool_file *file)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	int ret, warnings = 0;
 | 
						int ret = 0, warnings = 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	arch_initial_func_cfi_state(&initial_func_cfi);
 | 
						arch_initial_func_cfi_state(&initial_func_cfi);
 | 
				
			||||||
	init_cfi_state(&init_cfi);
 | 
						init_cfi_state(&init_cfi);
 | 
				
			||||||
| 
						 | 
					@ -4594,44 +4639,27 @@ int check(struct objtool_file *file)
 | 
				
			||||||
	cfi_hash_add(&func_cfi);
 | 
						cfi_hash_add(&func_cfi);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	ret = decode_sections(file);
 | 
						ret = decode_sections(file);
 | 
				
			||||||
	if (ret < 0)
 | 
						if (ret)
 | 
				
			||||||
		goto out;
 | 
							goto out;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	warnings += ret;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	if (!nr_insns)
 | 
						if (!nr_insns)
 | 
				
			||||||
		goto out;
 | 
							goto out;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (opts.retpoline) {
 | 
						if (opts.retpoline)
 | 
				
			||||||
		ret = validate_retpoline(file);
 | 
							warnings += validate_retpoline(file);
 | 
				
			||||||
		if (ret < 0)
 | 
					 | 
				
			||||||
			goto out;
 | 
					 | 
				
			||||||
		warnings += ret;
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (opts.stackval || opts.orc || opts.uaccess) {
 | 
						if (opts.stackval || opts.orc || opts.uaccess) {
 | 
				
			||||||
		ret = validate_functions(file);
 | 
							int w = 0;
 | 
				
			||||||
		if (ret < 0)
 | 
					 | 
				
			||||||
			goto out;
 | 
					 | 
				
			||||||
		warnings += ret;
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
		ret = validate_unwind_hints(file, NULL);
 | 
							w += validate_functions(file);
 | 
				
			||||||
		if (ret < 0)
 | 
							w += validate_unwind_hints(file, NULL);
 | 
				
			||||||
			goto out;
 | 
							if (!w)
 | 
				
			||||||
		warnings += ret;
 | 
								w += validate_reachable_instructions(file);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		if (!warnings) {
 | 
							warnings += w;
 | 
				
			||||||
			ret = validate_reachable_instructions(file);
 | 
					 | 
				
			||||||
			if (ret < 0)
 | 
					 | 
				
			||||||
				goto out;
 | 
					 | 
				
			||||||
			warnings += ret;
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
	} else if (opts.noinstr) {
 | 
						} else if (opts.noinstr) {
 | 
				
			||||||
		ret = validate_noinstr_sections(file);
 | 
							warnings += validate_noinstr_sections(file);
 | 
				
			||||||
		if (ret < 0)
 | 
					 | 
				
			||||||
			goto out;
 | 
					 | 
				
			||||||
		warnings += ret;
 | 
					 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (opts.unret) {
 | 
						if (opts.unret) {
 | 
				
			||||||
| 
						 | 
					@ -4639,87 +4667,67 @@ int check(struct objtool_file *file)
 | 
				
			||||||
		 * Must be after validate_branch() and friends, it plays
 | 
							 * Must be after validate_branch() and friends, it plays
 | 
				
			||||||
		 * further games with insn->visited.
 | 
							 * further games with insn->visited.
 | 
				
			||||||
		 */
 | 
							 */
 | 
				
			||||||
		ret = validate_unrets(file);
 | 
							warnings += validate_unrets(file);
 | 
				
			||||||
		if (ret < 0)
 | 
					 | 
				
			||||||
			goto out;
 | 
					 | 
				
			||||||
		warnings += ret;
 | 
					 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (opts.ibt) {
 | 
						if (opts.ibt)
 | 
				
			||||||
		ret = validate_ibt(file);
 | 
							warnings += validate_ibt(file);
 | 
				
			||||||
		if (ret < 0)
 | 
					 | 
				
			||||||
			goto out;
 | 
					 | 
				
			||||||
		warnings += ret;
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (opts.sls) {
 | 
						if (opts.sls)
 | 
				
			||||||
		ret = validate_sls(file);
 | 
							warnings += validate_sls(file);
 | 
				
			||||||
		if (ret < 0)
 | 
					 | 
				
			||||||
			goto out;
 | 
					 | 
				
			||||||
		warnings += ret;
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (opts.static_call) {
 | 
						if (opts.static_call) {
 | 
				
			||||||
		ret = create_static_call_sections(file);
 | 
							ret = create_static_call_sections(file);
 | 
				
			||||||
		if (ret < 0)
 | 
							if (ret)
 | 
				
			||||||
			goto out;
 | 
								goto out;
 | 
				
			||||||
		warnings += ret;
 | 
					 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (opts.retpoline) {
 | 
						if (opts.retpoline) {
 | 
				
			||||||
		ret = create_retpoline_sites_sections(file);
 | 
							ret = create_retpoline_sites_sections(file);
 | 
				
			||||||
		if (ret < 0)
 | 
							if (ret)
 | 
				
			||||||
			goto out;
 | 
								goto out;
 | 
				
			||||||
		warnings += ret;
 | 
					 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (opts.cfi) {
 | 
						if (opts.cfi) {
 | 
				
			||||||
		ret = create_cfi_sections(file);
 | 
							ret = create_cfi_sections(file);
 | 
				
			||||||
		if (ret < 0)
 | 
							if (ret)
 | 
				
			||||||
			goto out;
 | 
								goto out;
 | 
				
			||||||
		warnings += ret;
 | 
					 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (opts.rethunk) {
 | 
						if (opts.rethunk) {
 | 
				
			||||||
		ret = create_return_sites_sections(file);
 | 
							ret = create_return_sites_sections(file);
 | 
				
			||||||
		if (ret < 0)
 | 
							if (ret)
 | 
				
			||||||
			goto out;
 | 
								goto out;
 | 
				
			||||||
		warnings += ret;
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
		if (opts.hack_skylake) {
 | 
							if (opts.hack_skylake) {
 | 
				
			||||||
			ret = create_direct_call_sections(file);
 | 
								ret = create_direct_call_sections(file);
 | 
				
			||||||
			if (ret < 0)
 | 
								if (ret)
 | 
				
			||||||
				goto out;
 | 
									goto out;
 | 
				
			||||||
			warnings += ret;
 | 
					 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (opts.mcount) {
 | 
						if (opts.mcount) {
 | 
				
			||||||
		ret = create_mcount_loc_sections(file);
 | 
							ret = create_mcount_loc_sections(file);
 | 
				
			||||||
		if (ret < 0)
 | 
							if (ret)
 | 
				
			||||||
			goto out;
 | 
								goto out;
 | 
				
			||||||
		warnings += ret;
 | 
					 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (opts.prefix) {
 | 
						if (opts.prefix) {
 | 
				
			||||||
		ret = add_prefix_symbols(file);
 | 
							ret = add_prefix_symbols(file);
 | 
				
			||||||
		if (ret < 0)
 | 
							if (ret)
 | 
				
			||||||
			goto out;
 | 
								goto out;
 | 
				
			||||||
		warnings += ret;
 | 
					 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (opts.ibt) {
 | 
						if (opts.ibt) {
 | 
				
			||||||
		ret = create_ibt_endbr_seal_sections(file);
 | 
							ret = create_ibt_endbr_seal_sections(file);
 | 
				
			||||||
		if (ret < 0)
 | 
							if (ret)
 | 
				
			||||||
			goto out;
 | 
								goto out;
 | 
				
			||||||
		warnings += ret;
 | 
					 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (opts.orc && nr_insns) {
 | 
						if (opts.orc && nr_insns) {
 | 
				
			||||||
		ret = orc_create(file);
 | 
							ret = orc_create(file);
 | 
				
			||||||
		if (ret < 0)
 | 
							if (ret)
 | 
				
			||||||
			goto out;
 | 
								goto out;
 | 
				
			||||||
		warnings += ret;
 | 
					 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	free_insns(file);
 | 
						free_insns(file);
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -331,7 +331,7 @@ static int read_sections(struct elf *elf)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	elf->section_data = calloc(sections_nr, sizeof(*sec));
 | 
						elf->section_data = calloc(sections_nr, sizeof(*sec));
 | 
				
			||||||
	if (!elf->section_data) {
 | 
						if (!elf->section_data) {
 | 
				
			||||||
		perror("calloc");
 | 
							WARN_GLIBC("calloc");
 | 
				
			||||||
		return -1;
 | 
							return -1;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	for (i = 0; i < sections_nr; i++) {
 | 
						for (i = 0; i < sections_nr; i++) {
 | 
				
			||||||
| 
						 | 
					@ -467,7 +467,7 @@ static int read_symbols(struct elf *elf)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	elf->symbol_data = calloc(symbols_nr, sizeof(*sym));
 | 
						elf->symbol_data = calloc(symbols_nr, sizeof(*sym));
 | 
				
			||||||
	if (!elf->symbol_data) {
 | 
						if (!elf->symbol_data) {
 | 
				
			||||||
		perror("calloc");
 | 
							WARN_GLIBC("calloc");
 | 
				
			||||||
		return -1;
 | 
							return -1;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	for (i = 0; i < symbols_nr; i++) {
 | 
						for (i = 0; i < symbols_nr; i++) {
 | 
				
			||||||
| 
						 | 
					@ -799,7 +799,7 @@ elf_create_section_symbol(struct elf *elf, struct section *sec)
 | 
				
			||||||
	struct symbol *sym = calloc(1, sizeof(*sym));
 | 
						struct symbol *sym = calloc(1, sizeof(*sym));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (!sym) {
 | 
						if (!sym) {
 | 
				
			||||||
		perror("malloc");
 | 
							WARN_GLIBC("malloc");
 | 
				
			||||||
		return NULL;
 | 
							return NULL;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -829,7 +829,7 @@ elf_create_prefix_symbol(struct elf *elf, struct symbol *orig, long size)
 | 
				
			||||||
	char *name = malloc(namelen);
 | 
						char *name = malloc(namelen);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (!sym || !name) {
 | 
						if (!sym || !name) {
 | 
				
			||||||
		perror("malloc");
 | 
							WARN_GLIBC("malloc");
 | 
				
			||||||
		return NULL;
 | 
							return NULL;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -963,7 +963,7 @@ static int read_relocs(struct elf *elf)
 | 
				
			||||||
		nr_reloc = 0;
 | 
							nr_reloc = 0;
 | 
				
			||||||
		rsec->relocs = calloc(sec_num_entries(rsec), sizeof(*reloc));
 | 
							rsec->relocs = calloc(sec_num_entries(rsec), sizeof(*reloc));
 | 
				
			||||||
		if (!rsec->relocs) {
 | 
							if (!rsec->relocs) {
 | 
				
			||||||
			perror("calloc");
 | 
								WARN_GLIBC("calloc");
 | 
				
			||||||
			return -1;
 | 
								return -1;
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		for (i = 0; i < sec_num_entries(rsec); i++) {
 | 
							for (i = 0; i < sec_num_entries(rsec); i++) {
 | 
				
			||||||
| 
						 | 
					@ -1005,7 +1005,7 @@ struct elf *elf_open_read(const char *name, int flags)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	elf = malloc(sizeof(*elf));
 | 
						elf = malloc(sizeof(*elf));
 | 
				
			||||||
	if (!elf) {
 | 
						if (!elf) {
 | 
				
			||||||
		perror("malloc");
 | 
							WARN_GLIBC("malloc");
 | 
				
			||||||
		return NULL;
 | 
							return NULL;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	memset(elf, 0, sizeof(*elf));
 | 
						memset(elf, 0, sizeof(*elf));
 | 
				
			||||||
| 
						 | 
					@ -1099,7 +1099,7 @@ struct section *elf_create_section(struct elf *elf, const char *name,
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	sec = malloc(sizeof(*sec));
 | 
						sec = malloc(sizeof(*sec));
 | 
				
			||||||
	if (!sec) {
 | 
						if (!sec) {
 | 
				
			||||||
		perror("malloc");
 | 
							WARN_GLIBC("malloc");
 | 
				
			||||||
		return NULL;
 | 
							return NULL;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	memset(sec, 0, sizeof(*sec));
 | 
						memset(sec, 0, sizeof(*sec));
 | 
				
			||||||
| 
						 | 
					@ -1114,7 +1114,7 @@ struct section *elf_create_section(struct elf *elf, const char *name,
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	sec->name = strdup(name);
 | 
						sec->name = strdup(name);
 | 
				
			||||||
	if (!sec->name) {
 | 
						if (!sec->name) {
 | 
				
			||||||
		perror("strdup");
 | 
							WARN_GLIBC("strdup");
 | 
				
			||||||
		return NULL;
 | 
							return NULL;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1132,7 +1132,7 @@ struct section *elf_create_section(struct elf *elf, const char *name,
 | 
				
			||||||
	if (size) {
 | 
						if (size) {
 | 
				
			||||||
		sec->data->d_buf = malloc(size);
 | 
							sec->data->d_buf = malloc(size);
 | 
				
			||||||
		if (!sec->data->d_buf) {
 | 
							if (!sec->data->d_buf) {
 | 
				
			||||||
			perror("malloc");
 | 
								WARN_GLIBC("malloc");
 | 
				
			||||||
			return NULL;
 | 
								return NULL;
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		memset(sec->data->d_buf, 0, size);
 | 
							memset(sec->data->d_buf, 0, size);
 | 
				
			||||||
| 
						 | 
					@ -1179,7 +1179,7 @@ static struct section *elf_create_rela_section(struct elf *elf,
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	rsec_name = malloc(strlen(sec->name) + strlen(".rela") + 1);
 | 
						rsec_name = malloc(strlen(sec->name) + strlen(".rela") + 1);
 | 
				
			||||||
	if (!rsec_name) {
 | 
						if (!rsec_name) {
 | 
				
			||||||
		perror("malloc");
 | 
							WARN_GLIBC("malloc");
 | 
				
			||||||
		return NULL;
 | 
							return NULL;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	strcpy(rsec_name, ".rela");
 | 
						strcpy(rsec_name, ".rela");
 | 
				
			||||||
| 
						 | 
					@ -1199,7 +1199,7 @@ static struct section *elf_create_rela_section(struct elf *elf,
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	rsec->relocs = calloc(sec_num_entries(rsec), sizeof(struct reloc));
 | 
						rsec->relocs = calloc(sec_num_entries(rsec), sizeof(struct reloc));
 | 
				
			||||||
	if (!rsec->relocs) {
 | 
						if (!rsec->relocs) {
 | 
				
			||||||
		perror("calloc");
 | 
							WARN_GLIBC("calloc");
 | 
				
			||||||
		return NULL;
 | 
							return NULL;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -41,7 +41,7 @@ struct objtool_file {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
struct objtool_file *objtool_open_read(const char *_objname);
 | 
					struct objtool_file *objtool_open_read(const char *_objname);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void objtool_pv_add(struct objtool_file *file, int idx, struct symbol *func);
 | 
					int objtool_pv_add(struct objtool_file *file, int idx, struct symbol *func);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
int check(struct objtool_file *file);
 | 
					int check(struct objtool_file *file);
 | 
				
			||||||
int orc_dump(const char *objname);
 | 
					int orc_dump(const char *objname);
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -11,6 +11,7 @@
 | 
				
			||||||
#include <sys/types.h>
 | 
					#include <sys/types.h>
 | 
				
			||||||
#include <sys/stat.h>
 | 
					#include <sys/stat.h>
 | 
				
			||||||
#include <fcntl.h>
 | 
					#include <fcntl.h>
 | 
				
			||||||
 | 
					#include <errno.h>
 | 
				
			||||||
#include <objtool/builtin.h>
 | 
					#include <objtool/builtin.h>
 | 
				
			||||||
#include <objtool/elf.h>
 | 
					#include <objtool/elf.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -43,8 +44,9 @@ static inline char *offstr(struct section *sec, unsigned long offset)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#define WARN(format, ...)				\
 | 
					#define WARN(format, ...)				\
 | 
				
			||||||
	fprintf(stderr,					\
 | 
						fprintf(stderr,					\
 | 
				
			||||||
		"%s: %s: objtool: " format "\n",	\
 | 
							"%s%s%s: objtool: " format "\n",	\
 | 
				
			||||||
		objname,				\
 | 
							objname ?: "",				\
 | 
				
			||||||
 | 
							objname ? ": " : "",			\
 | 
				
			||||||
		opts.werror ? "error" : "warning",	\
 | 
							opts.werror ? "error" : "warning",	\
 | 
				
			||||||
		##__VA_ARGS__)
 | 
							##__VA_ARGS__)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -83,7 +85,10 @@ static inline char *offstr(struct section *sec, unsigned long offset)
 | 
				
			||||||
	}							\
 | 
						}							\
 | 
				
			||||||
})
 | 
					})
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#define WARN_ELF(format, ...)				\
 | 
					#define WARN_ELF(format, ...)					\
 | 
				
			||||||
	WARN(format ": %s", ##__VA_ARGS__, elf_errmsg(-1))
 | 
						WARN("%s: " format " failed: %s", __func__, ##__VA_ARGS__, elf_errmsg(-1))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#define WARN_GLIBC(format, ...)					\
 | 
				
			||||||
 | 
						WARN("%s: " format " failed: %s", __func__, ##__VA_ARGS__, strerror(errno))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#endif /* _WARN_H */
 | 
					#endif /* _WARN_H */
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -44,14 +44,14 @@ struct objtool_file *objtool_open_read(const char *filename)
 | 
				
			||||||
	return &file;
 | 
						return &file;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void objtool_pv_add(struct objtool_file *f, int idx, struct symbol *func)
 | 
					int objtool_pv_add(struct objtool_file *f, int idx, struct symbol *func)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	if (!opts.noinstr)
 | 
						if (!opts.noinstr)
 | 
				
			||||||
		return;
 | 
							return 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (!f->pv_ops) {
 | 
						if (!f->pv_ops) {
 | 
				
			||||||
		WARN("paravirt confusion");
 | 
							WARN("paravirt confusion");
 | 
				
			||||||
		return;
 | 
							return -1;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/*
 | 
						/*
 | 
				
			||||||
| 
						 | 
					@ -60,14 +60,15 @@ void objtool_pv_add(struct objtool_file *f, int idx, struct symbol *func)
 | 
				
			||||||
	 */
 | 
						 */
 | 
				
			||||||
	if (!strcmp(func->name, "_paravirt_nop") ||
 | 
						if (!strcmp(func->name, "_paravirt_nop") ||
 | 
				
			||||||
	    !strcmp(func->name, "_paravirt_ident_64"))
 | 
						    !strcmp(func->name, "_paravirt_ident_64"))
 | 
				
			||||||
		return;
 | 
							return 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/* already added this function */
 | 
						/* already added this function */
 | 
				
			||||||
	if (!list_empty(&func->pv_target))
 | 
						if (!list_empty(&func->pv_target))
 | 
				
			||||||
		return;
 | 
							return 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	list_add(&func->pv_target, &f->pv_ops[idx].targets);
 | 
						list_add(&func->pv_target, &f->pv_ops[idx].targets);
 | 
				
			||||||
	f->pv_ops[idx].clean = false;
 | 
						f->pv_ops[idx].clean = false;
 | 
				
			||||||
 | 
						return 0;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
int main(int argc, const char **argv)
 | 
					int main(int argc, const char **argv)
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
		Reference in a new issue