LCOV - code coverage report
Current view: top level - lib/eal/unix - eal_debug.c (source / functions) Hit Total Coverage
Test: Code coverage Lines: 32 33 97.0 %
Date: 2025-01-02 22:41:34 Functions: 1 1 100.0 %
Legend: Lines: hit not hit | Branches: + taken - not taken # not executed Branches: 20 28 71.4 %

           Branch data     Line data    Source code
       1                 :            : /* SPDX-License-Identifier: BSD-3-Clause
       2                 :            :  * Copyright(c) 2010-2014 Intel Corporation
       3                 :            :  */
       4                 :            : 
       5                 :            : #include <rte_debug.h>
       6                 :            : 
       7                 :            : #ifdef RTE_BACKTRACE
       8                 :            : 
       9                 :            : #include <dlfcn.h>
      10                 :            : #include <execinfo.h>
      11                 :            : #include <string.h>
      12                 :            : #include <sys/uio.h>
      13                 :            : #include <unistd.h>
      14                 :            : 
      15                 :            : #define BACKTRACE_SIZE 256
      16                 :            : 
      17                 :            : /*
      18                 :            :  * Convert number to string and return start of string.
      19                 :            :  * Note: string does not start at beginning of buffer.
      20                 :            :  */
      21                 :            : static char *safe_itoa(long val, char *buf, size_t len, unsigned int radix)
      22                 :            : {
      23                 :            :         char *bp = buf + len;
      24                 :            :         static const char hexdigit[] = "0123456789abcdef";
      25                 :            : 
      26                 :        252 :         *--bp = '\0'; /* Null terminate the string */
      27                 :            :         do {
      28                 :            :                 /* if buffer is not big enough, then truncate */
      29   [ +  -  +  -  :       1668 :                 if (bp == buf)
             +  -  +  - ]
      30                 :            :                         return bp;
      31                 :            : 
      32                 :       1668 :                 *--bp = hexdigit[val % radix];
      33                 :       1668 :                 val /= radix;
      34   [ +  +  +  +  :       1668 :         } while (val != 0);
             +  +  +  + ]
      35                 :            : 
      36                 :            :         return bp;
      37                 :            : }
      38                 :            : 
      39                 :            : /*
      40                 :            :  * Dump the stack of the calling core
      41                 :            :  *
      42                 :            :  * To be safe in signal handler requires limiting what functions are
      43                 :            :  * used in this code since may be called from inside libc or
      44                 :            :  * when malloc poll is corrupt.
      45                 :            :  *
      46                 :            :  * Most of libc is therefore not safe, include RTE_LOG (calls syslog);
      47                 :            :  * backtrace_symbols (calls malloc), etc.
      48                 :            :  */
      49                 :          6 : void rte_dump_stack(void)
      50                 :            : {
      51                 :            :         void *func[BACKTRACE_SIZE];
      52                 :            :         Dl_info info;
      53                 :            :         char buf1[8], buf2[32], buf3[32], buf4[32];
      54                 :            :         struct iovec iov[10];
      55                 :            :         int i, size;
      56                 :            : 
      57                 :          6 :         size = backtrace(func, BACKTRACE_SIZE);
      58                 :            : 
      59         [ +  + ]:         78 :         for (i = 0; i < size; i++) {
      60                 :            :                 struct iovec *io = iov;
      61                 :            :                 char *str;
      62                 :            :                 uintptr_t base;
      63                 :            :                 long offset;
      64                 :         72 :                 void *pc = func[i];
      65                 :            : 
      66                 :            : /*
      67                 :            :  * Macro to put string onto set of iovecs.
      68                 :            :  * cast is to suppress warnings about lose of const qualifier.
      69                 :            :  */
      70                 :            : #define PUSH_IOV(io, str) {                                     \
      71                 :            :                 (io)->iov_base = (char *)(uintptr_t)str;     \
      72                 :            :                 (io)->iov_len = strlen(str);                 \
      73                 :            :                 ++io; }
      74                 :            : 
      75                 :            :                 /* output stack frame number */
      76                 :         72 :                 str = safe_itoa(i, buf1, sizeof(buf1), 10);
      77                 :         72 :                 PUSH_IOV(io, str);      /* iov[0] */
      78                 :         72 :                 PUSH_IOV(io, ": ");   /* iov[1] */
      79                 :            : 
      80                 :            :                 /* Lookup the symbol information */
      81         [ -  + ]:         72 :                 if (dladdr(pc, &info) == 0) {
      82                 :          0 :                         PUSH_IOV(io, "?? [");
      83                 :            :                 } else {
      84                 :            :                         const char *fname;
      85                 :            : 
      86   [ +  -  +  - ]:         72 :                         if (info.dli_fname && *info.dli_fname)
      87                 :         72 :                                 fname = info.dli_fname;
      88                 :            :                         else
      89                 :            :                                 fname = "(vdso)";
      90                 :         72 :                         PUSH_IOV(io, fname);    /* iov[2] */
      91                 :         72 :                         PUSH_IOV(io, " (");   /* iov[3] */
      92                 :            : 
      93         [ +  + ]:         72 :                         if (info.dli_saddr != NULL) {
      94                 :         36 :                                 PUSH_IOV(io, info.dli_sname);   /* iov[4] */
      95                 :         36 :                                 base = (uintptr_t)info.dli_saddr;
      96                 :            :                         } else {
      97                 :         36 :                                 str = safe_itoa((unsigned long)info.dli_fbase,
      98                 :            :                                         buf3, sizeof(buf3), 16);
      99                 :         36 :                                 PUSH_IOV(io, str);
     100                 :         36 :                                 base = (uintptr_t)info.dli_fbase;
     101                 :            :                         }
     102                 :            : 
     103                 :         72 :                         PUSH_IOV(io, "+0x");  /* iov[5] */
     104                 :            : 
     105                 :         72 :                         offset = (uintptr_t)pc - base;
     106                 :            :                         str = safe_itoa(offset, buf4, sizeof(buf4), 16);
     107                 :         72 :                         PUSH_IOV(io, str);      /* iov[6] */
     108                 :            : 
     109                 :         72 :                         PUSH_IOV(io, ") [");  /* iov[7] */
     110                 :            :                 }
     111                 :            : 
     112                 :         72 :                 str = safe_itoa((unsigned long)pc, buf2, sizeof(buf2), 16);
     113                 :         72 :                 PUSH_IOV(io, str);      /* iov[8] */
     114                 :         72 :                 PUSH_IOV(io, "]\n");  /* iov[9] */
     115                 :            : 
     116         [ +  - ]:         72 :                 if (writev(STDERR_FILENO, iov, io - iov) < 0)
     117                 :            :                         break;
     118                 :            : #undef PUSH_IOV
     119                 :            :         }
     120                 :          6 : }
     121                 :            : 
     122                 :            : #else /* !RTE_BACKTRACE */
     123                 :            : 
     124                 :            : /* stub if not enabled */
     125                 :            : void rte_dump_stack(void) { }
     126                 :            : 
     127                 :            : #endif /* RTE_BACKTRACE */

Generated by: LCOV version 1.14