As far as I can tell, ddb's examine /m format

                 /m    display in unsigned hex with character dump at the end
                       of each line.  The location is also displayed in hex at
                       the beginning of each line.

has been documented since the start of the tree but never implemented.

The patch below is mostly from NetBSD, which added /m a while back.
I changed their column alignment code so (1) it would actually align
correctly and (2) not overflow 80 characters on LP64 archs.

Do we want this?  I don't know what else people use to look at,
say, network packets in memory:

ddb{3}> show mbuf $rax
mbuf 0xffffff00dfa9d200
m_type: 1       m_flags: 2<M_PKTHDR>
m_next: 0xffffff00dfa9df00      m_nextpkt: 0x0
m_data: 0xffffff00dfa9d2b0      m_len: 64
m_dat: 0xffffff00dfa9d220       m_pktdat: 0xffffff00dfa9d268
m_ptkhdr.ph_ifidx: 0    m_pkthdr.len: 136
m_ptkhdr.ph_tags: 0x0   m_pkthdr.ph_tagsset: 0
m_pkthdr.ph_flowid: 0   m_pkthdr.ph_loopcnt: 0
m_pkthdr.csum_flags: 0
m_pkthdr.ether_vtag: 0  m_ptkhdr.ph_rtableid: 0
m_pkthdr.pf.statekey: 0x0       m_pkthdr.pf.inp 0x0
m_pkthdr.pf.qid: 0      m_pkthdr.pf.tag: 0
m_pkthdr.pf.flags: 80<PROCESSED>
m_pkthdr.pf.routed: 0   m_pkthdr.pf.prio: 3
ddb{3}> x /bm 0xffffff00dfa9d2b0,0t64
0xffffff00dfa9d2b0:     60000000 00482940 200106f8 124a0000  `....H)@ ....J..
0xffffff00dfa9d2c0:     00000000 00000002 200106f8 124a0000  ........ ....J..
0xffffff00dfa9d2d0:     00000000 00000004 60000000 00203a40  ........`.... :@
0xffffff00dfa9d2e0:     200106f8 124a0000 00000000 00000002   ....J..........
ddb{3}> 

Index: db_examine.c
===================================================================
RCS file: /cvs/src/sys/ddb/db_examine.c,v
retrieving revision 1.22
diff -u -p -r1.22 db_examine.c
--- db_examine.c        7 Jun 2016 01:31:54 -0000       1.22
+++ db_examine.c        10 Oct 2016 17:39:17 -0000
@@ -72,10 +72,11 @@ db_examine_cmd(db_expr_t addr, int have_
 void
 db_examine(db_addr_t addr, char *fmt, int count)
 {
-       int             c;
+       int             i, c;
        db_expr_t       value;
        int             size;
        int             width;
+       int             bytes;
        char *          fp;
        db_addr_t       incr;
        int             dis;
@@ -130,6 +131,42 @@ db_examine(db_addr_t addr, char *fmt, in
                        case 'x':       /* unsigned hex */
                                value = db_get_value(addr, size, FALSE);
                                db_printf("%-*lx", width, (long)value);
+                               break;
+                       case 'm':       /* hex dump */
+                               /*
+                                * Print off in chunks of size. Try to print 16
+                                * bytes at a time into 4 columns. This
+                                * loops modify's count extra times in order
+                                * to get the nicely formatted lines.
+                                */
+                               incr = 0;
+                               bytes = 0;
+                               do {
+                                       for (i = 0; i < size; i++) {
+                                               value =
+                                                   db_get_value(addr+bytes, 1,
+                                                       FALSE);
+                                               db_printf("%02lx",
+                                                   (long)value);
+                                               bytes++;
+                                               if (!(bytes % 4))
+                                                       db_printf(" ");
+                                       }
+                               } while ((bytes != 16) && count--);
+                               /* True up the columns before continuing */
+                               db_printf("%-*s",
+                                   (16-bytes)*2 + (4 - bytes/4) + 1, " ");
+                               /* Print chars, use . for non-printables */
+                               while (bytes--) {
+                                       value = db_get_value(addr + incr, 1,
+                                           FALSE);
+                                       incr++;
+                                       if (value >= ' ' && value <= '~')
+                                               db_printf("%c", (int)value);
+                                       else
+                                               db_printf(".");
+                               }
+                               db_printf("\n");
                                break;
                        case 'z':       /* signed hex */
                                value = db_get_value(addr, size, TRUE);
-- 
Christian "naddy" Weisgerber                          [email protected]

Reply via email to