Merge branch 'objtool/urgent' into objtool/core
authorPeter Zijlstra <peterz@infradead.org>
Thu, 18 Jun 2020 15:55:29 +0000 (17:55 +0200)
committerPeter Zijlstra <peterz@infradead.org>
Thu, 18 Jun 2020 15:55:29 +0000 (17:55 +0200)
 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>
1  2 
tools/objtool/arch.h
tools/objtool/arch/x86/decode.c
tools/objtool/check.c
tools/objtool/elf.c
tools/objtool/elf.h
tools/objtool/orc_gen.c

index d0969a9328c2d85484ac8c86135fbf3a0c64550d,3c5967748abb93917cc43f5841084d0fd5ce87f1..2e2ce089b0e9e886c731f07dbbfa5c94bf7a1a40
@@@ -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 */
Simple merge
index 559c1baf9fc51a721018701ca13ba1adf6e21529,478267a072d08056d3f9c46a3305f1d743017d54..a2313ecce6d18304535bd4a6d15fa40ba88153ed
@@@ -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;
  
 -                      if (rela) {
 -                              rela->type = R_NONE;
 -                              elf_write_rela(file->elf, rela);
+               /*
+                * 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 (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.
index 95d86bcb95122b4f1deb6bcaa6576af791d5f8e9,26d11d8219418dd56d95c6025802d78b3c53fc52..3ddbd66f1a37611dd0021c8017755a814025f34a
@@@ -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;
index 78a2db23b8b6fbd64a6512315caf08e07c7d2c9d,7324e772583ee76cc53b26acf190e3d7722a3bc6..6cc80a0751668546c7dce140967c5b31181f9108
@@@ -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)
index 75e08cf0709b47975b0eadefe844bf3940eb0c27,4c37f80eb987fc7f3753f67bf708569df23574a9..968f55e6dd94d45bdcb7c8abcf1f5748f5ad0f81
@@@ -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;