From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: X-Google-Smtp-Source: AH8x227oR5ZqHWH85G97AddBt7RbDK5LLmm4NrFuCvdCnxSi1vmQ6VKqtYSH2wb6kYZD0H2wAcD8 ARC-Seal: i=1; a=rsa-sha256; t=1516721589; cv=none; d=google.com; s=arc-20160816; b=vdncBvyuMdEo8KsFNjugst1DYArMrZuRin+yhSUQRLgo9efY70yDRbLBCoMT3krjdF Kda7Z16cuXcSbFysXr3TdEdkkhwfiROJ6D/2XUsgP9jssRU5FMIuWF3ZlncvWLjQ8CeU 6ZcrG+LQA1POrCC0GuM1XvljaXB96FdviIhZa1xLsYJWTl15kbc0nkZ+4ja4eSOwn0ij NpTc6iBVVLgjBhSqa8JpgVx7EGYJFhKDEo9uWe5AkLkjOKcCb3jrvRvbY+ZQONQpjuos iH+0wrFQnWXNtO4AMwRRwUPgOJjy+j/EwBxEwXph1r27ZNbWHzxWTO+ueWR2M1Pus66+ OB4w== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=content-disposition:mime-version:references:subject:cc:to:from:date :user-agent:message-id:dkim-signature:arc-authentication-results; bh=iLwPsBX1zrllO6s6POrNWsjI+bMJF8sa1Caw5/kbUZg=; b=qzS4HSACO0vpL+/o5szlJ+ZfLkvIUN8UR23x6q4SQEyH8y8IZVQO6YU/1IUi7uvBsu /xMZ6E6Ymh/pGj53ZaZTt48b6v5ycHmlh7eqeoHrb4UyM/SKTZHVaDMyIbX25+6pEkep 30wqHjWmdbuDDl8NMgqeobUhyW2JrtoQ5SOliVp2d4P0nGpa29PJDuA78ruszy05lD1X kXuVyujoDHHn9wmbujC8neC2zbSvS1MYVX2kUJ6SwJDdVrvHqz2lifyka5W0kFu5IZKu VVB9/Gs4d8mpiLavB+4R7X2DllKvP0zJAoWLXyFYbjKbX0YDsuLGLcUir1jIBRV2M5bO g6Kw== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@infradead.org header.s=merlin.20170209 header.b=GbQm+7at; spf=pass (google.com: best guess record for domain of peterz@infradead.org designates 205.233.59.134 as permitted sender) smtp.mailfrom=peterz@infradead.org Authentication-Results: mx.google.com; dkim=pass header.i=@infradead.org header.s=merlin.20170209 header.b=GbQm+7at; spf=pass (google.com: best guess record for domain of peterz@infradead.org designates 205.233.59.134 as permitted sender) smtp.mailfrom=peterz@infradead.org Message-Id: <20180123152639.170696914@infradead.org> User-Agent: quilt/0.63-1 Date: Tue, 23 Jan 2018 16:25:59 +0100 From: Peter Zijlstra To: David Woodhouse , Thomas Gleixner , Josh Poimboeuf Cc: linux-kernel@vger.kernel.org, Dave Hansen , Ashok Raj , Tim Chen , Andy Lutomirski , Linus Torvalds , Greg KH , Andrea Arcangeli , Andi Kleen , Arjan Van De Ven , Dan Williams , Paolo Bonzini , Jun Nakajima , Asit Mallick , Jason Baron , Peter Zijlstra Subject: [PATCH 20/24] objtool: Another static block fail References: <20180123152539.374360046@infradead.org> MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Disposition: inline; filename=peterz-objtool-more-clever-3.patch X-getmail-retrieved-from-mailbox: INBOX X-GMAIL-THRID: =?utf-8?q?1590397857832042088?= X-GMAIL-MSGID: =?utf-8?q?1590397857832042088?= X-Mailing-List: linux-kernel@vger.kernel.org List-ID: I've observed GCC generate: sym: NOP/JMP 1f (static_branch) JMP 2f 1: /* crud */ JMP 3f 2: /* other crud */ 3: RETQ This means we need to follow unconditional jumps; be conservative and only follow if its a unique jump. (I've not yet figured out which CONFIG option is responsible for this, a normal defconfig build does not generate crap like this) Signed-off-by: Peter Zijlstra (Intel) --- tools/objtool/check.c | 53 +++++++++++++++++++++++++++++++++++++++++++++++--- tools/objtool/elf.h | 2 - 2 files changed, 51 insertions(+), 4 deletions(-) --- a/tools/objtool/check.c +++ b/tools/objtool/check.c @@ -1207,6 +1207,8 @@ static int assert_static_jumps(struct ob return 0; } +static void jmp_grow_static_block(struct objtool_file *file, struct instruction *insn); + static bool __grow_static_block(struct objtool_file *file, struct instruction *insn) { @@ -1216,7 +1218,8 @@ static bool __grow_static_block(struct o switch (insn->type) { case INSN_JUMP_UNCONDITIONAL: - /* mark this instruction, terminate this section */ + /* follow the jump, mark this instruction, terminate this section */ + jmp_grow_static_block(file, insn); insn->static_jump_dest = true; return false; @@ -1238,6 +1241,50 @@ static bool __grow_static_block(struct o return true; } +static void jmp_grow_static_block(struct objtool_file *file, struct instruction *insn) +{ + struct instruction *dest = insn->jump_dest; + bool old_sjd, static_block; + + if (!dest) + return; + + /* more than a single site jumps here, can't be certain */ + if (dest->branch_target > 1) + return; + + /* mark the destination, so we can continue there */ + old_sjd = dest->static_jump_dest; + dest->static_jump_dest = true; + + if (dest->offset > insn->offset) { + /* fwd jump, the main iteration will still get there. */ + return; + } + + /* backwards jump, we need to revisit the instructions */ + do { + static_block = __grow_static_block(file, dest); + + if (insn->type == INSN_CALL && !old_sjd && dest->static_jump_dest) { + struct symbol *func = insn->call_dest; + if (!func || func->bind != STB_LOCAL) + goto next; + + /* + * we flipped the call to static, update the stats. + */ + if (insn->static_jump_dest) { + func->non_static_call--; + func->static_call++; + } + } +next: + dest = list_next_entry(dest, list); + old_sjd = dest->static_jump_dest; + } while (static_block && dest != insn); +} + static int grow_static_blocks(struct objtool_file *file) { bool static_block = false; @@ -1255,9 +1302,9 @@ static int grow_static_blocks(struct obj continue; if (static_block) - func->static_call = true; + func->static_call++; else - func->non_static_call = true; + func->non_static_call++; } } --- a/tools/objtool/elf.h +++ b/tools/objtool/elf.h @@ -61,7 +61,7 @@ struct symbol { unsigned char bind, type; unsigned long offset; unsigned int len; - bool static_call, non_static_call; + unsigned int static_call, non_static_call; }; struct rela {