How to get printk format specifiers right

Author:

Randy Dunlap <rdunlap@infradead.org>

Author:

Andrew Murray <amurray@mpc-data.co.uk>

Integer types

If variable is of Type,         use printk format specifier:------------------------------------------------------------        signed char             %d or %hhx        unsigned char           %u or %x        char                    %u or %x        short int               %d or %hx        unsigned short int      %u or %x        int                     %d or %x        unsigned int            %u or %x        long                    %ld or %lx        unsigned long           %lu or %lx        long long               %lld or %llx        unsigned long long      %llu or %llx        size_t                  %zu or %zx        ssize_t                 %zd or %zx        s8                      %d or %hhx        u8                      %u or %x        s16                     %d or %hx        u16                     %u or %x        s32                     %d or %x        u32                     %u or %x        s64                     %lld or %llx        u64                     %llu or %llx

If <type> is architecture-dependent for its size (e.g., cycles_t, tcflag_t) oris dependent on a config option for its size (e.g., blk_status_t), use a formatspecifier of its largest possible type and explicitly cast to it.

Example:

printk("test: latency: %llu cycles\n", (unsigned long long)time);

Reminder: sizeof() returns type size_t.

The kernel’s printf does not support %n. Floating point formats (%e, %f,%g, %a) are also not recognized, for obvious reasons. Use of anyunsupported specifier or length qualifier results in a WARN and earlyreturn fromvsnprintf().

Pointer types

A raw pointer value may be printed with %p which will hash the addressbefore printing. The kernel also supports extended specifiers for printingpointers of different types.

Some of the extended specifiers print the data on the given address insteadof printing the address itself. In this case, the following error messagesmight be printed instead of the unreachable information:

(null)   data on plain NULL address(efault) data on invalid address(einval) invalid data on a valid address

Plain Pointers

%p      abcdef12 or 00000000abcdef12

Pointers printed without a specifier extension (i.e unadorned %p) arehashed to prevent leaking information about the kernel memory layout. Thishas the added benefit of providing a unique identifier. On 64-bit machinesthe first 32 bits are zeroed. The kernel will print(ptrval) until itgathers enough entropy.

When possible, use specialised modifiers such as %pS or %pB (described below)to avoid the need of providing an unhashed address that has to be interpretedpost-hoc. If not possible, and the aim of printing the address is to providemore information for debugging, use %p and boot the kernel with theno_hash_pointers parameter during debugging, which will print all %paddresses unmodified. If youreally always want the unmodified address, see%px below.

If (and only if) you are printing addresses as a content of a virtual file ine.g. procfs or sysfs (using e.g.seq_printf(), notprintk()) read by auserspace process, use the %pK modifier described below instead of %p or %px.

Error Pointers

%pe     -ENOSPC

For printing error pointers (i.e. a pointer for whichIS_ERR() is true)as a symbolic error name. Error values for which no symbolic name isknown are printed in decimal, while a non-ERR_PTR passed as theargument to %pe gets treated as ordinary %p.

Symbols/Function Pointers

%pS     versatile_init+0x0/0x110%ps     versatile_init%pSR    versatile_init+0x9/0x110        (with __builtin_extract_return_addr() translation)%pB     prev_fn_of_versatile_init+0x88/0x88

TheS ands specifiers are used for printing a pointer in symbolicformat. They result in the symbol name with (S) or without (s)offsets. If KALLSYMS are disabled then the symbol address is printed instead.

TheB specifier results in the symbol name with offsets and should beused when printing stack backtraces. The specifier takes intoconsideration the effect of compiler optimisations which may occurwhen tail-calls are used and marked with the noreturn GCC attribute.

If the pointer is within a module, the module name and optionally build ID isprinted after the symbol name with an extrab appended to the end of thespecifier.

%pS     versatile_init+0x0/0x110 [module_name]%pSb    versatile_init+0x0/0x110 [module_name ed5019fdf5e53be37cb1ba7899292d7e143b259e]%pSRb   versatile_init+0x9/0x110 [module_name ed5019fdf5e53be37cb1ba7899292d7e143b259e]        (with __builtin_extract_return_addr() translation)%pBb    prev_fn_of_versatile_init+0x88/0x88 [module_name ed5019fdf5e53be37cb1ba7899292d7e143b259e]

Probed Pointers from BPF / tracing

%pks    kernel string%pus    user string

Thek andu specifiers are used for printing prior probed memory fromeither kernel memory (k) or user memory (u). The subsequents specifierresults in printing a string. For direct use in regularvsnprintf() the (k)and (u) annotation is ignored, however, when used out of BPF’sbpf_trace_printk(),for example, it reads the memory it is pointing to without faulting.

Kernel Pointers

%pK     01234567 or 0123456789abcdef

