From: Josh Poimboeuf <jpoimboe@redhat.com>
To: Linus Torvalds <torvalds@linux-foundation.org>
Cc: Peter Zijlstra <peterz@infradead.org>, linux-kernel@vger.kernel.org
Subject: Re: New objtool warning..
Date: Wed, 16 Dec 2020 14:01:58 -0600 [thread overview]
Message-ID: <20201216200158.akf356yrw44o2rlb@treble> (raw)
In-Reply-To: <CAHk-=whpp_eo-5d0ZLpx=0X91J0ZNReZ_9riNf96z2dy24z=hw@mail.gmail.com>
On Tue, Dec 15, 2020 at 09:32:29PM -0800, Linus Torvalds wrote:
> > The asm code looks like this:
> >
> > cmpb $4, %al #, _30
> > jne .L176 #,
> > ...
> > cmpb $12, %al #, _30
> > jne .L176 #,
> > ...
> > .L176:
> > # drivers/gpu/drm/drm_edid.c:3118: unreachable();
> > #APP
> > # 3118 "drivers/gpu/drm/drm_edid.c" 1
> > 320: #
> > .pushsection .discard.unreachable
> > .long 320b - . #
> > .popsection
> > # 0 "" 2
> > #NO_APP
> > .. this falls through..
> >
> > So you *should* find that label that then falls through in that
> > ".discard.unreachable" section, and so it should be possible to teach
> > objdump about that (insane) unreachable code that way. No?
So this is kind of tricky, because the unreachable() annotation usually
means "the previous instruction is a dead end". Most of the time, the
next instruction -- the one actually pointed to by the annotation -- is
actually reachable from another path.
For example, here's a typical usage of unreachable():
je not_a_bug
ud2
.pushsection .discard.unreachable
.long not_a_bug - .
.popsection
not_a_bug:
... normal non-buggy code ...
The 'not_a_bug' label is pointed to by the unreachable annotation, but
it's actually reachable.
In your .o, .discard.unreachable points to 0xbb3, so objtool marks the
previous instruction (0xbae) as a dead end:
bae: e9 30 ff ff ff jmpq ae3 <do_cvt_mode+0xd3>
bb3: 66 66 2e 0f 1f 84 00 data16 nopw %cs:0x0(%rax,%rax,1)
bba: 00 00 00 00
bbe: 66 90 xchg %ax,%ax
And there's another path to 0xbb3 from the switch statement, so objtool
assumes it's reachable.
So maybe we need to make objtool's unreachable logic a little more
nuanced: If the previous instruction is an unconditional jump, then
consider *the annotated instruction itself* to be a dead end.
I'm not quite able to convince myself this wouldn't produce false
positives. It did immediately produce one false positive in
no_context(), but that should be easily fixable (see patch).
I can run it through more testing, if you don't see any obvious problems
with it.
diff --git a/arch/x86/mm/fault.c b/arch/x86/mm/fault.c
index f1f1b5a0956a..c888821bb40c 100644
--- a/arch/x86/mm/fault.c
+++ b/arch/x86/mm/fault.c
@@ -699,7 +699,6 @@ no_context(struct pt_regs *regs, unsigned long error_code,
*/
asm volatile ("movq %[stack], %%rsp\n\t"
"call handle_stack_overflow\n\t"
- "1: jmp 1b"
: ASM_CALL_CONSTRAINT
: "D" ("kernel stack overflow (page fault)"),
"S" (regs), "d" (address),
diff --git a/tools/objtool/check.c b/tools/objtool/check.c
index c6ab44543c92..267e8b88ca3a 100644
--- a/tools/objtool/check.c
+++ b/tools/objtool/check.c
@@ -370,9 +370,12 @@ static int add_dead_ends(struct objtool_file *file)
return -1;
}
insn = find_insn(file, reloc->sym->sec, reloc->addend);
- if (insn)
- insn = list_prev_entry(insn, list);
- else if (reloc->addend == reloc->sym->sec->len) {
+ if (insn) {
+ struct instruction *prev = list_prev_entry(insn, list);
+ if (prev->type != INSN_JUMP_UNCONDITIONAL)
+ insn = prev;
+
+ } else if (reloc->addend == reloc->sym->sec->len) {
insn = find_last_insn(file, reloc->sym->sec);
if (!insn) {
WARN("can't find unreachable insn at %s+0x%x",
next prev parent reply other threads:[~2020-12-16 20:03 UTC|newest]
Thread overview: 12+ messages / expand[flat|nested] mbox.gz Atom feed top
2020-12-16 4:22 Linus Torvalds
2020-12-16 4:49 ` Josh Poimboeuf
2020-12-16 5:31 ` Linus Torvalds
2020-12-16 16:20 ` Josh Poimboeuf
2020-12-16 10:46 ` David Laight
2020-12-16 16:58 ` Josh Poimboeuf
[not found] ` <CAHk-=wjMoZesNgi1yWzY3nikyR11PUxHgov561UNom5mL1R4rA@mail.gmail.com>
[not found] ` <CAHk-=whpp_eo-5d0ZLpx=0X91J0ZNReZ_9riNf96z2dy24z=hw@mail.gmail.com>
2020-12-16 20:01 ` Josh Poimboeuf [this message]
2020-12-17 10:45 ` Peter Zijlstra
2020-12-17 16:25 ` Josh Poimboeuf
2020-12-17 17:27 ` Linus Torvalds
2020-12-17 17:45 ` Linus Torvalds
2020-12-17 18:25 ` Joe Perches
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20201216200158.akf356yrw44o2rlb@treble \
--to=jpoimboe@redhat.com \
--cc=linux-kernel@vger.kernel.org \
--cc=peterz@infradead.org \
--cc=torvalds@linux-foundation.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox
all inboxes | Powered by JetHome®