]> granicus.if.org Git - strace/blobdiff - nlattr.c
nlattr: add unsigned int decoders that print in hex form
[strace] / nlattr.c
index f65d9cf6a6288f245aefff97f6512cd322b2d552..83a25bd6f402a0126ce58a488c2a8505c21d216c 100644 (file)
--- a/nlattr.c
+++ b/nlattr.c
@@ -273,12 +273,45 @@ decode_nla_xval(struct tcb *const tcp,
        if (len > sizeof(data))
                return false;
        else if (!umoven_or_printaddr(tcp, addr, len, data.bytes + bytes_offs))
+       {
+               if (opts->process_fn)
+                       data.val = opts->process_fn(data.val);
+               if (opts->prefix)
+                       tprints(opts->prefix);
                printxval_dispatch_ex(opts->xlat, opts->xlat_size, data.val,
                                      opts->dflt, opts->xt, opts->style);
+               if (opts->suffix)
+                       tprints(opts->suffix);
+       }
 
        return true;
 }
 
+static uint64_t
+process_host_order(uint64_t val)
+{
+       return ntohs(val);
+}
+
+bool
+decode_nla_ether_proto(struct tcb *const tcp,
+                      const kernel_ulong_t addr,
+                      const unsigned int len,
+                      const void *const opaque_data)
+{
+       const struct decode_nla_xlat_opts opts = {
+               .xlat = ethernet_protocols,
+               .xlat_size = ethernet_protocols_size,
+               .dflt = "ETHER_P_???",
+               .xt = XT_SORTED,
+               .prefix = "htons(",
+               .suffix = ")",
+               .process_fn = process_host_order,
+       };
+
+       return decode_nla_xval(tcp, addr, len, &opts);
+}
+
 bool
 decode_nla_ip_proto(struct tcb *const tcp,
                    const kernel_ulong_t addr,
@@ -295,6 +328,40 @@ decode_nla_ip_proto(struct tcb *const tcp,
        return decode_nla_xval(tcp, addr, len, &opts);
 }
 
+bool
+decode_nla_flags(struct tcb *const tcp,
+                const kernel_ulong_t addr,
+                const unsigned int len,
+                const void *const opaque_data)
+{
+       const struct decode_nla_xlat_opts * const opts = opaque_data;
+       union {
+               uint64_t flags;
+               uint8_t  bytes[sizeof(uint64_t)];
+       } data = { .flags = 0 };
+       const size_t bytes_offs = is_bigendian ? sizeof(data) - len : 0;
+
+       if (opts->xt == XT_INDEXED)
+               error_func_msg("indexed xlats are currently incompatible with "
+                              "printflags");
+
+       if (len > sizeof(data))
+               return false;
+       else if (!umoven_or_printaddr(tcp, addr, len, data.bytes + bytes_offs))
+       {
+               if (opts->process_fn)
+                       data.flags = opts->process_fn(data.flags);
+               if (opts->prefix)
+                       tprints(opts->prefix);
+               printflags_ex(data.flags, opts->dflt, opts->style, opts->xlat,
+                             NULL);
+               if (opts->suffix)
+                       tprints(opts->suffix);
+       }
+
+       return true;
+}
+
 bool
 decode_nla_be16(struct tcb *const tcp,
                const kernel_ulong_t addr,
@@ -347,6 +414,10 @@ decode_nla_ ## name(struct tcb *const tcp,         \
        return true;                                    \
 }
 
+DECODE_NLA_INTEGER(x8, uint8_t, "%#" PRIx8)
+DECODE_NLA_INTEGER(x16, uint16_t, "%#" PRIx16)
+DECODE_NLA_INTEGER(x32, uint32_t, "%#" PRIx32)
+DECODE_NLA_INTEGER(x64, uint64_t, "%#" PRIx64)
 DECODE_NLA_INTEGER(u8, uint8_t, "%" PRIu8)
 DECODE_NLA_INTEGER(u16, uint16_t, "%" PRIu16)
 DECODE_NLA_INTEGER(u32, uint32_t, "%" PRIu32)