For printing kernel pointers which should be hidden from unprivilegedusers. The behaviour of %pK depends on the kptr_restrict sysctl - seeDocumentation for /proc/sys/kernel/ for more details.

This modifier isonly intended when producing content of a file read byuserspace from e.g. procfs or sysfs, not for dmesg. Please refer to thesection about %p above for discussion about how to manage hashing pointersinprintk().

Unmodified Addresses

%px     01234567 or 0123456789abcdef

For printing pointers when youreally want to print the address. Pleaseconsider whether or not you are leaking sensitive information about thekernel memory layout before printing pointers with %px. %px is functionallyequivalent to %lx (or %lu). %px is preferred because it is more uniquelygrep’able. If in the future we need to modify the way the kernel handlesprinting pointers we will be better equipped to find the call sites.

Before using %px, consider if using %p is sufficient together with enabling theno_hash_pointers kernel parameter during debugging sessions (see the %pdescription above). One valid scenario for %px might be printing informationimmediately before a panic, which prevents any sensitive information to beexploited anyway, and with %px there would be no need to reproduce the panicwith no_hash_pointers.

Pointer Differences

%td     2560%tx     a00

For printing the pointer differences, use the %t modifier for ptrdiff_t.

Example:

printk("test: difference between pointers: %td\n", ptr2 - ptr1);

Struct Resources

%pr     [mem 0x60000000-0x6fffffff flags 0x2200] or        [mem 0x60000000 flags 0x2200] or        [mem 0x0000000060000000-0x000000006fffffff flags 0x2200]        [mem 0x0000000060000000 flags 0x2200]%pR     [mem 0x60000000-0x6fffffff pref] or        [mem 0x60000000 pref] or        [mem 0x0000000060000000-0x000000006fffffff pref]        [mem 0x0000000060000000 pref]

For printingstructresources. TheR andr specifiers result in aprinted resource with (R) or without (r) a decoded flags member. If start isequal to end only print the start value.

Passed by reference.

Physical address types phys_addr_t

%pa[p]  0x01234567 or 0x0123456789abcdef

For printing a phys_addr_t type (and its derivatives, such asresource_size_t) which can vary based on build options, regardless of thewidth of the CPU data path.

Passed by reference.

Struct Range

%pra    [range 0x0000000060000000-0x000000006fffffff] or        [range 0x0000000060000000]

For printingstructrange.structrange holds an arbitrary range of u64values. If start is equal to end only print the start value.

Passed by reference.

DMA address types dma_addr_t

%pad    0x01234567 or 0x0123456789abcdef

For printing a dma_addr_t type which can vary based on build options,regardless of the width of the CPU data path.

Passed by reference.

Raw buffer as an escaped string

%*pE[achnops]

For printing raw buffer as an escaped string. For the following buffer:

1b 62 20 5c 43 07 22 90 0d 5d

A few examples show how the conversion would be done (excluding surroundingquotes):

%*pE            "\eb \C\a"\220\r]"%*pEhp          "\x1bb \C\x07"\x90\x0d]"%*pEa           "\e\142\040\\\103\a\042\220\r\135"

The conversion rules are applied according to an optional combinationof flags (seestring_escape_mem() kernel documentation for thedetails):

  • a - ESCAPE_ANY

  • c - ESCAPE_SPECIAL

  • h - ESCAPE_HEX

  • n - ESCAPE_NULL

  • o - ESCAPE_OCTAL

  • p - ESCAPE_NP

  • s - ESCAPE_SPACE

By default ESCAPE_ANY_NP is used.

ESCAPE_ANY_NP is the sane choice for many cases, in particularly forprinting SSIDs.

If field width is omitted then 1 byte only will be escaped.

Raw buffer as a hex string

%*ph    00 01 02  ...  3f%*phC   00:01:02: ... :3f%*phD   00-01-02- ... -3f%*phN   000102 ... 3f

For printing small buffers (up to 64 bytes long) as a hex string with acertain separator. For larger buffers consider usingprint_hex_dump().

MAC/FDDI addresses

%pM     00:01:02:03:04:05%pMR    05:04:03:02:01:00%pMF    00-01-02-03-04-05%pm     000102030405%pmR    050403020100

For printing 6-byte MAC/FDDI addresses in hex notation. TheM andmspecifiers result in a printed address with (M) or without (m) byteseparators. The default byte separator is the colon (:).

Where FDDI addresses are concerned theF specifier can be used aftertheM specifier to use dash (-) separators instead of the defaultseparator.

For Bluetooth addresses theR specifier shall be used after theMspecifier to use reversed byte order suitable for visual interpretationof Bluetooth addresses which are in the little endian order.

Passed by reference.

IPv4 addresses

%pI4    1.2.3.4%pi4    001.002.003.004%p[Ii]4[hnbl]

