admin 管理员组

文章数量: 887019

%pS

之前看到有人在kernel中有人用%pF来打印,一直很好奇这个是啥意思。其中ai_sys_last_pc 是地址。
 seq_printf(m, "System:\t\t%lu (%pS)\n", ai_sys, ai_sys_last_pc);
后来追了一下实现
/source/lib/vsprintf.c
/*
1476  * Show a '%p' thing.  A kernel extension is that the '%p' is followed
1477  * by an extra set of alphanumeric characters that are extended format
1478  * specifiers.
1479  *
1480  * Right now we handle:
1481  *
1482  * - 'F' For symbolic function descriptor pointers with offset
1483  * - 'f' For simple symbolic function names without offset
1484  * - 'S' For symbolic direct pointers with offset
1485  * - 's' For symbolic direct pointers without offset
1486  * - '[FfSs]R' as above with __builtin_extract_return_addr() translation
1487  * - 'B' For backtraced symbolic direct pointers with offset
1488  * - 'R' For decoded struct resource, e.g., [mem 0x0-0x1f 64bit pref]
1489  * - 'r' For raw struct resource, e.g., [mem 0x0-0x1f flags 0x201]
1490  * - 'b[l]' For a bitmap, the number of bits is determined by the field
1491  *       width which must be explicitly specified either as part of the
1492  *       format string '%32b[l]' or through '%*b[l]', [l] selects
1493  *       range-list format instead of hex format
1494  * - 'M' For a 6-byte MAC address, it prints the address in the
1495  *       usual colon-separated hex notation
1496  * - 'm' For a 6-byte MAC address, it prints the hex address without colons
1497  * - 'MF' For a 6-byte MAC FDDI address, it prints the address
1498  *       with a dash-separated hex notation
1499  * - '[mM]R' For a 6-byte MAC address, Reverse order (Bluetooth)
1500  * - 'I' [46] for IPv4/IPv6 addresses printed in the usual way
1501  *       IPv4 uses dot-separated decimal without leading 0's (1.2.3.4)
1502  *       IPv6 uses colon separated network-order 16 bit hex with leading 0's
1503  *       [S][pfs]
1504  *       Generic IPv4/IPv6 address (struct sockaddr *) that falls back to
1505  *       [4] or [6] and is able to print port [p], flowinfo [f], scope [s]
1506  * - 'i' [46] for 'raw' IPv4/IPv6 addresses
1507  *       IPv6 omits the colons (01020304...0f)
1508  *       IPv4 uses dot-separated decimal with leading 0's (010.123.045.006)
1509  *       [S][pfs]
1510  *       Generic IPv4/IPv6 address (struct sockaddr *) that falls back to
1511  *       [4] or [6] and is able to print port [p], flowinfo [f], scope [s]
1512  * - '[Ii][4S][hnbl]' IPv4 addresses in host, network, big or little endian order
1513  * - 'I[6S]c' for IPv6 addresses printed as specified by
1514  *      
1515  * - 'E[achnops]' For an escaped buffer, where rules are defined by combination
1516  *                of the following flags (see string_escape_mem() for the
1517  *                details):
1518  *                  a - ESCAPE_ANY
1519  *                  c - ESCAPE_SPECIAL
1520  *                  h - ESCAPE_HEX
1521  *                  n - ESCAPE_NULL
1522  *                  o - ESCAPE_OCTAL
1523  *                  p - ESCAPE_NP
1524  *                  s - ESCAPE_SPACE
1525  *                By default ESCAPE_ANY_NP is used.
1526  * - 'U' For a 16 byte UUID/GUID, it prints the UUID/GUID in the form
1527  *       "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"
1528  *       Options for %pU are:
1529  *         b big endian lower case hex (default)
1530  *         B big endian UPPER case hex
1531  *         l little endian lower case hex
1532  *         L little endian UPPER case hex
1533  *           big endian output byte order is:
1534  *             [0][1][2][3]-[4][5]-[6][7]-[8][9]-[10][11][12][13][14][15]
1535  *           little endian output byte order is:
1536  *             [3][2][1][0]-[5][4]-[7][6]-[8][9]-[10][11][12][13][14][15]
1537  * - 'V' For a struct va_format which contains a format string * and va_list *,
1538  *       call vsnprintf(->format, *->va_list).
1539  *       Implements a "recursive vsnprintf".
1540  *       Do not use this feature without some mechanism to verify the
1541  *       correctness of the format string and va_list arguments.
1542  * - 'K' For a kernel pointer that should be hidden from unprivileged users
1543  * - 'NF' For a netdev_features_t
1544  * - 'h[CDN]' For a variable-length buffer, it prints it as a hex string with
1545  *            a certain separator (' ' by default):
1546  *              C colon
1547  *              D dash
1548  *              N no separator
1549  *            The maximum supported length is 64 bytes of the input. Consider
1550  *            to use print_hex_dump() for the larger input.
1551  * - 'a[pd]' For address types [p] phys_addr_t, [d] dma_addr_t and derivatives
1552  *           (default assumed to be phys_addr_t, passed by reference)
1553  * - 'd[234]' For a dentry name (optionally 2-4 last components)
1554  * - 'D[234]' Same as 'd' but for a struct file
1555  * - 'g' For block_device name (gendisk + partition number)
1556  * - 'C' For a clock, it prints the name (Common Clock Framework) or address
1557  *       (legacy clock framework) of the clock
1558  * - 'Cn' For a clock, it prints the name (Common Clock Framework) or address
1559  *        (legacy clock framework) of the clock
1560  * - 'Cr' For a clock, it prints the current rate of the clock
1561  * - 'G' For flags to be printed as a collection of symbolic strings that would
1562  *       construct the specific value. Supported flags given by option:
1563  *       p page flags (see struct page) given as pointer to unsigned long
1564  *       g gfp flags (GFP_* and __GFP_*) given as pointer to gfp_t
1565  *       v vma flags (VM_*) given as pointer to unsigned long
1566  *
1567  * ** Please update also Documentation/printk-formats.txt when making changes **
1568  *
1569  * Note: The difference between 'S' and 'F' is that on ia64 and ppc64
1570  * function pointers are really function descriptors, which contain a
1571  * pointer to the real address.
1572  */
1573 static noinline_for_stack
1574 char *pointer(const char *fmt, char *buf, char *end, void *ptr,
1575               struct printf_spec spec)
1576 {
1577         const int default_width = 2 * sizeof(void *);
1578 
1579         if (!ptr && *fmt != 'K') {
1580                 /*
1581                  * Print (null) with the same width as a pointer so it makes
1582                  * tabular output look nice.
1583                  */
1584                 if (spec.field_width == -1)
1585                         spec.field_width = default_width;
1586                 return string(buf, end, "(null)", spec);
1587         }
1588 
1589         switch (*fmt) {
1590         case 'F':
1591         case 'f':
1592                 ptr = dereference_function_descriptor(ptr);
1593                 /* Fallthrough */
1594         case 'S':
1595         case 's':
1596         case 'B':
1597                 return symbol_string(buf, end, ptr, spec, fmt);
上面这行是关键可以看到%pS/%ps/%pB 都已同一个意思,即根据指针找到对应的symbold

本文标签: ps