This is an automated email from the ASF dual-hosted git repository.

wusheng pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/skywalking-rover.git


The following commit(s) were added to refs/heads/main by this push:
     new 2331dbe  Support monitoring ztunnel to adapt istio ambient mode (#142)
2331dbe is described below

commit 2331dbe091343b9ebb2c74a8c6500af80274fb07
Author: mrproliu <[email protected]>
AuthorDate: Sat Sep 14 15:09:51 2024 +0800

    Support monitoring ztunnel to adapt istio ambient mode (#142)
---
 CHANGES.md                                         |   1 +
 bpf/accesslog/accesslog.c                          |   5 +-
 bpf/accesslog/ambient/ztunnel.c                    |  52 ++++++
 bpf/accesslog/ambient/ztunnel.h                    |  39 ++++
 go.mod                                             |   2 +-
 go.sum                                             |   4 +-
 pkg/accesslog/collector/collector.go               |   4 +
 pkg/accesslog/collector/ztunnel.go                 | 200 +++++++++++++++++++++
 pkg/accesslog/common/connection.go                 |  20 +++
 .../{collector/collector.go => events/ztunnel.go}  |  27 +--
 pkg/tools/elf/elf.go                               |  23 ++-
 scripts/build/bash/btfgen.sh                       |   2 +-
 12 files changed, 350 insertions(+), 29 deletions(-)

diff --git a/CHANGES.md b/CHANGES.md
index 320d3f9..0e1c187 100644
--- a/CHANGES.md
+++ b/CHANGES.md
@@ -10,6 +10,7 @@ Release Notes.
 * Add `pprof` module for observe self.
 * Add detect process from `CRI-O` container in Kubernetes.
 * Introduce `MonitorFilter` into access log module. 
+* Support monitoring ztunnel to adapt istio ambient mode.
 
 #### Bug Fixes
 * Fixed the issue where `conntrack` could not find the Reply IP in the access 
log module.
diff --git a/bpf/accesslog/accesslog.c b/bpf/accesslog/accesslog.c
index 87b62dd..a9e1088 100644
--- a/bpf/accesslog/accesslog.c
+++ b/bpf/accesslog/accesslog.c
@@ -56,4 +56,7 @@ char __license[] SEC("license") = "Dual MIT/GPL";
 // tls monitoring
 #include "tls/go_tls.c"
 #include "tls/node_tls.c"
-#include "tls/openssl.c"
\ No newline at end of file
+#include "tls/openssl.c"
+
+// ambient istio
+#include "ambient/ztunnel.c"
\ No newline at end of file
diff --git a/bpf/accesslog/ambient/ztunnel.c b/bpf/accesslog/ambient/ztunnel.c
new file mode 100644
index 0000000..5d5ffae
--- /dev/null
+++ b/bpf/accesslog/ambient/ztunnel.c
@@ -0,0 +1,52 @@
+// Licensed to Apache Software Foundation (ASF) under one or more contributor
+// license agreements. See the NOTICE file distributed with
+// this work for additional information regarding copyright
+// ownership. Apache Software Foundation (ASF) licenses this file to you under
+// the Apache License, Version 2.0 (the "License"); you may
+// not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied.  See the License for the
+// specific language governing permissions and limitations
+// under the License.
+
+#include "ztunnel.h"
+
+static __inline bool get_socket_addr_ip_in_ztunnel(bool success, void * arg, 
__u32 *ip, __u16 *port) {
+    if (!success) {
+        return false;
+    }
+    __u8 sockaddr[8];
+    if (bpf_probe_read(&sockaddr, sizeof(sockaddr), (void *)arg) != 0) {
+       return false;
+    }
+    // ip is stored in sockaddr[2], sockaddr[3], sockaddr[4], sockaddr[5]
+    *ip = ((__u32)sockaddr[2] << 24) | ((__u32)sockaddr[3] << 16) | 
((__u32)sockaddr[4] << 8) | (__u32)sockaddr[5];
+    if (port != NULL) {
+        // port is stored in sockaddr[6], sockaddr[7](should convert to 
big-endian)
+        *port = ((__u16)sockaddr[7] << 8) | sockaddr[6];
+    }
+    return true;
+}
+
+SEC("uprobe/connection_manager_track_outbound")
+int connection_manager_track_outbound(struct pt_regs* ctx) {
+    struct ztunnel_socket_mapping_t *event = 
create_ztunnel_socket_mapping_event();
+    if (event == NULL) {
+        return 0;
+    }
+    bool success = true;
+    success = get_socket_addr_ip_in_ztunnel(success, (void 
*)PT_REGS_PARM3(ctx), &event->orginal_src_ip, &event->src_port);
+    success = get_socket_addr_ip_in_ztunnel(success, (void 
*)PT_REGS_PARM4(ctx), &event->original_dst_ip, &event->dst_port);
+    success = get_socket_addr_ip_in_ztunnel(success, (void 
*)PT_REGS_PARM5(ctx), &event->lb_dst_ip, NULL);
+    if (!success) {
+        return 0;
+    }
+    bpf_perf_event_output(ctx, &ztunnel_lb_socket_mapping_event_queue, 
BPF_F_CURRENT_CPU, event, sizeof(*event));
+    return 0;
+}
diff --git a/bpf/accesslog/ambient/ztunnel.h b/bpf/accesslog/ambient/ztunnel.h
new file mode 100644
index 0000000..95fc1a0
--- /dev/null
+++ b/bpf/accesslog/ambient/ztunnel.h
@@ -0,0 +1,39 @@
+// Licensed to Apache Software Foundation (ASF) under one or more contributor
+// license agreements. See the NOTICE file distributed with
+// this work for additional information regarding copyright
+// ownership. Apache Software Foundation (ASF) licenses this file to you under
+// the Apache License, Version 2.0 (the "License"); you may
+// not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied.  See the License for the
+// specific language governing permissions and limitations
+// under the License.
+
+struct ztunnel_socket_mapping_t {
+    __u32 orginal_src_ip;       // origin local ip
+    __u32 original_dst_ip;      // origin remote ip(should be service ip)
+    __u16 src_port;             // origin local port
+    __u16 dst_port;             // origin remote port
+    __u32 lb_dst_ip;            // load balanced remote ip(should be real pod 
ip)
+};
+
+struct {
+       __uint(type, BPF_MAP_TYPE_PERF_EVENT_ARRAY);
+} ztunnel_lb_socket_mapping_event_queue SEC(".maps");
+struct {
+    __uint(type, BPF_MAP_TYPE_PERCPU_ARRAY);
+    __type(key, __u32);
+    __type(value, struct ztunnel_socket_mapping_t);
+    __uint(max_entries, 1);
+} ztunnel_socket_mapping_event_per_cpu_map SEC(".maps");
+
+static __inline struct ztunnel_socket_mapping_t* 
create_ztunnel_socket_mapping_event() {
+  __u32 kZero = 0;
+  return bpf_map_lookup_elem(&ztunnel_socket_mapping_event_per_cpu_map, 
&kZero);
+}
\ No newline at end of file
diff --git a/go.mod b/go.mod
index 0b60a47..191be7b 100644
--- a/go.mod
+++ b/go.mod
@@ -26,7 +26,7 @@ require (
        k8s.io/apimachinery v0.23.5
        k8s.io/client-go v0.23.5
        k8s.io/utils v0.0.0-20211116205334-6203023598ed
-       skywalking.apache.org/repo/goapi v0.0.0-20240604102541-64f9001abe03
+       skywalking.apache.org/repo/goapi v0.0.0-20240914024804-703f701836e6
 )
 
 require (
diff --git a/go.sum b/go.sum
index 09ece52..5fcd734 100644
--- a/go.sum
+++ b/go.sum
@@ -1062,5 +1062,5 @@ sigs.k8s.io/structured-merge-diff/v4 v4.2.1 
h1:bKCqE9GvQ5tiVHn5rfn1r+yao3aLQEaLz
 sigs.k8s.io/structured-merge-diff/v4 v4.2.1/go.mod 
h1:j/nl6xW8vLS49O8YvXW1ocPhZawJtm+Yrr7PPRQ0Vg4=
 sigs.k8s.io/yaml v1.2.0 h1:kr/MCeFWJWTwyaHoR9c8EjH9OumOmoF9YGiZd7lFm/Q=
 sigs.k8s.io/yaml v1.2.0/go.mod h1:yfXDCHCao9+ENCvLSE62v9VSji2MKu5jeNfTrofGhJc=
-skywalking.apache.org/repo/goapi v0.0.0-20240604102541-64f9001abe03 
h1:y0f+3gNmeyC/V5Bt8VE9aL9mmWESj+WvyqJ2tOb7qrk=
-skywalking.apache.org/repo/goapi v0.0.0-20240604102541-64f9001abe03/go.mod 
h1:+n8BMuS8eRdzdnGh15ElRGBXPi0eYZSs2TKySBDmRTE=
+skywalking.apache.org/repo/goapi v0.0.0-20240914024804-703f701836e6 
h1:ZGcxRsuAF+Q/IHzNzunHTeYPSCbXcLIjonEFkDlAfPc=
+skywalking.apache.org/repo/goapi v0.0.0-20240914024804-703f701836e6/go.mod 
h1:+n8BMuS8eRdzdnGh15ElRGBXPi0eYZSs2TKySBDmRTE=
diff --git a/pkg/accesslog/collector/collector.go 
b/pkg/accesslog/collector/collector.go
index e7d6e9b..8e2f4ae 100644
--- a/pkg/accesslog/collector/collector.go
+++ b/pkg/accesslog/collector/collector.go
@@ -19,9 +19,12 @@ package collector
 
 import (
        "github.com/apache/skywalking-rover/pkg/accesslog/common"
+       "github.com/apache/skywalking-rover/pkg/logger"
        "github.com/apache/skywalking-rover/pkg/module"
 )
 
+var log = logger.GetLogger("accesslog", "collector")
+
 type Collector interface {
        Start(mgr *module.Manager, context *common.AccessLogContext) error
        Stop()
@@ -35,5 +38,6 @@ func Collectors() []Collector {
                connectCollectInstance,
                tlsCollectInstance,
                processCollectInstance,
+               zTunnelCollectInstance,
        }
 }
diff --git a/pkg/accesslog/collector/ztunnel.go 
b/pkg/accesslog/collector/ztunnel.go
new file mode 100644
index 0000000..16c39a5
--- /dev/null
+++ b/pkg/accesslog/collector/ztunnel.go
@@ -0,0 +1,200 @@
+// Licensed to Apache Software Foundation (ASF) under one or more contributor
+// license agreements. See the NOTICE file distributed with
+// this work for additional information regarding copyright
+// ownership. Apache Software Foundation (ASF) licenses this file to you under
+// the Apache License, Version 2.0 (the "License"); you may
+// not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied.  See the License for the
+// specific language governing permissions and limitations
+// under the License.
+
+package collector
+
+import (
+       "context"
+       "fmt"
+       "strings"
+       "time"
+
+       "k8s.io/apimachinery/pkg/util/cache"
+
+       "github.com/apache/skywalking-rover/pkg/accesslog/common"
+       "github.com/apache/skywalking-rover/pkg/accesslog/events"
+       "github.com/apache/skywalking-rover/pkg/module"
+       "github.com/apache/skywalking-rover/pkg/tools/elf"
+       "github.com/apache/skywalking-rover/pkg/tools/host"
+
+       v3 "skywalking.apache.org/repo/goapi/collect/ebpf/accesslog/v3"
+
+       "github.com/shirou/gopsutil/process"
+)
+
+var (
+       // ZTunnelProcessFinderInterval is the interval to find ztunnel process
+       ZTunnelProcessFinderInterval = time.Second * 30
+       // ZTunnelTrackBoundSymbolPrefix is the prefix of the symbol name to 
track outbound connections in ztunnel process
+       // ztunnel::proxy::connection_manager::ConnectionManager::track_outbound
+       ZTunnelTrackBoundSymbolPrefix = 
"_ZN7ztunnel5proxy18connection_manager17ConnectionManager14track_outbound"
+)
+
+var zTunnelCollectInstance = NewZTunnelCollector(time.Minute)
+
+// ZTunnelCollector is a collector for ztunnel process in the Ambient Istio 
scenario
+type ZTunnelCollector struct {
+       ctx    context.Context
+       cancel context.CancelFunc
+       alc    *common.AccessLogContext
+
+       collectingProcess       *process.Process
+       ipMappingCache          *cache.Expiring
+       ipMappingExpireDuration time.Duration
+}
+
+func NewZTunnelCollector(expireTime time.Duration) *ZTunnelCollector {
+       return &ZTunnelCollector{
+               ipMappingCache:          cache.NewExpiring(),
+               ipMappingExpireDuration: expireTime,
+       }
+}
+
+func (z *ZTunnelCollector) Start(mgr *module.Manager, ctx 
*common.AccessLogContext) error {
+       z.ctx, z.cancel = context.WithCancel(ctx.RuntimeContext)
+       z.alc = ctx
+       ctx.ConnectionMgr.RegisterNewFlushListener(z)
+
+       err := z.findZTunnelProcessAndCollect()
+       if err != nil {
+               return err
+       }
+
+       ctx.BPF.ReadEventAsync(ctx.BPF.ZtunnelLbSocketMappingEventQueue, 
func(data interface{}) {
+               event := data.(*events.ZTunnelSocketMappingEvent)
+               localIP := z.convertBPFIPToString(event.OriginalSrcIP)
+               localPort := event.OriginalSrcPort
+               remoteIP := z.convertBPFIPToString(event.OriginalDestIP)
+               remotePort := event.OriginalDestPort
+               lbIP := z.convertBPFIPToString(event.LoadBalancedDestIP)
+               log.Debugf("received ztunnel lb socket mapping event: %s:%d -> 
%s:%d, lb: %s", localIP, localPort, remoteIP, remotePort, lbIP)
+
+               key := z.buildIPMappingCacheKey(localIP, int(localPort), 
remoteIP, int(remotePort))
+               z.ipMappingCache.Set(key, lbIP, z.ipMappingExpireDuration)
+       }, func() interface{} {
+               return &events.ZTunnelSocketMappingEvent{}
+       })
+       go func() {
+               ticker := time.NewTicker(ZTunnelProcessFinderInterval)
+               for {
+                       select {
+                       case <-ticker.C:
+                               err := z.findZTunnelProcessAndCollect()
+                               if err != nil {
+                                       log.Error("failed to find and collect 
ztunnel process: ", err)
+                               }
+                       case <-z.ctx.Done():
+                               ticker.Stop()
+                               return
+                       }
+               }
+       }()
+       return nil
+}
+
+func (z *ZTunnelCollector) ReadyToFlushConnection(connection 
*common.ConnectionInfo, _ events.Event) {
+       if connection == nil || connection.Socket == nil || 
connection.RPCConnection == nil || connection.RPCConnection.Attachment != nil {
+               return
+       }
+       key := z.buildIPMappingCacheKey(connection.Socket.SrcIP, 
int(connection.Socket.SrcPort),
+               connection.Socket.DestIP, int(connection.Socket.DestPort))
+       lbIPObj, found := z.ipMappingCache.Get(key)
+       if !found {
+               log.Debugf("there no ztunnel mapped IP address found for 
connection ID: %d, random ID: %d",
+                       connection.ConnectionID, connection.RandomID)
+               return
+       }
+       lbIP := lbIPObj.(string)
+       log.Debugf("found the ztunnel load balanced IP for the connection: %s, 
connectionID: %d, randomID: %d", lbIP,
+               connection.ConnectionID, connection.RandomID)
+       connection.RPCConnection.Attachment = &v3.ConnectionAttachment{
+               Environment: &v3.ConnectionAttachment_ZTunnel{
+                       ZTunnel: &v3.ZTunnelAttachmentEnvironment{
+                               RealDestinationIp: lbIP,
+                               By:                
v3.ZTunnelAttachmentEnvironmentDetectBy_ZTUNNEL_OUTBOUND_FUNC,
+                       },
+               },
+       }
+}
+
+func (z *ZTunnelCollector) convertBPFIPToString(ip uint32) string {
+       return fmt.Sprintf("%d.%d.%d.%d", ip>>24, ip>>16&0xff, ip>>8&0xff, 
ip&0xff)
+}
+
+func (z *ZTunnelCollector) buildIPMappingCacheKey(localIP string, localPort 
int, remoteIP string, remotePort int) string {
+       return fmt.Sprintf("%s:%d-%s:%d", localIP, localPort, remoteIP, 
remotePort)
+}
+
+func (z *ZTunnelCollector) Stop() {
+       if z.cancel != nil {
+               z.cancel()
+       }
+}
+
+func (z *ZTunnelCollector) findZTunnelProcessAndCollect() error {
+       if z.collectingProcess != nil {
+               running, err := z.collectingProcess.IsRunning()
+               if err == nil && running {
+                       // already collecting the process
+                       return nil
+               }
+               log.Warnf("detected ztunnel process is not running, should 
re-scan process to find and collect it")
+       }
+
+       processes, err := process.Processes()
+       if err != nil {
+               return err
+       }
+       var zTunnelProcess *process.Process
+       for _, p := range processes {
+               name, err := p.Exe()
+               if err != nil {
+                       continue
+               }
+               if strings.HasSuffix(name, "/ztunnel") {
+                       zTunnelProcess = p
+                       break
+               }
+       }
+
+       if zTunnelProcess == nil {
+               log.Debugf("ztunnel process not found is current node")
+               return nil
+       }
+
+       log.Infof("ztunnel process founded in current node, pid: %d", 
zTunnelProcess.Pid)
+       z.collectingProcess = zTunnelProcess
+       return z.collectZTunnelProcess(zTunnelProcess)
+}
+
+func (z *ZTunnelCollector) collectZTunnelProcess(p *process.Process) error {
+       pidExeFile := host.GetFileInHost(fmt.Sprintf("/proc/%d/exe", p.Pid))
+       elfFile, err := elf.NewFile(pidExeFile)
+       if err != nil {
+               return fmt.Errorf("read executable file error: %v", err)
+       }
+       trackBoundSymbol := elfFile.FilterSymbol(func(name string) bool {
+               return strings.HasPrefix(name, ZTunnelTrackBoundSymbolPrefix)
+       }, true)
+       if len(trackBoundSymbol) == 0 {
+               return fmt.Errorf("failed to find track outbound symbol in 
ztunnel process")
+       }
+
+       uprobeFile := z.alc.BPF.OpenUProbeExeFile(pidExeFile)
+       uprobeFile.AddLink(trackBoundSymbol[0].Name, 
z.alc.BPF.ConnectionManagerTrackOutbound, nil)
+       return nil
+}
diff --git a/pkg/accesslog/common/connection.go 
b/pkg/accesslog/common/connection.go
index de98fb9..fe1065c 100644
--- a/pkg/accesslog/common/connection.go
+++ b/pkg/accesslog/common/connection.go
@@ -85,6 +85,11 @@ type ConnectionProcessor interface {
        OnConnectionClose(event *events.SocketCloseEvent, callback 
ConnectionProcessFinishCallback)
 }
 
+type FlusherListener interface {
+       // ReadyToFlushConnection notify which connection ready to flush
+       ReadyToFlushConnection(connection *ConnectionInfo, 
getConnectionFromEvent events.Event)
+}
+
 type ProcessListener interface {
        OnNewProcessMonitoring(pid int32)
        OnProcessRemoved(pid int32)
@@ -115,6 +120,8 @@ type ConnectionManager struct {
 
        // connection already close but the connection (protocols)log not build 
finished
        allUnfinishedConnections map[string]*bool
+
+       flushListeners []FlusherListener
 }
 
 func (c *ConnectionManager) RegisterProcessor(processor ConnectionProcessor) {
@@ -125,6 +132,10 @@ func (c *ConnectionManager) AddProcessListener(listener 
ProcessListener) {
        c.processListeners = append(c.processListeners, listener)
 }
 
+func (c *ConnectionManager) RegisterNewFlushListener(listener FlusherListener) 
{
+       c.flushListeners = append(c.flushListeners, listener)
+}
+
 type addressInfo struct {
        pid uint32
 }
@@ -135,6 +146,7 @@ type ConnectionInfo struct {
        RPCConnection *v3.AccessLogConnection
        MarkDeletable bool
        PID           uint32
+       Socket        *ip.SocketPair
 }
 
 func NewConnectionManager(config *Config, moduleMgr *module.Manager, bpfLoader 
*bpf.Loader, filter MonitorFilter) *ConnectionManager {
@@ -150,6 +162,7 @@ func NewConnectionManager(config *Config, moduleMgr 
*module.Manager, bpfLoader *
                activeConnectionMap:      bpfLoader.ActiveConnectionMap,
                allUnfinishedConnections: make(map[string]*bool),
                monitorFilter:            filter,
+               flushListeners:           make([]FlusherListener, 0),
        }
        return mgr
 }
@@ -246,6 +259,7 @@ func (c *ConnectionManager) Find(event events.Event) 
*ConnectionInfo {
                                e.GetConnectionID(), e.GetRandomID(), 
socket.Role, socket.SrcIP, socket.SrcPort, socket.DestIP, socket.DestPort,
                                localAddress.String(), remoteAddress.String())
                }
+               c.connectionPostHandle(connection, event)
                return connection
        }
        return nil
@@ -312,6 +326,11 @@ func (c *ConnectionManager) 
connectionPostHandle(connection *ConnectionInfo, eve
                        }
                }
        }
+
+       // notify all flush listeners the connection is ready to flush
+       for _, flush := range c.flushListeners {
+               flush.ReadyToFlushConnection(connection, event)
+       }
 }
 
 func (c *ConnectionManager) ProcessIsMonitor(pid uint32) bool {
@@ -341,6 +360,7 @@ func (c *ConnectionManager) buildConnection(event 
*events.SocketConnectEvent, so
                RandomID:      event.RandomID,
                RPCConnection: connection,
                PID:           event.PID,
+               Socket:        socket,
        }
 }
 
diff --git a/pkg/accesslog/collector/collector.go 
b/pkg/accesslog/events/ztunnel.go
similarity index 64%
copy from pkg/accesslog/collector/collector.go
copy to pkg/accesslog/events/ztunnel.go
index e7d6e9b..33c6d35 100644
--- a/pkg/accesslog/collector/collector.go
+++ b/pkg/accesslog/events/ztunnel.go
@@ -15,25 +15,12 @@
 // specific language governing permissions and limitations
 // under the License.
 
-package collector
+package events
 
-import (
-       "github.com/apache/skywalking-rover/pkg/accesslog/common"
-       "github.com/apache/skywalking-rover/pkg/module"
-)
-
-type Collector interface {
-       Start(mgr *module.Manager, context *common.AccessLogContext) error
-       Stop()
-}
-
-func Collectors() []Collector {
-       return []Collector{
-               l24CollectorsInstance,
-               transferCollectInstance,
-               closeCollectorInstance,
-               connectCollectInstance,
-               tlsCollectInstance,
-               processCollectInstance,
-       }
+type ZTunnelSocketMappingEvent struct {
+       OriginalSrcIP      uint32
+       OriginalDestIP     uint32
+       OriginalSrcPort    uint16
+       OriginalDestPort   uint16
+       LoadBalancedDestIP uint32
 }
diff --git a/pkg/tools/elf/elf.go b/pkg/tools/elf/elf.go
index 51237ff..9d01111 100644
--- a/pkg/tools/elf/elf.go
+++ b/pkg/tools/elf/elf.go
@@ -50,22 +50,37 @@ func (f *File) Close() error {
 }
 
 func (f *File) FindSymbol(name string) *Symbol {
+       symbol := f.FilterSymbol(func(n string) bool {
+               return n == name
+       }, true)
+       if len(symbol) > 0 {
+               return symbol[0]
+       }
+       return nil
+}
+
+func (f *File) FilterSymbol(filter func(name string) bool, onlyOneResult bool) 
[]*Symbol {
        symbols, _ := f.realFile.Symbols()
        dynamicSymbols, _ := f.realFile.DynamicSymbols()
        if len(symbols) == 0 && len(dynamicSymbols) == 0 {
                return nil
        }
        symbols = append(symbols, dynamicSymbols...)
+
+       result := make([]*Symbol, 0)
        for _, s := range symbols {
-               if s.Name == name {
-                       return &Symbol{
-                               Name:     name,
+               if filter(s.Name) {
+                       result = append(result, &Symbol{
+                               Name:     s.Name,
                                Location: s.Value,
                                Size:     s.Size,
+                       })
+                       if onlyOneResult {
+                               break
                        }
                }
        }
-       return nil
+       return result
 }
 
 func (f *File) ReadSymbolData(section string, offset, size uint64) ([]byte, 
error) {
diff --git a/scripts/build/bash/btfgen.sh b/scripts/build/bash/btfgen.sh
index 80ecd68..8441e73 100644
--- a/scripts/build/bash/btfgen.sh
+++ b/scripts/build/bash/btfgen.sh
@@ -21,7 +21,7 @@ TMPDIR=$1
 ARCH=$2
 FROM=$3
 OUTPUT=$4
-BPF_SO_PATTERN="^bpf\_[a-z0-9]+\.o"
+BPF_SO_PATTERN="^bpf\_[a-z0-9]+(_[a-z0-9]+)?\.o"
 
 echo "btfhub-archive is a big archive project, maybe take some times..."
 git clone --depth 1 https://github.com/aquasecurity/btfhub $TMPDIR/btfhub

Reply via email to