For printing IPv4 dot-separated decimal addresses. TheI4 andi4specifiers result in a printed address with (i4) or without (I4) leadingzeros.

The additionalh,n,b, andl specifiers are used to specifyhost, network, big or little endian order addresses respectively. Whereno specifier is provided the default network/big endian order is used.

Passed by reference.

IPv6 addresses

%pI6    0001:0002:0003:0004:0005:0006:0007:0008%pi6    00010002000300040005000600070008%pI6c   1:2:3:4:5:6:7:8

For printing IPv6 network-order 16-bit hex addresses. TheI6 andi6specifiers result in a printed address with (I6) or without (i6)colon-separators. Leading zeros are always used.

The additionalc specifier can be used with theI specifier toprint a compressed IPv6 address as described byhttps://tools.ietf.org/html/rfc5952

Passed by reference.

IPv4/IPv6 addresses (generic, with port, flowinfo, scope)

%pIS    1.2.3.4         or 0001:0002:0003:0004:0005:0006:0007:0008%piS    001.002.003.004 or 00010002000300040005000600070008%pISc   1.2.3.4         or 1:2:3:4:5:6:7:8%pISpc  1.2.3.4:12345   or [1:2:3:4:5:6:7:8]:12345%p[Ii]S[pfschnbl]

For printing an IP address without the need to distinguish whether it’s oftype AF_INET or AF_INET6. A pointer to a validstructsockaddr,specified throughIS oriS, can be passed to this format specifier.

The additionalp,f, ands specifiers are used to specify port(IPv4, IPv6), flowinfo (IPv6) and scope (IPv6). Ports have a: prefix,flowinfo a/ and scope a%, each followed by the actual value.

In case of an IPv6 address the compressed IPv6 address as described byhttps://tools.ietf.org/html/rfc5952 is being used if the additionalspecifierc is given. The IPv6 address is surrounded by[,] incase of additional specifiersp,f ors as suggested byhttps://tools.ietf.org/html/draft-ietf-6man-text-addr-representation-07

In case of IPv4 addresses, the additionalh,n,b, andlspecifiers can be used as well and are ignored in case of an IPv6address.

Passed by reference.

Further examples:

%pISfc          1.2.3.4         or [1:2:3:4:5:6:7:8]/123456789%pISsc          1.2.3.4         or [1:2:3:4:5:6:7:8]%1234567890%pISpfc         1.2.3.4:12345   or [1:2:3:4:5:6:7:8]:12345/123456789

UUID/GUID addresses

%pUb    00010203-0405-0607-0809-0a0b0c0d0e0f%pUB    00010203-0405-0607-0809-0A0B0C0D0E0F%pUl    03020100-0504-0706-0809-0a0b0c0e0e0f%pUL    03020100-0504-0706-0809-0A0B0C0E0E0F

For printing 16-byte UUID/GUIDs addresses. The additionall,L,b andB specifiers are used to specify a little endian order inlower (l) or upper case (L) hex notation - and big endian order in lower (b)or upper case (B) hex notation.

Where no additional specifiers are used the default big endianorder with lower case hex notation will be printed.

Passed by reference.

dentry names

%pd{,2,3,4}%pD{,2,3,4}

For printing dentry name; if we race withd_move(), the name mightbe a mix of old and new ones, but it won’t oops. %pd dentry is a saferequivalent of %s dentry->d_name.name we used to use, %pd<n> printsnlast components. %pD does the same thing forstructfile.

Passed by reference.

block_device names

%pg     sda, sda1 or loop0p1

For printing name of block_device pointers.

struct va_format

%pV

For printingstructva_format structures. These contain a format stringand va_list as follows:

struct va_format {        const char *fmt;        va_list *va;};

Implements a “recursive vsnprintf”.

Do not use this feature without some mechanism to verify thecorrectness of the format string and va_list arguments.

Passed by reference.

Device tree nodes

%pOF[fnpPcCF]

For printing device tree node structures. Default behaviour isequivalent to %pOFf.

  • f - device node full_name

  • n - device node name

  • p - device node phandle

  • P - device node path spec (name + @unit)

  • F - device node flags

  • c - major compatible string

  • C - full compatible string

The separator when using multiple arguments is ‘:’

Examples:

%pOF    /foo/bar@0                      - Node full name%pOFf   /foo/bar@0                      - Same as above%pOFfp  /foo/bar@0:10                   - Node full name + phandle%pOFfcF /foo/bar@0:foo,device:--P-      - Node full name +                                          major compatible string +                                          node flags                                                D - dynamic                                                d - detached                                                P - Populated                                                B - Populated bus

Passed by reference.

Fwnode handles

%pfw[fP]

