[tip:core/urgent] objtool: Support GCC 8's cold subfunctions

2018-05-14 Thread tip-bot for Josh Poimboeuf
Commit-ID:  13810435b9a7014fb92eb715f77da488f3b65b99
Gitweb: https://git.kernel.org/tip/13810435b9a7014fb92eb715f77da488f3b65b99
Author: Josh Poimboeuf 
AuthorDate: Wed, 9 May 2018 22:39:15 -0500
Committer:  Ingo Molnar 
CommitDate: Mon, 14 May 2018 10:20:53 +0200

objtool: Support GCC 8's cold subfunctions

GCC 8 moves a lot of unlikely code out of line to "cold" subfunctions in
.text.unlikely.  Properly detect the new subfunctions and treat them as
extensions of the original functions.

This fixes a bunch of warnings like:

  kernel/cgroup/cgroup.o: warning: objtool: parse_cgroup_root_flags()+0x33: 
sibling call from callable instruction with modified stack frame
  kernel/cgroup/cgroup.o: warning: objtool: cgroup_addrm_files()+0x290: sibling 
call from callable instruction with modified stack frame
  kernel/cgroup/cgroup.o: warning: objtool: 
cgroup_apply_control_enable()+0x25b: sibling call from callable instruction 
with modified stack frame
  kernel/cgroup/cgroup.o: warning: objtool: rebind_subsystems()+0x325: sibling 
call from callable instruction with modified stack frame

Reported-and-tested-by: damian 
Reported-by: Arnd Bergmann 
Signed-off-by: Josh Poimboeuf 
Acked-by: Peter Zijlstra (Intel) 
Cc: David Laight 
Cc: Greg KH 
Cc: Linus Torvalds 
Cc: Peter Zijlstra 
Cc: Randy Dunlap 
Cc: Thomas Gleixner 
Link: 
http://lkml.kernel.org/r/0965e7fcfc5f31a276f0c7f298ff770c19b68706.1525923412.git.jpoim...@redhat.com
Signed-off-by: Ingo Molnar 
---
 tools/objtool/check.c | 93 ---
 tools/objtool/elf.c   | 42 +--
 tools/objtool/elf.h   |  2 ++
 3 files changed, 93 insertions(+), 44 deletions(-)

diff --git a/tools/objtool/check.c b/tools/objtool/check.c
index 264522d4e4af..14daf6a27d9f 100644
--- a/tools/objtool/check.c
+++ b/tools/objtool/check.c
@@ -59,6 +59,31 @@ static struct instruction *next_insn_same_sec(struct 
objtool_file *file,
return next;
 }
 
+static struct instruction *next_insn_same_func(struct objtool_file *file,
+  struct instruction *insn)
+{
+   struct instruction *next = list_next_entry(insn, list);
+   struct symbol *func = insn->func;
+
+   if (!func)
+   return NULL;
+
+   if (>list != >insn_list && next->func == func)
+   return next;
+
+   /* Check if we're already in the subfunction: */
+   if (func == func->cfunc)
+   return NULL;
+
+   /* Move to the subfunction: */
+   return find_insn(file, func->cfunc->sec, func->cfunc->offset);
+}
+
+#define func_for_each_insn_all(file, func, insn)   \
+   for (insn = find_insn(file, func->sec, func->offset);   \
+insn;  \
+insn = next_insn_same_func(file, insn))
+
 #define func_for_each_insn(file, func, insn)   \
