gen-btf.sh 3.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147
  1. #!/bin/sh
  2. # SPDX-License-Identifier: GPL-2.0
  3. # Copyright (c) 2025 Meta Platforms, Inc. and affiliates.
  4. #
  5. # This script generates BTF data for the provided ELF file.
  6. #
  7. # Kernel BTF generation involves these conceptual steps:
  8. # 1. pahole generates BTF from DWARF data
  9. # 2. resolve_btfids applies kernel-specific btf2btf
  10. # transformations and computes data for .BTF_ids section
  11. # 3. the result gets linked/objcopied into the target binary
  12. #
  13. # How step (3) should be done differs between vmlinux, and
  14. # kernel modules, which is the primary reason for the existence
  15. # of this script.
  16. #
  17. # For modules the script expects vmlinux passed in as --btf_base.
  18. # Generated .BTF, .BTF.base and .BTF_ids sections become embedded
  19. # into the input ELF file with objcopy.
  20. #
  21. # For vmlinux the input file remains unchanged and two files are produced:
  22. # - ${1}.btf.o ready for linking into vmlinux
  23. # - ${1}.BTF_ids with .BTF_ids data blob
  24. # This output is consumed by scripts/link-vmlinux.sh
  25. set -e
  26. usage()
  27. {
  28. echo "Usage: $0 [--btf_base <file>] <target ELF file>"
  29. exit 1
  30. }
  31. BTF_BASE=""
  32. while [ $# -gt 0 ]; do
  33. case "$1" in
  34. --btf_base)
  35. BTF_BASE="$2"
  36. shift 2
  37. ;;
  38. -*)
  39. echo "Unknown option: $1" >&2
  40. usage
  41. ;;
  42. *)
  43. break
  44. ;;
  45. esac
  46. done
  47. if [ $# -ne 1 ]; then
  48. usage
  49. fi
  50. ELF_FILE="$1"
  51. shift
  52. is_enabled() {
  53. grep -q "^$1=y" ${objtree}/include/config/auto.conf
  54. }
  55. case "${KBUILD_VERBOSE}" in
  56. *1*)
  57. set -x
  58. ;;
  59. esac
  60. gen_btf_data()
  61. {
  62. btf1="${ELF_FILE}.BTF.1"
  63. ${PAHOLE} -J ${PAHOLE_FLAGS} \
  64. ${BTF_BASE:+--btf_base ${BTF_BASE}} \
  65. --btf_encode_detached=${btf1} \
  66. "${ELF_FILE}"
  67. ${RESOLVE_BTFIDS} ${RESOLVE_BTFIDS_FLAGS} \
  68. ${BTF_BASE:+--btf_base ${BTF_BASE}} \
  69. --btf ${btf1} "${ELF_FILE}"
  70. }
  71. gen_btf_o()
  72. {
  73. btf_data=${ELF_FILE}.btf.o
  74. # Create ${btf_data} which contains just .BTF section but no symbols. Add
  75. # SHF_ALLOC because .BTF will be part of the vmlinux image. --strip-all
  76. # deletes all symbols including __start_BTF and __stop_BTF, which will
  77. # be redefined in the linker script.
  78. echo "" | ${CC} ${CLANG_FLAGS} ${KBUILD_CPPFLAGS} ${KBUILD_CFLAGS} -fno-lto -c -x c -o ${btf_data} -
  79. ${OBJCOPY} --add-section .BTF=${ELF_FILE}.BTF \
  80. --set-section-flags .BTF=alloc,readonly ${btf_data}
  81. ${OBJCOPY} --only-section=.BTF --strip-all ${btf_data}
  82. # Change e_type to ET_REL so that it can be used to link final vmlinux.
  83. # GNU ld 2.35+ and lld do not allow an ET_EXEC input.
  84. if is_enabled CONFIG_CPU_BIG_ENDIAN; then
  85. et_rel='\0\1'
  86. else
  87. et_rel='\1\0'
  88. fi
  89. printf "${et_rel}" | dd of="${btf_data}" conv=notrunc bs=1 seek=16 status=none
  90. }
  91. embed_btf_data()
  92. {
  93. ${OBJCOPY} --add-section .BTF=${ELF_FILE}.BTF ${ELF_FILE}
  94. # a module might not have a .BTF_ids or .BTF.base section
  95. btf_base="${ELF_FILE}.BTF.base"
  96. if [ -f "${btf_base}" ]; then
  97. ${OBJCOPY} --add-section .BTF.base=${btf_base} ${ELF_FILE}
  98. fi
  99. btf_ids="${ELF_FILE}.BTF_ids"
  100. if [ -f "${btf_ids}" ]; then
  101. ${RESOLVE_BTFIDS} --patch_btfids ${btf_ids} ${ELF_FILE}
  102. fi
  103. }
  104. cleanup()
  105. {
  106. rm -f "${ELF_FILE}.BTF.1"
  107. rm -f "${ELF_FILE}.BTF"
  108. if [ "${BTFGEN_MODE}" = "module" ]; then
  109. rm -f "${ELF_FILE}.BTF.base"
  110. rm -f "${ELF_FILE}.BTF_ids"
  111. fi
  112. }
  113. trap cleanup EXIT
  114. BTFGEN_MODE="vmlinux"
  115. if [ -n "${BTF_BASE}" ]; then
  116. BTFGEN_MODE="module"
  117. fi
  118. gen_btf_data
  119. case "${BTFGEN_MODE}" in
  120. vmlinux)
  121. gen_btf_o
  122. ;;
  123. module)
  124. embed_btf_data
  125. ;;
  126. esac
  127. exit 0