For printing information on an fwnode_handle. The default is to print the fullnode name, including the path. The modifiers are functionally equivalent to%pOF above.

  • f - full name of the node, including the path

  • P - the name of the node including an address (if there is one)

Examples (ACPI):

%pfwf   \_SB.PCI0.CIO2.port@1.endpoint@0        - Full node name%pfwP   endpoint@0                              - Node name

Examples (OF):

%pfwf   /ocp@68000000/i2c@48072000/camera@10/port/endpoint - Full name%pfwP   endpoint                                - Node name

Time and date

%pt[RT]                 YYYY-mm-ddTHH:MM:SS%pt[RT]s                YYYY-mm-dd HH:MM:SS%pt[RT]d                YYYY-mm-dd%pt[RT]t                HH:MM:SS%ptSp                   <seconds>.<nanoseconds>%pt[RST][dt][r][s]

For printing date and time as represented by:

R  content of struct rtc_timeS  content of struct timespec64T  time64_t type

in human readable format.

By default year will be incremented by 1900 and month by 1.Use %pt[RT]r (raw) to suppress this behaviour.

The %pt[RT]s (space) will override ISO 8601 separator by using ‘ ‘ (space)instead of ‘T’ (Capital T) between date and time. It won’t have any effectwhen date or time is omitted.

The %ptSp is equivalent to %lld.%09ld for the content of thestructtimespec64.When the other specifiers are given, it becomes the respective equivalent of%ptT[dt][r][s].%09ld. In other words, the seconds are being printed inthe human readable format followed by a dot and nanoseconds.

Passed by reference.

struct clk

%pC     pll1

For printingstructclk structures. %pC prints the name of the clock(Common Clock Framework) or a unique 32-bit ID (legacy clock framework).

Passed by reference.

bitmap and its derivatives such as cpumask and nodemask

%*pb    0779%*pbl   0,3-6,8-10

For printing bitmap and its derivatives such as cpumask and nodemask,%*pb outputs the bitmap with field width as the number of bits and %*pbloutput the bitmap as range list with field width as the number of bits.

The field width is passed by value, the bitmap is passed by reference.Helper macroscpumask_pr_args() andnodemask_pr_args() are available to easeprinting cpumask and nodemask.

Flags bitfields such as page flags and gfp_flags

%pGp    0x17ffffc0002036(referenced|uptodate|lru|active|private|node=0|zone=2|lastcpupid=0x1fffff)%pGg    GFP_USER|GFP_DMA32|GFP_NOWARN%pGv    read|exec|mayread|maywrite|mayexec|denywrite

For printing flags bitfields as a collection of symbolic constants thatwould construct the value. The type of flags is given by the thirdcharacter. Currently supported are:

  • p - [p]age flags, expects value of type (unsignedlong*)

  • v - [v]ma_flags, expects value of type (unsignedlong*)

  • g - [g]fp_flags, expects value of type (gfp_t*)

The flag names and print order depends on the particular type.

Note that this format should not be used directly in theTP_printk() part of a tracepoint. Instead, use the show_*_flags()functions from <trace/events/mmflags.h>.

Passed by reference.

Network device features

%pNF    0x000000000000c000

For printing netdev_features_t.

Passed by reference.

V4L2 and DRM FourCC code (pixel format)

%p4cc

Print a FourCC code used by V4L2 or DRM, including format endianness andits numerical value as hexadecimal.

Passed by reference.

Examples:

%p4cc   BG12 little-endian (0x32314742)%p4cc   Y10  little-endian (0x20303159)%p4cc   NV12 big-endian (0xb231564e)

Generic FourCC code

::

%p4c[h[R]lb] gP00 (0x67503030)

Print a generic FourCC code, as both ASCII characters and its numericalvalue as hexadecimal.

The generic FourCC code is always printed in the big-endian format,the most significant byte first. This is the opposite of V4L/DRM FourCCs.

The additionalh,hR,l, andb specifiers define whatendianness is used to load the stored bytes. The data might be interpretedusing the host, reversed host byte order, little-endian, or big-endian.

Passed by reference.

Examples for a little-endian machine, given &(u32)0x67503030:

%p4ch   gP00 (0x67503030)%p4chR  00Pg (0x30305067)%p4cl   gP00 (0x67503030)%p4cb   00Pg (0x30305067)

Examples for a big-endian machine, given &(u32)0x67503030:

%p4ch   gP00 (0x67503030)%p4chR  00Pg (0x30305067)%p4cl   00Pg (0x30305067)%p4cb   gP00 (0x67503030)

Rust

%pA

Only intended to be used from Rust code to formatcore::fmt::Arguments.Donot use it from C.

Thanks

If you add other %p extensions, please extend <lib/tests/printf_kunit.c>with one or more test cases, if at all feasible.

Thank you for your cooperation and attention.