Simplify gen_btf logic to make it work with llvm-objcopy. The existing 'file format' and 'architecture' parsing logic is brittle and does not work with llvm-objcopy/llvm-objdump. 'file format' output of llvm-objdump>=11 will match GNU objdump, but 'architecture' (bfdarch) may not. .BTF in .tmp_vmlinux.btf is non-SHF_ALLOC. Add the SHF_ALLOC flag because it is part of vmlinux image used for introspection. C code can reference the section via linker script defined __start_BTF and __stop_BTF. This fixes a small problem that previous .BTF had the SHF_WRITE flag (objcopy -I binary -O elf* synthesized .data). Additionally, `objcopy -I binary` synthesized symbols _binary__btf_vmlinux_bin_start and _binary__btf_vmlinux_bin_stop (not used elsewhere) are replaced with more commonplace __start_BTF and __stop_BTF. Add 2>/dev/null because GNU objcopy (but not llvm-objcopy) warns "empty loadable segment detected at vaddr=0xffffffff81000000, is this intentional?" We use a dd command to change the e_type field in the ELF header from ET_EXEC to ET_REL so that lld will accept .btf.vmlinux.bin.o. Accepting ET_EXEC as an input file is an extremely rare GNU ld feature that lld does not intend to support, because this is error-prone. The output section description .BTF in include/asm-generic/vmlinux.lds.h avoids potential subtle orphan section placement issues and suppresses --orphan-handling=warn warnings.
Unified · Split
| @@ -303,12 +303,6 @@ SECTIONS · 302 unmodified lines | ||
| 303 | 303 | *(.branch_lt) |
| 304 | 304 | } |
| 305 | 305 | |
| 306 | −#ifdef CONFIG_DEBUG_INFO_BTF | |
| 307 | − .BTF : AT(ADDR(.BTF) - LOAD_OFFSET) { | |
| 308 | − *(.BTF) | |
| 309 | − } | |
| 310 | −#endif | |
| 311 | − | |
| 312 | 306 | .opd : AT(ADDR(.opd) - LOAD_OFFSET) { |
| 313 | 307 | __start_opd = .; |
| 314 | 308 | KEEP(*(.opd)) |
| @@ -535,6 +535,7 @@ · 534 unmodified lines | ||
| 535 | 535 | \ |
| 536 | 536 | RO_EXCEPTION_TABLE \ |
| 537 | 537 | NOTES \ |
| 538 | + BTF \ | |
| 538 | 539 | \ |
| 539 | 540 | . = ALIGN((align)); \ |
| 540 | 541 | __end_rodata = .; |
| @@ -621,6 +622,20 @@ · 80 unmodified lines | ||
| 621 | 622 | __stop___ex_table = .; \ |
| 622 | 623 | } |
| 623 | 624 | |
| 625 | +/* | |
| 626 | + * .BTF | |
| 627 | + */ | |
| 628 | +#ifdef CONFIG_DEBUG_INFO_BTF | |
| 629 | +#define BTF \ | |
| 630 | + .BTF : AT(ADDR(.BTF) - LOAD_OFFSET) { \ | |
| 631 | + __start_BTF = .; \ | |
| 632 | + *(.BTF) \ | |
| 633 | + __stop_BTF = .; \ | |
| 634 | + } | |
| 635 | +#else | |
| 636 | +#define BTF | |
| 637 | +#endif | |
| 638 | + | |
| 624 | 639 | /* |
| 625 | 640 | * Init task |
| 626 | 641 | */ |
| @@ -3477,8 +3477,8 @@ errout: · 3476 unmodified lines | ||
| 3477 | 3477 | return ERR_PTR(err); |
| 3478 | 3478 | } |
| 3479 | 3479 | |
| 3480 | −extern char __weak _binary__btf_vmlinux_bin_start[]; | |
| 3481 | −extern char __weak _binary__btf_vmlinux_bin_end[]; | |
| 3480 | +extern char __weak __start_BTF[]; | |
| 3481 | +extern char __weak __stop_BTF[]; | |
| 3482 | 3482 | extern struct btf *btf_vmlinux; |
| 3483 | 3483 | |
| 3484 | 3484 | #define BPF_MAP_TYPE(_id, _ops) |
| @@ -3605,9 +3605,8 @@ struct btf *btf_parse_vmlinux(void) · 120 unmodified lines | ||
| 3605 | 3605 | } |
| 3606 | 3606 | env->btf = btf; |
| 3607 | 3607 | |
| 3608 | − btf->data = _binary__btf_vmlinux_bin_start; | |
| 3609 | − btf->data_size = _binary__btf_vmlinux_bin_end - | |
| 3610 | − _binary__btf_vmlinux_bin_start; | |
| 3608 | + btf->data = __start_BTF; | |
| 3609 | + btf->data_size = __stop_BTF - __start_BTF; | |
| 3611 | 3610 | |
| 3612 | 3611 | err = btf_parse_hdr(env); |
| 3613 | 3612 | if (err) |
| @@ -9,15 +9,15 @@ · 8 unmodified lines | ||
| 9 | 9 | #include <linux/sysfs.h> |
| 10 | 10 | |
| 11 | 11 | /* See scripts/link-vmlinux.sh, gen_btf() func for details */ |
| 12 | −extern char __weak _binary__btf_vmlinux_bin_start[]; | |
| 13 | −extern char __weak _binary__btf_vmlinux_bin_end[]; | |
| 12 | +extern char __weak __start_BTF[]; | |
| 13 | +extern char __weak __stop_BTF[]; | |
| 14 | 14 | |
| 15 | 15 | static ssize_t |
| 16 | 16 | btf_vmlinux_read(struct file *file, struct kobject *kobj, |
| 17 | 17 | struct bin_attribute *bin_attr, |
| 18 | 18 | char *buf, loff_t off, size_t len) |
| 19 | 19 | { |
| 20 | − memcpy(buf, _binary__btf_vmlinux_bin_start + off, len); | |
| 20 | + memcpy(buf, __start_BTF + off, len); | |
| 21 | 21 | return len; |
| 22 | 22 | } |
| 23 | 23 | |
| @@ -30,15 +30,14 @@ static struct kobject *btf_kobj; · 6 unmodified lines | ||
| 30 | 30 | |
| 31 | 31 | static int __init btf_vmlinux_init(void) |
| 32 | 32 | { |
| 33 | − if (!_binary__btf_vmlinux_bin_start) | |
| 33 | + if (!__start_BTF) | |
| 34 | 34 | return 0; |
| 35 | 35 | |
| 36 | 36 | btf_kobj = kobject_create_and_add("btf", kernel_kobj); |
| 37 | 37 | if (!btf_kobj) |
| 38 | 38 | return -ENOMEM; |
| 39 | 39 | |
| 40 | − bin_attr_btf_vmlinux.size = _binary__btf_vmlinux_bin_end - | |
| 41 | − _binary__btf_vmlinux_bin_start; | |
| 40 | + bin_attr_btf_vmlinux.size = __stop_BTF - __start_BTF; | |
| 42 | 41 | |
| 43 | 42 | return sysfs_create_bin_file(btf_kobj, &bin_attr_btf_vmlinux); |
| 44 | 43 | } |
| @@ -113,9 +113,6 @@ vmlinux_link() · 112 unmodified lines | ||
| 113 | 113 | gen_btf() |
| 114 | 114 | { |
| 115 | 115 | local pahole_ver |
| 116 | − local bin_arch | |
| 117 | − local bin_format | |
| 118 | − local bin_file | |
| 119 | 116 | |
| 120 | 117 | if ! [ -x "$(command -v ${PAHOLE})" ]; then |
| 121 | 118 | echo >&2 "BTF: ${1}: pahole (${PAHOLE}) is not available" |
| @@ -133,17 +130,16 @@ gen_btf() · 11 unmodified lines | ||
| 133 | 130 | info "BTF" ${2} |
| 134 | 131 | LLVM_OBJCOPY=${OBJCOPY} ${PAHOLE} -J ${1} |
| 135 | 132 | |
| 136 | − # dump .BTF section into raw binary file to link with final vmlinux | |
| 137 | − bin_arch=$(LANG=C ${OBJDUMP} -f ${1} | grep architecture | \ | |
| 138 | − cut -d, -f1 | cut -d' ' -f2) | |
| 139 | − bin_format=$(LANG=C ${OBJDUMP} -f ${1} | grep 'file format' | \ | |
| 140 | − awk '{print $4}') | |
| 141 | − bin_file=.btf.vmlinux.bin | |
| 142 | − ${OBJCOPY} --change-section-address .BTF=0 \ | |
| 143 | − --set-section-flags .BTF=alloc -O binary \ | |
| 144 | − --only-section=.BTF ${1} $bin_file | |
| 145 | − ${OBJCOPY} -I binary -O ${bin_format} -B ${bin_arch} \ | |
| 146 | − --rename-section .data=.BTF $bin_file ${2} | |
| 133 | + # Create ${2} which contains just .BTF section but no symbols. Add | |
| 134 | + # SHF_ALLOC because .BTF will be part of the vmlinux image. --strip-all | |
| 135 | + # deletes all symbols including __start_BTF and __stop_BTF, which will | |
| 136 | + # be redefined in the linker script. Add 2>/dev/null to suppress GNU | |
| 137 | + # objcopy warnings: "empty loadable segment detected at ..." | |
| 138 | + ${OBJCOPY} --only-section=.BTF --set-section-flags .BTF=alloc,readonly \ | |
| 139 | + --strip-all ${1} ${2} 2>/dev/null | |
| 140 | + # Change e_type to ET_REL so that it can be used to link final vmlinux. | |
| 141 | + # Unlike GNU ld, lld does not allow an ET_EXEC input. | |
| 142 | + printf '\1' | dd of=${2} conv=notrunc bs=1 seek=16 status=none | |
| 147 | 143 | } |
| 148 | 144 | |
| 149 | 145 | # Create ${2} .o file with all symbols from the ${1} object file |