0

When using the bcc tool funclatency, there are unknown function names. It would be helpful if I could track the entry and return values of a number of functions contained in the library ibverbs (Infiniband).

I use funclatency to print a histogram of the ibverbs functions called by perftest.

https://github.com/iovisor/bcc/tree/master/tools

To send packages between two nodes, I use the perftest.

https://github.com/linux-rdma/perftest

To compile the perftest application, I used the following compiler flags:

CFLAGS = -g -Wall -D_GNU_SOURCE -O3 -ggdb3 -O2 -fno-omit-frame-pointer

System:

Distributor ID: Debian
Description: Debian GNU/Linux 11 (bullseye)
Release: 11
Codename: bullseye

I use funclatency like this:

sudo funclatency-bpfcc ibverbs:ibv_get*

funclatency output:

Tracing 13 functions for "ibverbs:ibv_get*"... Hit Ctrl-C to end.
Function = b'[unknown]' [784402]
     nsecs               : count     distribution
         0 -> 1          : 0        |                                        |
         2 -> 3          : 0        |                                        |
         4 -> 7          : 0        |                                        |
         8 -> 15         : 0        |                                        |
        16 -> 31         : 0        |                                        |
        32 -> 63         : 0        |                                        |
        64 -> 127        : 0        |                                        |
       128 -> 255        : 0        |                                        |
       256 -> 511        : 0        |                                        |
       512 -> 1023       : 0        |                                        |
      1024 -> 2047       : 468      |****************************            |
      2048 -> 4095       : 512      |******************************          |
      4096 -> 8191       : 664      |****************************************|
      8192 -> 16383      : 332      |********************                    |
     16384 -> 32767      : 14       |                                        |
     32768 -> 65535      : 3        |                                        |
     65536 -> 131071     : 6        |                                        |
    131072 -> 262143     : 0        |                                        |
    262144 -> 524287     : 0        |                                        |
    524288 -> 1048575    : 0        |                                        |
   1048576 -> 2097151    : 0        |                                        |
   2097152 -> 4194303    : 0        |                                        |
   4194304 -> 8388607    : 0        |                                        |
   8388608 -> 16777215   : 1        |                                        |

Here is the source code for the translation of a memory address into a function name:

https://github.com/iovisor/bcc/blob/master/src/python/bcc/init.py

    def sym(addr, pid, show_module=False, show_offset=False, demangle=True):
    """sym(addr, pid, show_module=False, show_offset=False)

    Translate a memory address into a function name for a pid, which is
    returned. When show_module is True, the module name is also included.
    When show_offset is True, the instruction offset as a hexadecimal
    number is also included in the string.

    A pid of less than zero will access the kernel symbol cache.

    Example output when both show_module and show_offset are True:
        "start_thread+0x202 [libpthread-2.24.so]"

    Example output when both show_module and show_offset are False:
        "start_thread"
    """

    #addr is of type stacktrace_build_id
    #so invoke the bsym address resolver
    typeofaddr = str(type(addr))
    if typeofaddr.find('bpf_stack_build_id') != -1:
      sym = bcc_symbol()
      b = bcc_stacktrace_build_id()
      b.status = addr.status
      b.build_id = addr.build_id
      b.u.offset = addr.offset
      res = lib.bcc_buildsymcache_resolve(BPF._bsymcache,
                                          ct.byref(b),
                                          ct.byref(sym))
      if res < 0:
        if sym.module and sym.offset:
          name,offset,module = (None, sym.offset,
                    ct.cast(sym.module, ct.c_char_p).value)
        else:
          name, offset, module = (None, addr, None)
      else:
        name, offset, module = (sym.name, sym.offset,
                                ct.cast(sym.module, ct.c_char_p).value)
    else:
      name, offset, module = BPF._sym_cache(pid).resolve(addr, demangle)

    offset = b"+0x%x" % offset if show_offset and name is not None else b""
    name = name or b"[unknown]"
    name = name + offset
    module = b" [%s]" % os.path.basename(module) \
        if show_module and module is not None else b""
    return name + module

How can I read the function name correctly? It should not just return b'[unknown]'!

Bahamas
  • 345
  • 1
  • 2
  • 13

0 Answers0