Print this page
3317 dis(1) should support cross-target disassembly

@@ -22,10 +22,11 @@
 /*
  * Copyright 2007 Sun Microsystems, Inc.  All rights reserved.
  * Use is subject to license terms.
  *
  * Copyright 2011 Jason King.  All rights reserved.
+ * Copyright 2012 Joshua M. Clulow <josh@sysmgr.org>
  */
 
 #include <ctype.h>
 #include <getopt.h>
 #include <stdio.h>

@@ -95,10 +96,26 @@
                         (void) snprintf(buf, buflen, "%s+0x%x", symbol, offset);
         }
 }
 
 /*
+ * Determine if we are on an architecture with fixed-size instructions,
+ * and if so, what size they are.
+ */
+static int
+insn_size(dis_handle_t *dhp)
+{
+        int min = dis_min_instrlen(dhp);
+        int max = dis_max_instrlen(dhp);
+
+        if (min == max)
+                return (min);
+
+        return (0);
+}
+
+/*
  * The main disassembly routine.  Given a fixed-sized buffer and starting
  * address, disassemble the data using the supplied target and libdisasm handle.
  */
 void
 dis_data(dis_tgt_t *tgt, dis_handle_t *dhp, uint64_t addr, void *data,

@@ -113,10 +130,12 @@
         int i;
         int bytesperline;
         size_t symsize;
         int isfunc;
         size_t symwidth = 0;
+        int ret;
+        int insz = insn_size(dhp);
 
         db.db_tgt = tgt;
         db.db_data = data;
         db.db_addr = addr;
         db.db_size = datalen;

@@ -128,21 +147,21 @@
 
         symbol = NULL;
 
         while (addr < db.db_addr + db.db_size) {
 
-                if (dis_disassemble(dhp, addr, buf, BUFSIZE) != 0) {
-#if defined(__sparc)
+                ret = dis_disassemble(dhp, addr, buf, BUFSIZE);
+                if (ret != 0 && insz > 0) {
                         /*
-                         * Since sparc instructions are fixed size, we
+                         * Since we know instructions are fixed size, we
                          * always know the address of the next instruction
                          */
                         (void) snprintf(buf, sizeof (buf),
                             "*** invalid opcode ***");
-                        db.db_nextaddr = addr + 4;
+                        db.db_nextaddr = addr + insz;
 
-#else
+                } else if (ret != 0) {
                         off_t next;
 
                         (void) snprintf(buf, sizeof (buf),
                             "*** invalid opcode ***");
 

@@ -161,11 +180,10 @@
                                         db.db_nextaddr = db.db_addr +
                                             db.db_size;
                                 else
                                         db.db_nextaddr = addr + next;
                         }
-#endif
                 }
 
                 /*
                  * Print out the line as:
                  *

@@ -480,11 +498,10 @@
                  * we should be able to disassemble targets from different
                  * architectures.  For now, we only support objects as the
                  * native machine type.
                  */
                 switch (ehdr.e_machine) {
-#ifdef __sparc
                 case EM_SPARC:
                         if (ehdr.e_ident[EI_CLASS] != ELFCLASS32 ||
                             ehdr.e_ident[EI_DATA] != ELFDATA2MSB) {
                                 warn("invalid E_IDENT field for SPARC object");
                                 return;

@@ -518,21 +535,18 @@
                                 return;
                         }
 
                         g_flags |= DIS_SPARC_V9 | DIS_SPARC_V9_SGI;
                         break;
-#endif /* __sparc */
 
-#if defined(__i386) || defined(__amd64)
                 case EM_386:
                         g_flags |= DIS_X86_SIZE32;
                         break;
 
                 case EM_AMD64:
                         g_flags |= DIS_X86_SIZE64;
                         break;
-#endif /* __i386 || __amd64 */
 
                 default:
                         die("%s: unsupported ELF machine 0x%x", filename,
                             ehdr.e_machine);
                 }