All of lore.kernel.org
 help / color / mirror / Atom feed
From: Francis Laniel <flaniel@linux.microsoft.com>
To: Steven Rostedt <rostedt@goodmis.org>,
	Alexander Lobakin <aleksander.lobakin@intel.com>,
	Nick Alcock <nick.alcock@oracle.com>,
	Alessandro Carminati <alessandro.carminati@gmail.com>
Cc: Masahiro Yamada <masahiroy@kernel.org>,
	Nathan Chancellor <nathan@kernel.org>,
	Nick Desaulniers <ndesaulniers@google.com>,
	Nicolas Schier <nicolas@fjasle.eu>,
	Masami Hiramatsu <mhiramat@kernel.org>,
	Daniel Bristot de Oliveira <bristot@kernel.org>,
	Viktor Malik <vmalik@redhat.com>,
	Kris Van Hees <kris.van.hees@oracle.com>,
	Luis Chamberlain <mcgrof@kernel.org>,
	eugene.loh@oracle.com, Josh Poimboeuf <jpoimboe@kernel.org>,
	linux-kernel@vger.kernel.org, linux-kbuild@vger.kernel.org,
	live-patching@vger.kernel.org,
	linux-trace-kernel@vger.kernel.org
Subject: Re: [PATCH v2] scripts/link-vmlinux.sh: Add alias to duplicate symbols for kallsyms
Date: Thu, 24 Aug 2023 17:35:43 +0200	[thread overview]
Message-ID: <1862253.tdWV9SEqCh@pwmachine> (raw)
In-Reply-To: <CAPp5cGRBW6WDm9ku3nsr0x=rhEOGAUx==BctCo+DJ+498Tz2Sw@mail.gmail.com>

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@gmail.com> 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(&regex, ignore_list[i], REG_EXTENDED);
> > +               if (res)
> > +                       return -EREGEX;
> > +
> > +               res = regexec(&regex, symbol, 0, NULL, 0);
> > +               regfree(&regex);
> > +               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.



  parent reply	other threads:[~2023-08-24 15:36 UTC|newest]

Thread overview: 19+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2023-07-14 15:03 [PATCH v2] scripts/link-vmlinux.sh: Add alias to duplicate symbols for kallsyms Alessandro Carminati
2023-07-17 14:52 ` Steven Rostedt
2023-07-17 16:50   ` Luis Chamberlain
2023-07-18  1:01     ` Masami Hiramatsu
2023-07-18 16:06   ` Alessandro Carminati
2023-07-18 16:55     ` Steven Rostedt
2023-07-21  9:21       ` Alessandro Carminati
2023-07-21 12:40         ` Alessandro Carminati
2023-07-24 10:30           ` Alexander Lobakin
2023-08-24 15:35           ` Francis Laniel [this message]
2023-08-25 10:15             ` Alessandro Carminati
2023-08-25 12:31               ` Masami Hiramatsu
2023-07-19 16:08     ` Masami Hiramatsu
2023-07-19 11:12   ` Nick Alcock
2023-07-19 15:12     ` Alexander Lobakin
2023-07-20 13:00       ` Nick Alcock
2023-07-20 17:00         ` Alexander Lobakin
2023-07-21  1:09         ` Masami Hiramatsu
2023-07-21  1:39           ` Kris Van Hees

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=1862253.tdWV9SEqCh@pwmachine \
    --to=flaniel@linux.microsoft.com \
    --cc=aleksander.lobakin@intel.com \
    --cc=alessandro.carminati@gmail.com \
    --cc=bristot@kernel.org \
    --cc=eugene.loh@oracle.com \
    --cc=jpoimboe@kernel.org \
    --cc=kris.van.hees@oracle.com \
    --cc=linux-kbuild@vger.kernel.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=linux-trace-kernel@vger.kernel.org \
    --cc=live-patching@vger.kernel.org \
    --cc=masahiroy@kernel.org \
    --cc=mcgrof@kernel.org \
    --cc=mhiramat@kernel.org \
    --cc=nathan@kernel.org \
    --cc=ndesaulniers@google.com \
    --cc=nick.alcock@oracle.com \
    --cc=nicolas@fjasle.eu \
    --cc=rostedt@goodmis.org \
    --cc=vmalik@redhat.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.