From: Peter Zijlstra <peterz@infradead.org>
Date: Thu, 18 Jun 2020 15:55:29 +0000 (+0200)
Subject: Merge branch 'objtool/urgent' into objtool/core
X-Git-Url: http://git.maquefel.me/?a=commitdiff_plain;h=d832c0051f4e9cc7d26ef3bc6e9b662bc6a90f3a;p=linux.git

Merge branch 'objtool/urgent' into objtool/core

 Conflicts:
	tools/objtool/elf.c
	tools/objtool/elf.h
	tools/objtool/orc_gen.c
	tools/objtool/check.c

Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org>
---

d832c0051f4e9cc7d26ef3bc6e9b662bc6a90f3a
diff --cc tools/objtool/arch.h
index d0969a9328c2d,3c5967748abb9..2e2ce089b0e9e
--- a/tools/objtool/arch.h
+++ b/tools/objtool/arch.h
@@@ -82,6 -82,8 +82,8 @@@ bool arch_callee_saved_reg(unsigned cha
  
  unsigned long arch_jump_destination(struct instruction *insn);
  
 -unsigned long arch_dest_rela_offset(int addend);
 +unsigned long arch_dest_reloc_offset(int addend);
  
+ const char *arch_nop_insn(int len);
+ 
  #endif /* _ARCH_H */
diff --cc tools/objtool/check.c
index 559c1baf9fc51,478267a072d08..a2313ecce6d18
--- a/tools/objtool/check.c
+++ b/tools/objtool/check.c
@@@ -763,8 -764,26 +764,26 @@@ static int add_call_destinations(struc
  				return -1;
  			}
  		} else
 -			insn->call_dest = rela->sym;
 +			insn->call_dest = reloc->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);
