Hi. Le vendredi 21 juillet 2023, 14:40:54 CEST Alessandro Carminati a écrit : > Hello, > > I apologize for being noisy today. > > In an effort to be collaborative, I would like to share my thoughts on why I > see duplicate symbols in fs/binfmt_elf.c. > > Il giorno ven 21 lug 2023 alle ore 11:22 Alessandro Carminati > > <alessandro.carminati@xxxxxxxxx> ha scritto: > > Hello Steven, Alexander, and Nick, > > > > Since now I realize that a lot of people are working on my very same > > argument, I'm writing you this mail just with the intent of not leaving > > my statements floating in the air, and help the cause by sharing my > > experience, as little it is, to solve this problem. > > > > The addr2line strategy, I tried to implement, allows me to achieve the > > level of accuracy that Luis mentioned in his comment about live-patching > > suggestions. The addr2line-based approach is feasible, however, to make > > this approach operable, I had to ensure that vmlinux contains the > > necessary debug information. > > Let me clarify. > > During the kernel build, I do need the vmlinux to contain debug > > information. The approach I pursued parses the nm output and, when it > > detects a duplicate symbol, it needs to query vmlinux using addr2line to > > resolve the address where the symbol is reported to be. > > The whole process takes place during the building phase. > > I've completed the work to integrate the new alias within the compilation > > phase, and I wanted to share with you how it looks now. > > > > ``` > > ~ # uname -a > > Linux (none) 6.4.0 #1 SMP PREEMPT Thu Jul 20 10:05:36 UTC 2023 aarch64 > > GNU/Linux ~ # cat /proc/kallsyms | grep gic_mask_irq > > ffffacf2eb64dae4 t gic_mask_irq > > ffffacf2eb64dae4 t gic_mask_irq@_drivers_irqchip_irq-gic_c_167 > > ffffacf2eb650960 t gic_mask_irq > > ffffacf2eb650960 t gic_mask_irq@_drivers_irqchip_irq-gic-v3_c_404 > > ~ # > > ``` > > > > Despite this appearing to have a sufficient level of accuracy, when I > > tested it, I realized something I really did not expect. Multiple > > instances of the same function exist, and when I say "same function," I > > don't just mean the name, but also the function's body. I apologize for > > stating something that may sound obvious to you, but I found this really > > unexpected. > > > > ``` > > ~ # uname -a > > Linux (none) 6.4.0 #1 SMP PREEMPT Thu Jul 20 10:05:36 UTC 2023 aarch64 > > GNU/Linux ~ # cat /proc/kallsyms | grep -E " [ttT] " | cut -d" " > > -f3|sort| uniq -d| grep @_ > > BIT_initDStream@_lib_zstd_common_bitstream_h_259 > > __dev_hold@_include_linux_netdevice_h_4059 > > __dev_put@_include_linux_netdevice_h_4048 > > __flush_tlb_range@_arch_arm64_include_asm_tlbflush_h_291 > > __flush_tlb_range_constprop_0@_arch_arm64_include_asm_tlbflush_h_291 > > __kern_my_cpu_offset@_arch_arm64_include_asm_percpu_h_40 > > __kvm_nvhe_$x@_arch_arm64_kvm_hyp_include_nvhe_memory_h_22 > > __kvm_nvhe___kvm_skip_instr@_arch_arm64_kvm_hyp_include_hyp_adjust_pc_h_34 > > __kvm_nvhe_hyp_page_count@_arch_arm64_kvm_hyp_include_nvhe_memory_h_47 > > __kvm_nvhe_hyp_phys_to_virt@_arch_arm64_kvm_hyp_include_nvhe_memory_h_22 > > __kvm_nvhe_hyp_virt_to_phys@_arch_arm64_kvm_hyp_include_nvhe_memory_h_27 > > __kvm_skip_instr@_arch_arm64_kvm_hyp_include_hyp_adjust_pc_h_34 > > __nodes_weight_constprop_0@_include_linux_nodemask_h_239 > > __pi_$x@_scripts_dtc_libfdt_libfdt_h_145 > > __pi_fdt32_ld@_scripts_dtc_libfdt_libfdt_h_145 > > __preempt_count_dec_and_test@_arch_arm64_include_asm_current_h_19 > > acpi_dev_filter_resource_type_cb@_include_linux_acpi_h_520 > > add_quirk@_drivers_mmc_core_card_h_158 > > bpf_enable_instrumentation@_include_linux_bpf_h_1937 > > btf_id_cmp_func@_include_linux_btf_h_469 > > copy_from_sockptr_offset_constprop_0@_include_linux_sockptr_h_44 > > cpucap_multi_entry_cap_matches@_arch_arm64_include_asm_cpufeature_h_395 > > cpufreq_register_em_with_opp@_include_linux_cpufreq_h_1228 > > cpumask_weight@_include_linux_cpumask_h_691 > > cpumask_weight_constprop_0@_include_linux_cpumask_h_690 > > css_put@_include_linux_cgroup_refcnt_h_77 > > dma_cookie_status@_drivers_dma_dmaengine_h_74 > > dst_discard@_include_net_dst_h_392 > > dst_output@_include_net_dst_h_457 > > elf_core_dump@_fs_binfmt_elf_c_2027 > > fixup_use_fwh_lock@_drivers_mtd_chips_fwh_lock_h_102 > > flush_tlb_mm@_arch_arm64_include_asm_tlbflush_h_250 > > fwh_lock_varsize@_drivers_mtd_chips_fwh_lock_h_81 > > fwh_unlock_varsize@_drivers_mtd_chips_fwh_lock_h_92 > > fwh_xxlock_oneblock@_drivers_mtd_chips_fwh_lock_h_31 > > get_net_ns@_include_net_net_namespace_h_231 > > inline_map_read_isra_0@_include_linux_mtd_map_h_393 > > inline_map_write_part_0@_include_linux_mtd_map_h_426 > > io_run_task_work@_io_uring_io_uring_h_282 > > ipv6_portaddr_hash_isra_0@_include_net_ipv6_h_732 > > irq_find_host@_include_linux_irqdomain_h_322 > > jhash@_include_linux_jhash_h_76 > > jhash_constprop_0@_include_linux_jhash_h_76 > > ktime_get_boottime@_include_linux_timekeeping_h_94 > > ktime_get_real@_include_linux_timekeeping_h_78 > > load_elf_binary@_fs_binfmt_elf_c_824 > > load_elf_phdrs@_fs_binfmt_elf_c_468 > > may_use_simd@_arch_arm64_include_asm_alternative-macros_h_232 > > netif_tx_disable@_include_linux_netdevice_h_4486 > > of_parse_phandle@_include_linux_of_h_946 > > of_parse_phandle_constprop_0@_include_linux_of_h_943 > > padzero@_fs_binfmt_elf_c_142 > > percpu_down_read_constprop_0@_include_linux_percpu-rwsem_h_47 > > percpu_ref_get_many@_include_linux_percpu-refcount_h_199 > > percpu_ref_get_many_constprop_0@_include_linux_percpu-refcount_h_198 > > percpu_ref_put_many_constprop_0@_include_linux_percpu-refcount_h_326 > > percpu_up_read@_include_linux_percpu-rwsem_h_98 > > percpu_up_read_constprop_0@_include_linux_percpu-rwsem_h_97 > > pinconf_generic_dt_node_to_map_all@_include_linux_pinctrl_pinconf-generic_ > > h_223 > > pinconf_generic_dt_node_to_map_group@_include_linux_pinctrl_pinconf-gener > > ic_h_207 > > pinconf_generic_dt_node_to_map_pin@_include_linux_pinctrl_pinconf-generic > > _h_215 > > platform_device_register_resndata_constprop_0@_include_linux_platform_dev > > ice_h_125 > > ptrauth_keys_install_user@_arch_arm64_include_asm_alternative-macros_h_23 > > 2 readl@_arch_arm64_include_asm_io_h_75 > > reqsk_put@_include_net_request_sock_h_133 > > rht_key_get_hash_constprop_0_isra_0@_include_linux_rhashtable_h_133 > > rht_key_get_hash_isra_0@_include_linux_rhashtable_h_125 > > role_show@_include_linux_device_h_763 > > sdhci_and_cqhci_reset@_drivers_mmc_host_sdhci-cqhci_h_16 > > set_active_memcg_part_0@_include_linux_sched_mm_h_410 > > set_brk@_fs_binfmt_elf_c_114 > > set_is_seen@_arch_arm64_include_asm_current_h_19 > > set_lookup@_arch_arm64_include_asm_current_h_19 > > sha1_base_init@_include_crypto_sha1_base_h_22 > > sha224_base_init@_include_crypto_sha256_base_h_23 > > sha256_base_init@_include_crypto_sha256_base_h_31 > > spi_sync_transfer_constprop_0@_include_linux_spi_spi_h_1339 > > spi_write@_include_linux_spi_spi_h_1363 > > tlb_flush@_arch_arm64_include_asm_tlb_h_54 > > trace_xhci_dbg_quirks@_drivers_usb_host_xhci-trace_h_48 > > udp_lib_close@_include_net_udp_h_197 > > udp_lib_hash@_include_net_udp_h_189 > > virtio_net_hdr_to_skb_constprop_0@_include_linux_virtio_net_h_48 > > writenote@_fs_binfmt_elf_c_1479 > > zero_user_segments@_include_linux_highmem_h_271 > > zero_user_segments_constprop_0@_include_linux_highmem_h_268 > > ``` > > > > The previous evidence demonstrates that adding a tag with a file and line > > number does not make a symbol unique. > > > > Here, I inspect the function body to verify if the functions are indeed > > the same. > > > > ``` > > Welcome to Buildroot > > buildroot login: root > > ~ # cat /proc/kallsyms | grep set_brk > > ffffa8a9d1cf1d2c t set_brk > > ffffa8a9d1cf1d2c t set_brk@_fs_binfmt_elf_c_114 > > ffffa8a9d1cf4454 t set_brk > > ffffa8a9d1cf4454 t set_brk@_fs_binfmt_elf_c_114 > > ~ # QEMU: Terminated > > $ cat System.map | grep set_brk > > ffff8000082f1d2c t set_brk > > ffff8000082f4454 t set_brk > > ~ $ r2 vmlinux > > Warning: run r2 with -e bin.cache=true to fix relocations in disassembly > > > > -- Reduce the delta where flag resolving by address is used with > > cfg.delta > > > > [0xffff800008000000]> s 0xffff8000082f1d2c > > [0xffff8000082f1d2c]> aa > > [x] Analyze all flags starting with sym. and entry0 (aa) > > [x] Analyze all functions arguments/locals > > [0xffff8000082f1d2c]> pdf > > > > ; CALL XREFS from sym.load_elf_binary @ 0xffff8000082f352c(x), > > 0xffff8000082f38d4(x), 0xffff8000082f3a68(x)> > > ┌ 112: sym.set_brk (int64_t arg1, int64_t arg2, int64_t arg3); > > │ ; arg int64_t arg1 @ x0 > > │ ; arg int64_t arg2 @ x1 > > │ ; arg int64_t arg3 @ x2 > > │ ; var int64_t var_10h @ sp+0x10 > > │ 0xffff8000082f1d2c 3f2303d5 paciasp ; > > binfmt_elf.c:114 │ 0xffff8000082f1d30 fd7bbea9 stp > > x29, x30, [sp, -0x20]! │ 0xffff8000082f1d34 00fc3f91 > > add x0, x0, 0xfff ; binfmt_elf.c:115 ; arg1 │ > > 0xffff8000082f1d38 fd030091 mov x29, sp ; > > binfmt_elf.c:114 │ 0xffff8000082f1d3c 21fc3f91 add > > x1, x1, 0xfff ; binfmt_elf.c:116 ; arg2 │ 0xffff8000082f1d40 > > 00cc7492 and x0, x0, 0xfffffffffffff000 ; binfmt_elf.c:114 ; > > arg1 │ 0xffff8000082f1d44 f30b00f9 str x19, [sp, > > 0x10] ; binfmt_elf.c:116 │ 0xffff8000082f1d48 33cc7492 > > and x19, x1, 0xfffffffffffff000 ; arg2 │ 0xffff8000082f1d4c > > 1f0013eb cmp x0, x19 ; binfmt_elf.c:117 ; arg1 │ > > ┌─< 0xffff8000082f1d50 63010054 b.lo 0xffff8000082f1d7c │ > > ┌──> 0xffff8000082f1d54 014138d5 mrs x1, sp_el0 ; > > binfmt_elf.c:128 │ ╎│ 0xffff8000082f1d58 22fc41f9 ldr > > x2, [x1, 0x3f8] ; current.h:21 ; 0xd9 ; 217 │ ╎│ > > 0xffff8000082f1d5c 00008052 mov w0, 0 ; > > binfmt_elf.c:129 │ ╎│ 0xffff8000082f1d60 539400f9 str > > x19, [x2, 0x128] ; binfmt_elf.c:128 │ ╎│ 0xffff8000082f1d64 > > 21fc41f9 ldr x1, [x1, 0x3f8] ; current.h:17 ; 0xd9 ; 217 │ ╎│ > > 0xffff8000082f1d68 339000f9 str x19, [x1, 0x120] ; > > binfmt_elf.c:128 │ ╎│ 0xffff8000082f1d6c f30b40f9 ldr > > x19, [var_10h] ; binfmt_elf.c:129 ; 5 │ ╎│ 0xffff8000082f1d70 > > fd7bc2a8 ldp x29, x30, [sp], 0x20 │ ╎│ 0xffff8000082f1d74 > > bf2303d5 autiasp > > │ ╎│ 0xffff8000082f1d78 c0035fd6 ret > > │ ╎└─> 0xffff8000082f1d7c 42007e92 and x2, x2, 4 ; > > binfmt_elf.c:123 ; arg3 │ ╎ 0xffff8000082f1d80 610200cb > > sub x1, x19, x0 ; arg1 │ ╎ 0xffff8000082f1d84 cae3fc97 > > bl sym.vm_brk_flags │ └──< 0xffff8000082f1d88 60feff34 > > cbz w0, 0xffff8000082f1d54 ; binfmt_elf.c:125 │ > > 0xffff8000082f1d8c f30b40f9 ldr x19, [var_10h] ; > > binfmt_elf.c:130 ; 5 │ 0xffff8000082f1d90 fd7bc2a8 > > ldp x29, x30, [sp], 0x20 │ 0xffff8000082f1d94 bf2303d5 > > autiasp > > └ 0xffff8000082f1d98 c0035fd6 ret > > [0xffff8000082f1d2c]> s 0xffff8000082f4454 > > [0xffff8000082f4454]> pdf > > > > ; CALL XREFS from sym.load_elf_binary_1 @ > > 0xffff8000082f5cc0(x), 0xffff8000082f5e5c(x), > > 0xffff8000082f6648(x)> > > ┌ 112: sym.set_brk_1 (int64_t arg1, int64_t arg2, int64_t arg3); > > │ ; arg int64_t arg1 @ x0 > > │ ; arg int64_t arg2 @ x1 > > │ ; arg int64_t arg3 @ x2 > > │ ; var int64_t var_10h @ sp+0x10 > > │ 0xffff8000082f4454 3f2303d5 paciasp ; > > binfmt_elf.c:114 │ 0xffff8000082f4458 fd7bbea9 stp > > x29, x30, [sp, -0x20]! │ 0xffff8000082f445c 00fc3f91 > > add x0, x0, 0xfff ; binfmt_elf.c:115 ; arg1 │ > > 0xffff8000082f4460 fd030091 mov x29, sp ; > > binfmt_elf.c:114 │ 0xffff8000082f4464 21fc3f91 add > > x1, x1, 0xfff ; binfmt_elf.c:116 ; arg2 │ 0xffff8000082f4468 > > 00cc7492 and x0, x0, 0xfffffffffffff000 ; binfmt_elf.c:114 ; > > arg1 │ 0xffff8000082f446c f30b00f9 str x19, [sp, > > 0x10] ; binfmt_elf.c:116 │ 0xffff8000082f4470 33cc7492 > > and x19, x1, 0xfffffffffffff000 ; arg2 │ 0xffff8000082f4474 > > 1f0013eb cmp x0, x19 ; binfmt_elf.c:117 ; arg1 │ > > ┌─< 0xffff8000082f4478 63010054 b.lo 0xffff8000082f44a4 │ > > ┌──> 0xffff8000082f447c 014138d5 mrs x1, sp_el0 ; > > binfmt_elf.c:128 │ ╎│ 0xffff8000082f4480 22fc41f9 ldr > > x2, [x1, 0x3f8] ; current.h:21 ; 0xd9 ; 217 │ ╎│ > > 0xffff8000082f4484 00008052 mov w0, 0 ; > > binfmt_elf.c:129 │ ╎│ 0xffff8000082f4488 539400f9 str > > x19, [x2, 0x128] ; binfmt_elf.c:128 │ ╎│ 0xffff8000082f448c > > 21fc41f9 ldr x1, [x1, 0x3f8] ; current.h:17 ; 0xd9 ; 217 │ ╎│ > > 0xffff8000082f4490 339000f9 str x19, [x1, 0x120] ; > > binfmt_elf.c:128 │ ╎│ 0xffff8000082f4494 f30b40f9 ldr > > x19, [var_10h] ; binfmt_elf.c:129 ; 5 │ ╎│ 0xffff8000082f4498 > > fd7bc2a8 ldp x29, x30, [sp], 0x20 │ ╎│ 0xffff8000082f449c > > bf2303d5 autiasp > > │ ╎│ 0xffff8000082f44a0 c0035fd6 ret > > │ ╎└─> 0xffff8000082f44a4 42007e92 and x2, x2, 4 ; > > binfmt_elf.c:123 ; arg3 │ ╎ 0xffff8000082f44a8 610200cb > > sub x1, x19, x0 ; arg1 │ ╎ 0xffff8000082f44ac 00dafc97 > > bl sym.vm_brk_flags │ └──< 0xffff8000082f44b0 60feff34 > > cbz w0, 0xffff8000082f447c ; binfmt_elf.c:125 │ > > 0xffff8000082f44b4 f30b40f9 ldr x19, [var_10h] ; > > binfmt_elf.c:130 ; 5 │ 0xffff8000082f44b8 fd7bc2a8 > > ldp x29, x30, [sp], 0x20 │ 0xffff8000082f44bc bf2303d5 > > autiasp > > └ 0xffff8000082f44c0 c0035fd6 ret > > [0xffff8000082f4454]> > > ``` > > > > While I can speculate on a reasonable explanation for why I see symbols > > coming from header files being duplicated – when a header file is > > included in a C file and it produces a function that the compiler does > > not want to inline, it is replicated every time the file is included – I > > have no convincing explanation as to why the fs/binfmt.c functions exist > > in more than one instance. > > > > ``` > > elf_core_dump@_fs_binfmt_elf_c_2027 > > load_elf_binary@_fs_binfmt_elf_c_824 > > load_elf_phdrs@_fs_binfmt_elf_c_468 > > padzero@_fs_binfmt_elf_c_142 > > set_brk@_fs_binfmt_elf_c_114 > > writenote@_fs_binfmt_elf_c_1479 > > ``` > > After examining the contents of built-in.a, I have come up with a new > interpretation of what I am observing. > According to built-in.a, System.map, and vmlinux there are two symbols named > set_brk. > > ``` > ~ $ cat System.map | grep set_brk > ffff8000082f1d2c t set_brk > ffff8000082f4454 t set_brk > ~ $ > ~ $ nm -n vmlinux | grep set_brk > ffff8000082f1d2c t set_brk > ffff8000082f4454 t set_brk > ~ $ > ~ $ nm -n built-in.a| grep set_brk > 00000000000000d4 t set_brk > 00000000000000d4 t set_brk > ~ $ > ~ $ nm -n built-in.a | grep set_brk -B100| egrep "set_brk|\.o:$" > fs/binfmt_elf.o: > 00000000000000d4 t set_brk > fs/compat_binfmt_elf.o: > 00000000000000d4 t set_brk > ``` > > These two symbols come from fs/binfmt_elf.o and fs/compat_binfmt_elf.o, and > they are just two symbols that happen to share the same name, as is common > in the kernel. > > at the same time, addr2line reports symbols to be generated from the same > file. > > ``` > ~ $ llvm-addr2line-14 -fe vmlinux ffff8000082f1d2c ffff8000082f4454 > set_brk > /home/alessandro/src/lka64/linux-6.4/fs/binfmt_elf.c:114 > set_brk > /home/alessandro/src/lka64/linux-6.4/fs/binfmt_elf.c:114 > ~ $ > ~ $ addr2line -fe vmlinux ffff8000082f1d2c ffff8000082f4454 > set_brk > /home/alessandro/src/lka64/linux-6.4/fs/binfmt_elf.c:114 > set_brk > /home/alessandro/src/lka64/linux-6.4/fs/binfmt_elf.c:114 > ``` > looking at the source code: > https://elixir.bootlin.com/linux/v6.4/source/fs/compat_binfmt_elf.c#L144 > the cause of this behavior, which is unexpected but correct. Thank you for the investigation, this an interesting reading! > The rationale is that using source file + line number iproduces better > kallsyms table, but it is still do not produce unique names. When I first read your cover letter, I also thought it would be cool to have the filename rather than a serial ID. So, your latest modification is really good as it goes into this direction. Regarding having non unique names, I am not sure if this is a problem. In my case, which is using kprobe to attach BPF code to trace some events, your contribution would make me on the way to know which address I should use because I could choose regarding the filename. I am curious about a potential v3 of this patch! > BR > Alessandro > > > As a final note, please understand that my patch was not intended to > > undermine anyone's work. I simply encountered a problem that I wanted to > > help solve. Attached to this message is my code, in case anyone wants to > > replicate it. I would appreciate being kept in the loop, as I genuinely > > want to assist in fixing this problem. > > > > BR > > Alessandro > > --- > > > > init/Kconfig | 36 ++++ > > scripts/Makefile | 4 + > > scripts/kas_alias/Makefile | 4 + > > scripts/kas_alias/a2l.c | 268 ++++++++++++++++++++++++++++ > > scripts/kas_alias/a2l.h | 32 ++++ > > scripts/kas_alias/duplicates_list.c | 70 ++++++++ > > scripts/kas_alias/duplicates_list.h | 15 ++ > > scripts/kas_alias/item_list.c | 230 ++++++++++++++++++++++++ > > scripts/kas_alias/item_list.h | 26 +++ > > scripts/kas_alias/kas_alias.c | 217 ++++++++++++++++++++++ > > scripts/link-vmlinux.sh | 11 +- > > 11 files changed, 910 insertions(+), 3 deletions(-) > > create mode 100644 scripts/kas_alias/Makefile > > create mode 100644 scripts/kas_alias/a2l.c > > create mode 100644 scripts/kas_alias/a2l.h > > create mode 100644 scripts/kas_alias/duplicates_list.c > > create mode 100644 scripts/kas_alias/duplicates_list.h > > create mode 100644 scripts/kas_alias/item_list.c > > create mode 100644 scripts/kas_alias/item_list.h > > create mode 100644 scripts/kas_alias/kas_alias.c > > > > diff --git a/init/Kconfig b/init/Kconfig > > index f7f65af4ee12..bc69fcd9cbc8 100644 > > --- a/init/Kconfig > > +++ b/init/Kconfig > > @@ -1737,6 +1737,42 @@ config KALLSYMS_BASE_RELATIVE > > > > time constants, and no relocation pass is required at runtime to > > fix > > up the entries based on the runtime load address of the kernel. > > > > +config KALLSYMS_ALIAS > > + bool "Produces alias for duplicated symbols" if EXPERT > > + depends on KALLSYMS && (DEBUG_INFO_DWARF4 || DEBUG_INFO_DWARF5) > > + help > > + It is not uncommon for drivers or modules related to similar > > + peripherals to have symbols with the exact same name. > > + While this is not a problem for the kernel's binary itself, it > > + becomes an issue when attempting to trace or probe specific > > + functions using infrastructure like ftrace or kprobe. > > + > > + This option addresses this challenge by extending the symbol > > names + with unique suffixes during the kernel build process. > > + The newly created aliases for these duplicated symbols are > > unique > > + names that can be fed to the ftrace sysfs interface. By doing > > so, it + enables previously unreachable symbols to be probed. > > + > > +config CONFIG_KALLSYMS_ALIAS_DATA > > + bool "Produces alias also for data" > > + depends on KALLSYMS_ALIAS > > + help > > + Sometimes it can be useful to refer to data. In live patch > > scenarios, + you may find yourself needing to use symbols that > > are shared with + other functions. Since symbols face the same > > issue as functions, this + option allows you to create aliases > > for data as well. > > + > > +config CONFIG_KALLSYMS_ALIAS_DATA_ALL > > + bool "Removes all filter when producing data alias" > > + depends on CONFIG_KALLSYMS_ALIAS_DATA > > + help > > + When selecting data aliases, not all symbols are included in the > > set + This is because many symbols are unlikely to be used. If > > you choose + to have an alias for all data symbols, be aware that > > it will + significantly increase the size. > > + > > + If unsure, say N. > > + > > > > # end of the "standard kernel features (expert users)" menu > > > > # syscall, maps, verifier > > > > diff --git a/scripts/Makefile b/scripts/Makefile > > index 32b6ba722728..65fafe17cfe5 100644 > > --- a/scripts/Makefile > > +++ b/scripts/Makefile > > @@ -49,3 +49,7 @@ subdir-$(CONFIG_SECURITY_SELINUX) += selinux > > > > # Let clean descend into subdirs > > subdir- += basic dtc gdb kconfig mod > > > > + > > +# KALLSyms alias > > +subdir-$(CONFIG_KALLSYMS_ALIAS) += kas_alias > > + > > diff --git a/scripts/kas_alias/Makefile b/scripts/kas_alias/Makefile > > new file mode 100644 > > index 000000000000..e1fde69232b4 > > --- /dev/null > > +++ b/scripts/kas_alias/Makefile > > @@ -0,0 +1,4 @@ > > +# SPDX-License-Identifier: GPL-2.0 > > +hostprogs-always-$(CONFIG_KALLSYMS_ALIAS) += kas_alias > > + > > +kas_alias-objs := duplicates_list.o item_list.o kas_alias.o a2l.o > > diff --git a/scripts/kas_alias/a2l.c b/scripts/kas_alias/a2l.c > > new file mode 100644 > > index 000000000000..a9692ac30180 > > --- /dev/null > > +++ b/scripts/kas_alias/a2l.c > > @@ -0,0 +1,268 @@ > > +// SPDX-License-Identifier: GPL-2.0-or-later > > +#include <stdio.h> > > +#include <stdlib.h> > > +#include <string.h> > > +#include <unistd.h> > > +#include <sys/types.h> > > +#include <sys/wait.h> > > +#include <string.h> > > +#include <stdint.h> > > +#include <stdbool.h> > > + > > +#include "a2l.h" > > + > > +int addr2line_pid = -1; > > +int a2l_in[2]; > > +int a2l_out[2]; > > +char line[MAX_BUF]; > > +char vmlinux_path[MAX_BUF]; > > +char addr2line_cmd[MAX_CMD_LEN]; > > +FILE *a2l_stdin, *a2l_stdout; > > + > > +static char *normalize_path(const char *input_path, char *output_path) > > +{ > > + char *prev_token = NULL; > > + char *delimiter = "/"; > > + char inbuf[MAX_BUF]; > > + char *token; > > + char *pos; > > + > > + memset(inbuf, 0, MAX_BUF); > > + *output_path = '\0'; > > + strncpy(inbuf, input_path, MAX_BUF); > > + if (!input_path || !output_path || strlen(input_path) == 0) > > + return NULL; > > + > > + token = strtok(inbuf, delimiter); > > + while (token) { > > + if (strcmp(token, "..") == 0 && prev_token) { > > + pos = strrchr(output_path, '/'); > > + if (pos) > > + *pos = '\0'; > > + > > + } else if (strcmp(token, ".") != 0) { > > + strcat(output_path, "/"); > > + strcat(output_path, token); > > + } > > + > > + prev_token = token; > > + token = strtok(NULL, delimiter); > > + } > > + > > + return output_path; > > +} > > + > > +static void path_of(const char *full_path, char *path) > > +{ > > + const char *last_slash = strrchr(full_path, '/'); > > + size_t path_length; > > + char cwd[MAX_BUF]; > > + > > + if (!last_slash) { > > + if (getcwd(cwd, sizeof(cwd))) > > + strcpy(path, cwd); > > + else > > + strcpy(path, "."); > > + } else { > > + path_length = last_slash - full_path; > > + strncpy(path, full_path, path_length); > > + path[path_length] = '\0'; > > + } > > +} > > + > > +static bool file_exists(const char *file_path) > > +{ > > + FILE *file; > > + > > + file = fopen(file_path, "r"); > > + if (file) { > > + fclose(file); > > + return true; > > + } > > + return false; > > +} > > + > > +int addr2line_init(const char *cmd, const char *vmlinux) > > +{ > > + if ((!file_exists(cmd)) || (!file_exists(vmlinux))) { > > + printf("file not found\n"); > > + return 0; > > + } > > + > > + path_of(vmlinux, vmlinux_path); > > + if (pipe(a2l_in) == -1) { > > + printf("Failed to create pipe\n"); > > + return 0; > > + } > > + > > + if (pipe(a2l_out) == -1) { > > + printf("Failed to create pipe\n"); > > + return 0; > > + } > > + > > + addr2line_pid = fork(); > > + if (addr2line_pid == -1) { > > + printf("Failed to fork process\n"); > > + close(a2l_in[P_READ]); > > + close(a2l_in[P_WRITE]); > > + close(a2l_out[P_READ]); > > + close(a2l_out[P_WRITE]); > > + return 0; > > + } > > + > > + if (addr2line_pid == 0) { > > + dup2(a2l_in[P_READ], 0); > > + dup2(a2l_out[P_WRITE], 1); > > + close(a2l_in[P_WRITE]); > > + close(a2l_out[P_READ]); > > + > > + execlp(cmd, cmd, ADDR2LINE_ARGS, vmlinux, NULL); > > + > > + printf("Failed to execute addr2line command\n"); > > + exit(1); > > + } else { > > + close(a2l_in[P_READ]); > > + close(a2l_out[P_WRITE]); > > + } > > + > > + a2l_stdin = fdopen(a2l_in[P_WRITE], "w"); > > + if (!a2l_stdin) { > > + printf("Failed to open pipe a2l_in\n"); > > + return 0; > > + } > > + > > + a2l_stdout = fdopen(a2l_out[P_READ], "r"); > > + if (!a2l_stdout) { > > + printf("Failed to open pipe a2l_out\n"); > > + fclose(a2l_stdin); > > + return 0; > > + } > > + > > + return 1; > > +} > > + > > +const char *remove_subdir(const char *home, const char *f_path) > > +{ > > + int i = 0; > > + > > + while (*(home + i) == *(f_path + i)) > > + i++; > > + > > + return (strlen(home) != i) ? NULL : f_path + i; > > +} > > + > > +char *addr2line_get_lines(uint64_t address) > > +{ > > + char buf[MAX_BUF]; > > + > > + fprintf(a2l_stdin, "%08lx\n", address); > > + fflush(a2l_stdin); > > + > > + if (!fgets(line, sizeof(line), a2l_stdout)) { > > + printf("Failed to read lines from addr2line\n"); > > + return NULL; > > + } > > + > > + if (!fgets(line, sizeof(line), a2l_stdout)) { > > + printf("Failed to read lines from addr2line\n"); > > + return NULL; > > + } > > + > > + line[strcspn(line, "\n")] = '\0'; > > + strncpy(buf, line, MAX_BUF); > > + return normalize_path(buf, line); > > +} > > + > > +int addr2line_cleanup(void) > > +{ > > + int status; > > + > > + if (addr2line_pid != -1) { > > + kill(addr2line_pid, SIGKILL); > > + waitpid(addr2line_pid, &status, 0); > > + fclose(a2l_stdin); > > + fclose(a2l_stdout); > > + addr2line_pid = -1; > > + } > > + > > + return 1; > > +} > > + > > +static char *find_executable(const char *command) > > +{ > > + char *path_env = getenv("PATH"); > > + char *executable_path; > > + char *path_copy; > > + char *path; > > + int n; > > + > > + if (!path_env) > > + return NULL; > > + > > + path_copy = strdup(path_env); > > + if (!path_copy) > > + return NULL; > > + > > + path = strtok(path_copy, ":"); > > + while (path) { > > + n = snprintf(0, 0, "%s/%s", path, command); > > + executable_path = (char *)malloc(n + 1); > > + snprintf(executable_path, n + 1, "%s/%s", path, command); > > + if (access(executable_path, X_OK) == 0) { > > + free(path_copy); > > + return executable_path; > > + } > > + > > + path = strtok(NULL, ":"); > > + free(executable_path); > > + executable_path = NULL; > > + } > > + > > + free(path_copy); > > + if (executable_path) > > + free(executable_path); > > + return NULL; > > +} > > + > > +const char *get_addr2line(int mode) > > +{ > > + char *buf = ""; > > + > > + switch (mode) { > > + case A2L_CROSS: > > + buf = getenv("CROSS_COMPILE"); > > + memcpy(addr2line_cmd, buf, strlen(buf)); > > + case A2L_DEFAULT: > > + memcpy(addr2line_cmd + strlen(buf), ADDR2LINE, > > strlen(ADDR2LINE)); + buf = find_executable(addr2line_cmd); > > + if (buf) { > > + memcpy(addr2line_cmd, buf, strlen(buf)); > > + free(buf); > > + } > > + return addr2line_cmd; > > + case A2L_LLVM: > > + default: > > + return NULL; > > + } > > +} > > + > > +char *get_vmlinux(char *input) > > +{ > > + const char *match_string1 = ".syms"; > > + const char *match_string2 = ".tmp_vmlinux.kallsyms"; > > + char *result = NULL; > > + char *match_pos; > > + > > + match_pos = strstr(input, match_string1); > > + if (!match_pos) > > + return NULL; > > + > > + match_pos = strstr(input, match_string2); > > + if (!match_pos) > > + return NULL; > > + > > + result = strdup(input); > > + match_pos = strstr(result, match_string1); > > + *match_pos = '\0'; > > + return result; > > +} > > diff --git a/scripts/kas_alias/a2l.h b/scripts/kas_alias/a2l.h > > new file mode 100644 > > index 000000000000..ca6419229dde > > --- /dev/null > > +++ b/scripts/kas_alias/a2l.h > > @@ -0,0 +1,32 @@ > > +/* SPDX-License-Identifier: GPL-2.0-or-later */ > > +#ifndef A2L_H > > +#define A2L_H > > +#include <stdint.h> > > + > > +#define ADDR2LINE "addr2line" > > +#define ADDR2LINE_ARGS "-fe" > > +//#define VMLINUX "vmlinux" > > +#define MAX_BUF 4096 > > +#define MAX_CMD_LEN 256 > > +#define P_READ 0 > > +#define P_WRITE 1 > > +#define A2L_DEFAULT 1 > > +#define A2L_CROSS 2 > > +#define A2L_LLVM 3 > > +#define A2L_MAKE_VALUE 2 > > + > > +extern int addr2line_pid; > > +extern int a2l_in[2]; > > +extern int a2l_out[2]; > > +extern char line[MAX_BUF]; > > +extern char vmlinux_path[MAX_BUF]; > > +extern char addr2line_cmd[MAX_CMD_LEN]; > > + > > +int addr2line_init(const char *cmd, const char *vmlinux); > > +char *addr2line_get_lines(uint64_t address); > > +int addr2line_cleanup(void); > > +const char *remove_subdir(const char *home, const char *f_path); > > +const char *get_addr2line(int mode); > > +char *get_vmlinux(char *input); > > + > > +#endif > > diff --git a/scripts/kas_alias/duplicates_list.c > > b/scripts/kas_alias/duplicates_list.c new file mode 100644 > > index 000000000000..e7a3d2917937 > > --- /dev/null > > +++ b/scripts/kas_alias/duplicates_list.c > > @@ -0,0 +1,70 @@ > > +// SPDX-License-Identifier: GPL-2.0-or-later > > +#include <stdint.h> > > +#include <stdio.h> > > +#include <string.h> > > +#include <stdlib.h> > > +#include <stdbool.h> > > + > > +#include "item_list.h" > > +#include "duplicates_list.h" > > + > > +struct duplicate_item *find_duplicates(struct item *list) > > +{ > > + struct duplicate_item *current_duplicate = NULL; > > + struct duplicate_item *duplicates = NULL; > > + struct duplicate_item *new_duplicate; > > + struct item *current_item = list; > > + bool prev_was_duplicate = false; > > + struct item *prev_item = NULL; > > + > > + while (current_item) { > > + if ((prev_item && (strcmp(current_item->symb_name, > > prev_item->symb_name) == 0)) || + prev_was_duplicate) { > > + if (!duplicates) { > > + duplicates = malloc(sizeof(struct > > duplicate_item)); + if (!duplicates) > > + return NULL; > > + > > + duplicates->original_item = prev_item; > > + duplicates->next = NULL; > > + current_duplicate = duplicates; > > + } else { > > + new_duplicate = malloc(sizeof(struct > > duplicate_item)); + if (!new_duplicate) { > > + free_duplicates(&duplicates); > > + return NULL; > > + } > > + > > + new_duplicate->original_item = prev_item; > > + new_duplicate->next = NULL; > > + current_duplicate->next = new_duplicate; > > + current_duplicate = new_duplicate; > > + > > + if ((strcmp(current_item->symb_name, > > prev_item->symb_name) != 0) && + > > (prev_was_duplicate)) > > + prev_was_duplicate = false; > > + else > > + prev_was_duplicate = true; > > + } > > + } > > + > > + prev_item = current_item; > > + current_item = current_item->next; > > + } > > + > > + return duplicates; > > +} > > + > > +void free_duplicates(struct duplicate_item **duplicates) > > +{ > > + struct duplicate_item *duplicates_iterator = *duplicates; > > + struct duplicate_item *app; > > + > > + while (duplicates_iterator) { > > + app = duplicates_iterator; > > + duplicates_iterator = duplicates_iterator->next; > > + free(app); > > + } > > + > > + *duplicates = NULL; > > +} > > diff --git a/scripts/kas_alias/duplicates_list.h > > b/scripts/kas_alias/duplicates_list.h new file mode 100644 > > index 000000000000..76aa73e584bc > > --- /dev/null > > +++ b/scripts/kas_alias/duplicates_list.h > > @@ -0,0 +1,15 @@ > > +/* SPDX-License-Identifier: GPL-2.0-or-later */ > > +#ifndef DUPLICATES_LIST_H > > +#define DUPLICATES_LIST_H > > + > > +#include "item_list.h" > > + > > +struct duplicate_item { > > + struct item *original_item; > > + struct duplicate_item *next; > > +}; > > + > > +struct duplicate_item *find_duplicates(struct item *list); > > +void free_duplicates(struct duplicate_item **duplicates); > > + > > +#endif > > diff --git a/scripts/kas_alias/item_list.c b/scripts/kas_alias/item_list.c > > new file mode 100644 > > index 000000000000..48f2e525592a > > --- /dev/null > > +++ b/scripts/kas_alias/item_list.c > > @@ -0,0 +1,230 @@ > > +// SPDX-License-Identifier: GPL-2.0-or-later > > +#include <stdio.h> > > +#include <stdlib.h> > > +#include <stdint.h> > > +#include <string.h> > > +#include <stdbool.h> > > +#include <assert.h> > > +#include "item_list.h" > > + > > +#define CHECK_ORDER_BY_ADDRESS(sort_by, current, temp, op) \ > > + ((sort_by) == BY_ADDRESS && (current)->addr op (temp)->addr) > > +#define CHECK_ORDER_BY_NAME(sort_by, current, temp, op) \ > > + ((sort_by) == BY_NAME && strcmp((current)->symb_name, > > (temp)->symb_name) op 0) + > > +struct item *list_index[96] = {0}; > > + > > +void build_index(struct item *list) > > +{ > > + char current_first_letter = ' '; > > + struct item *current = list; > > + > > + while (current) { > > + if (current->symb_name[0] != current_first_letter) { > > + current_first_letter = current->symb_name[0]; > > + list_index[current_first_letter - 32] = current; > > + } > > + current = current->next; > > + } > > +} > > + > > +struct item *add_item(struct item **list, const char *name, char stype, > > uint64_t addr) +{ > > + struct item *new_item; > > + struct item *current; > > + > > + new_item = malloc(sizeof(struct item)); > > + if (!new_item) > > + return NULL; > > + > > + strncpy(new_item->symb_name, name, MAX_NAME_SIZE); > > + new_item->symb_name[MAX_NAME_SIZE - 1] = '\0'; > > + new_item->addr = addr; > > + new_item->stype = stype; > > + new_item->next = NULL; > > + > > + if (!(*list)) { > > + *list = new_item; > > + } else { > > + current = *list; > > + while (current->next) > > + current = current->next; > > + > > + current->next = new_item; > > + } > > + return new_item; > > +} > > + > > +void sort_list(struct item **list, int sort_by) > > +{ > > + struct item *current = *list; > > + struct item *sorted = NULL; > > + struct item *next_item; > > + struct item *temp; > > + > > + if (!(*list) || !((*list)->next)) > > + return; > > + > > + while (current) { > > + next_item = current->next; > > + if (!sorted || > > + (CHECK_ORDER_BY_ADDRESS(sort_by, current, sorted, <) > > || > > + CHECK_ORDER_BY_NAME(sort_by, current, sorted, >=))) { > > + current->next = sorted; > > + sorted = current; > > + } else { > > + temp = sorted; > > + while (temp->next && > > + (CHECK_ORDER_BY_ADDRESS(sort_by, current, > > temp->next, >=) || + > > CHECK_ORDER_BY_NAME(sort_by, current, temp->next, >=))) + > > temp = temp->next; > > + > > + current->next = temp->next; > > + temp->next = current; > > + } > > + current = next_item; > > + } > > + > > + *list = sorted; > > +} > > + > > +struct item *merge(struct item *left, struct item *right, int sort_by) > > +{ > > + struct item *current = NULL; > > + struct item *result = NULL; > > + > > + if (!left) > > + return right; > > + if (!right) > > + return left; > > + > > + if (sort_by == BY_NAME) { > > + if (strcmp(left->symb_name, right->symb_name) <= 0) { > > + result = left; > > + left = left->next; > > + } else { > > + result = right; > > + right = right->next; > > + } > > + } else { > > + if (sort_by == BY_ADDRESS) { > > + if (left->addr <= right->addr) { > > + result = left; > > + left = left->next; > > + } else { > > + result = right; > > + right = right->next; > > + } > > + } > > + } > > + > > + current = result; > > + > > + while (left && right) { > > + if (sort_by == BY_NAME) { > > + if (strcmp(left->symb_name, right->symb_name) <= > > 0) { + current->next = left; > > + left = left->next; > > + } else { > > + current->next = right; > > + right = right->next; > > + } > > + } else { > > + if (sort_by == BY_ADDRESS) { > > + if (left->addr <= right->addr) { > > + current->next = left; > > + left = left->next; > > + } else { > > + current->next = right; > > + right = right->next; > > + } > > + } > > + } > > + > > + current = current->next; > > + } > > + > > + if (left) { > > + current->next = left; > > + } else { > > + if (right) > > + current->next = right; > > + } > > + > > + return result; > > +} > > + > > +struct item *merge_sort(struct item *head, int sort_by) > > +{ > > + struct item *right; > > + struct item *slow; > > + struct item *fast; > > + struct item *left; > > + > > + if (!head || !head->next) > > + return head; > > + > > + slow = head; > > + fast = head->next; > > + > > + while (fast && fast->next) { > > + slow = slow->next; > > + fast = fast->next->next; > > + } > > + > > + left = head; > > + right = slow->next; > > + slow->next = NULL; > > + > > + left = merge_sort(left, sort_by); > > + right = merge_sort(right, sort_by); > > + > > + return merge(left, right, sort_by); > > +} > > + > > +void sort_list_m(struct item **head, int sort_by) > > +{ > > + if (!(*head) || !((*head)->next)) > > + return; > > + > > + *head = merge_sort(*head, sort_by); > > +} > > + > > +int insert_after(struct item *list, const uint64_t search_addr, > > + const char *name, uint64_t addr, char stype) > > +{ > > + struct item *new_item; > > + struct item *current; > > + int ret = 0; > > + > > + current = (list_index[name[0] - 32]) ? list_index[name[0] - 32] : > > list; + while (current) { > > + if (current->addr == search_addr) { > > + new_item = malloc(sizeof(struct item)); > > + if (!new_item) > > + return ret; > > + strncpy(new_item->symb_name, name, MAX_NAME_SIZE); > > + new_item->symb_name[MAX_NAME_SIZE - 1] = '\0'; > > + new_item->addr = addr; > > + new_item->stype = stype; > > + new_item->next = current->next; > > + current->next = new_item; > > + ret = 1; > > + break; > > + } > > + current = current->next; > > + } > > + return ret; > > +} > > + > > +void free_items(struct item **head) > > +{ > > + struct item *app, *item_iterator = *head; > > + > > + while (item_iterator) { > > + app = item_iterator; > > + item_iterator = item_iterator->next; > > + free(app); > > + } > > + *head = NULL; > > +} > > diff --git a/scripts/kas_alias/item_list.h b/scripts/kas_alias/item_list.h > > new file mode 100644 > > index 000000000000..b4891cb088ee > > --- /dev/null > > +++ b/scripts/kas_alias/item_list.h > > @@ -0,0 +1,26 @@ > > +/* SPDX-License-Identifier: GPL-2.0-or-later */ > > +#ifndef ITEM_LIST_H > > +#define ITEM_LIST_H > > +#include <stdint.h> > > + > > +#define MAX_NAME_SIZE 256 > > +#define BY_ADDRESS 1 > > +#define BY_NAME 2 > > + > > +struct item { > > + char symb_name[MAX_NAME_SIZE]; > > + uint64_t addr; > > + char stype; > > + struct item *next; > > +}; > > + > > +void build_index(struct item *list); > > +struct item *add_item(struct item **list, const char *name, char stype, > > uint64_t addr); +void sort_list(struct item **list, int sort_by); > > +struct item *merge(struct item *left, struct item *right, int sort_by); > > +struct item *merge_sort(struct item *head, int sort_by); > > +void sort_list_m(struct item **head, int sort_by); > > +int insert_after(struct item *list, const uint64_t search_addr, > > + const char *name, uint64_t addr, char stype); > > +void free_items(struct item **head); > > +#endif > > diff --git a/scripts/kas_alias/kas_alias.c b/scripts/kas_alias/kas_alias.c > > new file mode 100644 > > index 000000000000..532aeb39f851 > > --- /dev/null > > +++ b/scripts/kas_alias/kas_alias.c > > @@ -0,0 +1,217 @@ > > +// SPDX-License-Identifier: GPL-2.0-or-later > > +#include <stdio.h> > > +#include <stdlib.h> > > +#include <stdint.h> > > +#include <unistd.h> > > +#include <string.h> > > +#include <stdbool.h> > > +#include <stdarg.h> > > +#include <regex.h> > > + > > +#include "item_list.h" > > +#include "duplicates_list.h" > > +#include "a2l.h" > > + > > +#define SYMB_IS_TEXT(s) ((((s)->stype) == 't') || (((s)->stype) == 'T')) > > +#define SYMB_IS_DATA(s) ((((s)->stype) == 'b') || (((s)->stype) == 'B') > > || \ + (((s)->stype) == 'd') || (((s)->stype) == > > 'D') || \ + (((s)->stype) == 'r') || > > (((s)->stype) == 'R')) +#ifdef CONFIG_KALLSYMS_ALIAS_DATA > > +#define SYMB_NEEDS_ALIAS(s) (SYMB_IS_TEXT(s) || SYMB_IS_DATA(s)) > > +#else > > +#define SYMB_NEEDS_ALIAS(s) SYMB_IS_TEXT(s) > > +#endif > > +#define FNOMATCH 0 > > +#define FMATCH 1 > > +#define EREGEX 2 > > + > > +const char *ignore_regex[] = { > > + "^__cfi_.*$", // __cfi_ preamble > > +#ifndef CONFIG_KALLSYMS_ALIAS_DATA_ALL > > + "^_*TRACE_SYSTEM.*$", > > + "^__already_done\\.[0-9]+$", // Call a function once > > data + "^___tp_str\\.[0-9]+$", > > + "^___done\\.[0-9]+$", > > + "^__print_once\\.[0-9]+$", > > + "^_rs\\.[0-9]+$", > > + "^__compound_literal\\.[0-9]+$", > > + "^___once_key\\.[0-9]+$", > > + "^__func__\\.[0-9]+$", > > + "^__msg\\.[0-9]+$", > > + "^CSWTCH\\.[0-9]+$", > > + "^__flags\\.[0-9]+$", > > + "^__wkey.*$", > > + "^__mkey.*$", > > + "^__key.*$", > > +#endif > > + "^__pfx_.*$" // NOP-padding > > +}; > > + > > +int suffix_serial; > > + > > +static inline void verbose_msg(bool verbose, const char *fmt, ...) > > +{ > > + va_list args; > > + > > + va_start(args, fmt); > > + if (verbose) > > + printf(fmt, args); > > + > > + va_end(args); > > +} > > + > > +static void create_suffix(const char *name, char *output_suffix) > > +{ > > + sprintf(output_suffix, "%s__alias__%d", name, suffix_serial++); > > +} > > + > > +static void create_file_suffix(const char *name, uint64_t address, char > > *output_suffix, char *cwd) +{ > > + const char *f_path; > > + char *buf; > > + int i = 0; > > + > > + buf = addr2line_get_lines(address); > > + f_path = remove_subdir(cwd, buf); > > + if (f_path) { > > + sprintf(output_suffix, "%s@%s", name, f_path); > > + while (*(output_suffix + i) != '\0') { > > + switch (*(output_suffix + i)) { > > + case '/': > > + case ':': > > + case '.': > > + *(output_suffix + i) = '_'; > > + break; > > + default: > > + } > > + i++; > > + } > > + } else { > > + create_suffix(name, output_suffix); > > + } > > +} > > + > > +static int filter_symbols(char *symbol, const char **ignore_list, int > > regex_no) +{ > > + regex_t regex; > > + int res, i; > > + > > + for (i = 0; i < regex_no; i++) { > > + res = regcomp(®ex, ignore_list[i], REG_EXTENDED); > > + if (res) > > + return -EREGEX; > > + > > + res = regexec(®ex, symbol, 0, NULL, 0); > > + regfree(®ex); > > + switch (res) { > > + case 0: > > + return FMATCH; > > + case REG_NOMATCH: > > + break; > > + default: > > + return -EREGEX; > > + } > > + } > > + > > + return FNOMATCH; > > +} > > + > > +int main(int argc, char *argv[]) > > +{ > > + char t, sym_name[MAX_NAME_SIZE], new_name[MAX_NAME_SIZE + 15]; > > + struct duplicate_item *duplicate_iterator; > > + struct duplicate_item *duplicate; > > + struct item *head = {NULL}; > > + bool need_2_process = true; > > + struct item *last = {NULL}; > > + struct item *current; > > + int verbose_mode = 0; > > + uint64_t address; > > + FILE *fp; > > + int res; > > + > > + if (argc < 2 || argc > 3) { > > + printf("Usage: %s <nmfile> [-verbose]\n", argv[0]); > > + return 1; > > + } > > + > > + if (argc == 3 && strcmp(argv[2], "-verbose") == 0) > > + verbose_mode = 1; > > + > > + verbose_msg(verbose_mode, "Scanning nm data(%s)\n", argv[1]); > > + > > + fp = fopen(argv[1], "r"); > > + if (!fp) { > > + printf("Can't open input file.\n"); > > + return 1; > > + } > > + > > + if (!addr2line_init(get_addr2line(A2L_DEFAULT), > > get_vmlinux(argv[1]))) + return 1; > > + > > + while (fscanf(fp, "%lx %c %99s\n", &address, &t, sym_name) == 3) { > > + if (strstr(sym_name, "@_")) { > > + if (verbose_mode && need_2_process) > > + printf("Already processed\n"); > > + need_2_process = false; > > + } > > + last = add_item(&last, sym_name, t, address); > > + if (!last) { > > + printf("Error in allocate memory\n"); > > + free_items(&head); > > + return 1; > > + } > > + > > + if (!head) > > + head = last; > > + } > > + > > + fclose(fp); > > + > > + if (need_2_process) { > > + verbose_msg(verbose_mode, "Sorting nm data\n"); > > + sort_list_m(&head, BY_NAME); > > + verbose_msg(verbose_mode, "Scanning nm data for > > duplicates\n"); + duplicate = find_duplicates(head); > > + if (!duplicate) { > > + printf("Error in duplicates list\n"); > > + return 1; > > + } > > + > > + verbose_msg(verbose_mode, "Applying suffixes\n"); > > + build_index(head); > > + duplicate_iterator = duplicate; > > + while (duplicate_iterator) { > > + res = > > filter_symbols(duplicate_iterator->original_item->symb_name, + > > ignore_regex, sizeof(ignore_regex) / + > > sizeof(ignore_regex[0])); + > > if (res != FMATCH && > > + > > SYMB_NEEDS_ALIAS(duplicate_iterator->original_item)) { + > > if (res < 0) > > + return 1; > > + > > + > > create_file_suffix(duplicate_iterator->original_item->symb_name, + > > > > duplicate_iterator->original_item->addr, + > > new_name, vmlinux_path); + > > if (!insert_after(head, duplicate_iterator->original_item->addr, + > > new_name, > > duplicate_iterator->original_item->addr, + > > duplicate_iterator->original_item->stype)) + > > return 1; > > + } > > + > > + duplicate_iterator = duplicate_iterator->next; > > + } > > + > > + sort_list_m(&head, BY_ADDRESS); > > + } > > + current = head; > > + while (current) { > > + printf("%08lx %c %s\n", current->addr, current->stype, > > current->symb_name); + current = current->next; > > + } > > + > > + free_items(&head); > > + free_duplicates(&duplicate); > > + addr2line_cleanup(); > > + return 0; > > +} > > diff --git a/scripts/link-vmlinux.sh b/scripts/link-vmlinux.sh > > index a432b171be82..cacf60b597ce 100755 > > --- a/scripts/link-vmlinux.sh > > +++ b/scripts/link-vmlinux.sh > > @@ -89,8 +89,9 @@ vmlinux_link() > > > > ldflags="${ldflags} ${wl}--script=${objtree}/${KBUILD_LDS}" > > > > - # The kallsyms linking does not need debug symbols included. > > - if [ "$output" != "${output#.tmp_vmlinux.kallsyms}" ] ; then > > + # The kallsyms linking does not need debug symbols included, > > unless the KALLSYMS_ALIAS. + if [ ! is_enabled > > CONFIG_KALLSYMS_ALIAS ] && \ > > + [ "$output" != "${output#.tmp_vmlinux.kallsyms}" ] ; then > > > > ldflags="${ldflags} ${wl}--strip-debug" > > > > fi > > > > @@ -161,7 +162,11 @@ kallsyms() > > > > fi > > > > info KSYMS ${2} > > > > - scripts/kallsyms ${kallsymopt} ${1} > ${2} > > + if is_enabled CONFIG_KALLSYMS_ALIAS; then > > + ALIAS=".alias" > > + scripts/kas_alias/kas_alias ${1} >${1}${ALIAS} > > + fi > > + scripts/kallsyms ${kallsymopt} ${1}${ALIAS} > ${2} > > > > } > > > > # Perform one step in kallsyms generation, including temporary linking of > > > > -- > > 2.34.1 Best regards.