for (insn = find_insn(file, func->sec, func->offset);   \
 insn && >list != >insn_list && \
@@ -149,10 +174,14 @@ static int __dead_end_function(struct objtool_file *file, 
struct symbol *func,
if (!strcmp(func->name, global_noreturns[i]))
return 1;
 
-   if (!func->sec)
+   if (!func->len)
return 0;
 
-   func_for_each_insn(file, func, insn) {
+   insn = find_insn(file, func->sec, func->offset);
+   if (!insn->func)
+   return 0;
+
+   func_for_each_insn_all(file, func, insn) {
empty = false;
 
if (insn->type == INSN_RETURN)
@@ -167,28 +196,17 @@ static int __dead_end_function(struct objtool_file *file, 
struct symbol *func,
 * case, the function's dead-end status depends on whether the target
 * of the sibling call returns.
 */
-   func_for_each_insn(file, func, insn) {
-   if (insn->sec != func->sec ||
-   insn->offset >= func->offset + func->len)
-   break;
-
+   func_for_each_insn_all(file, func, insn) {
if (insn->type == INSN_JUMP_UNCONDITIONAL) {
struct instruction *dest = insn->jump_dest;
-   struct symbol *dest_func;
 
if (!dest)
/* sibling call to another file */
return 0;
 
-   if (dest->sec != func->sec ||
-   dest->offset < func->offset ||
-   dest->offset >= func->offset + func->len) {
-   /* local sibling call 

[tip:core/urgent] objtool: Support GCC 8's cold subfunctions

2018-05-14 Thread tip-bot for Josh Poimboeuf
Commit-ID:  13810435b9a7014fb92eb715f77da488f3b65b99
Gitweb: https://git.kernel.org/tip/13810435b9a7014fb92eb715f77da488f3b65b99
Author: Josh Poimboeuf 
AuthorDate: Wed, 9 May 2018 22:39:15 -0500
Committer:  Ingo Molnar 
CommitDate: Mon, 14 May 2018 10:20:53 +0200

objtool: Support GCC 8's cold subfunctions

GCC 8 moves a lot of unlikely code out of line to "cold" subfunctions in
.text.unlikely.  Properly detect the new subfunctions and treat them as
extensions of the original functions.

This fixes a bunch of warnings like:

  kernel/cgroup/cgroup.o: warning: objtool: parse_cgroup_root_flags()+0x33: 
sibling call from callable instruction with modified stack frame
  kernel/cgroup/cgroup.o: warning: objtool: cgroup_addrm_files()+0x290: sibling 
call from callable instruction with modified stack frame
  kernel/cgroup/cgroup.o: warning: objtool: 
cgroup_apply_control_enable()+0x25b: sibling call from callable instruction 
with modified stack frame
  kernel/cgroup/cgroup.o: warning: objtool: rebind_subsystems()+0x325: sibling 
call from callable instruction with modified stack frame

Reported-and-tested-by: damian 
Reported-by: Arnd Bergmann 
Signed-off-by: Josh Poimboeuf 
Acked-by: Peter Zijlstra (Intel) 
Cc: David Laight 
Cc: Greg KH 
Cc: Linus Torvalds 
Cc: Peter Zijlstra 
Cc: Randy Dunlap 
Cc: Thomas Gleixner 
Link: 
http://lkml.kernel.org/r/0965e7fcfc5f31a276f0c7f298ff770c19b68706.1525923412.git.jpoim...@redhat.com
Signed-off-by: Ingo Molnar 
---
 tools/objtool/check.c | 93 ---
 tools/objtool/elf.c   | 42 +--
 tools/objtool/elf.h   |  2 ++
 3 files changed, 93 insertions(+), 44 deletions(-)

diff --git a/tools/objtool/check.c b/tools/objtool/check.c
index 264522d4e4af..14daf6a27d9f 100644
--- a/tools/objtool/check.c
+++ b/tools/objtool/check.c
@@ -59,6 +59,31 @@ static struct instruction *next_insn_same_sec(struct 
objtool_file *file,
return next;
 }
 
+static struct instruction *next_insn_same_func(struct objtool_file *file,
+  struct instruction *insn)
+{
+   struct instruction *next = list_next_entry(insn, list);
+   struct symbol *func = insn->func;
+
+   if (!func)
+   return NULL;
+
+   if (>list != >insn_list && next->func == func)
+   return next;
+
+   /* Check if we're already in the subfunction: */
+   if (func == func->cfunc)
+   return NULL;
+
+   /* Move to the subfunction: */
+   return find_insn(file, func->cfunc->sec, func->cfunc->offset);
+}
+
+#define func_for_each_insn_all(file, func, insn)   \
+   for (insn = find_insn(file, func->sec, func->offset);   \
+insn;  \
+insn = next_insn_same_func(file, insn))
+
 #define func_for_each_insn(file, func, insn)   \
for (insn = find_insn(file, func->sec, func->offset);   \
 insn && >list != >insn_list && \
@@ -149,10 +174,14 @@ static int __dead_end_function(struct objtool_file *file, 
struct symbol *func,
if (!strcmp(func->name, global_noreturns[i]))
return 1;
 
-   if (!func->sec)
+   if (!func->len)
return 0;
 
-   func_for_each_insn(file, func, insn) {
+   insn = find_insn(file, func->sec, func->offset);
+   if (!insn->func)
+   return 0;
+
+   func_for_each_insn_all(file, func, insn) {
empty = false;
 
if (insn->type == INSN_RETURN)
@@ -167,28 +196,17 @@ static int __dead_end_function(struct objtool_file *file, 
struct symbol *func,
 * case, the function's dead-end status depends on whether the target
 * of the sibling call returns.
 */
-   func_for_each_insn(file, func, insn) {
-   if (insn->sec != func->sec ||
-   insn->offset >= func->offset + func->len)
-   break;
-
+   func_for_each_insn_all(file, func, insn) {
if (insn->type == INSN_JUMP_UNCONDITIONAL) {
struct instruction *dest = insn->jump_dest;
-   struct symbol *dest_func;
 
if (!dest)
/* sibling call to another file */
return 0;
 
-   if (dest->sec != func->sec ||
-   dest->offset < func->offset ||
-   dest->offset >= func->offset + func->len) {
-   /* local sibling call */
-   dest_func = find_symbol_by_offset(dest->sec,
- dest->offset);
-   if (!dest_func)
-   continue;
+   if