mirror of
				https://github.com/torvalds/linux.git
				synced 2025-11-04 10:40:15 +02:00 
			
		
		
		
	objtool: Fix noinstr vs KCOV
Since many compilers cannot disable KCOV with a function attribute, help it to NOP out any __sanitizer_cov_*() calls injected in noinstr code. This turns: 12: e8 00 00 00 00 callq 17 <lockdep_hardirqs_on+0x17> 13: R_X86_64_PLT32 __sanitizer_cov_trace_pc-0x4 into: 12: 0f 1f 44 00 00 nopl 0x0(%rax,%rax,1) 13: R_X86_64_NONE __sanitizer_cov_trace_pc-0x4 Just like recordmcount does. Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org> Acked-by: Dmitry Vyukov <dvyukov@google.com>
This commit is contained in:
		
							parent
							
								
									fdabdd0b05
								
							
						
					
					
						commit
						0f1441b44e
					
				
					 5 changed files with 46 additions and 1 deletions
				
			
		| 
						 | 
				
			
			@ -67,7 +67,7 @@ config X86
 | 
			
		|||
	select ARCH_HAS_FILTER_PGPROT
 | 
			
		||||
	select ARCH_HAS_FORTIFY_SOURCE
 | 
			
		||||
	select ARCH_HAS_GCOV_PROFILE_ALL
 | 
			
		||||
	select ARCH_HAS_KCOV			if X86_64
 | 
			
		||||
	select ARCH_HAS_KCOV			if X86_64 && STACK_VALIDATION
 | 
			
		||||
	select ARCH_HAS_MEM_ENCRYPT
 | 
			
		||||
	select ARCH_HAS_MEMBARRIER_SYNC_CORE
 | 
			
		||||
	select ARCH_HAS_NON_OVERLAPPING_ADDRESS_SPACE
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -84,4 +84,6 @@ unsigned long arch_jump_destination(struct instruction *insn);
 | 
			
		|||
 | 
			
		||||
unsigned long arch_dest_rela_offset(int addend);
 | 
			
		||||
 | 
			
		||||
const char *arch_nop_insn(int len);
 | 
			
		||||
 | 
			
		||||
#endif /* _ARCH_H */
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -565,3 +565,21 @@ void arch_initial_func_cfi_state(struct cfi_init_state *state)
 | 
			
		|||
	state->regs[16].base = CFI_CFA;
 | 
			
		||||
	state->regs[16].offset = -8;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
const char *arch_nop_insn(int len)
 | 
			
		||||
{
 | 
			
		||||
	static const char nops[5][5] = {
 | 
			
		||||
		/* 1 */ { 0x90 },
 | 
			
		||||
		/* 2 */ { 0x66, 0x90 },
 | 
			
		||||
		/* 3 */ { 0x0f, 0x1f, 0x00 },
 | 
			
		||||
		/* 4 */ { 0x0f, 0x1f, 0x40, 0x00 },
 | 
			
		||||
		/* 5 */ { 0x0f, 0x1f, 0x44, 0x00, 0x00 },
 | 
			
		||||
	};
 | 
			
		||||
 | 
			
		||||
	if (len < 1 || len > 5) {
 | 
			
		||||
		WARN("invalid NOP size: %d\n", len);
 | 
			
		||||
		return NULL;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return nops[len-1];
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										6
									
								
								tools/objtool/arch/x86/include/arch_elf.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										6
									
								
								tools/objtool/arch/x86/include/arch_elf.h
									
									
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,6 @@
 | 
			
		|||
#ifndef _OBJTOOL_ARCH_ELF
 | 
			
		||||
#define _OBJTOOL_ARCH_ELF
 | 
			
		||||
 | 
			
		||||
#define R_NONE R_X86_64_NONE
 | 
			
		||||
 | 
			
		||||
#endif /* _OBJTOOL_ARCH_ELF */
 | 
			
		||||
| 
						 | 
				
			
			@ -12,6 +12,7 @@
 | 
			
		|||
#include "check.h"
 | 
			
		||||
#include "special.h"
 | 
			
		||||
#include "warn.h"
 | 
			
		||||
#include "arch_elf.h"
 | 
			
		||||
 | 
			
		||||
#include <linux/hashtable.h>
 | 
			
		||||
#include <linux/kernel.h>
 | 
			
		||||
| 
						 | 
				
			
			@ -765,6 +766,24 @@ static int add_call_destinations(struct objtool_file *file)
 | 
			
		|||
		} else
 | 
			
		||||
			insn->call_dest = rela->sym;
 | 
			
		||||
 | 
			
		||||
		/*
 | 
			
		||||
		 * Many compilers cannot disable KCOV with a function attribute
 | 
			
		||||
		 * so they need a little help, NOP out any KCOV calls from noinstr
 | 
			
		||||
		 * text.
 | 
			
		||||
		 */
 | 
			
		||||
		if (insn->sec->noinstr &&
 | 
			
		||||
		    !strncmp(insn->call_dest->name, "__sanitizer_cov_", 16)) {
 | 
			
		||||
			if (rela) {
 | 
			
		||||
				rela->type = R_NONE;
 | 
			
		||||
				elf_write_rela(file->elf, rela);
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			elf_write_insn(file->elf, insn->sec,
 | 
			
		||||
				       insn->offset, insn->len,
 | 
			
		||||
				       arch_nop_insn(insn->len));
 | 
			
		||||
			insn->type = INSN_NOP;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		/*
 | 
			
		||||
		 * Whatever stack impact regular CALLs have, should be undone
 | 
			
		||||
		 * by the RETURN of the called function.
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
		Reference in a new issue