++			if (reloc) {
++				reloc->type = R_NONE;
++				elf_write_reloc(file->elf, reloc);
+ 			}
+ 
+ 			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.
diff --cc tools/objtool/elf.c
index 95d86bcb95122,26d11d8219418..3ddbd66f1a376
--- a/tools/objtool/elf.c
+++ b/tools/objtool/elf.c
@@@ -551,22 -518,22 +551,24 @@@ static int read_relocs(struct elf *elf
  				perror("malloc");
  				return -1;
  			}
 -			memset(rela, 0, sizeof(*rela));
 -
 -			if (!gelf_getrela(sec->data, i, &rela->rela)) {
 -				WARN_ELF("gelf_getrela");
 -				return -1;
 +			memset(reloc, 0, sizeof(*reloc));
 +			switch (sec->sh.sh_type) {
 +			case SHT_REL:
 +				if (read_rel_reloc(sec, i, reloc, &symndx))
 +					return -1;
 +				break;
 +			case SHT_RELA:
 +				if (read_rela_reloc(sec, i, reloc, &symndx))
 +					return -1;
 +				break;
 +			default: return -1;
  			}
- 			reloc->sym = find_symbol_by_index(elf, symndx);
+ 
 -			rela->type = GELF_R_TYPE(rela->rela.r_info);
 -			rela->addend = rela->rela.r_addend;
 -			rela->offset = rela->rela.r_offset;
 -			symndx = GELF_R_SYM(rela->rela.r_info);
 -			rela->sec = sec;
 -			rela->idx = i;
 -			rela->sym = find_symbol_by_index(elf, symndx);
 -			if (!rela->sym) {
 -				WARN("can't find rela entry symbol %d for %s",
 +			reloc->sec = sec;
++			reloc->idx = i;
++			reloc->sym = find_symbol_by_index(elf, symndx);
 +			if (!reloc->sym) {
 +				WARN("can't find reloc entry symbol %d for %s",
  				     symndx, sec->name);
  				return -1;
  			}
@@@ -880,23 -785,44 +884,73 @@@ static int elf_rebuild_rela_reloc_secti
  	return 0;
  }
  
- int elf_rebuild_reloc_section(struct section *sec)
++int elf_rebuild_reloc_section(struct elf *elf, struct section *sec)
 +{
 +	struct reloc *reloc;
 +	int nr;
 +
++	sec->changed = true;
++	elf->changed = true;
++
 +	nr = 0;
 +	list_for_each_entry(reloc, &sec->reloc_list, list)
 +		nr++;
 +
 +	switch (sec->sh.sh_type) {
 +	case SHT_REL:  return elf_rebuild_rel_reloc_section(sec, nr);
 +	case SHT_RELA: return elf_rebuild_rela_reloc_section(sec, nr);
 +	default:       return -1;
 +	}
 +}
 +
- int elf_write(const struct elf *elf)
+ int elf_write_insn(struct elf *elf, struct section *sec,
+ 		   unsigned long offset, unsigned int len,
+ 		   const char *insn)
+ {
+ 	Elf_Data *data = sec->data;
+ 
+ 	if (data->d_type != ELF_T_BYTE || data->d_off) {
+ 		WARN("write to unexpected data for section: %s", sec->name);
+ 		return -1;
+ 	}
+ 
+ 	memcpy(data->d_buf + offset, insn, len);
+ 	elf_flagdata(data, ELF_C_SET, ELF_F_DIRTY);
+ 
+ 	elf->changed = true;
+ 
+ 	return 0;
+ }
+ 
 -int elf_write_rela(struct elf *elf, struct rela *rela)
++int elf_write_reloc(struct elf *elf, struct reloc *reloc)
+ {
 -	struct section *sec = rela->sec;
++	struct section *sec = reloc->sec;
+ 
 -	rela->rela.r_info = GELF_R_INFO(rela->sym->idx, rela->type);
 -	rela->rela.r_addend = rela->addend;
 -	rela->rela.r_offset = rela->offset;
++	if (sec->sh.sh_type == SHT_REL) {
++		reloc->rel.r_info = GELF_R_INFO(reloc->sym->idx, reloc->type);
++		reloc->rel.r_offset = reloc->offset;
+ 
 -	if (!gelf_update_rela(sec->data, rela->idx, &rela->rela)) {
 -		WARN_ELF("gelf_update_rela");
 -		return -1;
++		if (!gelf_update_rel(sec->data, reloc->idx, &reloc->rel)) {
++			WARN_ELF("gelf_update_rel");
++			return -1;
++		}
++	} else {
++		reloc->rela.r_info = GELF_R_INFO(reloc->sym->idx, reloc->type);
++		reloc->rela.r_addend = reloc->addend;
++		reloc->rela.r_offset = reloc->offset;
++
++		if (!gelf_update_rela(sec->data, reloc->idx, &reloc->rela)) {
++			WARN_ELF("gelf_update_rela");
++			return -1;
++		}
+ 	}
+ 
+ 	elf->changed = true;
+ 
+ 	return 0;
+ }
+ 
+ int elf_write(struct elf *elf)
  {
  	struct section *sec;
  	Elf_Scn *s;
diff --cc tools/objtool/elf.h
index 78a2db23b8b6f,7324e772583ee..6cc80a0751668
--- a/tools/objtool/elf.h
+++ b/tools/objtool/elf.h
@@@ -58,18 -58,16 +58,19 @@@ struct symbol 
  	bool uaccess_safe;
  };
  
 -struct rela {
 +struct reloc {
  	struct list_head list;
  	struct hlist_node hash;
 -	GElf_Rela rela;
 +	union {
 +		GElf_Rela rela;
 +		GElf_Rel  rel;
 +	};
  	struct section *sec;
  	struct symbol *sym;
- 	unsigned int type;
  	unsigned long offset;
+ 	unsigned int type;
  	int addend;
+ 	int idx;
  	bool jump_table_start;
  };
  
@@@ -119,9 -118,13 +121,13 @@@ static inline u32 reloc_hash(struct rel
  
  struct elf *elf_open_read(const char *name, int flags);
  struct section *elf_create_section(struct elf *elf, const char *name, size_t entsize, int nr);
 -struct section *elf_create_rela_section(struct elf *elf, struct section *base);
 -void elf_add_rela(struct elf *elf, struct rela *rela);
 +struct section *elf_create_reloc_section(struct elf *elf, struct section *base, int reltype);
 +void elf_add_reloc(struct elf *elf, struct reloc *reloc);
- int elf_write(const struct elf *elf);
+ int elf_write_insn(struct elf *elf, struct section *sec,
+ 		   unsigned long offset, unsigned int len,
+ 		   const char *insn);
 -int elf_write_rela(struct elf *elf, struct rela *rela);
++int elf_write_reloc(struct elf *elf, struct reloc *reloc);
+ int elf_write(struct elf *elf);
  void elf_close(struct elf *elf);
  
  struct section *find_section_by_name(const struct elf *elf, const char *name);
@@@ -129,11 -132,11 +135,11 @@@ struct symbol *find_func_by_offset(stru
  struct symbol *find_symbol_by_offset(struct section *sec, unsigned long offset);
  struct symbol *find_symbol_by_name(const struct elf *elf, const char *name);
  struct symbol *find_symbol_containing(const struct section *sec, unsigned long offset);
 -struct rela *find_rela_by_dest(const struct elf *elf, struct section *sec, unsigned long offset);
 -struct rela *find_rela_by_dest_range(const struct elf *elf, struct section *sec,
 +struct reloc *find_reloc_by_dest(const struct elf *elf, struct section *sec, unsigned long offset);
 +struct reloc *find_reloc_by_dest_range(const struct elf *elf, struct section *sec,
  				     unsigned long offset, unsigned int len);
  struct symbol *find_func_containing(struct section *sec, unsigned long offset);
- int elf_rebuild_reloc_section(struct section *sec);
 -int elf_rebuild_rela_section(struct elf *elf, struct section *sec);
++int elf_rebuild_reloc_section(struct elf *elf, struct section *sec);
  
  #define for_each_sec(file, sec)						\
  	list_for_each_entry(sec, &file->elf->sections, list)
diff --cc tools/objtool/orc_gen.c
index 75e08cf0709b4,4c37f80eb987f..968f55e6dd94d
--- a/tools/objtool/orc_gen.c
+++ b/tools/objtool/orc_gen.c
@@@ -222,7 -222,7 +222,7 @@@ int create_orc_sections(struct objtool_
  		}
  	}
  
- 	if (elf_rebuild_reloc_section(ip_relocsec))
 -	if (elf_rebuild_rela_section(file->elf, ip_relasec))
++	if (elf_rebuild_reloc_section(file->elf, ip_relocsec))
  		return -1;
  
  	return 0;