instrumentation.h 1.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657
  1. /* SPDX-License-Identifier: GPL-2.0 */
  2. #ifndef __LINUX_INSTRUMENTATION_H
  3. #define __LINUX_INSTRUMENTATION_H
  4. #if defined(CONFIG_DEBUG_ENTRY) && defined(CONFIG_STACK_VALIDATION)
  5. /* Begin/end of an instrumentation safe region */
  6. #define instrumentation_begin() ({ \
  7. asm volatile("%c0: nop\n\t" \
  8. ".pushsection .discard.instr_begin\n\t" \
  9. ".long %c0b - .\n\t" \
  10. ".popsection\n\t" : : "i" (__COUNTER__)); \
  11. })
  12. /*
  13. * Because instrumentation_{begin,end}() can nest, objtool validation considers
  14. * _begin() a +1 and _end() a -1 and computes a sum over the instructions.
  15. * When the value is greater than 0, we consider instrumentation allowed.
  16. *
  17. * There is a problem with code like:
  18. *
  19. * noinstr void foo()
  20. * {
  21. * instrumentation_begin();
  22. * ...
  23. * if (cond) {
  24. * instrumentation_begin();
  25. * ...
  26. * instrumentation_end();
  27. * }
  28. * bar();
  29. * instrumentation_end();
  30. * }
  31. *
  32. * If instrumentation_end() would be an empty label, like all the other
  33. * annotations, the inner _end(), which is at the end of a conditional block,
  34. * would land on the instruction after the block.
  35. *
  36. * If we then consider the sum of the !cond path, we'll see that the call to
  37. * bar() is with a 0-value, even though, we meant it to happen with a positive
  38. * value.
  39. *
  40. * To avoid this, have _end() be a NOP instruction, this ensures it will be
  41. * part of the condition block and does not escape.
  42. */
  43. #define instrumentation_end() ({ \
  44. asm volatile("%c0: nop\n\t" \
  45. ".pushsection .discard.instr_end\n\t" \
  46. ".long %c0b - .\n\t" \
  47. ".popsection\n\t" : : "i" (__COUNTER__)); \
  48. })
  49. #else
  50. # define instrumentation_begin() do { } while(0)
  51. # define instrumentation_end() do { } while(0)
  52. #endif
  53. #endif /* __LINUX_INSTRUMENTATION_H */