|
@@ -11,9 +11,6 @@ analyzes every .o file and ensures the validity of its stack metadata.
|
|
|
It enforces a set of rules on asm code and C inline assembly code so
|
|
|
that stack traces can be reliable.
|
|
|
|
|
|
-Currently it only checks frame pointer usage, but there are plans to add
|
|
|
-CFI validation for C files and CFI generation for asm files.
|
|
|
-
|
|
|
For each function, it recursively follows all possible code paths and
|
|
|
validates the correct frame pointer state at each instruction.
|
|
|
|
|
@@ -23,6 +20,10 @@ alternative execution paths to a given instruction (or set of
|
|
|
instructions). Similarly, it knows how to follow switch statements, for
|
|
|
which gcc sometimes uses jump tables.
|
|
|
|
|
|
+(Objtool also has an 'orc generate' subcommand which generates debuginfo
|
|
|
+for the ORC unwinder. See Documentation/x86/orc-unwinder.txt in the
|
|
|
+kernel tree for more details.)
|
|
|
+
|
|
|
|
|
|
Why do we need stack metadata validation?
|
|
|
-----------------------------------------
|
|
@@ -93,37 +94,14 @@ a) More reliable stack traces for frame pointer enabled kernels
|
|
|
or at the very end of the function after the stack frame has been
|
|
|
destroyed. This is an inherent limitation of frame pointers.
|
|
|
|
|
|
-b) 100% reliable stack traces for DWARF enabled kernels
|
|
|
-
|
|
|
- (NOTE: This is not yet implemented)
|
|
|
-
|
|
|
- As an alternative to frame pointers, DWARF Call Frame Information
|
|
|
- (CFI) metadata can be used to walk the stack. Unlike frame pointers,
|
|
|
- CFI metadata is out of band. So it doesn't affect runtime
|
|
|
- performance and it can be reliable even when interrupts or exceptions
|
|
|
- are involved.
|
|
|
-
|
|
|
- For C code, gcc automatically generates DWARF CFI metadata. But for
|
|
|
- asm code, generating CFI is a tedious manual approach which requires
|
|
|
- manually placed .cfi assembler macros to be scattered throughout the
|
|
|
- code. It's clumsy and very easy to get wrong, and it makes the real
|
|
|
- code harder to read.
|
|
|
-
|
|
|
- Stacktool will improve this situation in several ways. For code
|
|
|
- which already has CFI annotations, it will validate them. For code
|
|
|
- which doesn't have CFI annotations, it will generate them. So an
|
|
|
- architecture can opt to strip out all the manual .cfi annotations
|
|
|
- from their asm code and have objtool generate them instead.
|
|
|
+b) ORC (Oops Rewind Capability) unwind table generation
|
|
|
|
|
|
- We might also add a runtime stack validation debug option where we
|
|
|
- periodically walk the stack from schedule() and/or an NMI to ensure
|
|
|
- that the stack metadata is sane and that we reach the bottom of the
|
|
|
- stack.
|
|
|
+ An alternative to frame pointers and DWARF, ORC unwind data can be
|
|
|
+ used to walk the stack. Unlike frame pointers, ORC data is out of
|
|
|
+ band. So it doesn't affect runtime performance and it can be
|
|
|
+ reliable even when interrupts or exceptions are involved.
|
|
|
|
|
|
- So the benefit of objtool here will be that external tooling should
|
|
|
- always show perfect stack traces. And the same will be true for
|
|
|
- kernel warning/oops traces if the architecture has a runtime DWARF
|
|
|
- unwinder.
|
|
|
+ For more details, see Documentation/x86/orc-unwinder.txt.
|
|
|
|
|
|
c) Higher live patching compatibility rate
|
|
|
|
|
@@ -211,7 +189,7 @@ they mean, and suggestions for how to fix them.
|
|
|
function, add proper frame pointer logic using the FRAME_BEGIN and
|
|
|
FRAME_END macros. Otherwise, if it's not a callable function, remove
|
|
|
its ELF function annotation by changing ENDPROC to END, and instead
|
|
|
- use the manual CFI hint macros in asm/undwarf.h.
|
|
|
+ use the manual unwind hint macros in asm/unwind_hints.h.
|
|
|
|
|
|
If it's a GCC-compiled .c file, the error may be because the function
|
|
|
uses an inline asm() statement which has a "call" instruction. An
|
|
@@ -231,8 +209,8 @@ they mean, and suggestions for how to fix them.
|
|
|
If the error is for an asm file, and the instruction is inside (or
|
|
|
reachable from) a callable function, the function should be annotated
|
|
|
with the ENTRY/ENDPROC macros (ENDPROC is the important one).
|
|
|
- Otherwise, the code should probably be annotated with the CFI hint
|
|
|
- macros in asm/undwarf.h so objtool and the unwinder can know the
|
|
|
+ Otherwise, the code should probably be annotated with the unwind hint
|
|
|
+ macros in asm/unwind_hints.h so objtool and the unwinder can know the
|
|
|
stack state associated with the code.
|
|
|
|
|
|
If you're 100% sure the code won't affect stack traces, or if you're
|
|
@@ -258,7 +236,7 @@ they mean, and suggestions for how to fix them.
|
|
|
instructions aren't allowed in a callable function, and are most
|
|
|
likely part of the kernel entry code. They should usually not have
|
|
|
the callable function annotation (ENDPROC) and should always be
|
|
|
- annotated with the CFI hint macros in asm/undwarf.h.
|
|
|
+ annotated with the unwind hint macros in asm/unwind_hints.h.
|
|
|
|
|
|
|
|
|
6. file.o: warning: objtool: func()+0x26: sibling call from callable instruction with modified stack frame
|
|
@@ -272,7 +250,7 @@ they mean, and suggestions for how to fix them.
|
|
|
|
|
|
If the instruction is not actually in a callable function (e.g.
|
|
|
kernel entry code), change ENDPROC to END and annotate manually with
|
|
|
- the CFI hint macros in asm/undwarf.h.
|
|
|
+ the unwind hint macros in asm/unwind_hints.h.
|
|
|
|
|
|
|
|
|
7. file: warning: objtool: func()+0x5c: stack state mismatch
|
|
@@ -288,8 +266,8 @@ they mean, and suggestions for how to fix them.
|
|
|
|
|
|
Another possibility is that the code has some asm or inline asm which
|
|
|
does some unusual things to the stack or the frame pointer. In such
|
|
|
- cases it's probably appropriate to use the CFI hint macros in
|
|
|
- asm/undwarf.h.
|
|
|
+ cases it's probably appropriate to use the unwind hint macros in
|
|
|
+ asm/unwind_hints.h.
|
|
|
|
|
|
|
|
|
8. file.o: warning: objtool: funcA() falls through to next function funcB()
|